为何先复制属性后添加节点仍触发XTDE0410属性添加错误?
XSLT转换触发XTDE0410错误的解决方案
问题描述
运行XSLT代码时出现错误:XTDE0410: Cannot add attribute node to an element node that already has non attribute or namespace children。尽管在复制节点时明确先复制属性再处理子节点,但错误依然触发。尝试移除报错节点、取消文件遍历、合并属性与节点的apply-templates操作,均未解决问题。
运行的XSLT代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xquery="http://www.w3.org/2005/xpath-functions" xmlns:upd="http://www.w3.org/2007/xquery-update-10"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <xsl:for-each select="document('f1.xml')"> <xsl:variable name="doc" select="."/> <xsl:variable name="newFileName" select="concat(substring-before(document-uri($doc), '.xml'), '_chg.xml')" /> <xsl:result-document href="{$newFileName}"> <xsl:apply-templates select="$doc/*"/> </xsl:result-document> </xsl:for-each> </xsl:template> <!-- Template to match the root element --> <xsl:template match="/"> <xsl:apply-templates select="*"/> </xsl:template> <!-- Identity template to copy all nodes and attributes --> <xsl:template match="@*|node()"> <xsl:copy> <!-- Copy attributes first --> <xsl:apply-templates select="@*"/> <!-- Then copy child nodes --> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
错误信息
XTDE0410: Cannot add attribute node to an element node that already has non attribute or namespace children
示例XML
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="file:///F:/temp%20(F)/2025-06-24a_debug/DataPower_Control_File_cleanup_actions_V3.xslt"?> <registeredServices> <domain name="entsvcs" description="Enterprise Services"> <service name="commonlogging" version="1.0" type="SOAP" endpoint="http://localhost:3016" sldpolicy="default_sld_policy"> <registeredConsumers> <!-- <consumer><consumerId></consumerId><consumerName></consumerName><clientName></clientName><slaPolicy>bcbst_default_sla_policy</slaPolicy><logLevel>0</logLevel> --> <!-- 0 = ALL, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=FATAL, 6=OFF --> <!-- </consumer> --> <consumer> <consumerId>bcbstesvcs</consumerId> <consumerName>BCBST</consumerName> <clientName>Enterprise Services</clientName> <slaPolicy>bcbst_default_sla_policy</slaPolicy> <logLevel>1</logLevel> </consumer> </registeredConsumers> </service> </domain> </registeredServices>
问题原因
代码中定义了两个匹配根节点/的模板,二者优先级相同,XSLT处理器无法确定执行逻辑,导致内部处理混乱,进而触发了看似与属性/子节点顺序相关的XTDE0410错误。
解决方案
删除多余的第二个match="/"模板,修改后的代码如下:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xquery="http://www.w3.org/2005/xpath-functions" xmlns:upd="http://www.w3.org/2007/xquery-update-10"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <xsl:for-each select="document('f1.xml')"> <xsl:variable name="doc" select="."/> <xsl:variable name="newFileName" select="concat(substring-before(document-uri($doc), '.xml'), '_chg.xml')" /> <xsl:result-document href="{$newFileName}"> <xsl:apply-templates select="$doc/*"/> </xsl:result-document> </xsl:for-each> </xsl:template> <!-- Identity template to copy all nodes and attributes --> <xsl:template match="@*|node()"> <xsl:copy> <!-- Copy attributes first --> <xsl:apply-templates select="@*"/> <!-- Then copy child nodes --> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
补充说明
- 原有的身份模板(identity template)逻辑正确:先复制属性再处理子节点,符合XML节点的构造规则(属性必须在子节点之前添加)。
- 编写XSLT时需确保同一节点的匹配模板唯一,或通过
priority属性明确指定模板优先级,避免处理器逻辑混乱。
内容的提问来源于stack exchange,提问作者paulhr
相关产品推荐
相关产品推荐

