XQuery switch函数中case表达式对<spip:img>元素不生效问题
解决spip:img元素无法匹配switch case的问题
看起来你的问题大概率出在switch语句的语法使用错误或者命名空间/节点选择逻辑的细节上,咱们一步步拆解解决:
1. 修正Switch语句的语法(最可能的原因)
你当前的switch写法不符合标准XQuery的模式匹配规则——XQuery的switch的case后面应该跟匹配模式,而非直接写布尔表达式。虽然有些实现可能支持非标准的布尔case,但这种写法容易导致逻辑异常,也是你img分支不生效的核心原因之一。
把你的函数改成带where子句的标准模式匹配写法:
declare function p($node as element(spip:p)+, $options as map(*)) { switch ($node) case $n where exists($n/spip:img) and not($n/text()[normalize-space(.) != '']) return passthru($n, $options) case $n where exists($n/spip:figure) and not($n/text()[normalize-space(.) != '']) return passthru($n, $options) case $n where exists($n/spip:blockquote) and not($n/text()[normalize-space(.) != '']) return passthru($n, $options) default return <para> <alinea>{ passthru($node, $options) }</alinea> </para> };
这里用exists($n/spip:img)替代instance of,直接检查spip:p下是否存在spip:img子元素,逻辑更清晰且更可靠。
2. 确认命名空间绑定与元素实际命名空间一致
你提到XML是带有spip命名空间的,但示例中写的是<p><img/></p>——要确保:
- XML中的img元素确实带有spip前缀(即
<spip:img/>),并且属于正确的spip命名空间; - 你的XQuery prolog中已经正确声明了spip命名空间,比如:
declare namespace spip = "http://your-spip-namespace-uri";
如果img元素没有使用spip命名空间,那$n/spip:img会找不到节点,自然无法匹配case。
3. 简化文本节点检查逻辑
你当前的文本检查fn:not($node/text()[fn:normalize-space(.) != ''])可以简化为not(normalize-space($node/text())),效果一致但更易读:
case $n where exists($n/spip:img) and not(normalize-space($node/text()))
4. 备选方案:改用if-then-else(既然你说这个逻辑在if里有效)
如果switch的模式匹配还是有问题,直接换成你验证过的if-then-else写法,逻辑更直观:
declare function p($node as element(spip:p)+, $options as map(*)) { if (exists($node/spip:img) and not(normalize-space($node/text()))) then passthru($node, $options) else if (exists($node/spip:figure) and not(normalize-space($node/text()))) then passthru($node, $options) else if (exists($node/spip:blockquote) and not(normalize-space($node/text()))) then passthru($node, $options) else <para> <alinea>{ passthru($node, $options) }</alinea> </para> };
你可以先尝试修正switch的语法,这应该能解决大部分问题。如果还是不行,检查命名空间是否匹配,或者直接改用if-then-else写法。
内容的提问来源于stack exchange,提问作者laconis




