import type { NamespaceTable } from "@/ua/NameSpaceTable"; export class XMLElem { name: string; value: string; elements: XMLElem[]=[]; attributes: XmlAttr[]=[]; constructor(name: string, value?:string) { this.name=name; this.value=value||''; } public add(elem: XMLElem): XMLElem { this.elements.push(elem); return elem; } public attr(name:string, value: string|boolean|undefined|null): XMLElem { if(value===undefined||value===null) return this; //skip undefined/null values this.attributes.push(new XmlAttr(name, value?.toString())); return this; } public elem(name:string, value: XMLElem|string|boolean|undefined|null): XMLElem { if(value===undefined||value===null) return this; //skip undefined/null values if(value instanceof XMLElem) this.elements.push(value); this.elements.push(new XMLElem(name, value?.toString())); return this; } public toString(level: number=0): string { let s=""; if(level==0) { s+='\n' } s+=" ".repeat(level+1) + `<${this.name} `; for(const attr of this.attributes) { if(attr.value==undefined) continue; s+=`${attr.name}="${this.escapeXml(attr.value)}" `; } s=s.slice(0, -1); s+=`>` for(const elem of this.elements) { s+="\n"+" ".repeat(level) + elem.toString(level+1); } if(this.value && this.elements.length==0) { s+=this.escapeXml(this.value); } if(this.elements.length>0) s+="\n" + " ".repeat(level); s+=`` return s; } private escapeXml(unsafe: string) { return unsafe.replace(/[<>&'"]/g, (c: string):string => { switch (c) { case '<': return '<'; case '>': return '>'; case '&': return '&'; case '\'': return '''; case '"': return '"'; } return c; }); } } class XmlAttr { constructor(public name: string, public value: string) { } } export interface IToXML { toXML(lnst: NamespaceTable, gnst: NamespaceTable) :XMLElem; }