Re: [xsl] write text using XSLT

Subject: Re: [xsl] write text using XSLT
From: Jon Gorman <jonathan.gorman@xxxxxxxxx>
Date: Fri, 19 Aug 2005 10:42:26 -0500
On 8/19/05, Praveenjothi Paranjothi <praveen_eu@xxxxxxxxx> wrote:
> Dear all,
>
> I am new to XML and XSLT. My task is to convert a XML
> file to CSV format. I have finished matching the
> elements and retrieving the data and writing as comma
> separated values. This data is basically from a
> Database and unfortunately the XML file does not
> contain the column names of the datas. I would like to
> write the column names of the data in XSLT so that it
> can be printed in the CSV file.
>
> I would like to know how to print a text once in the
> CSV format using XSLT.

ummm...have it print just once, not in a template that matches for every row.

Your xslt script you gave seemed broken (missing a template tag?).
But in any case, adding a template rule like the following should do
the trick.

 <xsl:template match="/">
product_number,product,quantity,size
<xsl:apply-templates />
</xsl:tempalte>

You might have spacing issues and need to do

<xsl:template match="/">
<xsl:text>product_number,product,quantity,size
</xsl:text>
<xsl:apply-templates />
</xsl:template>


>
> In the above stylesheet I want
> product_number,product_id,quantity,size to be written
> into the text format only once. But for each product
> row I get the above names written. Kindly suggest me
> how to solve the above problem.

I think you're confused by how the processing is done in XSLT.  I'm
going to make a radical leap and figure your actual stylesheet looks
like the one below

<?xml version="1.0"?>
<xsl:stylesheet version = "1.0"
   xmlns:xsl =
"http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="text"/>
<xsl:template match="row">
product_number,product,quantity,size
<xsl:value-of
select="description/@product_number"/>,<xsl:value-of
select="description"/>,<xsl:value-of
select="quantity"/>,<xsl:value-of select="size"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>

Your actual xml file probably looks like:

<databaseout>
<row>
... fill in the blanks
</row>
<row>
...
</row>
</databaseout>


So your stylesheet is taking advantage of built-in templates.  When
processing your stylesheet, it starts at the very top of the tree,
before the first element at "/".  A built-in template matches "/".
This template essentially says copy all text and process all children.
 / has no text, so it processes it's only child, databaseout.  The
same built-in template matches databaseout, so it copies the text
nodes and processes the children (all the row elements).  Read more in
the faq on these build-in templates (also called default rules I
believe).

Processing the row elements causes it to be matched by your
<xsl:template match="row"> template and the built-in rules.  Your
template by default has a higher priority match, so it wins and is the
one applies.  To get the first row to be what you want you really want
the first child of the resulting output tree to be a row of specific
text.   So you want the template to match at a higher level in the
tree than the row elements, hence either /  (document root) or the
first element in the document (databaseout).

Which is why I added <xsl:template match="/"> and put in that first
row.  It'll match once, write the text, and then apply templates to
all children of /.

Think of the processing as a tree and it'll make it easier.

Jon Gorman

Current Thread