Skip to content

Instantly share code, notes, and snippets.

@bag-man
Last active July 11, 2019 11:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bag-man/6b21122c1466a7fab639002a8f24e5d7 to your computer and use it in GitHub Desktop.
Save bag-man/6b21122c1466a7fab639002a8f24e5d7 to your computer and use it in GitHub Desktop.
A class wrapper around libxmljs, for reading values with XML namespaces
import { Document, Element, parseXml } from 'libxmljs';
import { VError } from 'verror';
export class XMLReader {
private document: Document;
private namespaces: Record<string, string>;
constructor(inputXml: string) {
try {
this.document = parseXml(inputXml);
this.namespaces = {};
// Bad typings? No .namespaces()
for (const ns of (this.document as any).namespaces()) {
let name = ns.prefix();
if (name === null) {
name = '_';
}
this.namespaces[name] = ns.href();
}
} catch (cause) {
throw new VError(
{ cause, name: 'ParseError', info: { inputXml } },
'Failed to parse XML',
);
}
}
public get(xpath: string): string {
const element: Element | null = this.document.get(xpath, this.namespaces);
if (element === null || element === undefined) {
throw new Error(`XPath element "${xpath}" was not found`);
}
return element.text();
}
}
const input: string = `<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="default:namespace" xmlns:opt="inner:namespace">
<outer><opt:inner>value</opt:inner></outer>
</root>
`;
const xml = new XMLReader(input);
// Need to specify the default namespace with _.
console.log(xml.get('/_:root/_:outer/opt:inner'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment