【问题标题】:xpath of xmllint outputxmllint 输出的 xpath
【发布时间】:2016-02-22 00:15:00
【问题描述】:

我有一些想要执行 xquery 操作的 xml 文档。通过返回与查询匹配的节点,xmllint 似乎几乎可以满足我的要求。这对我没有帮助,因为这个节点可能存在很多地方,我不知道匹配在哪里。

一个非常简单的例子是 xmllint -xpath '//shutdown[text()="false"]' 返回:<shutdown>false</shutdown><shutdown>false</shutdown><shutdown>false</shutdown><shutdown>false</shutdown><shutdown>false</shutdown>

这告诉我有匹配的节点,但不告诉我哪些节点。有什么方法可以获取返回节点的实际 xpath 吗?我什么都没找到。

虽然给出的示例也可以在编辑器中对 xml 文档进行 greping 操作,但这种方法对于更复杂的查询是不可能的。

【问题讨论】:

  • fn:path() (w3.org/TR/xpath-functions-30/#func-path) 是您正在寻找的。但是,这是 XQuery 3.0,我认为 xmllint 不支持它。如果您不必使用此工具,BaseX 和 eXist 是两个开源 XQuery 3.0 处理器。 basex -q '//shutdown[text()="false"]/path()' 做什么工作。
  • 谢谢,我会调查这些组件。

标签: xml xpath xmllint


【解决方案1】:

test.xml 的内容:

<l0>
<l1>
    <l1-1>
        <shutdown>true</shutdown>
    </l1-1>
    <l1-2>
        <shutdown>false</shutdown>
    </l1-2>
</l1>
<l2>
    <l2-1>
        <shutdown>false</shutdown>
    </l2-1>
</l2></l0>

Shell 脚本:

#!/bin/s

xpath="//shutdown[text()='false']"
count=$(echo "xpath ${xpath}" |xmllint --shell test.xml |grep ELEMENT|wc -l)

x=1
while [ $x -lt `expr $count + 1` ]
do
    parents=`       echo "xpath (${xpath})[${x}]/ancestor::*" | \
                    xmllint --shell test.xml| \
                    grep "ELEMENT" |\
                    sed "s/.*ELEMENT//"|\
                    sed ':a;N;$!ba;s/\n/ -> /g'`
    echo "${parents} -> shutdown(false)[${x}]"
    x=`expr $x + 1`
done

结果:

 l0 ->  l1 ->  l1-2 -> shutdown(false)[1]
 l0 ->  l2 ->  l2-1 -> shutdown(false)[2]

【讨论】:

  • 谢谢。我试过了,但显然我们设备上加载的 xmllint 没有 --shell 选项。我需要看看是否可以使用具有该选项的版本加载它。
  • 没问题。让我看看我是否可以在没有该选项的情况下重写它。但是,如果您可以升级,您将获得一些不错的功能。
  • OK.. 我能够得到您正在寻找的结果,但它是一个更大的包装程序 - 每次都附加 /.. 并向上走。这既麻烦又丑陋。如果您需要使用 xmllint,那么我认为您需要内置 shell 的版本。另外,请记住,还有其他命令行 XML 工具可能会以更简单的方式满足您的需求。
【解决方案2】:

xmllint 支持的普通 XPath 1.0 无法做到这一点(它不支持 XQuery,因为您标记了问题!)。 XPath 3.0(以及 XQuery 3.0)将支持@dirkk 提议的fn:path($element)。 XPath 1.0 只能用于选择整个子树(包括单个元素、文本节点、属性等),但不能从您的 XML 文档中创建新结果。

您必须使用更强大的语言(如 XQuery 或其他任何语言)来进一步处理 ancestor-or-self 轴步骤的 XPath 结果,其中包含路径上的所有元素并连接元素名称:

一个 XQuery 示例:

string-join(
  (
    (: root node :)
    "",
    (: following steps :)
    for $step in //path/to/element/ancestor-or-self::*
    return name($step)
  ),
  "/"
)

可以使用任意脚本语言执行类似的操作,我还提出了PHP equivalent in another question,另外甚至可以对特定路径使用位置谓词(这可以很容易地再次从代码中删除)。

【讨论】:

  • 对不起,XQUERY 标签不好,我只是把它当作一个查询。以后谈的时候一定要直截了当。
猜你喜欢
  • 1970-01-01
  • 2014-12-29
  • 2012-08-12
  • 2021-01-16
  • 2012-07-22
  • 2019-02-10
  • 2012-01-06
  • 2021-08-11
  • 1970-01-01
相关资源
最近更新 更多