XML使用替换组从xsd.exe生成的代码序列化无效(无效的xsi:类型错误)

时间:2010-11-26 14:33:29

标签: .net xml xsd xml-serialization xsd.exe

我已经从一些3GPP XSD(多个XSD文件/命名空间)生成了一些C#类,除了替换组中使用的抽象类型的具体实例的一个问题之外,它还非常适合序列化。

首先,架构的相关部分:

(genericNrm.xsd)

<element name="ManagedElement">
    <complexType>
      <complexContent>
        <extension base="xn:NrmClass">
          <sequence>
            ...
            <choice minOccurs="0" maxOccurs="unbounded">
              <element ref="xn:IRPAgent"/>
              <element ref="xn:ManagedElementOptionallyContainedNrmClass"/>
              <element ref="xn:VsDataContainer"/>
            </choice>
          </sequence>
        </extension>
      </complexContent>
    </complexType>
</element>

<element
    name="ManagedElementOptionallyContainedNrmClass"
    type="xn:NrmClass"
    abstract="true"
/>

(eutran.xsd)

<element name="ENBFunction" substitutionGroup="xn:ManagedElementOptionallyContainedNrmClass">
    <complexType>
      <complexContent>
        <extension base="xn:NrmClass">
          <sequence>
            <element name="attributes" minOccurs="0">
              <complexType>
                <all>
                  <element name="userLabel" type="string" minOccurs="0"/>
... etc

从包含ENBFunction的简单ManagedElement序列化的XML是:

<ManagedElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="1234" xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm">
    <ManagedElementOptionallyContainedNrmClass xmlns:q1="http://www.3gpp.org/ftp/specs/archive/32_series/32.765#eutranNrm" xsi:type="q1:ENBFunction" id="1234">
      <q1:attributes>
        <q1:userLabel>label</q1:userLabel>
      </q1:attributes>
    </ManagedElementOptionallyContainedNrmClass>
  </ManagedElement>

内置的visual studio XML验证抱怨该元素,声明“这是一个无效的xsi:类型”http://www.3gpp.org/ftp/specs/archive/32_series/32.765#eutranNrm:ENBFunction'。

序列化的XML错误还是验证?它与单独的命名空间有关吗?

我可以很好地反序列化XML,但我需要生成的XML符合模式(不更改模式)。我发现如果我手动将XML更改为以下内容,则错误消失(我发现它也更容易阅读):

<ManagedElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="1234" xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm">
    <q1:ENBFunction xmlns:q1="http://www.3gpp.org/ftp/specs/archive/32_series/32.765#eutranNrm" id="1234">
      <q1:attributes>
        <q1:userLabel>label</q1:userLabel>
      </q1:attributes>
    </q1:ENBFunction>
</ManagedElement>

我可以强制串行器以这种方式输出吗?

感谢您的期待...

1 个答案:

答案 0 :(得分:2)

我通过手动编辑从XSD生成的代码解决了这个问题。 ManagedElement类Items集合上需要XmlElementAttribute以确保序列化正常工作:

[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="http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm", IsNullable=false)]
public partial class ManagedElement : NrmClass {

...

[System.Xml.Serialization.XmlElementAttribute("ENBFunction", typeof(ENBFunction), Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.765#eutranNrm")]
public NrmClass[] Items {
...

从ManagedElement继承的所有类都需要此属性,以确保在序列化时使用正确的类。