и-запрос на соответствие значению атрибута и значению подэлемента - PullRequest
1 голос
/ 07 мая 2020

У меня есть документы, содержащие такие структуры, как:

<Reviews>
    <Review complete="false">
        <StartDate>2019-03-05T06:00:00Z</StartDate>
        <EndDate>2019-03-12T05:00:00Z</EndDate>
        <Reviewers>
            <Reviewer userName="jdoe">
                <ReviewStatus>Completed</ReviewStatus>
            </Reviewer>
        </Reviewers>
    </Review>
    <Review complete="false">
        <StartDate>2019-03-06T06:00:00Z</StartDate>
        <EndDate>2019-03-13T05:00:00Z</EndDate>
        <Reviewers>
            <Reviewer userName="jsmith">
                <ReviewStatus>Pending</ReviewStatus>
            </Reviewer>
            <Reviewer userName="jdoe">
                <ReviewStatus>Completed</ReviewStatus>
            </Reviewer>
        </Reviewers>
   </Review>
</Reviews>

Используя MarkLogi c XQuery, я хочу найти документы, в которых есть элемент Reviewer для jsmith И с his ReviewStatus = Завершено. Т.е. я не хочу видеть этот пример выше в моих результатах, потому что jsmith ReviewStatus не завершен. Я пробовал несколько разных типов запросов, где cts:and-query() использует комбинации значений атрибута, слова элемента и даже запросов диапазона пути. Но я не понял, как найти только те документы, которые содержат элемент Reviewer, где значение атрибута userName совпадает с «jsmith» И значение дочернего элемента ReviewStatus совпадает с «Completed» в том же элементе Reviewer. Может ли кто-нибудь предложить подход к этому?

1 Ответ

3 голосов
/ 07 мая 2020

Вам нужны запросы для определения объема, например cts:element-query. Это позволяет вам выбрать совместного предка для подзапросов. Вот код, который показывает, как это работает:

let $search-name := "jsmith"
let $search-status := "Completed"

let $xml := <Reviews>
    <Review complete="false">
        <StartDate>2019-03-05T06:00:00Z</StartDate>
        <EndDate>2019-03-12T05:00:00Z</EndDate>
        <Reviewers>
            <Reviewer userName="jsmith">
                <ReviewStatus>Completed</ReviewStatus>
            </Reviewer>
            <Reviewer userName="jdoe">
                <ReviewStatus>Pending</ReviewStatus>
            </Reviewer>
        </Reviewers>
    </Review>
    <Review complete="false">
        <StartDate>2019-03-06T06:00:00Z</StartDate>
        <EndDate>2019-03-13T05:00:00Z</EndDate>
        <Reviewers>
            <Reviewer userName="jsmith">
                <ReviewStatus>Pending</ReviewStatus>
            </Reviewer>
            <Reviewer userName="jdoe">
                <ReviewStatus>Completed</ReviewStatus>
            </Reviewer>
        </Reviewers>
   </Review>
</Reviews>
for $rev in $xml//Reviewer
where cts:contains(
  $rev,
  cts:element-query(
    xs:QName("Reviewer"),
    cts:and-query((
      cts:element-attribute-value-query(xs:QName("Reviewer"), xs:QName("userName"), $search-name),
      cts:element-value-query(xs:QName("ReviewStatus"), $search-status)
    ))
  )
)
return $rev

Обратите внимание, что вам нужно будет включить индексы позиций, если вам нужны точные результаты для нефильтрованного поиска.

HTH!

...