-1

I have the following XML file:

<myXML>
    <MyGroup>
        <source>OCU</source> 
        <endianity>
            <set>LITTLE</set><!--LITTLE/BIG Endian-->
        </endianity>
       <msgNumber>
          <Number>5</Number>
          <Field>
            <name>Pos_X</name>
            <entry>
                 <ByteOffset>
                    <offset>8</offset>
                 </ByteOffset>
                 <ByteSize>
                    <Size>4</Size>
                 </ByteSize>
            </entry>
          </Field>
          <Field>
            <name>Pos_Y</name>
            <entry>
                 <ByteOffset>
                    <offset>12</offset>
                 </ByteOffset>
                 <ByteSize>
                    <Size>4</Size>
                 </ByteSize>
            </entry>
          </Field>
       </msgNumber>
    </MyGroup>
</myXML>

I parsed it to an object using XmlSerializer and it worked. The only problem i had to create a class that matches that object. I mean something like this:

   xmlInputData = File.ReadAllText(newPath + xmlFileName);

    myXML messages = Deserialize<myXML>(xmlInputData);

I now want to work without creating a class - that means to parse the XML directly to a dictionary - something like the following:

Dictionary<MessageNumber, SecondDictionary>
                              |
                              |
                  SecondDictionary<FieldName, FieldValue>

How do i parse it using Nested Dictionaries? how to keep the same hierarchy from the XML?

EDIT:

I tried writing it in LINQ but it's too complicating for me:

  var doc = XDocument.Load(newPath + xmlFileName);
    var rootNodes = doc.Root.Descendants("msgNumber");
    var keyValuePairs = from n in rootNodes
                        select new
                        {
                            TagName = n.Name,
                            TagValue = n.Value
                        };


    Dictionary<string, string> allItems = new Dictionary<string, string>();
    foreach (var token in keyValuePairs)
    {
        allItems.Add(token.TagName.ToString(), token.TagValue.ToString());
    }

How do i get the desired hierarchy using LINQ? The main thing i want to accomplish is: For each message to obtain it fields.

For example, for msg number 5 i want to save all the fields (keep the hierarchy ). That means the name, and the entry (byte offset and byte size).

Or Rosenblum
  • 41
  • 1
  • 7
  • 2
    Why not just use LINQ to XML directly? It allows you to query the XML any way you want.Nested dictionaries sound like a nightmare. – Charles Mager Jun 28 '17 at 08:10
  • I updated the post. Please take a look (: – Or Rosenblum Jun 28 '17 at 09:06
  • It is not clear what you expect to happen for repeated elements like ``. The first marked duplicate does include answers that touch on that. Other duplicates provide alternative approaches. – Peter Duniho Jun 28 '17 at 18:02

1 Answers1

0

You'd be much better off using LINQ to XML to get the data you actually want rather than trying to create some nested dictionary structure. Presumably this is what you'd actually be attempting to do with the nested dictionaries anyway.

Based on your requirement to get the names and offset, you could create two classes:

public class Message
{
    public int Number { get; set; }
    public List<Field> Fields { get; set; }
}

public class Field
{
    public string Name { get; set; }
    public int ByteOffset { get; set; }
    public int ByteSize { get; set; }
}

And write a query like this:

var msgs =
    from msg in doc.Descendants("msgNumber")
    select new Message
    {
        Number = (int) msg.Element("Number"),
        Fields = msg
            .Elements("Field")
            .Select(x => new Field
            {
                Name = (string)x.Element("name"),
                ByteOffset = (int)x.Descendants("offset").Single(),
                ByteSize = (int)x.Descendants("Size").Single(),
            })
            .ToList()
    };

See this fiddle for a demo.

Charles Mager
  • 25,735
  • 2
  • 35
  • 45
  • Thanks for the answer, but i don't want to use a class. I want the user to modify the XML (add/remove attributes) without modifying the class. – Or Rosenblum Jun 28 '17 at 10:07
  • @OrRosenblum I don't see how that makes a difference. If the user added new elements or attributes, you'd need to handle them in your code if it was a class or some dictionary structure. – Charles Mager Jun 28 '17 at 10:54
  • @OrRosenblum I'm not sure that's really feasible without knowing something about the structure. `ByteOffset` contains a nested `offset` element that contains the value you want. What if a field had multiple elements? Different nesting? Attributes? – Charles Mager Jun 28 '17 at 11:18
  • All i want is to parse the XML as following: For each msgNumber get all of his fields. For example, for msgNumber 5 (the XML can obtain more then 1 msgNumber) get the Name and the Entry (ByteOffset and ByteSize). I want the parser to save the data in a Dictionary so i can use it in my code... BUT i don't want to use a class in my code because if i add an element to my XML i need to add it to the class as well. – Or Rosenblum Jun 28 '17 at 11:18
  • @OrRosenblum if you add an element to the XML, you'll need to add it to your code *somewhere*. I can't see it makes much difference where that is. If you really don't want to use a class, I'd suggest you use LINQ to XML directly - treat it as a hierarchical dictionary of elements/attributes and values - that's effectively what it is. – Charles Mager Jun 28 '17 at 11:19
  • Can i store with LINQ all the msgNumer(s) and their values and to store it in a dictionary? this is all i need... loop through the msgNumber elements to to store all the values so i can access them (my boss want the user to be able to makes changes in the XML without it effecting the code).. – Or Rosenblum Jun 28 '17 at 11:27
  • @OrRosenblum why do you need to 'store' them? LINQ to XML already has them 'stored' in memory and it effectively has the 'dictionary' api you want - you query the value of an element with a specific name. – Charles Mager Jun 28 '17 at 11:29
  • I'm making a WinForm application and i need to use the data from the XML in different locations in the application.Anyway, i'm a noob in LINQ - you can see what i manged to write in the code above - not even close to what i want to accomplish ;) – Or Rosenblum Jun 28 '17 at 11:33