XSLT 1 как группировать по 2 элементам - PullRequest
0 голосов
/ 08 апреля 2020

У меня проблемы с группировкой xml с использованием 2 элементов. Хотя это легко сделать с помощью версии 2.0, я ограничен xslt 1.0: (.

Чего я хочу добиться, так это получить только студентов со статистическим кодом = 1, а затем сгруппировать их по gradeId, так что в конце концов я иметь сумму посещаемости для каждого названия курса:

|---------------------|------------------|
|      CourseName     |     Attendance   |
|---------------------|------------------|
|          Bio        |         17       |
|---------------------|------------------|
|          Math       |         31       |
|---------------------|------------------|

Вот xml, с которыми я работаю:

 <Student>
      <statisticsCode>-1</statisticsCode>
      <attendance>15</attendance>
      <groupid>1</groupid>
      <statisticsCode>3</statisticsCode>
      <Grade>
        <gradeId>1</gradeId>
        <uidObjectID>00010004-0000-0000-0000-000000000031</uidObjectID>
        <CourseName>Science</CourseName>
      </Grade>
    </Student>
    <Student>
      <statisticsCode>-1</statisticsCode>
      <attendance>31</attendance>
      <groupid>1</groupid>
      <statisticsCode>1</statisticsCode>
      <Grade>
        <gradeId>1</gradeId>
        <uidObjectID>00010004-0000-0000-0000-000000000031</uidObjectID>
        <CourseName>Math</CourseName>
      </Grade>
    </Student>
    <Student>
      <statisticsCode>-1</statisticsCode>
      <attendance>14</attendance>
      <groupid>1</groupid>
      <statisticsCode>1</statisticsCode>
      <Grade>
        <gradeId>2</gradeId>
        <uidObjectID>00010004-0000-0000-0000-000000000031</uidObjectID>
        <CourseName>Bio</CourseName>
      </Grade>
    </Student>
    <Student>
      <statisticsCode>-1</statisticsCode>
      <attendance>3</attendance>
      <groupid>1</groupid>
      <statisticsCode>1</statisticsCode>
      <Grade>
        <gradeId>2</gradeId>
        <uidObjectID>00010004-0000-0000-0000-000000000031</uidObjectID>
        <CourseName>Bio</CourseName>
      </Grade>
    </Student>  

1 Ответ

0 голосов
/ 09 апреля 2020

Следующая таблица стилей должна сделать эту работу. Он имеет два настраиваемых параметра:

  1. statisticsCode-match
  2. gradeId-match

В настоящее время значения тезисов установлены на 1, поэтому студенты будут быть отфильтрованы в соответствии с вашим запросом, и в текущей настройке будет суммироваться только посещаемость учеников 1-го класса.

Надеюсь, это поможет; -)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" exclude-result-prefixes="xd" version="1.0">
    <xd:doc scope="stylesheet">
        <xd:desc>
            <xd:p><xd:b>Created on:</xd:b> Apr 9, 2020</xd:p>
            <xd:p><xd:b>Author:</xd:b> bwb</xd:p>
            <xd:p/>
        </xd:desc>
    </xd:doc>
    <xsl:output method="text"/>
    <xsl:param name="statisticsCode-match">1</xsl:param>
    <xsl:variable name="line-divider">
        <xsl:text>|--------------------|--------------------|</xsl:text>
    </xsl:variable>
    <xsl:variable name="break">
        <xsl:text>&#xa;</xsl:text>
    </xsl:variable>
    <xsl:variable name="students.filtered">
        <xsl:for-each select="//Student[statisticsCode = $statisticsCode-match]">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="coursenames.distinct">
        <xsl:for-each select="//Student[statisticsCode = $statisticsCode-match]//CourseName">
            <xsl:choose>
                <xsl:when test=". = preceding::CourseName"/>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="twenty-whitespaces">
        <xsl:text>                    </xsl:text>
    </xsl:variable>
    <xsl:template match="/">
        <xsl:value-of select="$break"/>
        <xsl:text>statisticsCode: </xsl:text>
        <xsl:value-of select="$statisticsCode-match"/>
        <xsl:value-of select="$break"/>
        <xsl:value-of select="$line-divider"/>
        <xsl:value-of select="$break"/>
        <xsl:text>|     CourseName     |     Attendance     |</xsl:text>
        <xsl:value-of select="$break"/>
        <xsl:value-of select="$line-divider"/>
        <xsl:for-each select="//Student[statisticsCode = $statisticsCode-match]//CourseName">
            <xsl:choose>
                <xsl:when test=". = preceding::CourseName"/>
                <xsl:otherwise>
                    <!-- course name -->
                    <xsl:variable name="padding.course" select="substring($twenty-whitespaces, 1, floor((20 - string-length(.)) div 2))"/>
                    <xsl:value-of select="$break"/>
                    <xsl:text>|</xsl:text>
                    <xsl:value-of select="$padding.course"/>
                    <xsl:value-of select="."/>
                    <xsl:value-of select="$padding.course"/>
                    <xsl:if test="string-length(.) mod 2 = 1">
                        <xsl:text> </xsl:text>
                    </xsl:if>
                    <!-- end course name -->
                    <xsl:text>|</xsl:text>
                    <!-- attendance -->
                    <xsl:variable name="attendance.count" select="sum(//Student[statisticsCode = $statisticsCode-match][Grade[CourseName = current()]]/attendance)"/>
                    <xsl:variable name="padding.attendance" select="substring($twenty-whitespaces, 1, floor((20 - string-length($attendance.count)) div 2))"/>
                    <xsl:value-of select="$padding.attendance"/>
                    <xsl:value-of select="$attendance.count"/>
                    <xsl:value-of select="$padding.attendance"/>
                    <xsl:if test="string-length($attendance.count) mod 2 = 1">
                        <xsl:text> </xsl:text>
                    </xsl:if>
                    <!-- end attendance -->
                    <xsl:text>|</xsl:text>
                    <!-- table divider -->
                    <xsl:value-of select="$break"/>
                    <xsl:value-of select="$line-divider"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
...