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

时间:2015-03-26 15:27:33

标签: c# .net xml serialization deserialization

- 更新 -

实际上,在再次查看代码之后,我应该重新解释这个问题。在下面添加了更多说明。

我有一个从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呈现,因此每个<Extrinsic>节点都是数据库中类/字段的属性。或者也许它无法完成,并且需要手动处理,我一直在讨论这个问题,并且无法找到一个好的自动方式。

- 更新 -

这就是我试图反序列化为

的类
    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。它甚至可能吗?

谢谢。

2 个答案:

答案 0 :(得分:2)

如果为回来的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加载到Element,获取money节点,并使用XElement为money节点实例化money类等。

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

答案 1 :(得分:0)

一种可能是使用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