Question

In the below XML example, there can be many ''Element'' entries. For each ''Element'' there can only ever be a single ''System'' entry but there can be many ''Device'' entries alongside that ''System'' entry within the same ''Element''.

I would like to know for each ''Element'', how do I construct a LINQ to XML query in C# that can select data as follows:

for each ''Element'' where ''System'' CONTAINS ''1A7'', return only those ''Device''-''InfoB''-''Settings''-''name'' values that also have a ''Device''-''InfoA''-''Core'' value of FALSE and then put those matching values into a List.

The LINQ has proved to be very difficult for me over the last week. I've not posted a code snippet as I think that none of the large number of code snippets that I've worked through (and failed with) would clarify this question more than the query outline above. I would hugely appreciate some help with this and I'm hoping that the above query is fairly straightforward to the LINQ to XML experts on here.

XML:

<?xml version="1.0" standalone="yes" ?>
<Base_TP>
  <Element>
    <System>
      <id>341A7</id>
    </System>
    <Device>
      <InfoA>
        <id>12</id>
        <Core>TRUE</Core>
      </InfoA>
      <InfoB>
        <Settings>
          <type>0</type>
          <name>DeviceA</name>
        </Settings>
      </InfoB>
    </Device>
    <Device>
      <InfoA>
        <id>13</id>
        <Core>FALSE</Core>
      </InfoA>
      <InfoB>
        <Settings>
          <type>0</type>
          <name>DeviceB</name>
        </Settings>
      </InfoB>
    </Device>
    <Device>
      <InfoA>
        <id>14</id>
        <Core>FALSE</Core>
      </InfoA>
      <InfoB>
        <Settings>
          <type>0</type>
          <name>DeviceC</name>
        </Settings>
      </InfoB>
    </Device>
  </Element>
</Base_TP>
Was it helpful?

Solution

var doc = XDocument.Load("Input.xml");

var values = from e in doc.Root.Elements("Element")
             where ((string)e.Element("System").Element("id")).Contains("1A7")
             from d in e.Elements("Device")
             where !(bool)d.Element("InfoA").Element("Core")
             select (string)d.Element("InfoB").Element("Settings").Element("name");

Returns IEnumerable<string>. Call ToString on it to get List<string> with materialized results.

OTHER TIPS

XDocument xDoc = XDocument.Load("System.xml"); 
List<string> result = xDoc.Descendants("Element").Where(el => el.Element("System").Element("id").Value.Contains("1A7")).SelectMany(e => e.Descendants("Device").Where(d => d.Element("InfoA").Element("Core").Value.ToUpper() == "FALSE").Select(x => x.Element("InfoB").Element("Settings").Element("name").Value)).ToList();

I'm going to do this in visual basic because it has native support for xml in-line but the translation is pretty simple.

Dim elements = From e In xml...<Element>
               Where e.<System>.<Id>.Value.Contains("1A7")
               Select e
Dim deviceBs = (From e In elements
               Where e.<Device>.<InfoA>.<Core>.Value = "FALSE"
               Select e.<Device>.<InfoB>.<name>.Value).ToList
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top