带有重复标记的XPath和Java

时间:2012-10-19 01:27:09

标签: java xml xpath tags

我在使用Java解析XML文件时遇到了一些麻烦。该文件采用以下形式:

<root>
  <thing>
    <name>Thing1</name>
    <property>
      <name>Property1</name>
    </property>
    ...
  </thing>
  ...
</root>

最后,我想将此文件转换为Thing对象列表,其中包含一个String名称(Thing1)和一个Property对象列表,每个对象都有一个名称(Property1)。

我一直在尝试使用xpath来获取这些数据,但是当我试图获得'thing'的名称时,它会给我所有出现在'thing'中的名字,包括那些'酒店的。我的代码是:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document dom = db.parse(filename);
XPath xpath = XPathFactory.newInstance().newXPath();


XPathExpression thingExpr = xpath.compile("//thing");
NodeList things = (NodeList)thingExpr.evaluate(dom, XPathConstants.NODESET);
for(int count = 0; count < things.getLength(); count++)
{
    Element thing = (Element)things.item(count);
    XPathExpression nameExpr = xpath.compile(".//name/text()");
    NodeList name = (NodeList) nameExpr.evaluate(thing, XPathConstants.NODESET);
    for(int i = 0; i < name.getLength(); i++)
    {
        System.out.println(name.item(i).getNodeValue());    
    }
}

有人可以帮忙吗?提前谢谢!

3 个答案:

答案 0 :(得分:1)

您可以尝试类似......

public class TestXPath {

    public static void main(String[] args) {
        String xml =
                        "<root>\n"
                        + "    <thing>\n"
                        + "        <name>Thing1</name>\n"
                        + "        <property>\n"
                        + "            <name>Property1</name>\n"
                        + "        </property>\n"
                        + "        <property>\n"
                        + "            <name>Property2</name>\n"
                        + "        </property>\n"
                        + "        <property>\n"
                        + "            <name>Property3</name>\n"
                        + "        </property>\n"
                        + "        <property>\n"
                        + "            <name>Property4</name>\n"
                        + "        </property>\n"
                        + "        <property>\n"
                        + "            <name>Property5</name>\n"
                        + "        </property>\n"
                        + "    </thing>/n"
                        + "    <NoAThin>\n"
                        + "        <name>Thing2</name>\n"
                        + "        <property>\n"
                        + "            <name>Property1</name>\n"
                        + "        </property>\n"
                        + "        <property>\n"
                        + "            <name>Property2</name>\n"
                        + "        </property>\n"
                        + "        <property>\n"
                        + "            <name>Property3</name>\n"
                        + "        </property>\n"
                        + "        <property>\n"
                        + "            <name>Property4</name>\n"
                        + "        </property>\n"
                        + "        <property>\n"
                        + "            <name>Property5</name>\n"
                        + "        </property>\n"
                        + "    </NoAThin>/n"
                        + "</root>";

        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
            Document dom = db.parse(bais);
            XPath xpath = XPathFactory.newInstance().newXPath();

            // Find the "thing" node...
            XPathExpression thingExpr = xpath.compile("/root/thing");
            NodeList things = (NodeList) thingExpr.evaluate(dom, XPathConstants.NODESET);

            System.out.println("Found " + things.getLength() + " thing nodes...");

            // Find the property nodes of thing
            XPathExpression expr = xpath.compile("property");
            NodeList nodes = (NodeList) expr.evaluate(things.item(0), XPathConstants.NODESET);

            System.out.println("Found " + nodes.getLength() + " thing/property nodes...");

            // Find all the property "name" nodes under thing
            expr = xpath.compile("property/name");
            nodes = (NodeList) expr.evaluate(things.item(0), XPathConstants.NODESET);

            System.out.println("Found " + nodes.getLength() + " name nodes...");
            System.out.println("Property value = " + nodes.item(0).getTextContent());

            // Find all nodes that have property nodes
            XPathExpression exprAll = xpath.compile("/root/*/property");
            NodeList nodesAll = (NodeList) exprAll.evaluate(dom, XPathConstants.NODESET);
            System.out.println("Found " + nodesAll.getLength() + " property nodes...");

        } catch (Exception exp) {
            exp.printStackTrace();
        }
    }
}

这将为您提供类似

的输出
Found 1 thing nodes...
Found 5 thing/property nodes...
Found 5 name nodes...
Property value = Property1
Found 10 property nodes...

答案 1 :(得分:0)

"//thing/name/text()"怎么样?

现在name之前的双斜线表示“树中的任何位置,不一定是直接的子节点”。

答案 2 :(得分:0)

使用这些XPath表达式

//thing[name='Thing1']

这将选择XML文档中的任何thing元素,该元素具有name子元素,其字符串值为"Thing1"

也可以

//property[name='Property1']

这将选择XML文档中的任何property元素,该元素具有name子元素,其字符串值为"Property1"

<强>更新

要获取所有包含thing元素字符串值的文本节点,只需执行

//thing/text()

在XPath 2.0中,可以使用以下方法获取字符串序列:

//thing/string(.)

使用单个XPath表达式是不可能的,但是可以得到特定(第n个)thing元素的字符串值,如下所示:

string((//thing)[$n])

其中$n必须替换为从1到count(//thing)的特定数字。

因此,在您的编程语言中,您可以通过评估此XPath表达式来确定cnt

count(//thing)

然后在$n的循环中从1到cnt动态生成xpath表达式并对其进行评估:

string((//thing)[$n])

获取property元素的所有值完全相同。