XSLT输出应该已经处理的节点文本

时间:2016-07-07 08:29:44

标签: xml xslt

我的XSLT文件存在问题,该文件大致采用以下形式的XML文件:

<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'>&lt;!DOCTYPE html&gt;</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>

我的问题是这个输出看起来很好,除了输出的HTML输出in/docout/docexception/doc和所有parameter/doc标签的文本。文档的最顶部(除了第一个in标签下的那些,为什么?)。

所以基本上doc输出是在文档的顶部(后跟其他看起来正确的输出,带有表和东西):

text4 text5 text6 text7 text8 text9 tex10

Output of the above transformation

为什么会这样?我知道这是因为默认模板,但在我看来,我不是在任何地方匹配这些标签。如果我这样做,我在底部添加了最终模板,匹配model/interface/acc/op/in/parameter/doc,只是为了捕捉这样的匹配,但它没有任何帮助。

我还尝试覆盖导致此行为的默认模板,例如:

<xsl:template match="text()" />

<xsl:template match="*" />

然而,这些都没有区别。我在这里不知所措。

P.S。随意评论我的XSLT风格。我只是学习它而且好奇我是否遵循惯用的XSLT。

2 个答案:

答案 0 :(得分:1)

显然,您正在将模板应用于包含要输出的文本节点的节点,但您没有与之匹配的相应模板。在这种情况下,built-in template rules将启动 - 他们的行动是输出所有后代文本值。

  

我还尝试覆盖导致的默认模板   这种行为,例如:

     

<xsl:template match="text()" />

如果这不起作用,那么模板已经以不同的模式应用了。事实上,

<xsl:template match="text()" mode="toc"/>

将禁止不需要的文字。

答案 1 :(得分:1)

您拥有<xsl:apply-templates select="//acc|//conn" mode="toc"/>,但该模式toc的唯一模板是

<xsl:template match="acc/op/in" mode="toc">
    <tr>
        <td><a href="#{../@name}"><xsl:value-of select="../@name"/>foo</a></td>
    </tr>
</xsl:template>

如果您只想处理该模式的acc/op/in元素以输出表格行,则不要处理其他元素,因此最简单的修复似乎是使用<xsl:apply-templates select="//acc/op/in" mode="toc"/>