简体   繁体   中英

Select specific nodes in XML with LINQ

I'm writing a function that loads and XML document and converts it to a CSV. Since I need only some values from the XML file, the goal i'm trying to achieve is to select only the nodes I'm interested in.

Here's my code:

      XDocument csvDocument = XDocument.Load(tempOutput);

        StringBuilder csvBuilder = new StringBuilder(1000);

        foreach (XElement node in csvDocument.Descendants("Sample"))
        {
            foreach (XElement innerNode in node.Elements())
            {
                        csvBuilder.AppendFormat("{0},", innerNode.Value);
                    }

                    csvBuilder.Remove(csvBuilder.Length -1, 1);

                    csvBuilder.AppendLine();
                }
                csvOut = csvBuilder.ToString();

But, in this way I'm selectin ALL the child nodes inside the "Sample" node.

In the XML, "Sample" tree is:

<Sample Type="Object" Class ="Sample">
    <ID>1</ID>
    <Name>10096</Name>
    <Type>2</Type>
    <Rep>0</Rep>
    <Selected>True</Selected>
    <Position>1</Position>
    <Pattern>0</Pattern>
   </Sample>

Code works flawlessly, but I need only "ID" and "Selected" to be selected and their values written inside the CSV file.

Could anyone point me in the right direction, please?

Thanks.

Learn more about Linq-to-xml here . You're not really taking advantage of the 'linq-edness' of XObject s

var samples = csvDocument.Descendants("Sample")
                         .Select(el => new {
                             Id = el.Element("ID").Value,
                             Selected = el.Elemnt("Selected").Value
                         });

This creates for you an IEnumerable<T> where 'T' is an anonymous type with the properties Id and Selected . You can parse ( int.Parse or bool.Parse ) the Id and Selected values for type safety. But since you are simply writing to a StringBuilder object you may not care ...just an FYI.

The StringBuilder object can then be written as follows:

foreach (var sample in samples) {
    csvBuilder.AppendFormat(myFormattedString, sample.Id, sample.Selected);
}

The caveat to this is that your anonymous object and the for-each loop should be within the same scope. But there are ways around that if necessary.

As always, there is more than one way to skin a cat.

Update ...in ref. to comment:

foreach (XElement node in csvDocument.Descendants("Sample"))
{
    foreach (XElement innerNode in node.Elements())
    {
        //    this logic assumes different formatting for values
        //    otherwise, change if statement to || each comparison
        if(innerNode.Name == "ID") {
            // append/format stringBuilder
            continue;
        }

        if(innerNode.Name == "Selected") {
            // append/format stringBuilder
            continue;
        }
    }

    csvBuilder.Remove(csvBuilder.Length -1, 1);

    csvBuilder.AppendLine();
}

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