2

在序列化/反序列化某些类时,我遇到了需要将某些属性标记或标记为 CDATA 元素(由于它们的内容)。我目前正在这样处理:

    <XmlElement("MessageText")> _
    Public Property XmlContentLeft() As XmlCDataSection
        Get
            Dim doc As New XmlDataDocument()
            Dim cd As XmlCDataSection = doc.CreateCDataSection(Me.MessageText)
            Return cd
        End Get
        Set(ByVal value As XmlCDataSection)
            Me.MessageText = value.Value
        End Set
    End Property

    <XmlIgnore()> _
    Public Property MessageText() As String
        Get
            Return _messageText
        End Get
        Set(ByVal value As String)
            _messageText= value
        End Set
    End Property

现在虽然这很好用,但它也有缺点——我现在有任何我想成为 CDATA 元素的重复属性,我必须为这些属性编写额外的代码。

所以我的问题是是否有更好的方法来做到这一点?我不想为每个类编写自定义模式或序列化例程。在理想情况下,我可以为这些属性添加一个属性,以便将它们自动视为 CDATA 元素。

4

2 回答 2

3

两件事情:

1)您可以像这样简化现有的 CDATA 代码:

<XmlElement("MessageText")> _
Public Property XmlContentLeft() As XmlCDataSection
    Get
        return GetCData(Me.MessageText)
    End Get
    Set(ByVal value As XmlCDataSection)
        Me.MessageText = value.Value
    End Set
End Property

' this method is re-usable by any property that needs CData
Private Function GetCData(ByVal value As String) As XmlCDataSection
    Static doc As New XmlDataDocument() 
    return doc.CreateCDataSection(value)
End Function

<XmlIgnore()> _
Public Property MessageText() As String
    Get
        Return _messageText
    End Get
    Set(ByVal value As String)
        _messageText= value
    End Set
End Property

当然,这实际上比您发布的代码要多,但请注意,您的 CData 属性现在要简单得多。此外,我的使用Static不是拼写错误或 C# 错误。VB.Net 有一个鲜为人知的Static用于在函数中创建成员的关键字。这样,XmlDataDocument 只为整个类创建一次,不会污染类的私有命名空间。

2) 序列化程序应该已经正确地转义了字符数据。你真的需要它是 CData 吗?您序列化的任何内容都应正确反序列化以匹配原始内容,甚至是代码字符串之类的内容。我唯一可能需要CDATA 部分的情况是,如果您必须符合预期的模式。

于 2008-11-12T16:18:08.437 回答
1

我有一个类似的问题 - 客户端需要来自 web 服务的 XML,其字符串包含在可怕的 CData 标记中,这完全没有必要,但他们不想重新编码他们的客户端,所以我必须使我的 XML 符合。

我的工作方式是将我想显示为 CDATA 的(字符串)属性重新输入到我自己的自定义类型“XmlCDataString”中。

然后我在该类型上实现了 IXmlSerializable 并在其中加入了几个 Narrowing 和 Widening 转换运算符重载,以便这些属性仍然尽可能像字符串一样工作。

Imports System.Xml.Serialization
Imports System.Xml
<Serializable()> _
Public Class XmlCDataString
  Implements IXmlSerializable

  Private _strValue As String = Nothing

  Public Sub New()

  End Sub

  Public Sub New(ByVal strValue As String)
    _strValue = strValue
  End Sub

  Public Property StringValue() As String
    Get
      Return _strValue
    End Get
    Set(ByVal value As String)
      _strValue = value
    End Set
  End Property

  Public Shared Widening Operator CType(ByVal strValue As String) As XmlCDataString
    Return New XmlCDataString(strValue)
  End Operator

  Public Shared Narrowing Operator CType(ByVal cdata As XmlCDataString) As String
    Return cdata.StringValue
  End Operator

  Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema
    Throw New NotImplementedException
  End Function

  Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml
    ' TODO
  End Sub

  Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml
    Dim doc As XmlDocument
    Dim xmlCData As XmlCDataSection
    Dim serializer As XmlSerializer

    doc = New XmlDataDocument()
    xmlCData = doc.CreateCDataSection(_strValue)
    serializer = New XmlSerializer(GetType(XmlCDataSection))
    serializer.Serialize(writer, xmlCData)

  End Sub
End Class

然后我要序列化为 CData 的属性我必须重新键入如下(使用您的示例):

Private _messageText As XmlCDataString  

Public Property MessageText() As XmlCDataString 
    Get 
        Return _messageText 
    End Get 
    Set(ByVal value As XmlCDataString) 
        _messageText= value 
    End Set 
End Property 

这对我有用!

于 2010-10-08T11:28:09.480 回答