How to add templates to existing XSLT that uses for-each loops to generate HTML?
I have a stylesheet that generates HTML for XML files.
Example XML file:
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="trial.xsl"?>
<wholeEnchilada>
<Interface>
<Messages>
<Message name="blah">
<Variable name="DialogIdentifier" dataType="UINT16"/>
<Variable name="ReplyCount" dataType="UINT16"/>
<Variable name="ReplyPeriod" dataType="UINT16"/>
</Message>
<Message>
<Variable name="Uptime" dataType="UINT32"/>
<Variable name="FaultIndicator" dataType="UINT32"/>
<Variable name="OperatingMode" dataType="UINT8"/>
</Message>
</Messages>
</Interface>
<Interface>
<Messages>
<Message>
<Variable name="vara" dataType="UINT64"/>
<Variable name="varb" dataType="UINT8"/>
</Message>
</Messages>
</Interface>
</wholeEnchilada>
Example stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<HTML>
<BODY>
<xsl:for-each select="*">
<xsl:for-each select="Interface">
<xsl:for-each selec开发者_JS百科t="Messages">
<xsl:for-each select="Message">
<TABLE BORDER="1">
<TR><TH>Field Name</TH><TH>Size</TH><TH>Offset</TH></TR>
<!-- Fields-->
<xsl:for-each select="Variable">
<TR>
<TD><xsl:value-of select="@name"/></TD>
<TD><xsl:value-of select="@size"/></TD>
<TD><xsl:value-of select="@offset"/></TD>
</TR>
</xsl:for-each> <!-- Fields-->
</TABLE>
<xsl:for-each select="Variable">
<xsl:variable name="fieldSize" select="substring-after(@dataType,'INT') div 8"/>
<TABLE BORDER="1">
<TR><TH>Name</TH> <TH><xsl:value-of select="@name"/></TH></TR>
<TR><TD>Size</TD> <TD><xsl:value-of select="$fieldSize"/></TD></TR>
<TR><TD>Offset</TD> <TD><xsl:value-of select="Offset"/></TD></TR>
<TR><TD>DataType</TD><TD><xsl:value-of select="@dataType"/></TD></TR>
</TABLE>
</xsl:for-each>
<hr size="10" noshade="true"/>
</xsl:for-each> <!-- Message -->
</xsl:for-each> <!-- Messages -->
</xsl:for-each> <!-- Interface -->
</xsl:for-each> <!-- * -->
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
My actualy stylesheet is ~300 lines long, and prints lots more attributes and navigates lots more structure than the sample given above.
I asked a question about how to calculate field sizes (INT8->1, INT16->2, INT32->4), and also variable offsets, where the first variable starts at 0, the next starts after the first, etc. I think the question was answered, but unfortunately I've been complete unsuccessful in integrating the answer to generate HTML in my existing stylesheet.
My attempt at integrating Alejandro's answer from his "Edit 3", but based on the output, I didn't do it right:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Variable">
<xsl:param name="fieldOffset" select="0"/>
<xsl:variable name="fieldSize" select="substring-after(@dataType,'INT') div 8"/>
(<xsl:value-of select="@name"/>, <xsl:value-of select="$fieldSize"/>, <xsl:value-of select="$fieldOffset"/>)
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:attribute name="size">
<xsl:value-of select="$fieldSize"/>
</xsl:attribute>
<xsl:attribute name="offset">
<xsl:value-of select="$fieldOffset"/>
</xsl:attribute>
</xsl:copy>
((<xsl:value-of select="@name"/>, <xsl:value-of select="@size"/>, <xsl:value-of select="@offset"/>))
<xsl:apply-templates select="following-sibling::Variable[1]">
<xsl:with-param name="fieldOffset" select="$fieldOffset + $fieldSize"/>
<xsl:value-of select="@fieldOffset"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="/">
<HTML>
<BODY>
<xsl:for-each select="*">
<xsl:for-each select="Interface">
<xsl:for-each select="Messages">
<xsl:for-each select="Message">
<TABLE BORDER="1">
<TR><TH>Field Name</TH><TH>Size</TH><TH>Offset</TH></TR>
<!-- Fields-->
<xsl:for-each select="Variable">
<xsl:apply-templates select="*[1]|following-sibling::*[1]"/>
<TR>
<TD><xsl:value-of select="@name"/></TD>
<TD><xsl:value-of select="@size"/></TD>
<TD><xsl:value-of select="@offset"/></TD>
</TR>
</xsl:for-each> <!-- Fields-->
</TABLE>
<xsl:for-each select="Variable">
<xsl:variable name="fieldSize" select="substring-after(@dataType,'INT') div 8"/>
<TABLE BORDER="1">
<TR><TH>Name</TH> <TH><xsl:value-of select="@name"/></TH></TR>
<TR><TD>Size</TD> <TD><xsl:value-of select="$fieldSize"/></TD></TR>
<TR><TD>Offset</TD> <TD><xsl:value-of select="Offset"/></TD></TR>
<TR><TD>DataType</TD><TD><xsl:value-of select="@dataType"/></TD></TR>
</TABLE>
</xsl:for-each>
<hr size="10" noshade="true"/>
</xsl:for-each> <!-- Message -->
</xsl:for-each> <!-- Messages -->
</xsl:for-each> <!-- Interface -->
</xsl:for-each> <!-- * -->
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
Based on my diagnostic statements (which show up in parenthesis in the HTML output), the templates are being executed, I just don't know how to make the proper output from the templates show up in the HTML. xsl:copy seems to be creating copies of the nodes and putting the new attributes @size and @offset in them, but not in a way that makes those attributes accessible to my <xsl:value-of select="@size"/>
and <xsl:value-of select="@offset"/>
statements.
Here's the HTML I'd like to get, for the first message in the XML file:
<table border="1">
<tbody>
<tr><th>Field Name</th><th>Size</th><th>Offset</th></tr>
</tbody>
<tbody>
<tr><td>DialogIdentifier</td><td>2</td><td>0</td></tr>
<tr><td>ReplyCount</td><td>2</td><td>2</td></tr>
<tr><td>ReplyPeriod</td><td>2</td><td>4</td>
</tr></tbody>
</table>
<table border="1">
<tbody>
<tr><th>Name</th><th>DialogIdentifier</th></tr>
<tr><td>Size</td><td>2</td></tr>
<tr><td>Offset</td><td>0</td></tr>
<tr><td>DataType</td><td>UINT16</td></tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr><th>Name</th><th>ReplyCount</th></tr>
<tr><td>Size</td><td>2</td></tr>
<tr><td>Offset</td><td>2</td></tr>
<tr><td>DataType</td><td>UINT16</td></tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr><th>Name</th><th>ReplyPeriod</th></tr>
<tr><td>Size</td><td>2</td></tr>
<tr><td>Offset</td><td>4</td></tr>
<tr><td>DataType</td><td>UINT16</td></tr>
</tbody>
</table>
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="Message">
<table border="1">
<tbody>
<tr>
<th>Field Name</th>
<th>Size</th>
<th>Offset</th>
</tr>
</tbody>
<tbody>
<xsl:apply-templates select="Variable[1]"/>
</tbody>
</table>
<xsl:apply-templates select="Variable[1]" mode="table"/>
</xsl:template>
<xsl:template match="Variable">
<xsl:param name="pOffset" select="0"/>
<xsl:variable name="vSize"
select="substring-after(@dataType,'UINT') div 8"/>
<tr>
<td>
<xsl:value-of select="@name"/>
</td>
<td>
<xsl:value-of select="$vSize"/>
</td>
<td>
<xsl:value-of select="$pOffset"/>
</td>
</tr>
<xsl:apply-templates select="following-sibling::Variable[1]">
<xsl:with-param name="pOffset" select="$pOffset + $vSize"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Variable" mode="table">
<xsl:param name="pOffset" select="0"/>
<xsl:variable name="vSize"
select="substring-after(@dataType,'UINT') div 8"/>
<table border="1">
<tbody>
<tr>
<th>Name</th>
<th>
<xsl:value-of select="@name"/>
</th>
</tr>
<tr>
<td>Size</td>
<td>
<xsl:value-of select="$vSize"/>
</td>
</tr>
<tr>
<td>Offset</td>
<td>
<xsl:value-of select="$pOffset"/>
</td>
</tr>
<tr>
<td>DataType</td>
<td>
<xsl:value-of select="@dataType"/>
</td>
</tr>
</tbody>
</table>
<xsl:apply-templates select="following-sibling::Variable[1]"
mode="table">
<xsl:with-param name="pOffset" select="$pOffset + $vSize"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
Output:
<table border="1">
<tbody>
<tr>
<th>Field Name</th>
<th>Size</th>
<th>Offset</th>
</tr>
</tbody>
<tbody>
<tr>
<td>DialogIdentifier</td>
<td>2</td>
<td>0</td>
</tr>
<tr>
<td>ReplyCount</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>ReplyPeriod</td>
<td>2</td>
<td>4</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Name</th>
<th>DialogIdentifier</th>
</tr>
<tr>
<td>Size</td>
<td>2</td>
</tr>
<tr>
<td>Offset</td>
<td>0</td>
</tr>
<tr>
<td>DataType</td>
<td>UINT16</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Name</th>
<th>ReplyCount</th>
</tr>
<tr>
<td>Size</td>
<td>2</td>
</tr>
<tr>
<td>Offset</td>
<td>2</td>
</tr>
<tr>
<td>DataType</td>
<td>UINT16</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Name</th>
<th>ReplyPeriod</th>
</tr>
<tr>
<td>Size</td>
<td>2</td>
</tr>
<tr>
<td>Offset</td>
<td>4</td>
</tr>
<tr>
<td>DataType</td>
<td>UINT16</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Field Name</th>
<th>Size</th>
<th>Offset</th>
</tr>
</tbody>
<tbody>
<tr>
<td>Uptime</td>
<td>4</td>
<td>0</td>
</tr>
<tr>
<td>FaultIndicator</td>
<td>4</td>
<td>4</td>
</tr>
<tr>
<td>OperatingMode</td>
<td>1</td>
<td>8</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Name</th>
<th>Uptime</th>
</tr>
<tr>
<td>Size</td>
<td>4</td>
</tr>
<tr>
<td>Offset</td>
<td>0</td>
</tr>
<tr>
<td>DataType</td>
<td>UINT32</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Name</th>
<th>FaultIndicator</th>
</tr>
<tr>
<td>Size</td>
<td>4</td>
</tr>
<tr>
<td>Offset</td>
<td>4</td>
</tr>
<tr>
<td>DataType</td>
<td>UINT32</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Name</th>
<th>OperatingMode</th>
</tr>
<tr>
<td>Size</td>
<td>1</td>
</tr>
<tr>
<td>Offset</td>
<td>8</td>
</tr>
<tr>
<td>DataType</td>
<td>UINT8</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Field Name</th>
<th>Size</th>
<th>Offset</th>
</tr>
</tbody>
<tbody>
<tr>
<td>vara</td>
<td>8</td>
<td>0</td>
</tr>
<tr>
<td>varb</td>
<td>1</td>
<td>8</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Name</th>
<th>vara</th>
</tr>
<tr>
<td>Size</td>
<td>8</td>
</tr>
<tr>
<td>Offset</td>
<td>0</td>
</tr>
<tr>
<td>DataType</td>
<td>UINT64</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<th>Name</th>
<th>varb</th>
</tr>
<tr>
<td>Size</td>
<td>1</td>
</tr>
<tr>
<td>Offset</td>
<td>8</td>
</tr>
<tr>
<td>DataType</td>
<td>UINT8</td>
</tr>
</tbody>
</table>
Too much to go through right now but here are a couple resources and tips.
Here's the link to the w3c school's online tutorial: http://www.w3schools.com/xsl/default.asp
If you're up to it, or desperate enough, you can also review the specs. for additional details: http://www.w3.org/TR/xslt
Use Firefox. It shows where the errors are and will help you greatly when debugging.
精彩评论