XSLT position() - 排除测试条件失败的元素

时间:2013-11-01 10:32:13

标签: xslt

假设我有以下xml文件:

<jobs>
  <job>
    <PositionTitle>Painter</PositionTitle>
    <InternalOrExternal>External</InternalOrExternal>
  </job>
  <job>
    <PositionTitle>Plumber</PositionTitle>
    <InternalOrExternal>Internal</InternalOrExternal>
  </job>
  <job>
    <PositionTitle>Chemist</PositionTitle>
    <InternalOrExternal>Internal</InternalOrExternal>
  </job>
  <job>
    <PositionTitle>Teacher</PositionTitle>
    <InternalOrExternal>External</InternalOrExternal>
  </job>
</jobs> 

我使用以下xslt处理它以仅显示外部作业:

<?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:content="http://purl.org/rss/1.0/modules/content/" >
  <xsl:output method="html"/>
  <xsl:template match="/">

        <xsl:for-each select="jobs/job">

            <xsl:if test="InternalOrExternal = 'External'"><!-- Only show external jobs -->
              <xsl:value-of select="PositionTitle"/> - <xsl:value-of select="position()"/><br />
            </xsl:if>

        </xsl:for-each>

 </xsl:template>
 </xsl:stylesheet>

结果为:

Painter - 1
Teacher - 4

我假设position()函数返回xml文件中的实际位置,并没有考虑任何可能排除某些作业的if语句。在这种情况下,内部工作被排除在外,但他们的职位仍在计算中。

我想要的结果是:

Painter - 1
Teacher - 2

他们有什么方法可以让position()函数只计算我显示的内容吗?

我试过这个没有运气:

<xsl:value-of select="position(jobs/job[InternalOrExternal='External'])"/>

2 个答案:

答案 0 :(得分:4)

position()为您提供"current node list"中当前节点的位置,即最近for-eachapply-templates选择的任何节点列表。您可以非正式地将其视为for-each 1 的当前迭代次数。通过说

<xsl:for-each select="jobs/job">

当前节点列表是 all 作业元素,因此第一个位置为1,第四个位置为4。如果您删除了xsl:if,而是将过滤转移到for-each选择器上的谓词中:

<xsl:for-each select="jobs/job[InternalOrExternal='External']">
  <xsl:value-of select="PositionTitle"/> - <xsl:value-of select="position()"/><br />
</xsl:for-each>

然后当前节点列表仅包含“外部”job元素,您将获得所需的position()值。


1 由于XSLT指令没有副作用(例如,没有可更新的变量),因此XSLT处理器不一定必须使用顺序循环在内部实现for-each。它可以选择并行或乱序处理不同的节点,只要它以一种与顺序循环产生的相同的方式组装输出即可。

答案 1 :(得分:0)

除了Ian Roberts的好答案:如果您必须将上下文设为job(无论出于何种原因),您还可以使用xsl:number代替position()

示例:

<xsl:value-of select="PositionTitle"/> - <xsl:number count="job[InternalOrExternal='External']"/><br />