在节点中,字符串可能包含一个或多个由单引号或双引号分隔的子字符串。例如
<node>Some text "and Some" More</node>
我要做的是将未被引号括起来的文本小写,因此结果应如下所示:
some text "and Some" more
我尝试了两件事:
replace
:replace('Some text "and Some" More', '"([^"]*)"', '*')
这将用双引号替换带*的文本。但我怎么能小写呢?这不会产生预期的结果:replace('Some text "and Some" More', '"([^"]*)"', lower-case('$1'))
tokenize
:for $t in tokenize('Some text "and Some" More', '"') return $t
。由于我的节点不以“开头”,我知道奇数条目将是由引号包围的子串。但我不知道如何选择和小写只有奇数条目。我试过position()
但每次迭代时返回1。感谢您对此进行调查。非常感谢。
答案 0 :(得分:1)
呼。
如果您喜欢这样的话:
concat(translate(substring-before(//node/text(), '"'),'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') ,substring(substring-after(//node/text(), '"'), 1, string-length(substring-after(//node/text(), '"')) - string-length(substring-after(substring-after(//node/text(), '"'), '"')) -1) , translate(substring-after(substring-after(//node/text(), '"'), '"'), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'))
只需将XP //node/text()
替换为XPath,即可获得所需文本。
我只是为了好玩而这样做,这不是最干净的&#34; (HA!)解决方案。
您可以通过确保放入的节点是上下文节点,或者为其提供更直接的路径来加快速度。
答案 1 :(得分:1)
在XQuery中,您可以使用
string-join(
for $x at $i in tokenize('Some text "and Some" More', '"') return
if ($i mod 2 = 1) then lower-case($x)
else $x
, '"')
但是xpath只有在没有at的情况下瘫痪。
在XPath 3中你可以使用!简单的map运算符(有点像for,除了它设置。和position()):
string-join(
tokenize('Some text "and Some" More', '"') !
if (position() mod 2 = 1) then lower-case(.)
else .
, '"')
最后在 XPath 2 中,您可以迭代索引并获取每个索引的子字符串:
string-join(
for $i in 1 to count(tokenize('Some text "and Some" More', '"')) return
if ($i mod 2 = 1) then lower-case(tokenize('Some text "and Some" More', '"')[$i])
else tokenize('Some text "and Some" More', '"')[$i]
, '"')
答案 2 :(得分:1)
这是一个单独的XPath 2.0表达式,以任意顺序处理引用和未引用字符串的任何混合 - 按任意顺序:
string-join(
(for $str in tokenize(replace(., "(.*?)("".*?"")([^""]*)", "|$1|$2|$3|", "x"),"\|")
return
if(not(contains($str, """")))
then lower-case($str)
else $str
),
"")
要进行全面测试,我会在以下XML文档中评估上述表达式:
<node>Some "Text""and Some" More "Text" XXX "Even More"</node>
产生了想要的正确结果:
some "Text""and Some" more "Text" xxx "Even More"
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:template match="/">
<xsl:sequence select=
'string-join(
(for $str in tokenize(replace(., "(.*?)("".*?"")([^""]*)", "|$1|$2|$3|", "x"),"\|")
return
if(not(contains($str, """")))
then lower-case($str)
else $str
),
"")
'/>
</xsl:template>
</xsl:stylesheet>
当对上述XML文档应用此转换时,将评估XPath表达式,并将此评估的结果复制到输出:
some "Text""and Some" more "Text" xxx "Even More"
最后,一个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:template match="/*">
<xsl:analyze-string select="." regex='".*?"'>
<xsl:non-matching-substring>
<xsl:sequence select="lower-case(.)"/>
</xsl:non-matching-substring>
<xsl:matching-substring><xsl:sequence select="."/></xsl:matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>