在使用 exslt 字符串替换功能时,我认为是一个命名空间的问题。我想按照此处的文档使用 exslt 字符串替换函数的节点集形式替换目标字符串中的几个字符串。然而,它似乎只替换了节点集的第一个字符串,而不是其他字符串。
这是我的文件:
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
<!ENTITY yen "¥">
<!ENTITY circle "●">
<!ENTITY raquo "»">
]>
<xsl:stylesheet
version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:str="http://exslt.org/strings"
xmlns:exsl="http://exslt.org/common"
xmlns:regexp="http://exslt.org/regular-expressions"
extension-element-prefixes="msxsl str exsl regexp">
<xsl:output
method="html"
indent="yes"
encoding="utf-8"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
/>
<!-- Start of the main template -->
<xsl:template match="/Top">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<body>
<xsl:variable name="text">
-[this]- This is a test string -[that]-
-[this]- This is another test string -[that]-
</xsl:variable>
text: <xsl:value-of select="$text" disable-output-escaping="yes" />
<xsl:variable name="searches" xmlns="">
<replacements xmlns="">
<searches>
<search>-[this]-</search>
<search>-[that]-</search>
</searches>
<replaces>
<replace>**[this]**</replace>
<replace>**[that]**</replace>
</replaces>
</replacements>
</xsl:variable>
<xsl:variable name="search_set" select="exsl:node-set($searches)/replacements/searches/search" />
<xsl:variable name="replace_set" select="exsl:node-set($searches)/replacements/replaces/replace" />
search_set: <xsl:copy-of select="$search_set" />
replace_set: <xsl:copy-of select="$replace_set" />
<xsl:if test="$search_set">
replaced via function:
<xsl:value-of select="str:replace($text, $search_set, $replace_set)" disable-output-escaping="yes" />
replaced via template:
<xsl:variable name="replaced_tpl">
<xsl:call-template name="str:replace">
<xsl:with-param name="string" select="$text"/>
<xsl:with-param name="search" select="$search_set"/>
<xsl:with-param name="replace" select="$replace_set"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$replaced_tpl" disable-output-escaping="yes" />
</xsl:if>
</body>
</html>
</xsl:template><!-- / end main template -->
<xsl:template name="str:replace" xmlns="">
<xsl:param name="string" select="''" />
<xsl:param name="search" select="/.." />
<xsl:param name="replace" select="/.." />
<xsl:choose>
<xsl:when test="not($string)" />
<xsl:when test="not($search)">
<xsl:value-of select="$string" />
</xsl:when>
<xsl:when test="function-available('exsl:node-set')">
<!-- this converts the search and replace arguments to node sets
if they are one of the other XPath types -->
<xsl:variable name="search-nodes-rtf">
<xsl:copy-of select="$search" />
</xsl:variable>
<xsl:variable name="replace-nodes-rtf">
<xsl:copy-of select="$replace" />
</xsl:variable>
<xsl:variable name="replacements-rtf">
<xsl:for-each select="exsl:node-set($search-nodes-rtf)/node()">
<xsl:variable name="pos"
select="position()" />
<replace search="{.}">
<xsl:copy-of select="exsl:node-set($replace-nodes-rtf)/node()[$pos]" />
</replace>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="sorted-replacements-rtf">
<xsl:for-each select="exsl:node-set($replacements-rtf)/replace">
<xsl:sort select="string-length(@search)"
data-type="number"
order="descending" />
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:variable>
<xsl:call-template name="str:_replace">
<xsl:with-param name="string"
select="$string" />
<xsl:with-param name="replacements"
select="exsl:node-set($sorted-replacements-rtf)/replace" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
ERROR: template implementation of str:replace relies on exsl:node-set().
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="str:_replace">
<xsl:param name="string"
select="''" />
<xsl:param name="replacements"
select="/.." />
<xsl:choose>
<xsl:when test="not($string)" />
<xsl:when test="not($replacements)">
<xsl:value-of select="$string" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="replacement"
select="$replacements[1]" />
<xsl:variable name="search"
select="$replacement/@search" />
<xsl:choose>
<xsl:when test="not(string($search))">
<xsl:value-of select="substring($string, 1, 1)" />
<xsl:copy-of select="$replacement/node()" />
<xsl:call-template name="str:_replace">
<xsl:with-param name="string"
select="substring($string, 2)" />
<xsl:with-param name="replacements"
select="$replacements" />
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($string, $search)">
<xsl:call-template name="str:_replace">
<xsl:with-param name="string"
select="substring-before($string, $search)" />
<xsl:with-param name="replacements"
select="$replacements[position() > 1]" />
</xsl:call-template>
<xsl:copy-of select="$replacement/node()" />
<xsl:call-template name="str:_replace">
<xsl:with-param name="string"
select="substring-after($string, $search)" />
<xsl:with-param name="replacements"
select="$replacements" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="str:_replace">
<xsl:with-param name="string"
select="$string" />
<xsl:with-param name="replacements"
select="$replacements[position() > 1]" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这是输出:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml"><head><style type="text/css"></style></head><body>
text:
-[this]- This is a test string -[that]-
-[this]- This is another test string -[that]-
search_set: <search xmlns="">-[this]-</search><search xmlns="">-[that]-</search>
replace_set: <replace xmlns="">**[this]**</replace><replace xmlns="">**[that]**</replace>
replaced via function:
**[this]** This is a test string -[that]-
**[this]** This is another test string -[that]-
replaced via template:
**[this]** This is a test string **[that]**
**[this]** This is another test string **[that]**
</body></html>
正如您在输出中看到的那样。在使用该函数时,只有第一个节点的字符串被替换。第二个没有。如您所见,我将模板代码从 exslt.org 复制到文件中,起初它没有工作,直到我将它添加xmlns=""
到 str:replace 模板中,如下所示:
<xsl:template name="str:replace" xmlns="">
那时模板表单起作用了,这让我相信这是一个名称空间问题。我相信在函数中对节点进行排序并创建自己的replace
节点时,如下所示:
<replace search="{.}">
<xsl:copy-of select="exsl:node-set($replace-nodes-rtf)/node()[$pos]" />
</replace>
该节点可能最终位于不同的命名空间中,因此后续循环无法解决它们。将xmlns
属性添加到str:replace
将其中创建的任何节点放入与我传入的节点相同的空命名空间中,然后它就可以工作了。但是,无论我尝试什么,我都无法使功能版本正常工作。我什至从文件和我创建的 xml 节点集中删除了所有命名空间,但它仍然不起作用。坦率地说,所有这些命名空间的东西让我有点困惑。也许这根本不是问题。
任何帮助将不胜感激,谢谢!