branching XSLT tree

R

Ruthless

hello.

All XML and XSLT are processed by preprocessor as a trees.

How can i simply display my XML as some kind of tree.

given xml:

<struct>
<node level="1" no="1">
<node level="2" no="2" />
</node>
<node level="1" no="5">
<node level="2" no="8" />
</node>
</struct>

given xslt:
<xsl:template match="struct">
<html>
<body>
<xsl:for-each select="node">
<xsl:sort select="@level"/>
<blockquote><pre>
<xsl:value-of select="name()"/> <br/>
<xsl:value-of select="@no"/> <br/>
<xsl:value-of select="@level"/>
</pre></blockquote>
</xsl:for-each>
</body>
</html>
</xsl:template>

i'd like with a little help of <blockquote> do indentation
and as a result sth like this:

node 1
node 2
node 3
node 4
node 2
node 1

but my xslt does it linear and the nodes of all levels are in the same
position:
[..]
node 4
node 2
node 1

thanx in advance
greetings R
 
D

Dimitre Novatchev

Using the first transformation from my answer to your "Looping templates"
question, and editing it a little we get the following:



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

<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="*[not(self::node) and node]">
<table border="1">
<tr>
<xsl:apply-templates select="node"/>
</tr>
</table>
</xsl:template>

<xsl:template match="node">
<tr>
<td ><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="@no"/></td>
<xsl:if test="node">
<tr>
<td>   </td>
<td>
<table border="1">
<xsl:apply-templates select="node"/>
</table>
</td>
</tr>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>


When applied on this source.xml:

<struct>
<node level="1" no="1">
<node level="2" no="2" />
<node level="2" no="3">
<node level="3" no="4"/>
</node>
<node level="2" no="5" />
</node>
<node level="1" no="6">
<node level="2" no="7">
<node level="3" no="8"/>
<node level="3" no="9"/>
</node>
<node level="2" no="10" />
<node level="2" no="11" />
</node>
</struct>


the wanted result is produced (as displayed by a browser):



node 1


node 2

node 3


node 4



node 5



node 6


node 7


node 8

node 9



node 10

node 11



Hope this helped.

Dimitre Novatchev.
FXSL developer, XML Insider,

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

Ruthless

thanks again ;D

greetings R

U¿ytkownik "Dimitre Novatchev said:
Using the first transformation from my answer to your "Looping templates"
question, and editing it a little we get the following:



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

<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="*[not(self::node) and node]">
<table border="1">
<tr>
<xsl:apply-templates select="node"/>
</tr>
</table>
</xsl:template>

<xsl:template match="node">
<tr>
<td ><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="@no"/></td>
<xsl:if test="node">
<tr>
<td>   </td>
<td>
<table border="1">
<xsl:apply-templates select="node"/>
</table>
</td>
</tr>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>


When applied on this source.xml:

<struct>
<node level="1" no="1">
<node level="2" no="2" />
<node level="2" no="3">
<node level="3" no="4"/>
</node>
<node level="2" no="5" />
</node>
<node level="1" no="6">
<node level="2" no="7">
<node level="3" no="8"/>
<node level="3" no="9"/>
</node>
<node level="2" no="10" />
<node level="2" no="11" />
</node>
</struct>


the wanted result is produced (as displayed by a browser):



node 1


node 2

node 3


node 4



node 5



node 6


node 7


node 8

node 9



node 10

node 11



Hope this helped.

Dimitre Novatchev.
FXSL developer, XML Insider,

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






Ruthless said:
hello.

All XML and XSLT are processed by preprocessor as a trees.

How can i simply display my XML as some kind of tree.

given xml:

<struct>
<node level="1" no="1">
<node level="2" no="2" />
</node>
<node level="1" no="5">
<node level="2" no="8" />
</node>
</struct>

given xslt:
<xsl:template match="struct">
<html>
<body>
<xsl:for-each select="node">
<xsl:sort select="@level"/>
<blockquote><pre>
<xsl:value-of select="name()"/> <br/>
<xsl:value-of select="@no"/> <br/>
<xsl:value-of select="@level"/>
</pre></blockquote>
</xsl:for-each>
</body>
</html>
</xsl:template>

i'd like with a little help of <blockquote> do indentation
and as a result sth like this:

node 1
node 2
node 3
node 4
node 2
node 1

but my xslt does it linear and the nodes of all levels are in the same
position:
[..]
node 4
node 2
node 1

thanx in advance
greetings R
 
R

Ruthless

I thought about my example and thought about what might happen if e.g.
element node will be inside some other hierarchy.

For instance - i took my doc.xml and created family.xml

I took <node> as <person>. I've created generations, mariages, singles, and
children(mariages) for new recursive generations.

Still does node has its own hierarchy inside generation hierarchy(i hope i
made myself clear ;))

I tried to branch(display) only the <person>

given xml:

<?xml version="1.0" encoding="iso-8859-2"?>
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
<tree>
<generation level="1">
<mariage>
<person>
<first_name>Aaa</first_name>
<last_name>Qwq</last_name>
</person>
<person>
<first_name>Bbb</first_name>
<last_name>aaa</last_name>
</person>
<children>
<generation level="2">
<mariage>
<person>
<first_name>MMM</first_name>
<last_name>qqq</last_name>
</person>
<person>
<first_name>P</first_name>
<last_name>K</last_name>
</person>
<children/>
</mariage>
<single>
<person>
<first_name>P</first_name>
<last_name>ww</last_name>
</person>
</single>
</generation>
</children>
</mariage>
<single>
<person>
<first_name>P</first_name>
<last_name>ww</last_name>
</person>
</single>

</generation>
</tree>

and yours the stylesheet(a bit modified):

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

<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="*[not(self::person) and person]">
<table border="1">
<tr>
<xsl:apply-templates select="person"/>
</tr>
</table>
</xsl:template>

<xsl:template match="person">
<tr>
<td ><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="last_name"/></td>
<td><xsl:value-of select="first_name"/></td>
<xsl:if test="person">
<tr>
<td>   </td>
<td>
<table border="1">
<xsl:apply-templates select="person"/>
</table>
</td>
</tr>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>

I tried to display all the persons - but only top generation(level='1') was
displayed

I don't know how to ommit all those unnecessary(from my point of view, as
far as i'm only interested in persons) elements and simply display only
persons as a branching table.

thanks in advance
you already helped me a lot with the understanding the XSLT

greetings R
 
D

Dimitre Novatchev

Ruthless said:
I thought about my example and thought about what might happen if e.g.
element node will be inside some other hierarchy.

For instance - i took my doc.xml and created family.xml

I took <node> as <person>. I've created generations, mariages, singles, and
children(mariages) for new recursive generations.

Still does node has its own hierarchy inside generation hierarchy(i hope i
made myself clear ;))

I tried to branch(display) only the <person>

given xml:

<?xml version="1.0" encoding="iso-8859-2"?>
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
<tree>
<generation level="1">
<mariage>
<person>
<first_name>Aaa</first_name>
<last_name>Qwq</last_name>
</person>
<person>
<first_name>Bbb</first_name>
<last_name>aaa</last_name>
</person>
<children>
<generation level="2">
<mariage>
<person>
<first_name>MMM</first_name>
<last_name>qqq</last_name>
</person>
<person>
<first_name>P</first_name>
<last_name>K</last_name>
</person>
<children/>
</mariage>
<single>
<person>
<first_name>P</first_name>
<last_name>ww</last_name>
</person>
</single>
</generation>
</children>
</mariage>
<single>
<person>
<first_name>P</first_name>
<last_name>ww</last_name>
</person>
</single>

</generation>
</tree>

and yours the stylesheet(a bit modified):

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

<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="*[not(self::person) and person]">
<table border="1">
<tr>
<xsl:apply-templates select="person"/>
</tr>
</table>
</xsl:template>

<xsl:template match="person">
<tr>
<td ><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="last_name"/></td>
<td><xsl:value-of select="first_name"/></td>
<xsl:if test="person">
<tr>
<td>   </td>
<td>
<table border="1">
<xsl:apply-templates select="person"/>
</table>
</td>
</tr>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>

I tried to display all the persons - but only top generation(level='1') was
displayed

I don't know how to ommit all those unnecessary(from my point of view, as
far as i'm only interested in persons) elements and simply display only
persons as a branching table.

thanks in advance
you already helped me a lot with the understanding the XSLT

Dear R,

Yes, this is possible.

I started with a transformation, which produces a nice hierarchical html
display of all elements in the xml tree.

Then I masked all elements, whose name is not the same as the value of a
special xsl:param.

Here's the result:

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

<xsl:param name="pNodeName" select="'person'"/>

<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="*">
<tr>
<td >
<xsl:if test="name() = $pNodeName">
<xsl:value-of select="name()"/>
</xsl:if>
<xsl:text> </xsl:text>
</td>
<td>
<xsl:if test="name() = $pNodeName">
<xsl:variable name="vNodeNum">
<xsl:number count="*" level="multiple"/>
</xsl:variable>
<xsl:value-of select="$vNodeNum"/>
</xsl:if>
<xsl:text> </xsl:text>
</td>
<xsl:if test="*">
<tr>
<td>   </td>
<td>
<table border="1">
<xsl:apply-templates select="*"/>
</table>
</td>
</tr>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>


Hope that this helped.


Dimitre Novatchev.
FXSL developer, XML Insider,

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

Ruthless

once again thanks

greetings R

U¿ytkownik "Dimitre Novatchev said:
Ruthless said:
I thought about my example and thought about what might happen if e.g.
element node will be inside some other hierarchy.

For instance - i took my doc.xml and created family.xml

I took <node> as <person>. I've created generations, mariages, singles, and
children(mariages) for new recursive generations.

Still does node has its own hierarchy inside generation hierarchy(i hope i
made myself clear ;))

I tried to branch(display) only the <person>

given xml:

<?xml version="1.0" encoding="iso-8859-2"?>
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
<tree>
<generation level="1">
<mariage>
<person>
<first_name>Aaa</first_name>
<last_name>Qwq</last_name>
</person>
<person>
<first_name>Bbb</first_name>
<last_name>aaa</last_name>
</person>
<children>
<generation level="2">
<mariage>
<person>
<first_name>MMM</first_name>
<last_name>qqq</last_name>
</person>
<person>
<first_name>P</first_name>
<last_name>K</last_name>
</person>
<children/>
</mariage>
<single>
<person>
<first_name>P</first_name>
<last_name>ww</last_name>
</person>
</single>
</generation>
</children>
</mariage>
<single>
<person>
<first_name>P</first_name>
<last_name>ww</last_name>
</person>
</single>

</generation>
</tree>

and yours the stylesheet(a bit modified):

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

<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="*[not(self::person) and person]">
<table border="1">
<tr>
<xsl:apply-templates select="person"/>
</tr>
</table>
</xsl:template>

<xsl:template match="person">
<tr>
<td ><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="last_name"/></td>
<td><xsl:value-of select="first_name"/></td>
<xsl:if test="person">
<tr>
<td>   </td>
<td>
<table border="1">
<xsl:apply-templates select="person"/>
</table>
</td>
</tr>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>

I tried to display all the persons - but only top generation(level='1') was
displayed

I don't know how to ommit all those unnecessary(from my point of view, as
far as i'm only interested in persons) elements and simply display only
persons as a branching table.

thanks in advance
you already helped me a lot with the understanding the XSLT

Dear R,

Yes, this is possible.

I started with a transformation, which produces a nice hierarchical html
display of all elements in the xml tree.

Then I masked all elements, whose name is not the same as the value of a
special xsl:param.

Here's the result:

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

<xsl:param name="pNodeName" select="'person'"/>

<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="*">
<tr>
<td >
<xsl:if test="name() = $pNodeName">
<xsl:value-of select="name()"/>
</xsl:if>
<xsl:text> </xsl:text>
</td>
<td>
<xsl:if test="name() = $pNodeName">
<xsl:variable name="vNodeNum">
<xsl:number count="*" level="multiple"/>
</xsl:variable>
<xsl:value-of select="$vNodeNum"/>
</xsl:if>
<xsl:text> </xsl:text>
</td>
<xsl:if test="*">
<tr>
<td>   </td>
<td>
<table border="1">
<xsl:apply-templates select="*"/>
</table>
</td>
</tr>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>


Hope that this helped.


Dimitre Novatchev.
FXSL developer, XML Insider,

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

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top