xml - Get substring of each element in a list and get them distinct in XSLT -
i need transform xml file xslt, , task kinda tricky.
i have attributes name attr_1000_a whereas number , suffix dynamic, attr_2000_b valid too.
further, there <row> elements combine related data. need transform them equally numbered attributes (i.e. attr_1000_a , attr_1000_b) put same element.
let me give example. following input xml:
<root> <row id="1"> <foo attr_1000_a="true">1</foo> <foo attr_1000_b="true">2</foo> <foo attr_1000_c="true">3</foo> </row> <row id="2"> <foo attr_1000_a="true" attr_1000_b="true" attr_1000_c="true">10</foo> <foo attr_2000_a="true" attr_2000_b="true" attr_2000_c="true">20</foo> </row> <row id="3"> <foo attr_1000_a="true" attr_2000_a="true" attr_3000_a="true">100</foo> <foo attr_1000_b="true" attr_2000_b="true" attr_3000_b="true">200</foo> <foo attr_1000_c="true" attr_2000_c="true" attr_3000_c="true">300</foo> </row> </root> you can see attributes can combined in several ways, makes transformation difficult. each attribute unique in each <row> can located in <foo> element. also, each <foo> can have arbitrary number of attributes.
the desired result:
<result> <row id="1"> <field attr="1000"> <a>1</a> <b>2</b> <c>3</c> </field> </row> <row id="2"> <field attr="1000"> <a>10</a> <b>10</b> <c>10</c> </field> <field attr="2000"> <a>20</a> <b>20</b> <c>20</c> </field> </row> <row id="3"> <field attr="1000"> <a>100</a> <b>200</b> <c>300</c> </field> <field attr="2000"> <a>100</a> <b>200</b> <c>300</c> </field> <field attr="3000"> <a>100</a> <b>200</b> <c>300</c> </field> </row> </result> i think have somehow list of numbers in row (for example 1000, 2000 , 3000) , iterate through elements have such attriute.
how can using xslt? possible?
quick , dirty, xslt
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="2.0"> <xsl:output indent="yes"/> <xsl:template match="root"> <result> <xsl:apply-templates select="@*|node()"/> </result> </xsl:template> <xsl:template match="foo/@*"> <xsl:element name="{substring-after(local-name(),'000_')}"> <xsl:value-of select=".."/> </xsl:element> </xsl:template> <xsl:template match="row"> <row id="{@id}"> <xsl:for-each-group select="foo/@*" group-by="substring(local-name(),1,9)"> <field attr="{substring-after(current-grouping-key(),'attr_')}"> <xsl:apply-templates select="current-group()"/> </field> </xsl:for-each-group> </row> </xsl:template> <xsl:template match="foo"> <xsl:apply-templates select="@*"/> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> applied input
<?xml version="1.0" encoding="utf-8"?> <root> <row id="1"> <foo attr_1000_a="true">1</foo> <foo attr_1000_b="true">2</foo> <foo attr_1000_c="true">3</foo> </row> <row id="2"> <foo attr_1000_a="true" attr_1000_b="true" attr_1000_c="true">10</foo> <foo attr_2000_a="true" attr_2000_b="true" attr_2000_c="true">20</foo> </row> <row id="3"> <foo attr_1000_a="true" attr_2000_a="true" attr_3000_a="true">100</foo> <foo attr_1000_b="true" attr_2000_b="true" attr_3000_b="true">200</foo> <foo attr_1000_c="true" attr_2000_c="true" attr_3000_c="true">300</foo> </row> </root> yields result
<?xml version="1.0" encoding="utf-8"?> <result> <row id="1"> <field attr="1000"> <a>1</a> <b>2</b> <c>3</c> </field> </row> <row id="2"> <field attr="1000"> <a>10</a> <b>10</b> <c>10</c> </field> <field attr="2000"> <a>20</a> <b>20</b> <c>20</c> </field> </row> <row id="3"> <field attr="1000"> <a>100</a> <b>200</b> <c>300</c> </field> <field attr="2000"> <a>100</a> <b>200</b> <c>300</c> </field> <field attr="3000"> <a>100</a> <b>200</b> <c>300</c> </field> </row> </result> the magic in
<xsl:element name="{substring-after(local-name(),'000_')}"> <xsl:value-of select=".."/> </xsl:element> this creates a/b/c elements dynamic name , travels 1 node value parent node (we're in attribute).
and in
<xsl:for-each-group select="foo/@*" group-by="substring(local-name(),1,9)"> <field attr="{substring-after(current-grouping-key(),'attr_')}"> <xsl:apply-templates select="current-group()"/> </field> </xsl:for-each-group> which regroups attributes (foo/@*) using part of their name (substring(local-name(),1,9)). first subsequently available current-group(), latter current-grouping-key(), can see.
Comments
Post a Comment