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

книга, которую я читаю в XML, говорит, что для выбора всех узлов в файле XML, имеющем определенный атрибут, используйте синтаксис:

//*/@_attribute_

Я не понимаю, почему нужна звездочка. Как я понимаю, выражение//выбирает всех потомков корня node. Итак, не будет // @lang, например, выбрать всех потомков корня node, у которых есть атрибут, называемый "lang"? Я даже не могу понять, что означает звездочка в приведенном выше выражении (я знаю, что звездочка вообще означает "все" ). Если бы кто-то мог сломать это для меня, я бы очень признателен.

Спасибо

Ответ 1

Привет, книга, которую я читаю на XML, говорит что для выбора всех узлов в XML файл с определенным атрибутом, используйте синтаксис:

//*/@attribute

Это неправильно. Он будет расширен до:

/descendant-or-self::node()/child::*/attribute::attribute

Значение: все атрибуты attribute любого дочернего элемента элемента node являются самим корневым документом или одним из его дескриптов

Вам нужно:

/descendant::*[attribute::attribute]

Или сокращенная форма

//*[@attribute]

О *: формальность - это тест имени, а не тег типа node. В XPath 1.0 нет теста типа элемента. В XPath 2.0 у вас есть element(). Итак, зачем выбирать только элементы? Ну, это не так. Ось имеет основной тип node, от http://www.w3.org/TR/xpath/#node-tests:

Каждая ось имеет основной тип node. Если ось может содержать элементы, то основным типом node является элемент; в противном случае это тип узлов что ось может содержать. Таким образом,

  • Для оси атрибута основным node является атрибут.
  • Для оси пространства имен основным типом node является пространство имен.
  • Для других осей основным типом node является элемент.

Вот почему *, child::*, self::*, descendant::* и т.д. выбирают элементы, но @* или attribute::* или namespace::* выбирают атрибуты или пространства пространств имен.

О предикате (часть [@attribute]): это выражение оценивается с каждым из узлов, которое выбирается последним шагом. Он ожидает булевское значение для фильтрации. Логическое значение для набора node (это результат для attribute::attribute) является ложным для пустого набора node и true в противном случае.

Ответ 2

Название этого вопроса:

выражение XPath для выбора всего узлы с общим атрибутом

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

Чтобы найти все узлы, которые имеют общий атрибут с именем x (BTW, только элементы-узлы могут иметь атрибуты), использовать:

//*[@x]

Использование

//@x

чтобы выбрать все атрибуты с именем x в документе XML. Это, вероятно, самое короткое выражение для этого.

В нет ничего плохого:

//*/@x

за исключением того, что он немного длиннее.

Это сокращение для:

/descendant-or-self::node()/child::*/attribute::x

а также все атрибуты x в документе XML.

Кто-то может подумать, что это выражение не выбирает атрибут x верхнего элемента в документе. Это неправильный вывод, потому что первый шаг местоположения:

/descendant-or-self::node()

выбирает каждый node в документе, включая корень (/).

Это означает, что:

/descendant-or-self::node()/child::*

выбирает каждый элемент, включая верхний элемент (который является единственным потомком корня node в хорошо сформированном XML-документе).

Итак, когда наконец добавлен последний шаг местоположения /@x, он выберет все атрибуты x всех узлов, выбранных до сих пор двумя первыми шагами расположения - это все атрибуты x для всего элемента -nodes в документе XML.