XQuery: искать узел с потомками в определенном порядке - PullRequest
4 голосов
/ 16 января 2020

У меня есть XML файл, который представляет синтаксические деревья всех предложений в книге:

<book>
    <sentence>
        <w class="pronoun" role="subject">
            I
        </w>
        <wg type="verb phrase">
            <w class="verb" role="verb">
                like
            </w>
            <wg type="noun phrase" role="object">
                <w class="adj">
                    green
                </w>
                <w class="noun">
                    eggs
                </w>
            </wg>
        </wg>
    </sentence>
    <sentence>
        ...
    </sentence>
    ...
</book>

Этот пример - фальшивка, но дело в том, что фактические слова (<w> элементы) вкладываются непредсказуемым образом на основе отношений syntacti c.

Я пытаюсь найти <sentence> узлов с <w> дочерними элементами, соответствующими определенным критериям в определенном порядке . Например, я могу искать предложение с потомком w[@class='pronoun'], за которым следует потомок w[@class='verb'].

Легко найти предложения, которые просто содержат обоих потомков, не заботясь о порядке:

//sentence[descendant::w[criteria1] and descendant::w[criteria2]]

Мне удалось выяснить этот запрос, который выполняет то, что я хочу, который ищет <w> со следующим <w>, соответствующим критериям того же самого ближайшего <sentence> предка:

for $sentence in //sentence
where $sentence[descendant::w[criteria1 and 
    following::w[(ancestor::sentence[1] = $sentence) and criteria2]]]
return ...

... но, к сожалению, это очень медленно, и я не уверен, почему.

Есть ли медленный способ поиска узла, который содержит критерии соответствия потомков в определенном порядке? Я использую XQuery 3.1 с BaseX. Если я не могу найти разумный способ сделать это с XQuery, план Б состоит в том, чтобы выполнить постобработку с Python.

1 Ответ

6 голосов
/ 16 января 2020

Ось following действительно дорогая, поскольку охватывает все последующие узлы документа, которые не являются ни потомками, ни предками.

Операторы сравнения узлов (<<, >>, is) может помочь вам здесь В приведенном ниже примере кода проверяется, существует ли хотя бы один глагол, за которым следует существительное:

for $sentence in //sentence
let $words1 := $sentence//w[@class = 'verb']
let $words2 := $sentence//w[@class = 'noun']
where some $w1 in $words1 satisfies 
      some $w2 in $words2 satisfies $w1 << $w2
return $sentence
...