XSLT行计数器-有那么难吗?

XSLT行计数器-有那么难吗?,xslt,Xslt,每次我需要使用JScript在XSLT中进行行计数时,我都会作弊,但在这种情况下,我无法做到这一点。我只想在整个输出文件中写出一个行计数器。此基本示例有一个简单的解决方案: <xsl:for-each select="Records/Record"> <xsl:value-of select="position()"/> </xsl:for-each> 产出将是: 一, 二, 三, 四, 等等 但是,如果结构与嵌套的foreach更为复杂,该怎么办

每次我需要使用JScript在XSLT中进行行计数时,我都会作弊,但在这种情况下,我无法做到这一点。我只想在整个输出文件中写出一个行计数器。此基本示例有一个简单的解决方案:

<xsl:for-each select="Records/Record">
   <xsl:value-of select="position()"/>
</xsl:for-each>

产出将是:

一,

二,

三,

四,

等等

但是,如果结构与嵌套的foreach更为复杂,该怎么办

<xsl:for-each select="Records/Record">
   <xsl:value-of select="position()"/>
   <xsl:for-each select="Records/Record">
       <xsl:value-of select="position()"/>
   </xsl:for-each>
</xsl:for-each>


在这里,内部foreach只需重置计数器(因此得到1、1、2、3、2、1、2、3、1、2等)。有人知道如何输出文件中的位置(即行数)?

XML文件中的行实际上与元素不同。在第一个示例中,您并没有真正计算行数,而是计算元素数

XML文件可能如下所示:

<cheeseCollection>
<cheese country="Cyprus">Gbejna</cheese><cheese>Liptauer</cheese><cheese>Anari</cheese>
</cheeseCollection>
<cheeseCollection>
    <cheese
       country="Cyprus">Gbejna</cheese>
    <cheese>Liptauer</cheese>
    <cheese>Anari</cheese>
</cheeseCollection>

格贝纳利普塔耶拉纳里
或者,完全相同的XML文件可以如下所示:

<cheeseCollection>
<cheese country="Cyprus">Gbejna</cheese><cheese>Liptauer</cheese><cheese>Anari</cheese>
</cheeseCollection>
<cheeseCollection>
    <cheese
       country="Cyprus">Gbejna</cheese>
    <cheese>Liptauer</cheese>
    <cheese>Anari</cheese>
</cheeseCollection>

格贝尼亚
利普托
阿纳里
XSLT将对其进行完全相同的解释——它不会真正地处理换行符

因此,很难使用XSLT以您想要的方式显示行号,因为它实际上并不适用于这种解析


如果我错了,有人会纠正我,但我想说您需要Javascript或其他脚本语言来完成您想要的任务。

虽然很难为XML文档的序列化标记行号(因为这种序列化本身是不明确的),但这是完全可能的,而且
很容易,对常规文本行进行编号。

此转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="/">
   <xsl:call-template name="numberLines"/>
 </xsl:template>

 <xsl:template name="numberLines">
  <xsl:param name="pLastLineNum" select="0"/>
  <xsl:param name="pText" select="."/>

  <xsl:if test="string-length($pText)">
   <xsl:value-of select="concat($pLastLineNum+1, ' ')"/>

   <xsl:value-of select="substring-before($pText, '&#xA;')"/>
   <xsl:text>&#xA;</xsl:text>

   <xsl:call-template name="numberLines">
    <xsl:with-param name="pLastLineNum"
      select="$pLastLineNum+1"/>
    <xsl:with-param name="pText"
      select="substring-after($pText, '&#xA;')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>
<t>The biggest airlines are imposing "peak travel surcharges"
this summer. In other words, they're going to raise fees
without admitting they're raising fees: Hey, it's not a $30
 price hike. It's a surcharge! This comes on the heels of
 checked-baggage fees, blanket fees, extra fees for window
 and aisle seats, and "snack packs" priced at exorbitant
 markups. Hotels in Las Vegas and elsewhere, meanwhile, are
 imposing "resort fees" for the use of facilities (in other
 words, raising room rates without admitting they're
 raising room rates). The chiseling dishonesty of these
 tactics rankles, and every one feels like another nail in
 the coffin of travel as something liberating and
 pleasurable.
</t>
1 The biggest airlines are imposing "peak travel surcharges"
2 this summer. In other words, they're going to raise fees
3 without admitting they're raising fees: Hey, it's not a $30
4  price hike. It's a surcharge! This comes on the heels of
5  checked-baggage fees, blanket fees, extra fees for window
6  and aisle seats, and "snack packs" priced at exorbitant
7  markups. Hotels in Las Vegas and elsewhere, meanwhile, are
8  imposing "resort fees" for the use of facilities (in other
9  words, raising room rates without admitting they're
10  raising room rates). The chiseling dishonesty of these
11  tactics rankles, and every one feels like another nail in
12  the coffin of travel as something liberating and
13  pleasurable.

感谢各位的回复-是的,你完全正确,一些外部函数是在XSLT中获得这种行为的唯一方法。对于那些搜索,我在.Net 3.5中使用编译转换时就是这样做的:

为函数创建帮助器类

在XSLT中使用它

将其放在样式表声明元素中:

 xmlns:helper="urn:helper"   
然后像这样使用:

<xsl:value-of select="helper:IncrementCount()" />

通常,
position()
是指当前节点相对于当前正在处理的整批节点的数量

在“为每个构件嵌套”的示例中,当您停止为每个构件嵌套并一次选择所有所需的图元时,可以很容易地实现连续编号

使用此XML:

<a><b><c/><c/></b><b><c/></b></a>
但你可以简单地这样做:

<xsl:for-each "a/b/c">
  <xsl:value-of select="position()" />
</xsl:for-each>

你说得对——“位置”(即行号)在XML中完全没有意义,因为空格,包括回车,不被视为文档树的一部分。@GalacticCowboy:空白被视为文档树的一部分--它们包含在文本节点中。@liori:我想他指的是属性之间的空间--这个空间在XDM中不是单独的对象,不能被XPath expressionExcellent问题(+1)访问。有关生成文本行号的解决方案,请参见我的答案。
11221
bccbc  // referred-to nodes
<xsl:for-each "a/b/c">
  <xsl:value-of select="position()" />
</xsl:for-each>
123
ccc    // referred-to nodes