Reputation: 186
I want to fetch the text in between curly braces and combining the hole text into one element
My XML Input is inside one td, r and t element contains text that text need to be combined in one t element with in one td:
<topic>
<body>
<table>
<tr><td><p id="1"><pPr><pstyle class="normal"/></pPr>
<r><t>{</t></r>
<r><t>Ram</t></r>
<r><t>Ramt}</t></r>
</p></td></tr>
<tr><td><p id="2"><pPr><pstyle class="normal"/></pPr>
<r><t>{Red</t></r>
<r><t>Sham</t></r>
<r><t>}</t></r>
</p></td></tr>
<tr><td><p id="3"><pPr><pstyle class="normal"/></pPr>
<r><t>{Red</t></r>
<r><t>}</t></r>
</p></td></tr>
<tr><td><p id="4"><pPr><pstyle class="normal"/></pPr>
<r><t>{Damn}</t></r>
</p></td></tr>
</table>
</body>
</topic>
XSLT I have used to fetch the curly braces text checked for staring and ending of curly then applied templates:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="r/t">
<xsl:choose>
<xsl:when test="starts-with(t, '{') and ends-with(t, '}')">
<r><t><xsl:apply-templates/></t></r>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:transform>
I am getting the output as only r elements values with out combining and t element also not existing
<topic>
<body>
<table>
<tr><td><p id="1"><pPr>
<pstyle class="normal"></pstyle>
</pPr>
<r>{</r>
<r>Ram</r>
<r>Ramt}</r>
</p></td></tr>
<tr><td><p id="2"><pPr><pstyle class="normal"></pstyle></pPr>
<r>{Red</r>
<r>Sham</r>
<r>}</r>
</p></td></tr>
<tr><td><p id="3"><pPr><pstyle class="normal"></pstyle></pPr>
<r>{Red</r>
<r>}</r>
</p></td></tr>
<tr><td><p id="4"><pPr><pstyle class="normal"></pstyle></pPr>
<r>{Damn}</r>
</p></td></tr>
</table>
</body>
</topic>
Output Needed as combining in element text which is inside r element:
<topic>
<body>
<table>
<tr><td><p id="1"><pPr><pstyle class="normal"/></pPr>
<r><t>{RamRamt}</t></r>
</p></td></tr>
<tr><td><p id="2"><pPr><pstyle class="normal"/></pPr>
<r><t>{RedSham}</t></r>
</p></td></tr>
<tr><td><p id="3"><pPr><pstyle class="normal"/></pPr>
<r><t>{Red}</t></r>
</p></td></tr>
<tr><td><p id="4"><pPr><pstyle class="normal"/></pPr>
<r><t>{Damn}</t></r>
</p></td></tr>
</table>
</body>
</topic>
Please advise
Upvotes: 0
Views: 39
Reputation: 167706
Here is an attempt using for-each-group
:
<xsl:template match="p[r/t]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*" group-adjacent="boolean(self::r[t])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:for-each-group select="current-group()" group-starting-with="r[t[starts-with(., '{')]]">
<xsl:for-each-group select="current-group()" group-ending-with="r[t[ends-with(., '}')]]">
<r><t><xsl:apply-templates select="current-group()/t/text()"/></t></r>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
Assumes the identity transformation is set up as the base transformation step e.g. with <xsl:mode on-no-match="shallow-copy"/>
in XSLT 3 (https://xsltfiddle.liberty-development.net/94AbWB4) or with an equivalent template spelling it out.
The above will not cover all edge cases but you haven't really spelled out whether there can be other content; it should be possible to tune the grouping conditions and/or the inner choose/when
tests to improve the code to handle more variable content.
Upvotes: 1