Счетчик строки XSLT - является этим это трудно?

Я обманул каждый раз, когда я должен был провести подсчет строки в XSLT при помощи JScript, но в этом случае я не могу сделать этого. Я просто хочу выписать счетчик строки всюду по выходному файлу. Этот основной пример имеет простое решение:

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

Вывод был бы:

1

2

3

4

и т.д...

Но что, если структура более сложна с вложенным foreach's:

<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 и т.д.). Кто-либо знает, как я могу произвести положение в файле (т.е. количество строки)?

5
задан Mr AH 26 May 2010 в 20:28
поделиться

4 ответа

Строка в XML-файле на самом деле не то же самое, что элемент. В вашем первом примере вы действительно считаете не строки, а количество элементов.

XML-файл может выглядеть так:

<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>

который XSLT будет интерпретировать точно так же - он не будет беспокоиться о переносах строк.

Поэтому трудно отображать номера строк так, как вы хотите, используя XSLT - на самом деле он не предназначен для такого анализа.

Кто-нибудь поправит меня, если я ошибаюсь, но я бы сказал, что вам понадобится Javascript или другой язык сценариев, чтобы делать то, что вы хотите.

5
ответ дан 18 December 2019 в 11:54
поделиться

Спасибо за ответы, ребята - да, вы совершенно правы, некоторые внешние функции - единственный способ добиться такого поведения в XSLT. Для тех, кто ищет, вот как я сделал это при использовании скомпилированного преобразования в .Net 3.5:

Создайте вспомогательный класс для вашей функции (ей)

/// <summary>
/// Provides functional support to XSLT
/// </summary>
public class XslHelper
{
    /// <summary>
    /// Initialise the line counter value to 1
    /// </summary>
    Int32 counter = 1;

    /// <summary>
    /// Increment and return the line count
    /// </summary>
    /// <returns></returns>
    public Int32 IncrementCount()
    {
        return counter++;
    }
}

Добавьте экземпляр в список аргументов для XSLT

XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(XmlReader.Create(s));
XsltArgumentList xslArg = new XsltArgumentList();
XslHelper helper = new XslHelper();
xslArg.AddExtensionObject("urn:helper", helper);
xslt.Transform(xd.CreateReader(), xslArg, writer);

Используйте его в вашем XSLT

Поместите это в элемент объявления таблицы стилей:

 xmlns:helper="urn:helper"   

Затем используйте так:

<xsl:value-of select="helper:IncrementCount()" />
3
ответ дан 18 December 2019 в 11:54
поделиться

Обычно position () относится к номеру текущего узла относительно всего пакета узлов, который обрабатывается в данный момент.

В вашем примере «вложенность для каждого» можно легко добиться последовательной нумерации, если вы прекратите вложение для каждой конструкции и просто выберете все желаемые элементы сразу.

С этим XML:

<a><b><c/><c/></b><b><c/></b></a>

конструкция цикла, подобная этой

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

, приведет к

11221
bccbc  // referred-to nodes

, но вы могли бы просто сделать это вместо:

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

и получить

123
ccc    // referred-to nodes
1
ответ дан 18 December 2019 в 11:54
поделиться

В то время как обозначить номера строк для сериализации 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>

при применении к этому XML-документу:

<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.
6
ответ дан 18 December 2019 в 11:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: