Reputation: 243
I know there are several questions on Stackoverflow already regarding this subject, but I still couldn't find any answer about repeating tags. If I have such a XML structure:
<root>
<block>
<PositionX>100</PositionX>
<PositionY>100</PositionY>
<block>
<PositionX>10</PositionX>
<PositionY>15</PositionY>
<button>
</button>
</block>
<button>
</button>
</block>
</root>
The above structure can have buttons within blocks and blocks within blocks. This is the code that I use at the moment, which doesn't allow nested items:
The Deserialization:
public static GUI Deserialize(string filename)
{
GUI gui = null;
XmlSerializer serializer = new XmlSerializer(typeof(GUI));
StreamReader reader = new StreamReader(filename);
gui = (GUI)serializer.Deserialize(reader);
reader.Close();
return gui;
}
The root class:
[Serializable()]
[XmlRoot("View")]
public class GUI
{
[XmlArray("Blocks")]
[XmlArrayItem("Block", typeof(GUIBlock))]
public GUIBlock[] Blocks { get; set; }
}
The block:
[Serializable()]
public class GUIBlock
{
[XmlElement("Name")]
public string Name { get; set; }
[XmlElement("Position")]
[XmlAttribute("X")]
public int PositionX { get; set; }
[XmlElement("Position")]
[XmlAttribute("Y")]
public int PositionY { get; set; }
[XmlElement("Width")]
public int Width { get; set; }
[XmlElement("Height")]
public int Height { get; set; }
[XmlElement("Background")]
public string Background { get; set; }
[XmlElement("Opacity")]
public int Opacity { get; set; }
// I also want to allow nested Blocks and Buttons in here, but I **dont** explicitly want to say:
[XmlArray("Blocks")]
[XmlArrayItem("Block", typeof(GUIBlock))]
public GUIBlock[] Blocks { get; set; }
}
Is there any way that I can get an answer which will recursively loop the the item without defining every possible combination?
I don't want to give block a list of blocks and a list of buttons and a button a list of blocks and a list of blocks. And add more options for every new tag.
I could also do it without deserialization and use XPath but then I don't know the information about parent/children if I don't explore it myself. Any help on this one?
Upvotes: 3
Views: 977
Reputation: 243
Didn't found the answer that I was looking for because I believe you can't do it with deserialization. So now my Block class also has a list of Blocks, so I can recursively loop them.
Upvotes: 0
Reputation: 441
I believe you are asking how can I deserialize an array of objects without having to create a ListNode that contains those items?
For example, you have a requirement that says your XML must look like this:
<Library>
<Location></Location>
<Book></Book>
<Book></Book>
<Book></Book>
</Library>
And it CANNOT look like this:
<Library>
<Location></Location>
<BookCollection>
<Book></Book>
<Book></Book>
<Book></Book>
<BookCollection>
</Library>
The way you would do this in a C# object is like this:
[Serializable]
public class Library
{
[XmlElement]
public string Location {get;set;}
[XmlElement("Book")]
public Book[] Book {get; set;}
}
public class Book
{
/// ....
}
Upvotes: 1
Reputation: 11439
You'll need to create a recursive function to go through each node, but what you can do is just:
// This groups all sub-elements of a node by their name.
// If there is more than one node with the same name, .Count() will return > 1
Int32 numberOfSameNameNodes =
node.Elements()
.GroupBy(element => element.Name)
.Count(elementsGroupedByName => elementsGroupedByName.Count() > 1);
// if there are duplicately named sub-nodes then
if (numberOfSameNameNodes > 0)
{
...
}
And this will determine if a node has sub-nodes that are duplicates.
Upvotes: 0