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     }
181 
SetNodeInfo(napi_env env,xmlNodePtr curNode,const napi_value & elementsObject,const std::string parentName) const182     void ConvertXml::SetNodeInfo(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject,
183                                  const std::string parentName) const
184     {
185         if (curNode->type == xmlElementType::XML_TEXT_NODE) {
186             return;
187         }
188         if (curNode->type == xmlElementType::XML_PI_NODE) {
189             if (!options_.ignoreInstruction) {
190                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
191             }
192         } else {
193                 SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
194         }
195         if ((curNode->type != xmlElementType::XML_COMMENT_NODE) &&
196             (curNode->type != xmlElementType::XML_CDATA_SECTION_NODE)) {
197             if (!(curNode->type == xmlElementType::XML_PI_NODE && options_.ignoreInstruction)) {
198                 SetKeyValue(env, elementsObject, options_.name, reinterpret_cast<const char*>(curNode->name));
199                 if (!parentName.empty()) {
200                     SetKeyValue(env, elementsObject, options_.parent, parentName);
201                 }
202             }
203         }
204     }
205 
SetEndInfo(napi_env env,xmlNodePtr curNode,const napi_value & elementsObject,bool & bFlag) const206     void ConvertXml::SetEndInfo(napi_env env, xmlNodePtr curNode, const napi_value &elementsObject,
207                                 bool &bFlag) const
208     {
209         SetKeyValue(env, elementsObject, options_.type, GetNodeType(curNode->type));
210         if (curNode->type == xmlElementType::XML_ELEMENT_NODE) {
211             SetKeyValue(env, elementsObject, options_.name, reinterpret_cast<const char*>(curNode->name));
212             bFlag = true;
213         } else if (curNode->type == xmlElementType::XML_TEXT_NODE) {
214             char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode));
215             if (options_.trim) {
216                 if (curContent != nullptr) {
217                     SetKeyValue(env, elementsObject, options_.text,
218                                 Trim(curContent));
219                 }
220             } else {
221                 if (curContent != nullptr) {
222                     SetKeyValue(env, elementsObject, options_.text, curContent);
223                 }
224             }
225             if (curContent != nullptr) {
226                 xmlFree(reinterpret_cast<void*>(curContent));
227             }
228             if (!options_.ignoreText) {
229                 bFlag = true;
230             }
231         }
232     }
233 
SetPrevInfo(napi_env env,const napi_value & recvElement,int flag,int32_t & index1) const234     void ConvertXml::SetPrevInfo(napi_env env, const napi_value &recvElement, int flag, int32_t &index1) const
235     {
236         if (!prevObj_.empty() && !flag) {
237             for (size_t i = (prevObj_.size() - 1); i > 0; --i) {
238                 napi_set_element(env, recvElement, index1++, prevObj_[i]);
239             }
240             napi_set_element(env, recvElement, index1++, prevObj_[0]);
241         }
242     }
243 
GetXMLInfo(napi_env env,xmlNodePtr curNode,const napi_value & object,int flag,const std::string parentName)244     void ConvertXml::GetXMLInfo(napi_env env, xmlNodePtr curNode, const napi_value &object,
245                                 int flag, const std::string parentName)
246     {
247         napi_value recvElement = nullptr;
248         napi_create_array(env, &recvElement);
249         xmlNodePtr pNode = curNode;
250         int32_t index = 0;
251         bool bFlag = false;
252         while (pNode != nullptr) {
253             if (!deprecated_) {
254                 if (pNode->type == xmlElementType::XML_TEXT_NODE &&
255                     (pNode->next != nullptr || pNode->prev != nullptr)) {
256                     pNode = pNode->next;
257                     continue;
258                 }
259             }
260             bFlag = false;
261             napi_value elementsObject = nullptr;
262             napi_create_object(env, &elementsObject);
263             SetNodeInfo(env, pNode, elementsObject, parentName);
264             SetAttributes(env, pNode, elementsObject);
265             char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(pNode));
266             if (curContent != nullptr) {
267                 if (pNode->children != nullptr) {
268                     curNode = pNode->children;
269                     const std::string parentNameTemp = apiFlag_ ? reinterpret_cast<const char*>(pNode->name) : "";
270                     GetXMLInfo(env, curNode, elementsObject, 1, parentNameTemp);
271                     bFlag = true;
272                 } else {
273                     SetXmlElementType(env, pNode, elementsObject, bFlag);
274                     SetEndInfo(env, pNode, elementsObject, bFlag);
275                 }
276                 xmlFree(reinterpret_cast<void*>(curContent));
277             }
278             SetPrevInfo(env, recvElement, flag, index);
279             if (elementsObject != nullptr && bFlag) {
280                 napi_set_element(env, recvElement, index++, elementsObject);
281                 elementsObject = nullptr;
282             }
283             pNode = pNode->next;
284         }
285         if (bFlag) {
286             napi_set_named_property(env, object, options_.elements.c_str(), recvElement);
287         }
288     }
289 
SetSpacesInfo(napi_env env,const napi_value & object) const290     void ConvertXml::SetSpacesInfo(napi_env env, const napi_value &object) const
291     {
292         napi_value iTemp = nullptr;
293         switch (spaceType_) {
294             case (SpaceType::T_INT32):
295                 napi_create_int32(env, iSpace_, &iTemp);
296                 napi_set_named_property(env, object, "spaces", iTemp);
297                 break;
298             case (SpaceType::T_STRING):
299                 SetKeyValue(env, object, "spaces", strSpace_);
300                 break;
301             case (SpaceType::T_INIT):
302                 SetKeyValue(env, object, "spaces", strSpace_);
303                 break;
304             default:
305                 break;
306             }
307     }
308 
Convert(napi_env env,std::string strXml,bool deprecated)309     napi_value ConvertXml::Convert(napi_env env, std::string strXml, bool deprecated)
310     {
311         xmlNodePtr curNode = nullptr;
312         napi_value object = nullptr;
313         napi_status status = napi_create_object(env, &object);
314         if (status != napi_ok) {
315             return nullptr;
316         }
317         size_t len = strXml.size();
318         xmlDocPtr doc = xmlParseMemory(strXml.c_str(), len);
319         deprecated_ = deprecated;
320         if (!doc) {
321             xmlFreeDoc(doc);
322             DealSingleLine(env, strXml, object);
323             return object;
324         }
325         napi_value subObject = nullptr;
326         napi_value subSubObject = nullptr;
327         napi_create_object(env, &subSubObject);
328         napi_create_object(env, &subObject);
329         if (doc != nullptr && doc->version != nullptr) {
330             SetKeyValue(env, subSubObject, "version", (const char*)doc->version);
331         }
332         if (doc != nullptr && doc->encoding != nullptr) {
333             SetKeyValue(env, subSubObject, "encoding", (const char*)doc->encoding);
334         }
335         if (!options_.ignoreDeclaration && strXml.find("xml") != std::string::npos) {
336             napi_set_named_property(env, subObject, options_.attributes.c_str(), subSubObject);
337             napi_set_named_property(env, object, options_.declaration.c_str(), subObject);
338         }
339         if (doc != nullptr) {
340             curNode = xmlDocGetRootElement(doc);
341             GetPrevNodeList(env, curNode);
342             GetXMLInfo(env, curNode, object, 0);
343         }
344         xmlFreeDoc(doc);
345         if (deprecated_) {
346             SetSpacesInfo(env, object);
347         }
348         return object;
349     }
350 
DealNapiStrValue(napi_env env,const napi_value napi_StrValue,std::string & result) const351     napi_status ConvertXml::DealNapiStrValue(napi_env env, const napi_value napi_StrValue, std::string &result) const
352     {
353         std::string buffer = "";
354         size_t bufferSize = 0;
355         napi_status status = napi_ok;
356         status = napi_get_value_string_utf8(env, napi_StrValue, nullptr, -1, &bufferSize);
357         if (status != napi_ok) {
358             HILOG_ERROR("can not get buffer size");
359             return status;
360         }
361         buffer.reserve(bufferSize + 1);
362         buffer.resize(bufferSize);
363         if (bufferSize > 0) {
364             status = napi_get_value_string_utf8(env, napi_StrValue, buffer.data(), bufferSize + 1, &bufferSize);
365             if (status != napi_ok) {
366                 HILOG_ERROR("can not get buffer value");
367                 return status;
368             }
369         }
370         if (buffer.data() != nullptr) {
371             result = buffer;
372         }
373         return status;
374     }
375 
DealSpaces(napi_env env,const napi_value napiObj)376     void ConvertXml::DealSpaces(napi_env env, const napi_value napiObj)
377     {
378         napi_value recvTemp = nullptr;
379         napi_get_named_property(env, napiObj, "spaces", &recvTemp);
380         napi_valuetype valuetype = napi_undefined;
381         napi_typeof(env, recvTemp, &valuetype);
382         if (valuetype == napi_string) {
383             DealNapiStrValue(env, recvTemp, strSpace_);
384             spaceType_ = SpaceType::T_STRING;
385         } else if (valuetype == napi_number) {
386             int32_t iTemp;
387             if (napi_get_value_int32(env, recvTemp, &iTemp) == napi_ok) {
388                 iSpace_ = iTemp;
389                 spaceType_ = SpaceType::T_INT32;
390             }
391         }
392     }
393 
DealIgnore(napi_env env,const napi_value napiObj)394     void ConvertXml::DealIgnore(napi_env env, const napi_value napiObj)
395     {
396         std::vector<std::string> vctIgnore = {"compact", "trim", "ignoreDeclaration", "ignoreInstruction",
397                                               "ignoreAttributes", "ignoreComment", "ignoreCDATA",
398                                               "ignoreDoctype", "ignoreText"};
399         size_t vctLength = vctIgnore.size();
400         for (size_t i = 0; i < vctLength; ++i) {
401             napi_value recvTemp = nullptr;
402             bool bRecv = false;
403             napi_get_named_property(env, napiObj, vctIgnore[i].c_str(), &recvTemp);
404             if ((napi_get_value_bool(env, recvTemp, &bRecv)) == napi_ok) {
405                 switch (i) {
406                     case 0:
407                         options_.compact = bRecv;
408                         break;
409                     case 1: // 1:trim
410                         options_.trim = bRecv;
411                         break;
412                     case 2: // 2:ignoreDeclaration
413                         options_.ignoreDeclaration = bRecv;
414                         break;
415                     case 3: // 3:ignoreInstruction
416                         options_.ignoreInstruction = bRecv;
417                         break;
418                     case 4: // 4:ignoreAttributes
419                         options_.ignoreAttributes = bRecv;
420                         break;
421                     case 5: // 5:ignoreComment
422                         options_.ignoreComment = bRecv;
423                         break;
424                     case 6: // 6:ignoreCdata
425                         options_.ignoreCdata = bRecv;
426                         break;
427                     case 7: // 7:ignoreDoctype
428                         options_.ignoreDoctype = bRecv;
429                         break;
430                     case 8: // 8:ignoreText
431                         options_.ignoreText = bRecv;
432                         break;
433                     default:
434                         break;
435                 }
436             }
437         }
438     }
439 
SetDefaultKey(size_t i,const std::string strRecv)440     void ConvertXml::SetDefaultKey(size_t i, const std::string strRecv)
441     {
442         switch (i) {
443             case 0:
444                 options_.declaration = strRecv;
445                 break;
446             case 1:
447                 options_.instruction = strRecv;
448                 break;
449             case 2: // 2:attributes
450                 options_.attributes = strRecv;
451                 break;
452             case 3: // 3:text
453                 options_.text = strRecv;
454                 break;
455             case 4: // 4:cdata
456                 options_.cdata = strRecv;
457                 break;
458             case 5: // 5:doctype
459                 options_.doctype = strRecv;
460                 break;
461             case 6: // 6:comment
462                 options_.comment = strRecv;
463                 break;
464             case 7: // 7:parent
465                 options_.parent = strRecv;
466                 break;
467             case 8: // 8:type
468                 options_.type = strRecv;
469                 break;
470             case 9: // 9:name
471                 options_.name = strRecv;
472                 break;
473             case 10: // 10:elements
474                 options_.elements = strRecv;
475                 break;
476             default:
477                 break;
478         }
479     }
480 
DealOptions(napi_env env,const napi_value napiObj,bool deprecated)481     void ConvertXml::DealOptions(napi_env env, const napi_value napiObj, bool deprecated)
482     {
483         std::vector<std::string> vctOptions = {"declarationKey", "instructionKey", "attributesKey", "textKey",
484                                               "cdataKey", "doctypeKey", "commentKey", "parentKey", "typeKey",
485                                               "nameKey", "elementsKey"};
486         size_t vctLength = vctOptions.size();
487         for (size_t i = 0; i < vctLength; ++i) {
488             napi_value recvTemp = nullptr;
489             std::string strRecv = "";
490             napi_get_named_property(env, napiObj, vctOptions[i].c_str(), &recvTemp);
491             if ((DealNapiStrValue(env, recvTemp, strRecv)) == napi_ok) {
492                 SetDefaultKey(i, strRecv);
493             }
494         }
495         DealIgnore(env, napiObj);
496         if (deprecated) {
497             DealSpaces(env, napiObj);
498         }
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                 if (!deprecated_ && curNode->type == xmlElementType::XML_TEXT_NODE &&
577                     (curNode->next != nullptr || curNode->prev != nullptr)) {
578                     curNode = curNode->next;
579                     continue;
580                 }
581                 SetEndInfo(env, curNode, elementsObject, bHasEle);
582                 napi_set_element(env, elements, index++, elementsObject);
583                 DealCDataInfo(bCData, curNode);
584             }
585             if (bHasEle) {
586                 napi_set_named_property(env, object, options_.elements.c_str(), elements);
587             }
588             xmlFreeDoc(doc);
589         }
590     }
591 
Replace(std::string & str,const std::string src,const std::string dst) const592     void ConvertXml::Replace(std::string &str, const std::string src, const std::string dst) const
593     {
594         size_t index = 0;
595         while ((index = str.find(src)) != std::string::npos) {
596             str.replace(index, src.size(), dst);
597         }
598     }
599 
DealCDataInfo(bool bCData,xmlNodePtr & curNode) const600     void ConvertXml::DealCDataInfo(bool bCData, xmlNodePtr &curNode) const
601     {
602         if (bCData && curNode->type == xmlElementType::XML_CDATA_SECTION_NODE &&
603             curNode->next && curNode->next->type == xmlElementType::XML_TEXT_NODE &&
604             curNode->next->next && curNode->next->next->type == xmlElementType::XML_CDATA_SECTION_NODE) {
605                 char *curContent = reinterpret_cast<char*>(xmlNodeGetContent(curNode->next));
606                 if (curContent != nullptr) {
607                     std::string strTemp = reinterpret_cast<char*>(curContent);
608                     Replace(strTemp, " ", "");
609                     Replace(strTemp, "\v", "");
610                     Replace(strTemp, "\t", "");
611                     Replace(strTemp, "\n", "");
612                     if (strTemp == "") {
613                         curNode = curNode->next->next;
614                     }
615                     xmlFree(reinterpret_cast<void*>(curContent));
616                 }
617             } else {
618                 curNode = curNode->next;
619             }
620     }
621 } // namespace OHOS::Xml
622