Сравнение узлов в xml с xslt

Я преобразовываю данные XML в HTML-страницу с помощью xslt. Я хочу устранить дубликаты данных, где это выглядит следующим образом.

XML-данные

<calendar>
<event>
<date>May 11</date>
<description>Mother's Day</description>
</event>
<event>
<date>May 12</date>
<description>Birthday</description>
</event>
<event>
<date>May 12</date>
<description>Board Meeting</description>
</event>
</calendar>

Мой код xslt

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <html>
  <body>
  <h2>Event Dates </h2>
  <table border="1">
  <tr bgcolor="#9acd32">
  <th>date</th>
  <th>description</th>
  </tr>
  <xsl:for-each select="calendar/event">
  <tr>
  <td><xsl:value-of select="date"/></td>
  <td><xsl:value-of select="description"/></td>
  </tr>
  </xsl:for-each>
  </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

Мой вывод

date    description
May 11   Mother's Day
May 12   Birthday
May 12   Board Meeting

Желаемый вывод.

date  description
May 11
  Mother's Day

May 12
  Birthday
  Board Meeting

Пожалуйста, предложите мне изменить код XSLT. Заранее спасибо.

3 ответа

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:key name="kDateByVal" match="date" use="."/>

 <xsl:template match="/">
  <xsl:text>date  description</xsl:text>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match=
  "date[generate-id()=generate-id(key('kDateByVal',.)[1])]">
     <xsl:value-of select="concat('&#xA;',.)"/>
     <xsl:for-each select="key('kDateByVal',.)">
      <xsl:value-of select="concat('&#xA;','  ', ../description)"/>
     </xsl:for-each>
     <xsl:text>&#xA;</xsl:text>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

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

<calendar>
    <event>
        <date>May 11</date>
        <description>Mother's Day</description>
    </event>
    <event>
        <date>May 12</date>
        <description>Birthday</description>
    </event>
    <event>
        <date>May 12</date>
        <description>Board Meeting</description>
    </event>
</calendar>

в нужный, правильный результат:

date  description
May 11
  Mother's Day

May 12
  Birthday
  Board Meeting

Я нашел это решение и применил к вашей проблеме.
Дженни Теннисон написала приятное и краткое объяснение метода.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="text" indent="yes"/>
<xsl:key name="distinct-date" match="/calendar/event/date" use="./text()"/>
<xsl:template match="calendar">
    <xsl:text>date  description
</xsl:text>
    <xsl:for-each select="event/date[generate-id(.) = generate-id(key('distinct-date',.)[1])]">
        <xsl:value-of select="./text()"/>
        <xsl:text>
</xsl:text>
        <xsl:apply-templates select="//event[date/text() = current()/text()]"/>
        <xsl:text>
</xsl:text>
        </xsl:for-each>
    </xsl:template>  

    <xsl:template match="event">
        <xsl:text>    </xsl:text><xsl:value-of select="description/text()"/>
        <xsl:text>
</xsl:text>
    </xsl:template>
</xsl:stylesheet>

Единственный способ решить вашу проблему - это так называемая "мюнхенская группировка". Пожалуйста, обратитесь к Muenchian Grouping - группа внутри узла, а не внутри всего документа, который почти совпадает с вашим вопросом, только с именами вместо дней.

Я надеюсь, что это помогает - с наилучшими пожеланиями, Питер

Другие вопросы по тегам