即使不同节点中的标签名称相同,也可以解析XML

时间:2019-01-10 15:19:10

标签: java xml dom xml-parsing

我正在使用DOM解析器/生成器解析Java中的XML文件。 对于我的XML标记名的一部分来说,它工作正常。但是当我尝试解析另一个Tagname时,情况变得越来越糟,因为Tagname也用于其他Tag中。

XML文件:

<RootTag>
  <humans>
    <human>
      <name>Max</name>
      <age>22</age>
      <friends>
        <friend>
          <name>Peter</name>
          <adress>
            <street>Way down 1</street>
          </adress>
        </friend>
        <friend>
          <name>Kevin</name>
          <adress>
            <street>Way left 2</street>
          </adress>
        </friend>
      </friends>
    </human>
    <human>
      <name>Justin</name>
      <age>22</age>
      <friends>
        <friend>
          <name>Georg</name>
          <adress>
            <street>Way up 1</street>
          </adress>
        </friend>
      </friends>
    </human>
  </humans>
  <friend>
    <friends>
      <name>Max</name>
      <numberFriends>2</numberFriends>
    </friends>
    <friends>
      <name>Justin</name>
      <numberFriends>1</numberFriends>
    </friends>
  </friend>
</RootTag>

Java:

public static void parse() throws ParserConfigurationException, IOException, SAXException {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(true);
    factory.setIgnoringElementContentWhitespace(true);
    DocumentBuilder builder = factory.newDocumentBuilder();
    File file = new File("humanFriends.xml");
    Document doc = builder.parse(file);

    NodeList humanL = doc.getElementsByTagName("human");
    for (int j = 0; j < humanL.getLength(); j++) {
        Node humanN = humanL.item(j);
        if (humanN.getNodeType() == Node.ELEMENT_NODE) {
            Element humanE = (Element) humanN;
            String name = humanE.getElementsByTagName("name").item(0).getTextContent();
            String vehicleId = humanE.getElementsByTagName("age").item(0).getTextContent();
        ... 
        }

    NodeList friendsL = doc.getElementsByTagName("friends");
    for (int j = 0; j < friendsL.getLength(); j++) {
        Node friendsN = friendsL.item(j);
        if (friendsN.getNodeType() == Node.ELEMENT_NODE) {
            Element friendsE = (Element) friendsN;
            String name = friendsE.getElementsByTagName("name").item(0).getTextContent();
            String vehicleId = friendsE.getElementsByTagName("numberFriends").item(0).getTextContent();

        here I'm getting error because parser take also friends from human Tag... 
        }
} 

是否可以像在特定子节点中按层次结构或仅对标记名进行解析? 而且即使在不同节点中使用相同的标记名也可以解析XML,还是XML的结构不好?

1 个答案:

答案 0 :(得分:1)

Element.getElementsByTagName("foo")返回所有 后代元素(当前元素的名称,具有给定的标记/元素名称)。在您的代码+示例中,这只会抛出一个讨厌的NPE,因为前friends个元素内部没有numberFriends

现在您可以:

  1. 抓住NullPointerException(或进行其他测试,确定您是否使用了正确的元素……这不是我最喜欢的方法,不是干净的方法,但很实用,简短且有效)。
  2. “深入”到xml结构中,为您选择合适的东西。 (因此,不是从{doc}根元素中获取getElementsByTagName() ...,而是从相应的子元素中获取。):

(代表2。)假设您想要所有//humans/human(<-XPATH)元素的名称+年龄以及所有//friend/friends元素的name + numberFriends,您将执行以下操作: / p>

import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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;

public class Test {

    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setValidating(true);
        factory.setIgnoringElementContentWhitespace(true);
        DocumentBuilder builder = factory.newDocumentBuilder();
        File file = new File("humanFriends.xml");
        Document doc = builder.parse(file);

        NodeList humansL = doc.getElementsByTagName("humans");
        //System.out.println(humansL.getLength());
        for (int i = 0; i < humansL.getLength(); i++) {
            Node humansN = humansL.item(i);
            if (humansN.getNodeType() == Node.ELEMENT_NODE) {
                NodeList humanL = ((Element) humansN).getElementsByTagName("human");
                // System.out.println(humanL.getLength());
                for (int j = 0; j < humanL.getLength(); j++) {
                    Node humanN = humanL.item(j);
                    if (humanN.getNodeType() == Node.ELEMENT_NODE) {
                        Element humanE = (Element) humanN;
                        String name = humanE.getElementsByTagName("name").item(0).getTextContent();
                        String age= humanE.getElementsByTagName("age").item(0).getTextContent();
                        System.out.println(name);
                        System.out.println(age);
                    }
                }
            }
        }

        NodeList friendsL = doc.getElementsByTagName("friend");
        // System.out.println(friendsL.getLength());
        for (int i = 0; i < friendsL.getLength(); i++) {
            Node friendsN = friendsL.item(i);
            if (friendsN.getNodeType() == Node.ELEMENT_NODE) {
                NodeList friendL = ((Element) friendsN).getElementsByTagName("friends");
                // System.out.println(friendL.getLength());
                for (int j = 0; j < friendL.getLength(); j++) {
                    Node friendN = friendL.item(j);
                    if (friendN.getNodeType() == Node.ELEMENT_NODE) {
                        Element friendE = (Element) friendN;
                        String name = friendE.getElementsByTagName("name").item(0).getTextContent();
                        System.out.println(name);
                        String numberFriends = friendE.getElementsByTagName("numberFriends").item(0).getTextContent();
                        System.out.println(numberFriends);
                    }
                }
            }
        }
    }
}

请稍微改变(测试)“ humanFriends.xml”中的值,尤其是要识别不明确的标记名称中的问题;)