2016-05-24 2 views
0

Я хочу использовать счетчик для увеличения и уменьшения значения в XSLT. Я могу добиться этого, используя Apache Xalan, но теперь я хочу добиться того же, что и Saxon.Использование Saxon, увеличение или уменьшение глобальных переменных в XSLT

Мой XSLT сценарий Xalan выглядит следующим образом:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:lxslt="http://xml.apache.org/xslt" 
       xmlns:result="http://www.example.com/results" 
       extension-element-prefixes="result"> 

    <lxslt:component prefix="result" functions="incr dcr"> 
     <lxslt:script lang="javascript"> 
      var count = 0; 
      function incr() { 
       count++; 
       return count; 
      } 

      function dcr() { 
       count--; 
       return count; 
      } 
     </lxslt:script> 
    </lxslt:component> 

    <xsl:template match="/"> 
     a)<xsl:value-of select="result:incr()"/> 
     b)<xsl:value-of select="result:incr()"/> 
     c)<xsl:value-of select="result:dcr()"/> 
    </xsl:template> 

</xsl:stylesheet> 

Ожидаемый результат:

a)1 
b)2 
c)1 

------------------------- my use case using saxon ------------------- 
This is my sample data.xml file. I want to transform this to html file. 

<entity> 
    <record>10</record> 
    <record>15</record> 
    <record>19</record> 
    <record>7</record> 
    <record>4</record> 
    <record>14</record> 
    <record>24</record> 
<entity> 

I want to implement a counter for line-number and want to increment the counter and print the line-number 
my expected outputs: 

case 1: If record values > 14, then my output should have line-number with value as. 
line-num value  
    1  15 
    2  19 
    3  24 

case 2 : If record values < 14, then my output should have line-number with value as. 
line-num value  
    1   10 
    2   7 
    3   4 

My other use case : 

<entity> 
    <record>10</record> 
    <record>15</record> 
    <record>19</record> 
    <record>7</record> 
    <record>20</record> 
    <record>14</record> 
    <record>24</record> 
    <entity> 
     <record>30</record> 
     <record>3</record> 
    </entity> 
</entity> 
<entity> 
    <record>5</record> 
    <record>17</record> 
    <record>19</record> 
    <record>6</record> 
    <record>70</record> 
    <record>9</record> 
    <record>35</record> 
    <entity> 
     <record>15</record> 
     <record>2</record> 
    </entity> 
</entity> 


This is my other use case, first <entity> record value > 15 and in second <entity> record value < 10, and my <entity> can grow bigger where i have to show only some record based on condition. 

line-num value 
    1  19 
    2  20 
    3  24 
    4  30 
    5  5 
    6  6 
    7  2 

ответ

1

Там нет никакого способа, чтобы использовать Javascript в Saxon, насколько я знаю.

Если вы хотите использовать назначаемую и изменяемую переменную в Saxon 9 (EE или PE), то вы можете использовать

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:saxon="http://saxon.sf.net/" 
    xmlns:mf="http://example.com/mf" 
    extension-element-prefixes="saxon" 
    exclude-result-prefixes="xs saxon mf" 
    version="2.0"> 

    <xsl:variable name="counter" as="xs:integer" select="0" saxon:assignable="yes"/> 

    <xsl:function name="mf:incr" as="xs:integer"> 
     <saxon:assign name="counter" select="$counter + 1"/> 
     <xsl:sequence select="$counter"/> 
    </xsl:function> 

    <xsl:function name="mf:decr" as="xs:integer"> 
     <saxon:assign name="counter" select="$counter - 1"/> 
     <xsl:sequence select="$counter"/> 
    </xsl:function> 

    <xsl:template match="/" name="main"> 
     a)<xsl:value-of select="mf:incr()"/> 
     b)<xsl:value-of select="mf:incr()"/> 
     c)<xsl:value-of select="mf:decr()"/> 
    </xsl:template> 

</xsl:stylesheet> 

Смотрите предупреждения и примечания в http://saxonica.com/html/documentation/extensions/instructions/assign.html однако на попытки введения побочных эффектов. Вы можете отредактировать свой вопрос, чтобы объяснить свой XML-ввод и желаемый результат, и почему вы считаете, что вам нужна такая переменная счетчика, мы надеемся, что тогда мы сможем показать чистое решение XSLT 2.0 вместо использования назначаемой переменной.

Что касается вашего требования для обработки и количества определенных входных элементов, таблицы стилей

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 

    <xsl:output indent="yes"/> 

    <xsl:template match="entity"> 
     <root> 
      <xsl:apply-templates select="record[. > 14]"/> 
      <xsl:apply-templates select="record[. &lt; 14]"/> 
     </root> 
    </xsl:template> 

    <xsl:template match="record"> 
     <xsl:copy> 
      <line-num> 
       <xsl:value-of select="position()"/> 
      </line-num> 
      <value> 
       <xsl:value-of select="."/> 
      </value> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

при запуске против ввода

<entity> 
    <record>10</record> 
    <record>15</record> 
    <record>19</record> 
    <record>7</record> 
    <record>4</record> 
    <record>14</record> 
    <record>24</record> 
</entity> 

выходов

<root> 
    <record> 
     <line-num>1</line-num> 
     <value>15</value> 
    </record> 
    <record> 
     <line-num>2</line-num> 
     <value>19</value> 
    </record> 
    <record> 
     <line-num>3</line-num> 
     <value>24</value> 
    </record> 
    <record> 
     <line-num>1</line-num> 
     <value>10</value> 
    </record> 
    <record> 
     <line-num>2</line-num> 
     <value>7</value> 
    </record> 
    <record> 
     <line-num>3</line-num> 
     <value>4</value> 
    </record> 
</root> 

Другие варианты используют, например, xsl:number count="entity[. &lt; 14]".

Что касается вашего последнего требования, я думаю, что вы все равно справитесь с этим, используя position(), пока вы выбираете элементы, которые хотите обработать, например. таблица стилей

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

    <xsl:output method="text"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="/root/entity[1]//record[. > 15], /root/entity[2]//record[. &lt; 10]"/> 
    </xsl:template> 

    <xsl:template match="record"> 
     <xsl:value-of select="concat(position(), ' ', ., '&#10;')"/> 
    </xsl:template> 

</xsl:stylesheet> 

при подаче на вход

<root> 
    <entity> 
     <record>10</record> 
     <record>15</record> 
     <record>19</record> 
     <record>7</record> 
     <record>20</record> 
     <record>14</record> 
     <record>24</record> 
     <entity> 
      <record>30</record> 
      <record>3</record> 
     </entity> 
    </entity> 
    <entity> 
     <record>5</record> 
     <record>17</record> 
     <record>19</record> 
     <record>6</record> 
     <record>70</record> 
     <record>9</record> 
     <record>35</record> 
     <entity> 
      <record>15</record> 
      <record>2</record> 
     </entity> 
    </entity> 
</root> 

выходов (с XSLT-процессором 2.0, как Saxon 9)

1 19 
2 20 
3 24 
4 30 
5 5 
6 6 
7 9 
8 2 
+0

Спасибо за душу. –

+0

Вчера я прочитал саксонскую документацию и смог разобраться с ней и попробовал свой образец. –

+0

«Мы надеемся, что тогда мы сможем показать чистое решение XSLT 2.0 вместо использования назначаемой переменной», я хочу контролировать счетчик с целью увеличения/уменьшения с любым целым значением. –

0

Без JavaScript, используя Саксон инструкции расширения.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:saxon="http://saxon.sf.net/" 
       extension-element-prefixes="saxon" 
       exclude-result-prefixes="saxon"> 
    <xsl:variable name="i" select="0" saxon:assignable="yes"/> 
    <xsl:template match="/"> 
     a) <xsl:value-of select="$i"/> 
      <saxon:assign name="i" select="$i+1"/> 
     b) <xsl:value-of select="$i"/> 
      <saxon:assign name="i" select="$i+2"/> 
     c) <xsl:value-of select="$i"/> 
      <saxon:assign name="i" select="$i+3"/> 
     d) <xsl:value-of select="$i"/> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Ссылка: http://www.saxonica.com/documentation9.5/extensions/instructions/assign.html –

1

(В ответ на расширенное описание проблемы)

ключевая вещь, чтобы оценить, что эта проблема требует последовательной обработки в record элементов в порядке документа. Это означает, что он не может быть достигнут независимым от процессора способом с xsl: for-each или xsl: apply-templates, потому что им не гарантируется обработка элементов по порядку (недавние версии Saxon, например, будет обрабатывать элементы параллельно, используя многопоточность, и спецификация позволяет это: это делает любую попытку обновить глобальные переменные неэффективными).

Классический способ обработки элементов последовательно использует рекурсию с хвостовым оперением.Напишите шаблон или функцию, которая принимает в качестве параметра последовательность record элементов, а текущий номер строки - второй. Если список записей не пуст, то (а) обработайте первый список record в списке и (б) вызовите себя рекурсивно для обработки остальной части списка, передав новое значение номера строки.

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

В XSLT 3.0 есть новая конструкция xsl: iterate, которая больше похожа на обычный цикл: когда вы вводите тело xsl: iterate, вы передаете начальные значения для своих параметров и каждый раз, когда вы переходите к следующей итерации цикла вы можете установить новые значения для параметров.

+0

У меня был другой вариант использования, в котором элементы записи могут быть child.pleas, дайте свои мысли об этом. Он доступен в разделе «Мой другой вариант использования:» в моем вопросе. –

+0

Прошу прощения, я не думаю, что СО работает хорошо, когда люди продолжают добавлять новые вопросы к вопросу. Это делает очень трудным для тех, кто приходит позже, чтобы следить за потоком, и другим трудно понять, что изменилось. Задайте новый вопрос и обратитесь к оригиналу. –

Смежные вопросы