#xml #xslt
#xml #xslt
Вопрос:
Я прошу прощения за то, что не очень хорошо знаю xsl, но у меня есть XML-документ, который я хотел бы преобразовать, и я не смог найти пример, который подходит для меня. Я хотел бы объединить местоположения в один элемент. У меня есть следующий документ:
<?xml version="1.0" encoding="UTF-8"?><tfs_events>
<title>Referees Events</title>
<event>
<id>256</id>
<name>SB-V,SB-JV vs McKinley HS</name>
<time_start>2011-04-12 17:00:00</time_start>
<time_end>2011-04-12 19:00:00</time_end>
<status>Active</status>
<locations>
<id>116</id>
<name>Lake Athletic Complex</name>
</locations>
</event>
<event>
<id>257</id>
<name>SB-V,SB-JV vs Jackson HS</name>
<time_start>2011-04-14 17:00:00</time_start>
<time_end>2011-04-14 19:00:00</time_end>
<status>Active</status>
<locations>
<id>116</id>
<name>Athletic Complex</name>
</locations>
<locations>
<id>6</id>
<name>HS Baseball Field</name>
</locations>
</event>
Я пытаюсь сделать это следующим образом:
<?xml version="1.0" encoding="UTF-8"?><tfs_events>
<title>Referees Events</title>
<event>
<id>256</id>
<name>SB-V,SB-JV vs McKinley HS</name>
<time_start>2011-04-12 17:00:00</time_start>
<time_end>2011-04-12 19:00:00</time_end>
<status>Active</status>
<location_name>Lake Athletic Complex</location_name>
</event>
<event>
<id>257</id>
<name>SB-V,SB-JV vs Jackson HS</name>
<time_start>2011-04-14 17:00:00</time_start>
<time_end>2011-04-14 19:00:00</time_end>
<status>Active</status>
<location_name>Athletic Complex, HS Baseball Field</location_name>
</event>
Комментарии:
1. Хороший вопрос, 1. Смотрите мой ответ для решения, которое не использует никаких режимов или каких-либо условных инструкций XSLT. 🙂
Ответ №1:
В этом преобразовании XSLT 1.0 не используются режимы и нет ни одной условной инструкции:
<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="locations[1]">
<location_name>
<xsl:apply-templates select=
"name | following-sibling::locations/name"/>
</location_name>
</xsl:template>
<xsl:template match="locations"/>
<xsl:template priority="5" match=
"locations[preceding-sibling::locations]/name">
<xsl:value-of select="concat(', ', .)"/>
</xsl:template>
<xsl:template match="locations/name[1]">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
При применении к предоставленному XML-документу (заключен в один верхний элемент для придания правильной формы)»
<t>
<title>Referees Events</title>
<event>
<id>256</id>
<name>SB-V,SB-JV vs McKinley HS</name>
<time_start>2011-04-12 17:00:00</time_start>
<time_end>2011-04-12 19:00:00</time_end>
<status>Active</status>
<locations>
<id>116</id>
<name>Lake Athletic Complex</name>
</locations>
</event>
<event>
<id>257</id>
<name>SB-V,SB-JV vs Jackson HS</name>
<time_start>2011-04-14 17:00:00</time_start>
<time_end>2011-04-14 19:00:00</time_end>
<status>Active</status>
<locations>
<id>116</id>
<name>Athletic Complex</name>
</locations>
<locations>
<id>6</id>
<name>HS Baseball Field</name>
</locations>
</event>
</t>
получен желаемый, правильный результат:
<t>
<title>Referees Events</title>
<event>
<id>256</id>
<name>SB-V,SB-JV vs McKinley HS</name>
<time_start>2011-04-12 17:00:00</time_start>
<time_end>2011-04-12 19:00:00</time_end>
<status>Active</status>
<location_name>Lake Athletic Complex</location_name>
</event>
<event>
<id>257</id>
<name>SB-V,SB-JV vs Jackson HS</name>
<time_start>2011-04-14 17:00:00</time_start>
<time_end>2011-04-14 19:00:00</time_end>
<status>Active</status>
<location_name>Athletic Complex, HS Baseball Field</location_name>
</event>
</t>
Ответ №2:
Используйте преобразование идентификатора с шаблонами, которые обрабатывают особые случаи:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="event">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::locations)]" />
<location_name>
<xsl:apply-templates select="locations" />
</location_name>
</xsl:copy>
</xsl:template>
<xsl:template match="locations">
<xsl:value-of select="name" />
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Ответ №3:
Вот альтернатива (XSLT 2.0):
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="event">
<xsl:copy-of select="* except locations"/>
<location_name>
<xsl:value-of select="locations/name" separator=", "/>
</location_name>
</xsl:template>
</xsl:stylesheet>
Ответ №4:
РЕДАКТИРОВАТЬ: Извините, я пропустил конструктор последовательности.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="node()" mode="sequence">
<xsl:if test="position()!=1">, </xsl:if>
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="locations"/>
<xsl:template match="locations[1]">
<location_name>
<xsl:apply-templates select="../locations/name" mode="sequence"/>
</location_name>
</xsl:template>
</xsl:stylesheet>
Вывод:
<tfs_events>
<title>Referees Events</title>
<event>
<id>256</id>
<name>SB-V,SB-JV vs McKinley HS</name>
<time_start>2011-04-12 17:00:00</time_start>
<time_end>2011-04-12 19:00:00</time_end>
<status>Active</status>
<location_name>Lake Athletic Complex</location_name>
</event>
<event>
<id>257</id>
<name>SB-V,SB-JV vs Jackson HS</name>
<time_start>2011-04-14 17:00:00</time_start>
<time_end>2011-04-14 19:00:00</time_end>
<status>Active</status>
<location_name>Athletic Complex, HS Baseball Field</location_name>
</event>
</tfs_events>
Примечание: Преобразование в стиле вытягивания выполняется только тогда, когда это необходимо, то есть когда есть некоторые locations
.