How to get an array with XML tags within only 1 node

This forum is meant for questions and discussions about the X# language and tools
Post Reply
ic2
Posts: 1798
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

How to get an array with XML tags within only 1 node

Post by ic2 »

This sounds simple but I have tried multiple solutions I found but none gave me what I want. Consider the XML file below. What I want is the "pos" tags below of a certain zoom factor. So for Zoom200 I want 10, 20 and 30 in a 3 element array.

I found (C# samples):

Code: Select all

XDocument doc = XDocument.Load(cPDFName);

var allElements = doc.Descendants("Zoom200").Select(element => element.Value).ToArray();
string[]AllPos = doc.Descendants("pos").Select(n => n.Value).ToArray();
var allnodes2 = doc2.SelectNodes("//Zoom200");

The first line returns allElemens but this is only 1 array element with all "pos" values in 1 line
The second line returns a string array with all requested "pos" values but it also includes for all zoom values for Zoom300
The third lines returns the contents of Zoom200 but how to get these "pos" values from it? InnerText is also 1 line (with "10-20-30") instead of an array of these 3 values.

It must be something simple I overlook or couldn't find.

Dick


<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Doc>
<Zoom200>
<pos>10</pos>
<pos>20</pos>
<pos>30</pos>
</Zoom200>
<Zoom300>
<pos>100</pos>
<pos>200</pos>
<pos>300</pos>
</Zoom300>
</Doc>
VR
Posts: 98
Joined: Sun Aug 23, 2020 3:07 pm
Location: Italy

Re: How to get an array with XML tags within only 1 node

Post by VR »

Hi,

this is how ChatGPT would do it...

Code: Select all

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main()
    {
        // Load the XML data from your file or string
        string xmlData = @"<?xml version=""1.0"" encoding=""utf-8"" standalone=""yes""?>
                            <Doc>
                                <Zoom200>
                                    <pos>10</pos>
                                    <pos>20</pos>
                                    <pos>30</pos>
                                </Zoom200>
                                <Zoom300>
                                    <pos>100</pos>
                                    <pos>200</pos>
                                    <pos>300</pos>
                                </Zoom300>
                            </Doc>";

        // Parse the XML data
        XDocument doc = XDocument.Parse(xmlData);

        // Specify the zoom factor you want (e.g., "Zoom200")
        string targetZoom = "Zoom200";

        // Find the <Zoom> element with the specified factor
        XElement zoomElement = doc.Root.Elements(targetZoom).FirstOrDefault();

        if (zoomElement != null)
        {
            // Extract the <pos> elements under the specified <Zoom> element
            var posElements = zoomElement.Elements("pos").Select(e => int.Parse(e.Value)).ToArray();

            // Now, posElements contains the values (10, 20, 30) for Zoom200
            Console.WriteLine("Values for " + targetZoom + ": " + string.Join(", ", posElements));
        }
        else
        {
            Console.WriteLine(targetZoom + " not found.");
        }
    }
}
ic2
Posts: 1798
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

Re: How to get an array with XML tags within only 1 node

Post by ic2 »

Hello Volmar,

A nice idea. I tried some ChatGPT queries and some look quite clever. I tried the program and it actually compiled. So far so good. But on running I got an exception System.FormatException: 'Input string was not in a correct format.' That is already a bit less clever.

I modified it as follows:

Code: Select all

var posElements = zoomElement.Elements("pos").Select(e => e.Value.ToArray());
to avoid the Parse causing the exception. I do get all values but it says all -literally- system.char instead of the values (10, 20, 30 in my posted sample). I inspected posElements The result view from the debugger of the elements (in my test XML I have got 5 values) actually contains the correct 'pos' values. See picture; the second pos tag in my actual XML is: <pos>2177,28</pos> and what I see is 50'2' 49'1' etc. No idea what the 50,49 etc mean but the second part forms indeed 2 1 7 7 , 2 8 (right of the red line)
XS3472RersultView.jpg
XS3472RersultView.jpg (30.38 KiB) Viewed 1937 times
Unfortunately I can't figure out how to retrieve these values as 2177,28 and the other values I've got in the XML. Or what to ask ChatGPT to have this solved :?

Dick
VR
Posts: 98
Joined: Sun Aug 23, 2020 3:07 pm
Location: Italy

Re: How to get an array with XML tags within only 1 node

Post by VR »

Hi Dick

Code: Select all

var posElements = zoomElement.Elements("pos").Select(e => e.Value.ToArray());
e.Value is a string -> e.Value.ToArray() gives you every char of the string as array. Try this instead:

Code: Select all

var posElements = zoomElement.Elements("pos").Select(e => e.Value).ToArray();
Volkmar
ic2
Posts: 1798
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

Re: How to get an array with XML tags within only 1 node

Post by ic2 »

Yes, that works! Lambda expressions are still a bit of a black box for me. It is very interesting that this is solved by a bit of ChatGPT (and an important bit of Volkmar).

What strikes me is that I would have expected a more direct way to retrieve these values in either the XmlDocument or XDocument class.

Anyway, thanks!

Dick
VR
Posts: 98
Joined: Sun Aug 23, 2020 3:07 pm
Location: Italy

Re: How to get an array with XML tags within only 1 node

Post by VR »

Hi...

The "one-liner" for this operation is

Code: Select all

var posElements = doc.Root.Element("Zoom200")?.Elements("pos").Select(e => e.Value).ToArray() ?? Array.Empty<string>();
ChatGPT tends to write code in a more verbose way.
ic2
Posts: 1798
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

Re: How to get an array with XML tags within only 1 node

Post by ic2 »

Indeed, but although I already made it a bit shorter, I tend to avoid oneliners as I prefer that I actually understand what the code is doing. Once again, I was quite impressed what ChatGPT produced (I didn't find a working sample in the usual websites) even though the actual result didn't work - but it was close.

Dick
Post Reply