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 #include "js_xml.h" 17 #include "napi/native_api.h" 18 #include "napi/native_node_api.h" 19 20 extern const char _binary_js_xml_js_start[]; 21 extern const char _binary_js_xml_js_end[]; 22 extern const char _binary_xml_abc_start[]; 23 extern const char _binary_xml_abc_end[]; 24 25 namespace OHOS::xml { XmlSerializerConstructor(napi_env env,napi_callback_info info)26 static napi_value XmlSerializerConstructor(napi_env env, napi_callback_info info) 27 { 28 napi_value thisVar = nullptr; 29 void *data = nullptr; 30 size_t argc = 0; 31 napi_value args[2] = { 0 }; // 2:The number of parameters is 2 32 XmlSerializer *object = nullptr; 33 size_t iLength = 0; 34 size_t offPos = 0; 35 napi_value arraybuffer = nullptr; 36 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, &data)); 37 NAPI_ASSERT(env, argc == 1 || argc == 2, "Wrong number of arguments"); // 2: number of args 38 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, &data)); 39 if (args[0] == nullptr) { 40 NAPI_CALL(env, napi_throw_error(env, "", "parameter is empty")); 41 } else { 42 bool bFlag = false; 43 napi_is_arraybuffer(env, args[0], &bFlag); 44 if (bFlag) { 45 napi_get_arraybuffer_info(env, args[0], &data, &iLength); 46 } 47 napi_is_dataview(env, args[0], &bFlag); 48 if (bFlag) { 49 napi_get_dataview_info(env, args[0], &iLength, &data, &arraybuffer, &offPos); 50 } 51 } 52 if (argc == 1) { 53 object = new XmlSerializer(reinterpret_cast<char*>(data), iLength); 54 } else if (argc == 2) { // 2:When the input parameter is set to 2 55 std::string encoding = ""; 56 napi_valuetype valuetype; 57 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype)); 58 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. String expected."); 59 napi_status status = napi_ok; 60 status = XmlSerializer::DealNapiStrValue(env, args[1], encoding); 61 if (status == napi_ok) { 62 object = new XmlSerializer(reinterpret_cast<char*>(data), iLength, encoding); 63 } 64 } 65 napi_wrap( 66 env, thisVar, object, 67 [](napi_env environment, void *data, void *hint) { 68 auto obj = reinterpret_cast<XmlSerializer*>(data); 69 if (obj != nullptr) { 70 delete obj; 71 } 72 }, 73 nullptr, nullptr); 74 return thisVar; 75 } 76 XmlPullParserConstructor(napi_env env,napi_callback_info info)77 static napi_value XmlPullParserConstructor(napi_env env, napi_callback_info info) 78 { 79 napi_value thisVar = nullptr; 80 void *data = nullptr; 81 size_t argc = 0; 82 napi_value args[2] = { 0 }; // 2:two args 83 XmlPullParser *object = nullptr; 84 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, &data)); 85 NAPI_ASSERT(env, argc == 1 || argc == 2, "Wrong number of arguments"); // 2:two args 86 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, &data)); 87 napi_valuetype valuetype = napi_null; 88 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); 89 NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument typr. Object(DataView or ArrayBuffer) expected."); 90 bool bFlag = false; 91 size_t len = 0; 92 size_t offPos = 0; 93 napi_value arraybuffer = nullptr; 94 NAPI_ASSERT(env, args[0] != nullptr, "Wrong argument value. (not nullptr expected)."); 95 napi_is_arraybuffer(env, args[0], &bFlag); 96 if (bFlag) { 97 napi_get_arraybuffer_info(env, args[0], &data, &len); 98 } 99 napi_is_dataview(env, args[0], &bFlag); 100 if (bFlag) { 101 napi_get_dataview_info(env, args[0], &len, &data, &arraybuffer, &offPos); 102 } 103 if (data) { 104 std::string strEnd(reinterpret_cast<char*>(data), len); 105 strEnd = strEnd.substr(0, std::strlen(strEnd.c_str())); 106 if (argc == 1) { 107 object = new XmlPullParser(strEnd, "utf-8"); 108 } else if (argc == 2) { // 2:When the input parameter is set to 2 109 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype)); 110 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. String expected."); 111 std::string strEncoding = ""; 112 XmlSerializer::DealNapiStrValue(env, args[1], strEncoding); 113 object = new XmlPullParser(strEnd, strEncoding); 114 } 115 } 116 napi_wrap( 117 env, thisVar, object, 118 [](napi_env env, void *data, void *hint) { 119 auto obj = reinterpret_cast<XmlPullParser*>(data); 120 if (obj != nullptr) { 121 delete obj; 122 } 123 }, 124 nullptr, nullptr); 125 return thisVar; 126 } 127 SetAttributes(napi_env env,napi_callback_info info)128 static napi_value SetAttributes(napi_env env, napi_callback_info info) 129 { 130 napi_value thisVar = nullptr; 131 size_t argc = 0; 132 napi_value args[2] = { 0 }; // 2:two args 133 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr)); 134 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); 135 NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); // 2: number of args 136 napi_valuetype valuetype = napi_null; 137 NAPI_ASSERT(env, args[0] != nullptr, "Parameter is empty."); 138 NAPI_ASSERT(env, args[1] != nullptr, "Parameter is empty."); 139 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); 140 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. Object expected."); 141 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype)); 142 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. Object expected."); 143 XmlSerializer *object = nullptr; 144 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 145 std::string name; 146 std::string value; 147 XmlSerializer::DealNapiStrValue(env, args[0], name); 148 XmlSerializer::DealNapiStrValue(env, args[1], value); 149 object->SetAttributes(name, value); 150 napi_value result = nullptr; 151 NAPI_CALL(env, napi_get_undefined(env, &result)); 152 return result; 153 } 154 AddEmptyElement(napi_env env,napi_callback_info info)155 static napi_value AddEmptyElement(napi_env env, napi_callback_info info) 156 { 157 napi_value thisVar = nullptr; 158 size_t argc = 1; 159 napi_value args[1] = { 0 }; 160 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); 161 NAPI_ASSERT(env, argc == 1, "Wrong number of arguments(Over)"); 162 if (args[0] == nullptr) { 163 NAPI_CALL(env, napi_throw_error(env, "", "parameter is empty")); 164 } else { 165 napi_valuetype valuetype; 166 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); 167 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. String expected."); 168 XmlSerializer *object = nullptr; 169 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 170 std::string name; 171 object->DealNapiStrValue(env, args[0], name); 172 object->AddEmptyElement(name); 173 } 174 napi_value result = nullptr; 175 NAPI_CALL(env, napi_get_undefined(env, &result)); 176 return result; 177 } 178 SetDeclaration(napi_env env,napi_callback_info info)179 static napi_value SetDeclaration(napi_env env, napi_callback_info info) 180 { 181 napi_value thisVar = nullptr; 182 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); 183 XmlSerializer *object = nullptr; 184 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 185 object->SetDeclaration(); 186 napi_value result = nullptr; 187 NAPI_CALL(env, napi_get_undefined(env, &result)); 188 return result; 189 } 190 StartElement(napi_env env,napi_callback_info info)191 static napi_value StartElement(napi_env env, napi_callback_info info) 192 { 193 size_t argc = 1; 194 napi_value args[1] = { 0 }; 195 napi_value thisVar = nullptr; 196 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr)); 197 NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); 198 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); 199 NAPI_ASSERT(env, args[0] != nullptr, "Parameter is empty."); 200 XmlSerializer *object = nullptr; 201 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 202 std::string name; 203 object->DealNapiStrValue(env, args[0], name); 204 object->StartElement(name); 205 napi_value result = nullptr; 206 NAPI_CALL(env, napi_get_undefined(env, &result)); 207 return result; 208 } 209 EndElement(napi_env env,napi_callback_info info)210 static napi_value EndElement(napi_env env, napi_callback_info info) 211 { 212 napi_value thisVar = nullptr; 213 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); 214 XmlSerializer *object = nullptr; 215 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 216 object->EndElement(); 217 napi_value result = nullptr; 218 NAPI_CALL(env, napi_get_undefined(env, &result)); 219 return result; 220 } 221 SetNamespace(napi_env env,napi_callback_info info)222 static napi_value SetNamespace(napi_env env, napi_callback_info info) 223 { 224 napi_value thisVar = nullptr; 225 size_t argc = 0; 226 napi_value args[2] = { 0 }; // 2:two args 227 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr)); 228 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); 229 NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); // 2:two args 230 napi_valuetype valuetype = napi_null; 231 NAPI_ASSERT(env, args[0] != nullptr, "Parameter is empty."); 232 NAPI_ASSERT(env, args[1] != nullptr, "Parameter is empty."); 233 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); 234 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. Object expected."); 235 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype)); 236 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. Object expected."); 237 XmlSerializer *object = nullptr; 238 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 239 std::string prefix; 240 std::string nsTemp; 241 XmlSerializer::DealNapiStrValue(env, args[0], prefix); 242 XmlSerializer::DealNapiStrValue(env, args[1], nsTemp); 243 object->SetNamespace(prefix, nsTemp); 244 napi_value result = nullptr; 245 NAPI_CALL(env, napi_get_undefined(env, &result)); 246 return result; 247 } 248 SetComment(napi_env env,napi_callback_info info)249 static napi_value SetComment(napi_env env, napi_callback_info info) 250 { 251 napi_value thisVar = nullptr; 252 size_t argc = 0; 253 napi_value args[1] = { 0 }; 254 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr)); 255 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); 256 NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); 257 napi_valuetype valuetype = napi_null; 258 NAPI_ASSERT(env, args[0] != nullptr, "Parameter is empty)."); 259 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); 260 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. String expected"); 261 XmlSerializer *object = nullptr; 262 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 263 std::string comment; 264 object->DealNapiStrValue(env, args[0], comment); 265 object->SetComment(comment); 266 napi_value result = nullptr; 267 NAPI_CALL(env, napi_get_undefined(env, &result)); 268 return result; 269 } 270 SetCData(napi_env env,napi_callback_info info)271 static napi_value SetCData(napi_env env, napi_callback_info info) 272 { 273 napi_value thisVar = nullptr; 274 size_t argc = 0; 275 napi_value args[1] = { 0 }; 276 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr)); 277 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); 278 NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); 279 napi_valuetype valuetype = napi_null; 280 NAPI_ASSERT(env, args[0] != nullptr, "Parameter is empty)."); 281 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); 282 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. String expected"); 283 XmlSerializer *object = nullptr; 284 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 285 std::string data; 286 XmlSerializer::DealNapiStrValue(env, args[0], data); 287 object->SetCData(data); 288 napi_value result = nullptr; 289 NAPI_CALL(env, napi_get_undefined(env, &result)); 290 return result; 291 } 292 SetText(napi_env env,napi_callback_info info)293 static napi_value SetText(napi_env env, napi_callback_info info) 294 { 295 napi_value thisVar = nullptr; 296 size_t argc = 0; 297 napi_value args[1] = { 0 }; 298 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr)); 299 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); 300 NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); 301 napi_valuetype valuetype = napi_null; 302 NAPI_ASSERT(env, args[0] != nullptr, "Parameter is empty)."); 303 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); 304 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. String expected."); 305 XmlSerializer *object = nullptr; 306 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 307 std::string text; 308 XmlSerializer::DealNapiStrValue(env, args[0], text); 309 object->SetText(text); 310 napi_value result = nullptr; 311 NAPI_CALL(env, napi_get_undefined(env, &result)); 312 return result; 313 } 314 SetDocType(napi_env env,napi_callback_info info)315 static napi_value SetDocType(napi_env env, napi_callback_info info) 316 { 317 napi_value thisVar = nullptr; 318 size_t argc = 0; 319 napi_value args[1] = { 0 }; 320 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr)); 321 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); 322 NAPI_ASSERT(env, argc == 1, "Wrong number of arguments"); 323 napi_valuetype valuetype = napi_null; 324 NAPI_ASSERT(env, args[0] != nullptr, "Parameter is empty)."); 325 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); 326 NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument typr. String expected."); 327 XmlSerializer *object = nullptr; 328 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 329 std::string text; 330 XmlSerializer::DealNapiStrValue(env, args[0], text); 331 object->SetDocType(text); 332 napi_value result = nullptr; 333 NAPI_CALL(env, napi_get_undefined(env, &result)); 334 return result; 335 } XmlSerializerError(napi_env env,napi_callback_info info)336 static napi_value XmlSerializerError(napi_env env, napi_callback_info info) 337 { 338 napi_value thisVar = nullptr; 339 napi_value result = nullptr; 340 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); 341 XmlSerializer *object = nullptr; 342 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 343 std::string temp = object->XmlSerializerError(); 344 size_t templen = temp.size(); 345 NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result)); 346 return result; 347 } 348 XmlSerializerInit(napi_env env,napi_value exports)349 static napi_value XmlSerializerInit(napi_env env, napi_value exports) 350 { 351 const char *xmlSerializerClass = "XmlSerializer"; 352 napi_value xmlClass = nullptr; 353 napi_property_descriptor xmlDesc[] = { 354 DECLARE_NAPI_FUNCTION("setAttributes", SetAttributes), 355 DECLARE_NAPI_FUNCTION("addEmptyElement", AddEmptyElement), 356 DECLARE_NAPI_FUNCTION("setDeclaration", SetDeclaration), 357 DECLARE_NAPI_FUNCTION("startElement", StartElement), 358 DECLARE_NAPI_FUNCTION("endElement", EndElement), 359 DECLARE_NAPI_FUNCTION("setNamespace", SetNamespace), 360 DECLARE_NAPI_FUNCTION("setComment", SetComment), 361 DECLARE_NAPI_FUNCTION("setCDATA", SetCData), 362 DECLARE_NAPI_FUNCTION("setText", SetText), 363 DECLARE_NAPI_FUNCTION("setDocType", SetDocType), 364 DECLARE_NAPI_FUNCTION("XmlSerializerError", XmlSerializerError) 365 }; 366 NAPI_CALL(env, napi_define_class(env, xmlSerializerClass, strlen(xmlSerializerClass), XmlSerializerConstructor, 367 nullptr, sizeof(xmlDesc) / sizeof(xmlDesc[0]), xmlDesc, &xmlClass)); 368 napi_property_descriptor desc[] = { 369 DECLARE_NAPI_PROPERTY("XmlSerializer", xmlClass) 370 }; 371 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 372 return exports; 373 } 374 Parse(napi_env env,napi_callback_info info)375 static napi_value Parse(napi_env env, napi_callback_info info) 376 { 377 napi_value thisVar = nullptr; 378 size_t argc = 0; 379 napi_value args[1] = { 0 }; 380 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr)); 381 NAPI_ASSERT(env, argc == 1, "Wrong number of arguments, one expected."); 382 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); 383 NAPI_ASSERT(env, args[0] != nullptr, "Parameter is empty."); 384 napi_valuetype valuetype; 385 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); 386 NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument typr. Object expected."); 387 XmlPullParser *object = nullptr; 388 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 389 object->DealOptionInfo(env, args[0]); 390 object->Parse(env, thisVar); 391 napi_value result = nullptr; 392 NAPI_CALL(env, napi_get_undefined(env, &result)); 393 return result; 394 } 395 XmlPullParserError(napi_env env,napi_callback_info info)396 static napi_value XmlPullParserError(napi_env env, napi_callback_info info) 397 { 398 napi_value thisVar = nullptr; 399 napi_value result = nullptr; 400 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); 401 XmlPullParser *object = nullptr; 402 NAPI_CALL(env, napi_unwrap(env, thisVar, reinterpret_cast<void**>(&object))); 403 std::string temp = object->XmlPullParserError(); 404 size_t templen = temp.size(); 405 NAPI_CALL(env, napi_create_string_utf8(env, temp.c_str(), templen, &result)); 406 return result; 407 } 408 XmlPullParserInit(napi_env env,napi_value exports)409 static napi_value XmlPullParserInit(napi_env env, napi_value exports) 410 { 411 const char *xmlPullParserClass = "XmlPullParser"; 412 napi_value xmlClass = nullptr; 413 napi_property_descriptor xmlDesc[] = { 414 DECLARE_NAPI_FUNCTION("parse", Parse), 415 DECLARE_NAPI_FUNCTION("XmlPullParserError", XmlPullParserError) 416 }; 417 NAPI_CALL(env, napi_define_class(env, xmlPullParserClass, strlen(xmlPullParserClass), 418 XmlPullParserConstructor, nullptr, sizeof(xmlDesc) / sizeof(xmlDesc[0]), 419 xmlDesc, &xmlClass)); 420 napi_property_descriptor desc[] = { 421 DECLARE_NAPI_PROPERTY("XmlPullParser", xmlClass) 422 }; 423 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 424 return exports; 425 }; 426 Init(napi_env env,napi_value exports)427 static napi_value Init(napi_env env, napi_value exports) 428 { 429 XmlSerializerInit(env, exports); 430 XmlPullParserInit(env, exports); 431 return exports; 432 } 433 434 extern "C" NAPI_xml_GetJSCode(const char ** buf,int * bufLen)435 __attribute__((visibility("default"))) void NAPI_xml_GetJSCode(const char **buf, int *bufLen) 436 { 437 if (buf != nullptr) { 438 *buf = _binary_js_xml_js_start; 439 } 440 441 if (bufLen != nullptr) { 442 *bufLen = _binary_js_xml_js_end - _binary_js_xml_js_start; 443 } 444 } 445 extern "C" NAPI_xml_GetABCCode(const char ** buf,int * buflen)446 __attribute__((visibility("default"))) void NAPI_xml_GetABCCode(const char** buf, int* buflen) 447 { 448 if (buf != nullptr) { 449 *buf = _binary_xml_abc_start; 450 } 451 if (buflen != nullptr) { 452 *buflen = _binary_xml_abc_end - _binary_xml_abc_start; 453 } 454 } 455 456 457 static napi_module xmlModule = { 458 .nm_version = 1, 459 .nm_flags = 0, 460 .nm_filename = nullptr, 461 .nm_register_func = Init, 462 .nm_modname = "xml", 463 .nm_priv = reinterpret_cast<void*>(0), 464 .reserved = {0}, 465 }; RegisterModule()466 extern "C" __attribute__((constructor)) void RegisterModule() 467 { 468 napi_module_register(&xmlModule); 469 } 470 } // namespace OHOS::Xml 471