Using for-each-group I'm trying to add parent node by the class value of each para element. I tried to apply the grouping but the result is not good, I'm not getting the desired output. I'm confused about using the grouping in this case. Is there any better approach in this case for adding the parent node?
Current XML:
<?xml version="1.0" encoding="utf-8" ?>
<section>
<h1>Some heading</h1>
<section>
<p>normal paragaraph</p>
<p class="list">list 1</p>
<p class="list">list 1</p>
<p>normal paragaraph</p>
<p class="list">list 2</p>
<p class="list">list 2</p>
</section>
<section> ... </section>
</section>
XSLT used:
<xsl:template match="section">
<xsl:for-each-group select="node()" group-by="if (#class='list') then 'list' else 'nolist'">
<xsl:for-each select="current-grouping-key()">
<xsl:choose>
<xsl:when test="current-grouping-key() = 'list'">
<list>
<xsl:apply-templates select="current-group()" />
</list>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each-group>
</xsl:template>
Current Output:
<h1>Some heading</h1>
<p>normal paragaraph</p>
<p>normal paragaraph</p>
<list>
<p class="list">list 1</p>
<p class="list">list 1</p>
<p class="list">list 2</p>
<p class="list">list 2</p>
</list>
<p>normal paragaraph</p>
....
Expected Output:
<section>
<h1>Some heading</h1>
<section>
<p>normal paragaraph</p>
<list>
<p class="list">list 1</p>
<p class="list">list 1</p>
</list>
<p>normal paragaraph</p>
<list>
<p class="list">list 2</p>
<p class="list">list 2</p>
</list>
</section>
<section>...</section>
</section>
<xsl:template match="section">
<section>
<h1>Some Heading</h1>
<section>
<xsl:for-each-group select="section/p" group-by=".">
<xsl:choose>
<xsl:when test="current-grouping-key() != 'normal paragaraph'">
<p>normal paragaraph</p>
<list>
<xsl:for-each select="current-group()">
<p class="list"><xsl:value-of select="current-grouping-key()"/></p>
</xsl:for-each>
</list>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</section>
</section>
</xsl:template>
Here is the answer I hope this helps someone, as commented by #marthin honnen, I tried with group-adjacent, got the desired output, this helped.
<xsl:template match="section">
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="if (#class='list') then 'list' else 'nolist'">
<xsl:for-each select="current-grouping-key()">
<xsl:choose>
<xsl:when test="current-grouping-key() = 'list'">
<list>
<xsl:apply-templates select="current-group()" />
</list>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
Related
How to sort data numbers with xsl:for-each?
Input XML
<root>
<p content-type="Sta_index2"><bold>6000–6243</bold></p>
<p content-type="Sta_index2"><bold>5000–5158</bold></p>
<p content-type="Sta_index2"><bold>6068(e)</bold></p>
<p content-type="Sta_index2"><bold>6148</bold></p>
<p content-type="Sta_index2"><bold>6200–6206</bold></p>
<p content-type="Sta_index2"><bold>6203(b)</bold></p>
<p content-type="Sta_index2"><bold>480</bold></p>
<p content-type="Sta_index2"><bold>6500</bold></p>
<p content-type="Sta_index2"><bold>6450</bold></p>
<p content-type="Sta_index2"><bold>6500–6592</bold></p>
<p content-type="Sta_index2"><bold>6501(f)(1)</bold></p>
<p content-type="Sta_index2"><bold>6533.5</bold></p>
<p content-type="Sta_index2"><bold>10018.15</bold></p>
<p content-type="Sta_index2"><bold>10018.14</bold></p>
</root>
XSLT
<xsl:template match="root">
<xsl:copy>
<xsl:for-each select="p">
<xsl:sort select="number(bold)" data-type="number" order="ascending"/>
<xsl:text>
</xsl:text>
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
Expected Output
<root>
<p content-type="Sta_index2"><bold>480</bold></p>
<p content-type="Sta_index2"><bold>5000–5158</bold></p>
<p content-type="Sta_index2"><bold>6000–6243</bold></p>
<p content-type="Sta_index2"><bold>6068(e)</bold></p>
<p content-type="Sta_index2"><bold>6148</bold></p>
<p content-type="Sta_index2"><bold>6200–6206</bold></p>
<p content-type="Sta_index2"><bold>6203(b)</bold></p>
<p content-type="Sta_index2"><bold>6450</bold></p>
<p content-type="Sta_index2"><bold>6500</bold></p>
<p content-type="Sta_index2"><bold>6500–6592</bold></p>
<p content-type="Sta_index2"><bold>6501(f)(1)</bold></p>
<p content-type="Sta_index2"><bold>6533.5</bold></p>
<p content-type="Sta_index2"><bold>10018.14</bold></p>
<p content-type="Sta_index2"><bold>10018.15</bold></p>
</root>
CODE: https://xsltfiddle.liberty-development.net/3NSTbfj/29
As Sebastien has indicated in a comment, you can try to strip anything after the decimal values you want to use for sorting:
<xsl:template match="root">
<xsl:copy>
<xsl:perform-sort select="p">
<xsl:sort select="bold => replace('[^0-9.].*$', '') => xs:decimal()"/>
</xsl:perform-sort>
</xsl:copy>
</xsl:template>
https://xsltfiddle.liberty-development.net/3NSTbfj/30
I have to transform XML tag out of p as separate div but i am unable to do it:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<p>
This is <bold>First</bold> paragraph
<boxed-text>
<sec>
<title>Boxed title</title>
<p>
<list list-type="bullet">
<list-item>
<p>List first para</p>
</list-item>
</list>
</p>
</sec>
</boxed-text>
This is <bold>Second</bold> paragraph
</p>
</root>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="xhtml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<html>
<head>
<title>Title</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="p">
<xsl:choose>
<xsl:when test="descendant::boxed-text">
<xsl:for-each-group select="node()" group-starting-with="node()">
<xsl:choose>
<xsl:when test="self::boxed-text">
<div class="boxed-text">
<xsl:apply-templates select="current-group()"/>
</div>
</xsl:when>
<xsl:otherwise>
<p class="indent">
<xsl:apply-templates select="current-group()"/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
<p class="indent">
<xsl:apply-templates/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="boxed-text">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="p[table-wrap | list]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="list">
<xsl:choose>
<xsl:when test="#list-type[. = 'bullet']">
<ol style="list-style-type:disc;">
<xsl:apply-templates/>
</ol>
</xsl:when>
<xsl:otherwise>
<ol style="list-style-type:none;">
<xsl:apply-templates/>
</ol>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="list-item">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
</xsl:stylesheet>
Current Output:
<?xml version="1.0" encoding="UTF-8"?><html>
<head>
<title>Title</title>
</head>
<body>
<p class="indent">
This is
</p>
<p class="indent">First</p>
<p class="indent"> paragraph
</p>
<div class="boxed-text">Boxed title
<ol style="list-style-type:disc;">
<li>
<p class="indent">List first para</p>
</li>
</ol>
</div>
<p class="indent">
This is
</p>
<p class="indent">Second</p>
<p class="indent"> paragraph
</p>
</body>
</html>
Excepted output:
<?xml version="1.0" encoding="UTF-8"?><html>
<head>
<title>Title</title>
</head>
<body>
<p class="indent">This is <b>First</b> paragraph</p>
<div class="boxed-text">Boxed title
<ol style="list-style-type:disc;">
<li>
<p class="indent">List first para</p>
</li>
</ol>
</div>
<p class="indent">This is <b>Second</b> paragraph</p>
</body>
</html>
It seems this is rather a job for group-adjacent="boolean(self::boxed-text)":
<xsl:template match="p[descendant::boxed-text]">
<xsl:for-each-group select="node()" group-adjacent="boolean(self::boxed-text)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<p class="indent">
<xsl:apply-templates select="current-group()"/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
Complete adaption is
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="html" indent="no" html-version="5"/>
<xsl:template match="/">
<html>
<head>
<title>.NET XSLT Fiddle Example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="p">
<p class="indent">
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="p[descendant::boxed-text]">
<xsl:for-each-group select="node()" group-adjacent="boolean(self::boxed-text)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<p class="indent">
<xsl:apply-templates select="current-group()"/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="boxed-text">
<div class="boxed-text">
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="p[table-wrap | list]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="list">
<ol style="list-style-type:none;">
<xsl:apply-templates/>
</ol>
</xsl:template>
<xsl:template match="list[#list-type[. = 'bullet']]">
<ol style="list-style-type:disc;">
<xsl:apply-templates/>
</ol>
</xsl:template>
<xsl:template match="list-item">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/6rewNyg
I am fairly new at this and I am not sure if it is possible to do what I want to achieve here. I have 3 for-each loops that stores a number for every chapter, section and paragraph. I want to get that stored number from the previous for-each loop and display it in the nested loop, but I can't get it to work.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title>Table of Contents, Chapter 3</title>
</head>
<body>
<xsl:for-each select="chapter">
<tr>
<xsl:variable name="capnr">
<xsl:number value="3" format="1. "/>
</xsl:variable>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="#title"/>
</tr>
<br />
<xsl:for-each select="section">
<tr>
<xsl:variable name="secnr">
<xsl:number format="1. "/>
</xsl:variable>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="$secnr"/>
<xsl:value-of select="#title"/>
</tr>
<br />
<xsl:for-each select="paragraph">
<tr>
<xsl:variable name="parnr">
<xsl:number format="1 "/>
</xsl:variable>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="$secnr"/>
<xsl:value-of select="$parnr"/>
<xsl:value-of select="#title"/>
</tr>
</xsl:for-each>
<br />
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
XML:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="ToC-3.xsl"?>
<chapter title="Chapter 3: Expressions">
<section title="Variables">
<paragraph title="Simple variables"></paragraph>
<paragraph title="Text variables"></paragraph>
<paragraph title="Remote identifiers"></paragraph>
</section>
<section title="The logical operators">
<paragraph title="Precedence of Boolean operators"></paragraph>
</section>
<section title="Designational expressions">
</section>
</chapter>
Without more details on the input and output, this should work. Of note is that the variable name is on the root, to allow all templates to access it. but since there appears to be one XSl per chapter this shouldn't be a problem.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="capnr">
<xsl:number value="3" format="1."/>
</xsl:variable>
<xsl:template match="/">
<html>
<head>
<title>Table of Contents, Chapter 3</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="chapter">
<h1>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="#title"/>
</h1>
<ol><xsl:apply-templates/></ol>
</xsl:template>
<xsl:template match="section">
<li>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="position()"/>
<xsl:text> - </xsl:text>
<xsl:value-of select="#title"/>
<ol><xsl:apply-templates/></ol>
</li>
</xsl:template>
<xsl:template match="paragraph">
<li>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="count(../preceding-sibling::*) + 1"/>
<xsl:text>.</xsl:text>
<xsl:value-of select="position()"/>
<xsl:text> - </xsl:text>
<xsl:value-of select="#title"/>
<ol><xsl:apply-templates/></ol>
</li>
</xsl:template>
</xsl:stylesheet>
The above when applied to the given input XMl gives:
<html>
<head>
<title>Table of Contents, Chapter 3</title>
</head>
<body>
<h1>3.Chapter 3: Expressions</h1>
<ol><li>3.1 - Variables<ol><li>3.1.1 - Simple variables<ol></ol>
</li>
<li>3.1.2 - Text variables<ol></ol>
</li>
<li>3.1.3 - Remote identifiers<ol></ol>
</li>
</ol>
</li>
<li>3.2 - The logical operators<ol><li>3.2.1 - Precedence of Boolean operators<ol></ol>
</li>
</ol>
</li>
<li>3.3 - Designational expressions<ol></ol>
</li>
</ol>
</body>
</html>
This is the xml data I need to generate xslt from.
<root>
<entry id="1">
<headword>go</headword>
<example>I <hw>go</hw> to school.</example>
</entry>
<entry id="2">
<headword>come</headword>
<example>I <verb>came</verb> back home.</example>
</entry>
I want to create an html like this:
<html>
<body>
<div class="entry" id="1">
<span class="headword">go</span>
<span class="example">I <span class="hw">go</span> to school.</span>
</div>
<div class="entry" id="2">
<span class="headword">comeo</span>
<span class="example">I <span class="hw">came</span> back home.</span>
</div>
</body>
</html>
This is my xslt:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="root/entry">
<div class="entry">
<span class="headword">
<xsl:value-of select="headword"/>
</span>
<span class="example">
<xsl:value-of select="example"/>
</span>
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I don't know how to convert the value of the attribute "id," and the element "hw."
Please give this a try. I'm assuming the second class="hw" in your sample output was a typo and was supposed to be class="verb" since that's the only possibility that makes sense:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="root/entry" />
</body>
</html>
</xsl:template>
<xsl:template match="entry">
<div class="entry" id="{#id}">
<xsl:apply-templates select="*" mode="entryContents" />
</div>
</xsl:template>
<xsl:template match="*" mode="entryContents">
<span class="{local-name()}">
<xsl:apply-templates select="node()" mode="entryContents" />
</span>
</xsl:template>
</xsl:stylesheet>
I had a problem in xsl:for-each-group and it was very nicely solved in here. Now I have some other problem. I have like this as input.
<?xml version="1.0" encoding="UTF-8"?>
<body>
<p name ="section">this is section</p>
<p name="h-title" other="main">Introduction</p>
<p name="h1-title " other="other-h1">XSLT and XQuery</p>
<p name="h2-title" other=" other-h2">XSLT</p>
<p name="">
<p1 name="bold"> XSLT is used to write stylesheets.</p1>
</p>
<p name="h2-title " name="other-h2">XQuery</p>
<p name="">
<p1 name="bold"> XQuery is used to query XML databases.</p1>
</p>
<p name="h3-title" name="other-h3">XQuery and stylesheets</p>
<p name="">
<p1 name="bold"> XQuery is used to query XML databases.</p1>
</p>
<p name ="section">this is section</p>
<p name="h1-title " other="other-h1">XSLT and XQuery</p>
<p name="h2-title " other=" other-h2">XSLT</p>
<p name ="section">this is section</section>
<p name="h1-title " other="other-h1">XSLT and XQuery</p>
<p name="h2-title " other=" other-h2">XSLT</p>
</body>
Now my wanted output is this
<?xml version="1.0" encoding="UTF-8"?>
<body>
<p name="h-title " other="main">Introduction</p>
<section>
<p name ="section">this is section</p>
<h1>
<p name="h1-title " other="other-h1"> XSLT and XQuery </p>
<h2>
<p name="h2-title " other="other-h2">XSLT</p>
<p name="">
<p1 name="bold">XSLT is used to write stylesheets.
</p1>
</p>
</h2>
<h2>
<p name="h2-title " other="other-h2"> XQuery is used to query XMLdatabases
</p>
<p name="">
<p name="bold"> XQuery is used to query XML databases.</p>
</p>
<h3>
<p name="h3-title " name="other-h3">XQuery and stylesheets</p>
<p name="">
<p1 name="bold"> XQuery is used to query XML databases.</p1>
</p>
</h3>
</h2>
</h1>
</section>
<section>
<p name ="section">this is section</p>
<h1>
<p name="h1-title " other="other-h1">XSLT and XQuery</p>
<h2>
<p name="h2"-title other=" other-h2">XSLT</p>
</h2>
</h1>
</section>
<section>
<p name ="section">this is section</p>
<h1>
<p name="h1-title " other="other-h1">XSLT and XQuery</p>
<h2>
<p name="h2"-title other=" other-h2">XSLT</p>
</h2>
</h1>
</section>
</body>
My used stylesheet(not working properly)
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf">
<xsl:param name="prefix" as="xs:string" select="'h'"/>
<xsl:param name="suffix" as="xs:string" select="'-title'"/>
<xsl:output method="html" version="4.0" indent="yes"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="items" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$items" group-starting-with="p[#name = concat($prefix,$level, $suffix)]">
<xsl:choose>
<xsl:when test="not(self::p[#name = concat($prefix, $level, $suffix)])">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="h{$level}">
<xsl:apply-templates select="."/>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body" name ="myTemplate">
<xsl:copy>
<xsl:sequence select="mf:group(*, 1)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body[#name='section']">
<section>
<xsl:call-template name="myTemplate"/>
</section>
</xsl:template>
</xsl:stylesheet>
But this is not correct. Things like <p name ="section">this is section</p> appear widely. not only that, there are few others like this. If someone please show me how to handle with section I will be able to do that for others too. Please tell me how to do this correctly.
ADDED
<body>
<intro>
<p></p>
<p></p>
</intro>
<section>
<para>
</para>
<h1></h2>
<h2></h2>
</section>
<section>
<para>
</para>
<h1></h2>
<h2></h2>
</section>
<sumary>
</summary>
</body>
what I did
<xsl:for-each-group select="*" group-starting-with="p[#name = 'intro']">
<intro>
<xsl:apply-templates select="current()"/>
</intro>
</xsl:for-each-group>
I think you mainly want another grouping step; the stylesheet
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf">
<xsl:param name="prefix" as="xs:string" select="'h'"/>
<xsl:param name="suffix" as="xs:string" select="'-title'"/>
<xsl:output method="html" version="4.0" indent="yes"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="items" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$items" group-starting-with="p[#name = concat($prefix, $level, $suffix)]">
<xsl:choose>
<xsl:when test="not(self::p[#name = concat($prefix, $level, $suffix)])">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="h{$level}">
<xsl:apply-templates select="."/>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="p[#name = 'section']">
<section>
<xsl:sequence select="mf:group(current-group(), 1)"/>
</section>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
transforms the corrected input
<?xml version="1.0" encoding="UTF-8"?>
<body>
<p name ="section">this is section</p>
<p name="h-title" other="main">Introduction</p>
<p name="h1-title" other="other-h1">XSLT and XQuery</p>
<p name="h2-title" other=" other-h2">XSLT</p>
<p name="">
<p1 name="bold"> XSLT is used to write stylesheets.</p1>
</p>
<p name="h2-title" other="other-h2">XQuery</p>
<p name="">
<p1 name="bold"> XQuery is used to query XML databases.</p1>
</p>
<p name="h3-title" other="other-h3">XQuery and stylesheets</p>
<p name="">
<p1 name="bold"> XQuery is used to query XML databases.</p1>
</p>
<p name ="section">this is section</p>
<p name="h1-title" other="other-h1">XSLT and XQuery</p>
<p name="h2-title" other=" other-h2">XSLT</p>
<p name ="section">this is section</p>
<p name="h1-title" other="other-h1">XSLT and XQuery</p>
<p name="h2-title" other=" other-h2">XSLT</p>
</body>
into the result
<body>
<section>
<p name="section">this is section</p>
<p name="h-title" other="main">Introduction</p>
<h1>
<p name="h1-title" other="other-h1">XSLT and XQuery</p>
<h2>
<p name="h2-title" other=" other-h2">XSLT</p>
<p name="">
<p1 name="bold"> XSLT is used to write stylesheets.</p1>
</p>
</h2>
<h2>
<p name="h2-title" other="other-h2">XQuery</p>
<p name="">
<p1 name="bold"> XQuery is used to query XML databases.</p1>
</p>
<h3>
<p name="h3-title" other="other-h3">XQuery and stylesheets</p>
<p name="">
<p1 name="bold"> XQuery is used to query XML databases.</p1>
</p>
</h3>
</h2>
</h1>
</section>
<section>
<p name="section">this is section</p>
<h1>
<p name="h1-title" other="other-h1">XSLT and XQuery</p>
<h2>
<p name="h2-title" other=" other-h2">XSLT</p>
</h2>
</h1>
</section>
<section>
<p name="section">this is section</p>
<h1>
<p name="h1-title" other="other-h1">XSLT and XQuery</p>
<h2>
<p name="h2-title" other=" other-h2">XSLT</p>
</h2>
</h1>
</section>
</body>
That has the structure you posted I think, with the exception of the <p name="h-title" other="main">Introduction</p> element being inside a section while your posted example moved it to the top. I am not sure what are the rules for doing that so I have not tried to implement that. Please clarify whether you simply want to move that single element to the top and not apply the grouping to it or whether there are more complex rules to exempt certain elements.
[edit]In case you simply want to move all p[#name = 't-title'] to the top and not group them then the following adaption of above stylesheet should do the job:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf">
<xsl:param name="prefix" as="xs:string" select="'h'"/>
<xsl:param name="suffix" as="xs:string" select="'-title'"/>
<xsl:output method="html" version="4.0" indent="yes"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="items" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$items" group-starting-with="p[#name = concat($prefix, $level, $suffix)]">
<xsl:choose>
<xsl:when test="not(self::p[#name = concat($prefix, $level, $suffix)])">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="h{$level}">
<xsl:apply-templates select="."/>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body">
<xsl:copy>
<xsl:apply-templates select="p[#name = 'h-title']"/>
<xsl:for-each-group select="* except p[#name = 'h-title']" group-starting-with="p[#name = 'section']">
<section>
<xsl:sequence select="mf:group(current-group(), 1)"/>
</section>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>