1

在我最近一次从噩梦中访问 XML 数据库的尝试中,我已经非常接近了。我实际上成功了,使用测试数据库;但是,当我将它应用于我实际尝试访问的数据库而不是 BaseX 示例数据库时,我得到一个特殊品牌的错误,这是对 XML 文件的有效投诉:

通过http://basex.org/products/live-demo/

文档(“测试”):=

<item>
<item_number>1171270</item_number>
<seller_info>
<seller_company_id>6356</seller_company_id>
<seller_rating>C31</seller_rating>
<seller_rating>T150 hr.</seller_rating>
</seller_info>
<product_info>
<unit>2022</unit>
<sinfo>55 cases</sinfo>
<sinfo>Yu-gi-oh trading card pack</sinfo>
<sinfo>.45kg per unit</sinfo>
<sinfo>24.7500kg shipment</sinfo>
</product_info>
<product_info>
<unit>9291</unit>
<sinfo>7 units</sinfo>
<sinfo>Naruto, Classic, action figure</sinfo>
<sinfo>1.8kg per unit</sinfo>
<sinfo>12.6kg shipment</sinfo>
</product_info>
</item>

0:编写您自己的查询... :=

let $doc := doc('test') 
for $v in $doc//item
where contains($v/product_info/unit,'9291')
return 
$v/seller_info/seller_company_id

回报:

Error:
Stopped at line 3, column 39: [XPTY0004] Single item expected, (element unit { ... }, element unit { ... }) found.

我不能说我没想到会遇到这样的问题。不幸的是,我没有格式化 XML 文档——其他人做了——而且它的格式都非常糟糕,如您所见。我试图访问它的部分原因是:重组它。

有没有办法运行我试图在文档上运行的查询并获得结果而不会让这个错误吐在我身上?Single item expected当我尝试将目标定位sinfo为返回值时,我也在查看我的退货中的错误,对吗?有没有办法得到,例如,all of the sinfo's?或者只有the second sinfo for each product_info不让这个讨厌的错误向我吐口水怎么样?

4

3 回答 3

9

where 子句中的路径$v/product_info/unit每次调用将产生多个项目,而该contains()函数仅接受单个项目作为参数。以下查询将为您提供预期的结果:

let $doc := doc('test') 
for $v in $doc//item
where some $i in $v/product_info/unit satisfies contains($i,'9291')
return $v/seller_info/seller_company_id

另一种解决方案(在谓词[...]中,每个项目将绑定到上下文项目.并逐个处理):

let $doc := doc('test') 
for $v in $doc//item
where $v/product_info/unit[contains(.,'9291')]
return $v/seller_info/seller_company_id
于 2012-09-18T10:24:37.397 回答
2

正如 Christian 所提到的, contains() xpath 函数需要一个节点,但是由于在您的 xml 根目录中,xpath 表达式返回了两个节点。因此 XQuery 可以写成

let $doc := doc('test')  
for $v in $doc//item 
where $v/product_info/unit[.='9291']
return  $v/seller_info/seller_company_id

这里要注意的另一件重要事情是 contains() 函数的用法。如果字符串作为一个整体或一部分包含在主字符串中,则此函数返回 true。这意味着对于具有以下值的单位,它将返回 true

9291

1 9291

23171239291 237283

...

因此,建议根据需要使用正确的功能。

于 2012-09-18T10:43:39.970 回答
1

您向我们展示了一个不正确的查询,并要求我们从中猜测您的实际意图,这不一定是可能的。但是,我的猜测是,如果 $v/product_info/unit 的多个值中的任何一个等于“9291”,您希望 where 子句返回 true。您犯了一个常见错误,即假设 contains() 函数测试一组值是否包含特定值,而它实际上测试字符串是否包含特定子字符串。要测试一组值是否包含特定值,请使用“=”运算符:

where $v/product_info/unit = '9291'
于 2012-09-18T20:47:46.770 回答