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

XSLT设置第2个property元素type属性,Qt实现不生效问题排查

问题描述

需要修改XML中第二个<property>元素的type属性,输入XML如下:

<t>
    <property>value1</property>
    <property type="oldtype">value2</property>
    <property type="oldtype">value3</property>
    <property type="oldtype">value4</property>
</t>

使用的XSLT 1.0代码如下:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:param name="pNewType" select="'newtype'"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="property[2]/@type">
        <xsl:attribute name="type">
            <xsl:value-of select="$pNewType"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

这段代码在xsltproc和在线XSLT工具中可以正常生成预期输出,但在Qt的XSLT实现中无效(isValid()返回true,但转换结果与输入一致)。去掉[2]索引时,能正常修改所有property的type属性。预期输出为:

<t>
    <property>value1</property>
    <property type="newtype">value2</property>
    <property type="oldtype">value3</property>
    <property type="oldtype">value4</property>
</t>

询问这种转换方式是否正确,以及如何解决Qt中的问题。

问题分析与解决方案

你写的这段XSLT在标准XSLT 1.0规范里是没问题的,但Qt的XSLT实现(大概率基于旧版libxslt或有自定义兼容逻辑)对直接通过property[2]/@type这种路径匹配属性节点的支持有兼容性问题,这就是为什么在其他工具里正常、Qt里没效果的原因。

给你两个可行的修正方案:

方案1:直接匹配第二个property元素再修改属性

换个思路,先匹配到第二个property元素,在复制它的时候替换type属性,这种写法兼容性更好:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:param name="pNewType" select="'newtype'"/>
    
    <!-- 身份模板:默认复制所有节点和属性 -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- 匹配第二个property元素 -->
    <xsl:template match="property[2]">
        <xsl:copy>
            <!-- 写入新的type属性 -->
            <xsl:attribute name="type">
                <xsl:value-of select="$pNewType"/>
            </xsl:attribute>
            <!-- 复制元素内的文本内容 -->
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

方案2:通过父节点判断匹配属性

如果想保留属性级别的模板匹配,可以通过属性的父节点位置来判断,避免在路径里直接用索引:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:param name="pNewType" select="'newtype'"/>
    
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- 匹配父节点是第二个property的type属性 -->
    <xsl:template match="@type[parent::property[2]]">
        <xsl:attribute name="type">
            <xsl:value-of select="$pNewType"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

这两种写法都能在Qt的XSLT实现中正常工作,核心是避开了Qt不兼容的路径索引匹配方式,改用更通用的节点匹配逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:46:15