Re: [xsl] nesting non-nested nodes

Subject: Re: [xsl] nesting non-nested nodes
From: Rudolf P. Weinmann <rudolf.weinmann@xxxxxxxxxxxx>
Date: Tue, 07 Jun 2005 20:45:18 +0200
Andrew

I amended your xml for better readability and control of the result after
transformation.

<?xml version="1.0" encoding="UTF-8?>
<Root>
	<head head-level="1">head title A1</head>
	<p>paragraph of A1</p>
	<head head-level="2">sub-head title A1.1</head>
	<p>paragraph of A1.1</p>
	<head head-level="2">sub-head title A1.2</head>
	<p>paragraph of A1.2</p>
	<head head-level="3">sub-sub-head title A1.2.1</head>
	<p>paragraph of A1.2.1</p>
	<head head-level="3">sub-sub-head title A1.2.2</head>
	<p>paragraph of A1.2.2</p>
	<head head-level="1">head title B1</head>
	<p>paragraph of B1</p>
</Root>

A similar question has been answered, please see '[xsl] flat XML to normal
XML' in this list.

If you know the highest value for @head-level, the xslt is straight forward.
Note, that the <xsl:apply-template
select="followin-sibling::head[1][@head-level='3']"/>
in the last template of the stylesheet is placed *after* the </level>
because head elements with @head-level='3' must not be nested.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<!-- Created:2005-06-07 Author:rudolf.weinmann@xxxxxxxxxxxx
http://www.assentis.com -->
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
	<NewDataSet>
		<!-- select all top level head elements -->
		<xsl:apply-templates select="Root/head[@head-level='1']"/>
	</NewDataSet>
</xsl:template>

<xsl:template match="head[@head-level='1']">
	<level>
		<title>
			<xsl:value-of select="."/>
		</title>
		<xsl:copy-of select="following-sibling::p[1]"/>
		<!-- select all adjaicent head elements with the next higher @head-level
-->
		<xsl:apply-templates select="following-sibling::head[@head-level='2']"/>
	</level>
</xsl:template>

<xsl:template match="head[@head-level='2']">
	<level>
		<title>
			<xsl:value-of select="."/>
		</title>
		<xsl:copy-of select="following-sibling::p[1]"/>
		<!-- select the adjaicent head element, if it is the next higher @head-level
-->
		<xsl:apply-templates select="following-sibling::head[1][@head-level='3']"/>
	</level>
</xsl:template>

<xsl:template match="head[@head-level='3']">
	<level>
		<title>
			<xsl:value-of select="."/>
		</title>
		<xsl:copy-of select="following-sibling::p[1]"/>
	</level>
	<!-- select the adjaicent head element, if it is the next higher @head-level
-->
	<!-- this apply-templates is *after* </level>, because @head-level='3'
elements must not be nested -->
	<xsl:apply-templates select="following-sibling::head[1][@head-level='3']"/>
</xsl:template>

</xsl:stylesheet>

And the result:
<?xml version='1.0' encoding='UTF-8' ?>
<NewDataSet>
  <level>
    <title>head title A1</title>
    <p>paragraph of A1</p>
    <level>
      <title>sub-head title A1.1</title>
      <p>paragraph of A1.1</p>
    </level>
    <level>
      <title>sub-head title A1.2</title>
      <p>paragraph of A1.2</p>
      <level>
        <title>sub-sub-head title A1.2.1</title>
        <p>paragraph of A1.2.1</p>
      </level>
      <level>
        <title>sub-sub-head title A1.2.2</title>
        <p>paragraph of A1.2.2</p>
      </level>
    </level>
  </level>
  <level>
    <title>head title B1</title>
    <p>paragraph of B1</p>
  </level>
</NewDataSet>

Hope this helps,
Rudolf

On Tue, 7 Jun 2005 10:48:49 -0400, you wrote:

>Hello all,
>I searched the archives for an answer to this, but I'm not sure how
>best to describe what I'm looking for. Sorry if this question has been
>asked previously. I'm trying to take non-nested nodes and get them
>nested. I'm using XSL version 1.0 and my processor is Libxslt.
>
>SOURCE:
>
><head head-level="1">
>	head title
></head>
><p>
>	paragraph(s)
></p>
><head head-level="2">
>	sub-head title
></head>
><p>
>	paragraph(s)
></p>
><head head-level="2">
>	sub-head title
></head>
><p>
>	paragraph(s)
></p>
><head head-level="3">
>	sub-sub-head title
></head>
><p>
>	paragraph(s)
></p>
><head head-level="1">
>	head title
></head>
><p>
>	For simplicity, I've reduced any amount of content in between head's
>to a single p.
></p>
>
>
>DESIRED RESULT:
>
><level>
>	<title>
>		head title
>	</title>
>	<p>
>		paragraph(s)
>	</p>
>	<level>
>		<title>
>			sub-head title
>		</title>
>		<p>
>			paragraph(s)
>		</p>
>	</level>
>	<level>
>		<title>
>			sub-head title
>		</title>
>		<p>
>			paragraph(s)
>		</p>
>		<level>
>			<title>
>				sub-sub-head title
>			</title>
>			<p>
>				paragraph(s)
>			</p>
>		</level>
>	</level>
></level>
><level>
>	<title>
>		head title
>	</title>
>	<p>
>		For simplicity, I've reduced any amount of content in between head's
>to a single p.
>	</p>
></level>
>
>
>Thank you all. This list is such a valuable resource.
>
>-Andrew

Current Thread