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