java 使用 DOM 迭代包含一些同名标签的 NodeList
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12132776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Iterating a NodeList consisting some tags with same name using DOM
提问by YankeeWhiskey
I'm trying to read in an XML using DOM in Java
我正在尝试使用 Java 中的 DOM 读取 XML
<?xml version="1.0"?>
<record>
<user>
<name>Leo</name>
<email>****@****.com</email>
<food-list>
<food>Hamburgers</food>
<food>Fish</food>
</food-list>
</user>
</record>
My current solution is
我目前的解决方案是
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();
And the output now is
现在的输出是
name : Leo
email : ******@*****.com
food :
food : null
food :
food : null
food :
Which quite confuses me. Could you tell me where I'm wrong? The number of food tags is not pre-defined.
这让我很困惑。你能告诉我我错在哪里吗?食品标签的数量不是预先定义的。
采纳答案by oldrinb
回答by Anthony
To get the sub elements of an element I've created a class that replace NodeList:
为了获取元素的子元素,我创建了一个替换 NodeList 的类:
ElementList as Replacement for NodeList
Note that the code is public domain.
请注意,代码是公共领域的。
/*
* 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);
}
}
回答by andirady
You can create your own NodeListclass and implements 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();
}
}
NOTE:NodeIterator needs to be in separate file.
注意:NodeIterator 需要在单独的文件中。