Сравнение узлов в 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('
',.)"/>
<xsl:for-each select="key('kDateByVal',.)">
<xsl:value-of select="concat('
',' ', ../description)"/>
</xsl:for-each>
<xsl:text>
</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 - группа внутри узла, а не внутри всего документа, который почти совпадает с вашим вопросом, только с именами вместо дней.
Я надеюсь, что это помогает - с наилучшими пожеланиями, Питер