xquery之为什么这个 XQuery 过滤器会返回不需要的元素

sharpest 阅读:86 2025-01-19 22:14:33 评论:0

我正在使用实现 XQuery 3.1 的 BaseX 8.4.1

我正尝试在 XQuery 中做一些非常基本的事情,但我似乎无法弄明白。

我创建了一些示例数据来说明我正在尝试做的事情。我的数据集看起来像这样。它是一个简单的嵌入式结构。有几天,每天都有一些事件,事件有成员。

数据

<root> 
    <day> 
        <name>1</name> 
        <event> 
            <name>1</name> 
            <member>A</member> 
            <member>B</member> 
        </event> 
        <event> 
            <name>2</name> 
            <member>C</member> 
        </event> 
    </day> 
    <day> 
        <name>2</name> 
        <event> 
            <name>3</name> 
            <member>A</member> 
            <member>B</member> 
        </event> 
        <event> 
            <name>4</name> 
            <member>C</member> 
        </event> 
    </day> 
    <day> 
        <name>3</name> 
        <event> 
            <name>5</name> 
            <member>C</member> 
        </event> 
    </day> 
</root> 

我想做的是获取成员列表,并为每个成员获取他们举办事件的日期列表,以及他们举办的事件。所以结果应该是这样的:

期望的结果

<member> 
  <name>A</name> 
  <day> 
    <name>1</name> 
    <event> 
      <name>1</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
  </day> 
  <day> 
    <name>2</name> 
    <event> 
      <name>3</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
  </day> 
</member> 
<member> 
  <name>B</name> 
  <day> 
    <name>1</name> 
    <event> 
      <name>1</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
  </day> 
  <day> 
    <name>2</name> 
    <event> 
      <name>3</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
  </day> 
</member> 
<member> 
  <name>C</name> 
  <day> 
    <name>1</name> 
    <event> 
      <name>2</name> 
      <member>C</member> 
    </event> 
  </day> 
  <day> 
    <name>2</name> 
    <event> 
      <name>4</name> 
      <member>C</member> 
    </event> 
  </day> 
  <day> 
    <name>3</name> 
    <event> 
      <name>5</name> 
      <member>C</member> 
    </event> 
  </day> 
</member> 

为此,我尝试了以下 XQuery:

我尝试了什么

for $member in distinct-values(//member) 
return 
<member> 
  <name>{$member}</name> 
    {for $day in //day where $day/event/member = $member 
      let $event := $day/event where $event/member = $member 
    return  
      <day> 
        {$day/name} 
        {$event} 
    </day>} 
</member> 

但是,这不应用过滤。因此,我为他们不是成员的成员保留所有事件:

我得到了什么

<member> 
  <name>A</name> 
  <day> 
    <name>1</name> 
    <event> 
      <name>1</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
    <event> 
      <name>2</name> 
      <member>C</member> 
    </event> 
  </day> 
  <day> 
    <name>2</name> 
    <event> 
      <name>3</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
    <event> 
      <name>4</name> 
      <member>C</member> 
    </event> 
  </day> 
</member> 
<member> 
  <name>B</name> 
  <day> 
    <name>1</name> 
    <event> 
      <name>1</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
    <event> 
      <name>2</name> 
      <member>C</member> 
    </event> 
  </day> 
  <day> 
    <name>2</name> 
    <event> 
      <name>3</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
    <event> 
      <name>4</name> 
      <member>C</member> 
    </event> 
  </day> 
</member> 
<member> 
  <name>C</name> 
  <day> 
    <name>1</name> 
    <event> 
      <name>1</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
    <event> 
      <name>2</name> 
      <member>C</member> 
    </event> 
  </day> 
  <day> 
    <name>2</name> 
    <event> 
      <name>3</name> 
      <member>A</member> 
      <member>B</member> 
    </event> 
    <event> 
      <name>4</name> 
      <member>C</member> 
    </event> 
  </day> 
  <day> 
    <name>3</name> 
    <event> 
      <name>5</name> 
      <member>C</member> 
    </event> 
  </day> 
</member> 

当然,这应该很容易,不是吗?

请您参考如下方法:

这是一个非常小的问题。您想要过滤事件,并将 $events 定义为 $day 的所有事件的序列。然后,您使用 = 运算符进行过滤,该运算符具有设置的语义——如果左侧的任何项目(所有 当天的事件成员)等于任何项目在右侧(当前 $member),where 子句的计算结果为 true

改为循环处理事件。

for $member in distinct-values(//member) 
return 
<member> 
  <name>{$member}</name> 
    {for $day in //day where $day/event/member = $member 
      (: for instead of let :) 
      for $event in $day/event where $event/member = $member 
    return  
      <day> 
        {$day/name} 
        {$event} 
    </day>} 
</member> 

使用谓词而不是 where 子句通常会使代码更易于阅读并且嵌套的显式循环更少。这是一个清理过的例子:

for $member in distinct-values(//member) 
return 
  <member>{ 
    <name>{ $member }</name>, 
    for $day in //day[event/member = $member] 
    return  
      <day>{ 
        $day/name, 
        $day/event[member = $member] 
      }</day> 
  }</member> 


标签:程序员
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号