Reputation: 45
Im an XSLT 2.0 beginner and trying to find a way to split big xml file into multiple chunks based on the condition.
Sample XML:
<?xml version="1.0" encoding="UTF-8"?>
<players>
<player>
<id>1</id>
<fname>Vcut</fname>
<lname>Piatos</lname>
<age>0</age>
<code>1002</code>
<hobby>reading</hobby>
<hobby>sports</hobby>
<hobby>travelling</hobby>
</player>
<player>
<id>2</id>
<fname>Mayo</fname>
<lname>Naise</lname>
<age>22</age>
<code>1003</code>
<hobby>reading books</hobby>
<hobby>program hobyist</hobby>
<hobby>watching tutorials</hobby>
</player>
<player>
<id>3</id>
<fname>Ben</fname>
<lname>Ten</lname>
<age>22</age>
<code>1004</code>
<hobby>play sports</hobby>
</player>
<player>
<id>4</id>
<fname>Dummy</fname>
<lname>One</lname>
<age>22</age>
<code>1005</code>
<hobby>Eat</hobby>
</player>
<player>
<id>5</id>
<fname>Dummy</fname>
<lname>Two</lname>
<age>23</age>
<code>1006</code>
<hobby>sleep</hobby>
</player>
</players>
Expected Output:
File1.xml
<players> <player> <id>3</id> <fname>Ben</fname> <lname>Ten</lname> <age>22</age> <code>1004</code> <hobby>play sports</hobby> </player> <player> <id>4</id> <fname>Dummy</fname> <lname>One</lname> <age>22</age> <code>1005</code> <hobby>Eat</hobby> </player> <player> <id>5</id> <fname>Dummy</fname> <lname>Two</lname> <age>23</age> <code>1006</code> <hobby>sleep</hobby> </player> </players>
file2.xml multiple hobby
<?xml version="1.0" encoding="UTF-8"?> <players> <player> <id>1</id> <fname>Vcut</fname> <lname>Piatos</lname> <age>0</age> <code>1002</code> <hobby>reading</hobby> </player> <player> <id>1</id> <fname>Vcut</fname> <lname>Piatos</lname> <age>0</age> <code>1002</code> <hobby>sports</hobby> </player> <player> <id>1</id> <fname>Vcut</fname> <lname>Piatos</lname> <age>0</age> <code>1002</code> <hobby>travelling</hobby> </player> <player> <id>2</id> <fname>Mayo</fname> <lname>Naise</lname> <age>22</age> <code>1003</code> <hobby>reading books</hobby> </player> <player> <id>2</id> <fname>Mayo</fname> <lname>Naise</lname> <age>22</age> <code>1003</code> <hobby>program hobyist</hobby> </player> <player> <id>2</id> <fname>Mayo</fname> <lname>Naise</lname> <age>22</age> <code>1003</code> <hobby>watching tutorials</hobby> </player> </players>
Tried applying same solution provided here but wasn't able to make it work.
Any tips you can provide? Idea I have is to count the hobby per player but not really sure how to split it and copy other segments after..
<xsl:if count(player/hobby> > 1 )
Actual XSLT that Im using ( literally a copy from the solution referenced I've shared )
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="*/player"/>
</xsl:template>
<xsl:template match="*/player">
<xsl:result-document href="Output{position()}.xml">
<xsl:apply-templates select="/*" mode="split">
<xsl:with-param name="target" tunnel="yes" select="current()"/>
</xsl:apply-templates>
</xsl:result-document>
</xsl:template>
<xsl:template match="@* | node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@*, node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*/player" mode="split">
<xsl:param name="target" tunnel="yes"/>
<xsl:if test="$target is .">
<xsl:next-match/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
This produces 5 file (1 per player) , im playing with it a bit but wasn't able to group player with single hobby into single file and for the multiple hobby its more worse.
Will really appreciate if you can share more direction.
Upvotes: 1
Views: 523
Reputation: 117073
AFAICT, you could do simply:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/players">
<xsl:for-each-group select="player" group-by="count(hobby) gt 1 ">
<result-document href="Output{position()}.xml">
<players>
<xsl:apply-templates select="current-group()/hobby"/>
</players>
</result-document>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="hobby">
<player>
<xsl:copy-of select="../* except ../hobby, ."/>
</player>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1