views:

133

answers:

1

Hi, i'm trying to learn a little bit XSD and I'm trying to create a XSD for this xml:

<Document>
  <TextBox Name="Username" />
  <TextBox Name="Password" />
</Document>

... so there's an element, which is an abstract complex type. Every element have elements and so on. Document and TextBox are extending Element.

I trid this:

<?xml version="1.0" encoding="utf-8" ?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"&gt;
  <xs:element name="Document">
    <xs:complexType>
      <xs:complexContent>
        <xs:extension base="Element">

        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="Element" abstract="true">
    <xs:sequence minOccurs="0" maxOccurs="unbounded">
      <xs:element name="Element" type="Element"></xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="TextBox">
    <xs:complexContent>
      <xs:extension base="Element">
        <xs:attribute name="Name" type="xs:string" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>

I compiled it to C# with Xsd2Code, and now I try to deserialize it:

var serializer = new XmlSerializer(typeof(Document));

var document = (Document)serializer.Deserialize(new FileStream("Document1.xml", FileMode.Open));

foreach (var element in document.Element1)
{
    Console.WriteLine(((TextBox)element).Name);
}

Console.ReadLine();

and it dosen't print anything. When I try to serialize it like so:

var serializer = new XmlSerializer(typeof(Document));

var document = new Document();

document.Element1 = new List<Element>();

document.Element1.Add(new TextBox()
{
    Name = "abc"
});

serializer.Serialize(new FileStream("d.xml", FileMode.Create), document);

...the output is:

<?xml version="1.0"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <Element1>
    <Element xsi:type="TextBox">
      <Element1 />
      <Name>abc</Name>
    </Element>
  </Element1>
</Document>

When it should be something like:

<?xml version="1.0"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <TextBox Name="abc" />
</Document>

Any ideas how to fix the xsd or another code generator?

Thanks.

A: 

In the XSD code, look at the line where you declare an element named "Element". This element should be named as such <xs:element name="TextBox" /> if you want to use <TextBox/> in your XML files.

With the above change implemented, you could run xsd.exe /c YourFile.xsd to generate a C# class from the XSD. Include the generated file in your C# project and you'll be able to use it like this:

  Document d = new Document();
  d.TextBox = new TextBox[]
  {
    new TextBox() { Name = "Username" },
    new TextBox() { Name = "Password" },
  };
  XmlSerializer ser = new XmlSerializer(typeof(Document));            
  ser.Serialize(Console.Out, d);

You'll also be able to deserialize the XML back into C# objects.

<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <TextBox xsi:type="TextBox" Name="Username" />
  <TextBox xsi:type="TextBox" Name="Password" />
</Document>

Note the xsi:type attribute - because you declared your TextBox element to be of type Element you will have to provide which concrete type implementation to use when deserializing one of these elements. Out of curiosity I tried changing the XSD type of the element named TextBox to the TextBox type, but xsd.exe threw a StackOverflowException. I chuckled. It probably to do with the recursive type relationship between Element and TextBox, but maybe a different tool would handle it differently?

Jono