Reputation: 567
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
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