【问题标题】:XPath and Java with Repeated Tags带有重复标记的 XPath 和 Java
【发布时间】:2012-10-19 01:27:09
【问题描述】:

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

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

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

我一直在尝试使用 xpaths 来获取这些数据,但是当我尝试只获取 '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());    
    }
}

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

【问题讨论】:

  • 您似乎没有准确地表达您想要使用 XPath 生成的内容——即使考虑了 cmets。 Xpath 用于选择我们感兴趣的一些特定节点——在您的特定情况下它们是哪些?您想从这些特定节点中提取哪些数据?请编辑问题并指定此缺失的重要信息。

标签: java xml xpath tags


【解决方案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...

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 这确实让我得到了所有的名字,但如果我以后对属性名称做同样的事情,我不知道如何匹配它们:/。稍后我确实使用了“.//”,因为有人告诉我这是相对的 xpath。
    【解决方案3】:

    使用这些 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 元素的所有值也是如此。

    【讨论】:

    • 假设我已经知道事物的名称,但我不知道...这就是我要找的 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-27
    • 2014-10-19
    • 1970-01-01
    • 2016-07-11
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多