Найти родительский узел по тексту содержимого узла - PullRequest
0 голосов
/ 01 февраля 2011

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

пример:

<div>
    <h1>Node to find</h1>
    <p>another node</p>
</div>

Весь мой код знает, что это за текст в узлеЭто и мой сценарий должен выяснить, в каком узле содержится текст.

я пробовал следующие xpaths:

 1. //*[. = "'. $text .'"]
 2. //*[contains(., "'. $text .'")]

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

Спасибо за любую помощь.

Ответы [ 2 ]

3 голосов
/ 01 февраля 2011

Я не уверен, что понимаю часть "'. $text .'" вашего ответа ... Я предполагаю, что это означает некоторый пример текста, а не предполагаемую ссылку на переменную с именем text?

В любом случае, когда вы используете contains(., "foo"), вы спрашиваете, содержит ли строковое значение текущего узла "foo". Строковое значение текущего узла является объединением всех строковых значений текстовых узлов Потомок . Вот почему //*[contains(., "foo")] возвращает список узлов: он соответствует каждому предку каждого текстового узла, содержащего «foo». (И это может быть очень неэффективно, потому что вы выполняете эту функцию конкатенации на каждом узле дерева.)

Причина, по которой ваш starts-with() ответ сработал (иногда), заключается в том, что вам повезло: родительский узел текстового узла имел других предшествующих братьев и сестер со своим собственным текстом, поэтому текстовое значение узла бабушки и дедушки начиналось с чего-то другого. Тоже очень неэффективно ...

Если искомый текст будет находиться только в одном текстовом узле, т. Е. Он не будет разбит на несколько элементов / комментариев / и т. Д., То вы сможете эффективно и точно сопоставить только элемент, содержащий текст узел, используя [отредактировано] :

//*[text()[contains(., "foo")]]

(похоже на то, что сказал @biziclop).

Если просматриваемый текст может быть разбит на несколько элементов / комментариев / и т. Д., То вы можете использовать это [отредактировано, дважды] :

//*[contains(., "foo") and not(*[contains(., "foo")])]

Но это довольно неэффективно. Следующее не гарантируется для работы:

//*[contains(., "foo")][1]

Это даст вам [отредактировано, дважды] каждый элемент , который является первым дочерним элементом его родителя (который является предком того, который) содержит текст . (Или пустой набор узлов, если «foo» не найден.) Я доверяю @Alejandro в этом ... Я до сих пор не усвоил, как определить, когда [position () = x] применяется к самому последнему шагу определения местоположения. только. В любом случае, это выражение XPath не гарантирует правильного результата.

1 голос
/ 01 февраля 2011

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

Классическим ответом будет:

//*[text()[contains(.,$pText)]]

Значение: любой элемент, имеющий хотя бы один дочерний узел текстового узла, содержащий $pText значение строки ссылки на переменную / параметр как частьего строковое значение

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

//*[contains(.,$pText)][not(*[contains(.,$pText)])]

Значение: любой элемент, содержащий $pText как часть его строкового значения, не имеющий дочернего элемента с$pText как часть его строкового значения .Другими словами, самый внутренний элемент, содержащий $pText строковое значение.

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