Разбор вложенных тегов XML с тем же именем - PullRequest
2 голосов
/ 21 марта 2010

Давайте возьмем простой XML-документ:

  <x>
    <e>
        <e>
            <e>Whatever 1</e>
        </e>
    </e>
    <e>
        <e>
            <e>Whatever 2</e>
        </e>
    </e>
    <e>
        <e>
            <e>Whatever 3</e>
        </e>
    </e>
  </x> 

Используя стандартный org.w3c.dom, я могу получить узлы в X, выполнив ..

NodeList fullnodelist = doc.getElementsByTagName("x");

Но если я хочу вернуть следующий набор "е", я пытаюсь использовать что-то вроде ..

Element element = (Element) fullnodelist.item(0);
NodeList nodes = pelement.getElementsByTagName("e");

Ожидается, что он возвратит «3» узла (потому что есть 3 набора «e»), но вместо этого он возвращает «9» - потому что он получает все записи с «e» одновременно.

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

  <x>
    <e>
      <pattern>whatever</pattern>
      <blanks>
        <e>Something Else</e>
      </blanks>
    </e>
    <e>
      <pattern>whatever</pattern>
      <blanks>
        <e>Something Else</e>
      </blanks>
    </e>
  </x>

Когда я запрашиваю значение "e", он возвращает 4 вместо (что я ожидаю) 2.

Я просто не понимаю, как работает анализ DOM? Обычно в прошлом я использовал свои собственные XML-документы, поэтому я никогда не назвал бы такие элементы, как это, но, к сожалению, это не мой XML-файл, и у меня нет выбора для такой работы.

То, что я думал, я бы сделал, это написать цикл, который "сверлит" узлы, чтобы я мог сгруппировать каждый узел вместе ...

public static NodeList getNodeList(Element pelement, String find)
    {
        String[] nodesfind = Utilities.Split(find, "/");
        NodeList nodeList = null;

        for (int i = 0 ; i <= nodesfind.length - 1; i++ )
        {
            nodeList = pelement.getElementsByTagName( nodesfind[i] );
            pelement = (Element)nodeList.item(i);
        }

        // value of the nod we are looking for
        return nodeList;
    }

.. Так что если вы передадите "s / e" в функцию, она вернет 2 искомых узла (или элементы, может быть, я использую неверную терминологию?). вместо этого он возвращает все узлы "e" в этом узле.

Я использую J2SE для этого, поэтому варианты довольно ограничены. Я не могу использовать сторонние парсеры XML.

В любом случае, если кто-то еще со мной и у него есть предложение, это будет оценено.

Ответы [ 3 ]

3 голосов
/ 22 марта 2010

Если вы вручную просматриваете Xml, попробуйте использовать переменную, которая увеличивается по мере того, как вы встречаете каждый тег "e", а затем уменьшается по мере того, как вы его покидаете.

Если источник следует приведенному выше примеру, который вы далиМожно использовать простое выражение if, чтобы убедиться, что счетчик равен 2, прежде чем выполнять действие (при условии, что оно началось с 0)

Возможно, я немного неправильно понял вашу конкретную проблему, но я надеюсь, что это поможет.

2 голосов
/ 10 февраля 2012

Лучшим решением, чем счетчик, было бы проверить каждый из возвращаемых узлов, чтобы увидеть, имеют ли они правильный родительский элемент.

getChildNodes() возвращает не только всех потомков, но и всех потомков (т.е. полное поддерево).

  Element element = doc.getDocumentElement();
  NodeList nodeList = element.getChildNodes();
  for (int i = 0; i < nodeList.getLength(); i++ ) {
    if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE && nodeList.item(i).getParentNode().isSameNode(element)) {
      Element childElement = (Element) nodeList.item(i);
      if (childElement.getTagName().equals("someTagName")) {
        handleSomeTag(childElement);
      } else if (childElement.getTagName().equals("someOtherTagName")) {
        handleSomeOtherTag(childElement);
      }
    }
  }

getElementsByTagName() возвращает не только всех потомков с этим тэгом, но и всех потомков с этим тэгом (т.е. все тэги с этим именем в полном поддереве).

  Element element = doc.getDocumentElement();
  NodeList nodeList = element.getElementsByTagName("someTag");
  for (int i = 0; i < nodeList.getLength(); i++ ) {
    if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE && nodeList.item(i).getParentNode().isSameNode(element)) {
      Element childElement = (Element) nodeList.item(i);
      handleSomeTag(childElement);
    }
  }
  nodeList = element.getElementsByTagName("someOtherTag");
  for (int i = 0; i < nodeList.getLength(); i++ ) {
    if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE && nodeList.item(i).getParentNode().isSameNode(element)) {
      Element childElement = (Element) nodeList.item(i);
      handleSomeOtherTag(childElement);
    }
  }
1 голос
/ 21 марта 2010

Вам нужно узнать о XPath. В стандартной версии Java 1.5 есть XPathFactory, и вы можете создать XPath, чтобы назвать нужные вам «e».

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