如何正确设置 class 结构以正确反序列化 XML?

How to properly setup a class structure to properly de-serialize XML?

--更新--

其实再看一遍代码,我应该改一下问题。在下面添加了更多说明。

我有一个从 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>

如何设置我的 class 结构以便正确反序列化? class 本身由 PetaPoco 渲染,因此每个 <Extrinsic> 节点都是数据库中 class/field 的 属性。或者做不出来,需要手动处理,我一直在苦苦思索,一直没有找到好的自动化方式。

--更新--

这就是我要反序列化为

的 class
    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。有可能吗?

谢谢。

一种可能是使用 xsd.exe

D:\WorkSpace\dump>xsd myxml.xml

甚至可以使用

等在线工具进行下一步

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

在适当的 xml 文件的情况下,这将生成易于使用的 C# 类 供 System.XML.Serialization.XMLSerializer 读写 XML

如果您为返回的 xml 文件定义一个 XML 模式 (.xsd) 文件,您可以生成 classes 与 XSD.exe 命令行工具。

Link to XSD Tool

或者,

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

来解析它

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

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 的主要内容,它将那些 classes 作为属性公开。在 ItemDetail 的构造函数中,我会将 xml 加载到一个元素,获取金钱节点,并使用金钱节点的 XElement 实例化金钱 class,等等

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