Reputation: 2936
I have a problem with my XSLT file, which takes an XML file on roughly the form:
<model>
<interface>
<doc>text1</doc>
<acc>
<op name="name">
<in>
<doc>text2</doc>
<parameter name="name" type="type">
<doc>text3</doc>
</parameter>
</in>
<out>
<doc>text4</doc>
<parameter name="name" type="type">
<doc>text5</doc>
</parameter>
</out>
<exception name="name">
<doc>text6</doc>
<parameter name="name" type="type">
<doc>text7</doc>
</parameter>
<parameter name="name" type="type">
<doc>text8</doc>
</parameter>
</exception>
</op>
</acc>
<conn>
<op name="name">
<in>
<doc>text9</doc>
<parameter name="name" type="type">
<doc>text10</doc>
</parameter>
</in>
</op>
</conn>
<!-- rest omitted !-->
</interface>
</model>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8" indent="yes" />
<xsl:template match="/">
<xsl:text disable-output-escaping='yes'><!DOCTYPE html></xsl:text>
<html>
<head>
<script>
<!-- omitted !-->
</script>
<style>
<!-- omitted !-->
</style>
</head>
<body>
<h2>Title</h2>
<table class="tablesorter" border="1">
<thead>
<tr bgcolor="#9acd32">
<th style="text-align:left">Name</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="//acc|//conn" mode="toc"/>
</tbody>
</table>
<xsl:apply-templates select="//acc|//conn" mode="detail"/>
</body>
</html>
</xsl:template>
<xsl:template name="create_detail_table">
<b>Description:</b> <xsl:value-of select="doc"/>
<h4>Parameters</h4>
<table class="tablesorter" border="1">
<thead>
<tr>
<th style="word-wrap:normal; width:30%">Name</th>
<th style="word-wrap:normal; width:30%">Type</th>
<th style="word-wrap:normal; width:30%">Description</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="parameter"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="acc/op/in" mode="toc">
<tr>
<td><a href="#{../@name}"><xsl:value-of select="../@name"/>foo</a></td>
</tr>
</xsl:template>
<xsl:template match="acc/op/in" mode="detail">
<h3 id="{../@name}"><xsl:value-of select="../@name"/>foo</h3>
<xsl:call-template name="create_detail_table"/>
</xsl:template>
<xsl:template match="parameter">
<tr>
<td><xsl:value-of select="@name"/></td>
<td><xsl:value-of select="@type"/></td>
<td><xsl:value-of select="doc"/></td>
</tr>
</xsl:template>
<xsl:template match="acc/op/out" mode="detail">
<h3><xsl:value-of select="../@name"/>foo</h3>
<xsl:call-template name="create_detail_table"/>
</xsl:template>
<xsl:template match="acc/op/exception" mode="detail">
<h3><xsl:value-of select="../@name"/>bar</h3>
<xsl:call-template name="create_detail_table"/>
</xsl:template>
<xsl:template match="conn/op/in" mode="detail">
<h3><xsl:value-of select="../@name"/>baz</h3>
<xsl:call-template name="create_detail_table"/>
</xsl:template>
<xsl:template match="model/interface/acc/op/in/parameter/doc" />
</xsl:stylesheet>
My problem is that this output looks completely fine except for the fact that the outputted HTML outputs the text of in/doc
, out/doc
, exception/doc
and all parameter/doc
tags at the very top of the document (except for those under the first in
tag, why?).
So basically the doc output is, at the top of the document (followed by other output that looks correct, with tables and stuff):
text4 text5 text6 text7 text8 text9 tex10
Why would this happen? I know that this happens because of default templates, but it seems to me that I am not matching those tags anywhere. And in the event that I did, I added the final template at the bottom, matching model/interface/acc/op/in/parameter/doc
, just to catch such a match, but it didn't help in any way.
I have also attempted to override the default templates that cause this behavior, such as:
<xsl:template match="text()" />
and
<xsl:template match="*" />
However, neither of these make a difference. I'm at a loss here.
P.S. Feel free to comment on my style of XSLT. I'm only just learning it and am curious if I'm following idiomatic XSLT.
Upvotes: 0
Views: 43
Reputation: 167571
You have <xsl:apply-templates select="//acc|//conn" mode="toc"/>
but the only template for that mode toc
is
<xsl:template match="acc/op/in" mode="toc">
<tr>
<td><a href="#{../@name}"><xsl:value-of select="../@name"/>foo</a></td>
</tr>
</xsl:template>
If you only want to process the acc/op/in
elements for that mode to output a table row then don't process other elements so the simplest fix seems to be to use <xsl:apply-templates select="//acc/op/in" mode="toc"/>
.
Upvotes: 1
Reputation: 116993
Clearly, you are applying templates to the nodes that contain the text nodes being output, but you do not have corresponding templates that match them. In such situation, the built-in template rules will kick in - and their action is to output all descendant text values.
I have also attempted to override the default templates that cause this behavior, such as:
<xsl:template match="text()" />
If this doesn't work, then apparrently the templates have been applied in a different mode. And indeed,
<xsl:template match="text()" mode="toc"/>
will suppress the unwanted text.
Upvotes: 1