为啥在 XSD 中定义为属性时,自动生成的类中的字段会序列化为元素?

Posted

技术标签:

【中文标题】为啥在 XSD 中定义为属性时,自动生成的类中的字段会序列化为元素?【英文标题】:Why is a field in an auto-generated class serialized into an element when defined as an attribute in the XSD?为什么在 XSD 中定义为属性时,自动生成的类中的字段会序列化为元素? 【发布时间】:2012-07-12 01:39:44 【问题描述】:

我正在尝试通过 REST API(使用 WCF)将一个相当复杂的对象公开为 XML。

但是,该对象是由 XSD 文件定义的,因此我使用 xsd.exe 工具生成了类。问题是,似乎当我的对象被序列化为 XML 时,一个属性(在 xsd 中定义)被序列化为一个元素。我不明白为什么。目前,我假设我的 xsd 以某种方式允许这样做,但我不知道为什么。 我不做任何自定义序列化,我让框架来处理。

谁能解释为什么会发生这种情况以及如何控制这种行为?

这里是 xsd 中包含元素和属性的部分。 编辑:有问题的属性是版本

<xs:schema xmlns:b="http://some.namespace.com/" xmlns="http://someothernamespace.com/" elementFormDefault="qualified" targetNamespace="http://someothernamespace.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="JobPositionPosting.xsd" />
  <xs:element name="Envelope">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="Sender" />
        <xs:element minOccurs="0" ref="TransactInfo" />
        <xs:element maxOccurs="unbounded" ref="Packet" />
      </xs:sequence>
      <xs:attribute fixed="0.52" name="version" type="xs:string" use="required" />
    </xs:complexType>
  </xs:element>

这是生成的代码。

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "<removed>")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://somenamespace.com", IsNullable = false)]
public partial class Envelope


    /// <remarks/>
    public Sender Sender;

    /// <remarks/>
    public TransactInfo TransactInfo;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Packet")]
    public Packet[] Packet;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute("version")]
    public string version;

    public Envelope()
    
        this.version = "0.52";
    

这是从 REST 服务返回的 xml,即序列化对象。

<!-- (the rest o the xml is left out on purpose) -->
<Envelope>
    <senderField i:nil="true"/>
    <transactInfoField i:nil="true"/>
    <versionField>0.52</versionField>
</Envelope>

谢谢!

【问题讨论】:

【参考方案1】:

xsd.exe 生成供System.Xml.Serialization.XmlSerializer 使用的类,而您的 REST 服务正在使用System.Runtime.Serialization.DataContractSerializer 的某些变体。

对于DataContractSerializer,您应该改用svcutil.exe

svcutil.exe /help
svcutil.exe schema.xsd /dconly

【讨论】:

我尝试了您的解决方案,但似乎 svcutil 无法处理我的 xsd。无论我尝试了什么选项,它都告诉我它无法从程序集中加载数据(这表明它不知道如何处理 xsd)。相反,我尝试修改生成的类以改为使用 XmlSerializer。我遇到了一些问题,但我希望能尽快解决。 @Anton 看来svcutil.exe 不支持XML 属性,尤其是use="required" 设置。只有xsd.exe 允许这样做。要将 XmlSerializer 与 WCF 一起使用,您可以在类上指定 XmlSerializerFormat 属性。

以上是关于为啥在 XSD 中定义为属性时,自动生成的类中的字段会序列化为元素?的主要内容,如果未能解决你的问题,请参考以下文章

向依赖于XSD中的信息的JAXB生成的类添加注释

JAXB xs:maxLength 和 minOccurs="0" 未在 xsd 生成的类中显示

如何定义XSD并在XML中使用XSD

从 XSD 生成 XML 中的自定义属性

为啥我看不到 XCode 中的类中存在的所有可用方法或属性?

JAXB:为啥在生成的 xml 文档中未使用定义的命名空间前缀?