xquery: поиск по переменному набору узлов - PullRequest
2 голосов
/ 22 мая 2011

Я использую BaseX XML Database.Рассмотрим XML-документ в базе данных следующим образом:

<entries>
<book-entry>
  <book>Book 1</book>
  <author>Author 1 ABC</author>
  <title>Title 1</title>
</book-entry>
<car-entry>
  <car>Car 1</car>
  <model>Model 1</model>
  <price>Price 1 ABC</price>
</car-entry>
</entries>

Я пытаюсь выполнить поиск с различными вариантами, такими как: поиск только по книгам, только по автомобилям, по книгам и по машинам.

Я пытаюсь использовать переменную xml в своем xquery для получения результатов поиска на основе требуемого типа поиска.

Пример значений переменных: - <types><type>book-entry</type></types>: поиск только по записям в книгах - <types><type>car-entry</type></types>: поиск только по записям автомобилей - <types><type>book-entry</type><type>car-entry</type></types>: поиск по записям книг и записям автомобилей

Пример XQuery:

declare variable $doc_name as xs:string external; (: name of xml document :)
declare variable $search_types as xs:anyAtomicType external; (: one of the example variable values shown above :)
declare variable $search_key as xs:string external; (: eg: ABC :)

for $entry in doc($doc_name)/entries[*[exists($search_types/types/type/text() = node-name(.)) and .//text() contains text $search_key]]
  return $entry

Приведенный выше запрос возвращает записи об автомобиле и книге, содержащие текстовый дочерний узел ABC, хотя я передаю <types><type>car-entry</type></types> в $ search_types.

Как ограничить поиск с помощью переменной xml?Есть ли лучший способ сделать это?Кроме того, xquery должен возвращать как автомобили, так и записи, если переменная xml имеет дочерние узлы обоих типов.

Спасибо, Sony

Ответы [ 2 ]

1 голос
/ 22 мая 2011
for $entry in doc($doc_name)/entries
         [*[exists($search_types/types/type/text() = node-name(.)) 
        and 
          .//text() contains text $search_key
           ]
         ]  return $entry

Должно быть :

for $entry in doc($doc_name)/entries/*
        [exists($search_types/types/type/text() = node-name(.)) 
       and 
         .//text() contains text $search_key]  
  return $entry

Или, в качестве альтернативы, можно использовать это простое выражение XPath :

/*/*[name() eq $vSearchTypes/types/type
   and
     .//text()[contains(., $vSearchKey)]
    ]

Наконец, это выражение XQuery :

let $vSearchTypes :=
  <types>
    <type>book-entry</type>
</types>,

$vSearchKey := 'ABC'

return
  /*/*[name(.) eq $vSearchTypes/type
        and
          .//text()[contains(., $vSearchKey)]
         ]

при применении к предоставленному документу XML:

<entries>
  <book-entry>
    <book>Book 1</book>
    <author>Author 1 ABC</author>
    <title>Title 1</title>
  </book-entry>
  <car-entry>
    <car>Car 1</car>
    <model>Model 1</model>
    <price>Price 1 ABC</price>
  </car-entry>
</entries>

дает желаемый, правильный результат :

<book-entry>
    <book>Book 1</book>
    <author>Author 1 ABC</author>
    <title>Title 1</title>
  </book-entry>
0 голосов
/ 22 мая 2011

для вашего вопроса 1 - вы можете попытаться с помощью fn: data () экранировать все пользовательские входные значения из специфической вещи Xml.

для вашего вопроса 2 - если вы используете какую-либо базу данных Xml, попытайтесь использовать API поиска по базе данных, а не Xpath. если нет, вам нужно придумать некоторый абстрактный слой поиска xquery, который может формировать грамматику XPath, а не следовать непосредственно через xpath.

...