Reputation: 369
I have xml with the following data.
<Rows>
<Header>
<sourcetable>Table_1</sourcetable>
<targettable>Table_2</targettable>
</Header>
<Table>
<Source_Fieldname>DTIME_INSERTED</Source_Fieldname>
<Source_Type>Timestamp</Source_Type>
<Source_Fieldname>ID_JOB</Source_Fieldname>
<Source_Type>String</Source_Type>
</Table>
<Header>
<sourcetable>Table_3</sourcetable>
<targettable>Table_4</targettable>
</Header>
<Table>
<Source_Fieldname>DTIME_INSERTED</Source_Fieldname>
<Source_Type>Timestamp</Source_Type>
<Source_Fieldname>ID_JOB</Source_Fieldname>
<Source_Type>String</Source_Type>
</Table>
</Rows>
I am trying to output this into separate tables per "Table" element just like this but can't figure it out since there are multiple elements with the same name.
So far this is what I got.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />
<xsl:template match="Row">
<table border="1px" cellpadding="3" cellspacing="1" style='font-family:"Calibri"; font-size:12; font-weight:"normal"' >
<tr align="center">
<xsl:for-each select="preceding-sibling::Header[1]">
<th colspan="4" bgcolor="#ccffff">
<font size="2" face="Calibri" style="text-transform:uppercase"> <xsl:value-of select="sourcetable" /> </font>
</th>
<th colspan="4" bgcolor="#ccffff">
<font size="2" face="Calibri" style="text-transform:uppercase"> <xsl:value-of select="targettable" /> </font>
</th>
</xsl:for-each>
<th bgcolor="#FFCCBC" rowspan="2">Flagfield</th>
</tr>
<tr align="left">
<td bgcolor="#C5E1A5">Source_Fieldname</td>
<td bgcolor="#C5E1A5">Source_Type</td>
</tr>
<xsl:for-each select=".">
<tr>
<xsl:for-each select="Source_Fieldname">
<td> <xsl:value-of select="."/> </td>
</xsl:for-each>
<xsl:for-each select="Source_Type">
<td> <xsl:value-of select="."/> </td>
</xsl:for-each>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
<br /><br/>
</xsl:template>
</xsl:stylesheet>
Any suggestion how to achieve desired output is appreciated. Thanks!
Upvotes: 0
Views: 894
Reputation: 2714
You had a good start but a few details were not working. Here's how I would solve it.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />
<xsl:template match="/">
<html>
<head/>
<body>
<xsl:apply-templates select="Rows/Table"/>
</body>
</html>
</xsl:template>
<xsl:template match="Table">
<table border="1px" cellpadding="3" cellspacing="1" style='font-family:"Calibri"; font-size:12; font-weight:"normal"' >
<tr align="center">
<th bgcolor="#ccffff">
<font size="2" face="Calibri" style="text-transform:uppercase"> <xsl:value-of select="preceding-sibling::Header[1]/sourcetable" /> </font>
</th>
<th bgcolor="#ccffff">
<font size="2" face="Calibri" style="text-transform:uppercase"> <xsl:value-of select="preceding-sibling::Header[1]/targettable" /> </font>
</th>
</tr>
<tr align="left">
<td bgcolor="#C5E1A5">Source_Fieldname</td>
<td bgcolor="#C5E1A5">Source_Type</td>
</tr>
<xsl:apply-templates select="Source_Fieldname"/>
</table>
<br/><br/>
</xsl:template>
<xsl:template match="Source_Fieldname">
<tr>
<td> <xsl:value-of select="."/> </td>
<td> <xsl:value-of select="following-sibling::Source_Type[1]"/> </td>
</tr>
</xsl:template>
</xsl:stylesheet>
You can test it here : https://xsltfiddle.liberty-development.net/bFWR5Ej/1
Upvotes: 1
Reputation: 29052
So far I managed to create the desired outcome, but however, I would seriously suggest to sanitize your XML file/input, because it's complicating things.
But with your current file, you can use this XSLT-1.0 stylesheet to get the desired output:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />
<!-- A template handling the main HTML stuff -->
<xsl:template match="/Rows">
<html>
<body>
<font size="2" face="Calibri" >
<h1>The following Source - Target Tables have DDL Mismatch(es)</h1>
<br />
<xsl:apply-templates select="Table" />
</font>
</body>
</html>
</xsl:template>
<xsl:template match="Table">
<table border="1px" cellpadding="3" cellspacing="1" style='font-family:"Calibri"; font-size:12; font-weight:"normal"' >
<tr align="center">
<xsl:for-each select="preceding-sibling::Header[1]">
<th colspan="1" bgcolor="#ccffff">
<font size="2" face="Calibri" style="text-transform:uppercase"> <xsl:value-of select="sourcetable" /> </font>
</th>
<th colspan="1" bgcolor="#ccffff">
<font size="2" face="Calibri" style="text-transform:uppercase"> <xsl:value-of select="targettable" /> </font>
</th>
</xsl:for-each>
<th bgcolor="#FFCCBC" rowspan="2">Flagfield</th>
</tr>
<tr align="left">
<td bgcolor="#C5E1A5">Source_Fieldname</td>
<td bgcolor="#C5E1A5">Source_Type</td>
</tr>
<xsl:for-each select="*[local-name()='Source_Fieldname']">
<tr>
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="following-sibling::Source_Type[1]"/></td>
</tr>
</xsl:for-each>
</table>
<br /><br/>
</xsl:template>
</xsl:stylesheet>
The central aspect is the xsl:for-each
loop:
<xsl:for-each select="*[local-name()='Source_Fieldname']">
<tr>
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="following-sibling::Source_Type[1]"/></td>
</tr>
</xsl:for-each>
The output is:
It simply iterates over all <Table>
children which are named Source_Fieldname
and then creates a table cell for these and for the first following-sibling Source_Type
element. This does work for a two element table, but it should be no problem to extend it to a several children situation.
Upvotes: 0