Использование XPath для извлечения нескольких относительных узлов - PullRequest
0 голосов
/ 19 июля 2011

Показанный XML является упрощенной версией того, с чем я работаю.Я использую PHP, а также DOMDocument и DOMXPath.

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

Вот пример XML:

<w:p>        
    <w:r>
        <w:rPr>...</w:rPr>
        <w:t>Text</w:t>
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="begin" />
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:instrText> MERGEFIELD  [PatName]  \* MERGEFORMAT  </w:instrText>
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="separate" />
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:t>[PatName]</w:t>
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="end" />
    </w:r>
</w:p>

Начальным узлом для работы является узел w: instrText с XPath, похожим на:

//w:r[contains(w:instrText,'MERGFIELD [PatFirstName]')].

Тогда я могу использовать предыдущийось-брат, чтобы найти предыдущий элемент.XPath выглядит следующим образом:

//w:r[contains(w:instrText,'MERGFIELD [PatFirstName]')]/preceding-sibling::w:r[1].

Затем я хотел бы получить оригинальный w: r, содержащий w: instrText, и два оставшихся узла w: r, содержащих w: fldChar, оставив узел w: tвне выбора.Но мои попытки написать XPath для этого потерпели неудачу:

//w:r[contains(w:instrText,'MERGEFIELD  [PatFirstName]')]/preceding-sibling::w:r[1]/following-sibling::w:r[1 and 2] 

захватывает слишком много узлов, возможно, потому что условие содержит оригинал, не относится к условиям следующего брата).

В конечном счете,из этого фрагмента будут извлечены следующие записи.

    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="begin" />
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:instrText> MERGEFIELD  [PatName]  \* MERGEFORMAT  </w:instrText>
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="separate" />
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="end" />
    </w:r>

Важно, чтобы для поиска использовались относительные узлы, поскольку в XML могут быть и другие похожие комбинации узлов.

НекоторыеВы можете распознать этот XML как формат Word 2003 XML для поля слияния, при этом большая часть ненужной информации удалена.Я пытаюсь изолировать узел w: r, содержащий w: t, чтобы я мог обновить его и удалить окружающие узлы, используемые для его идентификации как поля слияния.

1 Ответ

0 голосов
/ 19 июля 2011

Я пришел к выводу, что то, что я спрашиваю, слишком амбициозно только для XPath. Оси «следующий брат» и «предыдущий брат» - это 1 или все сделки (если кто-то не может показать мне иначе).

Я закончил тем, что использовал XPath, чтобы получить узел w: t, который мне интересно заменить, основываясь на MERGEFIELD, а затем я прошёл DOM, используя DOMDocument в PHP для удаления других узлов.

Вот XPATH, который я в итоге использовал, выраженный как присвоение переменной в PHP.

$query = '//w:r[preceding-sibling::w:r[2][contains(w:instrText,\'MERGEFIELD  '.$mergeField.'\')]]/w:t';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...