我在外部发送XML。
一个名为“datafield”的节点有一个名为“value”的元素。这可能包含普通文本内容或html内容(我需要将其包装在CData中)。
因此,我创建了一个基类(ProvisionDataField),其中有2个类继承自它(ProvisionTextField和ProvisionCDataField),如下所示:
<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
当我序列化时,我会得到类似的结果:
<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>
一切都很好,除了我被告知我必须从xml中删除“xsi:type”。所以相反,我需要生成的xml看起来像这样:
<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>
这可能吗?
答案 0 :(得分:2)
这是我正在寻找的答案 - 它将确保省略继承中使用的XmlInclude属性产生的xsi:类型:
ElseIf ns = XmlSchema.InstanceNamespace Then
' Omits all XSI attributes
_skip = True
Return
End If
虽然本节将从根
中省略xmlns:xsd和xmlns:xsi If prefix = "xmlns" AndAlso (localName = "xsd" OrElse localName = "xsi") Then
' Omits XSD and XSI from root
_skip = True
Return
完整代码:
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
答案 1 :(得分:1)
您必须覆盖xmlwriter。
This blogpost(不是我的)告诉你如何。
这是VB.Net版本。
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
结果就是这样。
<?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>
答案 2 :(得分:-1)
无需重写XmlWriter,只需使用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
这将导致xml根本没有名称空间。
编辑:更改为VB代码
编辑2:经过进一步测试,我使用的测试代码仅从生成的xml中删除了命名空间声明。我的原始测试没有在元素上产生xsi:type属性,即使我使用了OP提供的类,因此我无法确定我发布的代码是否会删除它们,正如John Saunder在评论中提到的那样。我假设如果删除了名称空间,那么xsi:type属性也会被删除,但是我发布的代码并没有证明这一点。