[xsl] transforming flat structure with xsl 2.0 grouping

Subject: [xsl] transforming flat structure with xsl 2.0 grouping
From: Charlie 0 <charlieo0@xxxxxxxxxxx>
Date: Sun, 19 May 2013 17:56:20 -0400
I have an extremely flat structure exported from Framemaker (not structured). The elements are created from style names and the structure is completely flat. Just about everything is a sibling of everything else.

I am transforming this flat structure to a proprietary content model (DTD). The entire project consists of a lot of group. Most of which I have a handle on. However there is aspect I could use some help with.

I have an XML input structure that something like this:

<XML>
<Warning>
</Warning>
<Graphic>
    <IMAGE  href="icon-30.gif"/>
</Graphic>
<WarnHazText>Cleaning solvent </WarnHazText>
<WarnHazText>Wear eye</WarnHazText>
<ProcStep>All weldel.</ProcStep>
<Warning>
</Warning>
<Graphic>
    <IMAGE  href="icon-30.gif"/>
</Graphic>
<WarnHazText>Cleaning solvent </WarnHazText>
<WarnHazText>Wear eye</WarnHazText>
<HazText>CARC </HazText>
<HazText>ALWAYS follow /HazText>
<Note></Note>
<HazText>When using a torch</HazText>
<ProcStep>All weldel.</ProcStep>
</XML>

Or it could look like this:

<XML>
<ProcStep>All weldel.</ProcStep>
<Warning>
</Warning>
<Graphic>
    <IMAGE  href="icon-30.gif"/>
</Graphic>
<WarnHazText>Cleaning solvent </WarnHazText>
<WarnHazText>Wear eye</WarnHazText>
<HazText>CARC </HazText>
<HazText>ALWAYS follow /HazText>
<ProcStep>All weldel.</ProcStep>
</XML>

I have templates for transforming the Warning and Note to the output structure, but my dilemma is how do I exclude the <HazText> elements from the <Warning> the precedes the <Note> when there is one.. I have to use "group-starting-with" because there is no way to know what element will follow the last <HazText> or <WarnHazText> of each Warning grouping.


<xsl:template match="Warning">
<xsl:for-each-group select="following-sibling::HazText|following-sibling::WarnHazText" group-starting-with="Warning">
<warning>
<xsl:apply-templates select="current-group()" mode="WCN"/>
</warning>
</xsl:for-each-group>
</xsl:template>


<xsl:template match="Note">
<xsl:for-each-group select="following-sibling::HazText" group-starting-with="Note">
<note>
<xsl:apply-templates select="current-group()" mode="WCN"/>
</note>
</xsl:for-each-group>
</xsl:template>


<xsl:template match="HazText|WarnHazText" mode="WCN">
    <trim.para>
        <xsl:value-of select="normalize-space(.)"/>
    </trim.para>
</xsl:template>


<xsl:template match="ProcStep">
<step1>
<xsl:choose>
<xsl:when test="preceding-sibling::Warning | preceding-sibling::Caution | preceding-sibling::Note">
<specpara>
<xsl:apply-templates select="preceding-sibling::Warning | preceding-sibling::Caution | preceding-sibling::Note""/>
<para>
<xsl:apply-templates/>
</para>
</specpara>
</xsl:when>
<xsl:otherwise>
<para>
<xsl:apply-templates/>
</para>
</xsl:otherwise>
</xsl:choose>
</step1>
</xsl:template>


Another question that is similar to the first, is within the <ProcStep> how to only apply-templates for the immediately preceding Warning or Notes? It is possible that there can be multiple Warnings (groups) and/or Notes (groups) that immediately precede a given <ProcStep>. There can be multiple <ProcStep> elements and theoretically each of those can have any number of preceding Warning or Notes. And of course, everything is a sibling to everything else.

Current Thread