1

悪夢からXMLデータベースにアクセスする最近の試みで、私は非常に近づきました。テストデータベースを使用して、実際に成功しました。ただし、BaseXサンプルデータベースではなく、実際にアクセスしようとしているデータベースに適用すると、XMLファイルに関する有効な苦情である特別なブランドのエラーが発生します。

http://basex.org/products/live-demo/経由

doc('test'):=

<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

別の解決策 ( predicate[...]では、各項目がコンテキスト項目にバインドされ、.1 つずつ処理されます):

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

クリスチャンが述べたように、contains() xpath 関数は単一のノードを想定していますが、xml ルートには xpath 式によって返されるノードが 2 つあります。したがって、XQuery は次のように記述できます。

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

ここで注意すべきもう 1 つの重要な点は、contains() 関数の使用法です。この関数は、文字列が全体または一部として Main 文字列に含まれている場合に 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 に答える