【问题标题】:How to properly setup a class structure to properly de-serialize XML?如何正确设置类结构以正确反序列化 XML?
【发布时间】:2015-03-26 15:27:33
【问题描述】:

--更新--

其实,再看一遍代码后,我应该重新表述一下这个问题。在下面添加了更多描述。

我有这个从 Web 服务返回的 XML 结构,据说是标准问题 cXML 结构。我的问题是重复的<Extrinsic> 节点,它有一个参数名称,除了区分它们的值之外。

像这样:

    <ItemDetail>
      <UnitPrice>
        <Money currency="USD">1.53 </Money>
      </UnitPrice>
      <Description>ASPIRIN  81 MG CHW  90</Description>
      <UnitOfMeasure>EA</UnitOfMeasure>
      <Extrinsic name="HCustomerNumber">0100074080</Extrinsic>
      <Extrinsic name="HPONumber">201</Extrinsic>
      <Extrinsic name="HOrderNumber">4413686057</Extrinsic>
      <Extrinsic name="HUserID">ABTGDEV</Extrinsic>
      <Extrinsic name="HLegacyCustomerNumber">055150912</Extrinsic>
      <Extrinsic name="LegacyItemNumber">198440</Extrinsic>
      <Extrinsic name="CustomerMaterialNumber"/>
      <Extrinsic name="ContractNumber"/>
      <Extrinsic name="NDC">00904628889</Extrinsic>
      <Extrinsic name="UPC">309046288893</Extrinsic>
      <Extrinsic name="Size">90</Extrinsic>
      <Extrinsic name="DrugFormPackSize">90.000</Extrinsic>
      <Extrinsic name="Prevent Sub">False</Extrinsic>
      <Extrinsic name="SHCCode"/>
      <Extrinsic name="DEPTCode"/>
      <Extrinsic name="GLCode"/>
      <Extrinsic name="SWP">3.62000</Extrinsic>
      <Extrinsic name="RetailPrice">0.00</Extrinsic>
      <Extrinsic name="RetailPriceOverride">0.00</Extrinsic>
      <Extrinsic name="TemporaryRetailPriceOverride">True</Extrinsic>
      <Extrinsic name="UDIF"/>
      <Extrinsic name="UDIFDesc"/>
      <Extrinsic name="Formulary"/>
      <Extrinsic name="SPLRouting"/>
    </ItemDetail>

如何设置我的类结构以便正确反序列化?类本身由 PetaPoco 呈现,因此每个 &lt;Extrinsic&gt; 节点都是数据库中类/字段的属性。或者可能做不到,需要手动处理,我一直在摸索,找不到好的自动方式。

--更新--

这就是我要反序列化的类

    public int syspohid { get; set; }
    public int syspodid { get; set; }
    public string pdvendor { get; set; }
    public string pdprefix { get; set; }
    public Nullable<int> pdnumber { get; set; }
    public Nullable<int> pdline { get; set; }
    public bool pdtaxable { get; set; }
    public bool pdfreightable { get; set; }
    public string comments { get; set; }
    public string pdlocation { get; set; }
    public string pddoctor { get; set; }
    public string pdpatient { get; set; }
    public string pdlotnum { get; set; }
    public Nullable<System.DateTime> pdcasedate { get; set; }
    public bool pduseany { get; set; }
    public string pdvnitemid { get; set; }
    public string pdvnuofm { get; set; }
    public Nullable<int> pdvnunit { get; set; }
    public string pddescript { get; set; }
    public Nullable<decimal> pdvnprice { get; set; }
    public Nullable<int> pdvnqty { get; set; }
    public Nullable<int> pdrcvtype { get; set; }
    public string pdrcvline { get; set; }
    public Nullable<int> sysprdid { get; set; }
    public Nullable<int> pdvnorgqty { get; set; }
    public Nullable<int> sysshipid { get; set; }
    public string shipid { get; set; }
    public string shipdesc { get; set; }
    public string pdgl { get; set; }
    public Nullable<System.DateTime> pdshipdt { get; set; }
    public string pdinternalid { get; set; }
    public string pdmanufacid { get; set; }
    public string pdndc { get; set; }
    public string pdpatchargeid { get; set; }
    public string pdupn { get; set; }
    public string entitycode { get; set; }
    public string deptcode { get; set; }
    public string classcode { get; set; }
    public string expencode { get; set; }
    public string cadduser { get; set; }
    public Nullable<System.DateTime> dadd { get; set; }
    public string cedituser { get; set; }
    public Nullable<System.DateTime> dedit { get; set; }
    public Nullable<decimal> taxpct { get; set; }
    public Nullable<int> invoiceqty { get; set; }
    public string auditinfo { get; set; }
    public string totenumber { get; set; }
    public string export { get; set; }
    public Nullable<int> scheduledDrugIndex { get; set; }
    public string contractid { get; set; }
    public string refnum { get; set; }

那么真正的问题就变成了,如何使用属性 name 的值来正确反序列化 xml。有没有可能?

谢谢。

【问题讨论】:

  • 您可以添加当前用于反序列化的代码吗?

标签: c# .net xml serialization deserialization


【解决方案1】:

如果为返回的 xml 文件定义 XML Schema (.xsd) 文件,则可以使用 XSD.exe 命令行工具生成类。

Link to XSD Tool

或者,

如果是我,我根本不会反序列化它。相反,我会用 XDocument/XElement 对象等来解析它。

例如,我会为所有内容手动创建类并为它们提供更好的功能,例如,

public enum CurrencyType
{
    USD = 0,
    EUR = 1 //etc..
}
public class Money
{
    public CurrencyType CurrenyType { get; set; }
    public decimal Value { get; set; }

    public Money(XElement element)
    {
        if (element.Name.LocalName != "Money")
            throw new Exception(...);
        var aCurrency = element.Attribute("currency");
        this.CurrencyType = aCurrency == null || string.IsNullOrEmpty(aCurrency.Value) ? CurrencyType.USD : (CurrencyType)Enum.Parse(typeof(CurrencyType), aCurrency.Value);
        this.Value = element != null && !string.IsNullOrEmpty(element.Value) ? element.Value : 0;
    }
}

我会为每个复杂的子元素制作一个。然后我会创建一个名为 ItemDetail 的主要类,它将这些类公开为属性。在 ItemDetail 的构造函数中,我会将 xml 加载到一个元素,获取货币节点,并使用货币节点的 XElement 实例化货币类,等等。

我通常会走这条路,因为反序列化会为您的外部节点提供字符串列表或字典,我发现对它进行复杂的编码。通过自己手动完成,我可以为每个 Extrinsic 值创建属性,而无需找出复杂的属性映射规则来让反序列化器执行此操作。这样做通常会产生更好的代码(更容易遵循和使用)并且更灵活。

【讨论】:

  • 谢谢Ryios。这是一种非常有趣的方法,如果找不到自动方法,我很可能会走这条路。
  • 在您这样做之前,请检查网络服务是否支持特定的内容类型。许多现代 Web 服务默认为 xml,但如果您将获取内容类型指定为 application/json,它将为您提供 json 而不是 XML。在这种情况下,您可以使用 NewtonSoft 的 Json 库将 JSON 序列化为动态对象。或者您可以在 www.json2csharp.com 上发布 json,它会为您生成 c# 类代码。注意:您需要先将 json 字符串化,然后再将其发布到侧面。我在 chrome 控制台中执行此操作, var obj = JSON.strinify('paste json here');对象;复制粘贴到 json2csharp 中。
【解决方案2】:

一种可能是使用 xsd.exe

D:\WorkSpace\dump>xsd myxml.xml

或者甚至通过使用诸如

之类的在线工具进行下一步

http://www.httputility.net/xsd-to-csharp-vb-class.aspx

如果有正确的 xml 文件,这将为 System.XML.Serialization.XMLSerializer 生成易于使用的 C# 类来读取和写入 XML

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多