如何在Java中使用XPath读取XML

我想用Java中的XPath读取XML数据,所以对于我收集的信息,我无法根据我的要求parsingXML。

这是我想要做的:

通过它的URL从在线获取XML文件,然后使用XPathparsing它,我想在其中创build两个方法。 一个是我在其中input一个特定的节点属性ID,我得到所有的子节点作为结果,第二是假设我只想得到一个特定的子节点值

<?xml version="1.0"?> <howto> <topic name="Java"> <url>http://www.rgagnonjavahowto.htm</url> <car>taxi</car> </topic> <topic name="PowerBuilder"> <url>http://www.rgagnon/pbhowto.htm</url> <url>http://www.rgagnon/pbhowtonew.htm</url> </topic> <topic name="Javascript"> <url>http://www.rgagnon/jshowto.htm</url> </topic> <topic name="VBScript"> <url>http://www.rgagnon/vbshowto.htm</url> </topic> </howto> 

在上面的例子中,我想读取所有的元素,如果我通过@namesearch,还有一个函数,我只想从@name'Javascript'的URL只返回一个节点元素。

我希望我清除我的问题:)

谢谢。

你需要一些东西:

 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(<uri_as_string>); XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); XPathExpression expr = xpath.compile(<xpath_expression>); 

然后调用expr.evaluate()传入在该代码中定义的文档和您期待的返回types,并将结果转换为结果的对象types。

如果你需要特定的XPathexpression式的帮助,你应该把它作为单独的问题来提出(除非这是你的问题 – 我理解你的问题是如何在Java中使用API​​)。

编辑:(响应评论):这个XPathexpression式将会得到你在PowerBuilder下的第一个URL元素的文本:

 /howto/topic[@name='PowerBuilder']/url/text() 

这会让你第二个:

 /howto/topic[@name='PowerBuilder']/url[2]/text() 

你得到这个代码:

 expr.evaluate(doc, XPathConstants.STRING); 

如果您不知道给定节点中有多less个URL,那么您应该这样做:

 XPathExpression expr = xpath.compile("/howto/topic[@name='PowerBuilder']/url"); NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); 

然后遍历NodeList。

入门示例:

xml文件:

 <inventory> <book year="2000"> <title>Snow Crash</title> <author>Neal Stephenson</author> <publisher>Spectra</publisher> <isbn>0553380958</isbn> <price>14.95</price> </book> <book year="2005"> <title>Burning Tower</title> <author>Larry Niven</author> <author>Jerry Pournelle</author> <publisher>Pocket</publisher> <isbn>0743416910</isbn> <price>5.99</price> </book> <book year="1995"> <title>Zodiac</title> <author>Neal Stephenson</author> <publisher>Spectra</publisher> <isbn>0553573862</isbn> <price>7.50</price> </book> <!-- more books... --> </inventory> 

Java代码:

 import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; try { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document doc = docBuilder.parse (new File("c:\\tmp\\my.xml")); // normalize text representation doc.getDocumentElement().normalize(); System.out.println ("Root element of the doc is " + doc.getDocumentElement().getNodeName()); NodeList listOfBooks = doc.getElementsByTagName("book"); int totalBooks = listOfBooks.getLength(); System.out.println("Total no of books : " + totalBooks); for(int i=0; i<listOfBooks.getLength() ; i++) { Node firstBookNode = listOfBooks.item(i); if(firstBookNode.getNodeType() == Node.ELEMENT_NODE) { Element firstElement = (Element)firstBookNode; System.out.println("Year :"+firstElement.getAttribute("year")); //------- NodeList firstNameList = firstElement.getElementsByTagName("title"); Element firstNameElement = (Element)firstNameList.item(0); NodeList textFNList = firstNameElement.getChildNodes(); System.out.println("title : " + ((Node)textFNList.item(0)).getNodeValue().trim()); } }//end of for loop with s var } catch (SAXParseException err) { System.out.println ("** Parsing error" + ", line " + err.getLineNumber () + ", uri " + err.getSystemId ()); System.out.println(" " + err.getMessage ()); } catch (SAXException e) { Exception x = e.getException (); ((x == null) ? e : x).printStackTrace (); } catch (Throwable t) { t.printStackTrace (); } 

你可以试试这个

XML文档

另存为employees.xml

 <?xml version="1.0" encoding="UTF-8"?> <Employees> <Employee id="1"> <age>29</age> <name>Pankaj</name> <gender>Male</gender> <role>Java Developer</role> </Employee> <Employee id="2"> <age>35</age> <name>Lisa</name> <gender>Female</gender> <role>CEO</role> </Employee> <Employee id="3"> <age>40</age> <name>Tom</name> <gender>Male</gender> <role>Manager</role> </Employee> <Employee id="4"> <age>25</age> <name>Meghan</name> <gender>Female</gender> <role>Manager</role> </Employee> </Employees> 

parsing器类

这个类有以下几种方法

  • 列表项目
  • 一个将返回inputID的员工名称的方法。
  • 将返回年龄大于input年龄的员工名单列表的方法。
  • 将返回女性员工名单的方法。

源代码

 import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class Parser { public static void main(String[] args) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder; Document doc = null; try { builder = factory.newDocumentBuilder(); doc = builder.parse("employees.xml"); // Create XPathFactory object XPathFactory xpathFactory = XPathFactory.newInstance(); // Create XPath object XPath xpath = xpathFactory.newXPath(); String name = getEmployeeNameById(doc, xpath, 4); System.out.println("Employee Name with ID 4: " + name); List<String> names = getEmployeeNameWithAge(doc, xpath, 30); System.out.println("Employees with 'age>30' are:" + Arrays.toString(names.toArray())); List<String> femaleEmps = getFemaleEmployeesName(doc, xpath); System.out.println("Female Employees names are:" + Arrays.toString(femaleEmps.toArray())); } catch (ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } } private static List<String> getFemaleEmployeesName(Document doc, XPath xpath) { List<String> list = new ArrayList<>(); try { //create XPathExpression object XPathExpression expr = xpath.compile("/Employees/Employee[gender='Female']/name/text()"); //evaluate expression result on XML document NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < nodes.getLength(); i++) list.add(nodes.item(i).getNodeValue()); } catch (XPathExpressionException e) { e.printStackTrace(); } return list; } private static List<String> getEmployeeNameWithAge(Document doc, XPath xpath, int age) { List<String> list = new ArrayList<>(); try { XPathExpression expr = xpath.compile("/Employees/Employee[age>" + age + "]/name/text()"); NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < nodes.getLength(); i++) list.add(nodes.item(i).getNodeValue()); } catch (XPathExpressionException e) { e.printStackTrace(); } return list; } private static String getEmployeeNameById(Document doc, XPath xpath, int id) { String name = null; try { XPathExpression expr = xpath.compile("/Employees/Employee[@id='" + id + "']/name/text()"); name = (String) expr.evaluate(doc, XPathConstants.STRING); } catch (XPathExpressionException e) { e.printStackTrace(); } return name; } } 

这里是一个例子,用vtd-xml处理xpath …对于繁重的XML处理来说,它是首屈一指的。 这是一个关于这个主题的最近的论文, 用Java处理XML – 性能基准

 import com.ximpleware.*; public class changeAttrVal { public static void main(String s[]) throws VTDException,java.io.UnsupportedEncodingException,java.io.IOException{ VTDGen vg = new VTDGen(); if (!vg.parseFile("input.xml", false)) return; VTDNav vn = vg.getNav(); AutoPilot ap = new AutoPilot(vn); XMLModifier xm = new XMLModifier(vn); ap.selectXPath("/*/place[@id=\"p14\" and @initialMarking=\"2\"]/@initialMarking"); int i=0; while((i=ap.evalXPath())!=-1){ xm.updateToken(i+1, "499");// change initial marking from 2 to 499 } xm.output("new.xml"); } } 

通过@bluish和@Yishai扩展出色的答案,这里是你如何使NodeLists和节点属性支持迭代器,即for(Node n: nodelist)接口。

像这样使用它:

 NodeList nl = ... for(Node n : XmlUtil.asList(nl)) {...} 

 Node n = ... for(Node attr : XmlUtil.asList(n.getAttributes()) {...} 

代码:

 /** * Converts NodeList to an iterable construct. * From: https://stackoverflow.com/a/19591302/779521 */ public final class XmlUtil { private XmlUtil() {} public static List<Node> asList(NodeList n) { return n.getLength() == 0 ? Collections.<Node>emptyList() : new NodeListWrapper(n); } static final class NodeListWrapper extends AbstractList<Node> implements RandomAccess { private final NodeList list; NodeListWrapper(NodeList l) { this.list = l; } public Node get(int index) { return this.list.item(index); } public int size() { return this.list.getLength(); } } public static List<Node> asList(NamedNodeMap n) { return n.getLength() == 0 ? Collections.<Node>emptyList() : new NodeMapWrapper(n); } static final class NodeMapWrapper extends AbstractList<Node> implements RandomAccess { private final NamedNodeMap list; NodeMapWrapper(NamedNodeMap l) { this.list = l; } public Node get(int index) { return this.list.item(index); } public int size() { return this.list.getLength(); } } } 

使用XPathFactory, SAXParserFactoryStAX (JSR-173)读取XML文件。

使用XPath获取节点及其子数据。

 /** * ELEMENT_NODE[1],ATTRIBUTE_NODE[2],TEXT_NODE[3],CDATA_SECTION_NODE[4], * ENTITY_REFERENCE_NODE[5],ENTITY_NODE[6],PROCESSING_INSTRUCTION_NODE[7], * COMMENT_NODE[8],DOCUMENT_NODE[9],DOCUMENT_TYPE_NODE[10],DOCUMENT_FRAGMENT_NODE[11],NOTATION_NODE[12] */ public static void getNodesFromXpath() { try { File jmxFile = new File("./books.xml"); FileInputStream in = new FileInputStream( jmxFile ); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); XPathFactory xpf = XPathFactory.newInstance(); XPath xpath = xpf.newXPath(); Document doc = builder.parse( in ); String xpathExpression = "//person/first"; // //person/first[.='Yash'] XPathExpression compile = xpath.compile(xpathExpression); NodeList nodeList = (NodeList) compile.evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); String NodeName = node.getNodeName(); NodeList childNodes = node.getChildNodes(); if ( childNodes.getLength() > 1 ) { for (int j = 0; j < childNodes.getLength(); j++) { Node child = childNodes.item(j); short nodeType = child.getNodeType(); if ( nodeType == 1 ) { System.out.format( "\n\t Node Name:[%s], Text[%s] ", child.getNodeName(), child.getTextContent() ); } } } else { System.out.format( "\n Node Name:[%s], Text[%s] ", NodeName, node.getTextContent() ); } } } catch (XPathExpressionException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } } 

XML文档

 <?xml version="1.0" encoding="UTF-8"?> <book> <person> <first>Yash</first> <last>M</last> <age>22</age> </person> <person> <first>Bill</first> <last>Gates</last> <age>46</age> </person> <person> <first>Steve</first> <last>Jobs</last> <age>40</age> </person> </book> 

输出给定的XPathExpression:

 String xpathExpression = "//person/first"; /*OutPut: Node Name:[first], Text[Yash] Node Name:[first], Text[Bill] Node Name:[first], Text[Steve] */ String xpathExpression = "//person"; /*OutPut: Node Name:[first], Text[Yash] Node Name:[last], Text[M] Node Name:[age], Text[22] Node Name:[first], Text[Bill] Node Name:[last], Text[Gates] Node Name:[age], Text[46] Node Name:[first], Text[Steve] Node Name:[last], Text[Jobs] Node Name:[age], Text[40] */ 

ReadAndPrintXMLFileWithStAX(使用Java SE 7)