将cXML反序列化为C#类 [英] Deserializing cXML to C# Class

查看:214
本文介绍了将cXML反序列化为C#类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将cXML字符串反序列化为C#类。但是,反序列化时,除了根元素之外,我似乎什么也没得到。 如何反序列化XML文档似乎提供了最大的帮助,使用该示例,我我设法反序列化了根cXML标记,但这在嵌套对象 PunchOutSetupRequest 上不起作用,这是我真正需要反序列化的对象。

I'm trying to deserialize a cXML string into C# classes. However, when deserializing, I can't seem to get anything other than the root element to deserialize. How to Deserialize XML document seemed to provide the most help, and using that example I've managed to deserialize the root cXML tag, but this doesn't work on the nested object PunchOutSetupRequest which is the object I really need deserialized.

在向您展示代码墙之前,我的问题是如何在不更改 cXML的情况下,将这些对象正确反序列化为下面定义的cXML类.cs 文件?由于这是一个标准,因此除非绝对必要,否则我不想编辑它。我的代码是公平的游戏。在此先感谢您的帮助,因为我知道该主题在SO的各个方面都有涉及。

My question, before showing you the wall of code, is how can I properly deserialize these objects to the cXML classes defined below without changing the cXML.cs file? Since this is a standard I'd prefer not to edit it unless I absolutely have to. My code is fair game. Thank you in advance for any help since I know this topic is covered far and wide across SO.

我有一个用于cXML的XSD文件,我已经使用 xsd.exe 工具转换为C#类。为了避免淡化问题,我不会在此处粘贴整个架构,但是您可以转到 cxml.org 如果需要更完整的图片。

I have this XSD file for cXML that I've used the xsd.exe tool to convert into C# classes. I won't paste the whole schema here to avoid diluting the question, but you can go to cxml.org if you need a more complete picture.

我的cXML代码,仅反序列化属性,并且不包含定义的Header或Request对象在cXML中:

My Code for the cXML which just deserializes the attributes and doesn't contain Header or Request objects defined in the cXML:

using (TextReader reader = new StringReader(text))
            {
                try
                {
                    XmlRootAttribute xRoot = new XmlRootAttribute();
                    xRoot.ElementName = "cXML";
                    xRoot.IsNullable = true;
                    var serializer = new XmlSerializer(typeof(cXML), xRoot);
                    cxml = (cXML)serializer.Deserialize(reader);
                }
                catch (Exception ex)
                {
                    string r = "";
                }
            }

我在 PunchOutSetupRequest 反序列化。尽管我将 xRoot 元素设置为 PunchOutSetupRequest

My code for the PunchOutSetupRequest deserialization. This one throws an error when it sees cXML as the root node despite me setting the xRoot element to PunchOutSetupRequest.

using (TextReader reader = new StringReader(text))
            {
                try
                {
                    XmlRootAttribute xRoot = new XmlRootAttribute();
                    xRoot.ElementName = "PunchOutSetupRequest";
                    xRoot.IsNullable = true;
                    var serializer = new XmlSerializer(typeof(PunchOutSetupRequest), xRoot);
                    PunchOutSetupRequest request;
                    request = (PunchOutSetupRequest)serializer.Deserialize(reader);
                }
                catch (Exception ex)
                {
                    string r = "";
                }
            }

文本变量值(已编辑的数据):

<?xml version = '1.0' encoding = 'UTF-8'?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.1.007/cXML.dtd">
<cXML version="1.1.007" xml:lang="en-US" payloadID="" timestamp="2016-01-    04T03:21:32-05:00">
   <Header>
      <From>
         <Credential domain="">
            <Identity></Identity>
         </Credential>
      </From>
      <To>
         <Credential domain="">
            <Identity></Identity>
         </Credential>
      </To>
      <Sender>
         <Credential domain="">
            <Identity></Identity>
            <SharedSecret></SharedSecret>
         </Credential>
         <UserAgent></UserAgent>
      </Sender>
   </Header>
   <Request>
      <PunchOutSetupRequest operation="create">
         <BuyerCookie></BuyerCookie>
         <Extrinsic name="User"></Extrinsic>
         <BrowserFormPost>
            <URL></URL>
         </BrowserFormPost>
         <Contact>
            <Name xml:lang="en-US"></Name>
            <Email></Email>
         </Contact>
         <SupplierSetup>
            <URL></URL>
         </SupplierSetup>
      </PunchOutSetupRequest>
   </Request>
</cXML>

xsd.exe生成的cXML类(已分段)

cXML Class Generated by xsd.exe (fragmented)

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://tempuri.org/cXML")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://tempuri.org/cXML", IsNullable = false)]
public partial class cXML
{

private object[] itemsField;

private string versionField;

private string payloadIDField;

private string timestampField;

private string langField;

public cXML()
{
    this.versionField = "1.1.010";
}

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Header", typeof(Header))]
[System.Xml.Serialization.XmlElementAttribute("Message", typeof(Message))]
[System.Xml.Serialization.XmlElementAttribute("Request", typeof(Request))]
[System.Xml.Serialization.XmlElementAttribute("Response", typeof(Response))]
public object[] Items
{
    get
    {
        return this.itemsField;
    }
    set
    {
        this.itemsField = value;
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
[System.ComponentModel.DefaultValueAttribute("1.1.010")]
public string version
{
    get
    {
        return this.versionField;
    }
    set
    {
        this.versionField = value;
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string payloadID
{
    get
    {
        return this.payloadIDField;
    }
    set
    {
        this.payloadIDField = value;
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string timestamp
{
    get
    {
        return this.timestampField;
    }
    set
    {
        this.timestampField = value;
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified, Namespace = "http://www.w3.org/XML/1998/namespace")]
public string lang
{
    get
    {
        return this.langField;
    }
    set
    {
        this.langField = value;
    }
}
}    

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://tempuri.org/cXML")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://tempuri.org/cXML", IsNullable = false)]
public partial class PunchOutSetupRequest
{

private BuyerCookie buyerCookieField;

private Extrinsic[] extrinsicField;

private BrowserFormPost browserFormPostField;

private Contact[] contactField;

private SupplierSetup supplierSetupField;

private ShipTo shipToField;

private SelectedItem selectedItemField;

private ItemOut[] itemOutField;

private PunchOutSetupRequestOperation operationField;

/// <remarks/>
public BuyerCookie BuyerCookie
{
    get
    {
        return this.buyerCookieField;
    }
    set
    {
        this.buyerCookieField = value;
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Extrinsic")]
public Extrinsic[] Extrinsic
{
    get
    {
        return this.extrinsicField;
    }
    set
    {
        this.extrinsicField = value;
    }
}

/// <remarks/>
public BrowserFormPost BrowserFormPost
{
    get
    {
        return this.browserFormPostField;
    }
    set
    {
        this.browserFormPostField = value;
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Contact")]
public Contact[] Contact
{
    get
    {
        return this.contactField;
    }
    set
    {
        this.contactField = value;
    }
}

/// <remarks/>
public SupplierSetup SupplierSetup
{
    get
    {
        return this.supplierSetupField;
    }
    set
    {
        this.supplierSetupField = value;
    }
}

/// <remarks/>
public ShipTo ShipTo
{
    get
    {
        return this.shipToField;
    }
    set
    {
        this.shipToField = value;
    }
}

/// <remarks/>
public SelectedItem SelectedItem
{
    get
    {
        return this.selectedItemField;
    }
    set
    {
        this.selectedItemField = value;
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ItemOut")]
public ItemOut[] ItemOut
{
    get
    {
        return this.itemOutField;
    }
    set
    {
        this.itemOutField = value;
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public PunchOutSetupRequestOperation operation
{
    get
    {
        return this.operationField;
    }
    set
    {
        this.operationField = value;
    }
}
}


推荐答案

TL; DR;
我通过在将xsd文件转换为c#模型之前对其进行编辑来解决此问题。

TL;DR; I solved this by editing the xsd file prior to converting it to c# models.

在从DTD生成的XSD中,更改:

In the XSD generated from the DTD, change:

< xs:schema xmlns = http://tempuri.org/cXML xmlns :ds = uri:ds elementFormDefault = qualified targetNamespace = http://tempuri.org/cXML xmlns:xs = http://www.w3.org/2001/XMLSchema>

收件人:

< xs:schema xmlns:ds = uri:ds elementFormDefault = qualified xmlns:xs = http://www.w3.org/2001/XMLSchema>

详细说明:

如果您在DTD文件上使用Visual Studio的[XML]-> [Create Schema],则Visual Studio将生成具有目标名称空间 http://tempuri.org/cXML 的XSD。

If you use Visual studio's [XML]->[Create Schema] on the DTD file, visual studio will generate an XSD with target namespace http://tempuri.org/cXML.

如果生成C#模型从XSD中删除,而无需删除这些名称空间引用(使用xsd2code或Visual Studio' s xsd blah.xsd / classes ),则XmlSerializer会希望在要反序列化的XML中使用该命名空间。

If you generate C# models from that XSD without removing these namespace references (using xsd2code or visual studio's xsd blah.xsd /classes), then XmlSerializer will expect that namespace to be used in the XML you want to deserialize.

诸如SAP Ariba之类的平台不使用该tempuri.org命名空间。 XML节点将因此被跳过,因为如果没有名称空间引用,则无法识别这些节点。我发现这是因为触发了XmlSerializer.UnknownNode事件,告诉我它无法识别Header和Request之类的节点,并且它期望具有tempuri.org命名空间前缀的节点。

Platforms such as SAP Ariba do not use that tempuri.org namespace. The XML nodes will thus be skipped, because without the namespace reference the nodes are not recognized. I found that out because the XmlSerializer.UnknownNode event fired, telling me it doesn't recognize the nodes such as Header and Request, and it expects nodes with a tempuri.org namespace prefix.

因此,如果您首先从XSD中删除伪造的名称空间,然后生成类(为此,我使用xsd2code),那么您将获得有效的c#(可反序列化)模型。

So if you first remove the bogus namespace from the XSD, and then generate the classes (I used xsd2code for that), then you end up with valid c# (de)serializable models.

然后,您也不需要使用 xRoot.ElementName = cXML; 。它将从c#类中拾取根节点,因为它没有在tempuri.org命名空间中寻找< cXML> 标记。

You then also don't need to use xRoot.ElementName = "cXML";. It will pick up the root node from the c# classes, because its not looking for a <cXML> tag with the tempuri.org namespace.

这样,您无需破坏从XSD生成的类,就可以按原样使用它们。

So this way you do not need to 'gut' the classes generated from XSD, and you can use them as is.

这篇关于将cXML反序列化为C#类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆