递归 XSLT,第 2 部分
[英] Recursive XSLT, part 2
本文介绍了递归 XSLT,第 2 部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
好的,接着我的问题 这里.
假设我的网页现在是这样的:
A.xml:
<header>页面A</header><content-a>页面A的随机内容</content-a><content-b>页面A的更多内容</content-b><content-c>页面A的更多内容</content-c><!-- 这不会继续:有预定义数量的部分--></页面>
B.xml:
<header>页面B</header><content-a>页面B的随机内容</content-a><content-b>页面B的更多内容</content-b><content-c>页面B的更多内容</content-c></页面>
C.xml:
<header>页面 C</header><content-a>页面C的随机内容</content-a><content-b>页面C的更多内容</content-b><content-c>页面C的更多内容</content-c></页面>
转换后(在 C.xml
上),我想以这样的方式结束:
页面C
<div><p>页面C的随机内容</p><p>页面B的随机内容</p><p>页面A的随机内容</p>
<div><p>页面 C 的更多内容</p><p>页面 B 的更多内容</p><p>A页面的更多内容</p>
<div><p>还有更多页面 C 的内容</p><p>页面 B 的更多内容</p><p>页面 A 的更多内容</p>
我知道我可以使用 document(@include)
来包含另一个文档.但是,递归有点超出我的范围.
我将如何编写这样的转换?
解决方案
这是一个 XSLT 2.0 解决方案:
</xsl:变量><xsl:copy><h1><xsl:value-of select="header"/></h1><!-- 你说有固定数量的名字,所以这应该没问题--><xsl:for-each select="'content-a','content-b','content-c'"><div><xsl:apply-templates select="$pages/page/*[name() = current()]"/>
</xsl:for-each></xsl:copy></xsl:模板><xsl:template match="page" mode="load"><xsl:sequence select="."/><xsl:apply-templates select="document(@include)" mode="load"/></xsl:模板><xsl:template match="content-a|content-b|content-c"><p><xsl:value-of select="."/></p></xsl:模板></xsl:stylesheet>
<小时>
对于 XSLT 1.0,等效的解决方案如下所示:
</xsl:变量><xsl:variable name="pages" select="exsl:node-set($pages-rtf)"/><!-- 你说有固定数量的名字,所以这应该没问题--><xsl:variable name="nodes-rtf"><content-a/><content-b/><content-c/></xsl:变量><xsl:variable name="nodes" select="exsl:node-set($nodes-rtf)"/><xsl:copy><h1><xsl:value-of select="header"/></h1><xsl:for-each select="$nodes"><div><xsl:apply-templates select="$pages/page/*[name() = name(current())]"/>
</xsl:for-each></xsl:copy></xsl:模板><xsl:template match="page" mode="load"><xsl:copy-of select="."/><xsl:apply-templates select="document(@include)" mode="load"/></xsl:模板><xsl:template match="content-a|content-b|content-c"><p><xsl:value-of select="."/></p></xsl:模板></xsl:stylesheet>
Ok, following on from my question here.
Lets say my pages are now like this:
A.xml:
<page>
<header>Page A</header>
<content-a>Random content for page A</content-a>
<content-b>More of page A's content</content-b>
<content-c>More of page A's content</content-c>
<!-- This doesn't keep going: there are a predefined number of sections -->
</page>
B.xml:
<page include="A.xml">
<header>Page B</header>
<content-a>Random content for page B</content-a>
<content-b>More of page B's content</content-b>
<content-c>More of page B's content</content-c>
</page>
C.xml:
<page include="B.xml">
<header>Page C</header>
<content-a>Random content for page C</content-a>
<content-b>More of page C's content</content-b>
<content-c>More of page C's content</content-c>
</page>
After the transform (on C.xml
), I'd like to end up with this:
<h1>Page C</h1>
<div>
<p>Random content for page C</p>
<p>Random content for page B</p>
<p>Random content for page A</p>
</div>
<div>
<p>More of page C's content</p>
<p>More of page B's content</p>
<p>More of page A's content</p>
</div>
<div>
<p>Yet more of page C's content</p>
<p>Yet more of page B's content</p>
<p>Yet more of page A's content</p>
</div>
I know that I can use document(@include)
to include another document. However, the recursion is a bit beyond me.
How would I go about writing such a transform?
解决方案
Here is an XSLT 2.0 solution:
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="page">
<xsl:variable name="pages">
<xsl:apply-templates select="." mode="load" />
</xsl:variable>
<xsl:copy>
<h1><xsl:value-of select="header" /></h1>
<!-- you say there is a fixed number of names, so this should be OK -->
<xsl:for-each select="'content-a','content-b','content-c'">
<div>
<xsl:apply-templates select="$pages/page/*[name() = current()]" />
</div>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="page" mode="load">
<xsl:sequence select="." />
<xsl:apply-templates select="document(@include)" mode="load" />
</xsl:template>
<xsl:template match="content-a|content-b|content-c">
<p><xsl:value-of select="." /></p>
</xsl:template>
</xsl:stylesheet>
EDIT: For XSLT 1.0, the equivalent solution would look like this:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
>
<xsl:template match="page">
<xsl:variable name="pages-rtf"><!-- rtf = result tree fragment -->
<xsl:apply-templates select="." mode="load" />
</xsl:variable>
<xsl:variable name="pages" select="exsl:node-set($pages-rtf)" />
<!-- you say there is a fixed number of names, so this should be OK -->
<xsl:variable name="nodes-rtf">
<content-a/><content-b/><content-c/>
</xsl:variable>
<xsl:variable name="nodes" select="exsl:node-set($nodes-rtf)" />
<xsl:copy>
<h1><xsl:value-of select="header" /></h1>
<xsl:for-each select="$nodes">
<div>
<xsl:apply-templates select="$pages/page/*[name() = name(current())]" />
</div>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="page" mode="load">
<xsl:copy-of select="." />
<xsl:apply-templates select="document(@include)" mode="load" />
</xsl:template>
<xsl:template match="content-a|content-b|content-c">
<p><xsl:value-of select="." /></p>
</xsl:template>
</xsl:stylesheet>
这篇关于递归 XSLT,第 2 部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!