【问题标题】:XSL: xsl:if test not working and calculate sumXSL:xsl:如果测试不起作用并计算总和
【发布时间】:2021-04-03 19:01:40
【问题描述】:

对于下面的简化转换表,我想添加以下功能:

  1. 对于“2019 年营业额”和“2020 年营业额”,我希望在红色徽章中获得低于 1mio 的值,在绿色徽章中获得超过 1mio 的值。我试图为“2019 年营业额”实现这一点,但是我得到一个空白输出。问题似乎出在<xsl:if test="...">-part 上,因为如果我输入<xsl:value-of select="key('keyToCreditcard', id)/turnover_2019"/>,我确实得到了正确的值(请参阅“2020 年营业额”)。
  2. 对于“总营业额”,我需要总结“2019 年营业额”和“2020 年营业额”的值。我该怎么做?

XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="keyToPerson" match="person" use="id"/>
  <xsl:key name="keyToCreditcard" match="creditcard" use="cardowner"/>

  <xsl:template match="/">
    <xsl:for-each select="data/persons/person">
      <xsl:if test="turnoverYear1 &lt; 1000000">
        <span class="badge bg-warning mx-2"><xsl:value-of select="key('keyToCreditcard', id)/turnoverYear1"/></span>
      </xsl:if>
      <xsl:if test="turnoverYear1 &gt; 999999.99">
        <span class="badge bg-danger mx-2"><xsl:value-of select="key('keyToCreditcard', id)/turnoverYear1"/></span>
      </xsl:if>
      <xsl:value-of select="key('keyToCreditcard', id)/turnoverYear2"/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

输入

<data>
 <persons>
   <person>
      <id>1</id>
      <name>Jeramie Bischoff</name>
      <city>Luzern</city>
      <birthdate>04/16/1951</birthdate>
    </person>
  </persons>
  <creditcards>
    <creditcard>
      <id>1</id>
      <cardtype>Visa</cardtype>
      <cardnumber>4041592612048990</cardnumber>
      <turnoverYear1>952411.33</turnoverYear1>
      <turnoverYear2>6135840.0</turnoverYear2>
      <cardowner>1</cardowner>
  </creditcard>
 </creditcards>
</data>

预期输出:

Name:Jeramie Bischoff
City: Luzern
birthdate: 04/16/1951

Card Type: Visa
Card Number: 4041592612048990
Turnover 2019: 952411.33
Turnover 2020: 6135840.0
Total Turnover: 7088251.33

【问题讨论】:

  • 没有看到您正在使用的 XML 就无法回答这个问题。
  • 请发minimal reproducible example incl。输入和预期输出(作为代码)。
  • 另外,您显然有名为&lt;turnover_2019&gt;&lt;turnover_2020&gt; 的元素。这是个坏主意。如果你能对此做任何事情,那就改变它。如果元素名称中包含数据,这让生活变得变得更加困难。请改用&lt;turnover year="2019"&gt; 之类的东西。
  • 1mio 是 100000 的意思吗?
  • 谢谢大家的意见,我现在已经相应地修改了。

标签: html xslt xslt-1.0


【解决方案1】:

根据您的示例 XML,一个好的方法是将内容拆分为多个模板。

一个处理创建基本 HTML 文档结构 (match="/"),一个处理 &lt;person&gt; 元素,一个处理营业额徽章,等等。一般来说,更喜欢&lt;xsl:apply-templates&gt;,而不是把所有东西都塞进一个带有一堆嵌套&lt;xsl:for-each&gt;的模板中。

由于您有一个将个人 ID 链接到信用卡的 &lt;xsl:key&gt;,因此可以使用它来将 &lt;creditcard&gt; 提取到变量 ($cc) 中并使用它。

<xsl:output method="html" indent="yes" />
<xsl:key name="keyToCreditcard" match="creditcard" use="cardowner"/>

<xsl:template match="/">
  <html>
    <!-- ... -->
    <xsl:apply-templates select="data/persons/person" />
    <!-- ... -->
  </html>
</xsl:template>

<xsl:template match="person">
  <div class="person">
    <xsl:variable name="cc" select="key('keyToCreditcard', id)" />
    <!-- your question #1 -->
    <div>
      <xsl:text>Turnover 2019: </xsl:text>
      <xsl:apply-templates select="$cc/turnoverYear1" />
    </div>
    <div>
      <xsl:text>Turnover 2020: </xsl:text>
      <xsl:apply-templates select="$cc/turnoverYear2" />
    </div>
    <!-- your question #2 -->
    <div>
      <xsl:text>Total Turnover: </xsl:text>
      <xsl:value-of select="$cc/turnoverYear1 + $cc/turnoverYear2" />
    </div>
  </div>
</xsl:template>

<xsl:template match="turnoverYear1|turnoverYear2">
  <span>
    <xsl:attribute name="class">
      <xsl:text>badge mx-2 </xsl:text>
      <xsl:choose>
        <xsl:when test=". &lt; 1000000">bg-warning</xsl:when>
        <xsl:when test=". &lt; 99999.99">bg-danger</xsl:when>
      </xsl:choose>
    </xsl:attribute>
    <xsl:value-of select="." />
  </span>
</xsl:template>

导致

<html>
  <div class="person">
    <div>Turnover 2019: <span class="badge mx-2 bg-warning">952411.33</span></div>
    <div>Turnover 2020: <span class="badge mx-2">6135840.0</span></div>
    <div>Total Turnover: 7088251.33</div>
  </div>
</html>

因为年份数字和 XML 元素名称是 XML 中的一个移动目标,所以您必须每年不断调整 XSLT 代码。这是完全没有必要的。将年份排除在 XML 元素名称之外要聪明得多。将其移动到属性中:

<creditcards>
  <creditcard>
    <id>1</id>
    <cardtype>Visa</cardtype>
    <cardnumber>4041592612048990</cardnumber>
    <turnover year="2019">952411.33</turnover>
    <turnover year="2020">6135840.0</turnover>
    <cardowner>1</cardowner>
  </creditcard>
</creditcards>

使用像这样的&lt;creditcard&gt; 设置,XSLT 代码变得更加通用。

<xsl:template match="person">
  <div class="person">
    <xsl:variable name="cc" select="key('keyToCreditcard', id)" />
    <!-- your question #1 -->
    <xsl:apply-templates select="$cc/turnover" />
    <!-- your question #2 -->
    <div>
      <xsl:text>Total Turnover: </xsl:text>
      <xsl:value-of select="sum($cc/turnover)" />
    </div>
  </div>
</xsl:template>

<xsl:template match="turnover">
  <div>
    <xsl:value-of select="concat('Turnover ', @year, ': ')" />
    <span>
      <xsl:attribute name="class">
        <xsl:text>badge mx-2 </xsl:text>
        <xsl:choose>
          <xsl:when test=". &lt; 1000000">bg-warning</xsl:when>
          <xsl:when test=". &lt; 99999.99">bg-danger</xsl:when>
        </xsl:choose>
      </xsl:attribute>
      <xsl:value-of select="." />
    </span>
  </div>
</xsl:template>

【讨论】:

  • 非常感谢您的帮助,成功了!
  • @Anja 很高兴听到。但也要想想你得到的所有 cmets。例如,为每人拥有一张以上信用卡时会发生什么做好计划。
猜你喜欢
  • 2012-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多