XPath: выбор узла на основе значения другого узла

Я пытаюсь использовать одно выражение XPath для выбора узла, у которого есть дочерний узел, соответствующий другому узлу в документе.

Совпадение будет означать, что ВСЕ атрибуты узла совпадают. Таким образом, если узел сравнивался с несколькими атрибутами, сравнение отдельных атрибутов было бы невозможным.

В качестве примера приведено следующее:

<Network>
    <Machines>
        <Machine Name = "MyMachine">
            <Services>
                 <ServiceDetails Description="MyService" Executable="c:\Myservice.exe" DisplayName="My Service" Version="5"/>
            </Services>
        </Machine>
        ...
    </Machines>
    <Services>
        <Service Name = "Service1">
            <ServiceDetails Description="MyService" Executable="c:\Myservice.exe" DisplayName="My Service" Version="5"/>
        </Service>
        ...
    </Services>
</Network>

Я хочу получить служебный узел из служб на основе ServiceDetails, перечисленных в разделе MyMachine.

Я думал, что это будет выглядеть примерно так:

//Services/Service[ServiceDetails = //Machines/Machine[@Name='MyMachine']/ServiceDetails]

но, похоже, это не работает. Я подозреваю, что оператор '=' неправильно обрабатывает сравнение узлов. Я думаю, что есть некоторые методы XPath 2.0, которые могут работать, но я использую .NET 4.0 (пространство имен System.XML). Я не знаю, смогу ли я их использовать. Если бы здесь помогли методы XPath 2.0, я был бы очень признателен за объяснение того, как их использовать в .Net 4.0.

Спасибо


person AAADad    schedule 21.09.2011    source источник
comment
Вы пытаетесь получить <Service> под <Services>, сопоставляя атрибуты @Description из обоих <ServiceDetails>? (В этом случае это сработает: /Network/Services/Service[ServiceDetails/@Description = /Network/Machines/Machine[@Name='MyMachine']/Services/ServiceDetails/@Description] )   -  person Daniel Haley    schedule 22.09.2011


Ответы (2)


Использование:

/*/Services/Service
            [ServiceDetails/@Description 
            = 
             /*/Machines/Machine[@Name = "MyMachine"]
                          /Services/ServiceDetails/@Description
            ]
person Dimitre Novatchev    schedule 22.09.2011
comment
@DevNull: Абсолютно - я увидел ваш комментарий и решил дать свой ответ - когда я написал его полностью, я увидел, что он почти идентичен выражению в вашем комментарии. Однако это заслуживает ответа, а не комментария. Пожалуйста, создайте ответ с этим выражением, тогда я удалю свой :) - person Dimitre Novatchev; 22.09.2011
comment
Я надеялся, что ОП разъяснит вопрос, прежде чем я отвечу, поскольку пример XML не соответствует объяснению того, что пытались сопоставить. Достаточно одного ответа; Я просто проголосую за вас, так как я согласен. :-) - person Daniel Haley; 22.09.2011
comment
Спасибо - в этом случае я посмотрю на все ваши ответы - обязательно найдется какой-нибудь хороший, которого я раньше не видел, за который я мог бы проголосовать. - person Dimitre Novatchev; 22.09.2011
comment
Спасибо за ответ, но сравнение вопроса касается всего узла. В приведенном выше примере я хотел бы убедиться, что описание и версия были правильными. Учитывая ваши примеры, я мог бы объединить сравнения атрибутов, но это быстро стало бы неуправляемым. Есть ли способ узнать, совпадает ли весь узел? Однако, если у этого узла есть несколько атрибутов или дочерних элементов, эти выражения довольно быстро станут очень большими. Есть ли способ проверить, совпадают ли узлы, а не просматривать каждый атрибут и дочерний элемент? - person AAADad; 22.09.2011
comment
@AAADad: вам нужно определить, что подразумевается под совпадением целых узлов. Существует термин равенство узлов, а в XPath 2.0 есть функция deep-equal(). Если вам нужно только поверхностное равенство (имена счетчиков атрибутов и соответствующие значения должны быть идентичными, я думаю, что это можно сделать с помощью выражения XPath. - person Dimitre Novatchev; 23.09.2011
comment
@AAADad: Кроме того, нет никакой реализации XPath 2.0 для .NET (SQL Server XQuery реализует версию WD - не окончательная рекомендация). Вы можете использовать любой существующий процессор XSLT 2.0 или XQuery 2.0 стороннего производителя. Из них XQSharp и Saxon.NET специально предназначены для использования в среде .NET. - person Dimitre Novatchev; 23.09.2011

Попробуйте это, чтобы проверить, что все значения атрибутов равны в обоих элементах, тогда это правда:

/Network[(descendant::ServiceDetails/@Description = /Network//Machine[@Name = "MyMachine"]/Services/ServiceDetails/@Description) and (descendant::ServiceDetails/@Executable = /Network//Machine[@Name = "MyMachine"]/Services/ServiceDetails/@Executable) and (descendant::ServiceDetails/@DisplayName = /Network//Machine[@Name = "MyMachine"]/Services/ServiceDetails/@DisplayName) and (descendant::ServiceDetails/@Version = /Network//Machine[@Name = "MyMachine"]/Services/ServiceDetails/@Version)]
person Yogib    schedule 01.09.2020