模板被调用在它不应该的地方

use*_*959 0 xslt

我有以下两个XML案例.

情况1:

<para>Rent is the sum of money paid by the Tenant to the Landlord for the exclusive use of premises. The Landlord and Tenant signs a <page num="4"/>tenancy agreement which has to be stamped with the tax authorities as required under the Stamp Duties Act. The stamping of a tenancy agreement gives it validity but if the tenancy agreement is not stamped that does not mean</para>
Run Code Online (Sandbox Code Playgroud)

案例2:

<para><page num="5"/>The Writ of Distress proceedings is an effective way to recover arrears in rent but regard must be had to the Landlord/Tenant relationship and the effect of publicity of such proceedings to the image of the building amongst other things.</para>
Run Code Online (Sandbox Code Playgroud)

和下面的XSLT

    <xsl:template match="para">
<xsl:apply-templates select="child::node()[(self::page)]"/>
  <li class="item">
  <div class="para">
<span class="item-num">
<xsl:value-of select="../@num"></xsl:value-of>
</span>  
<xsl:apply-templates select="child::node()[not(self::page)]"/>
  </div>
  </li>
</xsl:template>
    <xsl:template match="page">
    <xsl:processing-instruction name="pb">
        <xsl:text>label='</xsl:text>
        <xsl:value-of select="./@num"/>
        <xsl:text>'</xsl:text>
        <xsl:text>?</xsl:text>
    </xsl:processing-instruction>

    <a name="{concat('pg_',./@num)}"/>
    <xsl:apply-templates/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

我要做的是检查是否page是直接(第一个)孩子para并首先打印该值,然后完成剩下的工作.但在这两种情况下,page首先打印.

在以上提供的情况下,对于情形1,在page应该叫就像任何其他的模板para,因为它不是眼前的孩子para,但在案例2中,首先page要打印已经和旁边的模板被调用,因为page num="5"是眼前的孩子para,请让我知道我能做到这一点.

一个演示是在这里

Tim*_*m C 5

我认为你的意思是当页面para下的第一个子节点时你想要执行额外的处理.您的apply-templates需要如下所示

<xsl:apply-templates select="node()[1][self::page]" />
Run Code Online (Sandbox Code Playgroud)

但是,听起来您还想对页面元素执行其他处理.您可能需要两个匹配页面的模板,但其中一个模板具有"模式"以区别于您的正常处理.

像这样称呼它

<xsl:apply-templates select="node()[1][self::page]" mode="first"/>
Run Code Online (Sandbox Code Playgroud)

并且像这样匹配它

<xsl:template match="page" mode="first">
Run Code Online (Sandbox Code Playgroud)

这将包含输出处理指令的代码.

对于页面元素的"正常"处理,只需要另一个模板匹配页面而不使用模式

<xsl:template match="page">
    <a name="{concat('pg_',./@num)}"/>
    <xsl:apply-templates/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="para">
    <xsl:apply-templates select="node()[1][self::page]" mode="first"/>
      <li class="item">
      <div class="para">
    <span class="item-num">
    <xsl:value-of select="../@num"></xsl:value-of>
    </span>  
    <xsl:apply-templates />
      </div>
      </li>
    </xsl:template>

    <xsl:template match="page">
        <a name="{concat('pg_',./@num)}"/>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="page" mode="first">
        <xsl:processing-instruction name="pb">
            <xsl:text>label='</xsl:text>
            <xsl:value-of select="./@num"/>
            <xsl:text>'</xsl:text>
        </xsl:processing-instruction>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

编辑:如果您不希望同时应用"页面"模板以应用于第一个页面元素,则添加以下模板以忽略它

<xsl:template match="page[not(preceding-sibling::node())]" />
Run Code Online (Sandbox Code Playgroud)

请注意,只有当您<xsl:strip-space elements="*" />在文档中出现时才会删除仅限空格的文本节点.或者,你可以写这个

<xsl:template match="page[not(preceding-sibling::node()[not(self::text()) or normalize-space()])]" />
Run Code Online (Sandbox Code Playgroud)

编辑2:您需要额外模板的原因是因为这一行

<xsl:apply-templates />
Run Code Online (Sandbox Code Playgroud)

这将查找与当前para元素下的所有子元素匹配的模板.因此,对于页面元素,将匹配以下模板

<xsl:template match="page">
Run Code Online (Sandbox Code Playgroud)

但是你说你不希望在这种情况下匹配第一个页面元素.因此,您是一个更"特定"的模板来匹配它.例如

<xsl:template match="page[not(preceding-sibling::node())]" />
Run Code Online (Sandbox Code Playgroud)

此模板匹配页面元素,没有前面的兄弟; 即下的第一个元素.

XSLT具有模板优先级的概念.如果模板匹配具有指定条件的元素,则该模板将始终优先.在这种情况下,特定模板只是忽略页面元素,以确保它不会得到输出.

对于其他页面元素,其他模板将正常使用.