我有一个以下模式的xml文件,其中包含一些Complex Empty Elements
(没有内容的元素,只有属性)。
<items>
<item id="0" name="a" />
<item id="1" name="b" />
</items>
我迷失了解析他们的属性。这是我到目前为止所做的:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(inputStream);
Element itemsElement = document.getDocumentElement();
if (itemsElement.getTagName().equals(TAG_ITEMS)) {
NodeList nodeList = itemsElement.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
// process each item node
Node node = nodeList.item(i);
if (node.getNodeType() == Node.TEXT_NODE) { // Is this the right way?
Text text = (Text) node;
// Do stuff with attributes
}
}
}
我无法将这些Text
节点强制转换为Element
个节点并获取属性,我无法使用getAttributes
- NamedNodeMap attributes.getLength()
处的NPE从节点获取属性,我无法将其转换为Text
并获取属性。我该如何解析属性?
答案 0 :(得分:3)
您对items
内部节点的文本上下文不感兴趣,但对节点item
的属性不感兴趣。你可以按照以下步骤进行:
//process each item node
Node node = nodeList.item(i);
if (node.getNodeName().equals("item")) {
NamedNodeMap attributes = node.getAttributes();
System.out.printf("id=%s, name=%s%n",
attributes.getNamedItem("id").getTextContent(),
attributes.getNamedItem("name").getTextContent());
}
这将打印:
id=0, name=a
id=1, name=b
答案 1 :(得分:2)
假设您希望获得节点的个别属性,您需要选择两件事之一(或两者都取决于您的需要)......
例如,您需要测试当前节点是ELEMENT_NODE
还是当前节点的名称等于item
(假设所有节点名称相同)。 ..
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
public class Test {
public static final String TAG_ITEMS = "items";
public static void main(String[] args) {
try (InputStream is = Test.class.getResourceAsStream("/Test.xml")) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(is);
Element itemsElement = document.getDocumentElement();
if (itemsElement.getTagName().equals(TAG_ITEMS)) {
NodeList nodeList = itemsElement.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
NamedNodeMap attributes = node.getAttributes();
Node idAtt = attributes.getNamedItem("id");
Node nameAtt = attributes.getNamedItem("name");
System.out.println("id = " + idAtt.getNodeValue());
System.out.println("name = " + nameAtt.getNodeValue());
}
}
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
}
将输出...
id = 0
name = a
id = 1
name = b
使用XPath可以大大减少所有这些,例如,如果所有item
节点都是同一个名称,那么你可以使用
/items/item
作为查询。如果节点名称不同,但属性相同,则可以使用
/items/*[@id]
将列出items
下具有id
属性的所有节点,或
/items/*[@name]
将列出items
下具有name
属性...
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Test {
public static void main(String[] args) {
try (InputStream is = Test.class.getResourceAsStream("/Test.xml")) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(is);
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expression = xpath.compile("/items/item");
NodeList nodes = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
process(nodes);
expression = xpath.compile("/items/*[@id]");
nodes = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
process(nodes);
expression = xpath.compile("/items/*[@name]");
nodes = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
process(nodes);
} catch (Exception exp) {
exp.printStackTrace();
}
}
protected static void process(NodeList nodes) {
for (int index = 0; index < nodes.getLength(); index++) {
Node item = nodes.item(index);
NamedNodeMap attributes = item.getAttributes();
Node idAtt = attributes.getNamedItem("id");
Node nameAtt = attributes.getNamedItem("name");
System.out.println("id = " + idAtt.getNodeValue() + "; name = " + nameAtt.getNodeValue());
}
}
}