xslt not working as expected, match variable

233 views Asked by At

I'm working on an xslt for processing fix messages (I've already been assisted with this a bit.) I'm trying to retain all fields that have been referred to in various ways. My XSLT is not managing to do this though and I'm finding it very hard to work out why. I've a cut down xslt that retains the field I'm after, but the full xslt does not. This could be due to my lack of understanding around how variables work but I'm not sure. I'm not an xslt programmer so am finding this quite hard.

Sample xml file

<fix>
<messages>
    <message name="TheReport" >
        <component name="OuterComp" required="N" />
    </message>
</messages>
<components>
    <component name="OuterComp">
        <field name="AppID" required="N" />
        <component name="InnerComp" required="N" />
    </component>
    <component name="InnerComp">
        <group name="Bah" required="N" >
            <field name="NewField" required="N" />
        </group>
    </component>
</components>
<fields>
    <field number="3" name="AppID" type="STRING" />
    <field number="15" name="Bah" type="STRING" />
    <field number="16" name="NewField" type="STRING" />
</fields>
</fix>

The 'correctly' (as in it manages to retain the bah field) produced xml output

<?xml version="1.0" encoding="UTF-8"?>
<fix>
<messages>
    <message name="TheReport">
        <component name="OuterComp" required="N" />
    </message>
</messages>
<components>
    <component name="OuterComp">
        <field name="AppID" required="N" />
        <component name="InnerComp" required="N" />
    </component>
    <component name="InnerComp">
        <group name="Bah" required="N">
            <field name="NewField" required="N" />
        </group>
    </component>
</components>
<fields>
    <field number="15" name="Bah" type="STRING" />
</fields>
</fix>

The cut down XSLT that does work

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">

<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="mf" match="message/field" use="@name" />
<xsl:key name="cg" match="component/group" use="@name" />
<xsl:key name="cc" match="component/component" use="@name" />
<xsl:key name="mc" match="message/component" use="@name" />


<xsl:template match="@*|node()" name="identity">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

<xsl:template match="fields/field[not(key('mf', @name))]">
    <xsl:variable name="IsUsed">
        <xsl:apply-templates select="key('cg', @name)" mode="IsUsed" />
    </xsl:variable>
    <xsl:if test="$IsUsed != ''">
        <xsl:call-template name="identity" />
    </xsl:if>
</xsl:template>

<xsl:template match="component/group[not(key('mc', ../@name))]" mode="IsUsed">
    <xsl:apply-templates select="key('cc', ../@name)" mode="IsUsed"/>
</xsl:template>

<xsl:template match="component/group[key('mc', ../@name)]" mode="IsUsed">
    <xsl:text>1</xsl:text>
</xsl:template>

<xsl:template match="component/component[not(key('mc', ../@name))]" mode="IsUsed">
    <xsl:apply-templates select="key('mc', ../@name)" mode="IsUsed"/>
</xsl:template>

<xsl:template match="component/component[key('mc', ../@name)]" mode="IsUsed">
    <xsl:text>1</xsl:text>
</xsl:template>

</xsl:stylesheet> 

and the full one that does not

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">

<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="mc" match="message/component" use="@name" />
<xsl:key name="c2" match="group/component" use="@name" />
<xsl:key name="cc" match="component/component" use="@name" />

<xsl:key name="mf" match="message/field" use="@name" />
<xsl:key name="c4" match="group/field" use="@name" />
<xsl:key name="c5" match="group" use="@name" />
<xsl:key name="c7" match="component/field" use="@name" />
<xsl:key name="cg" match="component/group" use="@name" />

<xsl:template match="@*|node()" name="identity">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

<xsl:template match="fields/field[not(key('mf', @name))]">
    <xsl:variable name="IsUsed">

        <xsl:apply-templates select="key('c4', @name)" mode="IsUsed" />
        <xsl:apply-templates select="key('c7', @name)" mode="IsUsed" />
        <xsl:apply-templates select="key('c5', @name)" mode="IsUsed" />
        <xsl:apply-templates select="key('c2', @name)" mode="IsUsed" />
        <xsl:apply-templates select="key('cc', @name)" mode="IsUsed" />
        <xsl:apply-templates select="key('cg', @name)" mode="IsUsed" />
    </xsl:variable>
    <xsl:if test="$IsUsed != ''">
        <xsl:call-template name="identity" />
    </xsl:if>
</xsl:template>

<xsl:template match="group/field[not(key('mc', ../../@name))]" mode="IsUsed">
    <xsl:apply-templates select="key('c2', ../../@name)" mode="IsUsed"/>
    <xsl:apply-templates select="key('cc', ../../@name)" mode="IsUsed"/>
</xsl:template>

<xsl:template match="group/field[key('mc', ../../@name)]" mode="IsUsed">
    <xsl:text>1</xsl:text>
</xsl:template>

<xsl:template match="component/field[not(key('mc', ../@name))]" mode="IsUsed">
    <xsl:apply-templates select="key('c2', ../@name)" mode="IsUsed"/>
</xsl:template>

<xsl:template match="component/field[key('mc', ../@name)]" mode="IsUsed">
    <xsl:text>1</xsl:text>
</xsl:template>

<xsl:template match="component/group[not(key('mc', ../@name))]" mode="IsUsed">
    <xsl:apply-templates select="key('c2', ../@name)" mode="IsUsed"/>
    <xsl:apply-templates select="key('cc', ../@name)" mode="IsUsed"/>
</xsl:template>

<xsl:template match="component/group[key('mc', ../@name)]" mode="IsUsed">
    <xsl:text>1</xsl:text>
</xsl:template>

<!-- <xsl:template match="component[not(key('mc', @name))]" mode="IsUsed">
    <xsl:apply-templates select="key('c2', @name)" mode="IsUsed"/>
</xsl:template>

<xsl:template match="component[key('mc', @name)]" mode="IsUsed">
    <xsl:text>1</xsl:text>
</xsl:template> -->

<xsl:template match="group[not(key('mc', ../@name))]" mode="IsUsed">
    <xsl:apply-templates select="key('c2', ../@name)" mode="IsUsed"/>
</xsl:template>

<xsl:template match="group[key('mc', ../@name)]" mode="IsUsed">
    <xsl:text>1</xsl:text>
</xsl:template>

<xsl:template match="components/component[not(key('mc', @name))]">
    <xsl:variable name="IsUsed">
        <xsl:apply-templates select="key('cc', @name)" mode="IsUsed" />
        <xsl:apply-templates select="key('c2', @name)" mode="IsUsed" />

    </xsl:variable>
    <xsl:if test="$IsUsed != ''">
        <xsl:call-template name="identity" />
    </xsl:if>
</xsl:template>

<xsl:template match="group/component[not(key('mc', ../../@name))]"
    mode="IsUsed">
    <xsl:apply-templates select="key('c2', ../../@name)"
        mode="IsUsed" />
</xsl:template>

<xsl:template match="group/component[key('mc', ../../@name)]"
    mode="IsUsed">
    <xsl:text>1</xsl:text>
</xsl:template>

<xsl:template match="component/component[not(key('mc', ../@name))]"
    mode="IsUsed">
    <!-- used to be cc -->
    <xsl:apply-templates select="key('mc', ../@name)" 
        mode="IsUsed" />
</xsl:template>

<xsl:template match="component/component[key('mc', ../@name)]"
    mode="IsUsed">
    <xsl:text>1</xsl:text>
</xsl:template>

</xsl:stylesheet> 

Could I have some assistance in working out what is going wrong?

Thanks.

1

There are 1 answers

0
Paul Sweatte On

Managed to work out how to use the Eclipse XSLT debugger and sorted this problem. Was taking a route I didn't expect.