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 16interface ReceiveObject { 17 obj: Object; 18 spaces?: string | number; 19} 20 21interface NativeConvertXml { 22 new(): NativeConvertXml; 23 convert(strXml: string, options?: Object): ReceiveObject; 24 convertToJSObject(strXml: string, options?: Object): ReceiveObject; 25} 26interface ConvertXML { 27 ConvertXml: NativeConvertXml; 28} 29declare function requireInternal(s: string): ConvertXML; 30const convertXml = requireInternal('convertxml'); 31 32const LESS_SIGN_INDEX = 3; 33const TypeErrorCode = 401; 34class BusinessError extends Error { 35 code: number; 36 constructor(msg: string) { 37 super(msg) 38 this.name = 'BusinessError'; 39 this.code = TypeErrorCode; 40 } 41} 42 43class ConvertXML { 44 convertxmlclass: NativeConvertXml; 45 constructor() { 46 this.convertxmlclass = new convertXml.ConvertXml(); 47 } 48 convert(strXml: string, options?: Object): ReceiveObject { 49 strXml = dealXml(strXml); 50 let converted: ReceiveObject = this.convertxmlclass.convert(strXml, options); 51 let strEnd: string = ''; 52 if (converted.hasOwnProperty('spaces')) { 53 let space: string | number | undefined = converted.spaces; 54 delete converted.spaces; 55 } 56 return converted; 57 } 58 59 convertToJSObject(strXml: string, options?: Object): ReceiveObject { 60 if (typeof strXml !== 'string') { 61 throw new BusinessError(`Parameter error.The type of ${strXml} must be string`); 62 } 63 if (options && !(typeof options === 'undefined' || options === null) && typeof options !== 'object') { 64 throw new BusinessError(`Parameter error.The type of ${options} must be object`); 65 } 66 strXml = dealXml(strXml); 67 let converted: ReceiveObject = this.convertxmlclass.convert(strXml, options); 68 let strEnd: string = ''; 69 if (converted.hasOwnProperty('spaces')) { 70 let space: string | number | undefined = converted.spaces; 71 delete converted.spaces; 72 } 73 return converted; 74 } 75} 76 77function dealXml(strXml: string): string { 78 let idx: number = 0; 79 let idxSec: number = 0; 80 let idxThir: number = 0; 81 let idxCData: number = 0; 82 let idxCDataSec: number = 0; 83 while ((idx = strXml.indexOf(']]><![CDATA')) !== -1) { 84 strXml = strXml.substring(0, idx + LESS_SIGN_INDEX) + ' ' + strXml.substring(idx + LESS_SIGN_INDEX); 85 } 86 while ((idx = strXml.indexOf('>', idxSec)) !== -1) { 87 idxThir = strXml.indexOf('<', idx); 88 strXml = dealPriorReplace(strXml, idx, idxThir); 89 idxSec = strXml.indexOf('<', idx); 90 if (idxSec !== -1) { 91 idxCData = strXml.indexOf('<![CDATA', idxCDataSec); 92 if (idxSec === idxCData) { 93 idxSec = strXml.indexOf(']]>', idxCData); 94 strXml = dealLaterReplace(strXml, idxCData, idxSec); 95 idxCDataSec = idxSec; 96 } 97 } else { 98 break; 99 } 100 } 101 return strXml; 102} 103 104function dealPriorReplace(strXml: string, idx: number, idxThir: number): string { 105 let i: number = idx + 1; 106 for (; i < idxThir; i++) { 107 let cXml: string = strXml.charAt(i); 108 if (cXml !== '\n' && cXml !== '\v' && cXml !== '\t' && cXml !== ' ') { 109 break; 110 } 111 } 112 let j: number = idx + 1; 113 if (i === idxThir) { 114 strXml = strXml.substring(0, j) + strXml.substring(idxThir); 115 } 116 if (j < strXml.indexOf('<', idx)) { 117 let temp: string = strXml.substring(j, strXml.indexOf('<', idx)); 118 if (temp.indexOf('\n') !== -1 || temp.indexOf('\v') !== -1 || temp.indexOf('\t') !== -1) { 119 let pattern: RegExp = /[\n\v\t]/g; 120 let result: string = temp.replace(pattern, function (match) { 121 switch (match) { 122 case '\n': 123 return '\\n'; 124 case '\v': 125 return '\\v'; 126 case '\t': 127 return '\\t'; 128 default: 129 return match; 130 } 131 }); 132 strXml = strXml.replace(temp, result); 133 } 134 } 135 return strXml; 136} 137 138function dealLaterReplace(strXml: string, idx: number, idxThir: number): string { 139 let i: number = idx + 1; 140 let res = strXml.substring(i, idxThir); 141 if (res.indexOf('\n') !== -1 || res.indexOf('\v') !== -1 || res.indexOf('\t') !== -1 || res.indexOf('\r') !== -1) { 142 let pattern: RegExp = /[\n\v\t\r]/g; 143 let result: string = res.replace(pattern, function (match) { 144 switch (match) { 145 case '\n': 146 return '\\n'; 147 case '\v': 148 return '\\v'; 149 case '\t': 150 return '\\t'; 151 case '\r': 152 return '\\r'; 153 default: 154 return match; 155 } 156 }); 157 strXml = strXml.replace(res, result); 158 } 159 return strXml; 160} 161 162export default { 163 ConvertXML: ConvertXML 164}; 165