Jump to content

Need solution for a problem with comma separated values


babar_noor

Recommended Posts

Hi,I have an XML document that has got the following structure.<table>

<t>20,25,30</t>

<s>10,140,160</s>

<r>120, 330, 440, 550, 599, 600, 630,799, 800</r>

</table>I need to convert this XML file to another XML file using xslt such that the following combination can be achieved:t ______ s ______ r--------------------------------------------20 _______ 10 ______ 12020 ________ 140 _____ 33020 ________ 160 ______ 44025 ________ 10 _______ 55025 _________ 140 _______ 59925 __________ 160 ______ 60030 _________ 10 ______ 630.... and so on(Note: I added those underscores between values cuz I couldnt find a way to add a tab. Please dont answer this post by telling me how to add tab)In other words, for every combination of t and s, there is a corresponding r value depending on the index of t, s and r. (not very useful, is it, i'll keep it anyway)I was thinking of using arrays but there is no arrays in xslt. Can someone suggest a solution please.(I know basic xslt and xpath)ThanksBasit

Link to comment
Share on other sites

You say you "need to convert this XML file to another XML file" but the target format you have posted is not XML. So please post the XML you want to create from the input sample you posted, otherwise it is hard to understand what you want to achieve.And I do not understand so far what "and so on" means exactly; what happens once you have used all "r" values, do you start with the first one again?

Link to comment
Share on other sites

Well the target XML will be:<Modifiers>

<Product>

<t>10</t>

<Physical>

<s>100</s>

<r>300</r>

</Physical>

</Product>

</Modifiers>for the next combination of t, s and r there will be a similar structure, starting with Modifiers tag.regarding "so on...", there will always be a "r" value for every combination of "t" and "s", so there is no need to restart from beginning.Thanks for your post.Basit

Link to comment
Share on other sites

OK, I think not many people understood what I want to acheive,Let me make it simpler, I want to convert it into HTML using the t, s and r values.Basically for every combination of t and s there is a r value in the xml below<table> <t>59, 70, 100</t> <s>10, 20, 30</s> <r>100, 200, 300, 400, 500, 600, 659, 763, 782</r></table>The above table I want to convert to following html tablet-------s-------r59----10-----10059----20-----20059----30-----30070----10-----40070----20-----50070----30-----600100---10----659100---20----763100---30----782I would appreiciate a function or method to extract these values.

Link to comment
Share on other sites

With the input being

<table><t>59, 70, 100</t><s>10, 20, 30</s><r>100, 200, 300, 400, 500, 600, 659, 763, 782</r></table>

the following XSLT 2.0 stylesheet

<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="2.0"  xmlns:xs="http://www.w3.org/2001/XMLSchema"  exclude-result-prefixes="xs">    <xsl:output method="html" indent="yes"/>    <xsl:template match="table">	<table>	  <thead>		<tr>		  <xsl:apply-templates select="*" mode="header"/>		</tr>	  </thead>	  <tbody>		<xsl:variable name="ts" as="xs:string*" select="tokenize(t, ',\s+')"/>		<xsl:variable name="ss" as="xs:string*" select="tokenize(s, ',\s+')"/>		<xsl:variable name="sc" as="xs:integer" select="count($ss)"/>		<xsl:variable name="rs" as="xs:string*" select="tokenize(r, ',\s+')"/>		<xsl:for-each select="$ts">		  <xsl:variable name="tc" as="xs:string" select="."/>		  <xsl:variable name="tp" as="xs:integer" select="position()"/>		  <xsl:for-each select="$ss">			<xsl:variable name="sp" as="xs:integer" select="position()"/>			<tr>			  <td>				<xsl:value-of select="$tc"/>			  </td>			  <td>				<xsl:value-of select="."/>			  </td>			  <td>				<xsl:value-of select="$rs[($tp - 1) * $sc + $sp]"/>			  </td>			</tr>		  </xsl:for-each>		</xsl:for-each>	  </tbody>	</table>  </xsl:template>    <xsl:template match="table/*" mode="header">	<th>	  <xsl:value-of select="local-name()"/>	</th>  </xsl:template></xsl:stylesheet>

outputs

<table>   <thead>	  <tr>		 <th>t</th>		 <th>s</th>		 <th>r</th>	  </tr>   </thead>   <tbody>	  <tr>		 <td>59</td>		 <td>10</td>		 <td>100</td>	  </tr>	  <tr>		 <td>59</td>		 <td>20</td>		 <td>200</td>	  </tr>	  <tr>		 <td>59</td>		 <td>30</td>		 <td>300</td>	  </tr>	  <tr>		 <td>70</td>		 <td>10</td>		 <td>400</td>	  </tr>	  <tr>		 <td>70</td>		 <td>20</td>		 <td>500</td>	  </tr>	  <tr>		 <td>70</td>		 <td>30</td>		 <td>600</td>	  </tr>	  <tr>		 <td>100</td>		 <td>10</td>		 <td>659</td>	  </tr>	  <tr>		 <td>100</td>		 <td>20</td>		 <td>763</td>	  </tr>	  <tr>		 <td>100</td>		 <td>30</td>		 <td>782</td>	  </tr>   </tbody></table>

XSLT 2.0 can be executed with Saxon 9 (http://saxon.sourceforge.net/), AltovaXML Tools (http://www.altova.com/altovaxml.html), XQSharp (http://www.xqsharp.com/xqsharp/) and some other XSLT 2.0 processors (e.g. IBM has one as part of a WebSphere extension pack, Intel has a beta).If you want to solve that with XSLT 1.0 then you need to check whether an extension function like http://www.exslt.org/str/functions/tokenize/index.html is supported by your XSLT 1.0 processor or you need to write a named recursive template that does the tokenizing.

Link to comment
Share on other sites

ThanksTokenize is what I need, I am using Java to do the transformation and at the moment using the Java class javax.xml.transform.TransformerFactory.I will try to find something compatible with xslt 2.0 in Java or write the tokenize function.Thanks for your help.Basit

Link to comment
Share on other sites

Saxon is great :)Staying on the same topic, I need some help regarding the following condition:I will modify the original XML table to the following (to make it simpler)<table> <t>10, 20</t> <s>30, 40</s> <r>100, 100, 100, 100</r></table>condition is, if for every combination of t and s, the value of r is the same (which is the case in the above example) then write the following html output.t-----------s------------r10--------<40---------10020--------<40---------100in other words, for t = 10, and for all values of s less then 40, r will be 100Appreciate it.

Link to comment
Share on other sites

Saxon is great :)Staying on the same topic, I need some help regarding the following condition:I will modify the original XML table to the following (to make it simpler)<table> <t>10, 20</t> <s>30, 40</s> <r>100, 100, 100, 100</r></table>condition is, if for every combination of t and s, the value of r is the same (which is the case in the above example) then write the following html output.t-----------s------------r10--------<40---------10020--------<40---------100in other words, for t = 10, and for all values of s less then 40, r will be 100Appreciate it.
I managed to solve this using the following stylesheet
<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="2.0"  xmlns:xs="http://www.w3.org/2001/XMLSchema"  exclude-result-prefixes="xs">    <xsl:output method="html" indent="yes"/>    <xsl:template match="table">	<table>	  <thead>		<tr>		  <xsl:apply-templates select="*" mode="header"/>		</tr>	  </thead>	  <tbody>		<xsl:variable name="ts" as="xs:string*" select="tokenize(t, ',\s+')"/>		<xsl:variable name="ss" as="xs:string*" select="tokenize(s, ',\s+')"/>		<xsl:variable name="sc" as="xs:integer" select="count($ss)"/>		<xsl:variable name="rs" as="xs:string*" select="tokenize(r, ',\s+')"/>		<xsl:for-each select="$ts">		  <xsl:variable name="tc" as="xs:string" select="."/>		  <xsl:variable name="tp" as="xs:integer" select="position()"/>		  <xsl:choose>			   <xsl:when test='count(distinct-values($rs)) = 1'>					  <tr>							<td><xsl:value-of select="$tc"/></td>							<td>< <xsl:value-of select="$ss[$sc]"/></td>							<td><xsl:value-of select="distinct-values($rs)"/></td>					  </tr>			   </xsl:when>			   <xsl:otherwise>		  <xsl:for-each select="$ss">			<xsl:variable name="sp" as="xs:integer" select="position()"/>			<tr>			  <td>				<xsl:value-of select="$tc"/>			  </td>			  <td>				<xsl:value-of select="."/>			  </td>			  <td>				<xsl:value-of select="$rs[($tp - 1) * $sc + $sp]"/>			  </td>			</tr>		  </xsl:for-each>		  </xsl:otherwise>		  </xsl:choose>		</xsl:for-each>	  </tbody>	</table>  </xsl:template>    <xsl:template match="table/*" mode="header">	<th>	  <xsl:value-of select="local-name()"/>	</th>  </xsl:template></xsl:stylesheet>

Next thing to do is to check which combination of t and s have the same r values and combine them in one row. so if i have the following table,

	<table>		 <t>10, 20</t>		 <s>49, 66, 88</s>		 <r>100, 100, 200, 300, 300, 400</r>   </table>

since for t = 10, value of r is 100 for s = 49 and 66, so the row will bet-----------s----------r10--------<66-------100and for t=10, s=88 value of r = 200, so it will be in a row of its own10------88----------200so the final output will be as follows,t----------------s--------------r10------------<66------------10010------------88-------------20020------------<66-----------30020------------88------------400I think it will take me a couple of days at least to figure it out myself, however, i will appreciate any hints or functions to use.Basit

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...