XSLT: 3.0 Формат вывода отчета о сотрудниках имеет заголовок и строку. Любой способ добиться подсчета Total Emp в записи заголовка с использованием for-each и аккумулятора? - PullRequest
0 голосов
/ 06 мая 2020

Я хочу получить следующий вывод: Запись заголовка должна показать: Общее количество сотрудников в отчете

Строка запись должна показать: Emp ID | Имя

Вот мой XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:output method="text" indent="no"/>

<xsl:accumulator name="emp.count" streamable="yes" as="xs:integer" initial-value="0">
<xsl:accumulator-rule match="Employee_ID/text()" select="$value +1"/>
</xsl:accumulator>

<xsl:mode streamable="yes" on-no-match="shallow-skip" use-accumulators="emp.count"/>

<xsl:template match="/">
<xsl:for-each select="copy-of(Employee_Data)>
<xsl:value-of select="Employee_ID"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="First_Name"/>
<xsl:value-of select="accumulator-after('emp.count')"
<xsl:text>&#xa;&#xd;</xsl:text>
</xsl:for-each>
</xsl:template>

1 Ответ

0 голосов
/ 06 мая 2020

Единственная однопроходная потоковая обработка, которая может выводить данные о сотрудниках, которые вы хотите вывести, до того, как счетчик сотрудников должен будет буферизовать данные о сотрудниках, например, в последовательности карт:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">

    <xsl:mode on-no-match="shallow-skip" streamable="yes" use-accumulators="#all"/>

    <xsl:accumulator name="employees" as="map(xs:string, xs:string)*" initial-value="()" streamable="yes">
        <xsl:accumulator-rule 
            match="employee" 
            select="$value, map{}"/>
        <xsl:accumulator-rule 
            match="employee/id/text() | employee/first-name/text()"
            select="$value[position() lt last()], map:put($value[last()], local-name(..), string())"/>
    </xsl:accumulator>

    <xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:apply-templates/>
        <xsl:text>Employee count: {count(accumulator-after('employees'))}&#10;</xsl:text>
        <xsl:value-of select="accumulator-after('employees') ! (?id || '|' || ?first-name)" separator="&#10;"/>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/93dFepX/1 имеет код с простым входным образцом, но используется Saxon HE, поэтому потоковая передача игнорируется, но я проверил, что код работает с потоковой передачей с Saxon 9.9 и 10 EE.

Два передать решение, которое обрабатывает документ один раз для подсчета, а затем второй раз для потоковой передачи деталей, будет

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">

    <xsl:output method="text"/>

    <xsl:mode streamable="yes" on-no-match="shallow-skip"/>

    <xsl:param name="input-uri" as="xs:string">input1.xml</xsl:param>

    <xsl:template name="xsl:initial-template">
        <xsl:variable name="employee-count" as="xs:integer">
            <xsl:source-document href="{$input-uri}" streamable="yes">
                <xsl:sequence select="count(employees/employee)"/>
            </xsl:source-document>
        </xsl:variable>
        <xsl:text>Employee count: {$employee-count}&#10;</xsl:text>
        <xsl:source-document href="{$input-uri}" streamable="yes">
            <xsl:apply-templates/>
        </xsl:source-document>
    </xsl:template>

    <xsl:template match="employee">
        <xsl:value-of select="copy-of()!(id, first-name)" separator="|"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:template>  

</xsl:stylesheet>

Запустить его с -it в качестве параметра командной строки, передав исходный файл для обработки как параметр input-uri.

...