kbodh
kbodh

Reputation: 21

XML Grouping to add data in the table

I have xml data from the database. These are the events happening on certain days of the week. There may be a single or multiple events on a particular day.

I need to display events information in a table arranged by the day. Like Monday as heading then a table with event information Then Tuesday as heading and then 2 entries in Tuesday's table.

I realised I may need grouping based on the Weekday. I have not much experience of xslt. How do we go about it? Browsers do not support xslt 2.0 so I have to use xsl 1.0 . I have to parse the xml and display it as html.

<Events>
    <Event>
    <ActivityTypeName>Lab</ActivityTypeName>
    <WeekDay>Wednesday</WeekDay>
    <LocalDate>01/04/20</LocalDate>
    <Location>Eng. G29 Wet Lab</Location>
  </Event>
  <Event>
    <ActivityName>MAT427-MTRM061-DEN7601-DENM601-DENM600-DEN7600/B/Lec/02 [jt]</ActivityName>
    <ActivityTypeName>Lecture</ActivityTypeName>
    <WeekDay>Wednesday</WeekDay>  
     <LocalDate>02/04/20</LocalDate>
    <Location>Eng:2.16(42)</Location>
  </Event>
  <Event>
    <ActivityTypeName>Lecture</ActivityTypeName>
    <WeekDay>Thursday</WeekDay>
    <LocalDate>02/04/20</LocalDate>
    <Location>Eng:2.16(42)</Location>
  </Event>
  <Event>
    <ActivityTypeName>Seminar</ActivityTypeName>
    <WeekDay>Friday</WeekDay>
    <LocalDate>03/04/20</LocalDate>
    <Location>Graduate Ctr: GC102 (19)</Location>
  </Event>

Upvotes: 0

Views: 160

Answers (1)

klaus triendl
klaus triendl

Reputation: 1369

Let's concentrate on the xsl stylesheet, irrespective of where and how you apply it.

Presuming that your events are streamed in weekday and date order, I would create a key over the first event of succeeding events on a weekday. This approach allows us to easily iterate over those 'first' events and create independent tables.

<?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"/>

    <!-- index first of sequentially occurring Event elements by WeekDay -->
    <xsl:key name="firstof_weekday_key" match="/Events/Event[(position() = 1) or (WeekDay != preceding-sibling::Event[1]/WeekDay)]" use="WeekDay"/>

    <xsl:template match="/Events">
        <html>
            <head>
                <style type="text/css">
                    .Table
                    {
                    display: table;
                    }
                    .Caption
                    {
                    display: table-caption;
                    text-align: center;
                    font-weight: bold;
                    font-size: larger;
                    }
                    .THead
                    {
                    display: table-header-group;
                    }
                    .TBody
                    {
                    display: table-row-group;
                    }
                    .Heading
                    {
                    display: table-row;
                    font-weight: bold;
                    text-align: center;
                    }
                    .Row
                    {
                    display: table-row;
                    }
                    .Cell
                    {
                    display: table-cell;
                    border: solid;
                    border-width: thin;
                    padding-left: 5px;
                    padding-right: 5px;
                    }
                </style>
            </head>
            <body>
                <!-- select first Event of WeekDay (which is included in the key) -->
                <xsl:apply-templates select="Event[count(. | key('firstof_weekday_key', WeekDay)) = count(key('firstof_weekday_key', WeekDay))]" mode="first"/>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="/Events/Event" mode="first">
        <div class="Table">
            <div class="Caption">
                <xsl:value-of select="WeekDay"/>
            </div>
            <div class="THead">
                <div class="Heading">
                    <div class="Cell">
                        <xsl:value-of select="'Activity'"/>
                    </div>
                    <div class="Cell">
                        <xsl:value-of select="'Location'"/>
                    </div>
                    <div class="Cell">
                        <xsl:value-of select="'Date'"/>
                    </div>
                </div>
            </div>
            <div class="TBody">
                <xsl:apply-templates select="." mode="data"/>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="/Events/Event" mode="data">
        <div class="Row">
            <div class="Cell">
                <xsl:value-of select="ActivityTypeName"/>
            </div>
            <div class="Cell">
                <xsl:value-of select="Location"/>
            </div>
            <div class="Cell">
                <xsl:value-of select="LocalDate"/>
            </div>
        </div>
    
        <!-- get the next Event in the current WeekDay group -->
        <xsl:apply-templates select="following-sibling::Event[1][WeekDay = current()/WeekDay]" mode="data"/>
    </xsl:template>
</xsl:stylesheet>

This xslt will transform your events into the following html:

<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style type="text/css">
                    .Table
                    {
                    display: table;
                    }
                    .Caption
                    {
                    display: table-caption;
                    text-align: center;
                    font-weight: bold;
                    font-size: larger;
                    }
                    .THead
                    {
                    display: table-header-group;
                    }
                    .TBody
                    {
                    display: table-row-group;
                    }
                    .Heading
                    {
                    display: table-row;
                    font-weight: bold;
                    text-align: center;
                    }
                    .Row
                    {
                    display: table-row;
                    }
                    .Cell
                    {
                    display: table-cell;
                    border: solid;
                    border-width: thin;
                    padding-left: 5px;
                    padding-right: 5px;
                    }
                </style>
  </head>
  <body>
    <div class="Table">
      <div class="Caption">Wednesday</div>
      <div class="THead">
        <div class="Heading">
          <div class="Cell">Activity</div>
          <div class="Cell">Location</div>
          <div class="Cell">Date</div>
        </div>
      </div>
      <div class="TBody">
        <div class="Row">
          <div class="Cell">Lab</div>
          <div class="Cell">Eng. G29 Wet Lab</div>
          <div class="Cell">01/04/20</div>
        </div>
        <div class="Row">
          <div class="Cell">Lecture</div>
          <div class="Cell">Eng:2.16(42)</div>
          <div class="Cell">02/04/20</div>
        </div>
      </div>
    </div>
    <div class="Table">
      <div class="Caption">Thursday</div>
      <div class="THead">
        <div class="Heading">
          <div class="Cell">Activity</div>
          <div class="Cell">Location</div>
          <div class="Cell">Date</div>
        </div>
      </div>
      <div class="TBody">
        <div class="Row">
          <div class="Cell">Lecture</div>
          <div class="Cell">Eng:2.16(42)</div>
          <div class="Cell">02/04/20</div>
        </div>
      </div>
    </div>
    <div class="Table">
      <div class="Caption">Friday</div>
      <div class="THead">
        <div class="Heading">
          <div class="Cell">Activity</div>
          <div class="Cell">Location</div>
          <div class="Cell">Date</div>
        </div>
      </div>
      <div class="TBody">
        <div class="Row">
          <div class="Cell">Seminar</div>
          <div class="Cell">Graduate Ctr: GC102 (19)</div>
          <div class="Cell">03/04/20</div>
        </div>
      </div>
    </div>
  </body>
</html>

Upvotes: 1

Related Questions