平均值,从高格式到低格式排序

时间:2012-10-20 13:42:32

标签: xml xslt xslt-1.0

发现以下xsl / xml问题在回答时需要帮助。将其作为挑战。 问题: 1 - 得到每个大陆的平均值(格式编号“###,###。00”),
每批2个,应从最高到最低排序,
3顶级昂贵的批次只是列表
试图获得一些模板(下面)请帮助提出一个模板,该模板将运行以产生所需的结果 总批次(从最高到最低)=
每个大陆的平均值= ###。00 =昂贵批次的前三名=

<?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet type="text/xsl" href="factory.xslt"?>

 <factory>
    <branch>
        <continent>North America</continent>
        <location>usa</location>
        <address>671 fourth avenue</address>
        <batch>
            <car_make>
                <name>toyota</name>
                <number_of_makes>20</number_of_makes>
                <price_per_make>12000</price_per_make>
            </car_make>
        </batch>
        <batch>
            <car_make>
                <name>opel</name>
                <number_of_makes>5</number_of_makes>
                <price_per_make>10000</price_per_make>
            </car_make>
        </batch>
    </branch>
    <branch>
        <continent>Europe</continent>
        <location>france</location>
        <address>671 paris</address>
        <batch>
            <car_make>
                <name>nissan</name>
                <number_of_makes>10</number_of_makes>
                <price_per_make>20000</price_per_make>
            </car_make>
        </batch>
    </branch>
    <branch>
        <continent>North America</continent>
        <location>detroit</location>
        <address>45 parklane</address>
        <batch>
            <car_make>
                <name>doge</name>
                <number_of_makes>40</number_of_makes>
                <price_per_make>35000</price_per_make>
            </car_make>
        </batch>
        <batch>
            <car_make>
                <name>cadillac</name>
                <number_of_makes>20</number_of_makes>
                <price_per_make>14000</price_per_make>
            </car_make>
        </batch>
    </branch>
    <branch>
        <continent>Europe</continent>
        <location>germany</location>
        <address>675 berlin avenue</address>
        <batch>
            <car_make>
                <name>opel</name>
                <number_of_makes>42</number_of_makes>
                <price_per_make>19000</price_per_make>
            </car_make>
        </batch>
        <batch>
            <car_make>
                <name>mercedes</name>
                <number_of_makes>20</number_of_makes>
                <price_per_make>24000</price_per_make>
            </car_make>
        </batch>
    </branch>
    <branch>
        <continent>North America</continent>
        <location>texas</location>
        <address>46 parkland way</address>
        <batch>
            <car_make>
                <name>hummer</name>
                <number_of_makes>30</number_of_makes>
                <price_per_make>45000</price_per_make>
            </car_make>
        </batch>
        <batch>
            <car_make>
                <name>cadillac</name>
                <number_of_makes>20</number_of_makes>
                <price_per_make>14000</price_per_make>
            </car_make>
        </batch>
    </branch>
    <branch>
        <continent>Asia</continent>
        <location>india</location>
        <address>67 new delhi way</address>
        <batch>
            <car_make>
                <name>tata</name>
                <number_of_makes>12</number_of_makes>
                <price_per_make>25000</price_per_make>
            </car_make>
        </batch>
        <batch>
            <car_make>
                <name>ford</name>
                <number_of_makes>20</number_of_makes>
                <price_per_make>20000</price_per_make>
            </car_make>
        </batch>
    </branch>
    <branch>
        <continent>Asia</continent>
        <location>japan</location>
        <address>56 yorki avenue</address>
        <batch>
            <car_make>
                <name>mazda</name>
                <number_of_makes>40</number_of_makes>
                <price_per_make>23000</price_per_make>
            </car_make>
        </batch>
        <batch>
            <car_make>
                <name>hyundai</name>
                <number_of_makes>20</number_of_makes>
                <price_per_make>10000</price_per_make>
            </car_make>
        </batch>
    </branch>
    <branch>
        <continent>Asia</continent>
        <location>korea</location>
        <address>12 yung </address>
        <batch>
            <car_make>
                <name>skyline</name>
                <number_of_makes>14</number_of_makes>
                <price_per_make>18000</price_per_make>
            </car_make>
        </batch>
        <batch>
            <car_make>
                <name>toyota</name>
                <number_of_makes>40</number_of_makes>
                <price_per_make>12000</price_per_make>
            </car_make>
        </batch>
    </branch>
    <branch>
        <continent>Europe</continent>
        <location>england</location>
        <address>56 parklane</address>
        <batch>
            <car_make>
                <name>bentely</name>
                <number_of_makes>24</number_of_makes>
                <price_per_make>50000</price_per_make>
            </car_make>
        </batch>
        <batch>
            <car_make>
                <name>ferrari</name>
                <number_of_makes>10</number_of_makes>
                <price_per_make>120000</price_per_make>
            </car_make>
        </batch>
    </branch>
</factory>

以下是xslt版本1.0

    

<xsl:template match="/*">
  TOTAL BATCH:-<a>
    $<xsl:call-template name="sumProducts">
      <xsl:with-param name="pNodes" select="/*/*/*/batch"/>
      <xsl:with-param name="pName1" select="'number_of_make'"/>
      <xsl:with-param name="pName2" select="'price_per_make'"/>
    </xsl:call-template>
  </a><br/>
</xsl:template>



<xsl:template name="sumProducts">

  <xsl:param name="pNodes"/>
  <xsl:param name="pName1"/>
  <xsl:param name="pName2"/>
  <xsl:param name="pAccum" select="0"/>

  <xsl:choose>
    <xsl:when test="not($pNodes)">
      <xsl:value-of select="$pAccum"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="sumProducts">
        <xsl:with-param name="pNodes" select="$pNodes[position() >1]"/>
        <xsl:with-param name="pName1" select="$pName1"/>
        <xsl:with-param name="pName2" select="$pName2"/>
        <xsl:with-param name="pAccum" select="$pAccum + $pNodes[1]/*[name()=$pName1] * $pNodes[1]/*[name()=$pName2]"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="TotalPrice">

  <xsl:param name="pList"/>
  <xsl:param name="pRunningTotal" select="0"/>

  <xsl:choose>
    <xsl:when test="$pList">
      <xsl:variable name="varMapPath" select="$pList[1]"/>
      <xsl:call-template name="TotalPrice">
        <xsl:with-param name="pList" select="$pList[position() > 1]"/>
        <xsl:with-param name="pRunningTotal"
         select="$pRunningTotal + $varMapPath/productpriceperunit * $varMapPath/productsordered"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$pRunningTotal"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

1 个答案:

答案 0 :(得分:1)

这是我尝试解决方案:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="4.0" />

<xsl:variable name="title">Troy's Stack Overflow XSLT Challenge</xsl:variable>

<xsl:template match="/*">
  <xsl:element name="html">
    <xsl:element name="head">
      <xsl:element name="title">
        <xsl:value-of select="$title"/>
      </xsl:element>
    </xsl:element>
    <xsl:element name="body">
      <xsl:element name="h1">
        <xsl:value-of select="$title"/>
      </xsl:element>

      <xsl:call-template name="AverageCarPricePerContinent" />
      <xsl:call-template name="TotalPerBatch" />
      <xsl:call-template name="TopNMostExpensiveBatches"><xsl:with-param name="n" select="3" /></xsl:call-template>

    </xsl:element>
  </xsl:element>
</xsl:template>

<xsl:template match="/factory/branch">
  <xsl:call-template name="ContinentAverage">
    <xsl:with-param name="continentName" select="./continent/text()" />
  </xsl:call-template>
</xsl:template>

<xsl:template name="AverageCarPricePerContinent">
  <xsl:element name="h2">
    <xsl:text>1. Average Car Price Per Continent</xsl:text>
  </xsl:element>
  <xsl:element name="ol">
    <xsl:apply-templates select="/factory/branch[not(./continent=preceding-sibling::branch/continent)]" />
  </xsl:element>
</xsl:template>

<xsl:template name="TotalPerBatch">
  <xsl:element name="h2">
    <xsl:text>2. Total Per Batch (&#x25bc;)</xsl:text>
  </xsl:element>
  <xsl:call-template name="OutputBatchesDesc">
    <xsl:with-param name="batches" select="/factory/branch/batch" />
  </xsl:call-template>
</xsl:template>

<xsl:template name="TopNMostExpensiveBatches">
  <xsl:param name="n" />
  <xsl:element name="h2">
    <xsl:value-of select="concat('3. Top ',$n,' Most Expensive Batch(es)')"/>
  </xsl:element>
  <xsl:call-template name="OutputBatchesDesc">
    <xsl:with-param name="batches" select="/factory/branch/batch" />
    <xsl:with-param name="n" select="$n" />
  </xsl:call-template>
</xsl:template>

<xsl:template name="OutputBatchesDesc">
  <xsl:param name="batches" />
  <xsl:param name="n" select="count($batches)" />
  <xsl:element name="ol">
    <xsl:for-each select="$batches">

      <xsl:sort data-type="number" order="descending" select="(./car_make/price_per_make)[1] * (./car_make[1]/number_of_makes)[1]" />

      <xsl:if test="position() &lt;= $n">
        <xsl:element name="li">
          <xsl:value-of select="format-number(./car_make/price_per_make * ./car_make/number_of_makes, '0,000,000.00')"/>
          <xsl:text> - </xsl:text>
          <xsl:value-of select="../continent/text()"/>
          <xsl:text> - </xsl:text>
          <xsl:value-of select="../location/text()"/>
          <xsl:text> - </xsl:text>
          <xsl:value-of select="../address/text()"/>
          <xsl:text> - </xsl:text>
          <xsl:value-of select="./car_make/name/text()"/>
        </xsl:element>
      </xsl:if>

    </xsl:for-each>
  </xsl:element>
</xsl:template>



<xsl:template name="ContinentAverage">
  <xsl:param name="continentName" />
  <xsl:element name="li">
    <xsl:value-of select="$continentName"/>
    <xsl:text> - </xsl:text>
    <xsl:value-of select="format-number(sum(/factory/branch[./continent[text()=$continentName]]//batch/car_make/price_per_make/text()) div count(/factory/branch[./continent[text()=$continentName]]//batch/car_make/price_per_make), '###,###.00')"/>        
  </xsl:element>
</xsl:template>

</xsl:stylesheet>

输出(HTML源)

<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Troy's Stack Overflow XSLT Challenge</title>
  </head>
  <body>
    <h1>Troy's Stack Overflow XSLT Challenge</h1>
    <h2>1. Average Car Price Per Continent</h2>
    <ol>
      <li>North America - 21,666.67</li>
      <li>Europe - 46,600.00</li>
      <li>Asia - 18,000.00</li>
    </ol>
    <h2>2. Total Per Batch (?)</h2>
    <ol>
      <li>1,400,000.00 - North America - detroit - 45 parklane - doge</li>
      <li>1,350,000.00 - North America - texas - 46 parkland way - hummer</li>
      <li>1,200,000.00 - Europe - england - 56 parklane - bentely</li>
      <li>1,200,000.00 - Europe - england - 56 parklane - ferrari</li>
      <li>0,920,000.00 - Asia - japan - 56 yorki avenue - mazda</li>
      <li>0,798,000.00 - Europe - germany - 675 berlin avenue - opel</li>
      <li>0,480,000.00 - Europe - germany - 675 berlin avenue - mercedes</li>
      <li>0,480,000.00 - Asia - korea - 12 yung  - toyota</li>
      <li>0,400,000.00 - Asia - india - 67 new delhi way - ford</li>
      <li>0,300,000.00 - Asia - india - 67 new delhi way - tata</li>
      <li>0,280,000.00 - North America - detroit - 45 parklane - cadillac</li>
      <li>0,252,000.00 - Asia - korea - 12 yung  - skyline</li>
      <li>0,240,000.00 - North America - usa - 671 fourth avenue - toyota</li>
      <li>0,200,000.00 - Europe - france - 671 paris - nissan</li>
      <li>0,200,000.00 - Asia - japan - 56 yorki avenue - hyundai</li>
      <li>0,050,000.00 - North America - usa - 671 fourth avenue - opel</li>
    </ol>
    <h2>3. Top 3 Most Expensive Batch(es)</h2>
    <ol>
      <li>1,400,000.00 - North America - detroit - 45 parklane - doge</li>
      <li>1,350,000.00 - North America - texas - 46 parkland way - hummer</li>
      <li>1,200,000.00 - Europe - england - 56 parklane - bentely</li>
    </ol>
  </body>
</html>

修改 根据评论,现在更新以计算每个BRANCH的第2和第3部分而不是每个BATCH。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" version="4.0" />

  <xsl:variable name="title">Troy's Stack Overflow XSLT Challenge</xsl:variable>

  <xsl:template match="/*">
    <xsl:element name="html">
      <xsl:element name="head">
        <xsl:element name="title">
          <xsl:value-of select="$title"/>
        </xsl:element>
      </xsl:element>
      <xsl:element name="body">
        <xsl:element name="h1">
          <xsl:value-of select="$title"/>
        </xsl:element>

        <xsl:call-template name="AverageCarPricePerContinent" />
        <xsl:call-template name="TotalPerBranch" />
        <xsl:call-template name="TopNMostExpensiveBranches">
          <xsl:with-param name="n" select="3" />
        </xsl:call-template>

      </xsl:element>
    </xsl:element>
  </xsl:template>

  <xsl:template match="/factory/branch">
    <xsl:call-template name="ContinentAverage">
      <xsl:with-param name="continentName" select="./continent/text()" />
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="AverageCarPricePerContinent">
    <xsl:element name="h2">
      <xsl:text>1. Average Car Price Per Continent</xsl:text>
    </xsl:element>
    <xsl:element name="ol">
      <xsl:apply-templates select="/factory/branch[not(./continent=preceding-sibling::branch/continent)]" />
    </xsl:element>
  </xsl:template>

  <xsl:template name="TotalPerBranch">
    <xsl:element name="h2">
      <xsl:text>2. Total Per Branch (&#x25bc;)</xsl:text>
    </xsl:element>
    <xsl:element name="ol">
      <xsl:call-template name="OutputBranchesDesc">
        <xsl:with-param name="branches" select="/factory/branch" />
      </xsl:call-template>
    </xsl:element>
  </xsl:template>

  <xsl:template name="TopNMostExpensiveBranches">
    <xsl:param name="n" />
    <xsl:element name="h2">
      <xsl:value-of select="concat('3. Top ',$n,' Most Expensive Branch(es)')"/>
    </xsl:element>
    <xsl:call-template name="OutputBranchesDesc">
      <xsl:with-param name="branches" select="/factory/branch" />
      <xsl:with-param name="n" select="$n" />
    </xsl:call-template>
  </xsl:template>


  <xsl:template name="ContinentAverage">
    <xsl:param name="continentName" />
    <xsl:element name="li">
      <xsl:value-of select="$continentName"/>
      <xsl:text> - </xsl:text>
      <xsl:value-of select="format-number(sum(/factory/branch[./continent[text()=$continentName]]//batch/car_make/price_per_make/text()) div count(/factory/branch[./continent[text()=$continentName]]//batch/car_make/price_per_make), '###,###.00')"/>
    </xsl:element>
  </xsl:template>

  <xsl:template name="OutputBranchesDesc">
    <xsl:param name="branches" />
    <xsl:param name="n" select="count($branches)" />
    <xsl:choose>
      <xsl:when test="$branches and $n &gt; 0">
        <xsl:variable name="i">
          <xsl:call-template name="getHighest">
            <xsl:with-param name="branches" select="$branches" />
          </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="branchValue">
          <xsl:call-template name="GetBranchValue">
            <xsl:with-param name="branch" select="$branches[position() = $i]" />
          </xsl:call-template>
        </xsl:variable>
        <xsl:element name="li">
          <xsl:value-of select="format-number($branchValue, '0,000,000.00')"/>
          <xsl:text> - </xsl:text>
          <xsl:value-of select="$branches[position() = $i]/continent/text()"/>
          <xsl:text> - </xsl:text>
          <xsl:value-of select="$branches[position() = $i]/location/text()"/>
          <xsl:text> - </xsl:text>
          <xsl:value-of select="$branches[position() = $i]/address/text()"/>
        </xsl:element>
        <xsl:call-template name="OutputBranchesDesc">
          <xsl:with-param name="branches" select="($branches)[position() != $i]" />
          <xsl:with-param name="n" select="$n - 1" />
        </xsl:call-template>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

  <xsl:template name ="getHighest">
    <xsl:param name="branches" />
    <xsl:param name="highestValue" select="0" />
    <xsl:param name="highestIndex" select="0" />
    <xsl:param name="currentIndex" select="1" />
    <xsl:choose>
      <xsl:when test="$branches">

        <xsl:variable name="currentBranchValue">
          <xsl:call-template name="GetBranchValue">
            <xsl:with-param name="branch" select="$branches[position() = 1]" />
          </xsl:call-template>
        </xsl:variable>

        <xsl:variable name="highest">
          <xsl:choose>
            <xsl:when test="$highestValue &gt; $currentBranchValue">
              <xsl:value-of select="$highestValue"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="$currentBranchValue"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:variable name="newHighestIndex">
          <xsl:choose>
            <xsl:when test="$highestValue &gt; $currentBranchValue">
              <xsl:value-of select="$highestIndex"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="$currentIndex"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:call-template name="getHighest">
          <xsl:with-param name="branches" select="($branches)[position() &gt; 1]" />
          <xsl:with-param name="highestValue" select="$highest" />
          <xsl:with-param name="highestIndex" select="$newHighestIndex" />
          <xsl:with-param name="currentIndex" select="$currentIndex + 1" />
        </xsl:call-template>

      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$highestIndex"/>
      </xsl:otherwise>
    </xsl:choose>

  </xsl:template>

  <xsl:template name="GetBranchValue">
    <xsl:param name="branch" />
    <xsl:param name="value" select="0" />
    <xsl:param name="i" select="count($branch//batch)" />
    <xsl:choose>
      <xsl:when test="$i &gt; 0">
        <xsl:call-template name="GetBranchValue">
          <xsl:with-param name="branch" select="$branch" />
          <xsl:with-param name="i" select="$i - 1" />
          <xsl:with-param name="value" select="$value + (($branch//batch)[position() = $i]/car_make[1]/number_of_makes[1])[1] * (($branch//batch)[position() = $i]/car_make[1]/price_per_make[1])[1]" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$value"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


</xsl:stylesheet>

更新输出

<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Troy's Stack Overflow XSLT Challenge</title>
  </head>
  <body>
    <h1>Troy's Stack Overflow XSLT Challenge</h1>
    <h2>1. Average Car Price Per Continent</h2>
    <ol>
      <li>North America - 21,666.67</li>
      <li>Europe - 46,600.00</li>
      <li>Asia - 18,000.00</li>
    </ol>
    <h2>2. Total Per Branch (▼)</h2>
    <ol>
      <li>2,400,000.00 - Europe - england - 56 parklane</li>
      <li>1,680,000.00 - North America - detroit - 45 parklane</li>
      <li>1,630,000.00 - North America - texas - 46 parkland way</li>
      <li>1,278,000.00 - Europe - germany - 675 berlin avenue</li>
      <li>1,120,000.00 - Asia - japan - 56 yorki avenue</li>
      <li>0,732,000.00 - Asia - korea - 12 yung </li>
      <li>0,700,000.00 - Asia - india - 67 new delhi way</li>
      <li>0,290,000.00 - North America - usa - 671 fourth avenue</li>
      <li>0,200,000.00 - Europe - france - 671 paris</li>
    </ol>
    <h2>3. Top 3 Most Expensive Branch(es)</h2>
    <li>2,400,000.00 - Europe - england - 56 parklane</li>
    <li>1,680,000.00 - North America - detroit - 45 parklane</li>
    <li>1,630,000.00 - North America - texas - 46 parkland way</li>
  </body>
</html>