Xslt: How can I use xslt to create a table with multiple columns and rows?

How can I take this xml and create a table with a column for each "section" element, and then display all the "document" elements in this column using xslt?

<Documents>
  <Section>
  <SectionName>Green</SectionName>
    <Document>
      <FileName>Tier 1 Schedules</FileName>     
    </Document>
    <Document>
      <FileName>Tier 3 Schedules</FileName>      
    </Document>
    <Document>
      <FileName>Setback Schedule</FileName>    
    </Document>
    <Document>
      <FileName>Tier 2 Governance</FileName>    
    </Document>
 </Section>
 <Section>
 <SectionName>MRO/Refurb</SectionName>
   <Document>
     <FileName>Tier 2 Governance</FileName>    
   </Document>
 </Section>

Thanks Al

+3
source share
2 answers

This is one of the possible solutions:

<xsl:variable name="vCountRows">
  <xsl:apply-templates select="Documents/Section[1]" mode="findmax" />
</xsl:variable>

<xsl:variable name="vCountCols" select="count(Documents/Section)" />

<xsl:template match="/Documents">
  <table r="{$vCountRows}" s="{$vCountCols}">
    <thead>
      <xsl:call-template name="create-thead" />
    </thead>
    <tbody>
      <xsl:call-template name="create-tr" />
    </tbody>
  </table>
</xsl:template>

<xsl:template name="create-thead">
   <tr>
    <xsl:apply-templates select="Section" />
  </tr>    
</xsl:template>

<xsl:template match="Section">
  <th><xsl:value-of select="SectionName" /></th>
</xsl:template>

<xsl:template name="create-tr">
  <xsl:param name="row" select="1" />

  <tr>
    <xsl:call-template name="create-td">
      <xsl:with-param name="row" select="$row" />
    </xsl:call-template>
  </tr>

  <xsl:if test="$row &lt; $vCountRows">
    <xsl:call-template name="create-tr">
      <xsl:with-param name="row" select="$row + 1" />
    </xsl:call-template>
  </xsl:if>

</xsl:template>

<xsl:template name="create-td">
  <xsl:param name="col" select="1" />
  <xsl:param name="row" select="1" />

  <td>
    <xsl:value-of select="Section[$col]/Document[$row]/FileName" />
  </td>

  <xsl:if test="$col &lt; $vCountCols">
    <xsl:call-template name="create-td">
      <xsl:with-param name="col" select="$col + 1" />
      <xsl:with-param name="row" select="$row" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

<xsl:template match="Section" mode="findmax">
  <xsl:variable name="c" select="count(Document)" />
  <xsl:variable name="next" select="following-sibling::Section[count(Document) &gt; $c][1]" />

  <xsl:choose>    
    <xsl:when test="$next">
      <xsl:apply-templates select="$next" mode="findmax" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$c" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

With your input, it produces:

<table>
  <thead>
    <tr>
      <td>Green</td>
      <td>MRO/Refurb</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tier 1 Schedules</td>
      <td>Tier 2 Governance</td>
    </tr>
    <tr>
      <td>Tier 3 Schedules</td>
      <td></td>
    </tr>
    <tr>
      <td>Setback Schedule</td>
      <td></td>
    </tr>
    <tr>
      <td>Tier 2 Governance</td>
      <td></td>
    </tr>
  </tbody>
</table>

The general approach is as follows:

  • Find out how many rows we are going to get (this happens in <xsl:template match="Section" mode="findmax">which recursively finds the section with the maximum number of nodes<Document>
  • Find out how many columns we are going to get (by counting the number <Section>s)
  • , <tr>, , .
  • , <td> s. , ( 2).

:

  • ( XSLT)

(, <xsl:key> s) , .

+1

hi-lights XSLT, Muenchian, , .

:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:strip-space elements="*"/>

    <xsl:key name="kSectsByValue" match="SectionName"
         use="."/>

    <xsl:key name="kDocBySect" match="Document"
         use="../SectionName"/>

    <xsl:variable name="vCols" select=
       "/*/*/SectionName
                [generate-id()
                =          
                 generate-id(key('kSectsByValue',.)[1])
                 ]"/>

    <xsl:variable name="vMaxRows">
             <xsl:for-each select="$vCols">
               <xsl:sort data-type="number" order="descending"
                    select="count(key('kDocBySect', .))"      />
               <xsl:if test="position() = 1">
                 <xsl:value-of select="count(key('kDocBySect', .))"/>
               </xsl:if>
             </xsl:for-each>
    </xsl:variable>

    <xsl:template match="/">
             <table>
               <tr>
                 <xsl:apply-templates select="$vCols"/>
               </tr>

               <xsl:for-each select=
                 "(/*/*/Document)[not(position() > $vMaxRows)]">                   
                 <tr>

                   <xsl:variable name="vPos" select="position()"/>

                   <xsl:for-each select="$vCols">
                     <td>
                       <xsl:value-of select=
                           "../Document[$vPos]/FileName"/>
                     </td>
                   </xsl:for-each>

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

    </xsl:template>

    <xsl:template match="SectionName">
            <td>
              <xsl:value-of select="." />
            </td>   
    </xsl:template>
</xsl:stylesheet>

, XML- (, ):

<Documents>
    <Section>
        <SectionName>Green</SectionName>
        <Document>
            <FileName>Tier 1 Schedules</FileName>
        </Document>
        <Document>
            <FileName>Tier 3 Schedules</FileName>
        </Document>
        <Document>
            <FileName>Setback Schedule</FileName>
        </Document>
        <Document>
            <FileName>Tier 2 Governance</FileName>
        </Document>
    </Section>
    <Section>
        <SectionName>MRO/Refurb</SectionName>
        <Document>
            <FileName>Tier 2 Governance</FileName>
        </Document>
    </Section>
</Documents>

:

<table>
   <tr>
      <td>Green</td>
      <td>MRO/Refurb</td>
   </tr>
   <tr>
      <td>Tier 1 Schedules</td>
      <td>Tier 2 Governance</td>
   </tr>
   <tr>
      <td>Tier 3 Schedules</td>
      <td/>
   </tr>
   <tr>
      <td>Setback Schedule</td>
      <td/>
   </tr>
   <tr>
      <td>Tier 2 Governance</td>
      <td/>
   </tr>
</table>

:

  • Muenchian , , , XML .

  • Muenchian, , .

  • $vMaxRows

  • N , N - , !

  • N -th , N .

+3

Source: https://habr.com/ru/post/1706733/


All Articles