xpath / Потомок-или-Сам - Поиск узла в определенном дереве

Я читаю о сокращении "//", которое, по-видимому, является сокращением для:

"/ Потомок или-я"

ясно, что ожидать, скажем, от простого примера такого выражения, например,

// MyNode

Он вернет список узлов всех экземпляров в документе, найденных из корня, элементов с именем "myNode".

Однако в чем смысл более сложного выражения, такого как:

// аноде // MyNode

?

Поскольку // (являясь сокращением для "/ Потомок-или-Сам") дважды совпадает с корневым узлом, означает ли это, что первая часть выражения "// aNode" является избыточной и только увеличивает время, необходимое для завершения выполнение выражения (после того, как все еще только найдены все выражения во всем документе "myNode")?

"// myNode" и "// aNode // myNode" приведут к тому же результату?

Наконец, если бы я искал в документе экземпляр узла "myNode", который был косвенным потомком узла "интересного дерева ". Но я не хочу, чтобы экземпляр узла 'myNode' являлся косвенным потомком узла 'nonInterestingTree', как мне это сделать?

например, поиск в документе:

<root>
    <anode>
        <interestingTree>
            <unknownTree>
                <myNode/><!-- I want to find this one, not the other, where I don't know the path indicated by 'unknownTree' -->
            </unknownTree>
        </interestingTree>
        <nonInterestingTree>
            <unknownTree>
                <myNode/>
            </unknownTree>
        </nonInterestingTree>
    </anode>
    <anode>
        <someOtherNode/>
    </anode>
</root>

Спасибо!

2 ответа

Решение

"//myNode" и "//aNode//myNode" приведут к тому же результату?

Да, в этом случае, потому что все myNodes также являются потомками anode, Однако в общем смысле //aNode//myNode очевидно, не будет соответствовать узлам, которые не имеют anode родитель в их дереве предка.

Xpath:

//aNode//myNode

будет игнорировать любую промежуточную иерархию между aNode а также myNodeбудет соответствовать /aNode/myNode, /anyNodes/anode/myNode, а также /anyNodes/anode/xyzNode/myNode

Который отвечает на ваш последний вопрос, вы можете найти узлы в интересующем подпути следующим образом: (и снова, игнорируя любые промежуточные элементы в иерархии)

//anode//interestingTree//myNode

в идеале, конечно, вы должны быть как можно более явными со своим путем, // может повлечь за собой снижение производительности из-за потенциально большого количества элементов, необходимых для поиска.

Редактировать Возможно, это помогает?

Я настроил ваш ввод XML для ясности:

<root>
    <anode>
        <interestingTree>
            <unknownTree>
                <myNode>
                    MyNode In Interesting Tree
                </myNode>
            </unknownTree>
        </interestingTree>
        <nonInterestingTree>
            <unknownTree>
                <myNode>
                    MyNode In Non-Interesting Tree
                </myNode>
            </unknownTree>
        </nonInterestingTree>
    </anode>
    <anode>
        <someOtherNode/>
    </anode>
    <bnode>
        <myNode>
            MyNode in BNode
        </myNode>
    </bnode>
</root>

Когда анализируется через таблицу стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        Matched by `//myNode`
        <xsl:apply-templates select="//myNode">
        </xsl:apply-templates>

        Matched by `//aNode//myNode`
        <xsl:apply-templates select="//anode//myNode">
        </xsl:apply-templates>

        Matched by `//aNode//interestingTree//myNode`
        <xsl:apply-templates select="//anode//interestingTree//myNode">
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="myNode">
        <xsl:value-of select="text()"/>
    </xsl:template>
</xsl:stylesheet>

Возвращает следующее:

Matched by `//myNode`
        MyNode In Interesting Tree
        MyNode In Non-Interesting Tree
    MyNode in BNode

Matched by `//aNode//myNode`
        MyNode In Interesting Tree
        MyNode In Non-Interesting Tree

Matched by `//aNode//interestingTree//myNode`
        MyNode In Interesting Tree

Вы спрашиваете: "//myNode" и "//aNode//myNode" в результате получат одно и то же?"

Не обязательно. Первый вернет все элементы с именем myNode в документе; вторая вернет все элементы с именем myNode которые происходят как потомки элементов с именем aNode, В вашем примере XML эти два описания определяют один и тот же набор, но в некоторых документах XML они не будут.

Выражения //aNode//myNode а также //myNode[ancestor::aNode]с другой стороны, всегда будет возвращать один и тот же набор узлов.

Другие вопросы по тегам