XSLT将源子节点映射和求和为单个目标属性

时间:2012-03-06 18:20:35

标签: xslt-2.0

我有一个XML结构的源文档,类似于:

<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示例可以满足我的需求吗?

提前致谢

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分: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的第3个参数。