Сопоставить узел, если у него есть определенный атрибут, и его родительский элемент имеет тот же атрибут?

#xml #xslt #xpath

#xml #xslt #xpath

Вопрос:

Хорошо, у меня есть структура помощи в поиске, подобная этой:

 <c01 level="file">

<c02 level="file"></c02>

</c01>
  

Для моего шаблона XSLT я хотел бы иметь возможность сопоставлять только узлы с атрибутом level =»file», у которых родительский элемент также имеет атрибут level = «file», чтобы я мог применить некоторое конкретное форматирование к дочернему элементу.

Обычно для сопоставления level =»file» я просто использую следующее:

 <xsl:template match="*[@level="file"]">
  

Однако для целей форматирования (отступ и т.д.) Мне нужно, чтобы узел, который является дочерним элементом узла с тем же атрибутом, обрабатывался иначе, чем его родительский элемент. Итак, что-то вроде:

 <xsl:template match="*[@level="file"] and parent::[@level="file"]">
  

Есть идеи? Я надеюсь, что это имеет смысл. Спасибо!

Ответ №1:

Использовать:

 <xsl:template match="*[@level='file' ]/*[@level='file']">
  

Этот шаблон сопоставляет любой элемент, строковое значение level атрибута которого равно "file" , и который является дочерним элементом элемента, строковое значение level атрибута которого равно "file"

Обратите внимание: не используется .. ось parent:: или // , и это, вероятно, самый простой и точный шаблон сопоставления.

Комментарии:

1. Как вы думаете, этот фрагмент будет отменять совпадения на *[@level='file' ] ? Это проблема, с которой я сейчас сталкиваюсь. Получение этой строки для воздействия на узлы, как *[@level='file' ]/*[@level='file']/did когда у меня уже есть *[@level='file' ]/did в таблице стилей.

2. @librarion: Да, этот шаблон сопоставления более специфичен. Если он не выбран, то укажите priority="3"

Ответ №2:

Сопоставить на любом узле, родительский элемент которого имеет тот же атрибут @level, что и у меня, и мой атрибут @level = ‘file’

 <xsl:template match="*[../@level=./@level][./@level='file']">
 ...
</xsl:template>
  

Комментарии:

1. Работает ли это, если у меня уже есть другой раздел, соответствующий родительскому с <xsl:template match="*[@level="file"]"> ? Или они будут конфликтовать?

2. Насколько я понимаю, выигрывает более конкретное совпадение — у меня бы не было под рукой моей книги Майкла Кея по XSLT, но я помню, что есть взвешивание, которое применяется для определения порядка совпадений.

3. Хорошо, это имеет смысл. Последнее: что, если у меня есть дочерние элементы под ним? Как и в, могу ли я затем продолжить сопоставление <xsl:template match="*[../@level=./@level][./@level='file']/scopecontent"> , или это приведет к панике?

4. какой узел вы хотите, чтобы он соответствовал вашему узлу? scopecontent или это родительский элемент? Вам нужно рассматривать совпадение как путь с [filter] — таким образом, часть пути соответствует выбору узлов, например, ‘foo’ — все узлы вызывают foo, и фильтр [ @attribute = ‘bar’ ][baz] — которые имеют атрибут bar и дочерний узел baz. — итак, в вашем примере вы соответствуете узлу «содержимое области», который находится на единицу ниже любого узла, который соответствует вашим предыдущим критериям.