Akshay Gaur
Akshay Gaur

Reputation: 2515

Select a node the sibling of which has a specific child

This is the XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<multistatus
xmlns="DAV:">
<response>
    <href>/1437425399/carddavhome/</href>
    <propstat>
        <prop>
            <resourcetype>
                <collection/>
            </resourcetype>
        </prop>
        <status>HTTP/1.1 200 OK</status>
    </propstat>
</response>
<response>
    <href>/1437425399/carddavhome/card/</href>
    <propstat>
        <prop>
            <resourcetype>
                <addressbook
                    xmlns="urn:ietf:params:xml:ns:carddav"/>
                    <collection/>
                </resourcetype>
            </prop>
            <status>HTTP/1.1 200 OK</status>
        </propstat>
    </response>
</multistatus>

I want to select the < href > /1437425399/carddavhome/card/< /href > whose sibling < propstat > has the < addressbook > child element.

I tried the following:

XNamespace nsdav = "DAV:";
XNamespace nscd = "urn:ietf:params:xml:ns:carddav";
var hrefs = from response in root.Elements(nsdav + "response")
            where response.Elements(nscd + "addressbook") != null
            select response.Element(nsdav + "href");

and

var hrefs = from response in root.Elements(nsdav + "response")
            where response.Elements(nscd + "addressbook").Count() > 0
            select response.Element(nsdav + "href");

and

var hrefs = (from href in root.Descendants(nsdav + "href")
            where href.Parent.Elements(nscd + "addressbook").Count() > 0
            select href.Ancestors()).First()

and maybe some other similar logic but can't get the result that I am looking for. Where am I going wrong?

I am either getting both the < response > tags in the final result or none. I want to be able to select just the one node.

**EDIT I won't know in advance the text within < href > I want to select. Only thing I know is that I have to select the text of the < href > whose sibling has the < addressbook > node as its child.

Upvotes: 0

Views: 80

Answers (2)

Uttam Gupta
Uttam Gupta

Reputation: 418

You can use below code

public static XmlNode SelectXmlNode()
    {
        XmlNode addNode=null;
        string xmlString = "*xmlString*"
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(xmlString);
        var node = doc.ChildNodes;
        var siblings = node[0].NextSibling.ChildNodes;
        foreach (XmlNode cnode in siblings)
        {
                var childnode = cnode.ChildNodes[0].NextSibling.ChildNodes[0].ChildNodes[0].FirstChild;
                if (childnode.Name == "addressbook")
                {
                    addNode = cnode.ChildNodes[0];
                }  

        }

        return addNode;
    }

Upvotes: 3

Akshay Gaur
Akshay Gaur

Reputation: 2515

Ok, so I finally figured it out. My main problem was checking for existence of a particular child element and I was using null and count for that. However, linq to xml doesn't work that way. To check for existence of an element, you have to use "Any" like so:

var hrefs = from response in root.Elements(nsdav + "response")
            where 
                 (from addressbook in response.Descendants(nscd + "addressbook")
                 select addressbook)
                 .Any()
            select response.Element(nsdav + "href").Value;

And this is how I got the result I wanted.

Upvotes: 0

Related Questions