我正在尝试创建一个XSL样式表,该样式表允许一个合并从另一个XHTML文件引用的XHTML文件。反过来,从引用文件引用的任何XHTML文件也应该合并,依此类推。因此,应该有可能将一个开始的XHTML文件直接或间接引用的所有XHTML递归合并到一个XHTML文件中。这些引用是严格的层次结构。
示例:
文件a.html:
<html>
<body>Text1<br/><a href="b.html">Link</a></body>
</html>
文件b.html:
<html>
<body>Text2<br/><a href="c.html">Link</a></body>
</html>
文件c.html:
<html>
<body>Text3<br/></body>
</html>
以a.html开头时生成的合并文件:
<html>
<body>Text1<br/>Text2<br/>Text3<br/></body>
</html>
我不知道如何使用XSLT解决该问题。任何帮助表示赞赏。
使用document()
功能,如本样式表所示:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<!--IDENTITY TRANSFORM-->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<xsl:apply-templates select="document(@href)/html/body/node()"/>
</xsl:template>
</xsl:stylesheet>
使用您的3个html文件,并使用a.html
作为输入,将导致以下输出:
<html>
<body>Text1<br/>Text2<br/>Text3<br/>
</body>
</html>
而且,真正使之成为可能的是身份转换。它传递未与其他模板匹配的任何内容。
可能会有些棘手,但是请检查document()
功能。
我看到的示例显示了如何在输出中包含另一个文档,但是我没有看到任何示例可以让您在同一调用期间开始转换该文档。但是我自己也没有尝试。
如果无法确定document()
让您将转换递归到其他文档中,则可以循环调用转换,并编写要重复调用的转换。然后,您将需要一些方法来检查何时可以停止转换。
知道何时应停止的一种方法是在源文档和目标文档之间进行区分。
另一种方法是,如果找到任何子文档,则在文档顶部放置一个元素,如果找不到任何子文档,则将其删除。然后只需检查此元素是否存在。
但是也许有一种方法可以继续通过包含的子文档进行转换。
此转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<xsl:apply-templates select=
"document(@href)/*/body/node()"/>
</xsl:template>
</xsl:stylesheet>
应用于文件“ a.html”时:
<html>
<body>Text1<br/><a href="b.html">Link</a></body>
</html>
产生想要的正确结果:
<html><body>Text1<br/>Text2<br/>Text3<br/></body></html>
说明:
身份规则按原样复制每个节点。
唯一的覆盖模板与任何a
元素匹配。
在此模板中,将启动href
元素的a
属性中指向的文档的处理。必须使用标准的XSLT函数document()
。