在 NodeJS 中解析响应 XML 数据

Parse response XML data in NodeJS

我有一个来自我的 NodeJS 请求的简单 Web response.body,它看起来像这样,我需要将 ProjectNr 和 Description 放在一个数组中 - 我尝试了一些解析器,但 none为我工作(DomParser 等)我只是不知道该怎么做,因为当我使用 .getElementbyName 或 .getElementbyTagname 并搜索“ProjectNr”时,我只是得到“undefined”作为答案。 请帮我。非常感谢!

<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>

您问题中发布的代码不是 well-formed xml,这就是 DOMParser 无法正常工作的原因。但是,如果您的实际代码类似于以下内容,则以下内容应该有效:

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);
  }
}

输出将是

"505"
"Testproject"
"123"
"Project2"

XML 似乎使用了默认名称空间 (xmlns="http://abcdefs")。这意味着节点 Project 必须被读取为 {http://abcdefs}Project.

这是一组命名空间感知方法(带有后缀 NS),它们将预期的命名空间作为参数。

Xpath 表达式需要解析器 - 而且它们没有默认命名空间。您在 Xpath 表达式中使用的前缀与 XML 源分开。这是有道理的,因为 XML 是外部来源并且可能会改变。

我在以下示例中使用 nws。所以 //nws:Project 可以读作 //{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>

你可以像这样用camaro变身

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()

输出

{
  projectNr: [ '505', '123' ],
  projectDesc: [ 'Testproject', 'Project2' ]
}