XSLT Sorting - how to sort xml childnodes inside a parent node with an attribute

前端 未结 2 955
自闭症患者
自闭症患者 2020-12-17 21:11

What started out as a simple thing has turned out quite troublesome for XSLT noob.

Trying to sort childnodes/descending but, after adding an attribute to their pare

相关标签:
2条回答
  • 2020-12-17 21:24

    So are you saying that you're only passing part of your XML document (one <year> node) to the XSLT processor?

    You should use a separate template for year, so that that's the only template that uses sorting. How is the following:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="year">
        <xsl:copy>
          <xsl:apply-templates select="@*" />
          <xsl:apply-templates select="post">
            <xsl:sort select="@postid" data-type="number" order="descending"/>
          </xsl:apply-templates>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    

    I think the above is a better approach, but I think the root cause of your error is that it was mingling the attributes in with the elements when it did the sorting. Your original XSLT probably would run without error if you simply did this:

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*">
            <xsl:apply-templates select="node()">
                <xsl:sort select="@postid" data-type="text" order="descending"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    
    0 讨论(0)
  • 2020-12-17 21:40

    This transformation:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="node()|@*">
         <xsl:copy>
           <xsl:apply-templates select="@*|node()"/>
         </xsl:copy>
     </xsl:template>
    
     <xsl:template match="year">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="*">
          <xsl:sort select="@postid" data-type="number" order="descending"/>
        </xsl:apply-templates>
      </xsl:copy>
     </xsl:template>
    </xsl:stylesheet>
    

    when applied on the provided XML document:

    <posts>
        <year value="2013">
            <post postid="10030" postmonth="1">
                <othernode></othernode>
                <othernode2></othernode2>
            </post>
            <post postid="10040" postmonth="2">
                <othernode></othernode>
                <othernode2></othernode2>
            </post>
            <post postid="10050" postmonth="3">
                <othernode></othernode>
                <othernode2></othernode2>
            </post>
        </year>
        <year value="2012">
            <post postid="10010" postmonth="1">
                <othernode></othernode>
                <othernode2></othernode2>
            </post>
            <post postid="10015" postmonth="2">
                <othernode></othernode>
                <othernode2></othernode2>
            </post>
            <post postid="10020" postmonth="3">
                <othernode></othernode>
                <othernode2></othernode2>
            </post>
        </year>
    </posts>
    

    produces the wanted, correct result:

    <posts>
       <year value="2013">
          <post postid="10050" postmonth="3">
             <othernode/>
             <othernode2/>
          </post>
          <post postid="10040" postmonth="2">
             <othernode/>
             <othernode2/>
          </post>
          <post postid="10030" postmonth="1">
             <othernode/>
             <othernode2/>
          </post>
       </year>
       <year value="2012">
          <post postid="10020" postmonth="3">
             <othernode/>
             <othernode2/>
          </post>
          <post postid="10015" postmonth="2">
             <othernode/>
             <othernode2/>
          </post>
          <post postid="10010" postmonth="1">
             <othernode/>
             <othernode2/>
          </post>
       </year>
    </posts>
    
    0 讨论(0)
提交回复
热议问题