Reputation: 145
I need to adjust below xslt code to wrap the elements that are adjacent to any p whose name attributes include "level_" as a child to the preceding p, which gets transformed to li tags in the output xml.
Here is the source xml:
<root>
<header>Header text</header>
<p name="paragraph">Normal Paragraph</p>
<p name="level_1">Value 1</p>
<p name="level_1">Value 2 table</p>
<table frame="all" rowsep="1" colsep="1"
id="table_whs_jmk_hzb">
<title>table1</title>
<tgroup cols="2" align="center">
<colspec colname="c1" colnum="1" colwidth="1*"/>
<colspec colname="c2" colnum="2" colwidth="1*"/>
<thead>
<row>
<entry>Header 1</entry>
<entry>Header 2</entry>
</row>
</thead>
<tbody>
<row>
<entry>Testing cell 1 text</entry>
<entry>Testing cell 2</entry>
</row>
</tbody>
</tgroup>
</table>
<p name="level_2">Value 3</p>
<p name="level_2">Value 4</p>
<p name="level_1">Value 5 note</p>
<note>Another element</note>
<p name="level_1">Another Value 1</p>
<p name="level_2">Another Value 2</p>
<p name="level_2">Another Value 3 reference</p>
<reference>Some reference text</reference>
<p name="level_3">Another Value 4</p>
<p name="level_3">Another Value 5 example</p>
<example>Example text goes here</example>
<p name="level_4">Another Value 3 image</p>
<image src="./output/media/img(1).jpg"/>
<p name="level_4">Another Value 4</p>
<p name="level_1">Another Value 5</p>
<p name="level_1">Another Value 6</p>
</root>
And the desired output should look like:
<root>
<header>Header text</header>
<p name="paragraph">Normal Paragraph</p>
<ol outputclass="ol-level_1 ">
<li outputclass="li-level_1 ">Value 1</li>
<li outputclass="li-level_1 ">Value 2 table <table frame="all"
rowsep="1" colsep="1"
id="table_whs_jmk_hzb">
<title>table1</title>
<tgroup cols="2" align="center">
<colspec colname="c1" colnum="1" colwidth="1*"/>
<colspec colname="c2" colnum="2" colwidth="1*"/>
<thead>
<row>
<entry>Header 1</entry>
<entry>Header 2</entry>
</row>
</thead>
<tbody>
<row>
<entry>Testing cell 1 text</entry>
<entry>Testing cell 2</entry>
</row>
</tbody>
</tgroup>
</table>
<ol outputclass="ol-level-2 ">
<li outputclass="li-level_2 ">Value 3</li>
<li outputclass="li-level_2 ">Value 4</li>
</ol>
</li>
<li outputclass="li-level_1 ">Value 5 note <note>Another
element</note>
</li>
<li outputclass="li-level_1 ">Another Value 1
<ol outputclass="ol-level-2 ">
<li outputclass="li-level_2 ">Another Value 2</li>
<li outputclass="li-level_2 ">Another Value 3 reference
<reference>Some reference text</reference>
<ol outputclass="ol-level-3 ">
<li outputclass="li-level_3 ">Another Value 4</li>
<li outputclass="li-level_3 ">Another Value 5 example
<example>Example text goes here</example>
<ol outputclass="ol-level-4 ">
<li outputclass="li-level_4 ">Another Value 3 image
<image src="./output/media/img(1).jpg"/></li>
<li outputclass="li-level_4 ">Another Value 4</li>
</ol></li></ol></li></ol></li>
<li outputclass="li-level_1 ">Another Value 5</li>
<li outputclass="li-level_1 ">Another Value 6</li>
</ol></root>
And here is the xslt provided by @martin-honnen that I would like modified to get the desired output:
<xsl:stylesheet 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="#all" version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="items" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$items" group-starting-with="p[@name = 'level_' || $level]">
<xsl:choose>
<xsl:when test="self::p[@name = 'level_' || $level]">
<li outputclass="li-{@name}">
<xsl:apply-templates/>
<xsl:where-populated>
<ol outputclass="ol-level-{$level + 1}">
<xsl:sequence select="mf:group(tail(current-group()), $level + 1)"/>
</ol>
</xsl:where-populated>
</li>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="mf:group(current-group(), $level + 1)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="root">
<root>
<xsl:copy-of select="header"/>
<xsl:copy-of select="p[@name = 'paragraph']"/>
<ol outputclass="ol-level_1 ">
<xsl:sequence select="mf:group(p[@name = (1 to 6) ! ('level_' || .)], 1)"/>
</ol>
</root>
</xsl:template>
<!-- Templates for note, example, table, and image -->
<xsl:template match="note | example | table | image">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Views: 58
Reputation: 167716
Try this adaption of the solution to your previous question:
<xsl:stylesheet 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="#all"
version="3.0">
<xsl:function name="mf:group" as="node()*">
<xsl:param name="items" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:variable name="first-level-item" select="$items[self::p[@name = 'level_' || $level]][1]"/>
<xsl:variable name="first-level-item-pos" select="index-of($items/generate-id(), generate-id($first-level-item))"/>
<xsl:apply-templates select="$items[empty($first-level-item-pos) or position() lt $first-level-item-pos]"/>
<xsl:if test="$first-level-item">
<ol outputclass="ol-{$first-level-item/@name}">
<xsl:for-each-group select="$items[position() ge $first-level-item-pos]" group-starting-with="p[@name = 'level_' || $level]">
<xsl:choose>
<xsl:when test="self::p[@name = 'level_' || $level]">
<li outputclass="li-{@name}">
<xsl:apply-templates/>
<xsl:sequence select="mf:group(tail(current-group()), $level + 1)"/>
</li>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="mf:group(current-group(), $level + 1)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</ol>
</xsl:if>
</xsl:function>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root">
<xsl:copy>
<xsl:sequence select="mf:group(*, 1)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1