I am using XmlSerializer to create an object representing an XML file and now i want to add a schemalocation to the rootelement of my xml file. I can add namespaces like the following
XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
System.IO.FileStream fs = new FileStream(@"C:\test.xml", FileMode.Create);
TextWriter writer = new StreamWriter(fs, new UTF8Encoding());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("xy","http://www.w3.org/2005/08/addressing");
ns.Add("xlink","http://www.w3.org/1999/xlink");
serializer.Serialize(writer, myObject, ns);
But how do i add a xsi:schemalocation
attribute to my root element within my c# code. Namespace was added with a simple ns.Add()
. I would like to avoid messing around with the xsd.exe generated c# class.
Or do i have to edit manually the generated c# class and add some attribute to the root element of my xml?
EDIT: I have seen examples where i need to edit my c# manually, but there must be a way to do it in code!! If we are able to add namespaces to our root element, why shouldn't it be possible to add schemalocations?
Let's assume the following XSD:
There are two ways at least to do it. The first one relies on inheritance and how you can play with the serializer annotations.
xsd.exe generates this:
To "inject" the
xsi:schemaLocation
add a new class,elementA : elementB
; notice:schemaLocation
property setup.Test program:
Generates the expected result:
The second way relies on a custom writer that will inject what you want, wherever you want it (assuming the appropriate logic).
You implement a custom XmlWriter:
A modified test program:
The result is the same...
The XSD.exe generates partial classes, so you can add your own separate partial class to hold things like xsi:schemaLocation as fields or properties.
So, adding to @Petru Gardea's sample elementB class, you only need to create another file in your project and add this partial class:
There is one gotcha that I ran into doing this and that was by default xsd.exe does not add a namespace to the generated file(s). When you create this partial class of your own, it will most likely be in a namespace. Since <default namespace> and an explicitly defined namespace do not match, partial won't work. So, you need to use the namespace option on xsd.exe to actually get the generated classes into your namespace.