Different transforms for different children of same type

R

Ravi

My XML looks something like:

<one>
....
<two>A</two>
<two>B</two>
<two>C</two>
<two>D</two>
....
</one>

I want to transform this so that the XHTML looks like

Two:
A, B, C, D

If I use

<xsl:template match="two">
Two:<br/><xsl:value-of select="."/>,
</xsl:template>

This would cause

Two:
A,
Two:
B,
Two:
C,
Two:
D,

to be displayed which is not what I want. So my question is whether
there is someway to know what child (in terms of number) a given node is
of its parent i.e. when I see "two" for the first time and last time I
can do one type of transform and another type of transform for all other
occurances of "two" (i.e. not the first and last child (of type "two")
of parent "one").

On a related note is there someway to club together all occurances of
"two" if they are not contiguous i.e if the XML looks like

<one>
....
<two>A</two>
....
<two>B</two>
....
<two>C</two>
....
<two>D</two>
....
</one>

can I still have all the "two" elements clubbed together in the final
display?

What would be a good way to display the elements in a well aligned
manner on a single line (I do not know the number of values in advance
so I cannot create a table)? Basically after each value is printed I
want the next element displayed starting at the next tab (if one exists
on current line) or the first column of the next line.

TIA.
 
P

Patrick TJ McPhee

[...]

% to be displayed which is not what I want. So my question is whether
% there is someway to know what child (in terms of number) a given node is
% of its parent

You can use position() and last(). These work best if you use a select
expression on xsl:apply-templates, or if you use xsl:for-each.

% On a related note is there someway to club together all occurances of
% "two" if they are not contiguous i.e if the XML looks like

You can use a select expression on xsl:apply-templates or use xsl:for-each
<xsl:template match="one">
<xsl:text>Two: </xsl:text>
<xsl:apply-templates select="two"/>
<!-- ... -->
</xsl:template>

<xsl:template match="two"/>
<xsl:value-of select='.'/>
<xsl:if test='position() != last()'>, </xsl:if>
</xsl:for-each/>

or

<xsl:template match="one">
<xsl:text>Two: </xsl:text>
<xsl:for-each select="two"/>
<xsl:value-of select='.'/>
<xsl:if test='position() != last()'>, </xsl:if>
</xsl:for-each/>
<!-- ... -->
</xsl:template>

This is completely untested.
 
R

Ravi

Patrick said:
% On a related note is there someway to club together all occurances of
% "two" if they are not contiguous i.e if the XML looks like

You can use a select expression on xsl:apply-templates or use xsl:for-each
<xsl:template match="one">
<xsl:text>Two: </xsl:text>
<xsl:apply-templates select="two"/>
<!-- ... -->
</xsl:template>

<xsl:template match="two"/>
<xsl:value-of select='.'/>
<xsl:if test='position() != last()'>, </xsl:if>
</xsl:for-each/>

or

<xsl:template match="one">
<xsl:text>Two: </xsl:text>
<xsl:for-each select="two"/>
<xsl:value-of select='.'/>
<xsl:if test='position() != last()'>, </xsl:if>
</xsl:for-each/>
<!-- ... -->
</xsl:template>

This is completely untested.

Thank you for your reply. I have had to modify my xml and it now looks like

<one>
....
<two type="a">1</two>
<two type="b">2</two>
<two type="c">3</two>
<two type="a">4</two>
<two type="c">5</two>
<two type="d">6</two>
<two type="a">7</two>
....
</one>

and the clubbing is to be based on the type (i.e. attribute value) of
the element and not its name i.e.

Two
a:
1, 4, 7
b:
2
c:
3, 5
d:
6

I cannot know in advance which type(s) of "two" is(are) present or how
many of each type there are (although all the "two" elements will be
contiguous). Any suggestions will be highly appreciated.

TIA.
 
D

Dimitre Novatchev

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput omit-xml-declaration="yes"/>

<xsl:template match="text()"/>

<xsl:template match="two">
<xsl:if test="not(preceding-sibling::two)">Two:
</xsl:if>
<xsl:value-of select="."/>
<xsl:if test="following-sibling::two">, </xsl:if>
</xsl:template>
</xsl:stylesheet>

when applied on your source.xml:

<one>
....
<two>A</two>
<two>B</two>
<two>C</two>
<two>D</two>
....
</one>

produces the wanted result:

Two:
A, B, C, D


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top