XML 将对象序列化为不同的输出格式

XML serialize object into different output format

我正在使用 XmlSerializerXmlType / XmlAttribute 属性将 XML 序列化和反序列化为容器对象。

输入XML:

 <row identifier="blah" firstname="blah" lastname="blah" />

和对象:

<Serializable(), XmlType("row")> _
Public Class RowEmployee
    <XmlAttribute("identifier")> _
    Public EmployeeIdentifier As String

    <XmlAttribute("firstname")> _
    Public FirstName As String

    <XmlAttribute("middlename")> _
    Public MiddleName As String

    <XmlAttribute("lastname")> _
    Public LastName As String

End Class

这种方法很好,干净/简单,匹配输入 XML 格式,并且可以在 XML 之间转换,唯一的问题是我的输出 XML 是格式略有不同,例如

 <employee Identifier="blah" FirstName="blah" .....>

我对 XSLT 没有太多经验,但我假设这就是解决此问题的方法。对于这种设置,是否还有比 XSLT 更简单的其他方法?

此外,如果有人知道 "crash course" 在类似上下文中将 XSLT 与 .NET 结合使用的好资源,我们将不胜感激。

是否要将每个 RowEmployee class 序列化为 xml 中的 "row" 元素?您需要将其指定为使用此 class 的 ElementName,例如:

[XmlElement("row")]
public rows As List(Of RowEmployee)

回复:@afrogonabike 的回答,是的,我确实有一个容器 class 我掩盖了对对象的反序列化:

<Serializable(), XmlRoot("data"), XmlType("data")> _
Public Class AesopEmployeeCollection
    <XmlElement("row")> _
    Public Employees As List(Of AesopEmployee)

    Public Sub New()
        Me.Employees = New List(Of AesopEmployee)()
    End Sub

    Public Function GetEmployeeInfo(AesopId As String) As AesopEmployee
        Return (From e In Employees Where e.EmployeeIdentifier = AesopId).FirstOrDefault()
    End Function
End Class

我最终选择了 XSLT,转换实际上相当简单:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="row">
    <employees>
        <employee>
            <xsl:attribute name="Identifier">
                <xsl:value-of select="@identifier" />
            </xsl:attribute>
            <xsl:attribute name="FirstName">
                <xsl:value-of select="@firstname" />
            </xsl:attribute>
            <!-- dont send middlename if blank -->
            <xsl:if test="string-length(@middlename)!=0">
               <xsl:attribute name="MiddleName">
                   <xsl:value-of select="@middlename" />
               </xsl:attribute>
            </xsl:if>  
            <xsl:attribute name="LastName">
                 <xsl:value-of select="@lastname" />
            </xsl:attribute>
            ......
        </employee>
    </employees>
</xsl:template>

</xsl:stylesheet>   

序列化/转换逻辑也不错:

        Dim Ms As New System.IO.MemoryStream()
        Dim Xslt As New XslCompiledTransform()
        Xslt.Load(System.Web.HttpContext.Current.Server.MapPath("/MyRoot/Xslt/EmployeeInfo.xslt"))

        Using Xtw As New System.Xml.XmlTextWriter(Ms, System.Text.Encoding.UTF8)
            SharedInfo.EmpSerializer.Serialize(Xtw, RowEmp)
            Ms = DirectCast(Xtw.BaseStream, System.IO.MemoryStream)
            Ms.Seek(0, SeekOrigin.Begin)
            Dim XmlReader As New XmlTextReader(Ms)
            Dim sb As New StringBuilder()
            Dim WriterSettings As New XmlWriterSettings()
            WriterSettings.OmitXmlDeclaration = True
            Using XmlWriter As XmlWriter = XmlWriter.Create(sb, WriterSettings)
                Xslt.Transform(XmlReader, XmlWriter)
                Dim XmlResponse = EmpImportService.AddOrUpdate(sb.ToString(), ServiceApiKey)

                For Each ResponseNode As XmlNode In XmlResponse.ChildNodes
                    ResponseMessage.Append("<li>").Append(ResponseNode.Attributes("message").Value).Append("</li>")
                Next
            End Using
        End Using