I have a simple Web response.body from my NodeJS request which is looking like this, and I need to put the ProjectNr and Description in an Array - I tried some parsers but none of them works for me (DomParser etc.) I just don't know what to do, since when I use the .getElementbyName or .getElementbyTagname and search for "ProjectNr" I just get "undefined" as an answer. Please help me. Thanks a lot!
<XYZNetWebService xmlns="http://abcdefs">
<XYZNetResponse Guid="asfdsafdsa23c6"
LastAccess="2022-02-24" Report="Projects" Parameter="" status="200">
<Project>
<ProjectNr>505</ProjectNr>
<Description>Testproject</Description>
</Project>
<Project>
<ProjectNr>123</ProjectNr>
<Description>Project2</Description>
</Project>
The code posted in your question is not well-formed xml which is why DOMParser wasn't working. But if your actual code is something like the below, the following should work:
let xmldoc = `<?xml version="1.0" encoding="UTF-8"?>
<root>
<XYZNetWebService xmlns="http://abcdefs"/>
<XYZNetResponse Guid="asfdsafdsa23c6" LastAccess="2022-02-24" Report="Projects" Parameter="" status="200"/>
<Project>
<ProjectNr>505</ProjectNr>
<Description>Testproject</Description>
</Project>
<Project>
<ProjectNr>123</ProjectNr>
<Description>Project2</Description>
</Project>
</root>`;
const data = new DOMParser().parseFromString(xmldoc, 'text/xml');
let x = data.evaluate("//Project", data, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i = 0; i < x.snapshotLength; i++) {
let tags = data.evaluate('.//*', x.snapshotItem(i), null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i = 0; i < tags.snapshotLength; i++) {
console.log(tags.snapshotItem(i).textContent);
}
}
Output would be
"505"
"Testproject"
"123"
"Project2"
The XML seems to use a default namespace (xmlns="http://abcdefs"). This means that the node Project has to be read as {http://abcdefs}Project.
Here is set of namespace aware methods (with the suffix NS) that take the expected namespace as an argument.
Xpath expression need a resolver - and they don't have a default namespace. The prefixes you're using in the Xpath expression are separate from the XML source. Which makes sense because the XML is an external source and could change.
I am using nws in the following example. So //nws:Project can be read as //{http://abcdefs}Project
const output = document.querySelector('#demo');
const resolver = function(prefix) {
const namespaces = {
nws: 'http://abcdefs'
}
return namespaces[prefix || ''] || null;
}
const data = new DOMParser().parseFromString(getXMLString(), 'text/xml');
const projects = data.evaluate(
"//nws:Project", data, resolver, XPathResult.ANY_TYPE, null
);
let project;
while (project = projects.iterateNext()) {
const projectNr = data.evaluate(
'string(nws:ProjectNr)', project, resolver, XPathResult.STRING_RESULT, null
).stringValue;
const description = data.evaluate(
'string(nws:Description)', project, resolver, XPathResult.STRING_RESULT, null
).stringValue;
output
.appendChild(document.createElement('li'))
.textContent = `${projectNr}: ${description}`;
}
function getXMLString() {
return `<?xml version="1.0" encoding="UTF-8"?>
<XYZNetWebService xmlns="http://abcdefs">
<XYZNetResponse Guid="asfdsafdsa23c6" LastAccess="2022-02-24" Report="Projects" Parameter="" status="200">
<Project>
<ProjectNr>505</ProjectNr>
<Description>Testproject</Description>
</Project>
<Project>
<ProjectNr>123</ProjectNr>
<Description>Project2</Description>
</Project>
</XYZNetResponse>
</XYZNetWebService>`
};
<ul id="demo">
</ul>
you can transform with camaro like this
const { transform } = require('camaro')
async function main() {
const xml = `
<XYZNetWebService xmlns="http://abcdefs">
<XYZNetResponse Guid="asfdsafdsa23c6"
LastAccess="2022-02-24" Report="Projects" Parameter="" status="200">
<Project>
<ProjectNr>505</ProjectNr>
<Description>Testproject</Description>
</Project>
<Project>
<ProjectNr>123</ProjectNr>
<Description>Project2</Description>
</Project>
</XYZNetResponse>
</XYZNetWebService>
`
const template = {
projectNr: ['//Project', 'ProjectNr'],
projectDesc: ['//Project', 'Description']
}
const output = await transform(xml, template)
console.log(output);
}
main()
output
{
projectNr: [ '505', '123' ],
projectDesc: [ 'Testproject', 'Project2' ]
}