簡體   English   中英

具有屬性的XPath選擇元素

[英]XPath select element with an attribute

我有一個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());
        }

這里有幾個不同的問題正在相互作用,這意味着您的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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM