sandeep.mishra
sandeep.mishra

Reputation: 825

Get child node attribute value based on parent node attribute value

I have a xml given below

 <session xmlns="http://test.net/schema/session/1.0" name="test" start="2015-07-01T07:20:31.425Z">

  <download>
    <filename value="/UAT/Incoming/ Status/Archive/8-22-2011 3-20-14 PM306.xml" />
    <result success="false">
      <message>Timeout waiting .</message>
    </result>
  </download>
</session>

I want to select the message node value only if Result node value is false. I donot want to check on hard coded parent node like node download because it may change

Can anyone help me please..

Upvotes: 2

Views: 1755

Answers (4)

Enigmativity
Enigmativity

Reputation: 117009

This worked for me:

XNamespace ns = XNamespace.Get("http://test.net/schema/session/1.0");

IEnumerable<XElement> failures =
    doc
        .Descendants(ns + "download")
        .Concat(doc.Descendants(ns + "upload"))
        .Elements(ns + "result")
        .Elements(ns + "message")
        .Where(e => e.Parent.Attributes("success").Any(a => !(bool)a));

From your input I got this:

result

Upvotes: 2

Rahul Singh
Rahul Singh

Reputation: 21795

First of all you need to set the namespace for your XML file like this:-

XNamespace ns = "http://test.net/schema/session/1.0";

I will start looking into descendants of download because I need to find the result element which contains the success attribute (whose value we want to check). Thus, a simple where condition will filter those nodes for us and finally we can select the message node.

Update:

You can use Concat if you want to search both download & upload like this:-

IEnumerable<XElement> result = xdoc.Descendants(ns + "download")
                                 .Concat(xdoc.Descendants(ns + "upload"))
              .Where(x => x.Element(ns + "result") != null && 
                  (string)x.Element(ns + "result").Attribute("success") == "false")
              .Select(x => x.Element(ns +"result").Element(ns +"message"));

I am also checking in the where clause if result node exist or not by checking for null, otherwise it may result in Null reference exception.

Upvotes: 1

pierroz
pierroz

Reputation: 7870

Using some XPath, the following piece of code should work

    string xml = @"<session xmlns=""http://test.net/schema/session/1.0"" name=""test"" start=""2015-07-01T07:20:31.425Z"">    
      <download>
        <filename value=""/UAT/Incoming/ Status/Archive/8-22-2011 3-20-14 PM306.xml"" />
        <result success=""false"">
          <message>Timeout waiting .</message>
        </result>
      </download>
    </session>";

    XmlDocument xdoc  = new XmlDocument();
    xdoc.LoadXml(xml);

    // Here, you load the namespace used in your xml. You'll need it later in your XPath queries
    XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
    nsmgr.AddNamespace("test", "http://test.net/schema/session/1.0");

    // XPath to select the "result" node whose attribute "success" equals false
    XmlElement xelt = xdoc.DocumentElement.SelectSingleNode("descendant::test:download/test:result[@success=\"false\"]", nsmgr) as XmlElement;

    // return the "message" node
    return xelt.FirstChild as XmlElement;

As already mentioned, you'll find more details about XPath expression on this link: https://msdn.microsoft.com/en-us/library/d271ytdx%28v=vs.110%29.aspx

Upvotes: 0

Ramin Hajizadeh
Ramin Hajizadeh

Reputation: 31

        XDocument doc = XDocument.Load("your xml file path");
        var result = doc.Elements().
            First(e => e.Name == "download")
        .Elements().First(e => e.Name == "result");
        if (result.Attributes().First(a => a.Name == "success").Value == "false")
            return result.Elements().First(e => e.Name == "message").Value;

Upvotes: 3

Related Questions