2010-10-22 2 views
10

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

//*/@_attribute_ 

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

Благодаря

+0

Хороший вопрос, +1.См. Мой ответ за небольшую коррекцию утверждения Алехандро о том, что ваше выражение XPath является «неправильным». Ответ Алехандро хороший, за исключением того, что в этом выражении XPath нет ничего плохого. –

ответ

14

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

//*/@attribute

Это не так. Он будет расширен:

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

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

Понадобится:

/descendant::*[attribute::attribute] 

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

//*[@attribute] 

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

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

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

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

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

+0

@Alejandro. В '// */@ x' нет * ничего * неправильного, за исключением того, что оно больше, чем могло бы быть. –

12

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

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

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

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

//*[@x] 

Используйте:

//@x 

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

Там нет ничего плохого в:

//*/@x 

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

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

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

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

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

/descendant-or-self::node() 

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

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

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

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

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

+2

+1 Спасибо за разъяснение. Мне всегда нравится читать ваши ответы. – Garett

Смежные вопросы