Итерация NodeList, состоящий из некоторых тегов с тем же именем с помощью DOM

Я пытаюсь читать в XML, используя DOM в Java

<?xml version="1.0"?>
<record>
<user>
    <name>Leo</name>
    <email>****@****.com</email>
        <food-list>
            <food>Hamburgers</food>
            <food>Fish</food>
        </food-list>
</user>
</record>

мое текущее решение является

    for (int userNumber = 0; userNumber < masterList.getLength(); userNumber++) {

           Node singleUserEntry = masterList.item(userNumber);
           if (singleUserEntry.getNodeType() == Node.ELEMENT_NODE) {

              org.w3c.dom.Element userEntryElement = (org.w3c.dom.Element) singleUserEntry;



              System.out.println("name : " + getTagValue("name", userEntryElement));
              System.out.println("email : " +getTagValue("email", userEntryElement));
              NodeList foodList = userEntryElement.getElementsByTagName("food-list").item(0).getChildNodes();
              for(int i = 0; i < foodList.getLength(); i++){
                  Node foodNode = foodList.item(i);
                  System.out.println("food : " + foodNode.getNodeValue());
              }

private static String getTagValue(String sTag, org.w3c.dom.Element eElement) {
     NodeList nlList =  eElement.getElementsByTagName(sTag).item(0).getChildNodes();
     Node nValue = (Node) nlList.item(0);
     return nValue.getNodeValue();

и выход теперь

name : Leo 
email : ******@*****.com
food :          
food : null
food :          
food : null
food : 

что меня совершенно смущает. Не могли бы вы сказать, где я ошибаюсь? Количество тегов продуктов питания не определено заранее.

3 ответов


((Node) foodNode.getChildNodes().item(0)).getNodeValue()

обратите внимание, что, как вы можете ясно видеть, работа с DOM API в Java довольно болезненна. Вы смотрели на помощи jdom или dom4j?


чтобы получить подэлементы элемента, я создал класс, который заменяет NodeList:

ElementList в качестве замены для NodeList

обратите внимание, что код является общественным достоянием.

/*
 * The code of this file is in public domain.
 */
package org.xins.common.xml;

import Java.util.LinkedList;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import org.xins.common.text.ParseException;

/**
 * An ElementList is an NodeList with the following improvements:
*

    Implements List which make it iterable with for each loop *
    Only includes the direct child of the element *
    Only includes the elements *
    By default includes all direct child elements *
    Preserves the order of the child elements *
    Includes a method to get the sub element when unique * 


*
 * @author Anthony Goubard
*
 * @since XINS 3.0
 */
public class ElementList extends LinkedList {

   /**
    * The local name of the parent element.
    */
   private String parentName;

   /**
    * The local name of the child elements or * for all elements
    */
   private String childName;

   /**
    * Creates a list with all direct child element of the given element.
    *
    * @param element
    *    the parent element, cannot be null.
    */
   public ElementList(Element element) {
      this(element, "*");
   }

   /**
    * Creates a list with all direct child element with a specific local name of the given element.
    *
    * @param element
    *    the parent element, cannot be null.
    * @param childName
    *    the local name of the direct child elements that should be added to the list, cannot be null.
    */
   public ElementList(Element element, String childName) {
      parentName = element.getTagName();
      this.childName = childName;
      Node child = element.getFirstChild();
      while (child != null) {
         String newChildName = child.getLocalName();
         if (newChildName == null) {
            newChildName = child.getNodeName();
         }
         if (child.getNodeType() == Node.ELEMENT_NODE &&
                 (childName.endsWith("*") || childName.equals(newChildName))) {
            add((Element) child);
         }
         child = child.getNextSibling();
      }
   }

   /**
    * Gets the unique child of this list.
    *
    * @return
    *    the sub-element of this element list, never null.
    *
    * @throws ParseException
    *    if no child with the specified name was found,
    *    or if more than one child with the specified name was found.
    */
   public Element getUniqueChildElement() throws ParseException {
      if (isEmpty()) {
         throw new ParseException("No \"" + childName + "\" child found in the \"" + parentName + "\" element.");
      } else if (size() > 1) {
         throw new ParseException("More than one \"" + childName + "\" children found in the \"" + parentName + "\" element.");
      }
      return get(0);
   }

   /**
    * Gets the first child of this element.
    *
    * @return
    *    the sub-element of this element, or null if no element is found.
    */
   public Element getFirstChildElement() {
      if (isEmpty()) {
         return null;
      }
      return get(0);
   }
}

вы можете создать свой собственный узла класс и реализует типа Iterable.

public class NodeList<T extends Node> extends JavaScriptObject implements Iterable<T> {

  protected NodeList() {
  }

  public final native T getItem(int index) /*-{
    return this[index];
  }-*/;

  public final native int getLength() /*-{
    return this.length;
  }-*/;

  @Override
  final public Iterator<T> iterator() {
    return new NodeIterator<T>(this);
  }
}

public class NodeIterator<T extends Node> implements Iterator<T> {
  private int cursor = 0;
  private NodeList<T> nodeList;

  public NodeIterator(NodeList<T> nodeList) {
    this.nodeList = nodeList;
  }

  @Override
  public boolean hasNext() {
    return cursor < nodeList.getLength();
  }

  @Override
  public T next() {
    if (hasNext()) {
      return nodeList.getItem(cursor++);
    }
    throw new NoSuchElementException();
  }

  @Override
  public void remove() {
    throw new UnsupportedOperationException();
  }
}

Примечание: NodeIterator должен быть в отдельном файле.