#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. Спасибо за предоставленную вами информацию. Это было очень полезно и четко объяснено.