I have xml like this,
<section>
<p id="ss_main">aa</p>
<p id="ss_chap">bb</p>
<p id="main">cc</p>
<p id="main">dd</p>
<p id="main">ee</p>
<p id="ss_main">ff</p>
<p id="main">gg</p>
<p id="main">hh</p>
<p id="main">ii</p>
<p id="main">jj</p>
<p id="ss_chap">xx</p>
<p id="ss_main">yy</p>
<p id="ss_chap">zz</p>
</section>
what my requirement is place new nodes named <ss_start>
and <ss_end>
by covering existing nodes witch are start with ss
.
so the output should be,
<section>
<ss_start/>
<p id="ss_main">aa</p>
<p id="ss_chap">bb</p>
<ss_end/>
<p id="main">cc</p>
<p id="main">dd</p>
<p id="main">ee</p>
<ss_start/>
<p id="ss_main">ff</p>
<ss_end/>
<p id="main">gg</p>
<p id="main">hh</p>
<p id="main">ii</p>
<p id="main">jj</p>
<ss_start/>
<p id="ss_chap">xx</p>
<p id="ss_main">yy</p>
<p id="ss_chap">zz</p>
<ss_end/>
</section>
I can write xsl like follows to cover specific node by <ss_start>
and <ss_end>
<xsl:template match="p[@id='ss_main']">
<ss_start/>
<p id="ss_main"><xsl:apply-templates/></p>
<ss_end/>
</xsl:template>
but I'm struggling to find consecutive nodes that id attr starting from ss
and cover them by <ss_start>
and <ss_end>
.
Can anyone suggest me a method how can I do this?
You could also use ...
XSLT 1.0 sibling recursion
In XSLT 1.0 you can do this as follows, which uses a technique called sibling recursion (though sibling traversal is probably a better term).
Which, when run against your input, will create this output:
I see now that you tagged your question with xslt-2.0, which means you can use grouping. I'll try to update with an example in XSLT 2.0.
XSLT 2.0 group-adjacent
In XSLT 2.0, you can use a boolean true/false as the the group-adjacent grouping key as follows, which is quite a bit shorter than the XSLT 1.0 code above: