Skip to content

Instantly share code, notes, and snippets.

@jmakeig
Last active December 13, 2018 21:11
Show Gist options
  • Save jmakeig/2f45caf00f41c65f65c0778e5eec8952 to your computer and use it in GitHub Desktop.
Save jmakeig/2f45caf00f41c65f65c0778e5eec8952 to your computer and use it in GitHub Desktop.
Defensive MarkLogic XPath generator function
function* xpath(doc, path = '.', bindings = {}) {
// Only if you want path to be relative to the root element.
// Probably not what you want.
// if (doc instanceof Document) {
// yield* xpath(doc.root, path, bindings);
// } else
if (doc instanceof Node) {
yield* doc.xpath(path, bindings);
}
// Becuase this is a Generator, it’s probably better just to
// return an empty iterator than error out on non-Nodes
// else throw new TypeError(doc);
}
// https://gist.github.com/jmakeig/9a6aad1ebbe393128d5a643914619a32
function xml(strings, ...values) {
let str = '';
for (let i = 0; i < strings.length; i++) {
str += strings[i] + (values[i] || '');
}
return fn.head(xdmp.unquote(str, null, 'format-xml'));
}
const x = xml`<A:a xmlns:A="a"><b><c><d>1</d><d>2</d></c></b></A:a>`;
const j = xdmp.toJSON({a: {b: {c: [{d: 1}, {d: 2}]}}});
console.assert(2 === Array.from(xpath(x, '/NS:a/b/c/d', {'NS': 'a'})).length);
console.assert(2 === Array.from(xpath(x, 'A:a/b/c/d', {'A': 'a'})).length);
console.assert(2 === Array.from(xpath(j, '/a/b/c/d')).length);
console.assert(2 === Array.from(xpath(j, 'a/b/c/d')).length);
console.assert(0 === Array.from(xpath({}, 'a/b/c/d')).length);
console.assert(1 === Array.from(xpath(x)).length);
@jmakeig
Copy link
Author

jmakeig commented Dec 13, 2018

Basically,

function* xpath(doc, path = '.', bindings = {}) {
  if (doc instanceof Node) {
    yield* doc.xpath(path, bindings);
  } 
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment