You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT 1.0:动态生成节点的sign匹配求和与非兄弟sign节点求和及键问题

解决XSLT 1.0中的节点匹配与求和需求

一、动态生成节点的键(xsl:key)问题处理

XSLT 1.0的xsl:key默认仅能索引源文档节点,你通过ext:node-set()生成的临时节点集无法直接被全局key识别。解决方法是:先把临时节点集转为可索引的节点集,再在模板内部定义针对该节点集的key——XSLT 1.0允许在模板内定义key,只要作用域覆盖使用场景即可。

示例框架:

<!-- 假设已生成<a>节点并存储在$tempAs变量中 -->
<xsl:variable name="allAs" select="exsl:node-set($tempAs)/a"/>

<!-- 在模板内定义针对动态节点集的key -->
<xsl:key name="a-by-sign" match="$allAs" use="@sign"/>

注:不同处理器的扩展函数前缀不同,Apache用exsl:,MSXML用msxsl:,需对应调整。

二、需求1:含子节点的求和匹配的数值

利用上述定义的key,通过<b>/sign的文本值匹配@sign相等的节点,再用sum()函数完成求和:

<xsl:template match="b[sign]">
  <b-result sign="{sign/text()}">
    <!-- 求和所有@sign匹配当前<sign>值的<a>节点数值(示例假设数值存在于文本中) -->
    <xsl:value-of select="sum(key('a-by-sign', sign/text())/text())"/>
  </b-result>
</xsl:template>

三、需求2:无子节点的求和“不在兄弟的值”的数值

XSLT 1.0没有原生not in语法,可通过not(@sign = 集合)模拟该逻辑:

  1. 先收集所有兄弟的值到变量:
<xsl:variable name="existingSigns" select="../b[sign]/sign/text()"/>
  1. 筛选<a>节点中@sign不在该集合内的节点并求和:
<xsl:template match="b[not(sign)]">
  <b-result type="other">
    <xsl:variable name="existingSigns" select="../b[sign]/sign/text()"/>
    <xsl:value-of select="sum($allAs[not(@sign = $existingSigns)]/text())"/>
  </b-result>
</xsl:template>

not(@sign = $existingSigns)的逻辑:当@sign与集合中任意值相等时表达式为true,取反后即表示“不在集合内”。

完整示例参考

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:exsl="http://exslt.org/common"
                extension-element-prefixes="exsl">

  <!-- 模拟生成动态<a>节点的过程 -->
  <xsl:variable name="tempAs">
    <a sign="A">10</a>
    <a sign="B">20</a>
    <a sign="C">30</a>
    <a sign="D">40</a>
  </xsl:variable>
  <xsl:variable name="allAs" select="exsl:node-set($tempAs)/a"/>

  <!-- 定义针对动态节点集的key -->
  <xsl:key name="a-by-sign" match="$allAs" use="@sign"/>

  <xsl:template match="/">
    <output>
      <xsl:apply-templates select="//b"/>
    </output>
  </xsl:template>

  <!-- 处理带<sign>的<b>节点 -->
  <xsl:template match="b[sign]">
    <b-result sign="{sign/text()}">
      <xsl:value-of select="sum(key('a-by-sign', sign/text())/text())"/>
    </b-result>
  </xsl:template>

  <!-- 处理不带<sign>的<b>节点 -->
  <xsl:template match="b[not(sign)]">
    <b-result type="other">
      <xsl:variable name="existingSigns" select="../b[sign]/sign/text()"/>
      <xsl:value-of select="sum($allAs[not(@sign = $existingSigns)]/text())"/>
    </b-result>
  </xsl:template>

</xsl:stylesheet>

注意事项

内容的提问来源于stack exchange,提问作者Kaffetrinken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 03:22:48