Retrieve default value for Optional Element in an XSD - c#

I have the following XML:
<Person>
<Name>James</Name>
<Age>18</Age>
</Person>
In the XSD that validates this XML, I want to add another element. I want this element to be optional but with a default value - so if it is missing when the XML is validated, it is populated with the default value. Let's say the new element is "NumberOfSiblings" which defaults to 0. I've done this like so:
<xs:element name="Person">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Age" type="xs:integer" />
<xs:element name="NumberOfSiblings" type="xs:integer" minOccurs="0" default="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
So now let's assume I come to parse the XML above in .Net / C#. Is there a way to validate it so it would automatically create the element with the default value, and therefore the parser would not fall over? If not, what's the correct way to obtain this default value from the XSD?

Related

primitive class being ignore when serializing xsd generated class

I used xsd.exe to generate a .cs class.
The xsd file as below
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="SendComments">
<xs:complexType>
<xs:sequence>
<xs:element name="Input">
<xs:complexType>
<xs:sequence>
<xs:element name="TransId" maxOccurs="1" minOccurs="0" type="xs:string"/>
<xs:element name="SampleId" minOccurs="0" maxOccurs="1" type="xs:long"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Output" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
In my generated class, it has the correct field generated.
However, when I call the serializer. The SampleId field being ignored.
Serializer code segment:
var serializer = new XmlSerializer(typeof(SendComments));
using (StringWriter stringWriter = new StringWriter())
{
serializer.Serialize(stringWriter, SPCComment);
return stringWriter.ToString();
}
Result:
<?xml version="1.0" encoding="utf-16"?>
<SPCSendComments xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Input>
<TransId>-</TransId>
</Input>
</SPCSendComments>
I tried with other .xsd file, all the primitive type (bool, int, long) is being ignored when serializing.
I wonder what will be the cause that primitive type being ignored.
Your generated class has an extra field SampleIdSpecified that indicates if the field is null or not. Set that to true and the field will be serialized.
If you set TransId to null, that will also be ignored.
They're being ignored because they're optional fields in your schema. They have minOccurs = 0 which means that they don't need to be there for the XML to be valid.

XML Schema Validation for unknown elements

I am trying to validate the XML with the schema in C#. I will be having an unknown elements under the row element. I am using xs:any, I am getting the below error
The element 'row' has invalid child element 'Name'.
Schema -
<xs:element name="table">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="row">
<xs:complexType>
<xs:sequence>
<xs:any processContents="lax"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
XML -
<table>
<row>
<ProductID>994</ProductID>
<Name>LL Bottom Bracket</Name>
<ProductModel>LL Bottom Bracket</ProductModel>
<CultureID>en </CultureID>
<Description>Chromoly steel.</Description>
</row>
</table>
You've not specified a maxOccurs on the xs:any, and maxOccurs defaults to 1, which means that the second element, Name, is not allowed, thus the error message,
The element 'row' has invalid child element 'Name'.
Correct by adding maxOccurs="unbounded" to xs:any:
<xs:any processContents="lax" macOccurs="unbounded"/>

When validate XSD against XML getting an error?

I'm trying to validate XSD aginst XML but getting an error
The element 'Table' has incomplete content. List of possible elements expected: 'IP21TAG'.
XML:
<NewDataSet>
<Table>
<SITE>VMD</SITE>
<TANK>65-12-392</TANK>
<SERVICE>HZLPG</SERVICE>
</Table>
<Table>
<SITE>VMD</SITE>
<TANK>65-12-392</TANK>
<SERVICE>HZLPG</SERVICE>
<IP21TAG>BC-BBH-OS-4LI21392</IP21TAG>
</Table>
</NewDataSet>
XSD:
<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="NewDataSet">
<xs:complexType>
<xs:sequence>
<xs:element name="Table">
<xs:complexType>
<xs:sequence>
<xs:element name="SITE" type="xs:string" />
<xs:element name="PLANT" type="xs:string" />
<xs:element name="TANK" type="xs:string" />
<xs:element name="SERVICE" type="xs:string" />
<xs:element name="IP21TAG" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Can anyone help me how to solve this?
Thanks in advance.
Obviously, solution is to set minOccurs="0" on elements that are optional.
However, error message in Visual Studio displayes even optional elements in the "possible element name" list, so it is not obvious if you miss minOccurs on an element.
My problem was that ONE element missed the minOccurs="0", and error message listed ALL, approximately 100, elements...
You omit minOccurs in <xs:element> node of your schema, its default is one (see specifications) then if you don't specify that node your XML won't be validated against that schema.
If that node is optional simply change your XSD to reflect that. Here I changed just IP21TAG and PLANT (because they're both not present in your example XML but if others are optional too you should change them accordingly):
<xs:element name="IP21TAG" type="xs:string" minOccurs="0"/>
<xs:element name="PLANT" type="xs:string" minOccurs="0" />
If that element is not optional then to be wrong is your XML, you may - for example - provide an empty string instead of a missing node:
<NewDataSet>
<Table>
<SITE>VMD</SITE>
<TANK>65-12-392</TANK>
<SERVICE>HZLPG</SERVICE>
<IP21TAG></IP21TAG>
<PLANT></PLANT>
</Table>
</NewDataSet>

Modify xsd not to look for specific order of tags

I need to fix the error message below:
Error occured while validating xmlThe element 'UserFields' has invalid child element 'LastApproverID'. List of possible elements expected: 'FirtApproverID'.
Below is my xsd for validating the xml schema :
<xs:element name="UserFields" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="FirtApproverID" type="xs:string" minOccurs="1" />
<xs:element name="LastApproverID" type="xs:string" minOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
The order of the firstapproverid and lastapproverid does not matter but the tag need to occur atleast once.
i.e it can appear
<UserFields>
<LastApproverID>123</LastApproverID>
<FirtApproverID>456</FirtApproverID>
</UserFields>
OR
<UserFields>
<FirtApproverID>456</FirtApproverID>
<LastApproverID>123</LastApproverID>
</UserFields>
The <xs:all> indicator can solve your problem.
See here for answer
Please, improve your Google skills.

Deserializing XML to Objects defined in multiple schemas

I have an XML document containing types from 2 XML schemas. One (theirs.xsd) is a proprietary schema that I am integrating with (and cannot edit). To do this I am defining my own type (mine.xsd) that is an element within an 'any' element is the proprietary type.
I use Visual Studio's xsd.exe to generate C# classes from the schemas. However, the 'any' element in the proprietary type is generated as XmlElement[], and therefore my type doesn't get deserialized.
So I guess I can go one of two ways: either generate classes that will deserialize my type rather then keeping it as an XmlElement, or take the XmlElements and deserialize them individually. To deserialize I need an XmlReader, so I would need to go from an XmlElement to an XmlReader which I'm not sure how to do. Thanks.
Example:
File: theirs.xsd
<xs:element name="ProprietaryContainer">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
File: mine.xsd
<xs:element name="MyPairType">
<xs:complexType>
<xs:sequence>
<xs:element name="key" type="xs:string"/>
<xs:element name="value" type="xs:long"/>
</xs:sequence>
</xs:complexType>
</xs:element>
File: message.xml
<their:ProprietaryContainer>
<their:name>pairContainer</their:name>
<mine:MyPairType>
<mine:key>abc</mine:key>
<mine:value>long</mine:value>
</mine:MyPairType>
</their:ProprietaryContainer>
From the question:
To deserialize I need an XmlReader, so I would need to go from an XmlElement to an XmlReader which I'm not sure how to do
using(XmlReader reader = new XmlNodeReader(element)) {
//... use reader
}

Categories

Resources