1

我似乎对 Xalan 的翻译方法有疑问。我有以下代码:

translate(translate(string(name),'<sup>',''),'</sup>','')

这用于从字符串(名称)中删除<sup>和删除。</sup>不幸的是,当我这样做时,它似乎也从名称中删除了 s、u 和 p。sony Braiva <sup>tm</sup>所以像变得这样的名字ony bravia tm

感谢您提前提供帮助:)

4

2 回答 2

5

因为您说 translate() 函数已成功删除<sup>and </sup>,所以我假设它<sup>不是 XML 文档中的元素,而是编码为文本。

translate() 函数被定义为替换单个字符,通常不适用于字符串长度大于 1 时的字符串替换。

可以在 XSLT 中编写和使用通用字符串替换递归模板/函数。

XSLT 2.0 程序员可以使用标准的 XPath 2.0 函数 replace()。

在您的特定情况下,这可能就足够了:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="text()">
  <xsl:variable name="vPart1" select=
   "substring-before(., '&lt;sup>')"/>

  <xsl:value-of select="$vPart1"/>

  <xsl:variable name="vPart2" select=
   "substring-before(substring-after(., '&lt;sup>'),
                     '&lt;/sup>'
                     )"/>

  <xsl:value-of select="$vPart2"/>

  <xsl:variable name="vPart3" select=
   "substring-after(., '&lt;/sup>')"/>

  <xsl:value-of select="$vPart3"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时

<name>
 <![CDATA[sony Braiva <sup>tm</sup> xxx]]>
</name>

产生了想要的结果

<name>
sony Braiva tm xxx
</name>

或者,这里是成熟的递归模板解决方案:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="text()">
  <xsl:variable name="vFirstReplacement">
      <xsl:call-template name="replace">
       <xsl:with-param name="pText" select="."/>
       <xsl:with-param name="pPattern"
         select="'&lt;sup>'"/>
       <xsl:with-param name="pReplacement" select="''"/>
      </xsl:call-template>
  </xsl:variable>

  <xsl:call-template name="replace">
   <xsl:with-param name="pText"
        select="$vFirstReplacement"/>
   <xsl:with-param name="pPattern"
     select="'&lt;/sup>'"/>
   <xsl:with-param name="pReplacement" select="''"/>
  </xsl:call-template>
 </xsl:template>

 <xsl:template name="replace">
  <xsl:param name="pText"/>
  <xsl:param name="pPattern"/>
  <xsl:param name="pReplacement"/>

  <xsl:choose>
   <xsl:when test="not(contains($pText, $pPattern))">
    <xsl:value-of select="$pText"/>
   </xsl:when>
   <xsl:otherwise>
     <xsl:value-of select=
      "substring-before($pText, $pPattern)"/>

     <xsl:value-of select="$pReplacement"/>

     <xsl:call-template name="replace">
      <xsl:with-param name="pText" select=
       "substring-after($pText, $pPattern)"/>
      <xsl:with-param name="pPattern"
           select="$pPattern"/>
      <xsl:with-param name="pReplacement"
           select="$pReplacement"/>
     </xsl:call-template>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

当将此转换应用于此 XML 文档时

<name>
 <![CDATA[sony Braiva <sup>tm</sup> xxx]]>
</name>

产生了想要的正确结果:

<name>
 sony Braiva tm xxx
</name>

最后,这里是 XSLT 2.0 解决方案

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="text()">
  <xsl:value-of select=
   "replace(
            replace(., '&lt;sup>', ''),
            '&lt;/sup>',
            ''
            )
   "/>
 </xsl:template>
</xsl:stylesheet>
于 2010-07-05T19:25:09.533 回答
1

tl;dr 版本:如果可以避免,请不要将 html 或 xml 作为字符串操作。在 XSLT 中执行此操作。

我假设你所拥有的是一些元素包含类似的东西

<name>Sony Braiva <sup>tm</sup></name>

所以看起来您已经在 XSLT 中获得了一个已解析的 XML 文档。然后,您转身尝试使用字符串操作来拉出一些标签。这是个坏主意;看到这个关于匹配标签的问题。XSLT 正是用于这种操作,所以使用它!(如果我的假设是错误的,并且tm是实体化的或在 CDATA 部分或其他任何内容中,我猜这会有所不同。)

所以,首先。如果您想从名称中删除所有标签,只留下文本,您可以这样做

<xsl:value-of select="name" />

这将给出:

Sony Braiva tm

另一方面,如果你想删除所有 sup 标签及其内容,你首先要在别处定义一个匹配 sup 的模板(并对你想要删除的任何东西做同样的事情,例如 script 标签、img 标签等等):

<xsl:template match="sup" /> <!-- replace sup with nothing -->

然后就可以申请了

<xsl:apply-templates select="name" />

如果你真的想要,你甚至可以做这样的事情并用一个漂亮的 unicode 符号替换那个 HTML。将其置于不同的模式并使用该模式消除所有其他标签可能是个好主意。

<xsl:template match="sup" mode="mangle-name">
  <xsl:if test="'tm' = string(.)">
  &#8482;
  </xsl:if>
</xsl:template>

<!-- Later, somewhere else: -->
<xsl:apply-templates select="name" mode="mangle-name" />

所有这一切的免责声明:它是标准的 XSLT(甚至可能是 1.0),但我只在在线 Saxon 解析器中尝试过它,而不是在 Xalan 中。

于 2010-07-05T19:39:54.287 回答