Reputation: 63728
Given XSD like:
<xs:complexType name="accident">
<xs:sequence>
<xs:element name="NAME" type="xs:string" />
<xs:element name="DESCRIPTION" type="xs:string" />
<xs:element name="CREATIONDATE" type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
<xs:element name="accidents">
<xs:complexType>
<xs:sequence>
<xs:element name="accident" type="accident" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
I expect XML like:
<?xml version="1.0" encoding="UTF-8"?>
<accidents>
<accident>
<NAME>Accident 123</NAME>
<DESCRIPTION>Car crash</DESCRIPTION>
<CREATIONDATE>2016-01-20T12:08:00+00:00</CREATIONDATE>
</accident>
</accidents>
I used XSD2Code to generate C# classes so I can easy deserialize XML from a web-service. But they weren't working right - they were successfully loading a test XML like my example but there were zero accident
elements.
So I decided to reverse the process:
accidents aa = new accidents();
accident a = new accident();
a.NAME = "test";
aa.accident.Add(a);
aa.SaveToFile("accidents.xml");
This emitted the following XML:
<?xml version="1.0"?>
<accidents xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<accident>
<accident>
<NAME>test</NAME>
<CREATIONDATE>0001-01-01T00:00:00</CREATIONDATE>
</accident>
</accident>
</accidents>
If I attempt to deserialize that XML, it works just fine. But note, there is a nested accident
which is not correct and I have no idea it would do this or what to do to fix it!
This seems to be a similar question but since it didn't get much attention and the XSD isn't included, I'm not sure: xsd2code creates extra nested collection when serializing lists
Upvotes: 3
Views: 793
Reputation: 161
I'm a bit late on the scene for this one but here goes anyway !!
I have been using Xsd2Code myself for a while to take advantage of some cool features, but I have found it does have some annoying quirks. I agree that this issue you describe looks like a bug. However I have found that the issue disappears if your collection is itself a child element of another complex type. If you are happy for your "accidents" to exist as a property of a "report" for example, then you would alter your schema as follows:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:complexType name="accident">
<xs:sequence>
<xs:element name="NAME" type="xs:string" />
<xs:element name="DESCRIPTION" type="xs:string" />
<xs:element name="CREATIONDATE" type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="accidents">
<xs:sequence>
<xs:element name="accident" type="accident" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="report">
<xs:sequence>
<xs:element name="accidents" type="accidents"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
When you run this through the Xsd2Code tool you will find that the generated code creates the accidents property of report type as a list of accidents and will serialize in the way you would expect it.
Your test code should look more like this:
report r = new report();
r.accidents = new List<accident>();
accident a = new accident();
a.NAME = "test";
r.accidents.Add(a);
r.SaveToFile("accidents.xml");
The dodgy accidents class is still generated unfortunately - which could cause confusion to other developers, but there is a way to prevent this. First, put the accident and accidents complexType definitions in a file, accidents.xsd. Then put the report definition in report.xsd with an include statement referencing accidents.xsd. Only pass report.xsd through the Xsd2Code tool. The malformed accidents class will not appear in the generated code. This is just an illustrative example of course - expand as required. In the absence of a fix, this has been a very good solution for me - hopefully it will suit your needs.
Upvotes: 1
Reputation: 1161
You might start by specifying a target namespace and explicit qualification flags in your XSD. That is, convert your xsd to:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.com/foo"
xmlns="http://example.com/foo">
<xs:complexType name="accident">
<xs:sequence>
<xs:element name="NAME" type="xs:string" />
<xs:element name="DESCRIPTION" type="xs:string" />
<xs:element name="CREATIONDATE" type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
<xs:element name="accidents">
<xs:complexType>
<xs:sequence>
<xs:element name="accident" type="accident" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
and your XML to:
<?xml version="1.0" encoding="UTF-8"?>
<accidents xmlns="http://example.com/foo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/foo foo.xsd">
<accident>
<NAME>Accident 123</NAME>
<DESCRIPTION>Car crash</DESCRIPTION>
<CREATIONDATE>2016-01-20T12:08:00+00:00</CREATIONDATE>
</accident>
</accidents>
(You will need to save your xsd file as foo.exe for the above reference to work).
I'm not sure if this will fix your XSD2Code issue, but I've used this header format with xsd.exe for lots of equivalent (and much more complex) code. It gets you Intellisense in your XML and might also be sufficient to get XSD2Code to behave properly.
Upvotes: 0