Remove xsi:type from generated xml when serializing
I am sending XML externally.
One of the node called "datafield" has an element called "value". This may contain normal text content, or an html content (which I need to wrap in CData).
So, I created a base class (ProvisionD开发者_如何学CataField) with 2 classes inherits from it (ProvisionTextField, and ProvisionCDataField) as follows:
<XmlInclude(GetType(ProvisionTextField))>
<XmlInclude(GetType(ProvisionCDataField))>
Public MustInherit Class ProvisionDataField
<XmlAttribute("datatype")>
Public Property DataType As String
<XmlElement("name")>
Public Property Name As String
End Class
Public Class ProvisionCDataField
Inherits ProvisionDataField
<XmlIgnore()>
Public Property ValueContent As String
<XmlElement("value")>
Public Property Value() As XmlCDataSection
Get
Dim doc As New XmlDocument
Return doc.CreateCDataSection(ValueContent)
End Get
Set(ByVal value As XmlCDataSection)
ValueContent = value.Value
End Set
End Property
End Class
Public Class ProvisionTextField
Inherits ProvisionDataField
<XmlElement("value")>
Public Property Value As String
End Class
When I serialize,I get something like this:
<entitydata entitytype="company">
<datafield xsi:type="ProvisionTextField" datatype="string">
<name>companyAcronym</name>
<value>testCompany</value>
</datafield>
<datafield xsi:type="ProvisionCDataField" datatype="string">
<name>ssocontent</name>
<value><![CDATA[<html><body> HTML Content</body></html>]]></value>
</datafield>
</entitydata>
All good except that I've been told that I have to remove the "xsi:type" from the xml. So instead, I need my generated xml to look like this:
<entitydata entitytype="company">
<datafield datatype="string">
<name>companyAcronym</name>
<value>testCompany</value>
</datafield>
<datafield datatype="string">
<name>ssocontent</name>
<value><![CDATA[<html><body> HTML Content</body></html>]]></value>
</datafield>
</entitydata>
Is that possible?
This is the answer I am looking for - it will ensure that the xsi:type resulted from XmlInclude attribute used in inheritance is omitted:
ElseIf ns = XmlSchema.InstanceNamespace Then
' Omits all XSI attributes
_skip = True
Return
End If
While this section will omit the xmlns:xsd and xmlns:xsi from the root
If prefix = "xmlns" AndAlso (localName = "xsd" OrElse localName = "xsi") Then
' Omits XSD and XSI from root
_skip = True
Return
Full codes:
Imports System.IO
Imports System.Xml
Imports System.Xml.Schema
Public Class PlainXmlTextWriter
Inherits XmlTextWriter
Public Sub New(ByVal w As TextWriter)
MyBase.new(w)
End Sub
Public Sub New(ByVal w As Stream, ByVal encoding As Encoding)
MyBase.new(w, encoding)
End Sub
Public Sub New(ByVal filename As String, ByVal encoding As Encoding)
MyBase.new(filename, encoding)
End Sub
Dim _skip As Boolean = False
Public Overrides Sub WriteStartAttribute(ByVal prefix As String, ByVal localName As String, ByVal ns As String)
If prefix = "xmlns" AndAlso (localName = "xsd" OrElse localName = "xsi") Then
' Omits XSD and XSI from root
_skip = True
Return
ElseIf ns = XmlSchema.InstanceNamespace Then
' Omits all XSI attributes
_skip = True
Return
End If
MyBase.WriteStartAttribute(prefix, localName, ns)
End Sub
Public Overrides Sub WriteString(ByVal text As String)
If _skip Then Return
MyBase.WriteString(text)
End Sub
Public Overrides Sub WriteEndAttribute()
If _skip Then
_skip = False
Return
End If
MyBase.WriteEndAttribute()
End Sub
End Class
You will have to overwrite xmlwriter.
This blogpost (not mine) shows you how.
Here is the VB.Net version.
Imports System.Xml.Serialization
Imports System.Xml
Imports System.IO
Imports System.Text
Module Module1
Sub Main()
Dim p As New ProvisionCDataField()
p.Name = "test"
Dim sw1 = New StringWriter()
Dim xs1 As New XmlSerializer(GetType(ProvisionDataField))
xs1.Serialize(New XmlTextWriter(sw1), p)
Console.WriteLine(sw1.ToString())
Dim sw2 = New StringWriter()
Dim xs2 As New XmlSerializer(GetType(ProvisionDataField))
xs2.Serialize(New NonXsiTextWriter(sw2), p)
Console.WriteLine(sw2.ToString())
Console.ReadLine()
End Sub
End Module
Public Class NonXsiTextWriter
Inherits XmlTextWriter
Public Sub New(ByVal w As TextWriter)
MyBase.new(w)
End Sub
Public Sub New(ByVal w As Stream, ByVal encoding As Encoding)
MyBase.new(w, encoding)
End Sub
Public Sub New(ByVal filename As String, ByVal encoding As Encoding)
MyBase.new(filename, encoding)
End Sub
Dim _skip As Boolean = False
Public Overrides Sub WriteStartAttribute(ByVal prefix As String, ByVal localName As String, ByVal ns As String)
If localName = "xsi" Then
_skip = True
Return
End If
MyBase.WriteStartAttribute(prefix, localName, ns)
End Sub
Public Overrides Sub WriteString(ByVal text As String)
If _skip Then Return
MyBase.WriteString(text)
End Sub
Public Overrides Sub WriteEndAttribute()
If _skip Then
_skip = False
Return
End If
MyBase.WriteEndAttribute()
End Sub
End Class
<XmlInclude(GetType(ProvisionTextField))>
<XmlInclude(GetType(ProvisionCDataField))>
Public MustInherit Class ProvisionDataField
<XmlAttribute("datatype")>
Public Property DataType As String
<XmlElement("name")>
Public Property Name As String
End Class
Public Class ProvisionCDataField
Inherits ProvisionDataField
<XmlIgnore()>
Public Property ValueContent As String
<XmlElement("value")>
Public Property Value() As XmlCDataSection
Get
Dim doc As New XmlDocument
Return doc.CreateCDataSection(ValueContent)
End Get
Set(ByVal value As XmlCDataSection)
ValueContent = value.Value
End Set
End Property
End Class
Public Class ProvisionTextField
Inherits ProvisionDataField
<XmlElement("value")>
Public Property Value As String
End Class
With this as the result.
<?xml version="1.0" encoding="utf-16"?>
<ProvisionDataField xmlns:xsi="http://www .w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="ProvisionCDataField">
<name>test</name><value><![CDATA[]]></value>
</ProvisionDataField>
<?xml version="1.0" encoding="utf-16"?>
<ProvisionDataField xmlns:xsd="http://www.w3.org/2001/XMLSchema" d1p1:type="ProvisionCDataField" xmlns:d1p1="http://www.w3.org/2001/XMLSchema-instance">
<name>test</name><value><![CDATA[]]></value>
</ProvisionDataField>
No need to override XmlWriter, just use an instance of XmlSerializerNamespace:
Sub Main()
Dim xSer As New XmlSerializer(GetType(MyType))
Dim sb As New StringBuilder()
Dim obj As MyType = getAnInstanceOfMyType()
Using wrt As New StringWriter(sb)
Dim ns As New XmlSerializerNamespaces
ns.Add("", "")
xSer.Serialize(wrt, obj, ns)
End Using
Console.WriteLine(sb.ToString())
Console.ReadLine()
End Sub
This will result in the xml having no namespaces at all.
EDIT: Changed to VB code
EDIT 2: Upon further testing, the test code I used only removed the namespace declarations from the resulting xml. My original test did not produce the xsi:type attributes on the elements even though I used the classes provided by the OP, so I cannot determine if the code that I posted will remove them, as John Saunder alluded to in the comments. I presumed that if the namespaces were removed, then the xsi:type attributes would also be removed, but the code I posted does not prove this.
精彩评论