What is the right way to use xpath on nodejs + xpath-Module if you search in subnodes?

430 Views Asked by At

I use XMLDOM + XPath to find XMLs nodes in this script:

var DOMParser = require("xmldom").DOMParser;
var xpath = require("xpath");

let data = `<start>
    <b1 id="111"><c1 id="333">ccc</c1></b1>
<b1 id="222">bbb</b1>
</start>`;

let doc = new DOMParser().parseFromString(data);
let nodes = xpath.select("//b1", doc);

// let doc2 = new DOMParser().parseFromString(nodes[0].toString());
let doc2 = nodes[0];
console.log("doc2.toString: ", doc2.toString());

let nodes2 = xpath.select("b1", doc2);

console.log("nodes found by xpath 'b1': ", nodes2.toString());

if (nodes2.length > 0) {
  console.log("id = " + nodes2[0].getAttribute("id"));
}

nodes2 = xpath.select("b1/c1", doc2);

console.log("nodes found by xpath 'b1/c1': ", nodes2.toString());

if (nodes2.length > 0) {
  console.log("id = " + nodes2[0].getAttribute("id"));
}

nodes2 = xpath.select("c1", doc2);

console.log("nodes found by xpath 'c1': ", nodes2.toString());

if (nodes2.length > 0) {
  console.log("id = " + nodes2[0].getAttribute("id"));
}

I want make a list of <b1> nodes and then get the id-value of the node.

The XPath pattern b1/c1 don't work but the c1 does.

If I change from search in a subnode

let doc2 = nodes[0];

to search in complete XML Document

let doc2 = new DOMParser().parseFromString(nodes[0].toString());

the b1/c1 pattern work!

Why b1/c1 don't work in case one?

Try:

echo "<b1 id=\"111\"><c1 id=\"333\">ccc</c1></b1>" | xmllint  --xpath b1/c1 -

find:

<c1 id="333">ccc</c1>

On a plain XML the xpath pattern work fine, why not on subnodes from XMLDOM?

Or try in:

https://www.freeformatter.com/xpath-tester.html#ad-output

1

There are 1 best solutions below

2
On

I want make a list of nodes and then get the id-value of the node.

So, that is to say, you want to make a list of the id attribute values?

var DOMParser = require("xmldom").DOMParser;
var xpath = require("xpath");

let data = `<start>
    <b1 id="111"><c1 id="333">ccc</c1></b1>
    <b1 id="222">bbb</b1>
</start>`

let doc = new DOMParser().parseFromString(data);

let ids = xpath.select("//b1/@id", doc).map(attr => attr.value);
// -> ["333", "222"]

An alternative to the last line is this:

let ids = xpath.select("//b1", doc).map(node => node.getAttribute('id'));
// -> ["333", "222"]