2014-01-06 2 views
4

Может кто-нибудь объяснить мне, почему я получаю следующий вывод, применяя следующий xsl-файл к XML-файлу.Значение XSLT() и position() дают неверные индексы

<?xml version="1.0" encoding="ISO-8859-1"?> 
<source>  
    <number>1</number> 
    <number>2</number> 
    <number>3</number> 
    <number>4</number> 
    <number>5</number> 
    <number>6</number> 
    <number>7</number> 
    <number>8</number> 
</source> 

====================================

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> 
<xsl:template match="number"> 
    <p> 
    <xsl:value-of select="position()"/> 
    <xsl:text> of </xsl:text> 
    <xsl:value-of select="last()"/> 
    </p> 
</xsl:template> 
</xsl:stylesheet> 

======================================

<p>2 of 17</p> 
    <p>4 of 17</p> 
    <p>6 of 17</p> 
    <p>8 of 17</p> 
    <p>10 of 17</p> 
    <p>12 of 17</p> 
    <p>14 of 17</p> 
    <p>16 of 17</p> 

Я не совсем почему выход не 1 из 8, 2 из 8 и так далее.

+0

возможно дубликат [используя положение() функции в XSLT] (HTTP: //stackoverflow.com/questions/4449810/using-position-function-in-xslt) – Louis

ответ

2

Попытка добавления стрип-пространство, как показано ниже:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="number"> 
    <p> 
    <xsl:value-of select="position()"/> 
    <xsl:text> of </xsl:text> 
    <xsl:value-of select="last()"/> 
    </p> 
</xsl:template> 
</xsl:stylesheet> 

Это дает следующий результат:

<p>1 of 8</p> 
<p>2 of 8</p> 
<p>3 of 8</p> 
<p>4 of 8</p> 
<p>5 of 8</p> 
<p>6 of 8</p> 
<p>7 of 8</p> 
<p>8 of 8</p> 

Это связано с пробельных вопросов, как описано в этом document. В основном набор узлов содержит пробельные узлы, которые не соответствуют вашему шаблону, но вносят вклад в индекс каждого узла.

+0

Отлично, спасибо большое. – user1765902

3

Хороший ответ уже предоставлен @ColinE. Я хотел бы добавить еще один способ обхода этой проблемы подсчета узлов, которые явно не нацелены на ваши шаблоны. То есть без использования strip-space.

Соответствие вашему узлу документа (источнику) и использованию элемента xsl:for-each, вы убедитесь, что учитываются только number элементов. Другими словами, лишние узлы теперь не соответствуют контексту.

<?xml version="1.0" encoding="ISO-8859-1"?> 

<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> 

<xsl:output method="xml" omit-xml-declaration="yes"/> 

<xsl:template match="source"> 
    <xsl:for-each select="number"> 
    <p> 
     <xsl:value-of select="position()"/> 
     <xsl:text> of </xsl:text> 
     <xsl:value-of select="last()"/> 
    </p> 
    <xsl:text>&#10;</xsl:text> 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 

Это дает тот же результат:

<p>1 of 8</p> 
<p>2 of 8</p> 
<p>3 of 8</p> 
<p>4 of 8</p> 
<p>5 of 8</p> 
<p>6 of 8</p> 
<p>7 of 8</p> 
<p>8 of 8</p> 

С другой стороны, strip-space делает ваш вход выглядеть следующим образом:

<source><number>1</number><number>2</number><number>3</number><number>4</number><number>5</number><number>6</number><number>7</number><number>8</number></source> 

Теперь, если применить ваш первоначальный stylesheet для вышеупомянутого входного XML, который не имеет пробелов, вы получите тот же результат, что и при использовании solutio ns, выдвинутые ColinE и мной.

+0

+1 Это очень хороший момент – ColinE

0

Другой вариант - использовать xsl:number. Это намного мощнее, чем position(). (Дополнительные возможности xsl:number не нужны в этом простом примере, но это хорошо знать.)

Пример:

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

    <xsl:template match="number"> 
     <p> 
      <xsl:number/> 
      <xsl:text> of </xsl:text> 
      <xsl:value-of select="../number[last()]"/> 
     </p> 
    </xsl:template> 

</xsl:stylesheet> 
Смежные вопросы