Как использовать xsl: stream, xsl: Accumulator, xs: fork из XSLT 3.0?

Я читаю документацию W3C для XSLT 3.0 здесь. Интересно, как использовать эти элементы:

(1) xsl:decimal-format
(2) xsl:stream
(3) xsl:accumulator
(4) xsl:accumulator-rule
(5) xsl:fork

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

Я знаю, что на это нужно много ответить. Поэтому я буду поддерживать любой правильный частичный ответ в надежде, что он будет полезен другим.


person Chong Lip Phang    schedule 14.09.2014    source источник


Ответы (2)


xsl:decimal-format присутствует в спецификации с версии 1.0; другие элементы, которые вы цитируете, являются новыми в версии 3.0, и все они связаны с потоковой передачей (то есть с возможностью обрабатывать исходный документ «на лету», без загрузки всего дерева в память).

<xsl:stream href="in.xml">
   ...do something...
</xsl:stream>

имеет тот же эффект, что и

<xsl:for-each select="doc('in.xml')">
   ...do something...
</xsl:for-each>

за исключением того, что «сделай что-нибудь» передается в потоковом режиме (что означает, что оно должно соответствовать правилам потоковой передачи). Например, если вы хотите узнать среднюю зарплату большого количества сотрудников, вы можете сделать

<xsl:stream href="in.xml">
   <result><xsl:value-of select="avg(//employee/@salary)"/></result>
</xsl:stream>

Что, если вы хотите вычислить минимальную и максимальную зарплату во время одного прохода потоковой передачи входного документа? xsl: fork и аккумуляторы предоставляют решения этой проблемы. xsl: fork позволяет указать два или более вычислений, которые выполняются за один проход, эффективно параллельно:

<xsl:stream href="in.xml">
   <result>
     <xsl:fork>
        <xsl:sequence>
           <min><xsl:value-of select="min(//employee/@salary)"/></min>
        </xsl:sequence>
        <xsl:sequence>
           <max><xsl:value-of select="max(//employee/@salary)"/></max>
        </xsl:sequence>
     </xsl:fork>
   </result>
</xsl:stream>

xsl: Accumulator позволяет вам определять обработку, которая происходит эффективно как побочный эффект чтения документа:

<xsl:accumulator name="min-salary" initial-value="10000000">
  <xsl:accumulator-rule match="employee" 
      select="if (@salary lt $value) then @salary else $value"/>
</xsl:accumulator>

и затем в любой момент обработки вы можете узнать минимальную заработную плату, позвонив по телефону accumulator-before('min-salary').

person Michael Kay    schedule 14.09.2014
comment
Итак, когда оценивается аккумулятор? Как это связано со стримингом? - person Chong Lip Phang; 14.09.2014
comment
При потоковой передаче аккумуляторы оцениваются постепенно по мере чтения документа: каждое событие начального или конечного элемента вызывает срабатывание любых соответствующих правил аккумуляторов, которые потенциально обновляют значение аккумулятора для этого узла. Накопители также работают для непотоковых документов, но они предназначены для выполнения вычислений при потоковой передаче, которая в противном случае потребовала бы нескольких проходов по входному документу (например, создание указателя конца книги). - person Michael Kay; 15.09.2014

<xsl:decimal-format>
Здесь нашел хороший пример: MSDN xsl: decimal-format

Пример сокращен: объявление <xsl:decimal-format> в XSL

<xsl:decimal-format name="example" decimal-separator="." grouping-separator=","  
 infinity="INFINITY" minus-sign="-" NaN="Not a Number" percent="%"
 per-mille="m" zero-digit="0" digit="#" pattern-separator=";" />

Использование с <xsl:format-number>

<xsl:value-of select="format-number(1 div 0, '###,###.00', 'example')"/>  

Вывод: INFINITY
Ссылка: http://www.w3.org/TR/2013/WD-xslt-30-20131212/#dt-decimal-format
Полная рабочая демонстрация протестирована на http://exselt.net/demo:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="decimalformat.xsl"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="html"/>   
<xsl:decimal-format name="example" decimal-separator="." grouping-separator=","
  infinity="INFINITY" minus-sign="-" NaN="Not a Number" percent="%"
  per-mille="m" zero-digit="0" digit="#" pattern-separator=";" /> 
<xsl:template match="/">
  <html>
    <head></head>
    <body>
        <xsl:value-of select="format-number(1 div 0, '###,###.00', 'example')"/>  
    </body>
  </html>
</xsl:template>

person matthias_h    schedule 14.09.2014
comment
Странный. Мне пришлось изменить версию таблицы стилей с 3.0 на 1.0, чтобы она работала. - person Chong Lip Phang; 14.09.2014
comment
Также задумался об этом и только что обновил ответ с рабочим примером - person matthias_h; 14.09.2014