xml - XSL 1.0 Format table splitting values -


i've sample xml input following:

<table name="table1"> <fields>    <field name="field1" />    <field name="field2" />    <field name="field3" />    <field name="field4" /> </fields> <data>    <row value="2,description1,a,aa" />    <row value="3,description2,b,bb" />    <row value="7,description3,c,cc" /> </data> </table> <table name="table2"> <fields>    <field name="field7" />    <field name="field8" />    <field name="field9" /> </fields> <data>    <row value="q,description7,a" />    <row value="w,description8,b" />    <row value="x,description9,c" /> </data> </table> 

please note can have many tables different number of fields row values contain exact number of fields required.

the expected result output this:

<listoftable1> <item>    <field1>2</field1>    <field2>description1</field2>    <field3>a</field3>    <field4>aa</field4> </item> <item>    <field1>3</field1>    <field2>description2</field2>    <field3>b</field3>    <field4>bb</field4> </item> <item>    <field1>7</field1>    <field2>description3</field2>    <field3>c</field3>    <field4>cc</field4> </item> </listoftable1>  <listoftable2> <item>    <field7>q</field7>    <field8>description7</field8>    <field9>a</field9> </item> <item>    <field7>w</field7>    <field8>description8</field8>    <field9>b</field9> </item> <item>    <field7>x</field7>    <field8>description9</field8>    <field9>c</field9> </item> </listoftable2> 

i can use strict xslt 1.0 unfortunately no external functions or reference

i've been using modified version of third solution suggested

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform">    <xsl:template match="//table">     <xsl:value-of disable-output-escaping="yes" select="concat('&lt;listof',@name,'&gt;')" />     <xsl:apply-templates />     <xsl:value-of disable-output-escaping="yes" select="concat('&lt;/listof',@name,'&gt;')" />   </xsl:template>    <xsl:template match="table/data/row">     <item>       <xsl:call-template name="fldsplit">         <xsl:with-param name="f" select="@value" />         <xsl:with-param name="set" select="//fields/field" />       </xsl:call-template>     </item>   </xsl:template>    <xsl:template name="fldsplit">     <xsl:param name="f" />     <xsl:param name="set"/>     <xsl:variable name="bfc" select="substring-before($f,',')"/>     <xsl:variable name="afc" select="substring-after($f,',')"/>     <xsl:element name="{$set/@name}">       <xsl:choose>         <xsl:when test="$bfc">           <xsl:value-of select="$bfc"/>         </xsl:when>         <xsl:otherwise>           <xsl:value-of select="$f"/>         </xsl:otherwise>       </xsl:choose>     </xsl:element>     <xsl:if test="$afc">       <xsl:call-template name="fldsplit">         <xsl:with-param name="f" select="$afc"/>         <xsl:with-param name="set" select="$set/following-sibling::*" />       </xsl:call-template>     </xsl:if>   </xsl:template>  </xsl:stylesheet> 

but have issue second table (or other add input), fields name repeat starting field1 while expect use specific fields each table parsed

this current output (wrong)

<?xml version="1.0" encoding="utf-8"?>  <listoftable1>    <item><field1>2</field1><field2>description1</field2><field3>a</field3><field4>aa</field4></item>    <item><field1>3</field1><field2>descritpion2</field2><field3>b</field3><field4>bb</field4></item>    <item><field1>7</field1><field2>description3</field2><field3>c</field3><field4>cc</field4></item> </listoftable1> <listoftable2>    <item><field1>q</field1><field2>description7</field2><field3>a</field3></item>    <item><field1>w</field1><field2>description8</field2><field3>b</field3></item>    <item><field1>x</field1><field2>description9</field2><field3>c</field3></item> </listoftable2> 

if can commas in row value ones separate fields (i.e. there's no "escape" mechanism "\,"), , there right number of fields in every row, recursive approach work. i'm assuming here there single root element named root enclosing table elements in order make input well-formed.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0">   <xsl:output method="xml" indent="yes" />    <xsl:template match="/">     <data>       <xsl:apply-templates select="root/table" />     </data>   </xsl:template>    <xsl:template match="table">     <xsl:element name="listof{@name}">       <xsl:apply-templates select="data/row"/>     </xsl:element>   </xsl:template>    <xsl:template match="row">     <!-- add trailing comma value don't lose last field -->     <xsl:variable name="val" select="concat(@value, ',')" />     <item>       <!-- use fields belong table -->       <xsl:apply-templates select="../../fields/field[1]">         <xsl:with-param name="thisval" select="substring-before($val, ',')" />         <xsl:with-param name="rest" select="substring-after($val, ',')" />       </xsl:apply-templates>     </item>   </xsl:template>    <xsl:template match="field">     <xsl:param name="thisval"/>     <xsl:param name="rest"/>      <xsl:element name="{@name}">       <xsl:value-of select="$thisval" />     </xsl:element>      <xsl:apply-templates select="following-sibling::field[1]">       <xsl:with-param name="thisval" select="substring-before($rest, ',')" />       <xsl:with-param name="rest" select="substring-after($rest, ',')" />     </xsl:apply-templates>   </xsl:template> </xsl:stylesheet> 

the trick here generate <field1> etc. elements applying templates field elements in turn. there's no need explicit conditionals (if or choose) because recursion automatically stop @ last field when following-sibling::field[1] no longer selects anything.


Comments

Popular posts from this blog

c++ - CryptStringToBinary API behavior -

c++ - Correct method for redrawing a layered window -

java.util.scanner - How to read and add only numbers to array from a text file -