Thomas853
Thomas853

Reputation: 567

XmlAnyElementAttribute: How to add items to List<System.Xml.XmlElement> for XSD <any> element in xsd2code created class?

I am using xsd2code in order to create C# classes which can serialize/deserialize XML files based on a set of XSD files.

One XSD file contains an <any> element:

<xs:complexType name="AnyPlugInContainerType">
  <xs:sequence>
    <xs:any namespace="http://www.extra-standard.de/namespace/plugins/1" minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
</xs:complexType>

The XSD creator expects that elements based on the following abstract type are used to fill the any sequence:

<xs:complexType name="AbstractPlugInType" abstract="true"/>

The generated C# code of the first XSD section reads:

[XmlAnyElementAttribute(Namespace = "http://www.extra-standard.de/namespace/plugins/1", Order = 0)]
public List<System.Xml.XmlElement> Any
{
  get { return _any; }
  set { _any = value; }
}

When populating an object in C# which should be serialized later to an XML file, how can I add items to the Any list?

In order to create an XmlElement, I think I need an XmlDocument first. Afterwards, XmlDocument.CreateElement can be called. How do I get the XmlDocument?

When trying to change the type of the elements in the Any list from XmlElement to AbstractPlugInType, the following run-time error is raised when serializing the object:

XmlAnyElement can only be used with classes of type XmlNode or a type deriving from XmlNode

Do I need to manually replace the XmlAnyElementAttribute attribute with XmlArrayItemAttribute leading to:

[XmlArrayItemAttribute("AnyPlugInContainerType"Namespace = "http://www.extra-standard.de/namespace/plugins/1", Order = 0)]
public List<AbstractPlugInType> Any
{
  get { return _any; }
  set { _any = value; }
}

Any help appreciated!

(An old question on a similar problem exists which has been unanswered so far: Xsd2Code - Using <any> element to join schemas)

Upvotes: 0

Views: 693

Answers (1)

martijn
martijn

Reputation: 495

The only way I got this to work is a very cumbersome method. First you create the desired structure in an object. You serialize that object and use that as input for a new XmlDocument and then you add the DocumentElement to the any elementlist.

here is a small example that could help you

the msg.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/msg" xmlns:type="http://tempuri.org/type" targetNamespace="http://tempuri.org/msg" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:import namespace="http://tempuri.org/type" schemaLocation="type.xsd"/>
    <xs:element name="ExampleMsg">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Parent">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="Child1" type="xs:string"/>
                            <xs:element name="Child2" type="type:AnyType"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

the Type.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/type" targetNamespace="http://tempuri.org/type" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:complexType name="AnyType">
        <xs:sequence>
            <xs:any namespace="##targetNamespace" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="Mike">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Age" type="xs:int"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="John">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Age" type="xs:int"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="Nick">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Age" type="xs:int"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

the switches used in xsd to code (version 5.2) using an cmd file:

@echo off
set exepad=%programfiles(x86)%\Xsd2Code\xsd2code.exe
set sourcepad=%~dp0..\..\

set xsdpad=%sourcepad%ConsoleApp\xsd
set Outpad=%sourcepad%ConsoleApp\Messages

Set NameSpace=ConsoleApp.Messages

"%exepad%"  "%xsdpad%\\type.xsd" /o %Outpad%\type.cs /n %NameSpace% /l cs /pl Net45 /s /xml /sm Serial /dm Deserial /ssp /xa /emt /kro /uct /ust /Indent2Space 
"%exepad%"  "%xsdpad%\\msg.xsd" /o %Outpad%\msg.cs /n %NameSpace% /l cs /pl Net45 /s /xml /sm Serial /dm Deserial /ssp /xa /emt /kro /utc /ust /Indent2Space 

pause

the code:

static void Main(string[] args)
        {
            var msg = new ExampleMsg {Parent = new ExampleMsgParent {Child1 = "Rob"}};

            var mike = new Mike {Age = 1};
            var john = new John {Age = 2};
            var nick = new Nick {Age = 3};

            var xdoc = new XmlDocument();
            
            xdoc.LoadXml(mike.Serial());
            msg.Parent.Child2.Any.Add(xdoc.DocumentElement);

            xdoc.LoadXml(john.Serial());
            msg.Parent.Child2.Any.Add(xdoc.DocumentElement);

            xdoc.LoadXml(nick.Serial());
            msg.Parent.Child2.Any.Add(xdoc.DocumentElement);

            var msgstring = msg.Serial();
            Console.WriteLine(msgstring);

            Console.ReadLine();
        }

and the output:

<?xml version="1.0" encoding="utf-8"?>
<ExampleMsg xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/msg">
    <Parent>
        <Child1>Rob</Child1>
        <Child2>
            <Mike xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/type">
                <Age>1</Age>
            </Mike>
            <John xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/type">
                <Age>2</Age>
            </John>
            <Nick xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/type">
                <Age>3</Age>
            </Nick>
        </Child2>
    </Parent>
</ExampleMsg>

Upvotes: 1

Related Questions