• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "utils/log.h"
19 namespace OHOS::Xml {
ConvertXml()20     ConvertXml::ConvertXml()
21     {
22             spaceType_ = SpaceType::T_INIT;
23             strSpace_ = "";
24             iSpace_ = 0;
25     }
GetNodeType(const xmlElementType enumType) const26     std::string ConvertXml::GetNodeType(const xmlElementType enumType) const
27     {
28         std::string strResult = "";
29         switch (enumType) {
30             case xmlElementType::XML_ELEMENT_NODE:
31                 strResult = "element";
32                 break;
33             case xmlElementType::XML_ATTRIBUTE_NODE:
34                 strResult = "attribute";
35                 break;
36             case xmlElementType::XML_TEXT_NODE:
37                 strResult = "text";
38                 break;
39             case xmlElementType::XML_CDATA_SECTION_NODE:
40                 strResult = "cdata";
41                 break;
42             case xmlElementType::XML_ENTITY_REF_NODE:
43                 strResult = "entity_ref";
44                 break;
45             case xmlElementType::XML_ENTITY_NODE:
46                 strResult = "entity";
47                 break;
48             case xmlElementType::XML_PI_NODE:
49                 strResult = "instruction";
50                 break;
51             case xmlElementType::XML_COMMENT_NODE:
52                 strResult = "comment";
53                 break;
54             case xmlElementType::XML_DOCUMENT_NODE:
55                 strResult = "document";
56                 break;
57             case xmlElementType::XML_DOCUMENT_TYPE_NODE:
58                 strResult = "document_type";
59                 break;
60             case xmlElementType::XML_DOCUMENT_FRAG_NODE:
61                 strResult = "document_frag";
62                 break;
63             case xmlElementType::XML_DTD_NODE:
64                 strResult = "doctype";
65                 break;
66 #ifdef LIBXML_DOCB_ENABLED
67             case xmlElementType::XML_DOCB_DOCUMENT_NODE:
68                 strResult =  "docb_document";
69                 break;
70 #endif
71             default:
72                 break;
73         }
74         return strResult;
75     }
76 
SetKeyValue(napi_env env,const napi_value & object,const std::string strKey,const std::string strValue) const77     void ConvertXml::SetKeyValue(napi_env env, const napi_value &object, const std::string strKey,
78                                  const std::string strValue) const
79     {
80         napi_value attrValue = nullptr;
81         napi_create_string_utf8(env, strValue.c_str(), NAPI_AUTO_LENGTH, &attrValue);
82         napi_set_named_property(env, object, strKey.c_str(), attrValue);
83     }
Trim(std::string strXmltrim) const84     std::string ConvertXml::Trim(std::string strXmltrim) const
85     {
86         if (strXmltrim.empty()) {
87             return "";
88         }
89         size_t i = 0;
90         size_t strlen = strXmltrim.size();
91         for (; i < strlen;) {
92             if (strXmltrim[i] == ' ') {
93                 i++;
94             } else {
95                 break;
96             }
97         }
98         strXmltrim = strXmltrim.substr(i);
99         strlen = strXmltrim.size();
100         for (i = strlen - 1; i != 0; i--) {
101             if (strXmltrim[i] == ' ') {
102                 strXmltrim.pop_back();
103             } else {
104                 break;
105             }
106         }
107         return strXmltrim;
108     }
109 
GetPrevNodeList(napi_env env,xmlNodePtr curNode)110     void ConvertXml::GetPrevNodeList(napi_env env, xmlNodePtr curNode)
111     {
112         while (curNode->prev != nullptr) {
113             curNode = curNode->prev;
114             napi_value elementsObject = nullptr;
115             napi_create_object(env, &elementsObject);
116             char *curContent = nullptr;
117             if (curNode->type == xmlElementType::XML_PI_NODE && !options_.ignoreInstruction) {
118                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
119                 SetKeyValue(env, elementsObject, options_.name, reinterpret_cast<const char*>(curNode->name));
120                 curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode));
121                 if (curContent != nullptr) {
122                     SetKeyValue(env, elementsObject, options_.instruction, curContent);
123                     xmlFree(reinterpret_cast<void*>(curContent));
124                 }
125                 prevObj_.push_back(elementsObject);
126             }
127             if (curNode->type == xmlElementType::XML_COMMENT_NODE && !options_.ignoreComment) {
128                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
129                 curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode));
130                 if (curContent != nullptr) {
131                     SetKeyValue(env, elementsObject, options_.comment, curContent);
132                     xmlFree(reinterpret_cast<void*>(curContent));
133                 }
134                 prevObj_.push_back(elementsObject);
135             }
136             if (curNode->type == xmlElementType::XML_DTD_NODE && !options_.ignoreDoctype) {
137                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
138                 SetKeyValue(env, elementsObject, options_.doctype,
139                             reinterpret_cast<const char*>(curNode->name));
140                 prevObj_.push_back(elementsObject);
141             }
142         }
143     }
144 
SetAttributes(napi_env env,xmlNodePtr curNode,const napi_value & elementsObject) const145     void ConvertXml::SetAttributes(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject) const
146     {
147         xmlAttr *attr = curNode->properties;
148         if (attr && !options_.ignoreAttributes) {
149             napi_value attrTitleObj = nullptr;
150             napi_create_object(env, &attrTitleObj);
151             while (attr) {
152                 SetKeyValue(env, attrTitleObj, reinterpret_cast<const char*>(attr->name),
153                             reinterpret_cast<const char*>(attr->children->content));
154                 attr = attr->next;
155             }
156             napi_set_named_property(env, elementsObject, options_.attributes.c_str(), attrTitleObj);
157         }
158     }
159 
SetXmlElementType(napi_env env,xmlNodePtr curNode,const napi_value & elementsObject,bool & bFlag) const160     void ConvertXml::SetXmlElementType(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject,
161                                        bool &bFlag) const
162     {
163         char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode));
164         if (curNode->type == xmlElementType::XML_PI_NODE && !options_.ignoreInstruction) {
165             if (curContent != nullptr) {
166                 SetKeyValue(env, elementsObject, options_.instruction, curContent);
167                 bFlag = true;
168             }
169         } else if (curNode->type == xmlElementType::XML_COMMENT_NODE && !options_.ignoreComment) {
170             if (curContent != nullptr) {
171                 SetKeyValue(env, elementsObject, options_.comment, curContent);
172                 bFlag = true;
173             }
174         } else if (curNode->type == xmlElementType::XML_CDATA_SECTION_NODE && !options_.ignoreCdata) {
175             if (curContent != nullptr) {
176                 SetKeyValue(env, elementsObject, options_.cdata, curContent);
177                 bFlag = true;
178             }
179         }
180         if (curContent != nullptr) {
181             xmlFree(reinterpret_cast<void*>(curContent));
182         }
183     }
SetNodeInfo(napi_env env,xmlNodePtr curNode,const napi_value & elementsObject) const184     void ConvertXml::SetNodeInfo(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject) const
185     {
186         if (curNode->type == xmlElementType::XML_TEXT_NODE) {
187             return;
188         } else {
189             if (curNode->type == xmlElementType::XML_PI_NODE) {
190                 if (!options_.ignoreInstruction) {
191                     SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
192                 }
193             } else {
194                     SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
195             }
196             if ((curNode->type != xmlElementType::XML_COMMENT_NODE) &&
197                 (curNode->type != xmlElementType::XML_CDATA_SECTION_NODE)) {
198                 if (!(curNode->type == xmlElementType::XML_PI_NODE && options_.ignoreInstruction)) {
199                     SetKeyValue(env, elementsObject, options_.name, reinterpret_cast<const char*>(curNode->name));
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)243     void ConvertXml::GetXMLInfo(napi_env env, xmlNodePtr curNode, const napi_value &object, int flag)
244     {
245         napi_value elements = nullptr;
246         napi_create_array(env, &elements);
247         napi_value recvElement = nullptr;
248         napi_create_array(env, &recvElement);
249         xmlNodePtr pNode = curNode;
250         int32_t index = 0;
251         int32_t index1 = 0;
252         bool bFlag = false;
253         while (pNode != nullptr) {
254             bFlag = false;
255             napi_value elementsObject = nullptr;
256             napi_create_object(env, &elementsObject);
257             SetNodeInfo(env, pNode, elementsObject);
258             SetAttributes(env, pNode, elementsObject);
259             napi_value tempElement = nullptr;
260             napi_create_array(env, &tempElement);
261             napi_value elementObj = nullptr;
262             napi_create_object(env, &elementObj);
263             char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(pNode));
264             if (curContent != nullptr) {
265                 if (pNode->children != nullptr) {
266                     curNode = pNode->children;
267                     GetXMLInfo(env, curNode, elementsObject, 1);
268                     bFlag = true;
269                 } else {
270                     SetXmlElementType(env, pNode, elementsObject, bFlag);
271                     SetEndInfo(env, pNode, elementsObject, bFlag);
272                 }
273                 xmlFree(reinterpret_cast<void*>(curContent));
274             }
275             SetPrevInfo(env, recvElement, flag, index1);
276             if (elementsObject != nullptr && bFlag) {
277                 napi_set_element(env, recvElement, index1++, elementsObject);
278                 elementsObject = nullptr;
279             }
280             index++;
281             pNode = pNode->next;
282         }
283         if (bFlag) {
284             napi_set_named_property(env, object, options_.elements.c_str(), recvElement);
285         }
286     }
287 
SetSpacesInfo(napi_env env,const napi_value & object) const288     void ConvertXml::SetSpacesInfo(napi_env env, const napi_value &object) const
289     {
290         napi_value iTemp = nullptr;
291         switch (spaceType_) {
292             case (SpaceType::T_INT32):
293                 napi_create_int32(env, iSpace_, &iTemp);
294                 napi_set_named_property(env, object, "spaces", iTemp);
295                 break;
296             case (SpaceType::T_STRING):
297                 SetKeyValue(env, object, "spaces", strSpace_);
298                 break;
299             case (SpaceType::T_INIT):
300                 SetKeyValue(env, object, "spaces", strSpace_);
301                 break;
302             default:
303                 break;
304             }
305     }
306 
Convert(napi_env env,std::string strXml)307     napi_value ConvertXml::Convert(napi_env env, std::string strXml)
308     {
309         xmlDocPtr doc = nullptr;
310         xmlNodePtr curNode = nullptr;
311         napi_status status = napi_ok;
312         napi_value object = nullptr;
313         status = napi_create_object(env, &object);
314         if (status != napi_ok) {
315             return nullptr;
316         }
317         Replace(strXml, "\\r", "\r");
318         Replace(strXml, "\\n", "\n");
319         Replace(strXml, "\\v", "\v");
320         Replace(strXml, "\\t", "\t");
321         Replace(strXml, "]]><![CDATA", "]]> <![CDATA");
322         size_t len = strXml.size();
323         doc = xmlParseMemory(strXml.c_str(), len);
324         if (!doc) {
325             xmlFreeDoc(doc);
326             DealSingleLine(env, strXml, object);
327             return object;
328         }
329         napi_value subObject = nullptr;
330         napi_value subSubObject = nullptr;
331         napi_create_object(env, &subSubObject);
332         napi_create_object(env, &subObject);
333         if (doc != nullptr && doc->version != nullptr) {
334             SetKeyValue(env, subSubObject, "version", (const char*)doc->version);
335         }
336         if (doc != nullptr && doc->encoding != nullptr) {
337             SetKeyValue(env, subSubObject, "encoding", (const char*)doc->encoding);
338         }
339         if (!options_.ignoreDeclaration && strXml.find("xml") != std::string::npos) {
340             napi_set_named_property(env, subObject, options_.attributes.c_str(), subSubObject);
341             napi_set_named_property(env, object, options_.declaration.c_str(), subObject);
342         }
343         if (doc != nullptr) {
344             curNode = xmlDocGetRootElement(doc);
345             GetPrevNodeList(env, curNode);
346             GetXMLInfo(env, curNode, object, 0);
347         }
348         xmlFreeDoc(doc);
349         SetSpacesInfo(env, object);
350         return object;
351     }
352 
DealNapiStrValue(napi_env env,const napi_value napi_StrValue,std::string & result) const353     napi_status ConvertXml::DealNapiStrValue(napi_env env, const napi_value napi_StrValue, std::string &result) const
354     {
355         std::string buffer = "";
356         size_t bufferSize = 0;
357         napi_status status = napi_ok;
358         status = napi_get_value_string_utf8(env, napi_StrValue, nullptr, -1, &bufferSize);
359         if (status != napi_ok) {
360             HILOG_ERROR("can not get buffer size");
361             return status;
362         }
363         buffer.reserve(bufferSize + 1);
364         buffer.resize(bufferSize);
365         if (bufferSize > 0) {
366             status = napi_get_value_string_utf8(env, napi_StrValue, buffer.data(), bufferSize + 1, &bufferSize);
367             if (status != napi_ok) {
368                 HILOG_ERROR("can not get buffer value");
369                 return status;
370             }
371         }
372         if (buffer.data() != nullptr) {
373             result = buffer;
374         }
375         return status;
376     }
377 
DealSpaces(napi_env env,const napi_value napiObj)378     void ConvertXml::DealSpaces(napi_env env, const napi_value napiObj)
379     {
380         napi_value recvTemp = nullptr;
381         napi_get_named_property(env, napiObj, "spaces", &recvTemp);
382         napi_valuetype valuetype = napi_undefined;
383         napi_typeof(env, recvTemp, &valuetype);
384         if (valuetype == napi_string) {
385             DealNapiStrValue(env, recvTemp, strSpace_);
386             spaceType_ = SpaceType::T_STRING;
387         } else if (valuetype == napi_number) {
388             int32_t iTemp;
389             if (napi_get_value_int32(env, recvTemp, &iTemp) == napi_ok) {
390                 iSpace_ = iTemp;
391                 spaceType_ = SpaceType::T_INT32;
392             }
393         }
394     }
395 
DealIgnore(napi_env env,const napi_value napiObj)396     void ConvertXml::DealIgnore(napi_env env, const napi_value napiObj)
397     {
398         std::vector<std::string> vctIgnore = {"compact", "trim", "ignoreDeclaration", "ignoreInstruction",
399                                               "ignoreAttributes", "ignoreComment", "ignoreCDATA",
400                                               "ignoreDoctype", "ignoreText"};
401         size_t vctLength = vctIgnore.size();
402         for (size_t i = 0; i < vctLength; ++i) {
403             napi_value recvTemp = nullptr;
404             bool bRecv = false;
405             napi_get_named_property(env, napiObj, vctIgnore[i].c_str(), &recvTemp);
406             if ((napi_get_value_bool(env, recvTemp, &bRecv)) == napi_ok) {
407                 switch (i) {
408                     case 0:
409                         options_.compact = bRecv;
410                         break;
411                     case 1: // 1:trim
412                         options_.trim = bRecv;
413                         break;
414                     case 2: // 2:ignoreDeclaration
415                         options_.ignoreDeclaration = bRecv;
416                         break;
417                     case 3: // 3:ignoreInstruction
418                         options_.ignoreInstruction = bRecv;
419                         break;
420                     case 4: // 4:ignoreAttributes
421                         options_.ignoreAttributes = bRecv;
422                         break;
423                     case 5: // 5:ignoreComment
424                         options_.ignoreComment = bRecv;
425                         break;
426                     case 6: // 6:ignoreCdata
427                         options_.ignoreCdata = bRecv;
428                         break;
429                     case 7: // 7:ignoreDoctype
430                         options_.ignoreDoctype = bRecv;
431                         break;
432                     case 8: // 8:ignoreText
433                         options_.ignoreText = bRecv;
434                         break;
435                     default:
436                         break;
437                 }
438             }
439         }
440     }
441 
SetDefaultKey(size_t i,const std::string strRecv)442     void ConvertXml::SetDefaultKey(size_t i, const std::string strRecv)
443     {
444         switch (i) {
445             case 0:
446                 options_.declaration = strRecv;
447                 break;
448             case 1:
449                 options_.instruction = strRecv;
450                 break;
451             case 2: // 2:attributes
452                 options_.attributes = strRecv;
453                 break;
454             case 3: // 3:text
455                 options_.text = strRecv;
456                 break;
457             case 4: // 4:cdata
458                 options_.cdata = strRecv;
459                 break;
460             case 5: // 5:doctype
461                 options_.doctype = strRecv;
462                 break;
463             case 6: // 6:comment
464                 options_.comment = strRecv;
465                 break;
466             case 7: // 7:parent
467                 options_.parent = strRecv;
468                 break;
469             case 8: // 8:type
470                 options_.type = strRecv;
471                 break;
472             case 9: // 9:name
473                 options_.name = strRecv;
474                 break;
475             case 10: // 10:elements
476                 options_.elements = strRecv;
477                 break;
478             default:
479                 break;
480         }
481     }
482 
DealOptions(napi_env env,const napi_value napiObj)483     void ConvertXml::DealOptions(napi_env env, const napi_value napiObj)
484     {
485         std::vector<std::string> vctOptions = {"declarationKey", "instructionKey", "attributesKey", "textKey",
486                                               "cdataKey", "doctypeKey", "commentKey", "parentKey", "typeKey",
487                                               "nameKey", "elementsKey"};
488         size_t vctLength = vctOptions.size();
489         for (size_t i = 0; i < vctLength; ++i) {
490             napi_value recvTemp = nullptr;
491             std::string strRecv = "";
492             napi_get_named_property(env, napiObj, vctOptions[i].c_str(), &recvTemp);
493             if ((DealNapiStrValue(env, recvTemp, strRecv)) == napi_ok) {
494                 SetDefaultKey(i, strRecv);
495             }
496         }
497         DealIgnore(env, napiObj);
498         DealSpaces(env, napiObj);
499     }
500 
DealSingleLine(napi_env env,std::string & strXml,const napi_value & object)501     void ConvertXml::DealSingleLine(napi_env env, std::string &strXml, const napi_value &object)
502     {
503         size_t iXml = 0;
504         if ((iXml = strXml.find("xml")) != std::string::npos) {
505             xmlInfo_.bXml = true;
506             napi_value declObj = nullptr;
507             napi_create_object(env, &declObj);
508             napi_value attrObj = nullptr;
509             bool bFlag = false;
510             napi_create_object(env, &attrObj);
511             if (strXml.find("version=") != std::string::npos) {
512                 xmlInfo_.bVersion = true;
513                 SetKeyValue(env, attrObj, "version", "1.0");
514                 bFlag = true;
515             }
516             if (strXml.find("encoding=") != std::string::npos) {
517                 xmlInfo_.bEncoding = false;
518                 SetKeyValue(env, attrObj, "encoding", "utf-8");
519                 bFlag = true;
520             }
521             if (bFlag) {
522                 napi_set_named_property(env, declObj, options_.attributes.c_str(), attrObj);
523                 napi_set_named_property(env, object, options_.declaration.c_str(), declObj);
524             } else {
525                 napi_set_named_property(env, object, options_.declaration.c_str(), declObj);
526             }
527             if (strXml.find(">", iXml) == strXml.size() - 1) {
528                 strXml = "";
529             } else {
530                 strXml = strXml.substr(0, strXml.rfind("<", iXml)) + strXml.substr(strXml.find(">", iXml) + 1);
531             }
532         }
533         size_t iCount = 0;
534         size_t iLen = strXml.size();
535         for (; iCount < iLen; ++iCount) {
536             if (strXml[iCount] != ' ' && strXml[iCount] != '\v' &&
537                 strXml[iCount] != '\t' && strXml[iCount] != '\n') {
538                 break;
539             }
540         }
541         if (iCount < iLen) {
542             DealComplex(env, strXml, object);
543         }
544     }
545 
DealComplex(napi_env env,std::string & strXml,const napi_value & object) const546     void ConvertXml::DealComplex(napi_env env, std::string &strXml, const napi_value &object) const
547     {
548         if (strXml.find("<!DOCTYPE") != std::string::npos) {
549             strXml = strXml + "<node></node>";
550         } else {
551             strXml = "<node>" + strXml + "</node>";
552         }
553         xmlDocPtr doc = nullptr;
554         xmlNodePtr curNode = nullptr;
555         size_t len = strXml.size();
556         doc = xmlParseMemory(strXml.c_str(), static_cast<int>(len));
557         if (!doc) {
558             xmlFreeDoc(doc);
559         }
560         if (doc) {
561             curNode = xmlDocGetRootElement(doc);
562             curNode = curNode->children;
563             napi_value elements = nullptr;
564             napi_create_array(env, &elements);
565             bool bHasEle = false;
566             int index = 0;
567             bool bCData = false;
568             if (strXml.find("<![CDATA") != strXml.rfind("<![CDATA")) {
569                 bCData = true;
570             }
571             while (curNode != nullptr) {
572                 napi_value elementsObject = nullptr;
573                 napi_create_object(env, &elementsObject);
574                 SetNodeInfo(env, curNode, elementsObject);
575                 SetXmlElementType(env, curNode, elementsObject, bHasEle);
576                 SetEndInfo(env, curNode, elementsObject, bHasEle);
577                 napi_set_element(env, elements, index++, elementsObject);
578                 DealCDataInfo(bCData, curNode);
579             }
580             if (bHasEle) {
581                 napi_set_named_property(env, object, options_.elements.c_str(), elements);
582             }
583             xmlFreeDoc(doc);
584         }
585     }
586 
Replace(std::string & str,const std::string src,const std::string dst) const587     void ConvertXml::Replace(std::string &str, const std::string src, const std::string dst) const
588     {
589         size_t begCdata = 0;
590         size_t endCdata = 0;
591         size_t pos = 0;
592         size_t flag = 0;
593         size_t count = 0;
594         std::string temp = "";
595         while ((begCdata = str.find("<![CDATA", endCdata - count)) != std::string::npos &&
596             (endCdata = str.find("]]>", begCdata)) != std::string::npos) {
597             size_t strLen = begCdata - flag;
598             temp = str.substr(flag, strLen);
599             count = 0;
600             while ((pos = temp.find(src)) != std::string::npos) {
601                 temp.replace(pos, src.size(), dst);
602                 count++;
603             }
604             str.replace(flag, strLen, temp);
605             flag = endCdata - count + 3; // 3 : length of "]]>"
606         }
607         temp = str.substr(flag);
608         while ((pos = temp.find(src)) != std::string::npos) {
609             temp.replace(pos, src.size(), dst);
610         }
611         str.replace(flag, str.size() - flag, temp);
612     }
613 
DealCDataInfo(bool bCData,xmlNodePtr & curNode) const614     void ConvertXml::DealCDataInfo(bool bCData, xmlNodePtr &curNode) const
615     {
616         if (bCData && curNode->type == xmlElementType::XML_CDATA_SECTION_NODE &&
617             curNode->next && curNode->next->type == xmlElementType::XML_TEXT_NODE &&
618             curNode->next->next && curNode->next->next->type == xmlElementType::XML_CDATA_SECTION_NODE) {
619                 char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode->next));
620                 if (curContent != nullptr) {
621                     std::string strTemp = reinterpret_cast<char*>(curContent);
622                     Replace(strTemp, " ", "");
623                     Replace(strTemp, "\v", "");
624                     Replace(strTemp, "\t", "");
625                     Replace(strTemp, "\n", "");
626                     if (strTemp == "") {
627                         curNode = curNode->next->next;
628                     }
629                     xmlFree(reinterpret_cast<void*>(curContent));
630                 }
631             } else {
632                 curNode = curNode->next;
633             }
634     }
635 } // namespace OHOS::Xml
636