Преобразование xsl для группировки многослойных результатов

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

Ниже приведен XML.

<xmlData>
    <records>
      <record>
        <userid>1</userid>
        <usersname>Jane Doe</usersname>
        <companyname>Company A</companyname>
        <eventdate>01 FEB 2017</eventdate>
        <jeventdate>2457786</jeventdate>
      </record>
      <record>
        <userid>3</userid>
        <usersname>Jane Doe</usersname>
        <companyname>Company B</companyname>
        <eventdate>01 FEB 2017</eventdate>
        <jeventdate>2457786</jeventdate>
      </record>
      <record>
        <userid>2</userid>
        <usersname>Joe Smith</usersname>
        <companyname>Company B</companyname>
        <eventdate>01 DEC 2016</eventdate>
        <jeventdate>2457724</jeventdate>
      </record>
      <record>
        <userid>2</userid>
        <usersname>Joe Smith</usersname>
        <companyname>Company B</companyname>
        <eventdate>01 JAN 2017</eventdate>
        <jeventdate>2457755</jeventdate>
      </record>
      <record>
        <userid>2</userid>
        <usersname>Joe Smith</usersname>
        <companyname>Company B</companyname>
        <eventdate>01 FEB 2017</eventdate>
        <jeventdate>2457786</jeventdate>
      </record>
    </records>
</xmlData>

Результаты, которые я пытаюсь получить, показаны в следующем простом выводе HTML.

<h1>01 DEC 2016</h1>
  <h2>Company B</h2>
  <table>
    <tr><td>2</td><td>Joe Smith</td></tr>
  </table>
<h1>01 JAN 2017</h1>
  <h2>Company B</h2>
  <table>
    <tr><td>2</td><td>Joe Smith</td></tr>
  </table>
<h1>01 FEB 2017</h1>
  <h2>Company A</h2>
  <table>
    <tr><td>1</td><td>Jane Doe</td></tr>
  </table>
  <h2>Company B</h2>
  <table>
    <tr><td>3</td><td>Dave Dodd</td></tr>
    <tr><td>2</td><td>Joe Smith</td></tr>
  </table>

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

Вот XSL, с которым я работал.

<xsl:key name="monthof" match="record" use="eventdate"/>
<xsl:key name="companyof" match="record" use="concat(eventdate,'|',companyname)"/>
<xsl:key name="userof" match="record" use="concat(eventdate,'|',companyname,'|',usersname)"/>

<xsl:template match="xmlData/records">
    <xsl:for-each select="record[key('monthof',eventdate)]">
        <xsl:sort select="jeventdate"/>
        <xsl:variable name="lstEventDate" select="key('monthof',eventdate)" />
        <h2><xsl:value-of select="eventdate"/></h2>
        <xsl:for-each select="key('companyof',concat(eventdate,'|',companyname))">
            <xsl:sort select="companyname"/>
            <h3>
                <xsl:value-of select="companyname"/>
            </h3>
            <table>
                <xsl:for-each select="key('userof',concat(eventdate,'|',companyname,'|',usersname))">
                    <tr>
                        <td><xsl:value-of select="userid"/></td>
                        <td><xsl:value-of select="usersname"/></td>
                    </tr>                                   
                </xsl:for-each>
            </table>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

И вот результат, который я получаю.

01 DEC 2016

Company B

2 Jane Doe 

01 JAN 2017

Company B

2 Jane Doe 

01 FEB 2017

Company A

1 Joe Smith 

01 FEB 2017

Company B

1 Joe Smith 

Company B

3 Dave Dodd 

01 FEB 2017

Company B

1 Joe Smith 

Company B

2 Jane Doe 

person Peter S    schedule 27.02.2017    source источник
comment
Начните здесь: jenitennison.com/xslt/grouping/muenchian.html Затем выполните поиск примеров многоуровневой мюнхианской группировки здесь, на SO.   -  person michael.hor257k    schedule 27.02.2017
comment
Для группировки задач нужно указывать XSLT 1.0 или 2.0, потому что ответы будут совсем другие.   -  person Michael Kay    schedule 28.02.2017


Ответы (1)


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

<xsl:template match="xmlData/records">
    <xsl:for-each select="record[generate-id() = generate-id(key('monthof',eventdate)[1])]">
        <xsl:sort select="jeventdate"/>
        <h2><xsl:value-of select="eventdate"/></h2>
        <xsl:for-each select="key('monthof', eventdate)[generate-id() = generate-id(key('companyof',concat(eventdate,'|',companyname))[1])]">
            <xsl:sort select="companyname"/>
            <h3>
                <xsl:value-of select="companyname"/>
            </h3>
            <table>
                <xsl:for-each select="key('companyof',concat(eventdate,'|',companyname))[generate-id() = generate-id(key('userof',concat(eventdate,'|',companyname,'|',usersname))[1])]">
                    <tr>
                        <td><xsl:value-of select="userid"/></td>
                        <td><xsl:value-of select="usersname"/></td>
                    </tr>                                   
                </xsl:for-each>
            </table>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

Возможно, вы захотите проверить, не сможете ли вы перейти на XSLT 2.0, где становится намного проще делать

<xsl:template match="xmlData/records">
    <xsl:for-each-group select="record" group-by="eventdate">
        <xsl:sort select="jeventdate"/>
        <h2><xsl:value-of select="eventdate"/></h2>
        <xsl:for-each-group select="current-group()" group-by="companyname">
            <xsl:sort select="companyname"/>
            <h3>
                <xsl:value-of select="companyname"/>
            </h3>
            <table>
                <xsl:for-each-group select="current-group()" group-by="usersname">
                    <tr>
                        <td><xsl:value-of select="userid"/></td>
                        <td><xsl:value-of select="usersname"/></td>
                    </tr>                                   
                </xsl:for-each-group>
            </table>
        </xsl:for-each-group>
    </xsl:for-each-group>
</xsl:template>
person Martin Honnen    schedule 27.02.2017
comment
Спасибо, Мартин, это полностью сделало то, что я искал. Это многоуровневое применение ключа, которое я просто не понимал, но теперь вижу его гораздо больше. Хотел бы я сделать V2, но Microsoft держит меня за выкуп в Visual Studio, и я не собираюсь вносить изменения в другой движок, поскольку потенциальные изменения во всем приложении не гарантируются. - person Peter S; 01.03.2017