I'm looking for a way to split an XML file into multiple HTML files which in the end, should contain a table.
An example xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<table>
<row>
<name>user1</name>
<email>email1</email>
</row>
<row>
<name>user2</name>
<email>email2</email>
</row>
<row>
<name>user3</name>
<email>email3</email>
</row>
<row>
<name>user4</name>
<email>email4</email>
</row>
<row>
<name>user5</name>
<email>email5</email>
</row>
...
</table>
Now I want to split this xml file into different HTML files which contain a specific range from the XML file. Each HTML file should contain 3 rows from the XML for example.
table1.html
<table>
<tr>
<td>user1</td>
<td>email1</td>
</tr>
<tr>
<td>user2</td>
<td>email2</td>
</tr>
<tr>
<td>user3</td>
<td>email3</td>
</tr>
</table>
table2.html
<table>
<tr>
<td>user4</td>
<td>email4</td>
</tr>
<tr>
<td>user5</td>
<td>email5</td>
</tr>
<tr>
<td>user6</td>
<td>email6</td>
</tr>
</table>
Anyone an idea how the XSLT file needs to be formatted? I'm using ruby-xslt to load the XML and XSLT file and convert the whole thing to HTML.
If you apply this XSLT to your input XML it will split the XML into tables containing 3 records:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" method="xml"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- split file up into row elements -->
<xsl:template match="row[position() mod 3 = 1]">
<table>
<xsl:copy-of select=".|following-sibling::row[not(position() > 2)]"/>
</table>
</xsl:template>
<xsl:template match="row"/>
</xsl:stylesheet>
OUTPUT XML:
<?xml version="1.0" encoding="UTF-8"?>
<table>
<table>
<row>
<name>user1</name>
<email>email1</email>
</row>
<row>
<name>user2</name>
<email>email2</email>
</row>
<row>
<name>user3</name>
<email>email3</email>
</row>
</table>
<table>
<row>
<name>user4</name>
<email>email4</email>
</row>
<row>
<name>user5</name>
<email>email5</email>
</row>
</table>
</table>
If you run the OUTPUT XML through this XSLT you will get the wanted result:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="row">
<tr>
<xsl:apply-templates select="node()|@*"/>
</tr>
</xsl:template>
<xsl:template match="email | name">
<td>
<xsl:apply-templates select="node()|@*"/>
</td>
</xsl:template>
</xsl:stylesheet>
final OUTPUT XML:
<?xml version="1.0" encoding="UTF-8"?><table>
<table>
<tr>
<td>user1</td>
<td>email1</td>
</tr>
<tr>
<td>user2</td>
<td>email2</td>
</tr>
<tr>
<td>user3</td>
<td>email3</td>
</tr>
</table>
<table>
<tr>
<td>user4</td>
<td>email4</td>
</tr>
<tr>
<td>user5</td>
<td>email5</td>
</tr>
</table>
</table>
In my opinion this should work with XSLT 1.0 as long as you have the opportunity to run 2 stylesheets on your input XML.
Best regards,
Peter
To create multiple HTML files in a single XSLT transformation you will need the xsl:result-document instruction, which is only available in XSLT 2.0. You don't get that with ruby-xslt unfortunately.
An XSLT 1.0 transformation can create only a single output.
You may still have a single result that contains all the generated tables. Then you need to process this result outside XSLT (or perform N transformations on it) in order to produce the N separate outputs needed.
I strongly recommend that you use XSLT 2.0 for this task -- this can easily be accomplished using the new xsl:result-document
instruction.