This is newbie question. I am just start learning XQuery and XPath recently.
这是新手的问题。我最近刚刚开始学习XQuery和XPath。
Consider this XML
考虑这个XML
<employees>
<employee empid="1">
<ename>KING</ename>
<mgr></mgr>
<hiredate>17-11-1981</hiredate>
</employee>
<employee empid="2">
<ename>BLAKE</ename>
<mgr>7839</mgr>
<hiredate>1-5-1981</hiredate>
<test>
<sub1>one</sub1>
<sub2>two</sub2>
</test>
</employee>
When I execute the following XQuery,
当我执行以下XQuery时,
let $db := db:open("example")
for $item1 in $db/employees/employee,
$item2 in $db/employees/employee/test
return ($item1/mgr,$item1/ename,$item2/sub1)
I got...
我得到了……
<mgr/>
<ename>KING</ename>
<sub1>one</sub1>
<mgr>7839</mgr>
<ename>BLAKE</ename>
<sub1>one</sub1>
The result that I am hoping to get is...
我希望得到的结果是……
<mgr/>
<ename>KING</ename>
<mgr>7839</mgr>
<ename>BLAKE</ename>
<sub1>one</sub1>
This is because sub1 only exist in /employee/@empid='2'.
这是因为sub1只存在于/employee/@empid='2'中。
Can someone please point me to the right direction? Thanks
谁能给我指出正确的方向吗?谢谢
2 个解决方案
#1
3
In your for
expression
在你的表情
for $item1 in $db/employees/employee,
$item2 in $db/employees/employee/test
$item1
iterates through all the employees/employee
elements, and $item2
iterates through all the employees/employee/test
elements, independent of what the current value of $item1
is.
$item1遍历所有员工/员工元素,$item2遍历所有员工/员工/测试元素,与$item1的当前值无关。
To get what you need you might try this:
为了得到你需要的东西,你可以试试这个:
for $item1 in $db/employees/employee,
return ($item1/mgr,$item1/ename,
for $item2 in $item1/test
return $item2/sub1)
or, shorter:
或者,短:
$db/employees/employee/(mgr, ename, test/sub1)
#2
1
Here is one way to do it. Before returning, check with an if
statement whether test/sub1
exists or not.
这里有一个方法。在返回之前,检查if语句是否存在test/sub1。
I slightly changed the for clause as well, removing the db:open()
function, but it's easy to add it back in.
我还稍微修改了for子句,删除了db:open()函数,但是很容易将它添加回。
for $employee in /employees/employee
return
if ($employee/test/sub1)
then
($employee/mgr, $employee/ename, $employee/test/sub1)
else
($employee/mgr, $employee/ename)
and the result will be
结果是
<mgr/>
<ename>KING</ename>
<mgr>7839</mgr>
<ename>BLAKE</ename>
<sub1>one</sub1>
You said there is more than one ways to do this, can you please describe further
你说有不止一种方法可以做到这一点,你能进一步说明吗
A slightly different approach would be to use an if/then/else
XPath expression and unconditionally returning this expression:
另一种稍微不同的方法是使用if/then/else XPath表达式,并无条件地返回这个表达式:
for $employee in /employees/employee
return
($employee/mgr, $employee/ename, if ($employee/test/sub1) then $employee/test/sub1 else '')
And the answer by CiaPan shows yet another way, this time by nesting for
clauses. In my opinion, it is a little less straightforward but it works nevertheless. CiaPan also shows how a single XPath expression can potentially solve the problem - which is very straightforward!
CiaPan给出的答案是另一种方式,这次是嵌套子句。在我看来,这有点不太直接,但还是有效的。CiaPan还展示了单个XPath表达式如何可能解决问题——这非常简单!
#1
3
In your for
expression
在你的表情
for $item1 in $db/employees/employee,
$item2 in $db/employees/employee/test
$item1
iterates through all the employees/employee
elements, and $item2
iterates through all the employees/employee/test
elements, independent of what the current value of $item1
is.
$item1遍历所有员工/员工元素,$item2遍历所有员工/员工/测试元素,与$item1的当前值无关。
To get what you need you might try this:
为了得到你需要的东西,你可以试试这个:
for $item1 in $db/employees/employee,
return ($item1/mgr,$item1/ename,
for $item2 in $item1/test
return $item2/sub1)
or, shorter:
或者,短:
$db/employees/employee/(mgr, ename, test/sub1)
#2
1
Here is one way to do it. Before returning, check with an if
statement whether test/sub1
exists or not.
这里有一个方法。在返回之前,检查if语句是否存在test/sub1。
I slightly changed the for clause as well, removing the db:open()
function, but it's easy to add it back in.
我还稍微修改了for子句,删除了db:open()函数,但是很容易将它添加回。
for $employee in /employees/employee
return
if ($employee/test/sub1)
then
($employee/mgr, $employee/ename, $employee/test/sub1)
else
($employee/mgr, $employee/ename)
and the result will be
结果是
<mgr/>
<ename>KING</ename>
<mgr>7839</mgr>
<ename>BLAKE</ename>
<sub1>one</sub1>
You said there is more than one ways to do this, can you please describe further
你说有不止一种方法可以做到这一点,你能进一步说明吗
A slightly different approach would be to use an if/then/else
XPath expression and unconditionally returning this expression:
另一种稍微不同的方法是使用if/then/else XPath表达式,并无条件地返回这个表达式:
for $employee in /employees/employee
return
($employee/mgr, $employee/ename, if ($employee/test/sub1) then $employee/test/sub1 else '')
And the answer by CiaPan shows yet another way, this time by nesting for
clauses. In my opinion, it is a little less straightforward but it works nevertheless. CiaPan also shows how a single XPath expression can potentially solve the problem - which is very straightforward!
CiaPan给出的答案是另一种方式,这次是嵌套子句。在我看来,这有点不太直接,但还是有效的。CiaPan还展示了单个XPath表达式如何可能解决问题——这非常简单!