序列化 xml:2 个列表混淆

Serialization xml : 2 lists mixed up

我目前 运行 在 C# 中遇到 xml 序列化问题。

我的程序中有一个这样的 XML 结构,代表一棵树:

<FlatNodeTree>
  <Node>
    <Level>1</Level>
    <Name>Element 0</Name>
    <Guid>AAA</Guid>
    <NodeType>XElt</NodeType>
    <GuidParent />
  </Node>
  <Node>
    <Level>1</Level>
    <Name>Block 1</Name>
    <Guid>BBB</Guid>
    <NodeType>XBlock</NodeType>
    <GuidParent />
  </Node>
  <Node>
    <Level>2</Level>
    <Name>Element 1</Name>
    <Guid>CCC</Guid>
    <NodeType>XElt</NodeType>
    <GuidParent>BBB</GuidParent>
  </Node>
  <Node>
    <Level>1</Level>
    <Name>Element 2</Name>
    <Guid>DDD</Guid>
    <NodeType>XElt</NodeType>
    <GuidParent />
  </Node>
</FlatNodeTree>

如您所见,有节点 (XBlock) 和叶子 (XElt),并且级别 > 1 的对象通过 Guid 附加到父节点。

我希望它保存在这样的 xml 结构中(非常简单,但你明白了):

<Article>
    <Elt>Element 0</Elt>
    <Block name='Block 1'>
        <Elt>Element 1</Elt>
    </Block>
    <Elt>Element 2</Elt>
</Article>

我用来序列化的 C# 中的 class 如下所示:

 [Serializable]
 public class XArticle
 {
     public XArticle()
     {
         Blocks = new List<XBlock>();
         Elts = new List<XElt>();
     }

     [XmlElement("block")]
     public List<XBlock> Blocks { get; set; }

     [XmlElement("elt")]
     public List<XElt> Elts { get; set; }

      /*Plenty of other stuff*/

 }

我还有 XBlock 和 XElt classes。 XBlock class 有一个 innerBlocks 属性,它只是一个允许多个级别的列表。

我的问题在于,当我尝试创建我的 XArticle 时,Blocks 和 Elts 存储在 2 个单独的列表中,所以当然,当我尝试序列化它时,它会依次序列化一个列表,我完全如果它们混合在一起,则会丢失块和 elt 的顺序。

这是我得到的 XML 示例,而不是我之前发布的示例:

 <Article>
    <Block name='Block 1'>
        <Elt>Element 1</Elt>
    </Block>
    <Elt>Element 0</Elt>
    <Elt>Element 2</Elt>
</Article>

您可以看到它首先序列化所有块,然后序列化每个节点内的所有元素。

我对序列化知之甚少,想知道是否有 xml 指令或其他可以解决此问题的指令。

我想到的一个解决方案是在创建杂乱无章的 xml 后重新排序 Blocks 和 Elts 标签,但也许有更好的解决方案。

PS :我使用 System.Xml.Serialization.XmlSerializer.

PPS : 如果您需要查看将 xpath 数据转换为 X-classes.

的函数,请告诉我

如果你想在序列化列表中混合类型,你应该创建一个 属性 具有 2 个修饰属性,如下所示:

[Serializable]
public class XArticle
{

    [XmlElement(Type = typeof(XBlock), ElementName = "Block")]
    [XmlElement(Type = typeof(XElt), ElementName = "Elt")]
    public List<object> Elements { get; set; }

}

如果您使用以下内容填充元素:

Elements = new List<object> { new XElt { Text = "Element 0" }, new XBlock { Elt = new XElt { Text = "Element 1 " }, Name = "Block 1" }, new XElt { Text = "Element 2 " } };

它产生 xml :

<?xml version="1.0"?>
<XArticle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Elt>Element 0</Elt>
  <Block name="Block 1">
    <Elt>Element 1 </Elt>
  </Block>
  <Elt>Element 2 </Elt>
</XArticle>

编辑: 如果你必须保留 Blocks 和 Elts 属性,你可以这样做:

[Serializable]
public class XArticle
{
    [XmlIgnore]
    public List<XBlock> Blocks { get; set; }


    [XmlIgnore]
    public List<XElt> Elts { get; set; }

    [XmlElement(Type = typeof(XBlock), ElementName = "Block")]
    [XmlElement(Type = typeof(XElt), ElementName = "Elt")]
    public List<object> Elements
    {
        get
        {
            return Blocks.Select(b => new KeyValuePair<string, object>(b.Elt.Text, b))
                .Concat(Elts.Select(e => new KeyValuePair<string, object>(e.Text, e)))
                .OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value).ToList();
        }
        set { }
    }

这将创建一个按文本 属性 排序的列表。 您可以替换为您希望作为排序依据的任何其他字段。

非常感谢您的帮助,多亏了我才得以解决我的问题!

对于可能对其他人有帮助的人,我设法通过创建 2 个递归函数来重新排序我的最终 xml :

  • 首先,反序列化后将List<object> Elements转换为2个列表(List<XBlock> BlocksList<XElt> Elts,记住,它们在程序中无处不在必须喂食)。

  • 第二次,在序列化之前将 2 个列表(Blocks 和 Elts)合并为一个列表(Elements)。