我有一个typeswitch函数可以将部分XML文件转换为HTML,但我希望能够区分相同标签的嵌入和非嵌入事件。例如,我想
<nym>John</nym>
和
<def><nym>John</nym></def>
由typeswitch进行不同的处理。我想要这样的东西:
declare
function app:transform($nodes as node()*){
for $node in $nodes
return
typeswitch ($node)
case text () return
$node
case element (nym) return ()
case element (def/nym) return
<a href="view.html?canonical={$node}">{$node/text()}</a>
default return ()
};
但这似乎不可能。还有另一种方法可以创造这种行为吗?
答案 0 :(得分:1)
您无法在typeswitch
表达式中直接处理此问题;你必须在返回表达式中使用条件:
case element (nym) return
if (nym[ancestor::def])
then <a href="view.html?canonical={$node}">{$node/text()}</a>
else ()
答案 1 :(得分:1)
两个答案:
如joemfb所建议的那样,对代码的最小动机的方式是在element(nym)
的规则中插入条件:
declare function app:transform(
$nodes as node()*
){
for $node in $nodes
return
typeswitch ($node)
case text () return
$node
case element (nym) return
if ($node/parent::def) then
<a href="view.html?canonical={$node}"
>{$node/text()}</a>
else
()
default return ()
};
条件不能进入typeswitch的case
子句,因为typeswitch子句采用序列类型,而不是匹配模式或位置路径:element()
是合法的位置路径,{{1 },但不是element(nym)
。
最简单的方式(在我看来似乎是这样)是放弃typeswitch并使用if-then-else结构。保持对序列类型进行测试的概念,如在当前代码中,您可以写:
element(def/nym)
但是由于我不确定我可以把手指放在上面的原因,以这种方式写下来感觉更自然:
declare function app:transform2(
$nodes as node()*
){
for $node in $nodes
return
if ($node instance of text()) then
$node
else if ($node instance of element(nym)
and not($node/parent::*
instance of element(def))) then
()
else if ($node instance of element(nym)
and $node/parent::*
instance of element(def)) then
<a href="view.html?canonical={$node}"
>{$node/text()}</a>
else ()
};
在我的(浅层)测试中,这些都会返回相同的结果。
答案 2 :(得分:0)
您可以在xpath表达式中使用谓词过滤器:
nym[parent::def]
nym[not(parent::def)]
这将测试直接父节点。如果要检查所有父母,请使用:
nym[ancestor::def]
nym[not(ancestor::def)]