import { xml2js , xml2json , js2xml , Attributes , DeclarationAttributes , json2xml } from "xml-js" ; const keys = { elementsKey : "$children" , attributesKey : "$attrs" } ; interface Element { declaration ? : { attributes ? : DeclarationAttributes ; } ; instruction ? : string ; $attrs ? : Attributes ; cdata ? : string ; doctype ? : string ; comment ? : string ; text ? : string | number | boolean ; type ? : string ; name ? : string ; $children ? : Array < Element > ; } function convertFromXMLinner ( e ) { if ( ! e ) return undefined ; if ( e . type === "element" ) { let $children = e . $children ?. map ( convertFromXMLinner ) || [ ] ; return { $element : e . name as string , ... e . $attrs , $children } ; } else if ( e . type === "text" ) { return e . text ; } else if ( e . type === "cdata" ) { return e . cdata ; } return undefined ; } function convertToXMLinner ( e ) { if ( typeof e === "object" && e . $element ) { return { type : "element" , name : e . $element , $attrs : { ... e , $element : undefined , $children : undefined } , $children : e . $children ?. map ( f => convertToXMLinner ( f ) ) || [ ] } ; } else if ( typeof e === "object" ) { return undefined ; } else { return { type : "text" , text : e . toString ( ) } ; } } export type xmlTree = { $element : string ; $children : ( xmlTree | string ) [ ] ; } & { [ k ] : unknown ; } ; export function toXML ( input , declaration = true ) { let inter = JSON . stringify ( { $children : [ convertToXMLinner ( input ) ] } ) ; return json2xml ( inter , { compact : false , ... keys , } ) ; } export function fromXML ( docStr , root ) { let doc = xml2js ( docStr , { compact : false , alwaysArray : true , alwaysChildren : true , nativeType : true , ... keys } ) as Element ; if ( doc . $children ) { let index = doc . $children . findIndex ( e => e . name && root . indexOf ( e . name ) !== - 1 ) ; if ( index === - 1 ) return false ; else return convertFromXMLinner ( doc . $children [ index ] ) ; } else { return false ; } } type ret = { $element : string ; $children : ( ret | string ) [ ] ; } ; param obj param key returns export function expandNodeTree ( obj ) ; export function expandNodeTree ( obj , key ) ; export function expandNodeTree ( obj , key ? ) { if ( ! obj ) return [ ] ; if ( Array . isArray ( obj ) ) { if ( ! key ) throw new Error ( "key is required in expandNodeTree array branch" ) ; return obj . map ( e => ( { $element : key , $children : expandNodeTree ( e ) } ) ) ; } else if ( typeof obj === "object" ) { let $children = Object . keys ( obj ) . reduce ( ( n , e ) => [ ... n , ... expandNodeTree ( obj [ e ] , e ) ] , [ ] as ret [ ] ) ; return key ? [ { $element : key , $children } as ret ] : $children ; } else { let $children = [ obj . toString ( ) ] ; return key ? [ { $element : key , $children } ] : $children ; } }