如何在VB.NET中使用XSLT指定自定义属性排序顺序(VS2008)

时间:2016-02-26 12:37:03

标签: xml vb.net xslt visual-studio-2008

我有这样的架构:

enter image description here

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>  

我需要它在每次交付中对产品代码进行排序,因此输出是:

enter image description here

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>  

产品代码是字母或空白。以下规则适用:

  1. 产品代码R应首先出现
  2. 产品代码G应该最后出现
  3. 其他任何东西介于
  4. 之间

    我之前从未使用过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>
    

1 个答案:

答案 0 :(得分:1)

这是我的建议,它定义了产品代码到数字排序值作为参数的映射,并在xsl:sort中选择,唯一的缺点是在XSLT 1.0中需要exsl:node-set或{ {1}}将参数所在的结果树片段转换为节点集,以便能够使用它,如下所示:

msxsl:node-set

http://xsltransform.net/3NJ38ZM的在线示例。