XSLT-计算所选节点的价格总和

时间:2019-01-03 18:06:09

标签: xml xslt

我有以下xml代码:

struct A

此代码用于使用xslt进行xml转换:

<?xml version="1.0" encoding="UTF-8"?>
<audioteka xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="audioteka.xsd">

<CD id="p1">
<title>Butchered at Birth</title>
<author>Cannibal Corpse</author>
<genre>Metal</genre>
<release_date>1991-06-30</release_date>
<price currency="PLN">49.99</price>
<publisher>
    <name>Napalm Records</name>
    <country>USA</country>
</publisher>
</CD>
<CD id = "p2">
<title>Battalions of Fear</title>
<author>Blind Guardian</author>
<genre>Metal</genre>
<release_date>1988-02-15</release_date>
<price currency="PLN">34.99</price>
<publisher>
    <name>BMG</name>
    <country>Belgia</country>
</publisher>
</CD>
<CD id = "p3">
<title>Dangerous Days</title>
<author>Perturbator</author>
<genre>Synthwave</genre>
<release_date>2014-09-17</release_date>
<price currency="EUR">52.99</price>
<publisher>
    <name>Mystic Productions</name>
    <country>Polska</country>
</publisher>
</CD>
</audioteka>

但是我不知道如何计算5张所选CD的标题和价格之和。我尝试使用

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
version="1.0"
xmlns:a="http://www.test.com/">
<xsl:output method="xml" indent="yes"/>

<xsl:param name="Num" select="2"/>

<xsl:template match="audioteka">
     Zamowienie - faktura       
<xsl:for-each select="/audioteka/CD">
    <xsl:sort select="author" order="descending" />
    <xsl:if test="position() &lt;= $Num">
    Tytul: <xsl:value-of select="title"/>
    Autor: <xsl:value-of select="author"/>
    Gatunek: <xsl:value-of select="genre"/>
    Cena: <xsl:value-of select="price"/>
    ----------------------------------
    </xsl:if>     
</xsl:for-each>  

但是这给了我错误的值。有人有解决方案的想法吗?

1 个答案:

答案 0 :(得分:0)

解决此问题的想法是:

  • 将必需的元素存储在变量中。
  • 运行for-each循环以从此变量中提取内容。
  • 总价格也来自此变量。

有点麻烦的是,在XSLT 1.0中,此变量的类型 是结果树片段(RTF),因此不能直接在 XPath 中使用 表达式。

要规避此限制,必须使用exsl:node-set函数, 将此类 RTF 转换为节点集,然后在 XPath 中使用它。

因此整个脚本如下所示:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:exsl="http://exslt.org/common"
  extension-element-prefixes="exsl">
  <xsl:output method="text"/>

  <xsl:param name="Num" select="2"/>

  <xsl:template match="/">
    <xsl:variable name="discs">
      <xsl:for-each select="audioteka/CD">
        <xsl:sort select="author" order="descending"/>
        <xsl:if test="position() &lt;= $Num">
          <xsl:copy-of select="."/>
        </xsl:if>
      </xsl:for-each>
    </xsl:variable>
    <xsl:text>Zamowienie - faktura&#x0A;&#x0A;</xsl:text>
    <xsl:for-each select="exsl:node-set($discs)/CD">
      <xsl:value-of select="concat('Tytul:   ', title, '&#x0A;')"/>
      <xsl:value-of select="concat('Autor:   ', author, '&#x0A;')"/>
      <xsl:value-of select="concat('Gatunek: ', genre, '&#x0A;')"/>
      <xsl:value-of select="concat('Cena:    ', price, '&#x0A;')"/>
      <xsl:text>----------------------------------&#x0A;</xsl:text>
    </xsl:for-each>
    <xsl:value-of select="concat('Suma:    ', sum($discs/CD/price),
      '&#x0A;')"/>
  </xsl:template>
</xsl:stylesheet>

如您所见,我还对输出生成做了一些更正。

首先要注意的是输出方法= text ,因为您生成了 “普通”文本,而不是XML。

另一个变化是,对于文本输出,我将xsl:text&#x0A;用于换行符。 好处是脚本中的代码(和文本)缩进不 影响输出缩进。

有关工作示例,请参见http://xsltransform.net/3MP2uBx