Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Need help to create an XSL 1

Status
Not open for further replies.

royboy75

Programmer
Feb 13, 2007
114
GB
Hello,

I have an XML document that I need to create a table from it's data using XSL. The problem is that the document is dynamic, all I know about it is that it's root is always <MappingData> and that it's elements are under <MappingDataElement>, how many elements will be inside <MappingDataElement> is unkown for each file (but of course for a given file the number of elements under <MappingDataElement> is fixed.
So, a file can look for example like this:

<MappingData>
<MappingDataElement>
<A>Data A1</A>
<B>Data B1</B>
</MappingDataElement>
<MappingDataElement>
<A>Data A2</A>
<B>Data B2</B>
</MappingDataElement>
...
</MappingData>

Or like this:

<MappingData>
<MappingDataElement>
<A>Data A1</A>
<B>Data B1</B>
<C>Data C1</C>
</MappingDataElement>
<MappingDataElement>
<A>Data A2</A>
<B>Data B2</B>
<C>Data C2</C>
</MappingDataElement>
...
</MappingData>

ect ect...

Can someone please help me build an XSL file which will create a table for this data?

 
You don't tell us how skilled you might be at XSL. Do you have any previous experience? Do you understand everything that is taught in the online tutorial found at w3schools, for example? I am sure that you will learn how to use <xsl:for-each> to build a table.

If you need to know how many child elements exist for <MappingDataElement>, and it remains fixed for the entire document, then you might consider the following XPath expression:
Code:
count(/MappingData/MappingDataElement[1]/*)
This expression will return a count of all the child elements of the first <MappingDataElement> subordinate to <MappingData>.

Give it a try, and show us your result. That way, we can provide more help.

Tom Morrison
 
Hey,

Thanx for the lead but how do I combine xPath functions inside an XSLT document? Can you please show me a simple example?
 
Found it. I will take your suggestion to struggle it myself and will report here the results! Thanks! :)
 
OK, I made some progress but I having trouble presenting the data correctly in the table, here is my code:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="1.0">

<xsl:output method="html"/>
<xsl:template match="/">
<html>
 <body>
   <table border="1">
	<tr bgcolor="#9acd32">
	   <xsl:for-each select="/MappingData/MappingDataElement[1]/*">
	     <th> <xsl:value-of select="name(.)"/> </th>
	   </xsl:for-each>
        </tr>
	<xsl:for-each select="/MappingData/MappingDataElement">
	   <tr>
	     <xsl:for-each select="/MappingData/MappingDataElement/.">
	     <td> <xsl:value-of select="/MappingData/."/> </td>
	     </xsl:for-each>
	   </tr>
	</xsl:for-each>
   </table>
 </body>
</html>
</xsl:template>
</xsl:stylesheet>
 
I made another progress.
Using this code I receive the correct table but I see the first node only because I specifically set [1].
My question is how to change it to a variable that runs inside the elements:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="1.0">

<xsl:output method="html"/>
<xsl:template match="/">
<html>
 <body>
   <table border="1">
	<tr bgcolor="#9acd32">
	   <xsl:for-each select="/MappingData/MappingDataElement[1]/*">
	     <th> <xsl:value-of select="local-name()"/> </th>
	   </xsl:for-each>
        </tr>
	<xsl:for-each select="/MappingData/MappingDataElement">
	   <tr>
	     <xsl:for-each select="/MappingData/MappingDataElement[1]/*">
	     <td> <xsl:value-of select="."/> </td>
	     </xsl:for-each>
	   </tr>
	</xsl:for-each>
   </table>
 </body>
</html>
</xsl:template>
</xsl:stylesheet>
 
I think it is working now!
Here is my final code, I will be happy to get reviews/corrections:
Code:
<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet xmlns:xsl='[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform'[/URL] version='1.0'>

<xsl:output method='html'/>
<xsl:template match='/'>
<html>
 <body>
   <table border='1'>
	<tr>
	   <xsl:for-each select='/MappingData/MappingDataElement[1]/*'>
	     <th><xsl:value-of select='local-name()'/></th>
	   </xsl:for-each>
        </tr>
	<xsl:for-each select='/MappingData/MappingDataElement'>
	   <tr>
	     <xsl:for-each select='child::*'>
	     <td> <xsl:value-of select='.'/> </td>
	     </xsl:for-each>
	   </tr>
	</xsl:for-each>
   </table>
 </body>
</html>
</xsl:template>
</xsl:stylesheet>
 
Congratulations! Two hours spent with good results, I would say.

child::* is redundant. You could specify simply [tt]select="*"[/tt] with the same result. I think most XSLT 'programmers' (is that what we are?) would find the simpler "*" more readable. However, this is a very minor point on a very good first effort.

Tom Morrison
 
Thank you Tom and thank you for giving me a good start! :)

Roy
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top