0
votes

I'm attempting to try and wrap all nodes between two processing instructions but it is tricky due to the nature and placement of the PI's:

Sample input data:

<content>
  <p>Para 1 <?start?>changes <i>here</i></p>
  <x>Para 2 <b>changes</b> here <?end?> and continues here</x>
  <y>Para 3 here</y>
  <z>Para <?start?>4 here <i>with more</i> tags</z>
  <a>Para 5 starts here</a>
  <b>Para 6 starts here</b><?end?>
</content>

Desired output:

<content>
  <p>Para 1 <ins>changes <i>here</i></ins></p>
  <x><ins>Para 2 <b>changes</b> here </ins> and continues here</x>
  <y>Para 3 here</y>
  <z>Para <ins>4 here <i>with more</i> tags</ins></z>
  <a><ins>Para 5 starts here</ins></a>
  <b><ins>Para 6 starts here</ins></b>
</content>

For the and pi's I would like to wrap all the nodes between them in a element.

The PI's can also be in part of any element, which adds another wrinkle to this.

The tricky issue here is that the <?start?> and <?end?> pi's can start in one element and end in another element (see elements p and x in sample input), in which case I would need to wrap each element in each own <ins> tag (to create valid xml) and then start again on the next element until it hits the <?end?> pi. Any way to achieve my desired output with XSLT 2.0?

1
Are all PIs children of <p>? - michael.hor257k
@michael.hor257k no they could be a child of any element, let me add that as an edit to my post - Mike J
@michael.hor257k no, it is similar but my input is much more complex than that question - Mike J

1 Answers

0
votes

It is almost same as Wrapping all nodes in between 2 Processing Instructions with XSLT

Just need some modification in code as below

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        
       
    <xsl:output indent="yes" method="xml"/>

    <xsl:template match="/">
        <xsl:variable name="Cleanup">
            <xsl:apply-templates/>
        </xsl:variable>    
        
        <xsl:apply-templates select="$Cleanup" mode="Fixes"/>
    </xsl:template>
    
    <xsl:template match="*[processing-instruction('start')][not(processing-instruction('end'))]">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
            <xsl:processing-instruction name="end"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="*[processing-instruction('end')][not(processing-instruction('start'))][preceding::processing-instruction('start')]">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:processing-instruction name="start"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="*[not(processing-instruction('start'))][preceding-sibling::*[processing-instruction('start')][not(processing-instruction('end'))]][preceding::processing-instruction()[1][self::processing-instruction('start')]]">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:processing-instruction name="start"/>
            <xsl:apply-templates/>
            <xsl:processing-instruction name="end"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="node() | @*" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" mode="#current"/>
        </xsl:copy>
    </xsl:template>
    
    
    <xsl:template match="processing-instruction('start')" mode="Fixes">
        <xsl:variable name="piend"
            select="following-sibling::processing-instruction('end')[1]/generate-id()"/>
        <ins>
            <xsl:copy-of
                select="following-sibling::node()[following-sibling::processing-instruction('end')[generate-id() = $piend]]"
            />
        </ins>
    </xsl:template>
    
    <xsl:template
        match="node()[preceding::processing-instruction()[1][self::processing-instruction('start')]][following::processing-instruction()[1][self::processing-instruction('end')]]" mode="Fixes"> </xsl:template>
    
    <xsl:template match="processing-instruction('end')" mode="Fixes">
        
    </xsl:template>
</xsl:stylesheet>

See Transformation at https://xsltfiddle.liberty-development.net/a9Hk13