schultz
schultz

Reputation: 316

How do I use xslt to generate many table with one set of data?

I have the following XML

    <ArrayOfOperatorStation>
     <OperatorStation>
        <Name>OS1</Name>
        <OS>Microsoft Windows XP Professional</OS>
        <IP>172.20.254.90</IP>
        <Version>5.1.2600</Version>
        <Alive>true</Alive>
        <Files>
          <FileComparison>
            <Filename>C:\file1.txt</Filename>
            <Hash>82c7aa19c690bb41e91c6b71d22bb533</Hash>
          </FileComparison>
          <FileComparison>
            <Filename>C:\file3.txt</Filename>
            <Hash>82c7aa19c690bb41e91c6b71d22bb533</Hash>
          </FileComparison>
        </Files>
    </OperatorStation>
    <OperatorStation>
        <Name>OS2</Name>
        <OS>Microsoft Windows XP Professional</OS>
        <IP>172.20.254.91</IP>
        <Version>5.1.2600</Version>
        <Alive>true</Alive>
        <Files>
          <FileComparison>
            <Filename>C:\file1.txt</Filename>
            <Hash>82c7aa19c690bb41e91c6b71d22bb533</Hash>
          </FileComparison>
          <FileComparison>
            <Filename>C:\file2.txt</Filename>
            <Hash>82c7aa19c690bb41e91c6b71d22bb533</Hash>
          </FileComparison>
        </Files>
  </OperatorStation>
</ArrayOfOperatorStation>

and would like to generate to diffent tables of this data in the final html result.

Operator staion
----------------
OS1     |  OS2
Alive   |  Alive

and another one with a filelist
OS1    | OS2    | etc...
---------------------------
File1  | File1
File3  | File2

I have trouble making the second list, i have no idea how to begin. with the "query" at all.

Upvotes: 0

Views: 84

Answers (1)

hr_117
hr_117

Reputation: 9627

Here are solution for your second table. Which also considers the possibility that the amount of files for OperatorStation could differ.

Try something like this:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*" />
    <xsl:output method="xml" indent="yes"/>

    <xsl:key name="kOperatorStationFiles" match="FileComparison"  use="../preceding-sibling::OperatorStation[1]/Name" />

    <xsl:template match="OperatorStation" mode="files">
        <xsl:param name="fileNr" />
        <td>
            <xsl:value-of select="key('kOperatorStationFiles', Name)[$fileNr]/Filename"/>
        </td>
    </xsl:template>

    <xsl:template match="OperatorStation" mode="header">
        <td>
            <xsl:value-of select="Name"/>
        </td>
    </xsl:template>

    <xsl:template match="/">
        <table>
            <tr>
                <xsl:apply-templates select="//OperatorStation" mode="header"/>
            </tr>
            <!-- find max files -->
            <xsl:for-each select="//OperatorStation" >
                <xsl:sort select="count(key('kOperatorStationFiles', Name))" order="descending" />
                <xsl:if test="position()=1">
                    <xsl:for-each select="key('kOperatorStationFiles', Name)" >
                        <tr>
                        <xsl:apply-templates select="//OperatorStation" mode="files">
                            <xsl:with-param name="fileNr" select="position()" />
                        </xsl:apply-templates>
                        </tr>
                    </xsl:for-each>
                </xsl:if>
            </xsl:for-each>
        </table>
    </xsl:template>
</xsl:stylesheet>

With this (changed) input:

<?xml version="1.0" encoding="UTF-8"?>
<ArrayOfOperatorStation>
    <OperatorStation>
        <Name>OS1</Name>
        <OS>Microsoft Windows XP Professional</OS>
        <IP>172.20.254.90</IP>
        <Version>5.1.2600</Version>
        <Alive>true</Alive>
    </OperatorStation>
    <Files>
        <FileComparison>
            <Filename>C:\file1.txt</Filename>
            <Hash>82c7aa19c690bb41e91c6b71d22bb533</Hash>
        </FileComparison>
        <FileComparison>
            <Filename>C:\file3.txt</Filename>
            <Hash>82c7aa19c690bb41e91c6b71d22bb533</Hash>
        </FileComparison>
    </Files>

    <OperatorStation>
        <Name>OS2</Name>
        <OS>Microsoft Windows XP Professional</OS>
        <IP>172.20.254.91</IP>
        <Version>5.1.2600</Version>
        <Alive>true</Alive>
    </OperatorStation>
    <Files>
        <FileComparison>
            <Filename>C:\file1.txt</Filename>
            <Hash>82c7aa19c690bb41e91c6b71d22bb533</Hash>
        </FileComparison>
        <FileComparison>
            <Filename>C:\file2.txt</Filename>
            <Hash>82c7aa19c690bb41e91c6b71d22bb533</Hash>
        </FileComparison>
        <FileComparison>
            <Filename>C:\file471.txt</Filename>
            <Hash>82c7aa19c690bb41e91c6b71d22bb533</Hash>
        </FileComparison>

    </Files>
</ArrayOfOperatorStation>

It generates the following output:

<?xml version="1.0"?>
<table>
  <tr>
    <td>OS1</td>
    <td>OS2</td>
  </tr>
  <tr>
    <td>C:\file1.txt</td>
    <td>C:\file1.txt</td>
  </tr>
  <tr>
    <td>C:\file3.txt</td>
    <td>C:\file2.txt</td>
  </tr>
  <tr>
    <td/>
    <td>C:\file471.txt</td>
  </tr>
</table>

Update: Because of comment "The files have to be included in the -parent." Some small changes will do:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*" />
    <xsl:output method="xml" indent="yes"/>

    <xsl:key name="kOperatorStationFiles" match="FileComparison"  use="ancestor::OperatorStation/Name" />

    <xsl:template match="OperatorStation" mode="files">
        <xsl:param name="fileNr" />
        <td>
            <xsl:value-of select="key('kOperatorStationFiles', Name)[$fileNr]/Filename"/>
        </td>

    </xsl:template>

    <xsl:template match="OperatorStation" mode="header">
        <td>
            <xsl:value-of select="Name"/>
        </td>
    </xsl:template>

    <xsl:template match="/*">
        <table>
            <tr>
                <xsl:apply-templates select="/*/OperatorStation" mode="header"/>

            </tr>
            <!-- find max files -->
            <xsl:for-each select="/*/OperatorStation" >
                <xsl:sort select="count(key('kOperatorStationFiles', Name))" order="descending" />
                <xsl:if test="position()=1">
                    <xsl:for-each select="key('kOperatorStationFiles', Name)" >
                        <tr>
                        <xsl:apply-templates select="/*/OperatorStation" mode="files">
                            <xsl:with-param name="fileNr" select="position()" />
                        </xsl:apply-templates>
                        </tr>
                    </xsl:for-each>

                </xsl:if>
            </xsl:for-each>
        </table>
    </xsl:template>

</xsl:stylesheet>

Upvotes: 1

Related Questions