XML 将对象序列化为不同的输出格式
XML serialize object into different output format
我正在使用 XmlSerializer
和 XmlType / 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
我正在使用 XmlSerializer
和 XmlType / 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