假设我有以下XML输入:
<para>
text before
<sometag>Content</sometag>
text after
</para>
我希望将此内容转换为HTML。我有以下两个XSLT规则:
<xsl:template match="para">
<p>
<xsl:apply-templates />
</p>
</xsl:template>
<xsl:template match="sometag">
<div>
<xsl:apply-templates />
</div>
</xsl:template>
输入XML已修复。我目前的知识确实没有解决方法,“sometag”需要转换为div HTML元素。显然,这不是他常见或推荐使用,但它是DTD允许的。这将导致以下输出:
<p>
text before
<div>
Content
</div>
text after
</p>
这当然是无效的HTML,因为“p”不能包含“div”。
如果我在浏览器中打开包含此类无效XML的文件,它会自动将此格式错误的HTML自动修复为:
<p>
text before
</p>
<div>
Content
</div>
<p>
text after
</p>
当然,这里发生的是“p”元素在“div”元素开始之前被关闭了。
请注意输出应为HTML5。
我的问题是,是否可以在XSLT2.0中执行此操作?如果没有,是否有任何Java库可以做到这一点?如果是这样,请添加一个示例,我已经看到了类似的问题,但答案只是一个图书馆的链接,似乎没有人这样做。
答案 0 :(得分:1)
编写一个匹配text()
个元素节点的模板。这样,您可以利用这样的事实:当一个子元素属于一个元素的文本内容时,这会导致该元素的几个文本节点。
因此,您实际显示的para
元素的内容是:
[text node, "text before"] [sometag node] [text node, "text after"]
<强>样式表强>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="para|sometag">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="text()">
<xsl:choose>
<xsl:when test="parent::sometag">
<div>
<xsl:value-of select="."/>
</div>
</xsl:when>
<xsl:when test="parent::para">
<p>
<xsl:value-of select="."/>
</p>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<强>输出强>
<?xml version="1.0" encoding="UTF-8"?>
<p>
text before
</p>
<div>Content</div>
<p>
text after
</p>
答案 1 :(得分:1)
使用XSLT 2.0,我认为您希望将匹配para
的模板替换为
<xsl:template match="para">
<xsl:for-each-group select="node()" group-ending-with="sometag">
<p>
<xsl:apply-templates select="current-group()[not(self::sometag)]"/>
</p>
<xsl:apply-templates select="current-group()[last() and self::sometag]"/>
</xsl:for-each-group>
</xsl:template>
答案 2 :(得分:1)
这是另一个版本
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="para">
<xsl:for-each-group select="node()" group-adjacent="if (self::text()) then 1 else 0">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<p>
<xsl:apply-templates select="current-group()"/>
</p>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="sometag">
<div>
<xsl:apply-templates />
</div>
</xsl:template>
</xsl:stylesheet>
应用于您输入时:
<para>
text before
<sometag>Content</sometag>
text after
</para>
产生
<p>
text before
</p><div>Content</div><p>
text after
</p>