Sergio
Sergio

Reputation: 197

XLST: create multiple tables

i'm trying to use a for-each statement to create a table for each element "bill". The XML document is the following:

<group>
  <name>Casa Miles</name>
    <student>
      <id>sergio</id>
      <name>sergio</name>
      <surname>zavota</surname>
      <bill>
        <product>
          <name>sapone piatti</name>
          <amount>1</amount>
          <prize>3.3</prize>
          <participant>
            <id>stefano</id>
          </participant>
        </product>
        <product>
          <name>bresaola</name>
          <amount>1</amount>
          <prize>5.5</prize>
          <participant>
            <id>sergio</id>
          </participant>
        </product>
        <date>2020-02-03</date>
      </bill>
    </student>

    <student>
      <id>stefano</id>
      <name>stefano</name>
      <surname>silvestri</surname>
        <bill>
          <product>
            <name>liquore</name>
            <amount>2</amount>
            <prize>5.00</prize>
            <participant>
              <id>stefano</id>
            </participant>
          </product>
          <product>
            <name>coniglio</name>
            <amount>1</amount>
            <prize>4.5</prize>
            <participant>
              <id>stefano</id>
            </participant>
          </product>
          <date>2020-03-03</date>
        </bill>
      </student>
    </group>

I tried to use Muenchian grouping, but instead of getting two table (one for each date/bill), i get just one table with the date of the first bill (from top to down of the XML document) and two rows, one for each of the first product of each bill, as shown in this image.

https://ibb.co/TbK23JG

The XSLT doc is the following:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:key name="tableByBillDate" match="bill" use="date" />

<xsl:template match="/">
  <html>
    <head>
      <title>HTML Document</title>
    </head>

    <style>
        table {
          font-family: arial, sans-serif;
          border-collapse: collapse;
          width: 100%;
        }

        td, th {
          border: 1px solid #dddddd;
          text-align: left;
          padding: 8px;
        }

        tr:nth-child(even) {
            background-color: #dddddd;
        }   

        caption {
          display: table-caption;
          text-align: center;
        }
    </style>

    <body>

      <h3>Welcome<xsl:value-of select="group/student/name"/></h3>
      <h3>Group: <xsl:value-of select="group/name"/> </h3>
      <h3>Bills</h3>

      <xsl:for-each select="group/student/bill[generate-id() = generate                               
      id(key('tableByBillDate',date)[1])]">

        <table>
          <caption style="font-weight: bold;">Date: <xsl:value-of select="date"/></caption>

          <tr>
            <th>Name</th> 
            <th>Amount</th>
            <th>Cost</th>
            <th>Total</th>
           <th>Participants</th>        
          </tr>

          <xsl:for-each select="key('tableByBillDate',date)">
          <xsl:sort select="date" order="descending"/> 
            <tr>
              <td><xsl:value-of select="product/name"/></td>
              <td><xsl:value-of select="product/amount"/></td>
              <td><xsl:value-of select="product/prize"/></td>
              <td>Calculated with Javascript</td>
              <td><xsl:value-of select="product/participant"/></td>   
           </tr>
         </xsl:for-each>
        </table>
      </xsl:for-each>
    </body>
  </html>
</xsl:template>
</xsl:stylesheet>

Upvotes: 0

Views: 485

Answers (2)

Rahul Jawa
Rahul Jawa

Reputation: 34

Please find the correct following:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:strip-space elements="yes"/>
    <xsl:key name="tableByBillDate" match="bill" use="date" />

    <xsl:template match="/">
        <html>
            <head>
                <title>HTML Document</title>
            </head>

            <style>
                table {
                font-family: arial, sans-serif;
                border-collapse: collapse;
                width: 100%;
                }

                td, th {
                border: 1px solid #dddddd;
                text-align: left;
                padding: 8px;
                }

                tr:nth-child(even) {
                background-color: #dddddd;
                }   

                caption {
                display: table-caption;
                text-align: center;
                }
            </style>

            <body>

                <h3 align="center">Welcome: <xsl:value-of select="group/student/name"/></h3>
                <h3 align="center">Group: <xsl:value-of select="group/name"/> </h3>
                <h3 align="center">Bills</h3>

                <xsl:for-each select="group/student/bill[generate-id()= generate-id(key('tableByBillDate',date)[1])]">

                    <table>
                        <caption style="font-weight: bold;">Date: <xsl:value-of select="date"/></caption>

                        <tr>
                            <th>Name</th> 
                            <th>Amount</th>
                            <th>Cost</th>
                            <th>Total</th>
                            <th>Participants</th>        
                        </tr>

                        <xsl:for-each select="key('tableByBillDate',date)">
                            <xsl:sort select="date" order="descending"/> 
                            <tr>
                                <td><xsl:value-of select="product/name"/></td>
                                <td><xsl:value-of select="product/amount"/></td>
                                <td><xsl:value-of select="product/prize"/></td>
                                <td>Calculated with Javascript</td>
                                <td><xsl:value-of select="product/participant"/></td>   
                            </tr>
                        </xsl:for-each>
                    </table>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/gVhDDyA/5

Upvotes: 2

Martin Honnen
Martin Honnen

Reputation: 167696

I also think your used key should give you two tables with the sample data you have show, as you have two different dates; if you want to output all product data in each table then process all products in a "group":

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="html" indent="yes" version="5" doctype-system="about:legacy-doctype"/>

  <xsl:key name="tableByBillDate" match="bill" use="date" />

  <xsl:template match="group">
      <xsl:apply-templates select="student/bill[generate-id() = generate-id(key('tableByBillDate', date)[1])]">
          <xsl:sort select="date"/>
      </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="bill">
   <table>
     <caption style="font-weight: bold;">Date: <xsl:value-of select="date"/></caption>
     <thead>
      <tr>
        <th>Name</th> 
        <th>Amount</th>
        <th>Cost</th>
        <th>Total</th>
        <th>Participants</th>        
      </tr>             
     </thead>
     <tbody>
       <xsl:apply-templates select="key('tableByBillDate',date)/product"/>
     </tbody>
    </table>      
  </xsl:template>

  <xsl:template match="product">
            <tr>
              <td><xsl:value-of select="name"/></td>
              <td><xsl:value-of select="amount"/></td>
              <td><xsl:value-of select="prize"/></td>
              <td>Calculated with Javascript</td>
              <td><xsl:value-of select="participant"/></td>   
           </tr>      
  </xsl:template>


  <xsl:template match="/">
    <html>
      <head>
        <title>.NET XSLT Fiddle Example</title>
            <style>
        table {
          font-family: arial, sans-serif;
          border-collapse: collapse;
          width: 100%;
        }

        td, th {
          border: 1px solid #dddddd;
          text-align: left;
          padding: 8px;
        }

        tr:nth-child(even) {
            background-color: #dddddd;
        }   

        caption {
          display: table-caption;
          text-align: center;
        }
    </style>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/3MvmXis

Upvotes: 2

Related Questions