ChatGPT解决这个技术问题 Extra ChatGPT

XPath:从子节点获取父节点

我需要获取子节点 title 50 的父节点

目前我只使用

//*[title="50"]

我怎么能得到它的父母?结果应该是 store 节点。

<?xml version="1.0" encoding="utf-8"?>
<d:data xmlns:d="defiant-namespace" d:mi="23">
    <store d:mi="22">
        <book price="12.99" d:price="Number" d:mi="4">
            <title d:constr="String" d:mi="1">Sword of Honour</title>
            <category d:constr="String" d:mi="2">fiction</category>
            <author d:constr="String" d:mi="3">Evelyn Waugh</author>
        </book>
        <book price="8.99" d:price="Number" d:mi="9">
            <title d:constr="String" d:mi="5">Moby Dick</title>
            <category d:constr="String" d:mi="6">fiction</category>
            <author d:constr="String" d:mi="7">Herman Melville</author>
            <isbn d:constr="String" d:mi="8">0-553-21311-3</isbn>
        </book>
        <book price="8.95" d:price="Number" d:mi="13">
            <title d:constr="String" d:mi="10">50</title>
            <category d:constr="String" d:mi="11">reference</category>
            <author d:constr="String" d:mi="12">Nigel Rees</author>
        </book>
        <book price="22.99" d:price="Number" d:mi="18">
            <title d:constr="String" d:mi="14">The Lord of the Rings</title>
            <category d:constr="String" d:mi="15">fiction</category>
            <author d:constr="String" d:mi="16">J. R. R. Tolkien</author>
            <isbn d:constr="String" d:mi="17">0-395-19395-8</isbn>
        </book>
        <bicycle price="19.95" d:price="Number" d:mi="21">
            <brand d:constr="String" d:mi="19">Cannondale</brand>
            <color d:constr="String" d:mi="20">red</color>
        </bicycle>
    </store>
</d:data>

R
René Link

parent axes 与父节点的名称一起使用。

//*[title="50"]/parent::store

如果它是 store,则此 XPath 只会选择父节点。

但您也可以使用其中一种

//*[title="50"]/parent::*
//*[title="50"]/..

这些 xpath 将选择任何父节点。因此,如果文档发生更改,您将始终选择一个节点,即使它不是您期望的节点。

编辑

在给定示例中,如果父项是自行车,但父项的父项是商店,会发生什么情况?它上升吗?

不,只有当它是匹配 //*[title="50"] 的节点的父节点时才会选择存储。

如果没有,是否有一种方法可以在这种情况下上升,如果没有这样的父级,则返回 None ?

是的,您可以使用 ancestor 个坐标轴

//*[title="50"]/ancestor::store

这将选择与 //*[title="50"] 匹配的节点的所有祖先,即 `stores.例如

<data xmlns:d="defiant-namespace" d:mi="23">
    <store mi="1">
        <store mi="22">
            <book price="8.95" d:price="Number" d:mi="13">
                <title d:constr="String" d:mi="10">50</title>
                <category d:constr="String" d:mi="11">reference</category>
                <author d:constr="String" d:mi="12">Nigel Rees</author>
            </book>
        </store>
    </store>
</data>

https://i.stack.imgur.com/uzcSX.png


您还可以使用 parent::* 缩写语法 ..(例如://*[title="50"]/..)或嵌套谓词(例如://*[*[title="50"]]
或者 parent::node() 对应于快捷方式 .. 并且在我看来更好。事实上 parent::* 仅限于轴的主要节点类型,在大多数情况下这不是问题。
如果您正在使用尝试 .xpath('..')xpath('parent::node()')
“如果它是一个商店,这个 XPath 只会选择父节点。” - 在给定示例中,如果父项是 bicycle,但父项的父项是 store,会发生什么情况?它上升吗?如果没有,是否有一种方法可以在这种情况下上升并在没有这样的父级时返回 None
A
Aminah Nuraini

作为替代方案,您可以使用 ancestor

//*[title="50"]/ancestor::store

它比 parent 更强大,因为它甚至可以得到祖父母或曾曾祖父母


它不是“更强大”。只是不同而已。因此,轴的选择取决于用例。
@LudovicKuty 它更“灵活”,你现在“快乐”了吗?
不,这是错误的。从 op 的 xpath 来看,他要求的是父母,而不是祖先。
k
kjhughes

对旧的常见问题的新的改进答案......

我怎么能得到它的父母?结果应该是存储节点。

使用谓词而不是 parent:: 或祖先:: 轴

此处的大多数答案选择 title,然后向上遍历到目标父或祖先 (store) 元素。一种更简单、直接的方法是首先直接选择父元素或祖先元素,无需遍历 parent::ancestor:: 轴:

//*[book/title = "50"]

如果中间元素名称不同:

//*[*/title = "50"]

或者,在名称和深度上:

//*[.//title = "50"]

p
phduarte

您也可以使用表达式末尾的两个点。看这个例子:

//*[title="50"]/..