【问题标题】:XSLT: Sum of specific attribute value based on other attribute's nameXSLT:基于其他属性名称的特定属性值的总和
【发布时间】:2013-02-27 06:02:56
【问题描述】:

我有以下 XML 文档(由另一方提供)

<transactions>
  <transaction TaxAType="11" TaxAValue="111" TaxBType="2" TaxBValue="222" TaxCType="3" TaxCValue="333"/>
  <transaction TaxAType="11" TaxAValue="111" TaxBType="2" TaxBValue="222" TaxCType="3" TaxCValue="333"/>
</transactions>

例如,如果相应的 Tax*Type = '11',我想编写一个 XSLT 文档来转换这些行并总结 Tax*Value。

如果不使用模板,这可能吗?

XQuery 中的

name()、substring() 等函数? 您对此有何看法?

【问题讨论】:

  • 结果应该是什么样的?只有一个号码?一些带有总数的 XML?例如,您说“Tax*Type = '11'”。这是否意味着在您的示例 XML 中,TaxBValue 和 TaxCValue 不会相加?
  • 这个想法是,我会将类型为 10 的所有值的总和存储在转换后的文档的属性中。例如 转换交易元素
  • 这并不能说明问题。这次“10”型是从哪里来的?您是如何得出结果 5433 的?你能详细描述你想做什么吗?鉴于您在问题中提出的示例 XML,输出应该是什么?
  • 因此,如果 GST 等于税款 11,则 gstAmount 将为 222。问题是税款 11 可以存储在 TaxAType 和/或 TaxBType 和/或 TaxCType 中
  • 我现在明白了。谢谢你的澄清。如果您有兴趣,我在下面发布了一个通用解决方案。

标签: xml xslt xslt-1.0


【解决方案1】:

看看下面的 XSLT:

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

    Sum of TaxA where type = 11:
    <xsl:value-of select="sum(transactions/transaction[@TaxAType='11']/@TaxAValue)" />

    Sum of all tax where type = 11:
    <xsl:value-of select="sum(transactions/transaction[@TaxAType='11']/@TaxAValue) 
      + sum(transactions/transaction[@TaxBType='11']/@TaxBValue) 
      + sum(transactions/transaction[@TaxCType='11']/@TaxCValue)" />

  </xsl:template>
</xsl:stylesheet>

它计算 TaxAType = 11 节点的 TaxAValue 总和,以及 Tax?Type = 11 节点的所有 Tax?Value 总和。

【讨论】:

  • 这行得通!谢谢...我正在考虑使用用户定义的函数使用更通用的方法,但由于模式是预定义的,这将起作用!谢谢!
【解决方案2】:

这是一个有点冗长但通用的方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:param name="taxType" select="11" />

  <xsl:template match="transactions">
    <result>
      <xsl:variable name="allValues" 
                    select="transaction/@*[substring(local-name(), 5, 5) = 'Type']
                                          [. = $taxType]" />
      <xsl:call-template name="SumValues">
        <xsl:with-param name="items" select="$allValues" />
      </xsl:call-template>
    </result>
  </xsl:template>

  <xsl:template name="SumValues">
    <xsl:param name="items" />
    <xsl:param name="total" select="0" />

    <xsl:choose>
      <xsl:when test="not($items)">
        <xsl:value-of select="$total" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="currentItem" select="$items[1]" />
        <xsl:variable name="currentValue">
          <xsl:apply-templates select="$currentItem" mode="getMatchingValue" />
        </xsl:variable>

        <xsl:call-template name="SumValues">
          <xsl:with-param name="items" select="$items[position() > 1]" />
          <xsl:with-param name="total" select="$total +  $currentValue" />
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="@*" mode="getMatchingValue">
    <xsl:variable name="typeCodeLetter" select="substring(local-name(), 4, 1)" />
    <xsl:variable name="valueAttributeName"
                  select="concat('Tax', $typeCodeLetter, 'Value')" />
    <xsl:variable name="matchingValueAttribute"
                  select="../@*[local-name() = $valueAttributeName]" />

    <!-- Multiply by boolean to handle the case where the 
         attribute wasn't found-->
    <xsl:value-of select="$matchingValueAttribute * 
                          boolean($matchingValueAttribute)"/>
  </xsl:template>
</xsl:stylesheet>

这应该能够处理任意数量的Tax*Types(只要*是单个字符)并且可以将所需的类型作为参数传入。

【讨论】:

    【解决方案3】:

    此 xml 的格式不适合完成您要求执行的处理类型。 您最好的选择是使用 javascript 或其他具有 XML 功能的语言(C#、Java 等)来提取您需要的详细信息。

    使用 javascript,您可以找到 Tax*Type=11 的任何属性,然后获取下一个属性的值

    【讨论】:

    • 我相信它不是纯 XSL,但我可能已经找到了一种合理的方法来创建用户定义函数,该函数将接收所有属性的节点列表,其名称为 Tax?Type,值为 11,UDF然后会查看并总结“对应物”是 Tax?Value。
    【解决方案4】:

    sum(交易/交易[@TaxAType='11']/@TaxAValue | @TaxBvalue | @TaxCvalue)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-28
      • 1970-01-01
      • 2019-09-02
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      相关资源
      最近更新 更多