• 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 #ifndef XML_JS_XML_H_
17 #define XML_JS_XML_H_
18 
19 #include <algorithm>
20 #include <cstring>
21 #include <map>
22 #include <string>
23 #include <vector>
24 #include "napi/native_api.h"
25 #include "napi/native_node_api.h"
26 #include "utils/log.h"
27 
28 namespace OHOS::xml {
29     class XmlSerializer {
30     public:
31         /**
32          * Constructor for XmlSerializer.
33          *
34          * @param pStart is the pointer.
35          * @param bufferLengthis the length of the ArrayBuffer or
36          * DataView memory used to receive the written xml information.
37          */
pStart_(pStart)38         XmlSerializer(char *pStart, size_t bufferLength, const std::string &encoding = "utf-8") :pStart_(pStart),
39             iLength_(bufferLength), encoding_(encoding) {};
40 
41         /**
42          * XmlSerializer destructor.
43          */
~XmlSerializer()44         ~XmlSerializer() {}
45 
46         /**
47          * Set the Attributes method.
48          *
49          * @param name The parameter is the key value of the property.
50          * @param value The parameter is the value of the property.
51          */
52         void SetAttributes(const std::string &name, const std::string &value);
53 
54         /**
55          * Writes an empty element.
56          *
57          * @param name The parameter is the element name of the empty element.
58          */
59         void AddEmptyElement(std::string name);
60 
61         /**
62          * Set the Declaration method.
63          */
64         void SetDeclaration();
65 
66         /**
67          * Writes the element start tag with the given name.
68          *
69          * @param name The parameter is the element name of the current element.
70          */
71         void StartElement(const std::string &name);
72 
73         /**
74          * Write element end tag.
75          */
76         void EndElement();
77 
78         /**
79          * The namespace into which the current element tag is written.
80          *
81          * @param prefix The parameter is the prefix of the current element and its children.
82          * @param nsTemp The parameter is the namespace of the current element and its children.
83          */
84         void SetNamespace(std::string prefix, const std::string &nsTemp);
85 
86         /**
87          * Write the comment property.
88          *
89          * @param comment The parameter is the comment content of the current element.
90          */
91         void SetComment(const std::string &comment);
92 
93         /**
94          * Write CDATA attributes.
95          *
96          * @param comment The parameter is the content of the CDATA attribute.
97          */
98         void SetCData(std::string data);
99 
100         /**
101          * Write CDATA attributes.
102          *
103          * @param comment The parameter is the content of the CDATA attribute.
104          */
105         void SetText(const std::string &text);
106 
107         /**
108          * Write DocType property.
109          *
110          * @param text The parameter is the content of the DocType property.
111          */
112         void SetDocType(const std::string &text);
113 
114         /**
115          * write an escape.
116          *
117          * @param s The parameter is the passed in escaped string.
118          */
119         void WriteEscaped(std::string s);
120 
121         /**
122          * SplicNsp functio.
123          */
124         void SplicNsp();
125 
126         /**
127          * NextItem function.
128          */
129         void NextItem();
130 
131         /**
132          * Throw exception function.
133          */
134         std::string XmlSerializerError();
135 
136         /**
137          * Process the value of the string passed by napi.
138          *
139          * @param env The parameter is NAPI environment variables.
140          * @param napiStr The parameter is pass parameters.
141          * @param result The parameter is return the processed value.
142          */
143         static napi_status DealNapiStrValue(napi_env env, const napi_value napiStr, std::string &result);
144 
145     private:
146         char *pStart_;
147         size_t iPos_ = 0;
148         size_t iLength_;
149         std::string xmlSerializerError_;
150         std::string encoding_;
151         size_t depth_ = 0;
152         std::string type;
153         std::vector<std::string> elementStack = { "", "", ""};
154         std::map<int, std::map<int, std::string>> multNsp;
155         int CurNspNum = 0;
156         std::string out_;
157         bool isHasDecl = false;
158     };
159 
160     enum class TagEnum {
161         XML_DECLARATION = -1,
162         START_DOCUMENT,
163         END_DOCUMENT,
164         START_TAG,
165         END_TAG,
166         TEXT,
167         CDSECT,
168         COMMENT,
169         DOCDECL,
170         INSTRUCTION,
171         ENTITY_REFERENCE,
172         WHITESPACE,
173         ELEMENTDECL,
174         ENTITYDECL,
175         ATTLISTDECL,
176         NOTATIONDECL,
177         PARAMETER_ENTITY_REF,
178         OK,
179         ERROR1
180     };
181 
182     enum class TextEnum {
183         ATTRI,
184         TEXT,
185         ENTITY_DECL
186     };
187     class XmlPullParser {
188     public:
189         class ParseInfo {
190         public:
191             /**
192              * Get the current depth of the element.
193              * @param env The parameter is NAPI environment variables.
194              * @param info The parameter is the current depth of the returned element.
195              */
196             static napi_value GetDepth(napi_env env, napi_callback_info info);
197 
198             /**
199              * Get the current column number, starting at 1.
200              * @param env The parameter is NAPI environment variables.
201              * @param info The parameter is to return the current line number.
202              */
203             static napi_value GetColumnNumber(napi_env env, napi_callback_info info);
204 
205             /**
206              * Get the current line number, starting at 1.
207              * @param env The parameter is NAPI environment variables.
208              * @param info The parameter is to return the current column number.
209              */
210             static napi_value GetLineNumber(napi_env env, napi_callback_info info);
211 
212             /**
213              * Get the number of attributes of the current start tag.
214              * @param env The parameter is NAPI environment variables.
215              * @param info The parameter is the number of attributes of the current start tag.
216              */
217             static napi_value GetAttributeCount(napi_env env, napi_callback_info info);
218 
219             /**
220              * Get the current element name.
221              * @param env The parameter is NAPI environment variables.
222              * @param info The parameter is to return the current element name.
223              */
224             static napi_value GetName(napi_env env, napi_callback_info info);
225 
226             /**
227              * Get the namespace of the current element.
228              * @param env The parameter is NAPI environment variables.
229              * @param info The parameter is the namespace that returns the current element.
230              */
231             static napi_value GetNamespace(napi_env env, napi_callback_info info);
232 
233             /**
234              * Get the current element prefix.
235              * @param env The parameter is NAPI environment variables.
236              * @param info The parameter is to return the current element prefix.
237              */
238             static napi_value GetPrefix(napi_env env, napi_callback_info info);
239 
240             /**
241              * Get the text content of the current event.
242              * @param env The parameter is NAPI environment variables.
243              * @param info The parameter is to return the text content of the current event.
244              */
245             static napi_value GetText(napi_env env, napi_callback_info info);
246 
247             /**
248              * Check whether the current element is an empty element.
249              * @param env The parameter is NAPI environment variables.
250              * @param info The parameter is to returns true The current element is an empty element.
251              */
252             static napi_value IsEmptyElementTag(napi_env env, napi_callback_info info);
253 
254             /**
255              * Determines whether the current text event contains only space characters.
256              * @param env The parameter is NAPI environment variables.
257              * @param info The parameter is to returns true, the current text event contains only space characters.
258              */
259             static napi_value IsWhitespace(napi_env env, napi_callback_info info);
260         };
261         struct TagText {
262             const std::string START_CDATA = "<![CDATA[";
263             const std::string END_CDATA = "]]>";
264             const std::string START_COMMENT = "<!--";
265             const std::string END_COMMENT = "-->";
266             const std::string COMMENT_DOUBLE_DASH = "--";
267             const std::string END_PROCESSING_INSTRUCTION = "?>";
268             const std::string START_DOCTYPE = "<!DOCTYPE";
269             const std::string SYSTEM = "SYSTEM";
270             const std::string PUBLIC = "PUBLIC";
271             const std::string DOUBLE_QUOTE = "\"";
272             const std::string SINGLE_QUOTE = "\\";
273             const std::string START_ELEMENT = "<!ELEMENT";
274             const std::string EMPTY = "EMPTY";
275             const std::string ANY = "ANY";
276             const std::string START_ATTLIST = "<!ATTLIST";
277             const std::string NOTATION = "NOTATION";
278             const std::string REQUIRED = "REQUIRED";
279             const std::string IMPLIED = "IMPLIED";
280             const std::string FIXED = "FIXED";
281             const std::string START_ENTITY = "<!ENTITY";
282             const std::string NDATA = "NDATA";
283             const std::string START_NOTATION = "<!NOTATION";
284             const std::string ILLEGAL_TYPE = "Wrong event type";
285             const std::string START_PROCESSING_INSTRUCTION = "<?";
286             const std::string XML = "xml ";
287         };
288         struct SrcLinkList {
289             SrcLinkList* next;
290             std::string strBuffer;
291             int position;
292             size_t max;
SrcLinkListSrcLinkList293             SrcLinkList()
294             {
295                 this->next = nullptr;
296                 this->strBuffer = "";
297                 this->position = -1;
298                 this->max = -1;
299             };
SrcLinkListSrcLinkList300             SrcLinkList(SrcLinkList* pNext, const std::string &strTemp, int iPos, int iMax) :next(pNext),
301                 strBuffer(strTemp), position(iPos), max(iMax) {}
302         };
XmlPullParser(const std::string & strXml,const std::string & encoding)303         XmlPullParser(const std::string &strXml, const std::string &encoding) : strXml_(strXml),
304             encoding_(encoding) {};
~XmlPullParser()305         ~XmlPullParser()
306         {
307             while (srcLinkList_) {
308                 PopSrcLinkList();
309             }
310         };
311         int GetDepth() const;
312         int GetColumnNumber() const;
313         int GetLineNumber() const;
314         int GetAttributeCount() const;
315         std::string GetName() const;
316         std::string GetNamespace() const;
317         std::string GetPrefix() const;
318         std::string GetText() const;
319         bool IsEmptyElementTag() const;
320         bool IsWhitespace() const;
321         void PushSrcLinkList(std::string strBuffer);
322         void PopSrcLinkList();
323         bool DealLength(size_t minimum);
324         void Replace(std::string &strTemp, std::string strSrc, std::string strDes) const;
325         size_t GetNSCount(size_t iTemp);
326         void Parse(napi_env env, napi_value thisVar);
327         std::string GetNamespace(const std::string &prefix);
328         napi_value DealOptionInfo(napi_env env, napi_value napiObj);
329         TagEnum ParseTagType(bool inDeclaration);
330         void SkipText(std::string chars);
331         int PriorDealChar();
332         void SkipChar(char expected);
333         std::string ParseNameInner(size_t start);
334         std::string ParseName();
335         void SkipInvalidChar();
336         void ParseEntity(std::string& out, bool isEntityToken, bool throwOnResolveFailure, TextEnum textEnum);
337         std::string ParseTagValue(char delimiter, bool resolveEntities, bool throwOnResolveFailure, TextEnum textEnum);
338         bool ParseNsp();
339         void ParseStartTag(bool xmldecl, bool throwOnResolveFailure);
340         void ParseDeclaration();
341         void ParseEndTag();
342         std::string ParseDelimiterInfo(std::string delimiter, bool returnText);
343         std::string ParseDelimiter(bool returnText);
344         bool ParserDoctInnerInfo(bool requireSystemName, bool assignFields);
345         void ParseComment(bool returnText);
346         void ParseSpecText();
347         void ParseInnerEleDec();
348         void ParseInnerAttriDecl();
349         void ParseEntityDecl();
350         void ParseInneNotaDecl();
351         void ReadInternalSubset();
352         void ParseDoctype(bool saveDtdText);
353         TagEnum ParseOneTag();
354         void ParserPriorDeal();
355         void ParseInstruction();
356         void ParseText();
357         void ParseCdect();
358         std::string XmlPullParserError() const;
359         bool ParseAttri(napi_env env, napi_value thisVar) const;
360         bool ParseToken(napi_env env, napi_value thisVar) const;
361         void ParseNspFunction();
362         void ParseNspFunc(size_t &i, const std::string &attrName, bool &any);
363         void ParseInnerAttriDeclFunc(int &c);
364         TagEnum DealExclamationGroup();
365         void ParseEntityFunc(size_t start, std::string &out, bool isEntityToken, TextEnum textEnum);
366         bool ParseStartTagFuncDeal(bool throwOnResolveFailure);
367         bool ParseStartTagFunc(bool xmldecl, bool throwOnResolveFailure);
368         TagEnum ParseOneTagFunc();
369         size_t ParseTagValueInner(size_t &start, std::string &result, char delimiter, TextEnum textEnum, bool bFlag);
370         bool ParseTagValueFunc(char &c, bool bFlag, TextEnum textEnum, size_t &start, std::string &result);
371         void MakeStrUpper(std::string &src) const;
372         TagEnum DealLtGroup();
373         void DealWhiteSpace(unsigned char c);
374 
375     private:
376         bool bDoctype_ = false;
377         bool bIgnoreNS_ = false;
378         bool bStartDoc_ = true;
379         napi_value tagFunc_ = nullptr;
380         napi_value attrFunc_ = nullptr;
381         napi_value tokenFunc_ = nullptr;
382         TagText tagText_;
383         std::string strXml_ = "";
384         std::string version_ = "";
385         std::string encoding_ = "";
386         std::string prefix_ = "";
387         std::string namespace_ = "";
388         std::string name_ = "";
389         std::string text_ = "";
390         std::string sysInfo_ = "";
391         std::string pubInfo_ = "";
392         std::string keyInfo_ = "";
393         std::string xmlPullParserError_ = "";
394         std::vector<size_t> nspCounts_;
395         std::vector<std::string> nspStack_;
396         std::vector<std::string> elementStack_;
397         std::vector<std::string> attributes;
398         std::map<std::string, std::string> documentEntities;
399         std::map<std::string, std::map<std::string, std::string>> defaultAttributes;
400         std::map<std::string, std::string> DEFAULT_ENTITIES = {
401             {"lt;", "<"}, {"gt;", ">"}, {"amp;", "&"}, {"apos;", "'"}, {"quot;", "\""}
402         };
403         size_t position_ = 0;
404         size_t depth = 0;
405         size_t max_ = 0;
406         size_t bufferStartLine_ = 0;
407         size_t bufferStartColumn_ = 0;
408         size_t attriCount_ = 0;
409         TagEnum type = TagEnum::START_DOCUMENT;
410         bool bWhitespace_ = false;
411         SrcLinkList* srcLinkList_ = new SrcLinkList;
412         bool bEndFlag_ = false;
413         bool bAlone_ = false;
414         bool bUnresolved_ = false;
415         bool relaxed = false;
416         bool bKeepNsAttri = false;
417         bool bDocDecl = false;
418     };
419 } // namespace OHOS::Xml
420 #endif // XML_JS_XML_H_
421