这是我的模板:
<xsl:template name="rec">
<xsl:for-each select="*">
<div class="{local-name()}">
<xsl:for-each select="@*">
<xsl:attribute name="data-{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:value-of select="text()" />
<xsl:call-template name="rec" />
</div>
</xsl:for-each>
</xsl:template>
给出如此的文件:
<test>
<item value="1">Item 1 Text</item>
<item value="2">Item 2 Text</item>
</test>
上述转换会将其转换为:
<div class="test">
<div class="item" data-value="1">Item 1 Text</div>
<div class="item" data-value="2">Item 2 Text</div>
</div>
我遇到的问题是,这个转换不能正确地理解文本节点,而且我没有足够的背景来使用XSLT来弄清楚如何修复它。这是问题所在:给出像这样的xml:
<para>This is a <emphasis>paragraph</emphasis> people!</para>
我希望看到以下输出:
<div class="para">This is a <div class="emphasis">paragraph</div> people!</div>
问题是我没有得到这个 - 我得到了这个:
<div class="para">This is a <div class="emphasis">paragraph</div></div>
注意失踪的'人!'文本节点。如何修复上面的XSLT以向我提供我需要的输出?
答案 0 :(得分:4)
一个问题是
<xsl:value-of select="text()" />
只选择第一个子文本节点的值,然后输出它。
最简单的方法是使用<xsl:apply-templates>
代替<xsl:call-template>
。
然后代替
<xsl:for-each select="*">
和
<xsl:value-of select="text()" />
你可以使用
<xsl:apply-templates />
将按顺序将适当的模板应用于每个子元素和文本节点,而不是跳过任何。
这是一个完整的实现:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="*">
<div class="{local-name()}">
<xsl:for-each select="@*">
<xsl:attribute name="data-{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates />
</div>
</xsl:template>
</xsl:stylesheet>
注意<xsl:apply-templates/>
,默认情况下,在没有明确的select
属性的情况下,对上下文节点的所有子节点(包括文本节点)进行操作。
默认模板用于文本节点。该模板只是将它们复制到输出中。
示例输入:
<test>
<item value="1">Item 1 Text</item>
<item value="2">Item 2 Text</item>
<para>This is a <emphasis>paragraph</emphasis> people!</para>
</test>
产生所需的输出:
<div class="test">
<div class="item" data-value="1">Item 1 Text</div>
<div class="item" data-value="2">Item 2 Text</div>
<div class="para">This is a <div class="emphasis">paragraph</div> people!</div>
</div>