Search code examples
xmlxsltxslt-1.0xslt-2.0

How to find a particular 'string' in previous nodes, but within some range of previous nodes not in entire previous nodes


How to find a particular 'string' in previous nodes, but within some range of previous nodes not in entire previous nodes.

For Example 1:
Input:
<p>0Sum of [squares] test1<br/>[Factor1 Section]<b>A<br/>2Sum</b> of <i>(squares) test2 </i> test <br/>[Factor2] <b>(A)</b></p>

Required Output:
If the the scenario is matched, I need to change the <br/> into <p></p>:
<p>0Sum of [squares] test1</p><p>[Factor1 Section]<b>A<br/>2Sum</b> of <i>(squares) test2 </i> test <br/>[Factor2] <b>(A)</b></p>

Example 2:
It should be work within the para not one para to another para. You can see the below example xml, in this case it don't make any changes.
Input:
<p>[A]</b></p><p><br/>[0Sum of squares]</p>

Required Output:
<p>[A]</b></p><p><br/>[0Sum of squares]</p>

in that first I need to find the br[following-sibling::node()[1][matches(.,'^\[')], then need to find - If there is any "]" is present in previous nodes, but that finding range should be till the previous <br/> tag (i.e. one <br/> tag to previous <br/> tag).

Note: I have already make the code for that, here I have given below for your review. But I need better and straight forward code. Can some one help me out!

<xsl:template match="br[(following-sibling::node()[1][matches(normalize-space(.),'^\[')] and preceding-sibling::node()[matches(.,'\]')]>
<xsl:variable name="brcounts" select="count(preceding-sibling::br)"/>
<xsl:if test="$brcounts &gt; 0">
<xsl:choose>
<xsl:when test="(following-sibling::node()[1][matches(normalize-space(.),'^\[')] and preceding-sibling::node()[matches(.,'\]')]) and (preceding-sibling::node()[matches(.,'\]') and count(preceding-sibling::br) = $brcounts])">
</xsl:when>
<xsl:otherwise>
<xsl:copy />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:if test="$brcounts = 0">
<xsl:choose>
<xsl:when test="(following-sibling::node()[1][matches(normalize-space(.),'^\[')] and preceding-sibling::node()[matches(.,'\]')])">
</xsl:when>
<xsl:otherwise>
<xsl:copy />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>

Solution

  • You can try this

    <!-- Identical Transform -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="br[following-sibling::node()[1][matches(., '^\[')]]
        [preceding-sibling::node()[matches(., '\]')]]
        [generate-id(.) = generate-id(preceding-sibling::node()[matches(., '\]')][1]/following::br[1])]">
        <xsl:text disable-output-escaping="yes">&lt;/p>&lt;p></xsl:text>
    </xsl:template>
    

    Output and Script

    http://xsltransform.hikmatu.com/pPgCcom/3