选择属性值为self或descendant但不“overruled”的元素(如lang属性)

时间:2012-03-11 19:08:40

标签: php xpath

我试图模仿类似于HTML或lang的{​​{1}}属性的解释。

给出以下XML块:

xml:lang

我在制定XPath 1.0表达式时遇到问题,该表达式返回特定语言的所有节点,让我们说<xml lang="c"> c#0 <para>c#1</para> <para>c#2</para> <para lang="d"> d#0 <para>d#1</para> <para lang="c">c#3</para> <para lang="d"> d#2 <para>d#3</para> <para lang="c">c#4</para> </para> <para lang="c"> c#5 <para>c#6</para> </para> </para> </xml> 。节点匹配类似于xpath c函数匹配的lang()属性:

  1. 它的属性xml:lang的值为langc
  2. -OR-
    1. 其中一位家长拥有//*[@lang = "c"]属性,其值langc
    2. -AND-节点本身没有//*[ancestor::*/@lang = "c"]属性
    3. -AND NOT-如果其中任何父节点的lang属性定义为lang以外的更多&#34;接近&#34;比具有c属性lang的父级(2.1是&#34;否决&#34; )。
  3. 与上述XML的示例匹配和c的{​​{1}}示例匹配将提供7个节点:c#0到c#6。

    c

    我在xpath查询中描述这个问题。在过去的一年里,即使我用xpath做得更好,这个真的让我失望了。

    无论我尝试什么,我都有问题来描述一个祖先的覆盖性质,其中匹配谓词的祖先与不匹配的谓词。

    给出的示例甚至只是问题的一半,因为不仅有完整的属性值匹配,而且还有起始的匹配:

    lang

    但我很高兴看到首先解决了推翻问题。我用PHP(Online Demo)测试:

    <xml lang="c"> c#0 ...              (direct match, lang="c")
    <para>c#1</para>                    (parent has lang="c")
    <para>c#2</para>                    (parent has lang="c")
    <para lang="c">c#3</para>           (direct match, lang="c")
    <para lang="c">c#4</para>           (direct match, lang="c")
    <para lang="c"> c#5 ...             (direct match, lang="c")
    <para>c#6</para>                    (parent has lang="c", that parent is descending of 
                                         any other ancestor with lang="d")
    

2 个答案:

答案 0 :(得分:2)

使用

//*[@lang='c'
  or
   not(@lang) and ancestor::*[@lang][1]/@lang = 'c'
   ]

这将选择XML文档中具有值为lang的{​​{1}}属性或没有"c"属性且lang的值的任何元素具有lang属性的第一个祖先的属性是lang

更简单的等效XPath表达式

"c"

以下是使用XPath Visualizer 执行选择的快照:

enter image description here

答案 1 :(得分:1)

您预期的XPath

//*[(descendant-or-self::*/@lang = 'c' and not(descendant-or-self::*/@lang != 'c')) or (ancestor-or-self::*/@lang = 'c' and not(ancestor-or-self::*/@lang != 'c'))]

输出

xml     c#0 (lang: c)
para    c#1 (lang: c)
para    c#2 (lang: c)
para    c#3 (lang: c)