1

I am trying to use a single XPath expression to select a node that has a child node which matches another node in the document.

A match would mean that ALL attributes of the node are the same. So if a node was being compared with several attributes doing individual attribute comparisons would be unmaintainable.

As an example given the following:

<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>

I want to get the service node from Services based on the ServiceDetails listed under MyMachine.

I thought it would look something like:

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

but it doesn't seem to work. I suspect the '=' operator isn't handling the node comparison correctly. I think there are some XPath 2.0 Methods that might work but I am using .NET 4.0 (System.XML namespace) I do not know if I can use them. If XPath 2.0 methods would help here I would really appreciate an explanation on how to use them in .Net 4.0.

Thanks

1
  • Are you trying to get the <Service> under <Services> by matching the @Description attributes from both <ServiceDetails>? (This would work in that case: /Network/Services/Service[ServiceDetails/@Description = /Network/Machines/Machine[@Name='MyMachine']/Services/ServiceDetails/@Description] ) Commented Sep 21, 2011 at 23:39

2 Answers 2

4

Use:

/*/Services/Service
            [ServiceDetails/@Description 
            = 
             /*/Machines/Machine[@Name = "MyMachine"]
                          /Services/ServiceDetails/@Description
            ]
Sign up to request clarification or add additional context in comments.

6 Comments

@DevNull: Absolutely -- I saw your comment and decided to give my answer -- when I wrote it completely, I saw that it is almost identical to the expression in your comment. However, it deserves to be an answer -- not a comment. Please, create an answer with this expression, then I'll delete mine :)
I was hoping the OP would clarify the question before I answered since the XML example doesn't match the explanation of what was trying to be matched. One answer is sufficient; I will just upvote yours since I'm in agreement. :-)
Thanks -- in this case I will have a look at all your answers -- sure there will be some good one I hadn't seen before that I could upvote.
Thanks for the reply but the comparison for the question is regarding the entire node. In the example above I would want to make sure the Description and Version were both correct. Given your examples I might be able to concatenate the attribute comparisons but that would quickly become unmanageable. Is there a way to find out if the entire node matches? However, if there are several attributes or children to this node these expressions would get extremely large rather quickly. Is there a way to check if the nodes match rather than walk through each attribute and child?
@AAADad: You need to define what is meant by "entire nodes match". There is a term "node equality" and in XPath 2.0 there is a finction deep-equal(). If you need only "shallow equality" (attribute count names and corresponding values to be identical, I think this can be done with an XPath expression.
|
0

Try this will validate all attribute values are equal in both the elements then it is true:

/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)]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.