Сводная сводная таблица с использованием XSLT 1.0 - PullRequest
0 голосов
/ 25 ноября 2018

Мне нужна сводная таблица, которая будет отображать следующий XML.

<Records reportTime24h="18:02" reportTime="06:02:56PM" reportDate="2018-11-24" reportTitle="Pivot table">
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>F</Sex>
<TestID>1001</TestID>
<TestName>TRIGLYCERIDEN(501)</TestName>
<Total>91</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>F</Sex>
<TestID>1003</TestID>
<TestName>UREUM(501)</TestName>
<Total>62</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>M</Sex>
<TestID>1003</TestID>
<TestName>UREUM(501)</TestName>
<Total>1642</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>F</Sex>
<TestID>1004</TestID>
<TestName>NATRIUM(501)</TestName>
<Total>72</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>M</Sex>
<TestID>1004</TestID>
<TestName>NATRIUM(501)</TestName>
<Total>1929</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>F</Sex>
<TestID>1005</TestID>
<TestName>KALIUM(501)</TestName>
<Total>72</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>M</Sex>
<TestID>1005</TestID>
<TestName>KALIUM(501)</TestName>
<Total>1929</Total>
</Record>
</Records>

Вот как должна выглядеть таблица.

Pivot table in XSLT

Пересечение между строками и столбцами должно быть узлом Total xml, который соответствует пересекаемым данным.

Возможно ли это?

PD: я пытался сделать это, используя muenchianгруппировка.Однако я не смог эффективно перебрать данные по столбцам.Например, логика была не в состоянии обрабатывать узлы, которые имели данные только для одного из полов.Я попытался проверить данные в узле, чтобы отобразить ноль (0), но не получилось.

РЕДАКТИРОВАТЬ

Чтобы следовать рекомендации комментаторов.

Вот файл XSL, над которым я работал.Он достигает желаемого результата, но не дает результатов, когда в тесте есть данные только для одного пола.Данные будут помещены в первый столбец, независимо от того, принадлежит ли базовая точка к столбцам (пол).

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

<xsl:key name="key-tests" match="Record" use="TestID" />
<xsl:key name="key-sex" match="Record" use="Sex" />

<xsl:key name="key-tests-sex" match="Record" use="concat(TestID,'::',Sex)" />

<xsl:template match="/Records">

<html>

    <head>

        <style>

            body        { font-family: monospace;                                       }
            table       { border-collapse: collapse; font-size: 8pt;                    }
            table thead { background-color: gainsboro; font-weight: bold;               }
            td,th       { border: 1px solid gainsboro; padding: 3px; min-width: 26px;   }
            tbody td    { text-align: right;                                    }

        </style>

    </head>

    <body>

        <table>

            <thead>
                <tr>
                    <th>Sex</th>
                    <xsl:apply-templates select="Record[generate-id() = generate-id(key('key-sex',Sex)[1])]" mode="key-sex"/>
                </tr>
            </thead>

            <tbody>
              <xsl:apply-templates select="Record[generate-id() = generate-id(key('key-tests',TestID)[1])]" mode="key-tests"/>
                <tr>
                    <th></th>
                    <th><xsl:value-of select="sum(key('key-sex','F')/Total)"/></th>
                    <th><xsl:value-of select="sum(key('key-sex','M')/Total)"/></th>
                </tr>
            </tbody>

        </table>       

    </body>

</html>

</xsl:template>
<!--Row Data (totals)-->
<xsl:template match="Record" mode="key-tests-sex">
    <td><xsl:value-of select="Total"/></td>
</xsl:template>

<!-- Doctors (HEADER ROW) -->
<xsl:template match="Record" mode="key-sex">
    <th><xsl:value-of select="Sex"/></th>
</xsl:template>

<!-- Tests (ROWS) -->
<xsl:template match="Record" mode="key-tests">
    <tr>
        <td><xsl:value-of select="TestName"/></td>
        <xsl:apply-templates select="key('key-tests',TestID)[generate-id() = generate-id(key('key-tests-sex',concat(TestID,'::',Sex))[1])]" mode="key-tests-sex"/>
    </tr>

</xsl:template>

</xsl:stylesheet>

Вот изображение конечного результата.Я включил только часть, видимую в окне просмотра.Это около 3 страниц.Но этого должно быть достаточно, чтобы понять, чего я пытаюсь достичь.

enter image description here

Что не так с картинкой

Счет, показанный для женщины (7), фактически является счетом для мужчины.

enter image description here

1 Ответ

0 голосов
/ 25 ноября 2018

Попробуйте изменить шаблон соответствия Record для режима key-tests на

<!-- Tests (ROWS) -->
<xsl:template match="Record" mode="key-tests">
    <tr>
        <td><xsl:value-of select="TestName"/></td>
        <td>
            <xsl:value-of select="key('key-tests',TestID)[generate-id() = generate-id(key('key-tests-sex',concat(TestID,'::','F'))[1])]/Total"/>
        </td>
        <td>
            <xsl:value-of select="key('key-tests',TestID)[generate-id() = generate-id(key('key-tests-sex',concat(TestID,'::','M'))[1])]/Total"/>
        </td>
    </tr>
</xsl:template>

Это, по крайней мере, должно решить проблему с неправильным соотношением числа и пола.

Поскольку в ваших реальных данных различные значения элемента Sex не ограничены F и M, вам потребуется какой-то способ обрабатывать уникальные значения каждый раз, чтобы создать ячейку tdи внутри затем сопоставьте с соответствующими данными Record, чтобы шаблон стал

<!-- Tests (ROWS) -->
<xsl:template match="Record" mode="key-tests">
    <tr>
        <td><xsl:value-of select="TestName"/></td>
        <xsl:variable name="testId" select="TestID"/>
        <xsl:for-each select="$unique-genders">
            <td>
              <xsl:value-of select="key('key-tests', $testId)[generate-id() = generate-id(key('key-tests-sex',concat(TestID, '::', current()))[1])]/Total"/>  
            </td>
        </xsl:for-each>
    </tr>
</xsl:template>

с объявлениями

<xsl:key name="key-sex" match="Sex" use="." />

<xsl:variable name="unique-genders" select="//Sex[generate-id() = generate-id(key('key-sex', .)[1])]"/>

, как это сделано в https://xsltfiddle.liberty -development.net /3NzcBue / 2

...