显示子节点

时间:2012-04-26 08:26:33

标签: html xml xslt

我目前有一个简单的标记,主要代表HTML。

以下是

的摘录
<li>Make this <b>Bold</b></li>

我当然可以使用<xsl:copy-of>来确保<b>标记通过并自动显示为粗体,但是我遇到了问题。

我正在使用另一个XSL来检查关键字或短语存储库的标记,如果它们存在,则会创建链接。

以下是我的XSL

<xsl:template name="List" match="li">
  <li>
          <xsl:call-template name="markup">
            <xsl:with-param name="text" select="."/>
            <xsl:with-param name="phrases" select="document('../../documents/main/keywords.xml')/keywords/keyword"/>
            <xsl:with-param name="first-only" select="false()"/>
          </xsl:call-template>
  </li>
  </xsl:template>

此方法可以阻止任何子标记传递,但我不确定如何解决这个问题。

非常感谢任何帮助! 丹

1 个答案:

答案 0 :(得分:1)

问题是你的链接创建模板做错了。

正确的做法是使用标识模板并为<li>元素的文本节点后代创建专用模板。

试试这个:

<xsl:variable 
  name="keywords"
  select="document('../../documents/main/keywords.xml')/keywords/keyword" 
/>

<!-- the identity template does copies of everything not matched otherwise -->
<xsl:template match="node() | @*">
  <xsl:copy>
    <xsl:apply-templates select="node() | @*" />
  </xsl:copy>
</xsl:template>

<!-- text nodes in <li> elements get special treatment -->
<xsl:template match="li//text()">
  <xsl:call-template name="markup">
    <xsl:with-param name="phrases" select="$keywords"/>
    <xsl:with-param name="first-only" select="false()"/>
  </xsl:call-template>
</xsl:template>

<!-- marks up the current node -->
<xsl:template name="markup">
  <xsl:with-param name="phrases" />
  <xsl:with-param name="first-only" select="true()" />

  <!-- you can use . here - no need to pass in a $text param -->
</xsl:template>

身份模板是成功解决此类问题的关键。它处理透明地复制<li><b>

  1. 它执行输入的完整遍历,复制它,除非更具体的模板与当前节点匹配。
  2. 这意味着您只需要为要更改的节点编写模板。在这种情况下,匹配文本节点效果最好,因为它们不能嵌套子节点。
  3. 避免使用<xsl:template name="List">之类的命名模板。这是“推式”XSLT,即它必不可少,往往导致相当笨拙的结果。
  4. <xsl:template match="li//text()"> 节点拉出流,并执行比复制它们更复杂的操作。这是“拉式”XSLT,即模板匹配。它通常更容易处理并生成更清晰的XSLT代码。
  5. 当然,您并不局限于<li>元素中的文本节点。只需更改匹配表达式即可影响其他节点。
  6. 假设您希望将所有<b>个节点都转换为<strong>,而不会中断任何其他模板。使用拉式,这很简单:

    <xsl:template match="b">
      <strong>
        <xsl:apply-templates select="node() | @*" />
      <strong>
    </xsl:template>
    

    另请注意,执行<xsl:call-template>当前节点不会更改。因此,无需将当前节点传递给被调用的模板。