2

I've generated some C# classes from some 3GPP XSDs (multiple XSD files/namespaces) and it works great for serialization apart from one problem with concrete instances of an abstract type used in a substitution group.

Firstly, the relevant parts of the schema:

(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

The XML serialised from a simple ManagedElement with contained ENBFunction is:

<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>

The built in visual studio XML validation complains about the element, stating "This is an invalid xsi:type 'http://www.3gpp.org/ftp/specs/archive/32_series/32.765#eutranNrm:ENBFunction'.

So is the serialized XML wrong or the validation? Is it something to do with the separate namespaces?

I can deserialize the XML just fine but I need the generated XML to be schema compliant (without changing the schemas). I found that if I manually change the XML to the following, the error disappears (and I find it easier to read also):

<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>

Can I force the serializer to output it this way?

Thanks for looking...

John Saunders
  • 160,644
  • 26
  • 247
  • 397
zeroid
  • 701
  • 7
  • 19
  • 1
    Good luck getting the XML Serializer to deal with something this complex. You may be better off "rolling your own" using LINQ to XML, or at best, have some of your troublesome classes implement `IXmlSerializable`, and handle those "by hand".` – John Saunders Nov 26 '10 at 21:55
  • Thanks, I am considering my options but under pressure to get something working quickly. I'm a bit confused about the error related to xsi:type to be honest - is the XML generated using this incorrectly (it looks valid to me)? – zeroid Nov 29 '10 at 14:14

1 Answers1

2

I solved this by manually editing the code generated from the XSD. An XmlElementAttribute is needed on the ManagedElement classes Items collection to ensure the serialisation works correctly:

[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 {
...

This attribute is required for all classes inherited from ManagedElement to ensure the correct one is used at serialization time.

zeroid
  • 701
  • 7
  • 19