在 xslt 1.0 中减去排序节点

  • 本文关键字:排序 节点 xslt xml xslt
  • 更新时间 :
  • 英文 :


但是我对每个事件减去值 B 和 P 还有其他问题。源代码是这样的:

<EVENTS>
<ROW ID="204" ID_PLACE="1" EVENT_TYPE="B" EVENT_NAME="TEST1" EVENT_ID="201">
<PRICE>
<ROW EVENT_PRICE="165,00"/>
</PRICE>
</ROW>
<ROW ID="205" ID_PLACE="1" EVENT_TYPE="P" EVENT_NAME="TEST1" EVENT_ID="201">
<PRICE>
<ROW EVENT_PRICE="125,00"/>
</PRICE>
</ROW>
<ROW ID="206" ID_PLACE="1" EVENT_TYPE="B" EVENT_NAME="TEST2" EVENT_ID="202">
<PRICE>
<ROW EVENT_PRICE="100,00"/>
</PRICE>
</ROW>
<ROW ID="207" ID_PLACE="1" EVENT_TYPE="P" EVENT_NAME="TEST2" EVENT_ID="202">
<PRICE>
<ROW EVENT_PRICE="135,00"/>
</PRICE>
</ROW>
</EVENTS>

我必须得到这样的东西:

<EVENT_ID>201</EVENT_ID>
<DIFF>40.00</DIFF>
<EVENT_ID>202</EVENT_ID>
<DIFF>-35.00</DIFF>

等。在这种情况下,我现在EVENT_ID在文件中,但并不总是只有这两个 ID,所以我不能这样做:对于 ID=201 diff 是 40,对于 202 diff 是 -35。如何为源代码中的每个ID_EVENT编写 xsl 转换。

我会使用一个键来按行EVENT_ID链接行:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="p" match="ROW[@EVENT_TYPE='P']" use="@EVENT_ID" />
<xsl:template match="/EVENTS">
    <EVENTS>
        <xsl:for-each select="ROW[@EVENT_TYPE='B']">
            <xsl:variable name="B" select="PRICE/ROW/@EVENT_PRICE"/>
            <xsl:variable name="P" select="key('p', @EVENT_ID)/PRICE/ROW/@EVENT_PRICE"/>
            <xsl:variable name="diff" select="translate($B, ',', '.') - translate($P, ',', '.')" />
            <EVENT_ID>
                <xsl:value-of select="@EVENT_ID" />
            </EVENT_ID>
            <DIFF>
                <xsl:value-of select="format-number($diff, '0.00')" />
            </DIFF>
        </xsl:for-each>
    </EVENTS>
</xsl:template>
</xsl:stylesheet>

演示:http://xsltransform.net/bEzjRJW

另一种方法是使用分组:

XSLT 2.0

<xsl:for-each-group select="EVENTS/ROW" group-by="EVENT_ID">
  <xsl:variable name="B" select="current-group()[EVENT_TYPE='B']/PRICE/ROW/@EVENT_PRICE"/>
  <xsl:variable name="P" select="current-group()[EVENT_TYPE='P']/PRICE/ROW/@EVENT_PRICE"/>               
  <xsl:variable name="diff" select="translate($B, ',', '.') - translate($P, ',', '.')" />
  <EVENT_ID>
     <xsl:value-of select="current-grouping-key()" />
  </EVENT_ID>
  <DIFF>
     <xsl:value-of select="format-number($diff, '0.00')" />
  </DIFF>
</xsl:for-each-group>

在回答你之前的问题时,我说过,除了寻找具有共同<EVENTS>父元素的元素之外,还有其他方法可以解决匹配相应<ROW>元素的问题。 这个问题中提出的情况需要这样一种办法。

正如其他答案所建议的那样,可以使用键或 XSLT 2.0 分组来执行此操作。 但另一种方法是简单地编写一个合适的 XPath 表达式来选择与每个"B"行匹配的"P"行(反之亦然(。 例如

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
  <xsl:strip-space elements="*"/>
  <xsl:decimal-format decimal-separator="." zero-digit="0" minus-sign="-" />
  <!-- transform based on 'B' rows   -->
  <xsl:template match="EVENTS/ROW[@EVENT_TYPE = 'B']">
    <xsl:variable name="event-id" select="@EVENT_ID"/>
    <!-- select the corresponding 'P' row, if any -->
    <xsl:variable name="event-p" select="../ROW[@EVENT_TYPE = 'P' and @EVENT_ID = $event-id]"/>
    <!-- supposing that there was a matching 'P' row ... -->
    <xsl:if test="$event-p">
      <!-- extract the two rows' prices here to simplify later expressions -->
      <xsl:variable name="b-price"
          select="number(translate(PRICE/ROW/@EVENT_PRICE, ',', '.'))"/>
      <xsl:variable name="p-price"
          select="number(translate($event-p/PRICE/ROW/@EVENT_PRICE, ',', '.'))"/>
      <!-- Add the wanted elements to the result tree -->
      <EVENT_ID>
        <xsl:value-of select="$event-id"/>
      </EVENT_ID>
      <DIFF>
        <!-- If you require the specific numeric format you presented, then 
             you need to ask for it -->
        <xsl:value-of select="format-number($b-price - $p-price, '0.00;-0.00')" />
      </DIFF>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

最新更新