C# XML file - collect all elements with the value.

Markus Freitag 3,786 Reputation points
2021-01-28T16:52:46.037+00:00

Hello,

I have a XML file and need to collect all values from YPOS into a new list with index and value.

How can I easily reach this? Thanks in advance.

The goal is a list with

Index, YPOS

  • 1, 41.352
  • 2, 51.352
  • 3, 61.352
  • 4, 71.352

What is the best way with XDocument?

<root>
  <GROUP1>
    <POSITIONS>
      <POSITION>
        <INDEX value="1" />
        <XPOS value="45.598" />
        <YOFFSET value="0" />
        <YPOS value="41.352" />
        <ZPOS value="0" />
      </POSITION>
      <POSITION>
        <INDEX value="2" />
        <XPOS value="45.598" />
        <YOFFSET value="0" />
        <YPOS value="51.352" />
        <ZPOS value="0" />
      </POSITION>
    </POSITIONS>
  </GROUP1>
  <GROUP2>
    <POSITIONS>
      <POSITION>
        <INDEX value="3" />
        <XPOS value="45.598" />
        <YOFFSET value="0" />
        <YPOS value="61.352" />
        <ZPOS value="0" />
      </POSITION>
      <POSITION>
        <INDEX value="4" />
        <XPOS value="45.598" />
        <YOFFSET value="0" />
        <YPOS value="71.352" />
        <ZPOS value="0" />
      </POSITION>
    </POSITIONS>
  </GROUP2>
</root>
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,996 questions
{count} votes

Accepted answer
  1. Yitzhak Khabinsky 25,956 Reputation points
    2021-01-28T20:03:04.843+00:00

    Here is one way how to implement it.

    c#

    void Main()
    {
     const string SOURCEXMLFILE = @"e:\Temp\MarkusFreitagInput.xml";
    
     XDocument xdoc = XDocument.Load(SOURCEXMLFILE);
    
       List<PositionObject> objects2 = new List<PositionObject>();
    
     objects2 = xdoc.Descendants("POSITION")
        .Select(p => new PositionObject()
        {
        Index = Convert.ToInt16(p.Element("INDEX").Attribute("value")?.Value),
        YPOS = p.Element("YPOS").Attribute("value")?.Value
        }
        ).ToList();
    }
    
    public class PositionObject
    {
     public int Index { get; set; }
     public string YPOS { get; set; }
    }
    

    -- UPDATE --
    Method #2, by using a dictionary.

    void Main()
    {
        const string SOURCEXMLFILE = @"e:\Temp\MarkusFreitagInput.xml";
    
        XDocument xdoc = XDocument.Load(SOURCEXMLFILE);
    
        Dictionary<int, string> dictIndexContent = new Dictionary<int, string>();
    
        dictIndexContent = xdoc.Descendants("POSITION")
            .ToDictionary(e => Convert.ToInt32(e.Element("INDEX").Attribute("value")?.Value),
                        e => e.Element("YPOS").Attribute("value")?.Value);
    }
    

2 additional answers

Sort by: Most helpful
  1. Petrus 【KIM】 456 Reputation points
    2021-01-29T03:48:16.683+00:00
                var xDoc = XDocument.Load("../../XMLFile1.xml");
                var vList1 = new List<Tuple<string, string>>();
    
                var vIndex = "";
                var vYPos = "";
                var vPos = xDoc.XPathSelectElements("//POSITION");
                foreach (var vNode in vPos)
                {
                    vIndex = vNode.XPathSelectElement("INDEX").Attribute("value").Value;
                    vYPos = vNode.XPathSelectElement("YPOS").Attribute("value").Value;
    
                    vList1.Add(new Tuple<string, string>(vIndex, vYPos));
                }
    

  2. Timon Yang-MSFT 9,591 Reputation points
    2021-01-29T06:01:27.2+00:00

    Do you have to use XDocument?

    If you can use other methods, you can generate the required classes according to vb2ae's recommendations, and then use XmlSerializer to deserialize xml.

                XmlSerializer serializer = new XmlSerializer(typeof(root));  
                using (TextReader reader = new StreamReader(@"D:\test\xml\test.txt"))  
                {  
                    root root = (root)serializer.Deserialize(reader);  
                     
                    var positions = root.GROUP.SelectMany(t => t.POSITIONS);  
      
                    var result = from position in positions  
                                 select new  
                                 {  
                                     Index = position.INDEX.value,  
                                     XPOS = position.YPOS.value  
                                 };  
                }  
    

    The generated class is a bit long, I will provide it as an attachment.
    61733-classes.txt


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.