我需要将XML转换为XHTML。在XML中有多个段落和嵌入式引用,例如
<para>SomeText</para>
<para><quote>SomeText</quote></para>
<para>SomeText</para>
我试过了:
<xsl:choose>
<xsl:when test="//text/para">
<xsl:for-each select="//text">
<xsl:for-each select="//para">
<p><xsl:value-of select="text()"/></p>
</xsl:for-each>
</xsl:for-each>
</xsl:when>
<xsl:when test="//text/para[quote]">
<xsl:for-each select="//text">
<xsl:for-each select="//para/quote">
<p><q><xsl:value-of select="text()"/></q></p>
</xsl:for-each>
</xsl:for-each>
</xsl:when>
</xsl:choose>
然而,第二个条件却被忽略了。
答案 0 :(得分:2)
如@LarsH所示,请避免<xsl:for-each>
。使用模板匹配。
这个简单的转变:
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="para">
<p><xsl:apply-templates /></p>
</xsl:template>
<xsl:template match="quote">
<q><xsl:apply-templates /></q>
</xsl:template>
</xsl:transform>
会转过来:
<text>
<para>SomeText</para>
<para><quote>SomeText</quote></para>
<para>SomeText</para>
</text>
到
<p>SomeText</p>
<p><q>SomeText</q></p>
<p>SomeText</p>
进一步阅读SO:
答案 1 :(得分:1)
问题是你正在使用忽略上下文的XPath表达式(除了上下文文档),即以//
开头的表达式。因此,如果文档中任何位置具有<para>
子元素的<quote>
元素,则第一个条件将始终为true,并且永远不会达到第二个条件。
你真的想在select / when条件之外移动for-each循环(或者可能更好,一组带有匹配模式和apply-templates的模板)。事实上,一旦你拥有了正确的模板,你可能根本不需要选择/什么时候。
(从评论中移动一些信息)
XSLT和XPath非常复杂,在尝试通过反复试验获得某些功能之前,确实值得学习基础知识。你会节省很多时间。对于一般性介绍,我建议
然后,有关xsl:for-each
与xsl:apply-templates
的更高级讨论,请参阅