Node.js中使用xml-reader获取XML节点值为空的问题排查
解决xml-reader和xml-query无法获取XML
标签内容的问题
问题场景
在Node.js环境下使用xml-reader和xml-query解析XML文件时,无法读取<p>标签内的文本内容(例如aldScanningInterval对应的"30 sec"),控制台输出中参数值始终为空。
示例XML文件(sample_file.xml)
<raml><cmData> <managedObject class="com.nokia.srbts.eqm:APEQM" distName="MRBTS-Template/EQM-1/APEQM-1" version="EQM21A_2012_002" operation="create"> <p name="aldScanningInterval">30 sec</p> <p name="berMajorAlarmThreshold">-12</p> <p name="berMinorAlarmThreshold">-13</p> </managedObject> </cmData></raml>
原解析代码
const XmlReader = require('xml-reader'); const fs = require('fs'); const xml = fs.readFileSync("./publish/DATA/A2G/templates/sample_file.xml", "utf8"); const xmlr = XmlReader.parseSync(xml); const xmlQuery = require('xml-query'); xmlQuery(xmlr).children().children().map(node => console.log(node.attributes.distName + " Params: " + node.children.map(child => child.attributes.name + "=" + child.value + " ")));
原错误输出
Okt 31 13:30:54 S5-VPN a2gc[2835315]: MRBTS-Template/EQM-1/APEQM-1 Okt 31 13:30:54 S5-VPN a2gc[2835315]: Params: Okt 31 13:30:54 S5-VPN a2gc[2835315]: aldScanningInterval= Okt 31 13:30:54 S5-VPN a2gc[2835315]: ,berMajorAlarmThreshold= Okt 31 13:30:54 S5-VPN a2gc[2835315]: ,berMinorAlarmThreshold=
原因分析
xml-reader的解析规则是:标签内的文本内容会被封装成独立的文本子节点,而非直接挂载在<p>节点的value或text属性上。你看到<p>节点的children数组中存在的对象,就是这个文本子节点,需要访问它的value属性才能拿到内容。
解决方案
方案1:直接遍历文本子节点
修改原代码,手动取出<p>节点子数组中的文本节点值:
const XmlReader = require('xml-reader'); const fs = require('fs'); const xml = fs.readFileSync("./publish/DATA/A2G/templates/sample_file.xml", "utf8"); const xmlr = XmlReader.parseSync(xml); const xmlQuery = require('xml-query'); xmlQuery(xmlr).children().children().map(node => { console.log(node.attributes.distName); console.log(" Params:"); // 遍历每个<p>节点 node.children.forEach(child => { // 取出文本子节点的value,做空值兼容 const textValue = child.children[0]?.value || ''; console.log(` ${child.attributes.name}=${textValue}`); }); });
方案2:使用xml-query内置方法
利用xml-query提供的.text()方法直接获取节点文本,代码更简洁:
const XmlReader = require('xml-reader'); const fs = require('fs'); const xml = fs.readFileSync("./publish/DATA/A2G/templates/sample_file.xml", "utf8"); const xmlr = XmlReader.parseSync(xml); const xmlQuery = require('xml-query'); // 定位到managedObject节点 xmlQuery(xmlr).find('managedObject').each((_, moNode) => { console.log(moNode.attributes.distName); console.log(" Params:"); // 遍历每个<p>节点 xmlQuery(moNode).find('p').each((_, pNode) => { const paramName = pNode.attributes.name; // 用text()方法直接获取文本内容 const paramValue = xmlQuery(pNode).text(); console.log(` ${paramName}=${paramValue}`); }); });
验证结果
两种方案都会输出正确的参数内容:
MRBTS-Template/EQM-1/APEQM-1 Params: aldScanningInterval=30 sec berMajorAlarmThreshold=-12 berMinorAlarmThreshold=-13
内容的提问来源于stack exchange,提问作者João Paulo
相关产品推荐
相关产品推荐

