Reputation: 626
I am using webapi MVC template Using default XmlSerializer i get the following output
OUTPUT:
<ClassName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Child1>String</Child>
<Child2 xsi:nil=true/>
</ClassName>
DTO class
[XmlRoot("ClassName")]
[DataContract]
public class ClassName
{
[DataMember]
[XmlElement("Child1")]
public string Child1{ get; set; }
[DataMember]
[XmlElement("Child2",IsNullable =true)]
public string Child2{ get; set; }
}
I managed to remove the root node namespace by overriding the default xmlformatter
//Code to remove root node namespace
using (XmlWriter xw = XmlWriter.Create(streamWriter, settings))
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
serializer.Serialize(xw, value, ns);
}
But Now the namespace in the root node is removed but still the child node have the namespace
Current Output:
<ClassName>
<Child1>String</Child>
<Child2 xsi:nil=true p2:nil="true" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance"/>
</ClassName>
Expected output:
<ClassName>
<Child1>String</Child>
<Child2 />
</ClassName>
Upvotes: 2
Views: 2225
Reputation: 116806
The namespace "http://www.w3.org/2001/XMLSchema-instance"
is required to be added because you have specified XmlElementAttribute.IsNullable = true
for Child2
. This is explained in the documentation:
The XML schema specification for structures allows an XML document to explicitly signal that an element's content is missing. Such an element contains the attribute xsi:nil set to true. For more information, see the World Wide Web Consortium (www.w3.org) specification, "XML Schema Part 1: Structures".
If the IsNullable property is set to true, the xsi:nil attribute is generated for class members that have been set to null. For example if you set a field named MyStringArray to null, the XmlSerializer generates the following XML code.
<MyStringArray xsi:nil = "true" />
If the IsNullable property is false, no XML element is generated for class members that have been set to null.
Where the xsi
in "xsi:nil"
is a shortcut for the namespace http://www.w3.org/2001/XMLSchema-instance
as explained in Xsi:nil Attribute Binding Support. As xsi:nil
is a w3c standard attribute (defined here), omitting the namespace would create nonstandard XML that would not be correctly understood by receiving systems. Note that XmlSerializer
only emits the nil
attribute and associated namespace when required. The XML output for
new ClassName() { Child1 = null, Child2 = string.Empty }
will not contain the attribute or namespace.
Incidentally, to clear up a possible confusion, in the XML
<Child2 xsi:nil=true p2:nil="true" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance"/>
It is only the nil
attribute that is in the "http://www.w3.org/2001/XMLSchema-instance"
namespace, because only the attribute has the p2:
prefix. The Child2
element itself is in the default namespace, so the presence of the namespace isn't changing the overall meaning of your XML. In fact there's no reason not to leave the xsi
and xsd
namespaces on the root node. Since they are named namespaces not default namespaces, elements and attributes will belong to them only if they have the appropriate prefix.
That being said, if for whatever reason you must use a custom nil
attribute to represent a null text value, you will need to implement a custom property to serialize and deserialize it, for instance:
[XmlRoot("ClassName")]
[DataContract]
public class ClassName
{
[DataMember]
[XmlElement("Child1")]
public string Child1 { get; set; }
[DataMember]
[XmlIgnore]
public string Child2 { get; set; }
[XmlElement("Child2")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
[IgnoreDataMember]
public CustomXmlNilTextWrapper Child2Xml { get { return Child2; } set { Child2 = value; } }
}
public struct CustomXmlNilTextWrapper
{
bool forceNull;
string value;
public static implicit operator CustomXmlNilTextWrapper(string value)
{
return new CustomXmlNilTextWrapper(value);
}
public static implicit operator string(CustomXmlNilTextWrapper wrapper)
{
return wrapper.Value;
}
public CustomXmlNilTextWrapper(string value)
{
this.value = value;
this.forceNull = value == null;
}
[XmlAttribute("nil")]
public bool ForceNull { get { return forceNull; } set { forceNull = value; } }
public bool ShouldSerializeForceNull() { return ForceNull == true; }
[XmlText]
public string Value { get { return ForceNull ? null : value ?? string.Empty; } set { this.value = value; } }
}
Serializing a default instance of this class will produce output like:
<ClassName>
<Child2 nil="true" />
</ClassName>
This meets your requirement of not having a namespace - but it's not worth the bother in my opinion.
Prototype fiddle demonstrating how everything is working.
Upvotes: 5