xslt sort output xml

后端 未结 3 1090
一整个雨季
一整个雨季 2021-01-06 18:59

I\'m trying to find a solution to the following problem.

I\'m developing XSLT transformation (which is now about 40KB big) that is transforming quite complex XMLs i

相关标签:
3条回答
  • 2021-01-06 19:39

    Is it possible to apply xsl:sort on the output XML?

    Yes, multipass processing is possible, and especially in XSLT 2.0 you don't even need to apply an xxx:node-set() extension on the result, because the infamous RTF type does no longer exist:

    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="/">
      <xsl:variable name="vPass1">
       <!--
            Put/Invoke your cirrent code here   
            to generate the following           
    -->
        <Records>
          <Record key="XX3">
          </Record>
          <Record key="XX2">
          </Record>
          <Record key="XX4">
          </Record>
          <Record key="XX1">
          </Record>
        </Records>
      </xsl:variable>
    
      <xsl:apply-templates select="$vPass1/*"/>
     </xsl:template>
    
     <xsl:template match="Records">
      <Records>
       <xsl:perform-sort select="*">
        <xsl:sort select="@key"/>
       </xsl:perform-sort>
      </Records>
     </xsl:template>
    </xsl:stylesheet>
    

    When this transformation is performed on any XML document (not used/ignored), the wanted, correct, sorted result is produced:

    <Records>
       <Record key="XX1"/>
       <Record key="XX2"/>
       <Record key="XX3"/>
       <Record key="XX4"/>
    </Records>
    

    In XSLT 1.0 it is almost the same with the additional conversion of the result from RTF type to a normal tree:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ext="http://exslt.org/common"
     exclude-result-prefixes="ext">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="/">
      <xsl:variable name="vrtfPass1">
       <!--
            Put/Invoke your cirrent code here   
            to generate the following           
    -->
        <Records>
          <Record key="XX3">
          </Record>
          <Record key="XX2">
          </Record>
          <Record key="XX4">
          </Record>
          <Record key="XX1">
          </Record>
        </Records>
      </xsl:variable>
    
      <xsl:variable name="vPass1"
                    select="ext:node-set($vrtfPass1)"/>
    
      <xsl:apply-templates select="$vPass1/*"/>
     </xsl:template>
    
     <xsl:template match="Records">
      <Records>
       <xsl:for-each select="*">
        <xsl:sort select="@key"/>
    
        <xsl:copy-of select="."/>
       </xsl:for-each>
      </Records>
     </xsl:template>
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2021-01-06 19:42

    As an addendum to Dimitre's excellent solution above, if you're using an XSLT 1.0 processor (for example, .NET), the following can give you a pointer as to how to use node-set: http://www.xml.com/pub/a/2003/07/16/nodeset.html#tab.namespaces

    In my case, I was in .NET 1.1 (i.e. MSXML) and the solution looked something like:

    <?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">
        <xsl:template match="/">            
            <xsl:variable name="vrtfPass1">
                <Records xmlns="">  
                        <xsl:apply-templates />
                </Records >            
            </xsl:variable>
            <xsl:variable name="vPass1" select="msxsl:node-set($vrtfPass1)"/>
            <xsl:apply-templates select="$vPass1/*" mode="sorting"/>
        </xsl:template>
        <xsl:template match="Records" mode="sorting">
            <Records>
           <xsl:for-each select="Record">
            <xsl:sort select="@key"/>
            <xsl:copy-of select="."/>
           </xsl:for-each>
          </Records>
        </xsl:template>
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2021-01-06 19:57

    40Kb is a lot of code for one stylesheet. When things get to this kind of scale, it's usually best to split a transformation into a pipeline of smaller transformations. If you have such a pipeline architecture, then adding a sort step at the end is trivial. There are plenty of technologies for managing a pipeline of transformations (XProc, Orbeon, xmlsh, ant, Coccoon) depending on your requirements. The benefit of pipelining is that it keeps your code modular and reusable.

    0 讨论(0)
提交回复
热议问题