Re: [xsl] group-starting-with and ending with

Subject: Re: [xsl] group-starting-with and ending with
From: "Imsieke, Gerrit, le-tex gerrit.imsieke@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 6 Mar 2020 07:31:01 -0000
Hi Byomokesh,

What are the rules for grouping?

Adjacent <bb> elements, including text in between, should be grouped in <st>?

What about the other elements, <x>, <cc>, and <dd>, should they also be surrounded by something if they occur multiple times?

I didn't apply your stylesheet yet, but the group-adjacent will probably have no tangible effect since if there are adjacent text(), x, cc, or dd nodes, they will be reproduced. This applies in particular to the text node ', ' between the bb elements. You will see the effect more clearly when you wrap the adjacent groups in an element, for example z:

<xsl:when test="current-grouping-key()">
  <z>
    <xsl:copy-of select="current-group()"/>
  </z>
</xsl:when>

Then suddenly many nodes, including the text between the bb elements, will be wrapped in a <z> element.

If you only want to wrap <bb> and interstitial text, you can use group adjacent="exists(self::bb | self::text()[following-sibling::*[1]/self::bb][preceding-sibling::*[1]/self::bb])", and if current-grouping-key() is true(), you surround the group with <st>, otherwise you reproduce the currrent-group().

Please note that group-adjacent and group-by expect an atomic grouping key. This has been (accidentally?) achieved in your template by using "self::text() or self::x or self::dd or self::cc". The 'or' operator forces each side to be cast to a boolean, which is equivalent to "exists(self::text()) or exists(self::x) or exists(self::dd) or exists(self::cc)". If there is only one or no node supplied to the group-adjacent expression such as "self::bb | self::text()[b&]", it might throw an error when the node is empty. Please note that | (or union) ist not the same as 'or' in that it doesnbt force cast to boolean. Therefore I recommend to wrap the union expression in an exists(), as I did above.
Learning the difference between 'or' and '|' (which is a synonym for 'union') is helpful. And also learning that group-starting-with and group-ending-with expect matching patterns while group-by and group-adjacent expect atomic values is helpful if one wants to know why something works and why not.


Gerrit


On 06.03.2020 07:47, Byomokesh Sahoo sahoo.byomokesh@xxxxxxxxx wrote:
Hi,

Is it any possibilityB to <st> start and end tag in <bb>Test1</bb>, <bb>Test2</bb>.


Here is my XML


<a><x>To</x> Test, <bb>Test1</bb>, <bb>Test2</bb>, <cc>Test3</cc>, <dd>USA</dd></a>

Desired Output

<a><x>To</x> Test, <st><bb>Test1</bb>, <bb>Test2</bb></st>, <cc>Test3</cc>, <dd>USA</dd></a>

XSLT

<xsl:template match="a">
<xsl:element name="{local-name()}">
<xsl:for-each-group select="node()" group-adjacent="self::text() or self::x or self::dd or self::cc">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:copy-of select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:for-each-group select="*" group-starting-with="self::bb">
<st>
<xsl:for-each select="current-group()">
<xsl:copy-of select="current-group()"/>
</xsl:for-each>
<xsl:copy-of select="current-group()"/>
</st>
</xsl:for-each-group>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:element>
</xsl:template>


Thanks



XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/225679> (by email <>)

-- Gerrit Imsieke GeschC$ftsfC<hrer / Managing Director le-tex publishing services GmbH Weissenfelser Str. 84, 04229 Leipzig, Germany Phone +49 341 355356 110, Fax +49 341 355356 510 gerrit.imsieke@xxxxxxxxx, http://www.le-tex.de

Registergericht / Commercial Register: Amtsgericht Leipzig
Registernummer / Registration Number: HRB 24930

GeschC$ftsfC<hrer / Managing Directors:
Gerrit Imsieke, Svea Jelonek, Thomas Schmidt

Current Thread