2012-03-06 56 views
1

我有XML结构类似下面的源文件:XSLT映射和求和源儿童成一个单一的目标属性

<FOO> 
    <BAR>x</BAR> 
    <BAR>y</BAR> 
    <BAR>z</BAR> 
</FOO> 

我的目标XML必须有一个数字,表示x的数值总和的属性,y和z。其中x = 1,y = 2和z = 3

注意:x,y和z实际上并不是源文档中的数字。它们是字母,需要映射到它们首先代表的数字。

在这种情况下,目标应该是这个样子:

<Target Sum=6> 
</Target> 

任何人都有一个XSLT例子,会做什么,我需要?

在此先感谢

回答

0
<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes"/> 

<xsl:template match="/"> 
    <Target Sum="{sum(FOO/BAR)}" /> 
</xsl:template> 

编辑:

这是一个有点冗长,而且有可能是一个更优雅的方式来做到这一点,但本质上我有一个名为模板在这里递归调用自己来计算硬编码映射发生后的总和:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
    <Target> 
     <xsl:attribute name="Sum"> 
     <xsl:call-template name="GetSum"> 
      <xsl:with-param name="CurrentNode" select="FOO/BAR[position()=1]"/> 
     </xsl:call-template> 
    </xsl:attribute> 
    </Target> 
    </xsl:template> 

    <xsl:template name="GetSum"> 
    <xsl:param name="CurrentNode"/> 
    <xsl:param name="Number" select="0"/> 

    <xsl:variable name="Recursive_Result"> 
     <xsl:variable name="MappedNumber"> 
     <xsl:choose> 
      <xsl:when test="$CurrentNode/. = 'x'">1</xsl:when> 
      <xsl:when test="$CurrentNode/. = 'y'">2</xsl:when> 
      <xsl:when test="$CurrentNode/. = 'z'">3</xsl:when> 
      <xsl:otherwise>0</xsl:otherwise> 
     </xsl:choose> 
     </xsl:variable> 

     <!-- if there is a next sibling, recursively call GetSum --> 
     <xsl:choose> 
     <xsl:when test="$CurrentNode/following-sibling::BAR[1]"> 
      <xsl:call-template name="GetSum"> 
      <xsl:with-param name="CurrentNode" select="$CurrentNode/following-sibling::BAR[1]"/> 
      <xsl:with-param name="Number"> 
       <xsl:value-of select="$MappedNumber"/> 
      </xsl:with-param> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$MappedNumber"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:variable> 

    <!-- add the recursive_result to the number passed into the template. this will eventually build a sum --> 
    <xsl:value-of select="$Recursive_Result + $Number"/> 
    </xsl:template> 
</xsl:stylesheet> 
+0

布拉德,感谢您的快速回答。如果X,Y和Z实际上是源文档中的数字,那么这个技巧就会实现,但它们实际上是字母。所以我需要先映射它们。我怎么做?谢谢,-J – 2012-03-06 18:36:15

+0

啊 - 我明白你的意思了 - 我的错,我误解了。 X,Y和Z在哪里?源文档中的那些节点是否有一些? – 2012-03-06 18:46:20

+0

是的。它们是的文本节点,具体取决于运行时的实际值,我需要能够将它们映射到数值,然后将它们相加。我可以使用模板将它们转换为数值,但我想我不知道如何总结我从模板中获得的结果。合理? – 2012-03-06 18:52:09

0

一个更简单的,更短的和有效的解决方案

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:key name="kMap" match="@value" use="../@key"/> 

<xsl:variable name="vMaps" as="element()*"> 
    <map key="x" value="1"/> 
    <map key="y" value="2"/> 
    <map key="z" value="3"/> 
</xsl:variable> 

<xsl:template match="/*"> 
    <Target Sum="{sum(key('kMap', BAR, document('')))}"/> 
</xsl:template> 
</xsl:stylesheet> 

当这个变换所提供的XML文档施加:

<FOO> 
    <BAR>x</BAR> 
    <BAR>y</BAR> 
    <BAR>z</BAR> 
</FOO> 

有用,正确的结果产生

<Target Sum="6"/> 

说明:适当使用xsl:keykey()函数的第三个参数和AVT。