import { StringAnyMap } from "./dictionary" ; import { Stack } from "./stack" ; export class XMLNode { name : string = "" ; $ : StringAnyMap = { } ; protected _children : XMLNode [ ] = [ ] ; content : string = "" ; constructor ( name ) { this . name = name ; } appendAttribute ( key , val ) { this . $ [ key ] = val ; } appendContent ( content ) { this . content += content ; } appendChild ( child ) { this . _children . push ( child ) ; } children ( tag ? ) { if ( tag === undefined ) { return this . _children ; } return this . _children . filter ( ( xmlNode ) => { return xmlNode . name === tag ; } ) ; } } export class SAXStackParser { root : XMLNode ; stack : Stack < XMLNode > = new Stack < XMLNode > ( ) ; constructor ( ) { } private walkDoc ( node ) { const xmlNode = this . _startXMLNode ( node ) ; if ( node . attributes ) { for ( let i = 0 ; i < node . attributes . length ; ++ i ) { const attribute = node . attributes . item ( i ) ; this . attributes ( attribute . nodeName , attribute . nodeValue ) ; } } this . startXMLNode ( xmlNode ) ; if ( node . childNodes ) { for ( let i = 0 ; i < node . childNodes . length ; ++ i ) { const childNode = node . childNodes . item ( i ) ; if ( childNode . nodeType === childNode . TEXT_NODE ) { this . characters ( childNode . nodeValue ! ) ; } else { this . walkDoc ( childNode ) ; } } } this . endXMLNode ( this . stack . pop ( ) ! ) ; } private _startXMLNode ( node ) { const newNode = new XMLNode ( node . nodeName ) ; if ( ! this . stack . depth ( ) ) { this . root = newNode ; } else { this . stack . top ( ) ! . appendChild ( newNode ) ; } return this . stack . push ( newNode ) ; } parse ( xml ) { const domParser = new DOMParser ( ) ; const doc = domParser . parseFromString ( xml , "application/xml" ) ; this . startDocument ( ) ; this . walkDoc ( doc ) ; this . endDocument ( ) ; } startDocument ( ) { } endDocument ( ) { } startXMLNode ( node ) { } endXMLNode ( node ) { } attributes ( key , val ) { this . stack . top ( ) ! . appendAttribute ( key , val ) ; } characters ( text ) { this . stack . top ( ) ! . appendContent ( text ) ; } } class XML2JSONParser extends SAXStackParser { startXMLNode ( node ) { super . startXMLNode ( node ) ; switch ( node . name ) { case "xs:element" : break ; case "xs:simpleType" : break ; default : break ; } } endXMLNode ( node ) { switch ( node . name ) { case "xs:element" : break ; case "xs:simpleType" : break ; default : break ; } super . endXMLNode ( node ) ; } } export function xml2json ( xml ) { const saxParser = new XML2JSONParser ( ) ; saxParser . parse ( xml ) ; return saxParser . root ; }