Xquery for-if-then-else意外输出

时间:2014-08-31 03:00:50

标签: xml xquery

我正在尝试返回一些输出,而且我遇到了一些困难,很可能我对Xquery for-if-then-else语句没有正确的理解。

for $S in doc("prac5a.xml")/enrolment
return
  <enrolment>{
    for $s in//student, $e in//enrol
    return
      if($s/id = $e/stud) then
        <student>{$s/id, $s/name, $e/crs}</student>
      else <student>{$s/id, $s/name}</student>
  }</enrolment>

从此,我期待输出类似的东西;

<enrolment>
    <student>
        <id>s1</id>
        <name>John</name>
        <crs>c1</crs>
        <crs>c2</crs>
    </student>
    <student>
        <id>s2</id>
        <name>Peter</name>
        <crs>c2</crs>
        <crs>c3</crs>
    </student>
    <student>
        <id>s3</id>
        <name>Rob</name>
    </student>

相反,我得到了这个;

<?xml version="1.0" encoding="UTF-8"?>
<enrolment>
   <student>
      <id>s1</id>
      <name>John</name>
      <crs>c1</crs>
      <crs>c2</crs>
   </student>
   <student>
      <id>s1</id>
      <name>John</name>
   </student>
   <student>
      <id>s2</id>
      <name>Peter</name>
   </student>
   <student>
      <id>s2</id>
      <name>Peter</name>
      <crs>c2</crs>
      <crs>c3</crs>
   </student>
   <student>
      <id>s3</id>
      <name>Rob</name>
   </student>
   <student>
      <id>s3</id>
      <name>Rob</name>
   </student>
</enrolment>

为什么?或者更重要的是,我想我怎样才能得到理想的结果。

2 个答案:

答案 0 :(得分:1)

如果没有原始数据,我无法提供完整的解决方案,但是您的迭代问题是由您在FLWOR语句中使用for ... in子句引起的。 for ... in子句中的多个变量绑定是嵌套循环的简写,本示例应该演示:

for $x in (1, 2), $y in (3, 4)
return $x || "-" || $y

返回

1-3
1-4
2-3
2-4

您的代码中也存在一些拼写错误; for $s in//student, $e in//enrol无效XQuery(或可能是,但意味着student中的每个enrolfn:collection()元素。假设您想要for $st in $s//student, $e in $st//enrol之类的内容(并且取决于输入文档的结构),以下更改可以解决您的问题:

for $st in $s//student
let $e := $st//enrol
...

答案 1 :(得分:0)

由于您的问题都缺少示例数据和描述您想要实现的内容,因此这个答案包括一些猜测。

您当前的查询会对所有学生和课程执行交叉产品,如果他正在访问该课程,则会返回学生的新元素 - 或者仅包含学生的新元素。我想想你想要的是一个学生名单,以及他们注册的课程。这样的查询可能是:

<enrolment>{ (: Wrapper element for all students :)
  let $doc := doc("prac5a.xml")/enrolment (: Access the document, see note below :)
  for $student in $doc//student (: Loop over all students :)
  return <student>{
    $student/id,
    $student/name,
    $doc/enrol[$student/id = stud] (: Find all enrolments of this particular students, implicit loop :)
  }</student>
}</enrolment>

我添加了一些关于差异的评论(除了有意义的变量名称:从不使用单字母变量名称,使用描述性名称是免费的,并且减少了大量代码片段的复杂性)。需要注意的一件事是打开文档/数据库:将包装元素<enrolment/>)的内容绑定到$S,但从不使用它;相反,你从当前的上下文开始访问。我明确地加载并使用了该文档。