但是我对每个事件减去值 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>