我有一个xml文件,如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<alarm-response-list xmlns="http://www.ca.com/spectrum/restful/schema/response"
error="EndOfResults" throttle="277" total-alarms="288">
<alarm-responses>
<alarm id="53689bf8-6cc8-1003-0060-008010186429">
<attribute id="0x11f4a" error="NoSuchAttribute" />
<attribute id="0x12b4c">UPS DIAGNOSTIC TEST FAILED</attribute>
<attribute id="0x10b5a">IDG860237, SL3-PL4, US, SapNr=70195637,</attribute>
</alarm>
<alarm id="536b8c9a-28b3-1008-0060-008010186429">
<attribute id="0x11f4a" error="NoSuchAttribute" />
<attribute id="0x12b4c">DEVICE IN MAINTENANCE MODE</attribute>
<attribute id="0x10b5a">IDG860237, SL3-PL4, US, SapNr=70195637,</attribute>
</alarm>
</alarm-responses>
</alarm-response-list>
有很多这些警报。现在我想为每个报警标签保存一个字符串中id = 0x10b5a的属性。但我没有一个很好的线索。以我的方式它不会这样做。我只是表达了表达。
我的想法:
FileInputStream file = new FileInputStream(
new File(
"alarms.xml"));
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(file);
XPath xPath = XPathFactory.newInstance().newXPath();
System.out.println("*************************");
String expression = "/alarm-responses/alarm/attribute[@id='0x10b5a'] ";
System.out.println(expression);
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(
xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getFirstChild()
.getNodeValue());
}
答案 0 :(得分:1)
这里有几个不同的问题,它们相互作用意味着你的XPath表达式与任何东西都不匹配。首先,alarm-responses
元素不是文档的根目录 - 您需要在路径前面添加一个额外的步骤来选择alarm-response-list
元素。但更重要的是,你有命名空间问题。
XPath仅在已使用启用的命名空间解析XML时才有效,由于某种原因,这不是DocumentBuilderFactory
的默认值。在执行newDocumentBuilder
之前,您需要启用命名空间。
现在,您的XML文档具有xmlns="http://www.ca.com/spectrum/restful/schema/response"
,它将所有元素放在此命名空间中,但XPath表达式中未加前缀的节点名称始终引用不在命名空间中的节点。为了匹配命名空间节点,您需要将前缀绑定到命名空间URI,然后在路径中使用带前缀的名称。
对于javax.xml.xpath
,这是使用NamespaceContext
完成的,但令人烦恼的是,Java核心库中默认没有此接口的默认实现。作为Spring的一部分,有SimpleNamespaceContext实现可用,或者编写自己的实现相当简单。使用Spring类:
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
// enable namespaces
builderFactory.setNamespaceAware(true);
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(file);
XPath xPath = XPathFactory.newInstance().newXPath();
// Set up the namespace context
SimpleNamespaceContext ctx = new SimpleNamespaceContext();
ctx.bindNamespaceUri("ca", "http://www.ca.com/spectrum/restful/schema/response");
xPath.setNamespaceContext(ctx);
System.out.println("*************************");
// corrected expression
String expression = "/ca:alarm-response-list/ca:alarm-responses/ca:alarm/ca:attribute[@id='0x10b5a']";
System.out.println(expression);
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(
xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getTextContent());
}
另请注意我如何使用getTextContent()
获取每个匹配元素下的文本。 getNodeValue()
方法始终为元素节点返回null
。