2

さて、ここでの私の質問に続きます。

私のページが次のようになっているとしましょう。

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>

変換後(on C.xml)、私はこれで終わりたいと思います:

<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>

document(@include)別のドキュメントを含めるために使用できることを知っています。ただし、再帰は私を少し超えています。

このような変換をどのように記述しますか?

4

3 に答える 3

2

XSLT 2.0 ソリューションは次のとおりです。

<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>

編集: XSLT 1.0 の場合、同等のソリューションは次のようになります。

<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>
于 2010-05-25T19:43:19.100 に答える
1
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:template match="page">
    <h1>
      <xsl:value-of select="header"/>
    </h1>
    <div>
      <xsl:apply-templates select="." mode="content-a"/>
    </div>
    <div>
      <xsl:apply-templates select="." mode="content-b"/>
    </div>
    <div>
      <xsl:apply-templates select="." mode="content-c"/>
    </div>
  </xsl:template>

  <xsl:template match="page" mode="content-a">
    <p><xsl:value-of select="content-a"/></p>
    <xsl:if test="@include">
      <xsl:apply-templates select="document(@include)" mode="content-a"/>
    </xsl:if>    
  </xsl:template>

  <xsl:template match="page" mode="content-b">
    <p><xsl:value-of select="content-b"/></p>
    <xsl:if test="@include">
      <xsl:apply-templates select="document(@include)" mode="content-b"/>
    </xsl:if>
  </xsl:template>

  <xsl:template match="page" mode="content-c">
    <p><xsl:value-of select="content-c"/></p>
    <xsl:if test="@include">
      <xsl:apply-templates select="document(@include)" mode="content-c"/>
    </xsl:if>
  </xsl:template>

  <xsl:template match="page" mode="header">
    <xsl:value-of select="header"/>
    <xsl:if test="@include">
      <xsl:apply-templates select="document(@include)" mode="header"/>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>
于 2010-05-25T19:50:50.247 に答える
-1

これが私が思いついた解決策です。これは、コンテンツごとに 1 回ではなく、各サブページを 1 回だけロードします。

<xsl:template match="content-a | content-b | content-c">
    <p><xsl:value-of select="."></p>
</xsl:template>

<xsl:template name="get-content">
    <xsl:param name='page' />
    <xsl:param name='content-a' />
    <xsl:param name='content-b' />
    <xsl:param name='content-c' />
    <xsl:choose>
        <xsl:when test="$page/@include">
            <xsl:for-each select="document($page/@include)/page"> <!--set context-->
                <xsl:call-template name="get-members">
                    <xsl:with-param name="content-a" select="$content-a | content-a" />
                    <xsl:with-param name="content-b" select="$content-b | content-b" />
                    <xsl:with-param name="content-c" select="$content-c | content-c" />
                </xsl:call-template>
            </xsl:xsl:for-each>
        </xsl:when>
        <xsl:otherwise>
            <div>
                <xsl:apply-templates select="$content-a" />
            </div>
            <div>
                <xsl:apply-templates select="$content-b" />
            </div>
            <div>
                <xsl:apply-templates select="$content-c" />
            </div>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="page">
    <h1><xsl:value-of select="header"></h1>
    <xsl:call-template name="get-members">
        <xsl:with-param name="content-a" select="content-a" />
        <xsl:with-param name="content-b" select="content-b" />
        <xsl:with-param name="content-c" select="content-c" />
    </xsl:call-template>
</xsl:template>

これは、他のソリューションよりも良いと思いますか、それとも悪いと思いますか?

于 2010-05-25T20:43:55.550 に答える