0

My sample XML is something like this:

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <RoleSecurity Name="A" Workflowstatus ="B">
    <Accountgroup Name = "Group1">
      <Attribute ID="12345" Name="Sample1"/>
      <Attribute ID="12445" Name="Sample2"/>
    </Accountgroup>
    <Accountgroup Name = "Group2">
      <Attribute ID="12345" Name="Sample1"/>
      <Attribute ID="12445" Name="Sample2"/>
    </Accountgroup>
  </RoleSecurity>
</Root>

I am trying to enumerate and extract all the ID corresponding to a particular Role name, workflow status and account group.

My LINQ query is working to select a node based on role name. But I am unable to proceed further. Please help!

This is my LINQ code till now.

XElement xcd = XElement.Load(strFileName);
IEnumerable<XElement> enumCust = from cust in xcd.Elements("RoleSecurity")
           where (string)cust.Attribute("Name") == strRole
           select cust;
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
TheSilverBullet
  • 605
  • 7
  • 21
  • A very useful discussion on (Elements and Decendents) [http://stackoverflow.com/questions/3705020/what-is-the-difference-between-linq-to-xml-descendants-and-elements] – TheSilverBullet Sep 23 '13 at 06:49

4 Answers4

1

Try this:

string roleName = "A";
string workflowStatus = "B";
string accountGroup = "Group1";

string xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
    <Root>
        <RoleSecurity Name=""A"" Workflowstatus =""B"">
        <Accountgroup Name = ""Group1"">
            <Attribute ID=""12345"" Name=""Sample1""/>
            <Attribute ID=""12445"" Name=""Sample2""/>
        </Accountgroup>
        <Accountgroup Name = ""Group2"">
            <Attribute ID=""12345"" Name=""Sample1""/>
            <Attribute ID=""12445"" Name=""Sample2""/>
        </Accountgroup>
        </RoleSecurity>
    </Root>";

XElement element = XElement.Parse(xml);

var ids = element.Elements("RoleSecurity")
    .Where(
        e =>
            (string) e.Attribute("Name") == roleName &&
            (string) e.Attribute("Workflowstatus") == workflowStatus)
    .Elements("Accountgroup").Where(e => (string) e.Attribute("Name") == accountGroup)
    .Elements("Attribute")
    .Select(e => new {ID = (string) e.Attribute("ID"), Name = (string) e.Attribute("Name")});
Hamlet Hakobyan
  • 32,965
  • 6
  • 52
  • 68
  • Thanks a bunch! The miracle has happened, and code is working! :) One question about the `.Element` function. You have used it to query multiple levels. How does this work? – TheSilverBullet Sep 20 '13 at 08:34
  • I think you misunderstood something. At first, I use `Elements`, which returns `IEnumerable` of given node. Look at the code closer. Code traverses the levels one by other with filtering necessary content. – Hamlet Hakobyan Sep 20 '13 at 08:42
  • Thank you Hamlet... I realize that at each "." you go one level deep. Just wondering, how this the `Descendant` approach different? This solution has been given by one other SO user. Need to google that. – TheSilverBullet Sep 20 '13 at 09:19
  • `Descendants` returns all match nodes in any level from current level. – Hamlet Hakobyan Sep 20 '13 at 09:28
1

Try with this approach, seems different from your (and in some aspects it really changes), but in my opinion its a good way to use fluently a LINQ query to parse an XML file, it follows XML node sequence and it's easy to understand:

  XElement element = XElement.Load(strFileName);

  var linqList = element.Elements("RoleSecurity")
                              .Where(entry => entry.Attribute("Name").Value == "A" && 
                               entry.Attribute("Workflowstatus").Value == "B")
                                  .Descendants("Accountgroup")
                                  .Where(x => x.Attribute("Name").Value == "Group1")
                                     .Descendants("Attribute")
                                     .SelectMany(id => id.Attribute("ID").Value);
Francesco De Lisi
  • 1,493
  • 8
  • 20
  • Thank you for your answer! I have already implemented the accepted answer's approach. I just wonder which is a better approach for me, and why? – TheSilverBullet Sep 20 '13 at 09:20
0
XElement xcd = XElement.Load(strFileName);
IEnumerable<XElement> enumCust = from cust in xcd.Root.Elements("RoleSecurity")
           where cust.Attribute("Name").Value == strRole
           select cust;

This should work now you were missing .Root which is required to enumerate below the root node
and .Value to retrive the string value of the specified attribute

Parv Sharma
  • 12,581
  • 4
  • 48
  • 80
  • I am trying to dril down deeper. Like I have mentioned in the question, I am trying to enumerate and extract all the ID corresponding to a particular Role name, workflow status and account group. – TheSilverBullet Sep 20 '13 at 07:12
0

refer this artical :- http://www.dotnetcurry.com/ShowArticle.aspx?ID=564

foreach (XElement xcd xelement.Descendants("Id"))
    {
        Console.WriteLine((string)xcd);
    }
Neel
  • 11,625
  • 3
  • 43
  • 61