Есть ли способ синтаксического анализа XML, хотя те же имена тегов в разных узлах - PullRequest
0 голосов
/ 10 января 2019

Я анализирую мой XML-файл на Java с помощью DOM Parser / Builder. Для одной части моего тэга XML он работает нормально. Но когда я пытаюсь разобрать другой тэг, становится все хуже, потому что тэг также используется в других тэгах.

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 голосов
/ 10 января 2019

Element.getElementsByTagName("foo") возвращает все потомка элементов (текущего элемента с заданным именем тега / элемента). В вашем примере кода + это просто бросает неприятный NPE, потому что первые friends элементы не имеют numberFriends внутри.

Теперь вы можете:

  1. поймать NullPointerException (или иным образом проверить, находитесь ли вы в правильном элементе ... это не мой любимый подход, не чистый, но довольно прагматичный, короткий и работающий).
  2. «углубиться» в структуру xml, чтобы выбрать нужные для вас вещи. (Таким образом, не получает getElementsByTagName() ... из корневого элемента (doc), а из соответствующих подэлементов.):

(для 2.) Предполагая, что вам нужны имена + возраст всех //humans/human (<- XPATH) элементов и name + numberFriends из всех <code>//friend/friends элементов, вы должны сделать что-то вроде:

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", особенно для распознавания проблем в неоднозначных именах тегов;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...