我正在尝试创建一个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解决这个问题。任何帮助表示赞赏。
答案 0 :(得分:3)
就像Merlyn Morgan-Graham所说,关键是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>
此外,真正使这成为可能的是身份转换。它传递与另一个模板不匹配的任何内容。
答案 1 :(得分:0)
这可能有点棘手,但请查看document()
函数。
我见过的示例显示了如何在输出中包含另一个文档,但是我没有看到任何可以让您在同一个调用期间开始转换该文档的示例。但我自己也没试过。
如果document()
允许您将变换递归到其他文档中,则无法解决问题,您可以在循环中调用变换,并将变换编写为重复调用。那么你需要一些方法来检查何时可以停止转换。
了解何时停止的一种方法是在源文档和目标文档之间进行差异化。
另一种方法是,如果找到任何子文档,则在文档顶部放置一个元素,并在找不到任何子文档时将其删除。然后检查是否存在此元素。
但也许有一种方法可以继续转换所包含的子文档。
答案 2 :(得分:0)
此转化:
<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()
。