Я думаю, что вы неправильно диагностировали ситуацию, и причина неправильного диагноза (если провести аналогию слишком далеко) заключается в том, что вы рассмотрели симптомы примерно 7 пациентов, а не пошли в медицинский институт и не изучали анатомию.
«Анатомия» здесь — это модель данных XDM, которая лежит в основе семантики XPath. Обратите внимание, в частности, что
(а) когда у вас есть такая структура
<title>Water</title>
есть узел элемента, строковое значение которого равно «Вода» и который является родителем одного текстового узла, строковым значением которого также является «Вода».
(b) когда у вас есть такая структура
<title>H<sub>2</sub>O</title>
есть узел элемента со строковым значением "H2O", который является родителем трех дочерних элементов: текстовый узел со строковым значением "H", узел элемента со строковым значением "2" (который сам является родителем другого текстового узел...) и второй текстовый узел со строковым значением "O".
В случае (а) почти все операции дают одинаковый результат независимо от того, применены ли они к узлу элемента или узлу текста. Например, contains($x, "ate")
будет истинным, независимо от того, является ли $x
узлом элемента или текстовым узлом. Так что добавление /text()
к пути вообще избыточно: не вредит, но и не нужно. Мы часто советуем не делать этого, потому что это делает ваш код более хрупким, если структура данных позже изменится, не говоря уже о простом добавлении ненужного многословия.
В случае (b) добавление /text()
к вашему пути приводит к тому, что вы выбираете два текстовых узла «H» и «O» вместо выбора узла элемента. В XPath 1.0 многие операции (например, contains()
) при применении к последовательности из двух текстовых узлов игнорируют все, кроме первого, поэтому contains(x/y/title/text(), "O")
возвращает false; в XPath 2.0 выдается ошибка, говорящая о том, что аргумент для contains() должен быть одноэлементным. Если вы просто хотите узнать, содержит ли заголовок букву «О», то гораздо лучше пропустить /text()
и применить операцию к строковому значению элемента, что является конкатенацией всех текстовых узлов.
Единственный раз, когда вам нужно использовать «/text()», это если вы хотите более глубоко изучить внутреннюю структуру элемента title
.
Конечно, возможно, что между реализациями XPath есть различия — не все из них на 100% соответствуют стандарту. Но основные реализации довольно совместимы, и если вы обнаружите разницу, пожалуйста, сообщите нам об этом: четко укажите исходный документ, выражение пути и разные результаты, полученные в разных реализациях.
person
Michael Kay
schedule
15.08.2019
text()
. Если вы не смотрите на текстовые узлы, вы этого не сделаете. Дело не в правильности, требованиях или реализациях, а в том, что нужно коду. Вы можете узнать о разнице, изучая XML, DOM и XPath (не из фрагментов, а из фактической документации XPath, например MDN). - person Amadan   schedule 15.08.2019