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