XSLT: использование одного ключа для перекрестной ссылки на второй ключ

Мне нужно преобразовать XML в сетку таблиц, которая принимает формат:

A1,B1,C1

A2,B2,C2

A3,B3,C3

XML, с которым я работаю, предоставляет одно значение ячейки для каждой записи, но каждая запись предоставляет значение DayOfWeek (столбец) и Stream (строка).

Я сделал простое XSLT-преобразование, используя два ключа: один для Stream и один для DayOfWeek. Они успешно работают в том смысле, что у меня есть 3 строки, по одной для каждого потока, и 3 столбца, по одной на каждый день недели. Однако содержимое повторяется только в первой строке (т.е.

A1,B1,C1,
A1,B1,C1,
A1,B1,C1

Как выбрать DisplayStuff в ячейку таблицы на основе обоих ключевых критериев?

Вот мой XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes" encoding="us-ascii" />
    <xsl:key name="DayOfWeek1" match="DataRow" use="DayOfWeek" />
    <xsl:key name="Stream1" match="DataRow" use="Stream" />
    <xsl:template match="QueryResults">
        <table>
    <xsl:for-each select="//DataRow[generate-id() = generate-id(key('Stream1',Stream)[1])]">
        <tr style="border: 1px solid black;" class="scrolling">
            <xsl:for-each select="//DataRow[generate-id() = generate-id(key('DayOfWeek1',DayOfWeek)[1])]">


                <td style="border: 1px solid black;" width="100px">
                    <xsl:value-of select="DisplayStuff" />
                </td>

            </xsl:for-each>
        </tr>
    </xsl:for-each>
    </table>
    </xsl:template>
</xsl:stylesheet>

XML:

<?xml version="1.0" encoding="UTF-8"?>
<QueryResults>
<DataRow>
    <Stream>1</Stream>
    <DayOfWeek>1</DayOfWeek>
    <DisplayStuff>A1</DisplayStuff>
</DataRow>
<DataRow>
    <Stream>1</Stream>
    <DayOfWeek>2</DayOfWeek>
    <DisplayStuff>B1</DisplayStuff>
</DataRow>
<DataRow>
    <Stream>1</Stream>
    <DayOfWeek>3</DayOfWeek>
    <DisplayStuff>C1</DisplayStuff>
</DataRow>
<DataRow>
    <Stream>2</Stream>
    <DayOfWeek>1</DayOfWeek>
    <DisplayStuff>A2</DisplayStuff>
</DataRow>
<DataRow>
    <Stream>2</Stream>
    <DayOfWeek>2</DayOfWeek>
    <DisplayStuff>B2</DisplayStuff>
</DataRow>
<DataRow>
    <Stream>2</Stream>
    <DayOfWeek>3</DayOfWeek>
    <DisplayStuff>C2</DisplayStuff>
</DataRow>
<DataRow>
    <Stream>3</Stream>
    <DayOfWeek>1</DayOfWeek>
    <DisplayStuff>A3</DisplayStuff>
</DataRow>
<DataRow>
    <Stream>3</Stream>
    <DayOfWeek>2</DayOfWeek>
    <DisplayStuff>B3</DisplayStuff>
</DataRow>
<DataRow>
    <Stream>3</Stream>
    <DayOfWeek>3</DayOfWeek>
    <DisplayStuff>C3</DisplayStuff>
</DataRow>
</QueryResults>

person iainc    schedule 14.07.2017    source источник
comment
Возможно, это просто неудачный пример, но если вы знаете, что имеете дело с сеткой 3x3 (или 3xn), зачем вообще нужны ключи? Просто создайте строку для каждой группы из 3 записей и ячейку для каждой записи в этой группе - см., например, stackoverflow.com/a /26573496/3016153.   -  person michael.hor257k    schedule 14.07.2017
comment
в этом проблема. таблица динамическая. клиники могут работать до 7 дней в неделю, и дни не обязательно должны следовать друг за другом. может быть до 10 потоков клиники.   -  person iainc    schedule 16.07.2017
comment
в этом проблема. таблица динамическая. клиники могут работать до 7 дней в неделю, и дни не обязательно должны следовать друг за другом. может быть до 10 потоков клиники.   -  person iainc    schedule 16.07.2017


Ответы (1)


Попробуй так?

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="row-by-day" match="DataRow" use="DayOfWeek" />
<xsl:key name="row-by-stream" match="DataRow" use="Stream" />

<xsl:template match="/QueryResults">
    <!-- a column for each distinct day of week  -->
    <xsl:variable name="columns" select="DataRow[generate-id() = generate-id(key('row-by-day', DayOfWeek)[1])]" />
    <table border="1">
        <!--  a row for each distinct stream -->
        <xsl:for-each select="DataRow[generate-id() = generate-id(key('row-by-stream', Stream)[1])]">
            <xsl:variable name="stream" select="key('row-by-stream', Stream)" />
            <tr>
                <!-- a cell for each column -->
                <xsl:for-each select="$columns">
                    <xsl:sort select="DayOfWeek" data-type="number" order="ascending"/>
                    <td>
                        <xsl:value-of select="$stream[DayOfWeek = current()/DayOfWeek]/DisplayStuff" />
                    </td>
                </xsl:for-each>
            </tr>
        </xsl:for-each>
    </table>
</xsl:template>

</xsl:stylesheet>

Обратите внимание, что предполагается, что на каждом пересечении Stream и DayOfWeek будет не более одного DataRow.

person michael.hor257k    schedule 16.07.2017