xsl to flatten xml nodes

Simon (49)

Usenet Archive
Joined
Mar 27, 2004
Messages
3
Reaction score
0
Hi,

I have generated an xml document, and would like to be able to transform it to another such that the contents of a chosen node type are flattened (i.e.
tags removed). e.g.

<shop>
<name>super</name>
<sells>
<drink>squash</drink>
<drink>beer</drink>
<food>
<fresh>bread</fresh>
<fresh>apples</fresh>
<frozen>peas</frozen>
</food>
</sells>
</shop>

apply 'flatten' to <sells> to give...

<shop>
<name>super</name>
<sells>
squash
beer
bread
apples
peas
</sells>
</shop>

This seems like the kind of thing I could use xsl for. Could someone please give me a xsl example showing how this would be done?

Thanks for your time,
Simon
 

Simon (49)

Usenet Archive
Joined
Mar 27, 2004
Messages
3
Reaction score
0
This is quite straightforward. This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:eek:utput omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*" />

<xsl:template match="@* | node">
<xsl:copy>
<xsl:apply-templates select="@* | node"/>
</xsl:copy>
</xsl:template>

<xsl:template match="*[ancestor::sells]">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="text[ancestor::sells]">
<xsl:value-of select="concat('
',.)"/>
</xsl:template>

</xsl:stylesheet>

Thanks for such a quick response! Is there any chance you could talk me through it so I fully understand how it works? My xsl book hasn't arrived yet! Thanks again, Simon
 

Dimitre Novatchev MVP XML

Usenet Archive
Joined
Feb 11, 2004
Messages
43
Reaction score
0
Simon said:
Hi,

I have generated an xml document, and would like to be able to transform it to another such that the contents of a chosen node type are flattened (i.e.
tags removed). e.g.

<shop>
<name>super</name>
<sells>
<drink>squash</drink>
<drink>beer</drink>
<food>
<fresh>bread</fresh>
<fresh>apples</fresh>
<frozen>peas</frozen>
</food>
</sells>
</shop>

apply 'flatten' to <sells> to give...

<shop>
<name>super</name>
<sells>
squash
beer
bread
apples
peas
</sells>
</shop>

This seems like the kind of thing I could use xsl for. Could someone please give me a xsl example showing how this would be done?

This is quite straightforward. This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:eek:utput omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*" />

<xsl:template match="@* | node">
<xsl:copy>
<xsl:apply-templates select="@* | node"/>
</xsl:copy>
</xsl:template>

<xsl:template match="*[ancestor::sells]">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="text[ancestor::sells]">
<xsl:value-of select="concat('
',.)"/>
</xsl:template>

</xsl:stylesheet>

when applied on your source.xml:

<shop>
<name>super</name>
<sells>
<drink>squash</drink>
<drink>beer</drink>
<food>
<fresh>bread</fresh>
<fresh>apples</fresh>
<frozen>peas</frozen>
</food>
</sells>
</shop>

produces the wanted result:

<shop>
<name>super</name>
<sells>
squash
beer
bread
apples
peas</sells>
</shop>

Cheers,

Dimitre Novatchev [XML MVP],
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html
 

Martin Honnen

Usenet Archive
Joined
Apr 8, 2000
Messages
6,174
Reaction score
0
That template above is an identity transformation, it copies nodes from the source document to the result document. Many XSLT transformations use that template if much of the source document has to be copied over to the result document. Now you only need to write templates for those elements that are not to be copied.
<xsl:template match="*[ancestor::sells]">
<xsl:apply-templates/>
</xsl:template>

That template matches any element nodes whose ancestor is a <sells> element, that is your <drink> or <food> or <fresh> element. For those you don't want to copy the element but only their text content so all the template does is call xsl:apply-templates on the child nodes.
<xsl:template match="text[ancestor::sells]">
<xsl:value-of select="concat('
',.)"/>
</xsl:template>

This template then deals with all the text nodes which have a <sells> element as an ancestor and outputs any of them on a line of its own.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
548,208
Messages
3,104,798
Members
249,594
Latest member
henrywalsh

Latest Threads

Top