Help with joining neighboring nodes

I apologize for not knowing xsl very well, but I have an xml document that I would like to convert, and I could not find an example that works for me. I would like to combine locations into one element. I have the following document:

<?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> 

I am trying to do this:

 <?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> 

+4
source share
4 answers

This XSLT 1.0 conversion does not use modes and does not even have one conditional instruction :

 <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> 

When applied to the provided XML document (wrapped in one top element that must be executed correctly)

 <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> 

the desired, correct result is output:

 <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> 
+1
source

Use identity transformation with patterns that handle special cases:

 <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> 
+1
source

EDIT : Sorry, I skipped the sequence constructor.

 <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> 

Output:

 <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> 

Note : The Pull style only performs conversion when necessary , which means there are some locations .

0
source

Here's an alternative (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> 
0
source

Source: https://habr.com/ru/post/1347781/


All Articles