【问题标题】:Serialization xml : 2 lists mixed up序列化 xml:2 个列表混在一起
【发布时间】:2015-06-15 21:20:21
【问题描述】:

我目前遇到了 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# 中的类如下所示:

 [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 课程。 XBlock 类有一个 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 的函数,请告诉我。

【问题讨论】:

    标签: c# xml serialization xpath


    【解决方案1】:

    如果你想在序列化列表中混合类型,你应该创建一个具有 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 { }
        }
    

    这将创建一个按 Text 属性排序的列表。 您可以替换为您喜欢订购的任何其他字段。

    【讨论】:

    • 您好,感谢您的回复!我尝试使用您建议的 Elements 列表,但是如果这样做,我将不得不删除 XArticle 中的 List 和 List,这是我无法做到的,因为它们已被使用在解决方案的很多地方(我是该项目的新手,这不是我的原始代码)。也许如果我在 XBlock 和 XElt 类中放置一个“Order”属性,有没有办法在序列化过程中合并这两个列表?
    • 编辑答案以满足您的需求
    【解决方案2】:

    非常感谢您的帮助,感谢您的帮助,我能够解决我的问题!

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

    • 第一个,在反序列化后将List&lt;object&gt; Elements 转换为 2 个列表(List&lt;XBlock&gt; BlocksList&lt;XElt&gt; Elts,记住,它们在程序中的每个地方都使用过,并且必须输入)。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      • 1970-01-01
      • 2018-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多