我有这样的架构:
XML:
<Shipment> <Destination City='New York'> <Delivery> <Product ProductCode='B' ProductType='THI'></Product> <Product ProductCode='U' ProductType='SIS'></Product> <Product ProductCode='R' ProductType='JUS'></Product> <Product ProductCode='G' ProductType='TMA'></Product> <Product ProductCode='E' ProductType='DEU'></Product> <Product ProductCode='R' ProductType='POK'></Product> </Delivery> </Destination> <Destination City='London'> <Delivery> <Product ProductCode='C' ProductType='MAK'></Product> <Product ProductCode='H' ProductType='ESN'></Product> <Product ProductCode='E' ProductType='OSE'></Product> <Product ProductCode='R' ProductType='NSE'></Product> <Product ProductCode='R' ProductType='ATA'></Product> <Product ProductCode='Y' ProductType='LLL'></Product> </Delivery> </Destination> <Destination City='Paris'> <Delivery> <Product ProductCode='B' ProductType='WHO'></Product> <Product ProductCode='A' ProductType='WAT'></Product> <Product ProductCode='G' ProductType='CHE'></Product> <Product ProductCode='E' ProductType='STH'></Product> <Product ProductCode='L' ProductType='WAT'></Product> <Product ProductCode=' ' ProductType='CHM'></Product> </Delivery> </Destination> <Destination City='Munich'> <Delivery> <Product ProductCode='Q' ProductType='ENN'></Product> <Product ProductCode='U' ProductType='THE'></Product> <Product ProductCode='I' ProductType='SHA'></Product> <Product ProductCode='C' ProductType='DOW'></Product> <Product ProductCode='H' ProductType='KNO'></Product> <Product ProductCode='E' ProductType='WSS'></Product> </Delivery> </Destination> </Shipment>
我需要它在每次交付中对产品代码进行排序,因此输出是:
XML:
<Shipment> <Destination City='New York'> <Delivery> <Product ProductCode='R' ProductType='JUS'></Product> <Product ProductCode='R' ProductType='POK'></Product> <Product ProductCode='B' ProductType='THI'></Product> <Product ProductCode='U' ProductType='SIS'></Product> <Product ProductCode='E' ProductType='DEU'></Product> <Product ProductCode='G' ProductType='TMA'></Product> </Delivery> </Destination> <Destination City='London'> <Delivery> <Product ProductCode='R' ProductType='NSE'></Product> <Product ProductCode='R' ProductType='ATA'></Product> <Product ProductCode='C' ProductType='MAK'></Product> <Product ProductCode='H' ProductType='ESN'></Product> <Product ProductCode='E' ProductType='OSE'></Product> <Product ProductCode='Y' ProductType='LLL'></Product> </Delivery> </Destination> <Destination City='Paris'> <Delivery> <Product ProductCode='B' ProductType='WHO'></Product> <Product ProductCode='A' ProductType='WAT'></Product> <Product ProductCode='E' ProductType='STH'></Product> <Product ProductCode='L' ProductType='WAT'></Product> <Product ProductCode=' ' ProductType='CHM'></Product> <Product ProductCode='G' ProductType='CHE'></Product> </Delivery> </Destination> <Destination City='Munich'> <Delivery> <Product ProductCode='Q' ProductType='ENN'></Product> <Product ProductCode='U' ProductType='THE'></Product> <Product ProductCode='I' ProductType='SHA'></Product> <Product ProductCode='C' ProductType='DOW'></Product> <Product ProductCode='H' ProductType='KNO'></Product> <Product ProductCode='E' ProductType='WSS'></Product> </Delivery> </Destination> </Shipment>
产品代码是字母或空白。以下规则适用:
我之前从未使用过XSLT,而且自从我做任何VB.NET以来已经有很长一段时间了,所以为了得到一些有用的东西,我想出了以下内容。
Module Module1
Sub Main()
' The document
Dim document As String = "<Shipment> <Destination City='New York'> <Delivery> <Product ProductCode='B' ProductType='THI'></Product> <Product ProductCode='U' ProductType='SIS'></Product> <Product ProductCode='R' ProductType='JUS'></Product> <Product ProductCode='G' ProductType='TMA'></Product> <Product ProductCode='E' ProductType='DEU'></Product> <Product ProductCode='R' ProductType='POK'></Product> </Delivery> </Destination> <Destination City='London'> <Delivery> <Product ProductCode='C' ProductType='MAK'></Product> <Product ProductCode='H' ProductType='ESN'></Product> <Product ProductCode='E' ProductType='OSE'></Product> <Product ProductCode='R' ProductType='NSE'></Product> <Product ProductCode='R' ProductType='ATA'></Product> <Product ProductCode='Y' ProductType='LLL'></Product> </Delivery> </Destination> <Destination City='Paris'> <Delivery> <Product ProductCode='B' ProductType='WHO'></Product> <Product ProductCode='A' ProductType='WAT'></Product> <Product ProductCode='G' ProductType='CHE'></Product> <Product ProductCode='E' ProductType='STH'></Product> <Product ProductCode='L' ProductType='WAT'></Product> <Product ProductCode='S' ProductType='CHM'></Product> </Delivery> </Destination> <Destination City='Munich'> <Delivery> <Product ProductCode='Q' ProductType='ENN'></Product> <Product ProductCode='U' ProductType='THE'></Product> <Product ProductCode='I' ProductType='SHA'></Product> <Product ProductCode='C' ProductType='DOW'></Product> <Product ProductCode='H' ProductType='KNO'></Product> <Product ProductCode='E' ProductType='WSS'></Product> </Delivery> </Destination> </Shipment> "
' Load it
Dim xDoc As XmlDocument = New XmlDocument()
xDoc.LoadXml(DirtyHack(document))
' Required for string output
Dim sb As StringBuilder = New StringBuilder()
Dim writer As XmlWriter = XmlWriter.Create(sb)
' Do the transformation
Dim tranny As XslCompiledTransform = New XslCompiledTransform()
tranny.Load("c:\sandbox\MassageXML\Autobots.xslt")
tranny.Transform(xDoc, writer)
' See what mess we've made
Debug.WriteLine(sb.ToString)
End Sub
Function DirtyHack(ByVal inputString As String) As String
Dim dict = New Dictionary(Of String, String)
dict.Add("ProductCode='", "SortOrder='2' ProductCode='")
dict.Add("SortOrder='2' ProductCode='R'", "SortOrder='1' ProductCode='R'")
dict.Add("SortOrder='2' ProductCode='G'", "SortOrder='3' ProductCode='G'")
For Each kvp As KeyValuePair(Of String, String) In dict
inputString = inputString.Replace(kvp.Key, kvp.Value)
Next
Return inputString
End Function
End Module
本质上,我会动态添加另一个属性,按此排序然后删除它,但我确定必须有一个更清洁的方式。有什么想法吗?
这是迄今为止的XSLT脚本:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@SortOrder" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Delivery">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="*">
<xsl:sort select="@SortOrder" data-type="number" order="ascending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:1)
这是我的建议,它定义了产品代码到数字排序值作为参数的映射,并在xsl:sort
中选择,唯一的缺点是在XSLT 1.0中需要exsl:node-set
或{ {1}}将参数所在的结果树片段转换为节点集,以便能够使用它,如下所示:
msxsl:node-set