Использование аккумулятора в xslt 3.0 не работает, как мне нужно

У меня есть XML, в котором у меня есть список книг со свойствами, такими как название, цена, автор, дополнительная цена, исполнитель, страна и т. Д. XML приведен ниже. <?xml version="1.0" encoding="UTF-8"?> <catalog> <cd> <title>Empire Burlesque</title> <artist>Bob Dylan</artist> <country>USA</country> <company>Columbia</company> <price>10.90</price> <additionalprice>12.90</additionalprice> <year>1985</year> </cd> <cd> <title>Hide your heart</title> <artist>Bonnie Tyler</artist> <country>UK</country> <company>CBS Records</company> <price>9.90</price> <additionalprice>10.90</additionalprice> <year>1988</year> </cd>

и так далее

Я хочу написать XSLT 3.0, примененный к XML, чтобы получить HTML. Я хочу использовать аккумулятор, чтобы получить общее количество книг в каталоге. Хотя есть и лучшие методы, я просто хотел использовать аккумулятор для практических целей и распечатать итоги в конце таблицы, содержащей книги, где столбцы - это название, автор и общая стоимость. Для заполнения заголовка и автора я использовал for-each. Общая стоимость = цена + дополнительная цена. Я хочу использовать итерацию для подачи общей цены. Может кто-нибудь, пожалуйста, помогите мне с этим. Моя неполная таблица стилей выглядит следующим образом:

`<?xml version="3.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html> 
<body>
  <h2>My CD Collection</h2>
  <table border="2">
    <tr bgcolor="#9acd32">
       <th style="text-align:left">Title</th>
       <th style="text-align:left">Artist</th>
       <th style="text-align:left">Total Price</th>
    </tr>
 <xsl:accumulator name="total" as="xs:integer" initial-value="0" streamable="no">
    <xsl:accumulator-rule match="title" select="$value+1"/>
 </xsl:accumulator>
    <xsl:for-each select="catalog/cd">
     <tr>
       <td><xsl:value-of select="title"/></td>
       <td><xsl:value-of select="artist"/></td>
     </tr>
   </xsl:for-each>
         <tr bgcolor="#FFA500">
           <td> Total number of Books </td>
           <td> <xsl:value-of select="accumulator-before('total')"/</td>
         </tr>
     </table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>`

Я не хочу использовать потоковую передачу

1 ответ

Решение

Если вы посмотрите на спецификацию https://www.w3.org/TR/xslt-30/, то вы увидите, что xsl:accumulator это объявление, означающее, что вы должны использовать его как элемент / дочерний элемент верхнего уровня xsl:stylesheet, не внутри шаблона.

А значение аккумулятора связано с узлом и функциями, такими как https://www.w3.org/TR/xslt-30/ "Возвращает значение перед спуском выбранного аккумулятора в узле контекста. "Так в вашем случае, когда у вас есть один шаблон с узлом контекста / Это не имеет большого смысла, чтобы получить доступ к аккумулятору до значения, вам скорее нужно accumulator-after значение.

Наконец, вы должны объявить, что аккумулятор должен применяться в режиме по умолчанию

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

    <xsl:mode use-accumulators="#all"/>

    <xsl:accumulator name="total" as="xs:integer" initial-value="0" streamable="no">
        <xsl:accumulator-rule match="title" select="$value + 1"/>
    </xsl:accumulator>

    <xsl:template match="/">
        <html>
            <body>
                <h2>My CD Collection</h2>
                <table border="2">
                    <tr bgcolor="#9acd32">
                        <th style="text-align:left">Title</th>
                        <th style="text-align:left">Artist</th>
                        <th style="text-align:left">Total Price</th>
                    </tr>

                    <xsl:for-each select="catalog/cd">
                        <tr>
                            <td>
                                <xsl:value-of select="title"/>
                            </td>
                            <td>
                                <xsl:value-of select="artist"/>
                            </td>
                        </tr>
                    </xsl:for-each>
                    <tr bgcolor="#FFA500">
                        <td> Total number of Books </td>
                        <td>
                            <xsl:value-of select="accumulator-after('total')"/>
                        </td>
                    </tr>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>
Другие вопросы по тегам