0

I want to wrap all the appendix elements, but only if the first appendix element's preceding sibling is part.

So if the input is like

<part>
..
..
</part>
<appendix href="..">
</appendix>
<appendix href="..">
</appendix>

Then the output is like

<part>
..
..
</part>
<appendices>
  <appendix href="..">
  </appendix>
  <appendix href="..">
  </appendix>
</appendices>

I'm fairly new to XSLT. So all that I've tried has failed till now. Any help will be much appreciated.

Gaurav Goenka
  • 152
  • 12
  • Please explain whether you can use an XSLT 2.0 processor like Saxon 9 as grouping is easier in XSLT 2.0. You also need to provide more details on the possible input, can there be different type of input documents, one type that has the structure you have shown, others of a different structure that you don't want to transform at all? Or are there more elements in a single input document? – Martin Honnen Jul 14 '15 at 13:22
  • Yes, I'm using XSLT 2.0 with a Saxon processor. There can be two output's. One is the structure shown above and another is one where there is no but instead has a for which no processing need be done. – Gaurav Goenka Jul 14 '15 at 13:30
  • Also, there are much more elements than just these mentioned above. Hence, using `` gives a conflict with another template that starts with `` which is used to lowecase all elements in the file. – Gaurav Goenka Jul 14 '15 at 13:39

1 Answers1

0

With XSLT 2.0 your verbal description translates into

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

   <xsl:output indent="yes"/>

    <xsl:template match="*[appendix]">
        <xsl:copy>
            <xsl:for-each-group select="*" group-adjacent="boolean(self::appendix)">
                <xsl:choose>
                    <xsl:when test="current-grouping-key() and preceding-sibling::*[1][self::part]">
                        <appendices>
                            <xsl:apply-templates select="current-group()"/>
                        </appendices>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:transform>
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Sorry I did not mention this in my question, but there are other templates like `` which conflict with ``. Any workaround for that? – Gaurav Goenka Jul 14 '15 at 13:45
  • If you get a warning about an "ambiguous rule match" then you need to apply a priority for the template you want to have precedence e.g. `...`. – Martin Honnen Jul 14 '15 at 14:27
  • Sorry about this, but this does not seem to work for me. The code seems to be running but I guess one of the few other templates modying the appendix element is messing up. @Martin Honnen – Gaurav Goenka Jul 14 '15 at 17:30
  • Well if you need help integrating the suggested code into other code then edit your question and present the code. – Martin Honnen Jul 14 '15 at 17:42
  • Accepted this as the answer because this code works. Just needed to tweak it a little bit with my requirements for integration. Thanks so much @Martin Honnen – Gaurav Goenka Jul 16 '15 at 11:06