简体   繁体   English

在Java中使用XPath解析XML

[英]parsing XML using XPath in Java

Say I have the following XML file: 假设我有以下XML文件:

<?xml version="1.0" encoding="utf-8"?>
<venues>
  <group type="Nearby">
    <venue>
      <id>222307</id>
      <name>Union Chapel</name>
      <primarycategory>
        <id>78967</id>
        <fullpathname>Arts &amp; Entertainment:Music Venue</fullpathname>
        <nodename>Music Venue</nodename>
        <iconurl>http://foursquare.com/img/categories/arts_entertainment/musicvenue.png</iconurl>
      </primarycategory>
      <address>Compton Ave</address>
      <city>Islington</city>
      <state>Greater London</state>
      <zip>N1 2XD</zip>
      <verified>false</verified>
      <geolat>51.5439732</geolat>
      <geolong>-0.1020908</geolong>
      <stats>
        <herenow>0</herenow>
      </stats>
      <phone>02073594019</phone>
      <distance>33</distance>
    </venue>

............. .............

and my code is the following: 我的代码如下:

    XPathFactory factory = XPathFactory.newInstance();
    XPath xpath = factory.newXPath();
    XPathExpression expr = xpath.compile("//venue/*");

    Object result = expr.evaluate(document, XPathConstants.NODESET);
    NodeList nodes = (NodeList) result;
    //System.out.println(nodes.getLength());

    Venue ven = new Venue();

    for (int i = 0; i < nodes.getLength(); i++) {
        String nodeName = nodes.item(i).getNodeName();
        String nodeValue = nodes.item(i).getNodeValue();


        if (nodeName.equals("id")){
            ven = new Venue();
            if (nodeValue != null)
                ven.id = Integer.parseInt(nodeValue);
            System.out.println(ven.id);
        }

        if (nodeName.equals("name")){
            ven.name = nodeValue;
            System.out.println(ven.name);
        }

        if (nodeName.equals("address")){
            ven.address = nodeValue;
            System.out.println(ven.address);
        }

How can I do all of this in one for loop for efficiency? 如何在一个for循环中实现所有这些以提高效率? Otherwise for every attribute in the xml that I want to extract I need to create a for loop for each one of them 否则,对于我想要提取的xml中的每个属性,我需要为它们中的每一个创建一个for循环

If you use this as your xpath: 如果您将其用作xpath:

//venue/*

You'll get all the child nodes of venue. 您将获得场地的所有子节点。 You can then iterate over this and do a big if else on the node name's and assign them as needed. 然后,您可以对此进行迭代,并在节点名称上执行大的if else,并根据需要进行分配。

Like this: 像这样:

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("//venue/*");

Object result = expr.evaluate(document, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item( i );
            String nodeName = node.getNodeName();
            String nodeValue = node.getChildNodes().item( 0 ).getNodeValue();


            if( nodeName.equals( "name" ) ) {
                        name = nodeValue;
            } 
            else if( nodeName.equals( "address" ) ) {
                        address = nodeValue;
            } // ... the rest goes here
}

If you don't want to iterate over all child elements you could do something like this: 如果您不想迭代所有子元素,可以执行以下操作:

    XPathExpression expr = xpath.compile( "//venue" );

    Object result = expr.evaluate( document, XPathConstants.NODESET );
    NodeList nodes = (NodeList)result;
    for( int i = 0; i < nodes.getLength(); i++ ) {
        Node node = nodes.item( i );
        NodeList venueChildNodes = node.getChildNodes();

        String id = venueChildNodes.item( 1 ).getChildNodes().item( 0 ).getNodeValue();
        System.out.println( "id: " + id );

        String name = venueChildNodes.item( 3 ).getChildNodes().item( 0 ).getNodeValue();
        System.out.println( "name: " + name );

        String address = venueChildNodes.item( 7 ).getChildNodes().item( 0 ).getNodeValue();
        System.out.println( "address: " + address );
    }

Where you get all venue nodes and then map it's children. 在哪里获得所有场地节点然后映射它的孩子。 Though, this approach would require a fairly consistent xml structure. 但是,这种方法需要一个相当一致的xml结构。 Though, something like this seems safest to me: 虽然,这样的事情对我来说似乎最安全:

    XPathExpression expr = xpath.compile( "//venue" );

    Object result = expr.evaluate( document, XPathConstants.NODESET );
    NodeList nodes = (NodeList)result;
    for( int i = 0; i < nodes.getLength(); i++ ) {
        Node node = nodes.item( i );
        NodeList venueChildNodes = node.getChildNodes();

        String address = null;
        String name = null;

        for( int j = 0; j < venueChildNodes.getLength(); j++ ) {
            Node item = venueChildNodes.item( j );
            String nodeName = item.getNodeName();

            if ( nodeName.equals( "address" ) ) {
                address = item.getChildNodes().item( 0 ).getNodeValue();
            }

            if ( nodeName.equals( "name" ) ) {
                name = item.getChildNodes().item( 0 ).getNodeValue();
            }
        }

        System.out.println( "address: " + address );
        System.out.println( "name: " + name );
    }

You can combine them like: 您可以将它们组合成:

//venue/address/text()|//venue/name/text()

This will return the nodes in document order and you can simply iterate over them. 这将按文档顺序返回节点,您可以简单地迭代它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM