Xml 使用exslt str的问题:替换为节点集
在使用exslt字符串替换函数时,我认为存在一个名称空间问题。我想根据文档使用exslt string replace函数的节点集形式替换目标字符串中的几个字符串。但是,它似乎只替换节点集的第一个字符串,而不替换其他字符串 这是我的档案:Xml 使用exslt str的问题:替换为节点集,xml,xslt-1.0,exslt,node-set,Xml,Xslt 1.0,Exslt,Node Set,在使用exslt字符串替换函数时,我认为存在一个名称空间问题。我想根据文档使用exslt string replace函数的节点集形式替换目标字符串中的几个字符串。但是,它似乎只替换节点集的第一个字符串,而不替换其他字符串 这是我的档案: <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> <!ENTITY yen "¥"> <!ENTITY cir
<!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>
在这一点上,模板表单工作,这使我相信这是一个名称空间的问题。我相信在函数中,当它对节点进行排序并创建自己的replace
节点时,如下所示:
<replace search="{.}">
<xsl:copy-of select="exsl:node-set($replace-nodes-rtf)/node()[$pos]" />
</replace>
该节点最终可能位于不同的名称空间中,因此后续循环无法对其进行寻址。将xmlns
属性添加到str:replace
会将其中创建的任何节点与我传入的节点放在同一个空名称空间中,然后它就会工作。然而,无论我尝试什么,我都无法让函数版本正常工作。我甚至从文件和我创建的xml节点集中删除了所有名称空间,但它仍然不起作用。坦率地说,所有这些名称空间的东西对我来说都有点混乱。也许这根本不是问题所在
任何帮助都将不胜感激,谢谢
我可以正常使用函数来替换字符串,只需传入
第二个和第三个参数的字符串
这可能是在处理器中如何实现函数的问题。我建议您消除所有其他可能的失败原因,并尝试应用以下样式表:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/input">
<output>
<xsl:choose>
<xsl:when test="function-available('str:replace')">
<xsl:value-of select="str:replace(string, search, replace)" />
</xsl:when>
<xsl:otherwise>
<xsl:text>function str:replace() is not supported</xsl:text>
</xsl:otherwise>
</xsl:choose>
</output>
</xsl:template>
</xsl:stylesheet>
<input>
<string>Mary had a little lamb, its fleece was white as snow.
And everywhere that Mary went, the lamb was sure to go.</string>
<search>Mary</search>
<search>lamb</search>
<search>fleece</search>
<replace>John</replace>
<replace>dog</replace>
<replace>fur</replace>
</input>
<input>
<string>Mary had a little lamb, its fleece was white as snow. And everywhere that Mary went, the lamb was sure to go.</string>
</input>
不支持函数str:replace()
对于此输入:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/input">
<output>
<xsl:choose>
<xsl:when test="function-available('str:replace')">
<xsl:value-of select="str:replace(string, search, replace)" />
</xsl:when>
<xsl:otherwise>
<xsl:text>function str:replace() is not supported</xsl:text>
</xsl:otherwise>
</xsl:choose>
</output>
</xsl:template>
</xsl:stylesheet>
<input>
<string>Mary had a little lamb, its fleece was white as snow.
And everywhere that Mary went, the lamb was sure to go.</string>
<search>Mary</search>
<search>lamb</search>
<search>fleece</search>
<replace>John</replace>
<replace>dog</replace>
<replace>fur</replace>
</input>
<input>
<string>Mary had a little lamb, its fleece was white as snow. And everywhere that Mary went, the lamb was sure to go.</string>
</input>
玛丽有一只小羊羔,羊毛像雪一样白。
无论玛丽去哪里,羔羊都会去。
玛丽
羔羊
羊毛
约翰
狗
毛皮
并报告结果
继续的: 约翰有一只小羊羔,它的羊毛是白色的 洁白如雪。无论约翰走到哪里,羔羊都会来 开始。 那么很明显,这个功能并没有按照规范来实现。这并不是一件坏事,因为大多数处理器根本不实现str:replace()函数。在调用函数之前,只需通过调用命名模板来填充缺少的部分,例如:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="exsl str">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:variable name="dictionary">
<search>Mary</search>
<search>lamb</search>
<search>fleece</search>
<replace>John</replace>
<replace>dog</replace>
<replace>fur</replace>
</xsl:variable>
<xsl:template match="/input">
<output>
<xsl:call-template name="multi-replace">
<xsl:with-param name="string" select="string"/>
<xsl:with-param name="search-strings" select="exsl:node-set($dictionary)/search"/>
<xsl:with-param name="replace-strings" select="exsl:node-set($dictionary)/replace"/>
</xsl:call-template>
</output>
</xsl:template>
<xsl:template name="multi-replace">
<xsl:param name="string"/>
<xsl:param name="search-strings"/>
<xsl:param name="replace-strings"/>
<xsl:choose>
<xsl:when test="$search-strings">
<xsl:call-template name="multi-replace">
<xsl:with-param name="string" select="str:replace($string, $search-strings[1], $replace-strings[1])"/>
<xsl:with-param name="search-strings" select="$search-strings[position() > 1]"/>
<xsl:with-param name="replace-strings" select="$replace-strings[position() > 1]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
玛丽
羔羊
羊毛
约翰
狗
毛皮
应用于以下测试输入:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/input">
<output>
<xsl:choose>
<xsl:when test="function-available('str:replace')">
<xsl:value-of select="str:replace(string, search, replace)" />
</xsl:when>
<xsl:otherwise>
<xsl:text>function str:replace() is not supported</xsl:text>
</xsl:otherwise>
</xsl:choose>
</output>
</xsl:template>
</xsl:stylesheet>
<input>
<string>Mary had a little lamb, its fleece was white as snow.
And everywhere that Mary went, the lamb was sure to go.</string>
<search>Mary</search>
<search>lamb</search>
<search>fleece</search>
<replace>John</replace>
<replace>dog</replace>
<replace>fur</replace>
</input>
<input>
<string>Mary had a little lamb, its fleece was white as snow. And everywhere that Mary went, the lamb was sure to go.</string>
</input>
玛丽有一只小羊羔,羊毛像雪一样白。无论玛丽去哪里,羔羊都会去。
您应该看到以下结果:
<?xml version="1.0" encoding="utf-8"?>
<output>John had a little dog, its fur was white as snow. And everywhere that John went, the dog was sure to go.</output>
约翰有一只小狗,它的毛像雪一样白。无论约翰走到哪里,狗都肯定会去。
(我自己无法测试,因为我的处理器都不支持该功能)
这将使您非常接近指定的行为,除了一件事:规范声明“首先替换最长的搜索字符串”。如果您也想实现它,那么必须首先对字典字符串进行排序——如果您希望实现简单,那么应该成对输入字典字符串 您确定您的处理器支持此功能吗?--附言:将示例最小化到只展示问题所需的内容是最有帮助的。如果您的问题是函数,那么模板是完全不相关的,反之亦然。我相信它是这样的,因为我可以正常使用函数来替换字符串,只为第2个和第3个参数传递字符串。此外,使用节点集的方式,它可以工作,但只替换节点集中的第一个字符串。我只是后来把模板放在那里,试图调试正在发生的事情,它帮助我认识到问题是函数的代码,当它创建自己的
replace
节点时,似乎将它们放在了一个名称空间中,以后无法读取。对,我对搜索
和替换
的字符串也有同样的处理方法,但是当我根据文档为这些参数传入节点集时,它不起作用。@ragamufin对不起,我不明白你在说什么。在上面的示例中,str:replace()函数的最后两个参数是节点集。您的结果是什么?啊,不知什么原因,我没有在底部看到您的输入xml。约翰有一只小羊羔,它的羊毛像雪一样白。无论约翰走到哪里,羔羊都会去。。因此,即使在这种情况下,似乎也只替换了第一个节点。@ragamufin很好,现在我们知道了我们要处理的是什么-问题是您希望如何从这里开始。我已经在我的答案中添加了我认为最简单的方法。谢谢。在这个问题上,我尽了最大努力解释了一些事情,但我相信这有点混乱。然而,您在这里的方法很有意义,使用exslt.org中的模板代码,我也可以通过简单地按照上面的代码向模板添加xmlns=“”
,来实现这一点。事实上,我已经有了类似于您在这里发布的代码来替换几个字符串。当我意识到str:replace
可以获取节点集时,我希望通过使用函数语法使我的代码更加紧凑。。。