|
@@ -21,21 +21,37 @@ export class XMLElem {
|
|
|
|
|
|
public toString(level: number=0): string {
|
|
|
let s=" ".repeat(level+1) + `<${this.name} `;
|
|
|
- for(const attr of this.attributes)
|
|
|
- s+=`${attr.name}="${attr.value}" `;
|
|
|
+ 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.value;
|
|
|
+ s+=this.escapeXml(this.value);
|
|
|
}
|
|
|
if(this.elements.length>0)
|
|
|
s+=" ".repeat(level);
|
|
|
s+=`</${this.name}>\n`
|
|
|
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 {
|