带有缩进嵌套标记的C#XML反序列化

时间:2013-02-08 16:44:03

标签: c# xml deserialization

我知道Stackoverflow上已经有几个关于这个主题的问题,但我仍然找不到任何关于重复标签的答案。如果我有这样的XML结构:

<root>
    <block>
        <PositionX>100</PositionX>
        <PositionY>100</PositionY>
        <block>
            <PositionX>10</PositionX>
            <PositionY>15</PositionY>
            <button>
            </button>
        </block>
        <button>
        </button>
    </block>
</root>

上述结构可以具有块内的按钮和块内的块。这是我目前使用的代码,它不允许嵌套项目:

反序列化:

    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;
    }

根类:

[Serializable()]
[XmlRoot("View")]
public class GUI
{
    [XmlArray("Blocks")]
    [XmlArrayItem("Block", typeof(GUIBlock))]
    public GUIBlock[] Blocks { get; set; }
}

块:

[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; }
}

有什么方法可以得到一个答案,它会递归循环项而不定义每个可能的组合?

我不希望阻止块列表和按钮列表,按钮列表块列表和块列表。并为每个新标记添加更多选项。

我也可以在没有反序列化的情况下使用XPath但是如果我不亲自探索它,那么我不知道有关父/子的信息。对此有何帮助?

3 个答案:

答案 0 :(得分:1)

我相信您在问我如何反序列化对象数组而不必创建包含这些项的ListNode?

例如,您有一个要求,即您的XML必须如下所示:

<Library>
    <Location></Location>
    <Book></Book>
    <Book></Book>
    <Book></Book>
</Library>

它看起来不像这样:

<Library>
    <Location></Location>
    <BookCollection>
       <Book></Book>
       <Book></Book>
       <Book></Book>
    <BookCollection>
</Library>

在C#对象中执行此操作的方式如下:

[Serializable]
public class Library
{
    [XmlElement]
    public string Location {get;set;}

    [XmlElement("Book")]
    public Book[] Book {get; set;}

}

public class Book 
{
    /// ....
}

答案 1 :(得分:0)

您需要创建一个递归函数来遍历每个节点,但您可以做的只是:

// 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)
{
   ...
}

这将确定节点是否具有重复的子节点。

答案 2 :(得分:0)

没有找到我正在寻找的答案,因为我相信你无法通过反序列化来做到这一点。所以现在我的Block类也有一个Blocks列表,所以我可以递归循环它们。