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