Оси атрибутов XPath 1.0: нет шансов?

Вопрос начинающего здесь:

Учитывая следующий фрагмент XML:

<root>
  <element>
    <child1>a</child1><child2>b</child2><child3>c</child3>
  </element>
</root>

Когда я нахожусь в контексте child3, я могу использовать preceding-sibling::* для получения узла child2. Хорошо.

В следующем фрагменте XML:

<root>
  <element child1="a" child2="b" child3="c">
  </element>
</root>

Когда я нахожусь в контексте child3, правильно ли, что в XPath 1.0 нет оси для получения узла атрибута child2? Я думаю, мне нужно что-то вроде preceding-sibling-attribute::, которого нет в наличии.

Как дополнительный вопрос, возможно ли это с XPath 2?


person MazeGen    schedule 30.11.2012    source источник
comment
Можете ли вы объяснить свое требование в концептуальных терминах, помимо примера (переход от дочернего элемента 3 к дочернему элементу 2)? Если концептуальным требованием является выбор предыдущего атрибута, то нет, это невозможно, поскольку концепция не определена четко в XML.   -  person LarsH    schedule 30.11.2012


Ответы (1)


Это правда, что не существует одной оси для перехода от одного атрибута к другому, но, конечно, вы можете добраться туда, объединив оси в цепочку.

Атрибуты не считаются одноуровневыми, поскольку они не считаются "дочерними элементами" родительского элемента, в модели данных, которую использует XPath. Это одна из причин, почему preceding-sibling:: не работает. Это также означает, что имена атрибутов, такие как child1, child2 и т. д., вводят в заблуждение, поскольку атрибуты не являются «дочерними».

Другая причина, по которой preceding-sibling:: не работает, заключается в том, что порядок атрибутов данный элемент не определен (зависит от реализации). Атрибуты должны быть перечислены в определенном порядке в заданной сериализации (например, в файле), но этот файл может быть проанализирован и выведен снова с атрибутами в другом порядке, и он все равно будет считаться тем же документом из точки информационной модели XML. зрения. Следовательно, в XML нет такого понятия, как «предыдущий» или «предшествующий» атрибут.

Чтобы получить значение атрибута child2 из контекста атрибута child3, вы можете использовать один из них в зависимости от того, как вы знаете, какой атрибут вам нужен...

../@child2

"Атрибут с именем child2 родительского элемента"

../@*[name() != name(current())]

"Другие атрибуты родительского элемента (не этот)"

Вы могли бы даже попробовать

../@*[2]

но в целом результаты нельзя было бы предсказать, поскольку порядок атрибутов не определен.

Если имена атрибутов включают компонент индекса (1, 2, 3), как в вашем примере, вы можете заменить число в name(current()) на меньшее число.

Чтобы ответить на ваш побочный вопрос, это зависит от того, как определено ваше требование. Если требуется «выбрать предыдущий атрибут», то нет, эта концепция также не определена в XPath 2.

person LarsH    schedule 30.11.2012
comment
Спасибо за исчерпывающий ответ, LarsH. Я создаю файл XML и хочу преобразовать некоторые атрибуты в HTML точно в том же порядке, в котором они появляются в файле XML. Обработка немного сложна, поэтому необходимо знать, является ли атрибут первым. Вы пояснили это, сославшись на тот факт, что порядок атрибутов данного элемента не определен. Благодаря тому, что я полностью владею файлом XML, я собираюсь изменить генератор, чтобы вместо атрибутов использовались элементы. Это решит мою проблему. - person MazeGen; 30.11.2012
comment
@Карел: отличное решение. Когда порядок вещей в файле XML важен, вам действительно нужно использовать элементы, а не атрибуты. - person LarsH; 30.11.2012