#xml #xslt-1.0
#xml #xslt-1.0
Вопрос:
я немного застрял с группировкой. У меня есть следующий XML-код:
<?xml version="1.0" encoding="UTF-8"?>
<isif_data>
<date>29.05.
<event-date>
<type>type1</type>
<Time Timesort="1845">18.45</Time>
<title>event1</title>
<cell/>
<place>abc</place>
</event-date>
<event-date>
<type>type1</type>
<Time Timesort="0900">9</Time>
<title>event2</title>
<cell/>
<place>abd</place>
</event-date>
<event-date>
<type>type2</type>
<Time Timesort="1930">19.30</Time>
<title>event3</title>
<cell/>
<place>abe</place>
</event-date>
<event-date>
<type>type2</type>
<Time Timesort="1900">19</Time>
<title>event4</title>
<cell/>
<place>abf</place>
</event-date>
</date>
<date>30.05.
<event-date>
<type>type1</type>
<Time Timesort="1845">18.45</Time>
<title>event5</title>
<cell/>
<place>abg</place>
</event-date>
<event-date>
<type>type2</type>
<Time Timesort="0900">9</Time>
<title>event6</title>
<cell/>
<place>abh</place>
</event-date>
<event-date>
<type>type1 </type>
<Time Timesort="1500">15</Time>
<title>event7</title>
<cell/>
<place>abi</place>
</event-date>
<event-date>
<type>type2</type>
<Time Timesort="1700">17</Time>
<title>event8</title>
<cell/>
<place>abj</place>
</event-date>
</date>
</isif_data>
Теперь мне нужно, чтобы результирующий XML выглядел примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<isif_data>
<date>29.05.</date>
<type>type1</type>
<Time>9</Time>
<title>event2</title>
<cell/>
<place>abd</place>
<Time>18.45</Time>
<title>event1</title>
<cell/>
<place>abc</place>
<type>type2</type>
<Time>19</Time>
<title>event4</title>
<cell/>
<place>abf</place>
<Time>19.30</Time>
<title>event3</title>
<cell/>
<place>abe</place>
<date>30.05.</date>
<type>type1</type>
<Time>15</Time>
<title>event7</title>
<cell/>
<place>abi</place>
<Time>18.45</Time>
<title>event5</title>
<cell/>
<place>abg</place>
<type>type2</type>
<Time>9</Time>
<title>event6</title>
<cell/>
<place>abh</place>
<Time>17</Time>
<title>event8</title>
<cell/>
<place>abj</place>
</isif_data>
Я пробовал это с помощью Мюнхенского метода, но у меня так и не получилось, чтобы он работал так, как я хочу. У кого-нибудь здесь есть идея, как заставить это работать? Мне нужно использовать xsl версии 1.0. Если вам нужно больше информации, просто скажите мне. Заранее спасибо 🙂
Редактировать: я попробовал следующий XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:key name="type" match="event-date" use="type" />
<xsl:template match="isif_data">
<xsl:element name="isif_data">
<xsl:for-each select="date">
<xsl:element name="date"><xsl:value-of select="date"/></xsl:element>
<xsl:element name="cell"/>
<xsl:for-each select="event-date[count(. | key('type', type)[1]) = 1]">
<xsl:sort select="time/@Timesort" />
<xsl:call-template name="type" />
<xsl:for-each select="key('type', type)">
<xsl:call-template name="time" />
<xsl:call-template name="title" />
<xsl:call-template name="place" />
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Если вам нужны шаблоны, я тоже могу их предоставить. Я не совсем уверен, нужны ли они.
Комментарии:
1. Обновил мой первоначальный пост.
2. Я настоятельно рекомендую вам избавиться от элементов со смешанным содержимым. Либо ваши узлы содержат текст, либо они содержат дочерние элементы. Не оба. Вы напрасно создадите себе проблемы со смешанным контентом.
3. Вы читали: jenitennison.com/xslt/grouping/muenchian.html ?
4. Хорошо, я обновил свой исходный порт. Спасибо @michael.hor257k за информацию. Теперь группировка работает. Но не совсем правильно. Есть ли возможность создать группу для каждого тега даты из исходного кода?
5. И спасибо @Tomalak. Моя ошибка в публикации неправильного результата. На самом деле я создал свой xsl для преобразования так, как вы предложили. У меня есть атрибут в теге даты, который предоставляет мне необходимый текст. Таким образом, текст в узле совершенно не нужен. Извините.
Ответ №1:
Есть ли возможность создать группу для каждого тега даты из исходного кода?
Это:
<xsl:key name="type" match="event-date" use="type" />
будет группировать все даты событий по типу, независимо от даты. Поскольку вы хотите сгруппировать события по типу внутри каждой даты, вам необходимо использовать как дату, так и тип в ключе:
<xsl:key name="type" match="event-date" use="concat (../., '|', type)" />
Комментарии:
1. Спасибо! Я не знаю, почему я не видел этого раньше. Ты лучший.
Ответ №2:
Если я предполагаю, что типы с пробелами или без них должны быть сгруппированы в один, вам действительно нужно выполнить ввод ключей из-за нормализации пробелов, которая должна иметь место. Тогда это будет выглядеть примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="types" match="event-date"
use="concat(normalize-space(../text()), normalize-space(type))"/>
<xsl:template match="event-date">
<xsl:variable name="thisType" select="normalize-space(type)"/>
<xsl:variable name="thisSet"
select="key('types', concat(normalize-space(../text()), $thisType))"/>
<xsl:if test="count(. | $thisSet[1]) = 1">
<type><xsl:value-of select="$thisType"/>
<xsl:for-each select="$thisSet">
<xsl:apply-templates select="node()"/>
</xsl:for-each>
</type>
</xsl:if>
</xsl:template>
<xsl:template match="type"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Без пробелов и т.д. вам не нужен весь набор ключей. Тогда это выглядело бы примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template
match="event-date[not(type = preceding-sibling::*/type)]">
<type><xsl:value-of select="type"/>
<xsl:apply-templates select="../*[type=current()/type]/node()"/>
</type>
</xsl:template>
<xsl:template match="event-date | type"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Комментарии:
1. Группировка по-мюнхенски касается не пробелов и т.д., а производительности. Ваша альтернатива с использованием предиката «очень неэффективна» (цитата из статьи, упомянутой выше).
2. Извините, я не знал, что этот вопрос касается проблемы с производительностью. Я бы сказал, что в этом случае производительность в значительной степени зависит от количества дат и событий в пределах даты. Я не уверен, что группировка по-мюнхенски всегда приведет к повышению производительности здесь.