Apply a template between two specific nodes in XSLT - xslt

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>

Related

XSLT Grouping's : Add parent to set of elements in child elements

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>

How to sort data numbers with for-each group in XSLT

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

xsl:for-each-group not working as per exception

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

xslt how to fill missing numbers

This is the input xml
<?xml version="1.0" encoding="UTF-8"?>
<record>
<Tubes>
<Tube carousel_pos="1" tube_pos="1">
<TubeID>FLW140000293A0101</TubeID>
<markers>
<marker position="4">MSIGG1-PC55</marker>
<marker position="9">MSIGG1-PB</marker>
<marker position="8">MSIGG1-APCAF750</marker>
<marker position="10">CD45-KO</marker>
</markers>
</Tube>
<Tube carousel_pos="2" tube_pos="2">
<TubeID>FLW140000293A0102</TubeID>
<markers>
<marker position="4">CD3-PC55</marker>
<marker position="9">CD8-PB</marker>
<marker position="8">CD4-APCAF750</marker>
<marker position="10">CD45-KO</marker>
</markers>
</Tube>
</Tubes>
</record>
This is what it should output
<p num="1">Empty</p>
<p num="2">Empty</p>
<p num="3">Empty</p>
<p num="4">CD3-PC55</p>
<p num="5">Empty</p>
<p num="6">Empty</p>
<p num="7">Empty</p>
<p num="8">CD4-APCAF750</p>
<p num="9">CD8-PB</p>
<p num="10">CD45-KO</p>
This is my xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" exclude-result-prefixes="#all"/>
<xsl:template match="/record/Tubes/Tube">
<xsl:for-each select="markers/marker">
<xsl:sort select="#position" data-type="number"/>
<xsl:choose>
<xsl:when test="position() < #position">
<xsl:call-template name="routine">
<xsl:with-param name="PC" select="position()"/>
<xsl:with-param name="PT" select="#position"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template name="routine">
<xsl:param name="PC"/>
<xsl:param name="PT"/>
</xsl:template>
</xsl:stylesheet>
If you are able to use XSLT 2.0, as your current XSLT is showing, you should be able to make use of an incrementing loop, like so
<xsl:for-each select="1 to 10">
First create a variable holding all the marker elements, the get the maximum #position attribute
<xsl:variable name="markers" select="markers/marker" />
<xsl:variable name="max" select="max($markers/#position)" />
Then, you have your xsl:for-each loop like this:
<xsl:for-each select="1 to xs:integer($max)">
To check if the element exists for each position is then quite straight-forward using the previous markers variable
<xsl:variable name="position" select="position()" />
<xsl:choose>
<xsl:when test="$markers[#position = $position]">
Try this XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="#all">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/record/Tubes/Tube">
<xsl:variable name="markers" select="markers/marker" />
<xsl:variable name="max" select="max($markers/#position)" />
<div>
<xsl:for-each select="1 to xs:integer($max)">
<xsl:variable name="position" select="position()" />
<p num="{$position}">
<xsl:choose>
<xsl:when test="$markers[#position = $position]">
<xsl:value-of select="$markers[#position = $position]"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>Empty</xsl:text>
</xsl:otherwise>
</xsl:choose>
</p>
</xsl:for-each>
</div>
</xsl:template>
</xsl:stylesheet>
This produces the following output (This assumed your wanted to do it separately by each tube element:
<div>
<p num="1">Empty</p>
<p num="2">Empty</p>
<p num="3">Empty</p>
<p num="4">MSIGG1-PC55</p>
<p num="5">Empty</p>
<p num="6">Empty</p>
<p num="7">Empty</p>
<p num="8">MSIGG1-APCAF750</p>
<p num="9">MSIGG1-PB</p>
<p num="10">CD45-KO</p>
</div>
<div>
<p num="1">Empty</p>
<p num="2">Empty</p>
<p num="3">Empty</p>
<p num="4">CD3-PC55</p>
<p num="5">Empty</p>
<p num="6">Empty</p>
<p num="7">Empty</p>
<p num="8">CD4-APCAF750</p>
<p num="9">CD8-PB</p>
<p num="10">CD45-KO</p>
</div>

how can I represent nested element of xml with xslt?

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>