序列化时从生成的 xml 中删除 xsi:type

发布于 2024-12-08 04:49:03 字数 2251 浏览 3 评论 0原文

我正在向外部发送 XML。

称为“数据字段”的节点之一具有称为“值”的元素。这可能包含普通文本内容或 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>

这可能吗?

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 (ProvisionDataField) 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

冷…雨湿花 2024-12-15 04:49:03

这是我正在寻找的答案 - 它将确保省略继承中使用的 XmlInclude 属性产生的 xsi:type:

    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

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
傲性难收 2024-12-15 04:49:03

您将必须覆盖 xmlwriter。

这篇博文(不是我的)向您展示了如何操作。

这是 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>

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>
无敌元气妹 2024-12-15 04:49:03

无需重写 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 中删除了名称空间声明。即使我使用了 OP 提供的类,我最初的测试也没有在元素上生成 xsi:type 属性,因此我无法确定我发布的代码是否会删除它们,正如 John Saunder 在评论中提到的那样。我认为如果删除命名空间,那么 xsi:type 属性也会被删除,但我发布的代码并没有证明这一点。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文