XSLT 1.0 grouping childs when followed by a certain node - xslt

Input xml:
<entry>
<text>
<p>xyz</p>
<p>xyz</p>
<p>xyz</p>
<p>xyz</p>
<author>abc</author>
<p>xyz</p>
<p>xyz</p>
<p>xyz</p>
<author>abc</author>
</text>
</entry>
I'm using XSLT 1.0.
I would like to select all <p> elements until the next <author> element and group them (together with the next <author> element) under a new <div> element. So expected output look like this:
<entry>
<text>
<div>
<p>xyz</p>
<p>xyz</p>
<p>xyz</p>
<p>xyz</p>
<author>abc</author>
</div>
<div>
<p>xyz</p>
<p>xyz</p>
<p>xyz</p>
<author>abc</author>
</div>
</text>
</entry>
I tried this solution:
<xsl:template match="entry">
<entry>
<text>
<div>
<xsl:apply-templates select="child::node()[not(preceding-sibling::author)]"/>
</div>
</text>
</entry>
</xsl:template>
which works fine for the first group of <p> + <author>, but not for the next group(s).
I would appreciate any help.

You may group all elements before an author (preceding-sibling:* which are not author (name() != 'author') and have the current author as next following author
(generate-id( following-sibling::author[1]) = generate-id(current())):
preceding-sibling::*[ name() != 'author' and
generate-id( following-sibling::author[1]) = generate-id(current()) ]
Try something like this:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*" />
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text">
<xsl:copy>
<xsl:apply-templates select="author" mode="adddiv"/>
</xsl:copy>
</xsl:template>
<xsl:template match="author" mode="adddiv" >
<!-- preceding siblings not author -->
<xsl:variable name="fs" select="preceding-sibling::*[ name() != 'author' and
generate-id( following-sibling::author[1]
) = generate-id(current()) ]" />
<div >
<xsl:apply-templates select="$fs | ." />
</div>
</xsl:template>
</xsl:stylesheet>
Which will generate the following output:
<entry>
<text>
<div>
<p>xyz</p>
<p>xyz</p>
<p>xyz</p>
<p>xyz</p>
<author>abc</author>
</div>
<div>
<p>xyz</p>
<p>xyz</p>
<p>xyz</p>
<author>abc</author>
</div>
</text>
</entry>

Related

Getting rid of empty namespaces

I have the following xml:
<?xml version="1.0" encoding="UTF-8"?>
<Test xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lab="urn:oid:7.6">
<section>
<id extension="something" root="testRoot"/>
<text>
<paragraph styleCode="somestyle">Soemthing</paragraph>
<table>
<thead>
<tr>
<th styleCode="styled">Style</th>
<th>Stuff</th>
</tr>
</thead>
</table>
</text>
</section>
</Test>
and this is the xslt:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="urn:hl7-org:v3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="#all">
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match = "c:section/ c:text">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates/>
</div>
</text>
</xsl:template>
</xsl:stylesheet>
This is the output:
<?xml version="1.0" encoding="UTF-8"?><Test>
<section>
<id extension="something" root="testRoot"/>
<text><status value="generated"/><div xmlns="http://www.w3.org/1999/xhtml">
<paragraph xmlns="" styleCode="somestyle">Soemthing</paragraph>
<table xmlns="">
<thead>
<tr>
<th styleCode="styled">Style</th>
<th>Stuff</th>
</tr>
</thead>
</table>
</div></text>
</section>
</Test>
As you might expect, I don't want any of those empty namespaces like in paragraph and table. I want to get rid of them so that those elements are just as they are without any namespaces but the div element should retain the namespace.
EDIT: I also would like to get rid of the attributes (including their values) for all elements under text. So that final output looks like this:
<?xml version="1.0" encoding="UTF-8"?><Test>
<section>
<id extension="something" root="testRoot"/>
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<paragraph>Soemthing</paragraph>
<table>
<thead>
<tr>
<th>Style</th>
<th>Stuff</th>
</tr>
</thead>
</table>
</div>
</text>
</section>
</Test>
I am guessing (!) you want to do:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="urn:hl7-org:v3"
exclude-result-prefixes="c">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="*" mode="xhtml" >
<xsl:element name="{local-name(.)}" namespace="http://www.w3.org/1999/xhtml">
<xsl:apply-templates select="#* | node()" mode="xhtml"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*" mode="#all">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="c:section/c:text">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates mode="xhtml"/>
</div>
</text>
</xsl:template>
</xsl:stylesheet>
This will place all descendants of div into the same xhtml namespace as their ancestor - resulting in:
<?xml version="1.0" encoding="UTF-8"?>
<Test>
<section>
<id extension="something" root="testRoot"/>
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<paragraph styleCode="somestyle">Soemthing</paragraph>
<table>
<thead>
<tr>
<th styleCode="styled">Style</th>
<th>Stuff</th>
</tr>
</thead>
</table>
</div>
</text>
</section>
</Test>
Note that this is not valid XHTML markup.
Edit
I also would like to get rid of the attributes (including their
values) for all elements under text.
Well, then don't apply templates to them:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="urn:hl7-org:v3"
exclude-result-prefixes="c">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="*" mode="xhtml" >
<xsl:element name="{local-name(.)}" namespace="http://www.w3.org/1999/xhtml">
<xsl:apply-templates mode="xhtml"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="c:section/c:text">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates mode="xhtml"/>
</div>
</text>
</xsl:template>
</xsl:stylesheet>

How to match and wrap identical and adjacent node together in XSLT 1.0?

I have an XML file that look like this and I'm trying to wrap "Para_bb" node that are adjacent to each other with a div.
<Para_a></Para_a>
<Para_a></Para_a>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_a></Para_a>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_a></Para_a>
<Para_a></Para_a>
<Para_bb></Para_bb>
How can I make it look like this?
<p></p>
<p></p>
<div class="blackBox">
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
</div>
<p></p>
<div class="blackBox">
<Para_bb></Para_bb>
<Para_bb></Para_bb>
</div>
<p></p>
<p></p>
<div class="blackBox">
<Para_bb></Para_bb>
</div>
You can define a key as follows:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="group" match="Para_bb[preceding-sibling::*[1][self::Para_bb]]" use="generate-id(preceding-sibling::Para_bb[not(preceding-sibling::*[1][self::Para_bb])][1])"/>
<xsl:template match="Root">
<body>
<xsl:apply-templates/>
</body>
</xsl:template>
<xsl:template match="Para_a">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="Para_bb[preceding-sibling::*[1][self::Para_bb]]"/>
<xsl:template match="Para_bb[not(preceding-sibling::*[1][self::Para_bb])]">
<div class="blackBox">
<xsl:copy-of select=". | key('group', generate-id())"/>
</div>
</xsl:template>
</xsl:stylesheet>
That transforms
<Root>
<Para_a></Para_a>
<Para_a></Para_a>
<Para_bb>1</Para_bb>
<Para_bb>2</Para_bb>
<Para_bb>3</Para_bb>
<Para_bb>4</Para_bb>
<Para_a></Para_a>
<Para_bb>5</Para_bb>
<Para_bb>6</Para_bb>
<Para_a></Para_a>
<Para_a></Para_a>
<Para_bb>7</Para_bb>
</Root>
into
<body>
<p/>
<p/>
<div class="blackBox">
<Para_bb>1</Para_bb>
<Para_bb>2</Para_bb>
<Para_bb>3</Para_bb>
<Para_bb>4</Para_bb>
</div>
<p/>
<div class="blackBox">
<Para_bb>5</Para_bb>
<Para_bb>6</Para_bb>
</div>
<p/>
<p/>
<div class="blackBox">
<Para_bb>7</Para_bb>
</div>
</body>
One way to do this in XSLT 1.0 is to have a template that matches the first occurrence of each Para_bb element in a group
<xsl:template match="Para_bb[not(preceding-sibling::*[1][self::Para_bb])]">
Then you would call a new template, with a mode specified, just on this first element
<p>
<xsl:apply-templates select="." mode="div" />
</p>
Then, in the template matching Para_bb with the mode specified, you would copy the element, and select the next sibling, but only if it is another Para_bb
<xsl:template match="Para_bb" mode="div">
<xsl:call-template name="identity" />
<xsl:apply-templates select="following-sibling::*[1][self::Para_bb]" mode="div"/>
</xsl:template>
(Where the named template being called is the standard identity template)
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Para_bb[not(preceding-sibling::*[1][self::Para_bb])]">
<div class="blackBox">
<xsl:apply-templates select="." mode="div" />
</div>
</xsl:template>
<xsl:template match="Para_bb" />
<xsl:template match="Para_a">
<p>
<xsl:apply-templates select="#*|node()"/>
</p>
</xsl:template>
<xsl:template match="Para_bb" mode="div">
<xsl:call-template name="identity" />
<xsl:apply-templates select="following-sibling::*[1][self::Para_bb]" mode="div"/>
</xsl:template>
<xsl:template match="#*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Finding following sibling of text node

I am trying to wrap all the text node in a <text> element, but facing challenge when encounter an inline elements (i, b, emphasis), that should be in same <text> node (in other words, it should be considered as text)... Please see input and desired output below:
(Note: I have to do this for specific inline elements only, hence kept it in param (it could be anything), for rest of the elements standard <text> rule should be applied. (Please see my xslt for details)
Input XML:
<?xml version="1.0" encoding="utf-8"?>
<root>
<para>XML Translation is a format that's used to <emphasis>exchange <i>localisation</i></emphasis>data</para>
<para>The process can now be reformulated with more detail as follows:<ul>
<li>Text extraction <note>Separation of translatable text from layout data</note></li>
<li>Pre-translation</li>
<li>Translation</li>
<li>Reverse conversion</li>
<li>Translation memory improvement</li>
</ul>above mentioned steps should <b>executed</b> sequentially</para>
</root>
OutPut should be:
<?xml version="1.0" encoding="utf-8"?>
<root>
<para>
<text xid="d0t3">XML Translation is a format that's used to <g ctype="emphasis">exchange <g ctype="i">localisation</g></g>data </text>
</para>
<para>
<text xid="d0t10">The process can now be reformulated with more detail as follows:</text>
<ul>
<li><text xid="d0t13">Text extraction <g ctype="note">Separation of translatable text from layout data</g></text></li>
<li><text xid="d0t17">Pre-translation</text></li>
<li><text xid="d0t19">Translation</text></li>
<li><text xid="d0t21">Reverse conversion</text></li>
<li><text xid="d0t23">Translation memory improvement</text></li>
</ul>
<text xid="d0t24">above mentioned steps should <g ctype="b">executed</g> sequentially</text>
</para>
</root>
I am trying something like this, but not able to achieve correct result:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:param name="inlineElement" select="('emphasis', 'i', 'note', 'b')"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<text>
<xsl:attribute name="xid">
<xsl:value-of select="generate-id()"/>
</xsl:attribute>
<xsl:value-of select="."/>
<xsl:if test="following-sibling::node()[local-name()=$inlineElement]">
<g>
<xsl:apply-templates select="following-sibling::node()[local-name()=$inlineElement]/text()"/>
</g>
</xsl:if>
</text>
</xsl:template>
</xsl:stylesheet>
I would use for-each-group group-adjacent:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:param name="inlineElement" select="('emphasis', 'i', 'note', 'b')"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(local-name() = $inlineElement)]">
<xsl:copy>
<xsl:for-each-group select="node()" group-adjacent="boolean(self::text() | self::*[local-name() = $inlineElement])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<text xid="{generate-id(current-group()[self::text()][1])}">
<xsl:apply-templates select="current-group()"/>
</text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="*[local-name() = $inlineElement]">
<g ctype="{local-name()}">
<xsl:apply-templates/>
</g>
</xsl:template>
</xsl:stylesheet>
That way, with Saxon 9.5, I get
<?xml version="1.0" encoding="UTF-8"?>
<root>
<para>
<text xid="d1t3">XML Translation is a format that's used to <g ctype="emphasis">exchange <g ctype="i">localisation</g>
</g>data</text>
</para>
<para>
<text xid="d1t10">The process can now be reformulated with more detail as follows:</text>
<ul>
<li>
<text xid="d1t13">Text extraction <g ctype="note">Separation of translatable text from layout data</g>
</text>
</li>
<li>
<text xid="d1t17">Pre-translation</text>
</li>
<li>
<text xid="d1t19">Translation</text>
</li>
<li>
<text xid="d1t21">Reverse conversion</text>
</li>
<li>
<text xid="d1t23">Translation memory improvement</text>
</li>
</ul>
<text xid="d1t24">above mentioned steps should <g ctype="b">executed</g> sequentially</text>
</para>
</root>

finding preceding-sibling and processing in same node

Need to transform following XML snippet into DITA using XSLT. My requirements are:
1. All the tags comes before "orderedlist" should be wrapped under "context" node.
2. All the tags comes after "orderedlist" should be in "result".
3. All the "include" tags should be wrapped under their preceding sibling nodes.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<procedure>
<para>This is first para</para>
<para>This is second para</para>
<include>This is include</include>
<orderedlist>
<listitem>this is list item</listitem>
<include>This is include</include>
<listitem>this is list item <include>this is include</include></listitem>
</orderedlist>
<observation>this is observation</observation>
<para>this is result para <include>this is include</include></para>
<include>This is include</include>
</procedure>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<task>
<context>
<p>This is first para</p>
<p>This is second para <included type='tag'>This is include</included>
</p>
</context>
<ol>
<li>this is list item <included type='tag'>This is include</included>
</li>
<li>this is list item <included type='tag'>this is include</included></li>
</ol>
<result>
<observation>this is observation</observation>
<p>this is result para <included type='tag'>this is include</included><included type='tag'>this is include</included>
</p>
</result>
</task>
My XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="procedure">
<task>
<context>
<xsl:apply-templates select="*[parent::procedure][following-sibling::orderedlist]"/>
</context>
<xsl:apply-templates select="orderedlist"/>
<result>
<xsl:apply-templates select="*[parent::procedure][preceding-sibling::orderedlist]"/>
</result>
</task>
</xsl:template>
<xsl:template match="para">
<p>
<xsl:apply-templates/>
<include>
<xsl:apply-templates select="following-sibling::include"/>
</include>
</p>
</xsl:template>
<!-- rest of the template goes here -->
<xsl:template match="listitem">
<li>
<xsl:apply-templates/>
<include>
<xsl:apply-templates select="following-sibling::include"/>
</include>
</li>
</xsl:template>
</xsl:stylesheet>
Any pointer will be a great help. Thanks.
The first thing to note is you can simplify the following expression:
<xsl:apply-templates select="*[parent::procedure][following-sibling::orderedlist]"/>
You don't need the [parent::procedure] here, because you are already positioned on a procedure element, so so you know if you select any child element, it will have that as a parent!
<xsl:apply-templates select="*[following-sibling::orderedlist]"/>
However, you might need to add an clause to ensure you don't output the include elements at this point, as you will need special code to handle them being included later
<xsl:template match="include" />
To handle the include elements, it might be worth defining a key, so you can group them by the first most proceding non-include element, like so
<xsl:key name="include" match="include" use="generate-id(preceding-sibling::*[not(self::include)][1])"/>
Then, when matching an element such as para or listitem, you can then get the include elements to include, just like this:
<xsl:copy-of select="key('include', generate-id())"/>
Note I am not sure how you want to handle multipe include elements for a single element, but in my example, it will output them separately as opposing to merging them:
Here is the full XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="include" match="include" use="generate-id(preceding-sibling::*[not(self::include)][1])"/>
<xsl:template match="procedure">
<task>
<context>
<xsl:apply-templates select="*[following-sibling::orderedlist]"/>
</context>
<xsl:apply-templates select="orderedlist"/>
<result>
<xsl:apply-templates select="*[preceding-sibling::orderedlist]"/>
</result>
</task>
</xsl:template>
<xsl:template match="orderedlist">
<ol>
<xsl:apply-templates />
</ol>
</xsl:template>
<xsl:template match="para">
<p>
<xsl:apply-templates/>
<xsl:copy-of select="key('include', generate-id())" />
</p>
</xsl:template>
<xsl:template match="listitem">
<li>
<xsl:apply-templates/>
<xsl:copy-of select="key('include', generate-id())" />
</li>
</xsl:template>
<xsl:template match="include" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When applied to your sample XML, the following is output
<task>
<context>
<p>This is first para</p>
<p>This is second para<include>This is include</include></p>
</context>
<ol>
<li>this is list item<include>This is include</include></li>
<li>this is list item</li>
</ol>
<result>
<observation>this is observation</observation>
<p>this is result para<include>This is include</include></p>
</result>
</task>
Give this a try:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="#* | node()" name="Copy">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
<xsl:call-template name="Include" />
</xsl:copy>
</xsl:template>
<xsl:template match="procedure">
<task>
<context>
<xsl:apply-templates select="*[following-sibling::orderedlist]"/>
</context>
<xsl:apply-templates select="orderedlist"/>
<result>
<xsl:apply-templates select="*[preceding-sibling::orderedlist]"/>
</result>
</task>
</xsl:template>
<xsl:template match="para">
<p>
<xsl:apply-templates/>
<xsl:call-template name="Include" />
</p>
</xsl:template>
<!-- rest of the template goes here -->
<xsl:template match="listitem">
<li>
<xsl:apply-templates/>
<xsl:call-template name="Include" />
</li>
</xsl:template>
<xsl:template name="Include">
<xsl:apply-templates
select="following-sibling::include[
generate-id(preceding-sibling::*[not(self::include)][1]) =
generate-id(current())]"
mode="performIncludes"/>
</xsl:template>
<xsl:template match="include" />
<xsl:template match="include" mode="performIncludes">
<xsl:call-template name="Copy" />
</xsl:template>
</xsl:stylesheet>
Output when run on your sample input:
<task>
<context>
<p>This is first para</p>
<p>This is second para<include>This is include</include></p>
</context>
<orderedlist>
<li>this is list item<include>This is include</include></li>
<li>this is list item</li>
</orderedlist>
<result>
<observation>this is observation</observation>
<p>this is result para<include>This is include</include></p>
</result>
</task>

XSLT node transformation in a predefined order

How do I make transformation follow xml node order?
The xml file is something like this
<root>
<paragraph>First paragraph</paragraph>
<paragraph>Second paragraph</paragraph>
<unordered_list>
<list_name>Unordered list name</list_name>
<list_element>First element</list_element>
<list_element>Second element</list_element>
</unordered_list>
<paragraph>Third paragraph</paragraph>
</root>
I would like to transform it to HTML
...
<p>First paragraph</p>
<p>Second Paragraph</p>
<h3>Unordered list name</h3>
<ul>
<li>First element</li>
<li>Second element</li>
</ul>
<p>Third paragraph</p>
...
When I use xsl:for-each
It outputs all paragraphs first and then the list, or the other way round.
I want to keep the order of the XML file.
I am aware this might be very basic but I seem to be getting nowhere using xsl:choose and xsl:if. So please help me someone.
Here is a sample xslt stylesheet that does exactly what you are looking for:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- iterate through all the child nodes,
and apply the proper template to them -->
<xsl:template match="/">
<!-- added an extra div tag, to create a correct xml
that contains only one root tag -->
<div>
<xsl:apply-templates />
</div>
</xsl:template>
<!-- create the **p** tags -->
<xsl:template match="paragraph">
<p>
<xsl:value-of select="text()" />
</p>
</xsl:template>
<!-- create the **ul** tags -->
<xsl:template match="unordered_list">
<h3>
<xsl:value-of select="list_name" />
</h3>
<ul>
<xsl:apply-templates select="list_element" />
</ul>
</xsl:template>
<!-- create the **li** tags -->
<xsl:template match="list_element">
<li>
<xsl:value-of select="text()" />
</li>
</xsl:template>
</xsl:stylesheet>
The output of this transformation will be:
<?xml version="1.0" encoding="UTF-8"?>
<div>
<p>First paragraph</p>
<p>Second paragraph</p>
<h3>Unordered list name</h3>
<ul>
<li>First element</li>
<li>Second element</li>
</ul>
<p>Third paragraph</p>
</div>
A shorter and more consize transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="paragraph">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="unordered_list/list_name">
<h3><xsl:apply-templates/></h3>
</xsl:template>
<xsl:template match="unordered_list/list_element"/>
<xsl:template match="unordered_list/list_element[1]">
<ul>
<xsl:apply-templates mode="list"
select=".|following-sibling::*"/>
</ul>
</xsl:template>
<xsl:template mode="list" match="unordered_list/list_element">
<li><xsl:apply-templates/></li>
</xsl:template>
</xsl:stylesheet>