1

来源

<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>

问题:

它不会按属性“值”降序排序 - 是因为前面的语句吗?

来源可以在这里找到:http: //xmlsoap.dk/xml/crCountLog.xml

4

1 回答 1

2

它没有按您期望的方式工作的原因是它以文档顺序preceding-sibling::查看items 的前面的兄弟姐妹,而不是当前的排序顺序。所以它们正在被排序,但是值正在被计算,就好像你根本没有对它们进行排序一样。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>

This approach selects the first item with no items less than itself, and applies templates to only that, passing the remaining items as parameters. Then the next top item is selected and the template recursively calls itself, repeatedly until all of the items have been used up.

于 2013-02-11T09:38:13.067 回答