Шаблоны XSLT и применение шаблонов

#xslt

#xslt

Вопрос:

Я очень новичок в XSLT, и мне трудно понять некоторые из его концепций.

У меня есть следующий XML-файл:

  <?xml version="1.0" encoding="ISO-8859-1"?>
 <?xml-stylesheet type="text/xsl" href="test.xsl"?>

<Page>
    <Page>
        <Page />
    </Page>
    <Page>
        <Page />
    </Page>
    <Page />
    <Page />
    <Page />
</Page>
  

И когда применяется следующий файл XSL (test.xsl):

 <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
 <html>
    <head>
    </head>
    <body>
        <h2>
            <xsl:apply-templates name="PageCount" />
        </h2>
    </body>
 </html>
 </xsl:template>

 <xsl:template match="Page" name="PageCount">
     Page <xsl:value-of select="position()" />
     of <xsl:value-of select="count(/Page/Page)" />

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

Я получаю вывод:

Страница 2 из 5

Однако, если я изменю «apply-templates» на «call-template», результат изменится на:

Страница 1 из 5

Почему это происходит?

Также, если я добавлю другой шаблон:

   <xsl:template match="Page" name="PageCount2">
    Page <xsl:value-of select="position()" />
    of <xsl:value-of select="count(/Page)" />
  </xsl:template>
  

и использование «apply-templates», похоже, дает мне результат:

Страница 2 из 1

Это сбивает меня с толку. Что происходит?

Заранее спасибо.

Комментарии:

1. Вы не должны получать никаких выходных данных для <xsl:apply-templates name="PageCount" /> — это синтаксическая ошибка (apply-templates принимает атрибут select, а не атрибут name). Вы уверены, что это то, что вы написали?

2. @Michael Kay — я считаю, что @ dherrin79 хочет знать разницу между <xsl:apply-templates/> и <xsl:call-template name="PageCount"/> (который выдает описанный результат) и почему он оценивается по-разному.

3. @MichaelKay — Это именно то, что я написал, поскольку я просто вставил это прямо в свой вопрос. Однако спасибо за понимание. Я не знал, что имя не является допустимым атрибутом для команды «применить-шаблоны».

Ответ №1:

Когда вы используете <xsl:apply-templates/> , это действительно сокращение <xsl:apply-templates select="node()"/> и вызывается внутри шаблона match on / , который является корневым узлом документа и абстрактным понятием для начала файла. Его дочерние элементы включают элемент document (т.Е. <Page> ), а также любые комментарии верхнего уровня или инструкции по обработке, которые могут быть родственниками элемента document.

Итак, когда вы «стоите» на корневом узле, вызов to <xsl:apply-templates/> применит шаблоны к /Page , который соответствует шаблону, который вы определяете. position() вычисляется из соответствующего контекста, который является /Page , и возвращает 2 , потому что это второй элемент в документе. Первый элемент — это инструкция по обработке XML-таблиц стилей. Если бы вы его удалили, то position() оценили бы 1 .

При использовании <xsl:call-template name="PageCount"/> он вызывает тот же шаблон, но контекст не меняется при вызове шаблона.Вы все еще «стоите» на корневом узле, поэтому position() оценивается 1 как .

count() Всегда вычисляется одинаково, независимо от контекста, потому что он использует XPath, который начинается с корневого узла. Если бы вы изменили его на count(Page/Page) и оценили relative из узла контекста, тогда вы получили бы разные значения ( 2 и 5 соответственно).

Комментарии:

1. Спасибо за предоставленную вами информацию. Это было очень полезно и четко объяснено.