简体   繁体   中英

LINQ to read XML file and print results

I got the following XML file (Data.xml):

<root>
 <sitecollection name="1A">
   <site name="1B">
     <maingroup name="1C"> 
        <group name="1D"> </group>
     </maingroup> 
    </site>
 </sitecollection>
 <sitecollection name="2A">
   <site name="2B">
     <maingroup name="2C"> 
        <group name="2D"> </group>
     </maingroup> 
    </site>
 </sitecollection>
</root>

And I need to print all the all the child elements in this format:

1A
 1B
  1C
   1D
2A
 2B
  2C
   2D

I have the following code so far which needs some adjustment. I could also change it completely if there's an easier method. Thanks for your help

class xmlreader
{
    public static void Main()
    {

        // Xdocument to read XML file
        XDocument xdoc = XDocument.Load("Data.xml");
        var result = new System.Text.StringBuilder();

        var lv1s = from lv1 in xdoc.Descendants("sitecollection")
                   select new
                   {
                       sitecollection = lv1.Attribute("name").Value,
                       maingroup = lv1.Descendants("group")

                   };
        var lv2s = from lv2 in xdoc.Descendants("site")
                   select new
                   {
                       site = lv2.Attribute("name").Value,
                       sitetittle = lv2.Descendants()
                   };
        var lv3s = from lv3 in xdoc.Descendants("maingroup")
                   select new
                   {
                       maingroup = lv3.Attribute("name").Value,
                   };
        var lv4s = from lv4 in xdoc.Descendants("group")
                   select new
                   {
                       grouppage = lv4.Attribute("name").Value,
                   };


        // Loop to print results
        foreach (var lv1 in lv1s)
        {
            result.AppendLine(lv1.sitecollection);
            foreach (var lv2 in lv2s)
            {
                result.AppendLine("   " + lv2.Attribute("name").Value);

                foreach (var lv3 in lv3s)
                {
                    result.AppendLine("   " + lv3.Attribute("name").Value);

                    foreach (var lv4 in lv4s)
                    {
                        result.AppendLine("   " + lv4.Attribute("name").Value);
                    }
                }
            }
        }
    }
}

With such a uniform hierarchy, recursion can do the job with a lot less code:

    void PrintNames(StringBuilder result, string indent, XElement el)
    {
        var attr = el.Attributes("name");
        if (attr != null)
        {
            result.Append(indent);
            result.Append(attr.Value);
            result.Append(System.Environment.NewLine);
        }
        indent = indent + " ";
        foreach(var child in el.Elements())
        {
            PrintNames(result, indent, child);
        }
    }

...

var sb = new StringBuilder();
PrintNames(sb, String.Empty, xdoc.Root);

How about the following, find all elements with a name attribute, then add spaces based on their depth.

var result = new System.Text.StringBuilder();
var namedElements = doc.Descendants().Where(el => el.Attributes("name")!=null);
foreach(var el in namedElements)
{
  int depth = el.Ancestors().Count();
  for (int i=0;i<depth;i++)
    result.Append(" "); 

  result.Append(el.Attributes("name").Value);
  result.Append(System.Environment.NewLine);
}

NOTE: The above is from memory, so please check the syntax!

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