I have a xml file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE agent SYSTEM "http://www.someUrl.com">
<myData>
<service>
<description>Description</description>
</service>
<courier>
<listener port="55556"
/>
<mainService
name="Some Name"
port="55555"
/>
</courier>
</myData>
and I want to get the value of the listener port variable using nodejs.
According to the docu for SaxonJs SaxonJS.XPath.evaluate is the method I need. It requires a query and a document node object. When I convert my xml file into dom object I get the error message : "Uncaught TypeError TypeError: Cannot read properties of undefined (reading ‘length’)"
const saxonJs = require('saxon-js');
const fs = require('node:fs');
const jsdom = require("jsdom");
var xmlFile = fs.readFileSync(xmlFilePath, 'utf8');
var doc = new jsdom.JSDOM(xml);
var xpathQuery = '//listener/@port';
var result = saxonJs.XPath.evaluate(xpathQuery, doc);
2
Answers
Do you need to use XPath in particular? Since you have JSDOM, I’d just query using a CSS selector:
You can use
JSDOM.fromFile
to read from disk without usingfs
(although that’s fine too).If you don’t mind querying with CSS, Cheerio provides an even cleaner option:
If you really want to use XPath, you can do it in JSDOM (note the
[@port]
change to select by attribute on thelistener
element):or selecting the attribute string value directly:
Note that using both JSDOM and Saxon is probably unnecessary, since Saxon can parse the XML without support from JSDOM. Pick one or the other.
I’m not familiar with Saxon, but at the time of writing, JSDOM has 22,000,000 weekly downloads, while saxon-js has 20,000. My instinct is to avoid the dependency on saxon-js if possible. On the other hand, apparently JSDOM XPath has "quite a few issues", so you may have a good reason for pursuing Saxon if it’s a better tool for your particular use case (i.e. you need robust XML support and don’t mind the support/maintenance cost of using a less popular library).
To give you an example for SaxonJS with Node.js:
Of course you can also try to select the
@port
attribute node and output its value with e.g.Or in the ESM module world as