Xslt 如何使用其他节点的计算数据汇总节点
使用XSLT1.0,我如何总结给定节点下的子节点,同时以优雅的方式使用另一组节点的数据修改内容?假设我有以下xml:Xslt 如何使用其他节点的计算数据汇总节点,xslt,xpath,Xslt,Xpath,使用XSLT1.0,我如何总结给定节点下的子节点,同时以优雅的方式使用另一组节点的数据修改内容?假设我有以下xml: <Root> <ExchangeRates> <ExchangeRate> <CurrencyCode>USD</CurrencyCode> <Rate>6.4</Rate> </ExchangeRate
<Root>
<ExchangeRates>
<ExchangeRate>
<CurrencyCode>USD</CurrencyCode>
<Rate>6.4</Rate>
</ExchangeRate>
<ExchangeRate>
<CurrencyCode>EUR</CurrencyCode>
<Rate>8.44</Rate>
</ExchangeRate>
<ExchangeRate>
<CurrencyCode>SEK</CurrencyCode>
<Rate>1</Rate>
</ExchangeRate>
</ExchangeRates>
<Prices>
<Price>
<Currency>SEK</Currency>
<Amount>10000</Amount>
</Price>
<Price>
<Currency>EUR</Currency>
<Amount>1000</Amount>
</Price>
<Price>
<Currency>USD</Currency>
<Amount>1000</Amount>
</Price>
</Prices>
</Root>
美元
6.4
欧元
8.44
瑞典克朗
1.
瑞典克朗
10000
欧元
1000
美元
1000
我要在汇率的帮助下将所有金额的总和兑换成瑞典克朗。结果应该是:
<SumInSEK>24840</SumInSEK>
24840
如果不必转换金额,我只需使用xpath sum()函数。在这种情况下是否可以使用该功能 我想这可能很简单。。。但我认为你不能在这个场合使用sum()。。。我只能做一个递归模板
?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:key name="rates" match="//ExchangeRate/Rate" use="parent::*/child::CurrencyCode/text()"/>
<xsl:template match="//Prices">
<SUmInSEK>
<xsl:call-template name="sum"/>
</SUmInSEK>
</xsl:template>
<xsl:template name="sum">
<xsl:param name="iterator" select="1"/>
<xsl:param name="total" select="0"/>
<xsl:variable name="price" select="child::Price[$iterator]"/>
<xsl:variable name="current">
<xsl:value-of select="number($price/child::Amount) * number( key('rates', $price/child::Currency) )"/>
</xsl:variable>
<xsl:variable name="newtotal">
<xsl:value-of select="$total + $current"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$price/following-sibling::Price">
<xsl:call-template name="sum">
<xsl:with-param name="iterator" select="$iterator+1"/>
<xsl:with-param name="total" select="$newtotal"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$total + $current"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="* | /">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="text() | @*">
</xsl:template>
<xsl:template match="processing-instruction() | comment()" />
</xsl:stylesheet>
?xml version=“1.0”encoding=“utf-8”>
我想这可能很简单。。。但我认为你不能在这个场合使用sum()。。。我只能做一个递归模板
?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:key name="rates" match="//ExchangeRate/Rate" use="parent::*/child::CurrencyCode/text()"/>
<xsl:template match="//Prices">
<SUmInSEK>
<xsl:call-template name="sum"/>
</SUmInSEK>
</xsl:template>
<xsl:template name="sum">
<xsl:param name="iterator" select="1"/>
<xsl:param name="total" select="0"/>
<xsl:variable name="price" select="child::Price[$iterator]"/>
<xsl:variable name="current">
<xsl:value-of select="number($price/child::Amount) * number( key('rates', $price/child::Currency) )"/>
</xsl:variable>
<xsl:variable name="newtotal">
<xsl:value-of select="$total + $current"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$price/following-sibling::Price">
<xsl:call-template name="sum">
<xsl:with-param name="iterator" select="$iterator+1"/>
<xsl:with-param name="total" select="$newtotal"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$total + $current"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="* | /">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="text() | @*">
</xsl:template>
<xsl:template match="processing-instruction() | comment()" />
</xsl:stylesheet>
?xml version=“1.0”encoding=“utf-8”>
另一种可能的解决方案,没有递归调用,但具有exsl扩展。
这将使用键定义形式@softwarebear
<?xml version="1.0" encoding="utf-8"?>
<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:key name="rates" match="//ExchangeRate/Rate" use="parent::*/child::CurrencyCode/text()"/>
<xsl:template match="/" >
<xsl:apply-templates select="//Prices"/>
</xsl:template>
<xsl:template match="Prices">
<SUmInSEK>
<xsl:variable name="price_SEK">
<xsl:apply-templates mode="SEK" />
</xsl:variable>
<xsl:value-of select="sum(exsl:node-set($price_SEK)//price_SEK)"/>
</SUmInSEK>
</xsl:template>
<xsl:template match="Price" mode="SEK">
<price_SEK>
<xsl:value-of
select="number(Amount) * number( key('rates', Currency) )" />
</price_SEK>
</xsl:template>
</xsl:stylesheet>
输出是多少
<SUmInSEK>24840</SUmInSEK>
24840
另一种可能的解决方案,没有递归调用,但具有exsl扩展。
这将使用键定义形式@softwarebear
<?xml version="1.0" encoding="utf-8"?>
<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:key name="rates" match="//ExchangeRate/Rate" use="parent::*/child::CurrencyCode/text()"/>
<xsl:template match="/" >
<xsl:apply-templates select="//Prices"/>
</xsl:template>
<xsl:template match="Prices">
<SUmInSEK>
<xsl:variable name="price_SEK">
<xsl:apply-templates mode="SEK" />
</xsl:variable>
<xsl:value-of select="sum(exsl:node-set($price_SEK)//price_SEK)"/>
</SUmInSEK>
</xsl:template>
<xsl:template match="Price" mode="SEK">
<price_SEK>
<xsl:value-of
select="number(Amount) * number( key('rates', Currency) )" />
</price_SEK>
</xsl:template>
</xsl:stylesheet>
输出是多少
<SUmInSEK>24840</SUmInSEK>
24840
比我的递归尝试更好+为什么使用迭代器和Price节点作为参数?这只是我开始工作的第一个解决方案,我猜我可以沿着Price节点作为当前上下文来工作。。。哦,看看你的答案。。。我不知道我们能比我的递归尝试做得更好+为什么使用迭代器和Price节点作为参数?这只是我开始工作的第一个解决方案,我猜我可以沿着Price节点作为当前上下文来工作。。。哦,看看你的答案。。。我不知道我们可以做得很好,我选择使用这个解决方案。从中也学到了一些东西。有两件事我很好奇:为什么在价格模板中使用mode属性而不是匹配模式?为什么在price_SEK节点名称之前有两个斜杠?这个小示例在没有模式的情况下也可以工作。但是,如果您必须对价格标签执行其他操作,那么您仍然可以添加另一个价格模板(无模式)。你是对的,一个斜杠就可以了。(似乎我是个粗心的人)很好,我选择使用这个解决方案。从中也学到了一些东西。有两件事我很好奇:为什么在价格模板中使用mode属性而不是匹配模式?为什么在price_SEK节点名称之前有两个斜杠?这个小示例在没有模式的情况下也可以工作。但是,如果您必须对价格标签执行其他操作,那么您仍然可以添加另一个价格模板(无模式)。你是对的,一个斜杠就可以了。(看来我是个粗心的人)