以下は、引用符で囲まれた文字列と引用符で囲まれていない文字列の任意の組み合わせ (任意の順序) を目的の方法で処理する単一の 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>