• 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         friend class XmlTest;
146 
147     private:
148         char *pStart_;
149         size_t iPos_ = 0;
150         size_t iLength_;
151         std::string xmlSerializerError_;
152         std::string encoding_;
153         size_t depth_ = 0;
154         std::string type;
155         std::vector<std::string> elementStack = { "", "", ""};
156         std::map<int, std::map<int, std::string>> multNsp;
157         int CurNspNum = 0;
158         std::string out_;
159         bool isHasDecl = false;
160     };
161 
162     enum class TagEnum {
163         XML_DECLARATION = -1,
164         START_DOCUMENT,
165         END_DOCUMENT,
166         START_TAG,
167         END_TAG,
168         TEXT,
169         CDSECT,
170         COMMENT,
171         DOCDECL,
172         INSTRUCTION,
173         ENTITY_REFERENCE,
174         WHITESPACE,
175         ELEMENTDECL,
176         ENTITYDECL,
177         ATTLISTDECL,
178         NOTATIONDECL,
179         PARAMETER_ENTITY_REF,
180         OK,
181         ERROR1
182     };
183 
184     enum class TextEnum {
185         ATTRI,
186         TEXT,
187         ENTITY_DECL
188     };
189     class XmlPullParser {
190     public:
191         class ParseInfo {
192         public:
193             /**
194              * Get the current depth of the element.
195              * @param env The parameter is NAPI environment variables.
196              * @param info The parameter is the current depth of the returned element.
197              */
198             static napi_value GetDepth(napi_env env, napi_callback_info info);
199 
200             /**
201              * Get the current column number, starting at 1.
202              * @param env The parameter is NAPI environment variables.
203              * @param info The parameter is to return the current line number.
204              */
205             static napi_value GetColumnNumber(napi_env env, napi_callback_info info);
206 
207             /**
208              * Get the current line number, starting at 1.
209              * @param env The parameter is NAPI environment variables.
210              * @param info The parameter is to return the current column number.
211              */
212             static napi_value GetLineNumber(napi_env env, napi_callback_info info);
213 
214             /**
215              * Get the number of attributes of the current start tag.
216              * @param env The parameter is NAPI environment variables.
217              * @param info The parameter is the number of attributes of the current start tag.
218              */
219             static napi_value GetAttributeCount(napi_env env, napi_callback_info info);
220 
221             /**
222              * Get the current element name.
223              * @param env The parameter is NAPI environment variables.
224              * @param info The parameter is to return the current element name.
225              */
226             static napi_value GetName(napi_env env, napi_callback_info info);
227 
228             /**
229              * Get the namespace of the current element.
230              * @param env The parameter is NAPI environment variables.
231              * @param info The parameter is the namespace that returns the current element.
232              */
233             static napi_value GetNamespace(napi_env env, napi_callback_info info);
234 
235             /**
236              * Get the current element prefix.
237              * @param env The parameter is NAPI environment variables.
238              * @param info The parameter is to return the current element prefix.
239              */
240             static napi_value GetPrefix(napi_env env, napi_callback_info info);
241 
242             /**
243              * Get the text content of the current event.
244              * @param env The parameter is NAPI environment variables.
245              * @param info The parameter is to return the text content of the current event.
246              */
247             static napi_value GetText(napi_env env, napi_callback_info info);
248 
249             /**
250              * Check whether the current element is an empty element.
251              * @param env The parameter is NAPI environment variables.
252              * @param info The parameter is to returns true The current element is an empty element.
253              */
254             static napi_value IsEmptyElementTag(napi_env env, napi_callback_info info);
255 
256             /**
257              * Determines whether the current text event contains only space characters.
258              * @param env The parameter is NAPI environment variables.
259              * @param info The parameter is to returns true, the current text event contains only space characters.
260              */
261             static napi_value IsWhitespace(napi_env env, napi_callback_info info);
262         };
263         struct TagText {
264             const std::string START_CDATA = "<![CDATA[";
265             const std::string END_CDATA = "]]>";
266             const std::string START_COMMENT = "<!--";
267             const std::string END_COMMENT = "-->";
268             const std::string COMMENT_DOUBLE_DASH = "--";
269             const std::string END_PROCESSING_INSTRUCTION = "?>";
270             const std::string START_DOCTYPE = "<!DOCTYPE";
271             const std::string SYSTEM = "SYSTEM";
272             const std::string PUBLIC = "PUBLIC";
273             const std::string DOUBLE_QUOTE = "\"";
274             const std::string SINGLE_QUOTE = "\\";
275             const std::string START_ELEMENT = "<!ELEMENT";
276             const std::string EMPTY = "EMPTY";
277             const std::string ANY = "ANY";
278             const std::string START_ATTLIST = "<!ATTLIST";
279             const std::string NOTATION = "NOTATION";
280             const std::string REQUIRED = "REQUIRED";
281             const std::string IMPLIED = "IMPLIED";
282             const std::string FIXED = "FIXED";
283             const std::string START_ENTITY = "<!ENTITY";
284             const std::string NDATA = "NDATA";
285             const std::string START_NOTATION = "<!NOTATION";
286             const std::string ILLEGAL_TYPE = "Wrong event type";
287             const std::string START_PROCESSING_INSTRUCTION = "<?";
288             const std::string XML = "xml ";
289         };
290         struct SrcLinkList {
291             SrcLinkList* next;
292             std::string strBuffer;
293             int position;
294             size_t max;
SrcLinkListSrcLinkList295             SrcLinkList()
296             {
297                 this->next = nullptr;
298                 this->strBuffer = "";
299                 this->position = -1;
300                 this->max = -1;
301             };
SrcLinkListSrcLinkList302             SrcLinkList(SrcLinkList* pNext, const std::string &strTemp, int iPos, int iMax) :next(pNext),
303                 strBuffer(strTemp), position(iPos), max(iMax) {}
304         };
XmlPullParser(const std::string & strXml,const std::string & encoding)305         XmlPullParser(const std::string &strXml, const std::string &encoding) : strXml_(strXml),
306             encoding_(encoding) {};
~XmlPullParser()307         ~XmlPullParser()
308         {
309             while (srcLinkList_) {
310                 PopSrcLinkList();
311             }
312         };
313         int GetDepth() const;
314         int GetColumnNumber() const;
315         int GetLineNumber() const;
316         int GetAttributeCount() const;
317         std::string GetName() const;
318         std::string GetNamespace() const;
319         std::string GetPrefix() const;
320         std::string GetText() const;
321         bool IsEmptyElementTag() const;
322         bool IsWhitespace() const;
323         void PushSrcLinkList(std::string strBuffer);
324         void PopSrcLinkList();
325         bool DealLength(size_t minimum);
326         void Replace(std::string &strTemp, std::string strSrc, std::string strDes) const;
327         size_t GetNSCount(size_t iTemp);
328         void Parse(napi_env env, napi_value thisVar);
329         std::string GetNamespace(const std::string &prefix);
330         napi_value DealOptionInfo(napi_env env, napi_value napiObj);
331         TagEnum ParseTagType(bool inDeclaration);
332         void SkipText(std::string chars);
333         int PriorDealChar();
334         void SkipChar(char expected);
335         std::string ParseNameInner(size_t start);
336         std::string ParseName();
337         void SkipInvalidChar();
338         void ParseEntity(std::string& out, bool isEntityToken, bool throwOnResolveFailure, TextEnum textEnum);
339         std::string ParseTagValue(char delimiter, bool resolveEntities, bool throwOnResolveFailure, TextEnum textEnum);
340         bool ParseNsp();
341         void ParseStartTag(bool xmldecl, bool throwOnResolveFailure);
342         void ParseDeclaration();
343         void ParseEndTag();
344         std::string ParseDelimiterInfo(std::string delimiter, bool returnText);
345         std::string ParseDelimiter(bool returnText);
346         bool ParserDoctInnerInfo(bool requireSystemName, bool assignFields);
347         void ParseComment(bool returnText);
348         void ParseSpecText();
349         void ParseInnerEleDec();
350         void ParseInnerAttriDecl();
351         void ParseEntityDecl();
352         void ParseInneNotaDecl();
353         void ReadInternalSubset();
354         void ParseDoctype(bool saveDtdText);
355         TagEnum ParseOneTag();
356         void ParserPriorDeal();
357         void ParseInstruction();
358         void ParseText();
359         void ParseCdect();
360         std::string XmlPullParserError() const;
361         bool ParseAttri(napi_env env, napi_value thisVar) const;
362         bool ParseToken(napi_env env, napi_value thisVar) const;
363         void ParseNspFunction();
364         void ParseNspFunc(size_t &i, const std::string &attrName, bool &any);
365         void ParseInnerAttriDeclFunc(int &c);
366         TagEnum DealExclamationGroup();
367         void ParseEntityFunc(size_t start, std::string &out, bool isEntityToken, TextEnum textEnum);
368         bool ParseStartTagFuncDeal(bool throwOnResolveFailure);
369         bool ParseStartTagFunc(bool xmldecl, bool throwOnResolveFailure);
370         TagEnum ParseOneTagFunc();
371         size_t ParseTagValueInner(size_t &start, std::string &result, char delimiter, TextEnum textEnum, bool bFlag);
372         bool ParseTagValueFunc(char &c, bool bFlag, TextEnum textEnum, size_t &start, std::string &result);
373         void MakeStrUpper(std::string &src) const;
374         TagEnum DealLtGroup();
375         void DealWhiteSpace(unsigned char c);
376         friend class XmlTest;
377     private:
378         bool bDoctype_ = false;
379         bool bIgnoreNS_ = false;
380         bool bStartDoc_ = true;
381         napi_value tagFunc_ = nullptr;
382         napi_value attrFunc_ = nullptr;
383         napi_value tokenFunc_ = nullptr;
384         TagText tagText_;
385         std::string strXml_ = "";
386         std::string version_ = "";
387         std::string encoding_ = "";
388         std::string prefix_ = "";
389         std::string namespace_ = "";
390         std::string name_ = "";
391         std::string text_ = "";
392         std::string sysInfo_ = "";
393         std::string pubInfo_ = "";
394         std::string keyInfo_ = "";
395         std::string xmlPullParserError_ = "";
396         std::vector<size_t> nspCounts_;
397         std::vector<std::string> nspStack_;
398         std::vector<std::string> elementStack_;
399         std::vector<std::string> attributes;
400         std::map<std::string, std::string> documentEntities;
401         std::map<std::string, std::map<std::string, std::string>> defaultAttributes;
402         std::map<std::string, std::string> DEFAULT_ENTITIES = {
403             {"lt;", "<"}, {"gt;", ">"}, {"amp;", "&"}, {"apos;", "'"}, {"quot;", "\""}
404         };
405         size_t position_ = 0;
406         size_t depth = 0;
407         size_t max_ = 0;
408         size_t bufferStartLine_ = 0;
409         size_t bufferStartColumn_ = 0;
410         size_t attriCount_ = 0;
411         TagEnum type = TagEnum::START_DOCUMENT;
412         bool bWhitespace_ = false;
413         SrcLinkList* srcLinkList_ = new SrcLinkList;
414         bool bEndFlag_ = false;
415         bool bAlone_ = false;
416         bool bUnresolved_ = false;
417         bool relaxed = false;
418         bool bKeepNsAttri = false;
419         bool bDocDecl = false;
420     };
421 } // namespace OHOS::Xml
422 #endif // XML_JS_XML_H
423