XSLT1.0复制XML节点新增元素时XPath报错及多元素丢失问题
问题根因
- 单节点新增XPath定位失效:
- 若输入XML存在默认命名空间,XSLT未声明对应命名空间前缀会导致节点匹配失败
- 判断条件误用
QTY/C186/E6063 != '指定值':该表达式在SG26下无QTY节点时会返回false,无法正确触发新增逻辑,必须使用not(QTY/C186/E6063 = '指定值')才能正确判断“不存在匹配节点”的场景
- 多节点新增时单个节点丢失:
- 多目标值判断共用同一个分支逻辑,未做独立判断
- 遍历目标值时XPath上下文错误,无法正确关联当前SG26节点下的QTY元素
实现方案
基础逻辑
基于XSLT1.0的身份模板实现全量节点无损复制,单独匹配SG26节点做扩展处理:先复制所有原有子节点,再逐个检查目标E6063值,不存在对应节点则新增。
兼容EXSLT的通用实现(支持任意数量目标值)
大部分XSLT1.0处理器(libxslt、MSXML等)均支持EXSLT扩展,适合目标值较多的场景:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl"> <!-- 身份模板:全量复制原有节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- SG26节点特殊处理 --> <xsl:template match="SG26"> <xsl:copy> <!-- 复制原有所有子节点 --> <xsl:apply-templates select="@*|node()"/> <!-- 定义需要新增的E6063目标值列表 --> <xsl:variable name="targetE6063"> <val>59</val> <val>60</val> </xsl:variable> <!-- 遍历目标值逐个判断 --> <xsl:for-each select="exsl:node-set($targetE6063)/val"> <xsl:variable name="currentVal" select="."/> <!-- 定位到当前SG26节点判断是否存在对应QTY --> <xsl:if test="not(../../QTY/C186/E6063 = $currentVal)"> <QTY> <C186> <E6063><xsl:value-of select="$currentVal"/></E6063> <!-- 可按需补充其他C186子节点,示例为E6060赋值0 --> <E6060>0</E6060> </C186> </QTY> </xsl:if> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
无扩展兼容实现(仅支持固定数量目标值)
如果处理器不支持EXSLT,可独立编写每个目标值的判断逻辑,避免节点丢失:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="SG26"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <!-- 独立判断E6063=59的场景 --> <xsl:if test="not(QTY/C186/E6063 = '59')"> <QTY> <C186> <E6063>59</E6063> <E6060>0</E6060> </C186> </QTY> </xsl:if> <!-- 独立判断E6063=60的场景 --> <xsl:if test="not(QTY/C186/E6063 = '60')"> <QTY> <C186> <E6063>60</E6063> <E6060>0</E6060> </C186> </QTY> </xsl:if> </xsl:copy> </xsl:template> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者Petrucho
相关产品推荐
相关产品推荐

