【问题标题】:Xml deserialization, perserving order across different tagsXml反序列化,跨不同标签保持顺序
【发布时间】:2012-04-26 14:45:00
【问题描述】:

我有需要用 XmlSerializer 反序列化的 xml(我无法控制)。我的麻烦是我需要在一个列表中保留两个不同标签之间的顺序。举个例子吧:

<users>
    <luser>..some more elements..</luser>
    <luser>..some more elements..</luser>
    <admin>..different elements than in luser</admin>
    <luser>..some more elements..</luser>
    <admin>..different elements than in luser</admin>
    <luser>..some more elements..</luser>
    <admin>..different elements than in luser</admin>
<users>

现在,如果我直接反序列化,我最终会得到两个列表,一个用于 luser,一个用于管理员。但是,它们出现的顺序是隐式 ID! (这当然应该是 xml 中的属性或元素,但可惜不是)

我尝试过制作这样的元元素

[XmlElement("luser"),XmlElement("admin")]
public List<Person> Person { get; set; }

public class Person
{
    public Luser Luser { get; set; }
    public Admin Admin { get; set; }
}

计划检查列表以查看条目是 luser 还是管理员,并让人员包装器维护元素的顺序。然而,单个属性上的多个 XmlElement 属性似乎是非法的。

另一个可接受的解决方案是最终得到两个列表,但每个列表中的每个条目都有一个我可以用来获取原始订单的 ID。

我希望它尽可能干净。之后通过 xml 搜索以查找订单、手动提取标签等类似操作,是我会避免并作为最后手段做的事情。

【问题讨论】:

  • 我知道这并不能真正帮助你,但你需要保持它们的顺序似乎很愚蠢。显然,似乎没有规定这种安排的模式。为什么你不能让所有管理员都跟随所有 luser?这是您的系统施加的限制,还是其他方要求您不要更改列表?也看看这个,它可能会给你一些想法:stackoverflow.com/questions/1007626/…
  • 第一个条目(用户或管理员)是 id 1,下一个是 id 2(无论是用户还是管理员)等等。是的,这很愚蠢,但我对此无能为力。我去看看链接,谢谢
  • Ew,userId 是基于 XML 文档中的位置的?那太可怕了。我想将它更改为 userId 是一个属性是不可能的?
  • 恐怕 xml 是一成不变的,是从第三方交付给我的。是的,我经常诅咒他们。

标签: c# .net deserialization xmlserializer


【解决方案1】:

当然应该是属性...

然后尽快将其设为属性。然后处理结果。

var doc = XDocument.Load(...);

var fixeruppers = doc
      .Descendants("users")
      .Elements()
      .ToList();   // isolate us from any movements in the doc

int id = 1; // base
foreach (var fixer in fixeruppers)
   fixer.SetAttributeValue("Id", id++);

XmlReader readerForDeserialize = doc.CreateReader();

【讨论】:

  • +1。不保留顺序的原因是 XML 中没有这样的顺序 - 你想要一个,你就有一个。谁做错了都是负责任的——没有办法解决这个问题。添加一个 ID。
  • 这是迄今为止最干净的方式,虽然感觉有点老套,但它肯定比手动反序列化整个 ting 或其他我想到的事情要好
  • 重点是早做,十指相扣。大多数 XML 工具/解析器不会觉得有义务维护任何“顺序”。另请注意 XDocument.CreateReader(),您可以连接大多数反序列化器。
  • 我接受这是最好的答案,并且对 CreateReader 表示 +1,这使得将 linq 与 xml 和序列化程序混合起来变得不那么尴尬。
【解决方案2】:

以下将指示顺序(使用 order:= 值),它不会改变类的序列化方式。

Imports System.Runtime.Serialization
Imports System.ServiceModel

<DataContract()> _
Public Class MyClass

    <DataMember(order:=1)> _
    Public Property SomeData() As String

    <DataMember(order:=2)> _
    Public Property SomeOtherData() As String

End Class

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 2018-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-10
    相关资源
    最近更新 更多