https://xsltfiddle.liberty-development.net/bFDb2C4
我想将以下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>
结果应该是:
test;Joe;34;A;1
test;Joe;34;B;2
test;Joe;34;C;3
test;Sam;24;A;1
因此我认为我可以匹配最深层次(这里是type
),并附加所有ancestor::
。以下xslt一般工作,但也输出很多&#34;噪声&#34;围绕期望的结果(参见xsltfidde):
<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>
问题:&#34;噪音&#34;来自?我怎样才能收到csv线?
这是目前的结果:
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
答案 0 :(得分:1)
你拥有的模板很好,并且正在完成它的工作。问题是当XSLT开始处理时,它会查找与文档元素/
匹配的模板,其模板中没有。当XSLT正在寻找模板且模板中没有匹配的模板时,它会使用built-in templates。
基本上,它将遍历XML和输出文本节点。因此,在最终到达匹配type
的模板之前,您会获得大量文本输出。
有几种解决方案。一种是使模板匹配/
并明确选择type
节点
<xsl:template match="/">
<xsl:apply-templates select="//type" />
</xsl:template>
另一种选择是使模板匹配text()
个节点,以忽略它们,从而覆盖默认模板行为
<xsl:template match="text()" />
但是,当您使用XSLT 3.0时,您也可以执行此操作,而不是添加新模板以指定不采用匹配模板的操作
<xsl:mode on-no-match="shallow-skip"/>
注意,在所有情况下,您都需要在现有模板中输出换行符。
试试这个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:mode on-no-match="shallow-skip"/>
<xsl:template match="type">
<xsl:value-of select="ancestor::global/attr,
ancestor::employee/details/name,
ancestor::employee/details/age,
@code,
@count"
separator=";" />
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>