使用XQuery typeswitch以不同方式处理嵌套标签

时间:2014-04-15 11:48:29

标签: xml xquery

我有一个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 ()
};

但这似乎不可能。还有另一种方法可以创造这种行为吗?

3 个答案:

答案 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)]