如何在XSLT中正确访问祖先元素并生成纯净CSV结果?
XSLT转换XML到CSV时的冗余噪声问题解决
问题背景
你需要把这份XML转换成指定格式的CSV:
<employees> <global> <attr>test</attr> </global> <employee> <details> <name>Joe</name> <age>34</age> <stage> <type code="A" count="1"/> <type code="B" count="2"/> <type code="C" count="3"/> </stage> </details> </employee> <employee> <details> <age>24</age> <name>Sam</name> </details> <stage> <type code="A" count="1"/> </stage> </employee> </employees>
期望得到的CSV结果是:
test;Joe;34;A;1 test;Joe;34;B;2 test;Joe;34;C;3 test;Sam;24;A;1
你尝试了这份XSLT代码:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" omit-xml-declaration="yes" indent="no"/> <xsl:template match="type"> <xsl:value-of select="ancestor::employees/global/attr, ancestor::employee/details/name, ancestor::employee/details/age, @code, @count" separator=";" /> </xsl:template> </xsl:stylesheet>
但生成的结果却带有冗余噪声:
test Joe 34 test;Joe;34;A;1 test;Joe;34;B;2 test;Joe;34;C;3 24 Sam test;Sam;24;A;1
噪声来源分析
这些冗余内容其实是XSLT的默认模板行为导致的:
- XSLT有一套内置的默认模板,其中针对文本节点(包括XML里的空白换行、标签内的文本内容)的模板会直接输出文本内容。
- 你的XML里的
<attr>test</attr>、<name>Joe</name>、<age>34</age>这些文本节点,还有节点之间的空白字符,都没有被你的自定义模板匹配,所以默认模板就把它们都输出了,就变成了你看到的“噪声”。
解决方法
要解决这个问题,我们需要做两件事:
- 覆盖默认的文本节点模板,阻止输出无关的文本内容;
- 确保每条CSV记录单独占一行,让结果更规范。
修改后的XSLT代码如下:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" omit-xml-declaration="yes" indent="no"/> <!-- 覆盖默认文本节点模板,不输出任何无关文本 --> <xsl:template match="text()"/> <xsl:template match="type"> <xsl:value-of select="ancestor::employees/global/attr, ancestor::employee/details/name, ancestor::employee/details/age, @code, @count" separator=";" /> <!-- 每条记录后添加换行符,让结果每行一条 --> <xsl:text> </xsl:text> </xsl:template> </xsl:stylesheet>
代码解释
<xsl:template match="text()"/>:这个模板匹配所有文本节点,并且什么都不输出,直接覆盖了默认的文本输出模板,这样那些空白字符和无关的文本内容就不会被输出了。<xsl:text> </xsl:text>:添加换行符( 是换行的Unicode转义),让每条CSV记录单独占一行,和你期望的结果格式一致。
运行修改后的XSLT,就能得到干净的目标CSV结果啦!
内容的提问来源于stack exchange,提问作者membersound
相关产品推荐
相关产品推荐

