从复杂空元素中解析XML属性

时间:2014-08-18 08:35:14

标签: java xml

我有一个以下模式的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并获取属性。我该如何解析属性?

2 个答案:

答案 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());
        }
    }

}