Выражение 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.