I have the schema below:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="WSParam">
<xs:complexType>
<xs:sequence>
<xs:element name="domain" type="xs:string"/>
<xs:element name="userName" type="xs:string"/>
<xs:element name="Cases">
<xs:complexType>
<xs:sequence>
<xs:element name="caseName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I expected the output of DataSet.GetXml() below:
<NewDataSet>
<WSParam>
<domain>ad</domain>
<userName>admin</userName>
<Cases>
<caseName>case 1</caseName>
</Cases>
</WSParam>
</NewDataSet>
But the output is:
<NewDataSet>
<WSParam>
<domain>ad</domain>
<userName>admin</userName>
</WSParam>
<Cases>
<caseName>case 1</caseName>
</Cases>
</NewDataSet>
Anyone confirm me the correct behavior of DataSet.GetXml() with complex type or I miss something.
Any guidance is highly appreciated.
UPDATES1:
I am using DataSet.ReadXmlSchema("...xsd"). From that, I use DataSet.Tables[..] to create DataTable to put the data. Then call DataSet.GetXml() to get the string XML representation.
UPDATES2:
Code:
private void button2_Click(object sender, EventArgs e)
{
String sXSD = @"C:\WindowsFormsApplication1\WindowsFormsApplication1\XMLFile1.xsd";
DataSet dsXSD = new DataSet();
dsXSD.ReadXmlSchema(sXSD);
int k = 0;
do
{
DataRow d;
d = dsXSD.Tables["tblUser"].NewRow();
int i = 0;
do
{
d[i] = k;
i = (i + 1);
} while (i < dsXSD.Tables["tblUser"].Columns.Count);
dsXSD.Tables["tblUser"].Rows.Add(d);
d = dsXSD.Tables["tblUserRole"].NewRow();
i = 0;
do
{
d[i] = k;
i = (i + 1);
} while (i < dsXSD.Tables["tblUserRole"].Columns.Count);
dsXSD.Tables["tblUserRole"].Rows.Add(d);
k = (k + 1);
} while (k < 3);
dsXSD.WriteXml("c:\\test.xml");
}
XSD:
<?xml version="1.0" encoding="utf-16" ?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="tblUser">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="UserID" type="xsd:int" />
<xsd:element name="FullName" type="xsd:string" nillable="true" />
<xsd:element name="tblUserRole">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="UserID" type="xsd:int" />
<xsd:element name="RoleID" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
OUTPUT:
<?xml version="1.0" standalone="yes"?>
<NewDataSet>
<tblUser>
<UserID>0</UserID>
<FullName>0</FullName>
<tblUserRole>
<UserID>0</UserID>
<RoleID>0</RoleID>
</tblUserRole>
</tblUser>
<tblUser>
<UserID>1</UserID>
<FullName>1</FullName>
<tblUserRole>
<UserID>1</UserID>
<RoleID>1</RoleID>
</tblUserRole>
</tblUser>
<tblUser>
<UserID>2</UserID>
<FullName>2</FullName>
<tblUserRole>
<UserID>2</UserID>
<RoleID>2</RoleID>
</tblUserRole>
</tblUser>
</NewDataSet>
I'm not sure if it is possible using datasets.
But you could do it yourself by creating a non standard microsoft dataset xsd. It requires a little work but you can afterwards tweak it as you like.
The key is to use an xs:group.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="NewDataSet">
<xs:complexType>
<xs:sequence>
<xs:element name="WSParam">
<xs:complexType>
<xs:sequence>
<xs:element name="domain" type="xs:string" minOccurs="0" />
<xs:element name="userName" type="xs:string" minOccurs="0" />
<xs:group ref="CasesGroup" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:group name="CasesGroup">
<xs:sequence>
<xs:element name="Cases">
<xs:complexType>
<xs:sequence>
<xs:element name="CaseName" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
</xs:schema>
For the above xsd (which I named wsparam.xsd) run "xsd.exe wsparam.xsd /classes /n:Yournamespace"
Now you can fill the data from code
NewDataSetWSParam p = new NewDataSetWSParam();
p.domain = "ad";
p.userName = "admin";
p.Cases = new NewDataSetWSParamCaseName[] {
new NewDataSetWSParamCaseName () { Value ="case 1" }
};
Now comes the tricky part Using a non standard XmlTextWriter when serializing to strip namespace attributes from the XML file
public class NoNamespaceXmlWriter : XmlTextWriter
{
public NoNamespaceXmlWriter(System.IO.TextWriter output)
: base(output)
{
Formatting = System.Xml.Formatting.None;
}
public override void WriteStartDocument() { }
public override void WriteStartElement(string prefix, string localName, string ns)
{
base.WriteStartElement("", localName, "");
}
}
Use the code below to Serialize you object
string serialXML = string.Empty;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer serializer = new XmlSerializer(p.GetType());
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (XmlWriter writer = new RDECommon.Xml.NoNamespaceXmlWriter(sw))
{
serializer.Serialize(writer, p, ns);
serialXML = sb.ToString();
}
serialXML contains your xml
<NewDataSet>
<WSParam>
<domain>ad</domain>
<userName>admin</userName>
<Cases>
<caseName>case 1</caseName>
</Cases>
</WSParam>
</NewDataSet>