2013-03-28 8 views
0

Это следующий стандартный код для синтаксического анализа XML с использованием XPath в Java. Я не могу отлаживать, почему я получаю нулевые значения. Я приложил java-файл, xml-файл и вывод. Был бы признателен, если кто-нибудь сможет немного объяснить, где я ошибаюсь. Заранее спасибо! :)XML XPath Parsing in Java

XPathParser.java

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.xpath.XPath; 
import javax.xml.xpath.XPathConstants; 
import javax.xml.xpath.XPathExpression; 
import javax.xml.xpath.XPathFactory; 

import org.w3c.dom.Document; 
import org.w3c.dom.NodeList; 

public class XPathParser { 
    public static void main(String args[]) throws Exception { 
     //loading the XML document from a file 
     DocumentBuilderFactory builderfactory = DocumentBuilderFactory.newInstance(); 
     builderfactory.setNamespaceAware(true); 

     //XML read 
     DocumentBuilder builder = builderfactory.newDocumentBuilder(); 
     Document xmlDocument = builder.parse("Stocks.xml"); 

     // Creates a XPath factory 
     XPathFactory factory = javax.xml.xpath.XPathFactory.newInstance(); 

     //Creates a XPath Object 
     XPath xPath = factory.newXPath(); 

     //Compiles the XPath expression 
     //XPathExpression xPathExpression_count = xPath.compile("count(//stock)"); 
     XPathExpression xPathExpression = xPath.compile("//stock"); 

     //Run the query and get a nodeset 
     Object result = xPathExpression.evaluate(xmlDocument,XPathConstants.NODESET); 

     //Cast the result into a DOM nodelist 
     NodeList nodes = (NodeList) result; 
     System.out.println(nodes.getLength()); 
     System.out.println(nodes.item(0)); 
     for (int i=0; i<nodes.getLength();i++){ 
      System.out.println(nodes.item(i).getNodeValue()); 
     } 
    } 
} 

Stocks.xml

<?xml version="1.0" encoding="UTF-8"?> 
<stocks> 
       <stock> 
              <symbol>ABC</symbol> 
              <price>10</price> 
              <quantity>50</quantity> 
       </stock> 
       <stock> 
              <symbol>XYZ</symbol> 
              <price>20</price> 
              <quantity>1000</quantity> 
       </stock> 
</stocks> 

ВЫВОД:

2 
[stock: null] 
null 
null 
+1

Что вы ожидаете? Ваш XPath выбирает все узлы 'stock', после чего вы вызываете [' getNodeValue'] (http://docs.oracle.com/javase/1.5.0/docs/api/org/w3c/dom/Node.html#getNodeValue ()) на них, который возвращает 'null'. Что вы пытаетесь получить? –

+1

попробуйте напечатать 'nodes.item (i) .getTextContent()' вместо 'nodes.item (i) .getNodeValue()'. Или измените выражение XPath на '// stock/text()' –

ответ

0

Вы пытаетесь вызова getNodeValue метод на Stock узлов - это не имеют смысл, поскольку они не имеют значения, они являются родительскими узлами.

Вы можете перебираем дочерние узлы Stock и искать информацию:

final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes())); 
final XPathExpression expression = XPathFactory.newInstance().newXPath().compile("//stock"); 
final NodeList nodeList = (NodeList) expression.evaluate(document, XPathConstants.NODESET); 
for (int i = 0; i < nodeList.getLength(); ++i) { 
    final NodeList childList = ((Element) nodeList.item(i)).getChildNodes(); 
    for (int j = 0; j < childList.getLength(); ++j) { 
     final Node node = childList.item(j); 
     if (node.getNodeType() == Node.ELEMENT_NODE) { 
      System.out.println(node.getNodeName() + "=" + node.getTextContent()); 
     } 
    } 
} 

Выход:

symbol=ABC 
price=10 
quantity=50 
symbol=XYZ 
price=20 
quantity=1000 

Обратите внимание, что вы должны фильтровать ребенку Node сек по типу в противном случае вам петлю на сочетание дочерних узлов и текстового значения узла, которое появляется как текстовый узел. Это обычная игра, проходящая через XML таким образом.

Вы можете также цикл по всем дочерним текстовым узлам Stock:

final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes())); 
final XPathExpression expression = XPathFactory.newInstance().newXPath().compile("//stock/*/text()"); 
final NodeList nodeList = (NodeList) expression.evaluate(document, XPathConstants.NODESET); 
for (int i = 0; i < nodeList.getLength(); ++i) { 
    final Node node = nodeList.item(i); 
    System.out.println(node.getNodeValue()); 
} 

Выход:

ABC 
10 
50 
XYZ 
20 
1000 

В этой ситуации вы перебираешь все текстовые узлы, что дети детей Stock - это означает, что вы теряете информацию об имени узла. Но вы можете воссоздать первый подход, обернув над всеми детьми Stock, которые не являются текстовыми узлами:

final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes())); 
final XPathExpression expression = XPathFactory.newInstance().newXPath().compile("//stock/*"); 
final NodeList nodeList = (NodeList) expression.evaluate(document, XPathConstants.NODESET); 
for (int i = 0; i < nodeList.getLength(); ++i) { 
    final Node node = nodeList.item(i); 
    System.out.println(node.getNodeName() + "=" + node.getTextContent()); 
} 

Выход:

symbol=ABC 
price=10 
quantity=50 
symbol=XYZ 
price=20 
quantity=1000 

Или вы можете выбрать конкретный дочерний узел в XPath, если вы хотите что-то более конкретно:

final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes())); 
final XPathExpression expression = XPathFactory.newInstance().newXPath().compile("//stock/symbol/text()"); 
final NodeList nodeList = (NodeList) expression.evaluate(document, XPathConstants.NODESET); 
for (int i = 0; i < nodeList.getLength(); ++i) { 
    final Node node = nodeList.item(i); 
    System.out.println(node.getNodeValue()); 
} 

Выход:

ABC 
XYZ