1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_convertxml.h"
17 #include "securec.h"
18 #include "tools/log.h"
19 namespace OHOS::Xml {
GetNodeType(const xmlElementType enumType) const20     std::string ConvertXml::GetNodeType(const xmlElementType enumType) const
21     {
22         std::string strResult = "";
23         switch (enumType) {
24             case xmlElementType::XML_ELEMENT_NODE:
25                 strResult = "element";
26                 break;
27             case xmlElementType::XML_ATTRIBUTE_NODE:
28                 strResult = "attribute";
29                 break;
30             case xmlElementType::XML_TEXT_NODE:
31                 strResult = "text";
32                 break;
33             case xmlElementType::XML_CDATA_SECTION_NODE:
34                 strResult = "cdata";
35                 break;
36             case xmlElementType::XML_ENTITY_REF_NODE:
37                 strResult = "entity_ref";
38                 break;
39             case xmlElementType::XML_ENTITY_NODE:
40                 strResult = "entity";
41                 break;
42             case xmlElementType::XML_PI_NODE:
43                 strResult = "instruction";
44                 break;
45             case xmlElementType::XML_COMMENT_NODE:
46                 strResult = "comment";
47                 break;
48             case xmlElementType::XML_DOCUMENT_NODE:
49                 strResult = "document";
50                 break;
51             case xmlElementType::XML_DOCUMENT_TYPE_NODE:
52                 strResult = "document_type";
53                 break;
54             case xmlElementType::XML_DOCUMENT_FRAG_NODE:
55                 strResult = "document_frag";
56                 break;
57             case xmlElementType::XML_DTD_NODE:
58                 strResult = "doctype";
59                 break;
60 #ifdef LIBXML_DOCB_ENABLED
61             case xmlElementType::XML_DOCB_DOCUMENT_NODE:
62                 strResult =  "docb_document";
63                 break;
64 #endif
65             default:
66                 break;
67         }
68         return strResult;
69     }
70 
SetKeyValue(napi_env env, const napi_value &object, const std::string strKey, const std::string strValue) const71     void ConvertXml::SetKeyValue(napi_env env, const napi_value &object, const std::string strKey,
72                                  const std::string strValue) const
73     {
74         napi_value attrValue = nullptr;
75         napi_create_string_utf8(env, strValue.c_str(), NAPI_AUTO_LENGTH, &attrValue);
76         napi_set_named_property(env, object, strKey.c_str(), attrValue);
77     }
Trim(std::string strXmltrim) const78     std::string ConvertXml::Trim(std::string strXmltrim) const
79     {
80         if (strXmltrim.empty()) {
81             return "";
82         }
83         size_t i = 0;
84         size_t strlen = strXmltrim.size();
85         for (; i < strlen;) {
86             if (strXmltrim[i] == ' ') {
87                 i++;
88             } else {
89                 break;
90             }
91         }
92         strXmltrim = strXmltrim.substr(i);
93         strlen = strXmltrim.size();
94         for (i = strlen - 1; i != 0; i--) {
95             if (strXmltrim[i] == ' ') {
96                 strXmltrim.pop_back();
97             } else {
98                 break;
99             }
100         }
101         return strXmltrim;
102     }
103 
GetPrevNodeList(napi_env env, xmlNodePtr curNode)104     void ConvertXml::GetPrevNodeList(napi_env env, xmlNodePtr curNode)
105     {
106         while (curNode->prev != nullptr) {
107             curNode = curNode->prev;
108             napi_value elementsObject = nullptr;
109             napi_create_object(env, &elementsObject);
110             char *curContent = nullptr;
111             if (curNode->type == xmlElementType::XML_PI_NODE && !options_.ignoreInstruction) {
112                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
113                 SetKeyValue(env, elementsObject, options_.name, reinterpret_cast<const char*>(curNode->name));
114                 curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode));
115                 if (curContent != nullptr) {
116                     SetKeyValue(env, elementsObject, options_.instruction, curContent);
117                     xmlFree(reinterpret_cast<void*>(curContent));
118                 }
119                 prevObj_.push_back(elementsObject);
120             }
121             if (curNode->type == xmlElementType::XML_COMMENT_NODE && !options_.ignoreComment) {
122                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
123                 curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode));
124                 if (curContent != nullptr) {
125                     SetKeyValue(env, elementsObject, options_.comment, curContent);
126                     xmlFree(reinterpret_cast<void*>(curContent));
127                 }
128                 prevObj_.push_back(elementsObject);
129             }
130             if (curNode->type == xmlElementType::XML_DTD_NODE && !options_.ignoreDoctype) {
131                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
132                 SetKeyValue(env, elementsObject, options_.doctype,
133                             reinterpret_cast<const char*>(curNode->name));
134                 prevObj_.push_back(elementsObject);
135             }
136         }
137     }
138 
SetAttributes(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject) const139     void ConvertXml::SetAttributes(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject) const
140     {
141         if (curNode->type == XML_ENTITY_DECL) {
142             return;
143         }
144         xmlAttr *attr = curNode->properties;
145         if (attr && !options_.ignoreAttributes) {
146             napi_value attrTitleObj = nullptr;
147             napi_create_object(env, &attrTitleObj);
148             while (attr) {
149                 SetKeyValue(env, attrTitleObj, reinterpret_cast<const char*>(attr->name),
150                             reinterpret_cast<const char*>(attr->children->content));
151                 attr = attr->next;
152             }
153             napi_set_named_property(env, elementsObject, options_.attributes.c_str(), attrTitleObj);
154         }
155     }
156 
SetXmlElementType(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject, bool &bFlag) const157     void ConvertXml::SetXmlElementType(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject,
158                                        bool &bFlag) const
159     {
160         char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode));
161         if (curNode->type == xmlElementType::XML_PI_NODE && !options_.ignoreInstruction) {
162             if (curContent != nullptr) {
163                 SetKeyValue(env, elementsObject, options_.instruction, curContent);
164                 bFlag = true;
165             }
166         } else if (curNode->type == xmlElementType::XML_COMMENT_NODE && !options_.ignoreComment) {
167             if (curContent != nullptr) {
168                 SetKeyValue(env, elementsObject, options_.comment, curContent);
169                 bFlag = true;
170             }
171         } else if (curNode->type == xmlElementType::XML_CDATA_SECTION_NODE && !options_.ignoreCdata) {
172             if (curContent != nullptr) {
173                 SetKeyValue(env, elementsObject, options_.cdata, curContent);
174                 bFlag = true;
175             }
176         }
177         if (curContent != nullptr) {
178             xmlFree(reinterpret_cast<void*>(curContent));
179         }
180     }
SetNodeInfo(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject, const std::string parentName) const181     void ConvertXml::SetNodeInfo(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject,
182                                  const std::string parentName) const
183     {
184         if (curNode->type == xmlElementType::XML_TEXT_NODE) {
185             return;
186         }
187         if (curNode->type == xmlElementType::XML_PI_NODE) {
188             if (!options_.ignoreInstruction) {
189                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
190             }
191         } else {
192                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
193         }
194         if ((curNode->type != xmlElementType::XML_COMMENT_NODE) &&
195             (curNode->type != xmlElementType::XML_CDATA_SECTION_NODE)) {
196             if (!(curNode->type == xmlElementType::XML_PI_NODE && options_.ignoreInstruction)) {
197                 SetKeyValue(env, elementsObject, options_.name, reinterpret_cast<const char*>(curNode->name));
198                 if (!parentName.empty()) {
199                     SetKeyValue(env, elementsObject, options_.parent, parentName);
200                 }
201             }
202         }
203     }
204 
SetEndInfo(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject, bool &bFlag) const205     void ConvertXml::SetEndInfo(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject,
206                                 bool &bFlag) const
207     {
208         SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
209         if (curNode->type == xmlElementType::XML_ELEMENT_NODE) {
210             SetKeyValue(env, elementsObject, options_.name, reinterpret_cast<const char*>(curNode->name));
211             bFlag = true;
212         } else if (curNode->type == xmlElementType::XML_TEXT_NODE) {
213             char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode));
214             if (options_.trim) {
215                 if (curContent != nullptr) {
216                     SetKeyValue(env, elementsObject, options_.text,
217                                 Trim(curContent));
218                 }
219             } else {
220                 if (curContent != nullptr) {
221                     SetKeyValue(env, elementsObject, options_.text, curContent);
222                 }
223             }
224             if (curContent != nullptr) {
225                 xmlFree(reinterpret_cast<void*>(curContent));
226             }
227             if (!options_.ignoreText) {
228                 bFlag = true;
229             }
230         }
231     }
232 
SetPrevInfo(napi_env env, const napi_value &recvElement, int flag, int32_t &index1) const233     void ConvertXml::SetPrevInfo(napi_env env, const napi_value &recvElement, int flag, int32_t &index1) const
234     {
235         if (!prevObj_.empty() && !flag) {
236             for (size_t i = (prevObj_.size() - 1); i > 0; --i) {
237                 napi_set_element(env, recvElement, index1++, prevObj_[i]);
238             }
239             napi_set_element(env, recvElement, index1++, prevObj_[0]);
240         }
241     }
242 
GetXMLInfo(napi_env env, xmlNodePtr curNode, const napi_value &object, int flag, const std::string parentName)243     void ConvertXml::GetXMLInfo(napi_env env, xmlNodePtr curNode, const napi_value &object,
244                                 int flag, const std::string parentName)
245     {
246         napi_value recvElement = nullptr;
247         napi_create_array(env, &recvElement);
248         xmlNodePtr pNode = curNode;
249         int32_t index = 0;
250         bool bFlag = false;
251         while (pNode != nullptr) {
252             bFlag = false;
253             napi_value elementsObject = nullptr;
254             napi_create_object(env, &elementsObject);
255             SetNodeInfo(env, pNode, elementsObject, parentName);
256             SetAttributes(env, pNode, elementsObject);
257             char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(pNode));
258             if (curContent != nullptr) {
259                 if (pNode->children != nullptr) {
260                     curNode = pNode->children;
261                     const std::string parentNameTemp = apiFlag_ ? reinterpret_cast<const char*>(pNode->name) : "";
262                     GetXMLInfo(env, curNode, elementsObject, 1, parentNameTemp);
263                     bFlag = true;
264                 } else {
265                     SetXmlElementType(env, pNode, elementsObject, bFlag);
266                     SetEndInfo(env, pNode, elementsObject, bFlag);
267                 }
268                 xmlFree(reinterpret_cast<void*>(curContent));
269             }
270             SetPrevInfo(env, recvElement, flag, index);
271             if (elementsObject != nullptr && bFlag) {
272                 napi_set_element(env, recvElement, index++, elementsObject);
273                 elementsObject = nullptr;
274             }
275             pNode = pNode->next;
276         }
277         if (bFlag) {
278             napi_set_named_property(env, object, options_.elements.c_str(), recvElement);
279         }
280     }
281 
SetSpacesInfo(napi_env env, const napi_value &object) const282     void ConvertXml::SetSpacesInfo(napi_env env, const napi_value &object) const
283     {
284         napi_value iTemp = nullptr;
285         switch (spaceType_) {
286             case (SpaceType::T_INT32):
287                 napi_create_int32(env, iSpace_, &iTemp);
288                 napi_set_named_property(env, object, "spaces", iTemp);
289                 break;
290             case (SpaceType::T_STRING):
291                 SetKeyValue(env, object, "spaces", strSpace_);
292                 break;
293             case (SpaceType::T_INIT):
294                 SetKeyValue(env, object, "spaces", strSpace_);
295                 break;
296             default:
297                 break;
298             }
299     }
300 
Convert(napi_env env, std::string strXml)301     napi_value ConvertXml::Convert(napi_env env, std::string strXml)
302     {
303         xmlNodePtr curNode = nullptr;
304         napi_value object = nullptr;
305         napi_status status = napi_create_object(env, &object);
306         if (status != napi_ok) {
307             return nullptr;
308         }
309         size_t len = strXml.size();
310         xmlDocPtr doc = xmlParseMemory(strXml.c_str(), len);
311         if (!doc) {
312             xmlFreeDoc(doc);
313             DealSingleLine(env, strXml, object);
314             return object;
315         }
316         napi_value subObject = nullptr;
317         napi_value subSubObject = nullptr;
318         napi_create_object(env, &subSubObject);
319         napi_create_object(env, &subObject);
320         if (doc != nullptr && doc->version != nullptr) {
321             SetKeyValue(env, subSubObject, "version", (const char*)doc->version);
322         }
323         if (doc != nullptr && doc->encoding != nullptr) {
324             SetKeyValue(env, subSubObject, "encoding", (const char*)doc->encoding);
325         }
326         if (!options_.ignoreDeclaration && strXml.find("xml") != std::string::npos) {
327             napi_set_named_property(env, subObject, options_.attributes.c_str(), subSubObject);
328             napi_set_named_property(env, object, options_.declaration.c_str(), subObject);
329         }
330         if (doc != nullptr) {
331             curNode = xmlDocGetRootElement(doc);
332             GetPrevNodeList(env, curNode);
333             GetXMLInfo(env, curNode, object, 0);
334         }
335         xmlFreeDoc(doc);
336         SetSpacesInfo(env, object);
337         return object;
338     }
339 
DealNapiStrValue(napi_env env, const napi_value napi_StrValue, std::string &result) const340     napi_status ConvertXml::DealNapiStrValue(napi_env env, const napi_value napi_StrValue, std::string &result) const
341     {
342         std::string buffer = "";
343         size_t bufferSize = 0;
344         napi_status status = napi_ok;
345         status = napi_get_value_string_utf8(env, napi_StrValue, nullptr, -1, &bufferSize);
346         if (status != napi_ok) {
347             HILOG_ERROR("can not get buffer size");
348             return status;
349         }
350         buffer.reserve(bufferSize + 1);
351         buffer.resize(bufferSize);
352         if (bufferSize > 0) {
353             status = napi_get_value_string_utf8(env, napi_StrValue, buffer.data(), bufferSize + 1, &bufferSize);
354             if (status != napi_ok) {
355                 HILOG_ERROR("can not get buffer value");
356                 return status;
357             }
358         }
359         if (buffer.data() != nullptr) {
360             result = buffer;
361         }
362         return status;
363     }
364 
DealSpaces(napi_env env, const napi_value napiObj)365     void ConvertXml::DealSpaces(napi_env env, const napi_value napiObj)
366     {
367         napi_value recvTemp = nullptr;
368         napi_get_named_property(env, napiObj, "spaces", &recvTemp);
369         napi_valuetype valuetype = napi_undefined;
370         napi_typeof(env, recvTemp, &valuetype);
371         if (valuetype == napi_string) {
372             DealNapiStrValue(env, recvTemp, strSpace_);
373             spaceType_ = SpaceType::T_STRING;
374         } else if (valuetype == napi_number) {
375             int32_t iTemp;
376             if (napi_get_value_int32(env, recvTemp, &iTemp) == napi_ok) {
377                 iSpace_ = iTemp;
378                 spaceType_ = SpaceType::T_INT32;
379             }
380         }
381     }
382 
DealIgnore(napi_env env, const napi_value napiObj)383     void ConvertXml::DealIgnore(napi_env env, const napi_value napiObj)
384     {
385         std::vector<std::string> vctIgnore = {"compact", "trim", "ignoreDeclaration", "ignoreInstruction",
386                                               "ignoreAttributes", "ignoreComment", "ignoreCDATA",
387                                               "ignoreDoctype", "ignoreText"};
388         size_t vctLength = vctIgnore.size();
389         for (size_t i = 0; i < vctLength; ++i) {
390             napi_value recvTemp = nullptr;
391             bool bRecv = false;
392             napi_get_named_property(env, napiObj, vctIgnore[i].c_str(), &recvTemp);
393             if ((napi_get_value_bool(env, recvTemp, &bRecv)) == napi_ok) {
394                 switch (i) {
395                     case 0:
396                         options_.compact = bRecv;
397                         break;
398                     case 1: // 1:trim
399                         options_.trim = bRecv;
400                         break;
401                     case 2: // 2:ignoreDeclaration
402                         options_.ignoreDeclaration = bRecv;
403                         break;
404                     case 3: // 3:ignoreInstruction
405                         options_.ignoreInstruction = bRecv;
406                         break;
407                     case 4: // 4:ignoreAttributes
408                         options_.ignoreAttributes = bRecv;
409                         break;
410                     case 5: // 5:ignoreComment
411                         options_.ignoreComment = bRecv;
412                         break;
413                     case 6: // 6:ignoreCdata
414                         options_.ignoreCdata = bRecv;
415                         break;
416                     case 7: // 7:ignoreDoctype
417                         options_.ignoreDoctype = bRecv;
418                         break;
419                     case 8: // 8:ignoreText
420                         options_.ignoreText = bRecv;
421                         break;
422                     default:
423                         break;
424                 }
425             }
426         }
427     }
428 
SetDefaultKey(size_t i, const std::string strRecv)429     void ConvertXml::SetDefaultKey(size_t i, const std::string strRecv)
430     {
431         switch (i) {
432             case 0:
433                 options_.declaration = strRecv;
434                 break;
435             case 1:
436                 options_.instruction = strRecv;
437                 break;
438             case 2: // 2:attributes
439                 options_.attributes = strRecv;
440                 break;
441             case 3: // 3:text
442                 options_.text = strRecv;
443                 break;
444             case 4: // 4:cdata
445                 options_.cdata = strRecv;
446                 break;
447             case 5: // 5:doctype
448                 options_.doctype = strRecv;
449                 break;
450             case 6: // 6:comment
451                 options_.comment = strRecv;
452                 break;
453             case 7: // 7:parent
454                 options_.parent = strRecv;
455                 break;
456             case 8: // 8:type
457                 options_.type = strRecv;
458                 break;
459             case 9: // 9:name
460                 options_.name = strRecv;
461                 break;
462             case 10: // 10:elements
463                 options_.elements = strRecv;
464                 break;
465             default:
466                 break;
467         }
468     }
469 
DealOptions(napi_env env, const napi_value napiObj)470     void ConvertXml::DealOptions(napi_env env, const napi_value napiObj)
471     {
472         std::vector<std::string> vctOptions = {"declarationKey", "instructionKey", "attributesKey", "textKey",
473                                               "cdataKey", "doctypeKey", "commentKey", "parentKey", "typeKey",
474                                               "nameKey", "elementsKey"};
475         size_t vctLength = vctOptions.size();
476         for (size_t i = 0; i < vctLength; ++i) {
477             napi_value recvTemp = nullptr;
478             std::string strRecv = "";
479             napi_get_named_property(env, napiObj, vctOptions[i].c_str(), &recvTemp);
480             if ((DealNapiStrValue(env, recvTemp, strRecv)) == napi_ok) {
481                 SetDefaultKey(i, strRecv);
482             }
483         }
484         DealIgnore(env, napiObj);
485         DealSpaces(env, napiObj);
486     }
487 
DealSingleLine(napi_env env, std::string &strXml, const napi_value &object)488     void ConvertXml::DealSingleLine(napi_env env, std::string &strXml, const napi_value &object)
489     {
490         size_t iXml = 0;
491         if ((iXml = strXml.find("xml")) != std::string::npos) {
492             xmlInfo_.bXml = true;
493             napi_value declObj = nullptr;
494             napi_create_object(env, &declObj);
495             napi_value attrObj = nullptr;
496             bool bFlag = false;
497             napi_create_object(env, &attrObj);
498             if (strXml.find("version=") != std::string::npos) {
499                 xmlInfo_.bVersion = true;
500                 SetKeyValue(env, attrObj, "version", "1.0");
501                 bFlag = true;
502             }
503             if (strXml.find("encoding=") != std::string::npos) {
504                 xmlInfo_.bEncoding = false;
505                 SetKeyValue(env, attrObj, "encoding", "utf-8");
506                 bFlag = true;
507             }
508             if (bFlag) {
509                 napi_set_named_property(env, declObj, options_.attributes.c_str(), attrObj);
510                 napi_set_named_property(env, object, options_.declaration.c_str(), declObj);
511             } else {
512                 napi_set_named_property(env, object, options_.declaration.c_str(), declObj);
513             }
514             if (strXml.find(">", iXml) == strXml.size() - 1) {
515                 strXml = "";
516             } else {
517                 strXml = strXml.substr(0, strXml.rfind("<", iXml)) + strXml.substr(strXml.find(">", iXml) + 1);
518             }
519         }
520         size_t iCount = 0;
521         size_t iLen = strXml.size();
522         for (; iCount < iLen; ++iCount) {
523             if (strXml[iCount] != ' ' && strXml[iCount] != '\v' &&
524                 strXml[iCount] != '\t' && strXml[iCount] != '\n') {
525                 break;
526             }
527         }
528         if (iCount < iLen) {
529             DealComplex(env, strXml, object);
530         }
531     }
532 
DealComplex(napi_env env, std::string &strXml, const napi_value &object) const533     void ConvertXml::DealComplex(napi_env env, std::string &strXml, const napi_value &object) const
534     {
535         if (strXml.find("<!DOCTYPE") != std::string::npos) {
536             strXml = strXml + "<node></node>";
537         } else {
538             strXml = "<node>" + strXml + "</node>";
539         }
540         xmlDocPtr doc = nullptr;
541         xmlNodePtr curNode = nullptr;
542         size_t len = strXml.size();
543         doc = xmlParseMemory(strXml.c_str(), static_cast<int>(len));
544         if (!doc) {
545             xmlFreeDoc(doc);
546         }
547         if (doc) {
548             curNode = xmlDocGetRootElement(doc);
549             curNode = curNode->children;
550             napi_value elements = nullptr;
551             napi_create_array(env, &elements);
552             bool bHasEle = false;
553             int index = 0;
554             bool bCData = false;
555             if (strXml.find("<![CDATA") != strXml.rfind("<![CDATA")) {
556                 bCData = true;
557             }
558             while (curNode != nullptr) {
559                 napi_value elementsObject = nullptr;
560                 napi_create_object(env, &elementsObject);
561                 SetNodeInfo(env, curNode, elementsObject);
562                 SetXmlElementType(env, curNode, elementsObject, bHasEle);
563                 SetEndInfo(env, curNode, elementsObject, bHasEle);
564                 napi_set_element(env, elements, index++, elementsObject);
565                 DealCDataInfo(bCData, curNode);
566             }
567             if (bHasEle) {
568                 napi_set_named_property(env, object, options_.elements.c_str(), elements);
569             }
570             xmlFreeDoc(doc);
571         }
572     }
573 
Replace(std::string &str, const std::string src, const std::string dst) const574     void ConvertXml::Replace(std::string &str, const std::string src, const std::string dst) const
575     {
576         size_t index = 0;
577         while ((index = str.find(src)) != std::string::npos) {
578             str.replace(index, src.size(), dst);
579         }
580     }
581 
DealCDataInfo(bool bCData, xmlNodePtr &curNode) const582     void ConvertXml::DealCDataInfo(bool bCData, xmlNodePtr &curNode) const
583     {
584         if (bCData && curNode->type == xmlElementType::XML_CDATA_SECTION_NODE &&
585             curNode->next && curNode->next->type == xmlElementType::XML_TEXT_NODE &&
586             curNode->next->next && curNode->next->next->type == xmlElementType::XML_CDATA_SECTION_NODE) {
587                 char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode->next));
588                 if (curContent != nullptr) {
589                     std::string strTemp = reinterpret_cast<char*>(curContent);
590                     Replace(strTemp, " ", "");
591                     Replace(strTemp, "\v", "");
592                     Replace(strTemp, "\t", "");
593                     Replace(strTemp, "\n", "");
594                     if (strTemp == "") {
595                         curNode = curNode->next->next;
596                     }
597                     xmlFree(reinterpret_cast<void*>(curContent));
598                 }
599             } else {
600                 curNode = curNode->next;
601             }
602     }
603 } // namespace OHOS::Xml
604