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 (Object.prototype.hasOwnProperty.call(converted, '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;
68    if (arguments.length === 1) {
69      converted = this.convertxmlclass.convert(strXml);
70    } else {
71      converted = this.convertxmlclass.convert(strXml, options);
72    }
73    if (Object.prototype.hasOwnProperty.call(converted, 'spaces')) {
74      let space: string | number | undefined = converted.spaces;
75      delete converted.spaces;
76    }
77    return converted;
78  }
79}
80
81function dealXml(strXml: string): string {
82  strXml = strXml.replace(/(<!\[CDATA\[[\s\S]*?\]\]>)|(>\s+<)/g, function(match, group) {
83    if (group) {
84      return group;
85    } else {
86      return '><';
87    }
88  }).trim();
89  if ((strXml.indexOf('[CDATA')) !== -1) {
90    return dealXmlInner(strXml);
91  }
92  return strXml;
93}
94
95function dealXmlInner(strXml: string): string {
96  strXml = strXml.replace(/\]\]><!\[CDATA/g, ']]> <![CDATA');
97  return strXml.replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, function (match) {
98    return match.replace(/\\/g, '\\\\').replace(/[\r\n\t\v]/g, function (suit) {
99      switch (suit) {
100        case '\n': return '\\n';
101        case '\r': return '\\r';
102        case '\t': return '\\t';
103        case '\v': return '\\v';
104        default: return suit;
105      }
106    });
107  });
108}
109
110export default {
111  ConvertXML: ConvertXML
112};
113