使用XSLT 1.0更新XML节点属性失败(命名空间导致)
嘿,这个问题我太熟悉了——命名空间在XML和XSLT里简直是最容易踩的隐形坑!你遇到的核心问题是:输入XML里的所有元素都属于http://www.rixml.org/2013/2/RIXML命名空间,但你的XSLT完全没处理命名空间规则,导致目标模板根本匹配不到元素。移除命名空间后元素脱离了命名空间约束,模板就能正常触发,这也反过来验证了问题根源。
下面是具体的修复步骤和修正后的代码:
1. 给XSLT添加命名空间声明
首先在XSLT的根元素<xsl:stylesheet>里声明目标命名空间,并用一个前缀(比如rix)来引用它:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rix="http://www.rixml.org/2013/2/RIXML">
2. 修正模板的匹配路径
原来的匹配规则//Research/Product/StatusInfo只会匹配无命名空间的元素,必须加上我们声明的前缀,让XSLT知道要匹配哪个命名空间下的元素:
<xsl:template match="rix:Research/rix:Product/rix:StatusInfo">
3. 修复属性名的拼写错误
你XSLT里的属性名写成了stausType(少了一个a),这会导致即使匹配成功,生成的属性名也是错误的,要改成statusType。
4. 保留元素的原命名空间
原来的<xsl:element name="StatusInfo">会生成无命名空间的元素,我们需要确保新生成的StatusInfo元素仍属于原命名空间,可以直接用前缀<rix:StatusInfo>,或者在xsl:element里指定namespace属性。
完整修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rix="http://www.rixml.org/2013/2/RIXML"> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*" /> </xsl:copy> </xsl:template> <xsl:template match="rix:Research/rix:Product/rix:StatusInfo"> <rix:StatusInfo> <xsl:attribute name="statusType">Deleted</xsl:attribute> </rix:StatusInfo> </xsl:template> </xsl:stylesheet>
为什么原来的代码不生效?
XML里的元素一旦带上命名空间,就相当于属于一个“独立的元素集合”,XSLT的匹配规则默认只会匹配无命名空间的元素。你移除XML的xmlns属性后,元素脱离了命名空间,自然就能被原来的模板匹配到了。
Java代码无需修改
你的Java转换逻辑是完全正常的,不需要做任何调整,只要替换修正后的XSLT文件,就能正常更新属性了。
内容的提问来源于stack exchange,提问作者user2709315

