PHP中的条件XSLT转换

时间:2009-08-25 18:23:03

标签: xml xslt wml

我有一段XML数据需要转换为WML

这是这样的:

 <root>
  <category name="music"/>
  <subcategory name="classic"/>
  <subcategory name="rock"/>
  <subcategory name="Techno"/>
  <node type="music" subtype="classic" name="beethoven"/>
  <node type="music" subtype="classic" name="chopin"/>
  <record author="beethoven" name="moonlight sonata"/>
  …
 </root>

我无法更改文件结构。

某些Nokia移动浏览器无法将大量<card>加载到内存中。

因此,根据移动浏览器的不同,WML页面应该是一整套<card><card>的某个子集。

例如,如果我使用普通浏览器下载页面,它应该如下所示:

<wml>
 <card id="TOC">
  <p><a href="#contents">Contents</a></p>
  <p><a href="#az">A-Z</a></p>
 </card>
 <card id="contents">
  <p><a href="#music">music</a></p>
  <p><a href="#video">video</a></p>
  <p><a href="#java">java</a></p>
 </card>
 <card id="az">
  <p><a href="#beethoven">beethoven</a></p>
  <p><a href="#chopin">chopin</a></p>
 </card>
 <card id="music">
  <p><a href="#classic">classic</a></p>
  <p><a href="#rock">rock</a></p>
  <p><a href="#Techno">Techno</a></p>
 </card>
 <card id="classic">
  <p><a href="#beethoven">beethoven</a></p>
  <p><a href="#chopin">chopin</a></p>
 </card>
 …
</wml>

,这样用户就可以浏览而无需额外往返服务器。

但是,当我使用Nokia并访问起始页时,页面应如下所示:

http://example.com/

<wml>
 <card id="TOC">
  <p><a href="#contents">Contents</a></p>
  <p><a href="#az">A-Z</a></p>
 </card>
 <card id="contents">
  <p><a href="#music">music</a></p>
  <p><a href="#video">video</a></p>
  <p><a href="#java">java</a></p>
 </card>
 <card id="az">
  <p><a href="/beethoven">beethoven</a></p>
  <p><a href="/chopin">chopin</a></p>
 </card>
 <card id="music">
  <p><a href="/classic">classic</a></p>
  <p><a href="/rock">rock</a></p>
  <p><a href="/Techno">Techno</a></p>
 </card>
 <card id="video">
  <p><a href="/movies">Movies</a></p>
 </card>
 <card id="java">
  <p><a href="/games">Games</a></p>
 </card>
</wml>

,当我访问href时,它应该显示内部内容:

http://example.com/classic

<wml>
 <card id="TOC">
  <p><a href="#contents">Contents</a></p>
  <p><a href="#az">A-Z</a></p>
 </card>
 <card id="contents">
  <p><a href="/music">music</a></p>
  <p><a href="/video">video</a></p>
  <p><a href="/java">java</a></p>
 </card>
 <card id="az">
  <p><a href="#beethoven">beethoven</a></p>
  <p><a href="#chopin">chopin</a></p>
 </card>
 <card id="classic">
  <p><a href="#beethoven">beethoven</a></p>
  <p><a href="#chopin">chopin</a></p>
 </card>
 …
</wml>

基本上,XSLT应该做以下事情:

  • 接受某种要显示的参数:类别,子类别等。

  • 计算将要显示的<card>

    1. 如果我们只加载类型和TOC,我们会获得2张卡片(我们会一直显示)
      • 如果我们只加载类型和子类型,我们会获得10张卡片。
      • 如果我们加载类型,子类型和标题,我们会显示100卡片。
      • 如果我们加载所有内容,我们会显示300卡片。
    2. Nokia无法处理超过120张卡片,因此我们只停留在3级别。

      如果XML更改且级别3需要130张卡,我们应该停在2级。

    3. 如果<card>低于特定级别

    4. ,请勿显示
    5. 如果不显示该卡,请将#(内部链接)替换为/(外部链接)。

是否可以在单个XSL文件中执行?

3 个答案:

答案 0 :(得分:1)

我不确定问题到底是什么。如上所述,答案是“是的,有可能” - xsl:ifxsl:choose应足以处理您的所有条件。您必须通过参数向样式表传达限制(例如结果将转到诺基亚的事实) - 请参阅xsl:param

答案 1 :(得分:0)

我建议创建变量,累积计算每个“级别”(类型,子类型,标题......)的所有节点,并为XSL提供一个参数,指示要生成的最大卡数。 XSL可能看起来像这样:

<xsl:stylesheet …>
  <xsl:param name="max-cards" select="999999"/>

  <xsl:template match="/root">
    <!-- "2" here for the type/TOC cards -->
    <xsl:variable name="nSubs" select="2 + count(subcategory)"/>
    <xsl:variable name="nNodes" select="$nSubs + count(node)"/>
    <xsl:variable name="nRecs" select="$nNodes + count(record)"/>

    <!-- generate types & TOC here -->

    <xsl:if test="$nSubs < $max-cards">
        <!-- generate subtypes here -->
    </xsl:if>

    <xsl:if test="$nNodes < $max-cards">
        <!-- generate titles here -->
    </xsl:if>

    <xsl:if test="$nRecs < $max-cards">
        <!-- generate everything else here -->
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

样式表参数可以类似地用于限制上层的生成,但是对于SO而言,这样的示例将过长。 ^。^

答案 2 :(得分:0)

我的理解是XSL是完整的,所以几乎任何'答案都可能吗?'问题是肯定的。答案是'你会喜欢它吗?',也许不是那么多: - )

一种简单的方法,可以使用&lt; xsl:param&gt;传入控制参数,&lt; xsl:choose&gt;选择要显示的格式,然后分支/委托给每种格式的特定模板或函数。

如果您的格式有共同点,您可以通过将这些部分委托给自己的模板或函数来干掉它们,并在主要格式的更高级别模板中重复使用它们。基本上分而治之。

编辑:更具体地说明委托的意思,我的意思是明确地调用模板并对它们进行参数化,例如:

   <xsl:call-template name="showcard">
     <xsl:with-param name="kind" select="nokia"/>
   </xsl:call-template>

将这些模板依次委托给其他人等。您还可以从value-of和apply-templates中获得很多,将流程指向特定模板。虽然您的情况可能更简单,但这可能会导致更易读的代码。