递归 XSLT,第 2 部分 [英] Recursive XSLT, part 2

查看:69
本文介绍了递归 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屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆