выбор одного из нескольких элементов, которые отличаются по атрибуту - PullRequest
5 голосов
/ 02 августа 2011

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

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

Например, предположим, у меня есть один файл XML (назовите его "файл 1 "), содержащий

<food>
    <snack>Chips</snack>
    <snack type="nuts">Peanuts</snack>
</food>

и другой файл XML (" файл 2 "), содержащий

<food>
    <snack>Cheese puffs</snack>
</food>

Мне нужен XSLT, который выводит только" Peanuts "(но не"Chips ") при обработке файла 1, но все равно выводит" Cheese puffs "для файла 2 (т.е. я не могу просто выбрать только те элементы, которые имеют атрибут" type ", что было бы слишком просто).

Это, наверное, просто, но я застрял ...

Ответы [ 2 ]

1 голос
/ 02 августа 2011

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match=
   "*[snack/@type]/snack[not(@type)]"/>
</xsl:stylesheet>

дает желаемые результаты в обоих случаях .

Объяснение :

  1. Правило / шаблон идентификации копирует каждый узел "как есть" .

  2. Второй шаблон переопределяет шаблон идентификации для любого элемента snack без атрибута type, который имеет родственные элементы snack, которые имеют атрибут type. Этот шаблон имеет пустое тело, которое эффективно «удаляет» соответствующий элемент из (копируемого) вывода.

0 голосов
/ 02 августа 2011

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

Прямой перевод этого будет

if (count(snack) = 1) then snack else snack[@type='nuts']

, который является допустимым синтаксисом XPath 2.0 - если вам нужно сделать это в 1.0, тогда он довольно прямо (хотя и многословно) преобразуется в эквивалентный xsl: select.

Если вы хотите что-то более краткое, чем указано выше, вы также можете написать в XPath 2.0

(snack[@type='nuts'], snack)[1]

, который создает список, содержащий сначала закуски с type = 'nuts', затем все закуски, а затем выбирает первый элемент из этого списка.

...