1import _ from 'lodash'
2
3export default class JSON2XML {
4    constructor(indent = '  ', newline = '\n') {
5        this.xml = ''
6        this.indent = indent
7        this.newline = newline
8    }
9
10    convert = (jsObject) => {
11        return this.handleConvert(jsObject)
12    }
13
14    handleConvert(jsObject) {
15        if (!(_.isObject(jsObject) || _.isArray(jsObject))) {
16            throw new Error('Not js object')
17        }
18        this.xml = '<?xml version="1.0" encoding="utf-8"?>'
19        for (const jsObjectKey in jsObject) {
20            this.#convertObject(0, jsObjectKey, jsObject[jsObjectKey])
21        }
22        return this.xml
23    }
24
25    #getAttrText(jso) {
26        let attrs = {}
27        Object.keys(jso).map((childKey) => {
28                if (_.startsWith(childKey, '@')) {
29                    attrs[childKey.substr(1)] = jso[childKey]
30                    delete jso[childKey]
31                }
32            }
33        )
34        let attrText = ''
35        for (const attrsKey in attrs) {
36            attrText += ` ${attrsKey}="${attrs[attrsKey]}"`
37        }
38        return attrText
39    }
40
41    addNewlineAndIndent(deepth) {
42        this.xml += this.newline + _.repeat(this.indent, deepth)
43    }
44
45    #convertObject(deepth, selfName, jsObjectElement) {
46        // this.#convertObject('acrn-config',jso['acrn-config'])
47        // let example = {
48        //     'acrn-config': {
49        //         '@board': 'whl-ipc-i7',
50        //         hv: {},
51        //         vm: [
52        //             {'@id': 1},
53        //             {'@id': 2},
54        //             {'@id': 3}
55        //         ]
56        //     }
57        // }
58
59        if (_.isString(jsObjectElement) || _.isNumber(jsObjectElement)) {
60            // this.#convertObject('boot_args', 'default')
61            this.addNewlineAndIndent(deepth)
62            let val = _.escape(`${jsObjectElement}`)
63            this.xml += `<${selfName}>${val}</${selfName}>`
64        } else if (_.isArray(jsObjectElement)) {
65            // this.#convertObject('cpuid', [1,2,3])
66            // this.#convertObject('vm', [{},{},{}])
67            for (const index in jsObjectElement) {
68                this.#convertObject(deepth, selfName, jsObjectElement[index])
69            }
70        } else if (_.isObject(jsObjectElement)) {
71            // this.#convertObject('acrn-config',jso['acrn-config'])
72            let attrText = this.#getAttrText(jsObjectElement)
73            this.addNewlineAndIndent(deepth)
74            this.xml += `<${selfName}${attrText}>`
75            for (const key in jsObjectElement) {
76                this.#convertObject(deepth + 1, key, jsObjectElement[key])
77            }
78            this.addNewlineAndIndent(deepth)
79            this.xml += `</${selfName}>`
80        } else if (jsObjectElement == null) {
81            //pass
82        } else {
83            console.log(jsObjectElement)
84            debugger;
85            throw new Error("Unknown Object")
86        }
87    }
88}