如何解决XSLT转换带命名空间XML时的输出不符合预期问题?
XML转换问题解决方案
问题背景
现有带命名空间的XML文档,需通过XSLT转换为指定格式,当前转换结果不符合预期,具体信息如下:
原XML文档
<Records xmlns=http://www.archer-tech.com/ xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation=https://analysiscenter.veracode.com/schema/2.0/archerapi https://analysiscenter.veracode.com/resource/2.0/archerreport.xsd> <Record> <app_name>C3L-SCHEDULER</app_name> <app_id>1484475</app_id> <cwe_description>testsdsasadas</cwe_description> </Record> <Record> <app_name>C3L-SCHEDULER</app_name> <app_id>1484475</app_id> </Record> <Record> <app_name>C3L-SCHEDULER</app_name> <app_id>1484475</app_id> <cwe_description>testsdsasadsadasdsadaas</cwe_description> </Record> </Records>
原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" input="xml" /> <xsl:template match="/"> <Records> <xsl:for-each select="./Record"> <Record> <xsl:copy-of select="app_name" /> <app_id><xsl:value-of select="app_id" /></app_id> <cwe_description> <xsl:if test="cwe_description"> <xsl:copy-of select="cwe_description" /> </xsl:if> </cwe_description> </Record> </xsl:for-each> </Records> </xsl:template> </xsl:stylesheet>
预期输出
<Records> <Record> <app_name>C3L-SCHEDULER</app_name> <app_id>1484475</app_id> <cwe_description>testsdsasadas</cwe_description> </Record> <Record> <app_name>C3L-SCHEDULER</app_name> <app_id>1484475</app_id> <cwe_description></cwe_description> </Record> <Record> <app_name>C3L-SCHEDULER</app_name> <app_id>1484475</app_id> <cwe_description>testsdsasadsadasdsadaas</cwe_description> </Record> </Records>
问题原因
- 命名空间未处理:原XML的
Records节点带有默认命名空间http://www.archer-tech.com/,XSLT未绑定该命名空间,导致./Record无法匹配到任何节点,最终输出空的<Records>。 - 标签嵌套错误:处理
cwe_description时,在<cwe_description>标签内部使用<xsl:copy-of>会生成嵌套的<cwe_description>标签,不符合预期格式。 - 无效输出属性:
<xsl:output>中的input="xml"是无效属性,不符合XSLT规范。
修正后的XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:arch="http://www.archer-tech.com/" exclude-result-prefixes="arch"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <xsl:template match="/"> <Records> <xsl:for-each select="arch:Records/arch:Record"> <Record> <xsl:copy-of select="arch:app_name"/> <app_id><xsl:value-of select="arch:app_id"/></app_id> <cwe_description><xsl:value-of select="arch:cwe_description"/></cwe_description> </Record> </xsl:for-each> </Records> </xsl:template> </xsl:stylesheet>
关键修改说明
- 绑定命名空间:添加
xmlns:arch="http://www.archer-tech.com/",并通过exclude-result-prefixes="arch"避免命名空间污染输出结果。 - 修正节点选择路径:将
./Record改为arch:Records/arch:Record,正确匹配带命名空间的节点。 - 简化cwe_description处理:使用
<xsl:value-of>直接获取节点内容,无论原节点是否存在,都会输出<cwe_description>标签,内容为空或原节点值,符合预期格式。 - 修正输出配置:移除无效的
input="xml",添加indent="yes"让输出更易读。
内容的提问来源于stack exchange,提问作者Thiago Oberle
相关产品推荐
相关产品推荐

