代码之家  ›  专栏  ›  技术社区  ›  Mat Walker

XPath返回同一级别上的所有元素

  •  2
  • Mat Walker  · 技术社区  · 11 年前

    我正在尝试从 <a id='me'>match</a> 这将匹配处于同一级别的元素。兄弟姐妹、堂姐妹、二堂姐妹等。。。

    使用以下XML <a id=“me”>匹配</a> 返回同一级别上的所有元素,其id属性为“me”:-

    <alpha>
        <beta>
            <gamma1>
                <a id='me'>match</a>
                <a id='me'>match me too</a>
                <b id='me'>no match</b>
            </gamma1>
            <gamma2>
                <a id='notme'>no match</a>
                <a id='me'>match</a>
                </b>
            </gamma2>
        </beta>
        <delta>
            <epsilon>
                <a id='notme'>no match</a>
                <a id='me'>match</a>
                </b>
                <foo>
                    <a id='me'>no match</a>
                </foo>
            </epsilon>
        </delta>
        <bar>
          <a id='me'>no match</a>
        </bar>
    </alpha>
    

    .\..\a[@id='me'] 将返回两个元素 <gamma1> .\..\..\*\a[@id='me'] 将返回匹配的元素 <γ1> <gamma2> 然而,我正在尝试使用XPath来返回文档中同一级别上的所有匹配元素,而与它们的深度无关。

    我可以在代码中循环,通过构建动态xpath来上下循环,但这不会很优雅,可能需要很长时间才能运行。。

    有什么想法吗?

    2 回复  |  直到 9 年前
        1
  •  2
  •   Mathias Müller    11 年前

    Lingamuthy已经给出的答案是完全正确的,但我想指出另一种看待问题的方式。您解释了以某个节点为起点计算XPath表达式, /alpha/beta/gamma1/a[1] 。因此,我假设您知道该节点的准确位置,即使不知道文档的其他信息。

    如果这在您的情况下成立,您可以简单地计算该节点的祖先(遵循 ancestor::* 轴),仅选择 a 祖先数量相同的元素:

    //a[@id = 'me' and count(ancestor::*) = count(/alpha/beta/gamma1/a[1]/ancestor::*)]
    

    结果将是(单个结果由 --------- ):

    <a id="me">match</a>
    -----------------------
    <a id="me">match me too</a>
    -----------------------
    <a id="me">match
    </a>
    -----------------------
    <a id="me">match
    </a>
    

    再次用另一个答案中所示的技术排除该列表中的第一个结果, (...)[position() != 1] ,如果这对你很重要的话。

    顺便说一下:您的输入XML无效,有两个 未正确关闭的元件。

        2
  •  1
  •   Mathias Müller    11 年前

    怎么样:

    (../../*/a[@id = 'me'])[position() != 1]
    

    在这里,xpath选择上下文节点的父节点的所有子节点,并使用 position() != 1 ,它会删除上下文节点本身(假设上下文节点是列表中的第一个,正如您在问题中提到的那样)。