Найти ближайшего предка / брата, который соответствует критериям - PullRequest
1 голос
/ 14 декабря 2011

У меня есть XML, который состоит из узлов-контейнеров, содержащих различные дочерние узлы, включая другие узлы-контейнеры. Пример XML будет выглядеть как ...

<CONTAINER>
    <SEARCHFOR />
    <ITEM/>
    <ITEM/>
    <ITEM/>
    <ITEM/>
    <ITEM/>
    <CONTAINER>
        <SEARCHFOR />
        <ITEM/>
        <ITEM/>
        <CONTAINER>
            <SEARCHFOR />
            <ITEM id="1" />
            <ITEM/>
            <ITEM/>
            <CONTAINER>
                <ITEM id="2" />
            </CONTAINER>
        </CONTAINER>
    </CONTAINER>
</CONTAINER>

Я бы хотел найти узел SEARCHFOR, ближайший (по объему) к ПУНКТУ, имеющий id = 2. Узел SEARCHFOR может быть предшествующим узлом ITEM или дочерним узлом предка CONTAINER. У меня есть выражение XPath, которое может найти все узлы SEARCHFOR, находящиеся в области видимости, которые соответствуют критериям, но я не могу заставить его вернуть только один ближайший элемент.

//ITEM[@id="2"]/ancestor::CONTAINER/SEARCHFOR

Я тестирую в Sketchpath и буду реализовывать это в Delphi, используя анализатор XML, который может обрабатывать XPath 2.0, так что синтаксис также приемлем. Я могу сделать это в коде, получив свои результаты и используя Delphi, чтобы получить тот, который представляет интерес, но, если это вообще возможно, мне действительно нужно, чтобы это было сделано в самом XPath для моей реализации. Любая помощь приветствуется.

Спасибо, Michael

Ответы [ 2 ]

1 голос
/ 14 декабря 2011

Ось preceding выполняет поиск в обратном порядке документов, поэтому выбор первого такого предшествующего элемента работает должным образом (при условии, что мы можем предположить, что элементы SEARCHFOR сами по себе не являются предками цели ITEM):

(//ITEM[@id='2']/preceding::SEARCHFOR[parent::CONTAINER])[1]

Можем ли мы также предположить, что SEARCHFOR элементы всегда находятся в CONTAINER? Если это так, то нам не нужна эта явная проверка, что делает ее еще короче:

(//ITEM[@id='2']/preceding::SEARCHFOR)[1]
1 голос
/ 14 декабря 2011

Может быть, это выражение XPath 2.0 отвечает на ваш вопрос:

(//ITEM[@id='2']/(ancestor::CONTAINER/SEARCHFOR|preceding-sibling::SEARCHFOR))[last()]

Он работает, выстраивая последовательность элементов в порядке документа, затем выбирает последний, который, согласно вашему описанию, является ближайшим (если я вас правильно понял).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...