简体   繁体   中英

C# LINQ - Retrieve multiple attributes from single element, convert to structured (non-xml) text

I have an XML file with property groups and properties. I want to retrieve the property groups, print the Name attribute from that element, and then print the child properties of said property group below that entry.

Example XML file:

  <?xml version="1.0" ?> 
  <XMLDocument xmlns:ns="http://www.namespace.com/ns">
  <ns:collectionProperties>
    <ns:propertyGroup name="PERSON">
      <ns:property key="ID" value="555"/>
      <ns:property key="Name" value="Ehron"/>
      <ns:property key="Location" value="Atlanta"/>
    </ns:propertyGroup>
    <ns:propertyGroup name="DOG">
      <ns:property key="Dog Name" value="Lenny"/>
      <ns:property key="Dog Breed" value="Corgle"/>
    </ns:propertyGroup>
    <ns:propertyGroup name="CAT">
      <ns:property key="Cat Color" value="Grey"/>
      <ns:property key="Cat Hates" value="Everyone"/>
      <ns:property key="Name" value="Lester"/>
    </ns:propertyGroup>
  </ns:collectionProperties>
  </XMLDocument>

Desired resultant text:

[PERSON]
ID=555
Name=Ehron
Location=Atlanta
[DOG]
Dog Name=Lenny
Dog Breed=Corgle
[CAT]
Cat Color=Grey
Cat Hates=Everyone
Name=Lester

I managed to get the propertyGroup name to print, but I can't seem to retrieve more than one attribute from the property elements without doing two LINQ queries. I have not found a way to do this thus far.

static void Main(string[] args)
        {
            XDocument xml = XDocument.Load(@"c:\xml.xml");
            XNamespace ns = "http://namespace.com/ns";

            // Pull out the categories
            var categories = from c in xml.Descendants(ns + "propertyGroup")
                             select (string)c.Attribute("name");

            // write categories
            foreach (string name in categories)
            {

                Console.WriteLine('[' + name + ']');
            }

        }

Here is an approach that uses nested LINQ to assembly a nested, anonymous type collection using the var keyword.

void Main(string[] args)
{
  XDocument xml = XDocument.Parse("XML CONTENTS HERE")
  XNamespace ns = "http://www.namespace.com/ns";

  // Pull out the property Groups
  var propertyGroups = 
    from pg in xml.Descendants(ns + "propertyGroup")
            //Return a new, anonymous object to represent the xml propertyGroup
    select new 
    {
        Name = pg.Attribute("name").Value,
                    //Pairs will be a collection of all properties in the group
        Pairs = from p in pg.Descendants(ns + "property")
                            //Nested anonymous type
            select new
            {
                Key = p.Attribute("key").Value,
                Value = p.Attribute("value").Value
            }
    };

  foreach (var propertyGroup in propertyGroups)
  {
    Console.WriteLine("[" + propertyGroup.Name + "]");
    foreach (var pair in propertyGroup.Pairs)
    {
        Console.WriteLine(pair.Key + "=" + pair.Value);
    }
  }
}
XDocument doc = XDocument.Load(...);
XNamespace ns = "http://www.namespace.com/ns";

With LINQ:

string result =

doc.Element("XMLDocument")
   .Element(ns + "collectionProperties")
   .Elements(ns + "propertyGroup")
   .Aggregate(new StringBuilder(),
              (sb, g) => g.Elements(ns + "property")
                          .Aggregate(sb.Append("[")
                                       .Append((string)g.Attribute("name"))
                                       .AppendLine("]"),
                                     (sb1, p) => sb1.Append((string)p.Attribute("key"))
                                                    .Append("=")
                                                    .AppendLine((string)p.Attribute("value"))))
   .ToString();

Without LINQ:

StringBuilder sb = new StringBuilder();

foreach (var propertyGroup in doc.Element("XMLDocument")
                                 .Element(ns + "collectionProperties")
                                 .Elements(ns + "propertyGroup"))
{
    sb.Append("[")
      .Append((string)propertyGroup.Attribute("name"))
      .AppendLine("]");

    foreach (var property in propertyGroup.Elements(ns + "property"))
    {
        sb.Append((string)property.Attribute("key"))
          .Append("=")
          .AppendLine((string)property.Attribute("value"));
    }
}

string result = sb.ToString();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM