Подтвердить что ты не робот

XPath - разница между node() и текстом()

Мне трудно понять разницу между text() и node(). Насколько я понимаю, text() будет тем, что находится между тегами <item>apple</item>, которые в этом случае apple. Node будет тем, что Node на самом деле, что будет item

Но потом мне была назначена какая-то работа, где он просит меня "Выбрать текст всех элементов под продуктом", и в отдельном вопросе спрашивается "Выберите все узлы менеджера во всех отделах"

Как вывод должен выглядеть text(), а не node()

отладка XML

<produce>
 <item>apple</item>
 <item>banana</item>
 <item>pepper</item>
</produce>

<department>
 <phone>123-456-7891</phone>
 <manager>John</manager>
</department>

Конечно, есть больше отделов и больше менеджеров, но это всего лишь фрагмент кода.

Любая помощь будет очень признательна!

4b9b3361

Ответ 1

text() и node() являются тестами node, в терминологии XPath (сравните).

Тесты

Node работают на множестве (на оси , а точнее) узлов и возвращают те, которые имеют определенный тип. Когда ось не указана, ось child принимается по умолчанию.

Существуют все типы Node tests:

  • node() соответствует любому node (наименее конкретному тегу node для всех)
  • text() соответствует только текстовым узлам
  • comment() соответствует узлам комментариев
  • * соответствует любому элементу node
  • foo соответствует любому элементу node с именем "foo"
  • processing-instruction() соответствует узлам PI (они выглядят как <?name value?>).
  • Боковое примечание: * также соответствует узлам атрибутов, но только вдоль оси attribute. @* является сокращением для attribute::*. Атрибуты не являются частью оси child, поэтому обычный * не выбирает их.

Этот документ XML:

<produce>
    <item>apple</item>
    <item>banana</item>
    <item>pepper</item>
</produce>

представляет собой следующую DOM (упрощенную):

root node
   element node (name="produce")
      text node (value="\n    ")
      element node (name="item")
         text node (value="apple")
      text node (value="\n    ")
      element node (name="item")
         text node (value="banana")
      text node (value="\n    ")
      element node (name="item")
         text node (value="pepper")
      text node (value="\n")

Итак, с XPath:

  • / выбирает корень node
  • /produce выбирает дочерний элемент корня node, если он имеет имя "produce" (Это называется элементом документа, он представляет сам документ. Элемент документа и корень node часто путают, но это не одно и то же.)
  • /produce/node() выбирает любой тип дочернего node под /produce/ (т.е. все 7 детей)
  • /produce/text() выбирает только 4 (!) текстовые узлы только для пробелов
  • /produce/item[1] выбирает первый дочерний элемент с именем "item"
  • /produce/item[1]/text() выбирает все дочерние текстовые узлы (там только один - "яблоко" - в этом случае)

И так далее.

Итак, ваши вопросы

  • "Выберите текст всех элементов под производством" /produce/item/text() (выбрано 3 узла)
  • "Выберите все узлы менеджера во всех отделах" //department/manager (выбрано 1 node)

Примечания

  • Ось по умолчанию в XPath - это ось child. Вы можете изменить ось, указав другое имя оси. Например: //item/ancestor::produce
  • Элементные узлы имеют текстовые значения. Когда вы оцениваете элемент node, его текстовое содержимое будет возвращено. В случае этого примера /produce/item[1]/text() и string(/produce/item[1]) будут одинаковыми.
  • Также см. этот ответ, где я описываю отдельные части выражения XPath графически.

Ответ 2

Выберите текст всех элементов под продуктом:

//produce/item/text()

Выберите все узлы менеджера во всех отделах:

//department/*