You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Node.js遍历XML节点并输出指定标签下全部子节点内容

问题

我希望通过Node.js结合用户输入遍历XML节点,例如输入“unit”时,输出该标签下的所有内容。XML结构如下:

<course>
     <name>...</name>
     <duration>...</duration>
     <unit>
          <title>...</title>
          <lecturer>
              <surname language="English">...</surname>
              <othernames language="English">...</othernames>
              <email>...</email>
          </lecturer>
     </unit>
</course>

目前我能获取unit标签下的title内容,但无法输出lecturer、surname、othernames和email标签的内容。请问该如何修改代码以实现需求?当前使用的代码如下:

const xmldom = require('xmldom').DOMParser;
const fs = require('fs');
const readLineSync = require('readline-sync');

let parser, doc, targetNodes;
let i, count = 0, userInput;
let targetObj, fcObj, parentObj;

// use fs to read xml document
fs.readFile('course.xml', 'utf-8', function (err, data) {
    if (err) {
        throw err;
    }
    // construct parser
    parser = new xmldom();
    // call method to parse document - not the type
    doc = parser.parseFromString(data, 'application/xml');

    userInput = readLineSync.question("Enter tag to be printed: ");

    // use DOM Node method
    targetNodes = doc.getElementsByTagName(userInput.toLowerCase());
    console.log("Tag " + userInput + " entered");
    
    for (i in targetNodes) {
        // process current ith node
        targetObj = targetNodes[i];
    
        // if it is the firstchild
        if (targetObj.firstChild) {
            // obtain the node value
            fcObj = targetObj.childNodes;
            parentObj = targetObj.parentNode;
            
            if (parentObj == null && count == 0){
                console.log("No identical tag found.");
            } else {
                count = 1;
                if (parentObj != null) {
                    if (fcObj[count].childNodes) {
                        console.log(fcObj[count].childNodes[0].nodeValue);
                    } else {
                        console.log(fcObj[count].nodeValue);
                    }
                }
            }
        }
    }
});
解决方案

原代码仅处理了目标节点的单个子节点,未递归遍历嵌套子元素,同时未过滤XML解析产生的空白文本节点。以下是修改后的代码,可实现遍历目标标签下所有内容的功能:

const xmldom = require('xmldom').DOMParser;
const fs = require('fs');
const readLineSync = require('readline-sync');

// 递归遍历节点并输出内容的函数
function traverseNode(node, indent = 0) {
    // 过滤空白文本节点和注释节点
    if (node.nodeType === Node.TEXT_NODE && node.nodeValue.trim() === '') {
        return;
    }

    const indentStr = '  '.repeat(indent);
    if (node.nodeType === Node.ELEMENT_NODE) {
        // 输出标签名及属性
        let tagStr = `${indentStr}<${node.tagName}`;
        if (node.attributes.length > 0) {
            Array.from(node.attributes).forEach(attr => {
                tagStr += ` ${attr.name}="${attr.value}"`;
            });
        }
        tagStr += '>';
        console.log(tagStr);

        // 递归遍历所有子节点
        Array.from(node.childNodes).forEach(child => {
            traverseNode(child, indent + 1);
        });

        // 输出闭合标签
        console.log(`${indentStr}</${node.tagName}>`);
    } else if (node.nodeType === Node.TEXT_NODE) {
        // 输出文本内容
        console.log(`${indentStr}${node.nodeValue.trim()}`);
    }
}

fs.readFile('course.xml', 'utf-8', function (err, data) {
    if (err) {
        throw err;
    }
    const parser = new xmldom();
    const doc = parser.parseFromString(data, 'application/xml');

    const userInput = readLineSync.question("Enter tag to be printed: ");
    const targetNodes = doc.getElementsByTagName(userInput.toLowerCase());
    
    console.log(`Tag ${userInput} entered`);
    
    if (targetNodes.length === 0) {
        console.log("No identical tag found.");
        return;
    }

    // 遍历所有匹配的目标节点
    Array.from(targetNodes).forEach((node, index) => {
        console.log(`\n--- 匹配的第 ${index + 1} 个 ${userInput} 节点内容 ---`);
        traverseNode(node);
    });
});

修改说明

  1. 新增递归遍历函数:traverseNode负责递归处理所有子节点,包括嵌套的lecturer、surname等元素。
  2. 过滤无效节点:跳过XML中因换行、缩进产生的空白文本节点,避免输出冗余内容。
  3. 完整输出标签信息:不仅输出标签内容,还会打印标签的属性(比如surname的language属性),并保持层级缩进,结构更清晰。
  4. 优化节点遍历逻辑:用Array.from将NodeList转为数组,避免遍历到非节点属性;增加匹配节点数量判断,直接提示无匹配的情况。

内容的提问来源于stack exchange,提问作者allen walker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 01:47:14