I need to serialise an object to the following XML in .Net.
Probably the easiest way is to implement IXMLSerializable due to the control I need over the end result.... What do I need to do to output in the following schema:
<ns2:ProcessRepairOrder languageCode="de-DE" releaseID="1.0" systemEnvironmentCode="PROD" versionID="1.0">
<ns2:ApplicationArea>
<ns2:Sender>
<ns2:CreatorNameCode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:TextType">SomeVendor</ns2:CreatorNameCode>
<ns2:SenderNameCode name="Dave"/>
<ns2:Sender>
</ns2:ApplicationArea>
</ns2:ProcessRepairOrder>
More specifically it is the prefixes without the namespace, and the xsi:type I can't get into the XML.
the full version looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns1:PutMessage xmlns:ns1="http://www.starstandards.org/webservices/2009/transport" xmlns:ns2="http://www.starstandard.org/STAR/5" xmlns:ns3="http://www.openapplications.org/oagis/9">
<ns1:payload>
<ns1:content>
<ns2:ProcessRepairOrder languageCode="de-DE" releaseID="1.0" systemEnvironmentCode="PROD" versionID="1.0">
...many more XML elements
</ns2:ProcessRepairOrder>
</ns1:PutMessage>
</S:Body>
</S:Envelope>
Are you able to use .NET 3.5? If so LINQ-to-XML might be easier to use. Here is some code I've tested which will produce exactly the XML output in your question:
XNamespace ns2 = "some-uri";
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
XElement root = new XElement("Root",
// Define ns2 namespace on Root element
new XAttribute(XNamespace.Xmlns + "ns2", ns2.NamespaceName),
new XElement(ns2 + "ProcessRepairOrder",
// Attributes of ProcessRepairOrder
new XAttribute("languageCode", "de-DE"),
new XAttribute("releaseID", "1.0"),
new XAttribute("systemEnvironmentCode", "PROD"),
new XAttribute("versionID", "1.0"),
// Child elements of ProcessRepairOrder
new XElement(ns2 + "ApplicationArea",
new XElement(ns2 + "Sender",
new XElement(ns2 + "CreatorNameCode",
// Attributes of CreatorNameCode and define xsi namespace
new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName),
new XAttribute(xsi + "type", "ns3:TextType"),
// Value of CreatorNameCode,
"SomeVendor"
),
new XElement(ns2 + "SenderNameCode",
// Attributes of SenderNameCode
new XAttribute("name", "Dave")
)
)
)
)
);
You can look at this MSDN page to see how to create XML tress using LINQ-to-XML, and this link explains how to apply XML namespaces to them.
Edited:
Following on from your comments below, it seems you want a less standard approach in that you can't have the root element I've defined above, but LINQ-to-XML seems to require it in order to create a valid XML structure with the correct namespaces defined. If you want to use this approach then there is a way around it but it requires a bit more fiddling around with the output.
Using the code I've written above and then doing root.Elements().First().ToString()
would produce this serialized XML:
<ns2:ProcessRepairOrder languageCode="de-DE" releaseID="1.0" systemEnvironmentCode="PROD" versionID="1.0" xmlns:ns2="some-uri">
<ns2:ApplicationArea>
<ns2:Sender>
<ns2:CreatorNameCode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:TextType">SomeVendor</ns2:CreatorNameCode>
<ns2:SenderNameCode name="Dave" />
</ns2:Sender>
</ns2:ApplicationArea>
</ns2:ProcessRepairOrder>
Nearly there but notice that LINQ-to-XML has inserted the xmlns:ns2
namespace on the ProcessRepairOrder
because to use ns2
elements throughout the hierarchy it needs to be defined somewhere. But now that you have this in a string format you can easily use String.Replace()
to remove that and you'll end up with what you require.
I wouldn't say it is an elegant solution, but it would work for your non-standard method of producing XML.