1

我目前有一个简单的标记,主要代表 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>

此方法可防止任何子标签通过,但是我不确定如何解决此问题。

任何帮助是极大的赞赏!担

4

1 回答 1

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>元素内的文本节点。只需更改匹配表达式以影响其他节点。

假设您想在不破坏任何其他模板的情况下将所有<b>节点转换为。<strong>使用拉式风格,这很简单:

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

另请注意,当您这样做时,当前节点不会更改<xsl:call-template>。因此不需要将当前节点传递给被调用的模板。

于 2012-04-26T08:59:35.873 回答