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

Popular posts from this blog

jquery - Invalid Assignment Left-Hand Side -

java - Play! framework 2.0: How to display multiple image? -

gmail - Is there any documentation for read-only access to the Google Contacts API? -