如何使用 XSLT 将格式化 HTML 中的关键字替换为 HTML 标记?

问题描述 投票:0回答:2

我正在尝试向 XML 文档中存储的 HTML 格式文本中的关键字添加超链接。

XML 片段:

<NoteText>Heading of note<br/>
Body of note blah blah keyword blah blah.<br/>
May contain more lines.</NoteText>

所需输出:

Heading of note<br/>
Body of note blah blah <a href="http://127.0.0.1/">keyword</a> blah blah.<br/>
May contain more lines.

XSLT 模板的原始尝试。这会添加 HTML 标签,但会丢失所有现有格式。

  <xsl:template name="string-replace-all">
    <xsl:param name="text" />
    <xsl:param name="replace" />
    <xsl:param name="by" />
    <xsl:choose>
      <xsl:when test="contains($text, $replace)">
        <xsl:value-of select="substring-before($text,$replace)" disable-output-escaping="yes" />
        <xsl:value-of select="$by" disable-output-escaping="yes" />
        <xsl:call-template name="string-replace-all">
          <xsl:with-param name="text" select="substring-after($text,$replace)" />
          <xsl:with-param name="replace" select="$replace" />
          <xsl:with-param name="by" select="$by" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text" disable-output-escaping="yes" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

第二次尝试。这会保留现有格式,但添加新的 HTML 作为显示文本而不是功能标记。

  <xsl:template name="string-replace-formatted">
    <xsl:param name="text" />
    <xsl:param name="replace" />
    <xsl:param name="by" />
    <xsl:choose>
      <xsl:when test="contains($text, $replace)">
        <xsl:copy-of select="substring-before($text,$replace)" />
        <xsl:copy-of select="$by" />
        <xsl:call-template name="string-replace-formatted">
          <xsl:with-param name="text" select="substring-after($text,$replace)" />
          <xsl:with-param name="replace" select="$replace" />
          <xsl:with-param name="by" select="$by" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy-of select="$text" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

所以,我正在寻找两全其美的方法 - 如何保留现有的 HTML 标签并添加新的 HTML 标签?是否可以使用像我这里这样的通用模板(以便它可以重用于其他标签),或者我是否需要一个单一用途的模板,该模板具有找到和替换的字符串的常量值?

xslt xslt-1.0
2个回答
1
投票

使用 xslt 1.0 你可以尝试这样的事情:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0">
  
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="NoteText//text()">
    <xsl:call-template name="make-link">
      <xsl:with-param name="linktext" select="'keyword'"/>
      <xsl:with-param name="link" >
        <a href="http://127.0.0.1/"/>
      </xsl:with-param>
    </xsl:call-template>
  </xsl:template>
  
  <xsl:template name="make-link">
    <xsl:param name="text" select="." />
    <xsl:param name="linktext" />
    <xsl:param name="link" />
    <xsl:choose>
      <xsl:when test="contains($text, $linktext)">
        <xsl:copy-of select="substring-before($text,$linktext)" />
        <a href="http://127.0.0.1/">
          <xsl:value-of select="$linktext" />
        </a>
        <xsl:call-template name="make-link">
          <xsl:with-param name="text" select="substring-after($text,$linktext)" />
          <xsl:with-param name="linktext" select="$linktext" />
          <xsl:with-param name="link" select="$link" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  

</xsl:stylesheet>

0
投票

这对于 XSLT 3 来说是一项简单的工作:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  exclude-result-prefixes="#all"
  expand-text="yes">
  
  <xsl:template match="NoteText//text()">
    <xsl:apply-templates select="analyze-string(., 'keyword')" mode="wrap-match"/>
  </xsl:template>
  
  <xsl:template match="fn:match" mode="wrap-match">
    <a href="http://localhost/">{.}</a>
  </xsl:template>

  <xsl:mode on-no-match="shallow-copy"/>
  
</xsl:stylesheet>

XSLT 3 可用于 Java 平台的 Saxon、.NET 平台、用于 Python/C/C++ 的 SaxonC、用于 Node.js 和浏览器的 SaxonJS。

© www.soinside.com 2019 - 2024. All rights reserved.