You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何对XML元素值应用函数并输出保留属性的新XML文档?

解决XSLT处理XML时属性丢失与复杂公式应用问题

咱们先拆解你遇到的两个核心问题:row元素的name属性丢失,以及如何应用依赖元素值的复杂计算逻辑,一步步来解决:

一、为什么name属性会丢失?

你的自定义模板匹配test/row[@name='C/A'] | test/row[@name='C/B']时,只执行了<xsl:copy>复制元素本身,然后直接输出计算后的值,但<xsl:copy>并不会自动复制元素的属性。你需要在这个模板里显式处理属性节点,就像默认的identity模板那样。

修改后的模板如下:

<xsl:template match="test/row[@name='C/A'] | test/row[@name='C/B']">
  <xsl:copy>
    <!-- 先复制当前元素的所有属性(包括name) -->
    <xsl:apply-templates select="@*"/>
    <!-- 再输出计算后的值 -->
    <xsl:value-of select=". * 1000"/>
  </xsl:copy>
</xsl:template>

这样处理后,row元素的name属性就会被保留下来了。

二、如何应用依赖元素值的复杂公式?

如果你的计算逻辑需要根据当前row的值动态调整(比如根据数值正负、范围使用不同乘数),在XSLT 1.0里可以用<xsl:choose>实现条件判断,或者把复用逻辑封装成模板调用。

示例1:简单条件判断计算

比如实现“负数乘以2000,正数乘以1000”的逻辑:

<xsl:template match="test/row[@name='C/A'] | test/row[@name='C/B']">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:choose>
      <xsl:when test=". &lt; 0">
        <xsl:value-of select=". * 2000"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select=". * 1000"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:copy>
</xsl:template>

示例2:封装复杂计算为可复用模板

如果公式逻辑更复杂(比如多分支判断、多步骤计算),可以把计算逻辑封装成独立模板,方便复用:

<!-- 封装计算逻辑的模板 -->
<xsl:template name="complex-calculate">
  <xsl:param name="input-value"/>
  <xsl:choose>
    <xsl:when test="$input-value &lt; -0.15">
      <xsl:value-of select="$input-value * 1500"/>
    </xsl:when>
    <xsl:when test="$input-value &lt; 0">
      <xsl:value-of select="$input-value * 1000"/>
    </xsl:when>
    <xsl:when test="$input-value &lt; 2">
      <xsl:value-of select="$input-value * 900"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$input-value * 800"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<!-- 调用计算模板的row处理逻辑 -->
<xsl:template match="test/row[@name='C/A'] | test/row[@name='C/B']">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:call-template name="complex-calculate">
      <xsl:with-param name="input-value" select="."/>
    </xsl:call-template>
  </xsl:copy>
</xsl:template>

完整的修改后XSLT样式表

把上面的逻辑整合起来,最终的样式表如下:

<?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" version="1.0" encoding="UTF-8" indent="yes" />
 <!-- Identity模板:默认复制所有未被自定义模板匹配的节点和属性 -->
 <xsl:template match="@* | node()">
  <xsl:copy>
   <xsl:apply-templates select="@* | node()" />
  </xsl:copy>
 </xsl:template>
 <!-- 处理C/A和C/B的row元素,保留属性并应用自定义计算 -->
 <xsl:template match="test/row[@name='C/A'] | test/row[@name='C/B']">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <!-- 这里替换成你的复杂计算逻辑 -->
    <xsl:value-of select=". * 1000"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

使用这个样式表处理你的源XML,就能得到保留name属性且计算正确的输出了。

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

火山引擎 最新活动