Wrap an ordered list of nodes - xslt

Hi I have an xml document which look like that:
<a> <!-- Several nodes "a" with the same structure for children -->
<b>12</b>
<c>12</c>
<d>12</d>
<e>12</e>
<f>12</f>
<g>12</g>
</a>
I'm trying to obtain the following document using xslt 2.0
<a>
<b>12</b>
<c>12</c>
<wrap>
<d>12</d>
<e>12</e>
<f>12</f>
<g>12</g>
</wrap>
</a>
I started my xsl file with
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
And changed it for several cases like replacing a string part, filter some nodes, etc.
But I'm stuck with "selecting four consecutive nodes", any clue on how to achieve the wrapping?

If all your a elements are genuinely exactly the same structure then the simplest would be a brute-force
<xsl:template match="a">
<xsl:copy>
<xsl:apply-templates select="b | c" />
<wrap>
<xsl:apply-templates select="d | e | f | g" />
</wrap>
</xsl:copy>
</xsl:template>
or if you want to be a bit cleverer
<wrap>
<xsl:apply-templates select="* except (b | c)" />
</wrap>
If you want to always "wrap" the last four child elements of a, then how about
<xsl:template match="a">
<xsl:variable name="lastFour" select="*[position() > (last() - 4)]" />
<xsl:copy>
<xsl:apply-templates select="* except $lastFour" />
<wrap>
<xsl:apply-templates select="$lastFour" />
</wrap>
</xsl:copy>
</xsl:template>

With XSLT 2.0 you can also make use of for-each-group group-adjacent:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="boolean(self::d | self::e | self::f | self::g)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<wrap>
<xsl:apply-templates select="current-group()"/>
</wrap>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Related

XSLT transforming flat xml with dot to hierarchical xml

I want to transform below XML using XSLT. This XML elements has dots to represent hierarchy
<UsrEmployee>
<Code>70068579</Code>
<Initials>F</Initials>
<FirstName>Koichi</FirstName>
<Prefix></Prefix>
<LastName>Nakamura</LastName>
<PropertyRef>70068579</PropertyRef>
<SpaceRef.Code>001</SpaceRef.Code>
<SpaceRef.FloorRef.Code>01</SpaceRef.FloorRef.Code>
<SpaceRef.FloorRef.PropertyRef>70068579</SpaceRef.FloorRef.PropertyRef>
<SpaceRef.propertyRef>70068579</SpaceRef.propertyRef>
</UsrEmployee>
The above XML I want to transform as below XML, in the source XML element names can be any thing, number of dots(depth) is not known(not fixed). I want to create XSLT which would transform any generic XML of any size to hierarchical structure
<UsrEmployee>
<Code>70068579</Code>
<Initials>F</Initials>
<FirstName>Koichi</FirstName>
<Prefix></Prefix>
<LastName>Nakamura</LastName>
<SpaceRef>
<Code>001</Code>
<propertyRef>70068579</propertyRef>
<FloorRef>
<Code>01</Code>
<PropertyRef>70068579</PropertyRef>
</FloorRef>
</SpaceRef>
<PropertyRef>70068579</PropertyRef>
</UsrEmployee>
Can someone help me on this
Just create matching templates for your "dotted" elements and apply them.
Use select to control the "catch-all" identity template (the last template in the xslt)
Of course this may be an oversimplified solution and a more complex transformation will be needed if you have an arbitrary hierarchical structure where selecting your templates like this is not practicable.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="UsrEmployee">
<xsl:element name="UsrEmployee">
<xsl:apply-templates select="Code | Initials | FirstName | Prefix | LastName | PropertyRef" />
<xsl:element name="SpaceRef">
<xsl:apply-templates select="SpaceRef.Code | SpaceRef.propertyRef" />
<xsl:element name="FloorRef">
<xsl:apply-templates select="SpaceRef.FloorRef.Code | SpaceRef.FloorRef.PropertyRef" />
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="SpaceRef.Code">
<xsl:element name="Code">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
<xsl:template match="SpaceRef.propertyRef">
<xsl:element name="propertyRef">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
<xsl:template match="SpaceRef.FloorRef.Code">
<xsl:element name="Code">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
<xsl:template match="SpaceRef.FloorRef.PropertyRef">
<xsl:element name="PropertyRef">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

XSLT - Best practice for moving specific attributes around

I was looking for some guidance on how best to approach my issue.
I have an XML document like the following but on a larger scale.
<NewDataSet>
<Table Attri1="Attri1Val" Attri2="Attri2Val" Attri3="Attri3Val" Attri4="Attri4Val" Attri5="Attri5Val" Attri6="Attri6Val" Attri7="Attri7" />
</NewDataSet>
I need to move certain attributes from the Table node, for example Attri2 and Attri5 into elements within the Table node, however I need to leave the rest of the attributes as they are.
What would be the best way to approach this? The data scale is about 3-4 times that shown.
EDIT:
Expected output:
<NewDataSet>
<Table Attri1="Attri1Val" Attri3="Attri3Val" Attri4="Attri4Val" Attri6="Attri6Val" Attri7="Attri7">
<Attri2>Attri2Val</Attri2>
<Attri5>Attri5Val</Attri5>
</Table>
</NewDataSet>
The complexity is not really the issue, more the scale of the data and what is the best way to deal with it.
Use
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Table">
<xsl:copy>
<xsl:apply-templates select="#*[not(name() = 'Attri2') and not(name() = 'Attri5')]"/>
<xsl:apply-templates select="#Attri2 | #Attri5 | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Table/#Attri2 | Table/#Attri5">
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
[edit]
The name comparison of the attributes is a bit ugly but will probably do for your sample. What we really need is #* execpt (#Attri2, #Attri5), only that is XPath 2.0. With XPath 1.0 the equivalent is
<xsl:template match="Table">
<xsl:copy>
<xsl:variable name="all-attributes" select="#*"/>
<xsl:variable name="to-be-transformed" select="#Attri2 | #Attri5"/>
<xsl:apply-templates select="$all-attributes[count(. | $to-be-transformed) != count($to-be-transformed)]"/>
<xsl:apply-templates select="$to-be-transformed | node()"/>
</xsl:copy>
</xsl:template>
This generic transformation can handle any set of attributes, with any length, whose names can be specified externally to the 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:param name="pToTransform" select="'|Attri2|Attri5|'"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Table">
<xsl:copy>
<xsl:apply-templates select=
"#*[not(contains($pToTransform, concat('|',name(),'|')))] | node()"/>
<xsl:apply-templates mode="makeElement"
select="#*[contains($pToTransform, concat('|',name(),'|'))]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#*" mode="makeElement">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied to the provided XML document:
<NewDataSet>
<Table Attri1="Attri1Val" Attri2="Attri2Val"
Attri3="Attri3Val" Attri4="Attri4Val"
Attri5="Attri5Val" Attri6="Attri6Val"
Attri7="Attri7" />
</NewDataSet>
the wanted, correct result is produced:
<NewDataSet>
<Table Attri1="Attri1Val" Attri3="Attri3Val" Attri4="Attri4Val" Attri6="Attri6Val" Attri7="Attri7">
<Attri2>Attri2Val</Attri2>
<Attri5>Attri5Val</Attri5>
</Table>
</NewDataSet>

Replacing the namespace in input xml

I have two types of input xml, one with namespace prefix and another one without prefix and i want to replace the namespaces.
Sample1
<v1:Library xmlns:v1="http://testlibrary" xmlns:v2="http://commonprice">
<v1:Books_details>
<v1:Name>test1</v1:Name>
<v1:title>test2</v1:title>
<v2:price xmlns="http://commonprice">12</v2:price>
</v1:Books_details>
</v1:Library>
Sample2
<Library xmlns="http://testlibrary">
<Books_details>
<Name>test1</Name>
<title>test2</title>
<price xmlns="http://commonprice">12</price>
</Books_details>
</Library>
I have written following XSLT to change the namespace from "http://testlibrary" to "http://newlibrary" and it works fine for sample1 but it doesn't work for the sample2. It gives wrong result. It also the change the namespace of the price element even though it doesn't have namespace to be replaced.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:param name="old_namespace"/>
<xsl:param name="new_namespace"/>
<xsl:template match="/">
<xsl:apply-templates select="#* | node()"/>
</xsl:template>
<xsl:template match="text() | comment() | processing-instruction()">
<xsl:copy>
<xsl:apply-templates select="text() | comment() | processing-instruction()"/>
</xsl:copy>
</xsl:template>
<!-- Template used to copy elements -->
<xsl:template match="*">
<xsl:variable name="name">
<xsl:choose>
<xsl:when test="contains(name(), ':')">
<xsl:value-of select="name()"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="local-name()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{$name}" namespace="{$new_namespace}">
<!-- Copy all namespace through except for namespace to be changed -->
<xsl:for-each select="namespace::*">
<xsl:if test="string(.)!=$old_namespace">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Note: My first answer was wrong because in XSLT 1.0, you can't use variable references within a match pattern.
This style-sheet will take either Sample1 or Sample2 as input document and replace all occurrences of the old namespace, from the element names, with the new namespace. Note: you can change the xsl:variable for xsl:param.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="old_namespace" select="'http://testlibrary'" />
<xsl:variable name="new_namespace" select="'http://newlibrary'" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test="namespace-uri()=$old_namespace">
<xsl:element name="{local-name()}" namespace="{$new_namespace}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Caveat
The above style-sheet will only change the namespace of the elements. It will not change the namespaces of attributes, nor will it remove extraneous namespaces nodes.
On a more specific solution
It is very unusual to require a general solution for an operation on a variable namespace. Namespaces, being what they are tend to be fixed and known. Consider carefully, if you really need a generalized solution. If you need a specific solution, meaning replacing occurrences of a specific namespace, then things get a lot easier, such as with this style-sheet...
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:old="http://testlibrary"
xmlns:new="http://newlibrary">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="old:*">
<xsl:element name="{local-name()}" namespace="http://newlibrary">
<xsl:apply-templates select="#*|node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
UPDATE
I just noticed Dimitre's solution to a very similar question here.

XSL Transformation - Insert Attribute

I'm very much a beginner with xsl transformations
I have some xml that I need to insert an attribute into an element when that attribute doesn't exist..
Using the below xml as an example.
<Order Id="IR1598756" Status="2">
<Details>
<SomeInfo>Sample Data</SomeInfo>
</Details>
<Documents>
<Invoice>
<Date>15-02-2011</Date>
<Time>11:22</Time>
<Employee Id="159">James Morrison</Employee>
</Invoice>
<DeliveryNote>
<Reference>DN1235588</Reference>
<HoldingRef>HR1598785</HoldingRef>
<Date>16-02-2011</Date>
<Time>15:00</Time>
<Employee Id="25">Javi Cortez</Employee>
</DeliveryNote>
</Documents>
</Order>
Desired Output
<Order Id="IR1598756" Status="2">
<Details>
<SomeInfo>Sample Data</SomeInfo>
</Details>
<Documents>
<Invoice Id="DN1235588">
<Date>15-02-2011</Date>
<Time>11:22</Time>
<Employee Id="159">James Morrison</Employee>
</Invoice>
</Documents>
</Order>
The <Invoice> element can have an Id attribute <Invoice Id="IR1564897">
How can I check the following.
Check that the attribute exists
If not then Insert the Value of the <Refernce>DN1235588</Reference> as the Id
If there is no <Reference> Use the Value of the <HoldingRef>HR1598785</HoldingRef>
I was looking at implementing something like the following
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//Order"/>
</xsl:template>
<xsl:template match="Order/Documents/Invoice[not(#Id)]">
<xsl:attribute name="Id">
<xsl:value-of select="//Documents/DeliveryNote/Reference"/>
</xsl:attribute>
</xsl:template>
The above is not outputting the full <Invoice> element.
How can I correct this?
<xsl:if test="Order/Documents/DeliveryNote/Reference">
<xsl:value-of select="//Documents/DeliveryNote/Reference"/>
</xsl:if>
<xsl:if test="Not(Order/Documents/DeliveryNote/Reference)">
<xsl:value-of select="//Documents/DeliveryNote/HoldingRef"/>
</xsl:if>
If either one will always exist will this work to alternate between <Reference> and <HoldingRef>?
With the help of Alex:
The following has worked for me to replace the attribute
<xsl:template match="Order/Documents/Invoice[not(#Id)]">
<Invoice>
<xsl:attribute name="Id">
<xsl:value-of Select="//Documents/DeliveryNote/Reference"/>
</xsl:attribute>
<xsl:apply-templates select="#* | node()"/>
</Invoice>
</xsl:template>
The shortest answer:
<xsl:template match="Invoice[not(#Id)]">
<Invoice Id="{(../DeliveryNote/Reference|
../DeliveryNote/HoldingRef)[1]}">
<xsl:apply-templates select="#* | node()"/>
</Invoice>
</xsl:template>
Give a try:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates select="//Order"/>
</xsl:template>
<!-- Match invoices without ids -->
<!-- [DeliveryNote[Reference or HoldingRef] - defend against empty attributes -->
<xsl:template match="Invoice[not(#id)][DeliveryNote[Reference or HoldingRef]]">
<xsl:copy>
<!-- create an attribute and fetch required data. In case Reference is present then insert reference
otherwise - HoldingRef -->
<xsl:attribute name="Id">
<xsl:value-of select="following-sibling::DeliveryNote[1]/Reference |
following-sibling::DeliveryNote[1]/HoldingRef"/>
</xsl:attribute>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//DeliveryNote"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
As for your questions:
The above is not outputting the full element. How can I correct this?
See my example.
If either one will always exist will this work to alternate between <Reference> and <HoldingRef>?
Either with XPath (as in my example) or with xsl:choose.
What about this?
<xsl:template match="Invoice[not(#Id)]">
<xsl:element name="Invoice">
<xsl:attribute name="Id">
<xsl:variable name="REF" select="../DeliveryNote/Reference"/>
<xsl:choose>
<xsl:when test="not($REF)">
<xsl:value-of select="../DeliveryNote/HoldingRef"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="../DeliveryNote/Reference"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
Use it instead your <xsl:template match="Order/Documents/Invoice[not(#Id)]">

XSLT deepening content structure

given the following structure:
<TITEL1>...</TITEL1>
<p>..</p>
<TITEL2>...</TITEL2>
<TITEL3>...</TITEL3>
<TITEL3>...</TITEL3>
<P>...<P>
is there a way to get to this:
<TITEL1>
<TITEL>...</TITEL>
<p>...</p>
<TITEL2>
<TITEL>...</TITEL>
<TITEL3>
<TITEL>...</TITEL>
<P>...</P>
</TITEL3>
<TITEL3>
<TITEL>...</TITEL>
<P>...</P>
</TITEL3>
</TITEL2>
</TITEL1>
or in other words,is there a way to have higher level titels inclose lower level titels and all content that follows them, thus creating a nested structure. The content of each TITEL1,2 and 3 tag should go into a new <TITEL>-element
With XSLT 2.0 (as implemented by Saxon 9 or AltovaXML tools) you can use xsl:for-each-group group-starting-with and a recursive function:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/2010/mf"
exclude-result-prefixes="xsd mf">
<xsl:output indent="yes"/>
<xsl:function name="mf:nest" as="element()*">
<xsl:param name="elements" as="element()*"/>
<xsl:param name="level" as="xsd:integer"/>
<xsl:for-each-group select="$elements" group-starting-with="*[starts-with(local-name(), concat('TITEL', $level))]">
<xsl:choose>
<xsl:when test="self::*[starts-with(local-name(), concat('TITEL', $level))]">
<xsl:element name="TITEL{$level}">
<xsl:apply-templates select="."/>
<xsl:sequence select="mf:nest(current-group() except ., $level + 1)"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="ROOT">
<xsl:sequence select="mf:nest(*, 1)"/>
</xsl:template>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(local-name(), 'TITEL')]">
<TITEL>
<xsl:apply-templates select="#* | node()"/>
</TITEL>
</xsl:template>
</xsl:stylesheet>
With that stylesheet the input
<ROOT>
<TITEL1>Titel 1, 1</TITEL1>
<p>..</p>
<TITEL2>Titel 2, 1</TITEL2>
<TITEL3>Titel 3, 1</TITEL3>
<TITEL3>Titel 3, 2</TITEL3>
<P>...</P>
</ROOT>
is transformed to the output
<TITEL1>
<TITEL>Titel 1, 1</TITEL>
<p>..</p>
<TITEL2>
<TITEL>Titel 2, 1</TITEL>
<TITEL3>
<TITEL>Titel 3, 1</TITEL>
</TITEL3>
<TITEL3>
<TITEL>Titel 3, 2</TITEL>
<P>...</P>
</TITEL3>
</TITEL2>
</TITEL1>
There isn't a particularly eligant way of doing what you want. It's (probably) possible, but it would involve some pretty ugly (and slow) XPath queries using the following-sibling axis with filters on the preceding-sibling axis matching back to the current node.
If it's at all a possibility, I would recommend creating the hierarchy outside of XSLT (in C#, Java, etc)
If you choose to go down the scary path, you would be looking to do something like this (untested):
<xsl:template match="TITEL1">
<TITEL1>
<xsl:apply-templates
select="following-sibling::(p|TITEL2)[(preceding-sibling::TITEL1)[1]=.]" />
</TITEL1>
</xsl:template>
<xsl:template match="TITEL2">
<TITEL1>
<xsl:apply-templates
select="following-sibling::(p|TITEL3)[(preceding-sibling::TITEL2)[1]=.]" />
</TITEL1>
</xsl:template>
...
This is only an example, and I can already see problems with the match. Coming up with the final XPath query would be quite involved, if it's actually possible at all.
If you can't use XSLT 2.0, here is an XSLT 1.0 stylesheet that should produce the same result as the XSLT 2.0 stylesheet I posted earlier:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="ROOT">
<xsl:apply-templates select="*[1]" mode="nest">
<xsl:with-param name="level" select="1"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*[starts-with(local-name(), 'TITEL')]" mode="nest">
<xsl:param name="level"/>
<xsl:choose>
<xsl:when test="$level = substring-after(local-name(), 'TITEL')">
<xsl:element name="TITEL{$level}">
<xsl:apply-templates select="."/>
<xsl:apply-templates select="following-sibling::*[1][not(starts-with(local-name(), concat('TITEL', $level)))]" mode="nest">
<xsl:with-param name="level" select="$level"/>
</xsl:apply-templates>
</xsl:element>
<xsl:apply-templates select="following-sibling::*[starts-with(local-name(), concat('TITEL', $level))][1]" mode="nest">
<xsl:with-param name="level" select="$level"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="nest">
<xsl:with-param name="level" select="$level + 1"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*[not(starts-with(local-name(), 'TITEL'))]" mode="nest">
<xsl:param name="level"/>
<xsl:apply-templates select="."/>
<xsl:apply-templates select="following-sibling::*[1][not(starts-with(local-name(), concat('TITEL', $level)))]" mode="nest">
<xsl:with-param name="level" select="$level"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(local-name(), 'TITEL')]">
<TITEL>
<xsl:apply-templates select="#* | node()"/>
</TITEL>
</xsl:template>
</xsl:stylesheet>