确定具有多个谓词的模板中position()的上下文

Chr*_*ina 5 xslt predicate xslt-2.0

我在确定节点集的正确上下文时遇到了一些麻烦.我有一个看起来有点像这样的模板匹配(使用XSL 2.0):

<xsl:template match="//chapter/body/*[matches(name(), '^toc')][crossref][not(crossref/@idref='cip' or crossref/@idref='copy')]">
  <xsl:variable name="curr_id" select="crossref/@idref"/>
  <xsl:element name="location">
    <xsl:attribute name="id"><xsl:value-of select="$curr_id"/></xsl:attribute>
    <xsl:attribute name="order"><xsl:value-of select="position()"/></xsl:attribute>
    <xsl:element name="label">
        <text><xsl:value-of select="."/></text>
    </xsl:element>
  </xsl:element>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

XML看起来有点像这样:

<chapter id="toc">
  <body>
    <title>Contents</title>
    <tocfm><crossref idref="cip">Catalog</crossref></tocfm>
    <tocfm><crossref idref="copy">Copyright</crossref></tocfm>
    <tocfm><crossref idref="ded">Dedication</crossref></tocfm>
    <toc><crossref idref="prologue">Prologue</crossref></toc>
    <toc><crossref idref="pt1">Book One</crossref></toc>
    <toc><crossref idref="pt2">Book Two</crossref></toc>
    <toc><crossref idref="pt3">Book Three</crossref></toc>
  </body>
</chapter>
Run Code Online (Sandbox Code Playgroud)

我的期望是谓词将生成一个包含以下内容的节点集:

<tocfm><crossref idref="ded">Dedication</crossref></tocfm>
<toc><crossref idref="prologue">Prologue</crossref></toc>
<toc><crossref idref="pt1">Book One</crossref></toc>
<toc><crossref idref="pt2">Book Two</crossref></toc>
<toc><crossref idref="pt3">Book Three</crossref></toc>
Run Code Online (Sandbox Code Playgroud)

换句话说,所有包含crossref的toc类元素,其idref不是cip或copy.模板在输出方面执行此操作,但位置函数似乎不在该节点集上.相反,它为奉献产生了一个'3'的位置.但是,如果我输出通过跟随[1]的谓词找到的节点的值,我会得到Dedication作为该值.所以,我对于正在发挥作用的立场感到难过.任何人都可以开导我吗?

Sea*_*kin 9

您的期望是错误的,因为它基于对如何定义上下文序列的常见误解.上下文序列不是由模板匹配模式决定的,而是由模板之外的东西决定的.

在某些时候,使用select表达式调用xsl:apply-templates.评估此表达式以生成项序列.将当前上下文序列推送到堆栈上.该项目序列成为上下文序列.上下文序列按顺序迭代.在访问每个项目时,此项目成为上下文项目,position()函数反映上下文序列中上下文项目的位置.此时,根据匹配表达式和优先级找到适当的模板.匹配表达式不返回序列.它们只是对上下文项的布尔测试 - 上下文项与模板规则匹配,或者不是.如果匹配且具有最高优先级,则输入模板序列构造函数.此时,上下文序列,上下文项和位置()都由客户端xsl:apply-templates定义,而不是由匹配条件定义.退出序列构造函数后,控件返回客户端xsl:apply-templates.它将增加position()数,更新上下文项,并再次找到适当的模板.这可以是与前一项相同的模板或不同的模板.

插图

此样式表说明了它是确定上下文序列和位置()的客户端指令(apply-templates,for-each等),而不是模板匹配模式.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
 <t>
   <note message ="apply-templates on EVEN items">
    <xsl:apply-templates select="*/item[ (@id mod 2) = 0]"/>
   </note>  
   <note message ="apply-templates on ODD items">
    <xsl:apply-templates select="*/item[ (@id mod 2) = 1]">
     <xsl:sort select="position()" data-type="number" order="descending"/>
    </xsl:apply-templates>
   </note>  
 </t>
</xsl:template>

<xsl:template match="item[@colour='blue']">
 <note message='Brought to you by the Blue template!' positon="{position()}"> 
  <xsl:copy-of select='self::*'/>
  </note>  
</xsl:template>

<xsl:template match="item[@colour='red']">
 <note message='Brought to you by the Red template!' positon="{position()}"> 
  <xsl:copy-of select='self::*'/>
  </note>  
</xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

...适用于此文件......

<t>
 <item id="1" colour="blue" /> 
 <item id="2" colour="blue" /> 
 <item id="3" colour="blue" /> 
 <item id="4" colour="red" /> 
 <item id="5" colour="red" /> 
 <item id="6" colour="red" /> 
</t>
Run Code Online (Sandbox Code Playgroud)

......产生这个输出......

<t>
  <note message="apply-templates on EVEN items">
    <note message="Brought to you by the Blue template!" positon="1">
      <item id="2" colour="blue" />
    </note>
    <note message="Brought to you by the Red template!" positon="2">
      <item id="4" colour="red" />
    </note>
    <note message="Brought to you by the Red template!" positon="3">
      <item id="6" colour="red" />
    </note>
  </note>
  <note message="apply-templates on ODD items">
    <note message="Brought to you by the Red template!" positon="1">
      <item id="5" colour="red" />
    </note>
    <note message="Brought to you by the Blue template!" positon="2">
      <item id="3" colour="blue" />
    </note>
    <note message="Brought to you by the Blue template!" positon="3">
      <item id="1" colour="blue" />
    </note>
  </note>
</t>
Run Code Online (Sandbox Code Playgroud)