XSLT排序问题 - 属性不会排序

时间:2013-02-11 08:47:10

标签: xslt svg

来源

<roll>
  <dayquantum date="20130125">
    <item index="2" value="4" product="Margherita"/>
    <item index="3" value="2" product="Capricciosa"/>
    <item index="4" value="2" product="Quattro Stagioni"/>
    <item index="5" value="7" product="Bresola"/>
    <item index="6" value="1" product="Gorgonzola"/>
    <item index="7" value="7" product="Piccante"/>
    <item index="8" value="3" product="Rosmarino"/>
    <item index="9" value="2" product="Caprese"/>
    <item index="10" value="7" product="Parma"/>
    <item index="11" value="1" product="Parmigiana"/>
    <item index="12" value="2" product="Pollo"/>
    <item index="13" value="2" product="Hawaii"/>
    <item index="14" value="17" product="Pepperoni"/>
    <item index="15" value="4" product="Calzone"/>
    <item index="16" value="2" product="Bologna"/>
    <item index="17" value="3" product="Tonno"/>
    <item index="18" value="1" product="Marinara"/>
    <item index="19" value="2" product="Napoletana"/>
    <item index="20" value="1" product="Carne"/>
    <item index="21" value="1" product="Mascarpone"/>
    <item index="22" value="4" product="Carpaccio"/>
    <item index="25" value="1" product="Tartufo"/>
    <item index="26" value="8" product="Prosciutto"/>
    <item index="27" value="3" product="Lasagna Originale"/>
    <item index="28" value="1" product="Tortellini Gorgonzola"/>
    <item index="29" value="1" product="Tortellini Tartufo"/>
    <item index="31" value="4" product="Tagliatelle Dolce Vita"/>
    <item index="33" value="1" product="Spaghetti Carbonara"/>
    <item index="37" value="2" product="Antipasta Toto e Pepino"/>
    <item index="38" value="1" product="Vitello Tonnato"/>
    <item index="41" value="4" product="Bruschetta classica"/>
    <item index="44" value="1" product="Tiramisu"/>
    <item index="47" value="4" product="Panino al Pollo"/>
    <item index="48" value="5" product="Panino al Prosciutto"/>
    <item index="49" value="8" product="Panino al vitello tonnato"/>
  </dayquantum>
</roll>

XSLT

    <svg viewBox="0 0 2400 1400" style="background: #000 ; font-family: 'Racing Sans One'"  id="zcanvas" version="1.1" xsl:version="1.0"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
     xmlns="http://www.w3.org/2000/svg">
    <defs><link xmlns="http://www.w3.org/1999/xhtml" href="http://fonts.googleapis.com/css?family=Racing+Sans+One|Six+Caps" type="text/css" rel="stylesheet" /></defs>  

    <xsl:for-each select="roll/dayquantum">
      <xsl:sort select="@date" order="descending" data-type="number"/>

      <xsl:variable name="y" select="(position() * 180) - 100" />    

      <text fill="#fff" font-size="48">      
        <xsl:attribute name="x"><xsl:value-of select="80" /></xsl:attribute>            
        <xsl:attribute name="y"><xsl:value-of select="$y - 40" /></xsl:attribute>        
        <xsl:attribute name="transform">rotate(90, 80, <xsl:value-of select="$y - 40 " />)</xsl:attribute>                      
        <xsl:value-of select="substring(@date,7,2)" /><xsl:value-of select="substring('  JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC', number(substring(@date,5,2)) * 3, 3)" />          
      </text>
      <text fill="#ff6000" font-size="48">      
        <xsl:attribute name="x"><xsl:value-of select="120" /></xsl:attribute>            
        <xsl:attribute name="y"><xsl:value-of select="$y - 10" /></xsl:attribute>        
        <xsl:value-of select="sum(item/@value)" />
      </text>

      <xsl:for-each select="item">     
        <xsl:sort select="@value" order="descending" data-type="number"/>
        <rect fill="green" >      
          <xsl:attribute name="x"><xsl:value-of select="200 + (sum(preceding-sibling::item/@value) * 16)" /></xsl:attribute>            
          <xsl:attribute name="y"><xsl:value-of select="$y - 48" /></xsl:attribute>        
          <xsl:attribute name="width"><xsl:value-of select="@value * 16" /></xsl:attribute>            
          <xsl:attribute name="rx">10</xsl:attribute>        
          <xsl:attribute name="height">48</xsl:attribute>        
        </rect>
        <g font-family="sans-serif">
        <text fill="#fff" font-size="20" text-anchor="middle">      
          <xsl:attribute name="x"><xsl:value-of select="200 + (sum(preceding-sibling::item/@value) * 16) + ((@value * 16) div 2)" /></xsl:attribute>            
          <xsl:attribute name="y"><xsl:value-of select="$y - 20" /></xsl:attribute>          
          <xsl:value-of select="@value" />
        </text>       
        <text fill="#888" font-size="18" text-anchor="start">      
          <xsl:attribute name="x"><xsl:value-of select="200 + (sum(preceding-sibling::item/@value) * 16) + ((@value * 16) div 2)" /></xsl:attribute>            
          <xsl:attribute name="y"><xsl:value-of select="$y" /></xsl:attribute>          
          <xsl:attribute name="transform">rotate(90, <xsl:value-of select="200 + (sum(preceding-sibling::item/@value) * 16) + ((@value * 16) div 2)" />, <xsl:value-of select="$y" />)</xsl:attribute>            
          <xsl:value-of select="@product" />
        </text>
        </g>
      </xsl:for-each>    
    </xsl:for-each>  
    </svg>

问题:

它不会对属性“value”降序进行排序 - 这是因为前面的语句吗?

可在此处找到来源:http://xmlsoap.dk/xml/crCountLog.xml

1 个答案:

答案 0 :(得分:2)

它没有按预期方式工作的原因是preceding-sibling::查看文档顺序中的item s'前面的兄弟姐妹,而不是当前的排序顺序。所以它们正在被排序,但x值正在被计算,就像你根本没有对它们进行排序一样。

以下递归方法应该实现您的目标:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns="http://www.w3.org/2000/svg">
  <xsl:output method="xml" omit-xml-declaration="yes" />

  <xsl:template match="/">
    <svg viewBox="0 0 2400 1400"
         style="background: #000 ; font-family: 'Racing Sans One'"  id="zcanvas"
         version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
      <defs>
        <link xmlns="http://www.w3.org/1999/xhtml"
              href="http://fonts.googleapis.com/css?family=Racing+Sans+One|Six+Caps"
              type="text/css" rel="stylesheet" />
      </defs>

      <xsl:apply-templates select="roll/dayquantum">
        <xsl:sort select="@date" order="descending" data-type="number"/>
      </xsl:apply-templates>
    </svg>
  </xsl:template>

  <xsl:template match="dayquantum">
    <xsl:variable name="y" select="(position() * 180) - 100" />

    <text fill="#fff" font-size="48" x="80" y="{$y - 40}"
          transform="rotate(90, 80, {$y - 40})">
      <xsl:value-of select="substring(@date,7,2)" />
      <xsl:value-of select="substring('  JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC', 
                            number(substring(@date,5,2)) * 3, 3)" />
    </text>
    <text fill="#ff6000" font-size="48" x="120" y="{$y - 10}">
      <xsl:value-of select="sum(item/@value)" />
    </text>

    <xsl:variable name="topItem" select="item[not(../item/@value > @value)][1]" />
    <xsl:apply-templates select="$topItem">
      <xsl:with-param name="y" select="$y" />
      <xsl:with-param name="remainingItems" 
                      select="item[generate-id() != generate-id($topItem)]" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="item">
    <xsl:param name="y" />
    <xsl:param name="previousItems" select="/.." />
    <xsl:param name="remainingItems" />

    <xsl:variable name="leadingSpace"
                  select="200 + sum($previousItems/@value) * 16" />
    <xsl:variable name="width" select="@value * 16" />
    <xsl:variable name="hCenter" select="$leadingSpace + $width div 2" />

    <rect fill="green" x="{$leadingSpace}" y="{$y - 48}" width="{$width}"
          rx="10" height="48" />

    <g font-family="sans-serif">
      <text fill="#fff" font-size="20" text-anchor="middle" x="{$hCenter}"
            y="{$y - 20}">
        <xsl:value-of select="@value" />
      </text>

      <text fill="#888" font-size="18" text-anchor="start" x="{$hCenter}"
            y="{$y}" transform="rotate(90, {$hCenter}, {$y})">
        <xsl:value-of select="@product" />
      </text>
    </g>

    <xsl:variable name="topItem"
               select="$remainingItems[not($remainingItems/@value > @value)][1]" />
    <xsl:apply-templates select="$topItem">
      <xsl:with-param name="y" select="$y" />
      <xsl:with-param name="previousItems" select="$previousItems | ." />
      <xsl:with-param name="remainingItems"
                      select="$remainingItems[generate-id() != 
                                                generate-id($topItem)]" />
    </xsl:apply-templates>
  </xsl:template>


</xsl:stylesheet>

此方法选择没有小于其自身的项目的第一个项目,并仅将模板应用于该项目,将其余项目作为参数传递。然后选择下一个顶级项目,模板以递归方式自行调用,直到所有项目都用完为止。