[xsl] Parameterizing an XML using a XSLT

Subject: [xsl] Parameterizing an XML using a XSLT
From: Scott H Snyder <shsnyder@xxxxxxxxxx>
Date: Wed, 9 Apr 2003 09:57:38 -0400



I am relatively new to XSLT so I am still trying to figure out how to move
from a procedural to functional mindset.
I have an XML file that I need to parameterize by replacing certain values
within tags with a placeholder.
This modified XML file will be sent to an external tool that will fill in
values for the placeholder at the appropriate time.

I would like to convert the first xml file below to the second one.  The
placeholders are written in () with a variable name in between.

Source File:
<Document>
    <Header>
        <ID>12345</ID>
    </Header>
    <Body>
        <Status>
            <Command>Test</Command>
            <Reference>11</Reference>
        </Status>
        <Status>
            <Command>Add</Command>
            <Reference>67</Reference>
        </Status>
        <Map>
            <MapItem>
                <Target>
                    <Loc>67</Loc>
                </Target>
            </MapItem>
        </Map>
       <Status>
            <Command>Test</Command>
            <Reference>22</Reference>
        </Status>
        <Status>
            <Command>Add</Command>
            <Reference>89</Reference>
        </Status>
        <Map>
            <MapItem>
                <Target>
                    <Loc>89</Loc>
                </Target>
            </MapItem>
        </Map>
    </Body>
</Document>

Desired Output:
<Document>
    <Header>
        <ID>(id)</ID>
    </Header>
    <Body>
        <Status>
            <Command>Test</Command>
            <Reference>11</Reference>
        </Status>
        <Status>
            <Command>Add</Command>
            <Reference>(ref1)</Reference>
        </Status>
        <Map>
            <MapItem>
                <Target>
                    <Loc>(ref1)</Loc>
                </Target>
            </MapItem>
        </Map>
        <Status>
            <Command>Test</Command>
            <Reference>22</Reference>
        </Status>
        <Status>
            <Command>Add</Command>
            <Reference>(ref2)</Reference>
        </Status>
        <Map>
            <MapItem>
                <Target>
                    <Loc>(ref2)</Loc>
                </Target>
            </MapItem>
        </Map>
    </Body>
</Document>

My XSL file simply copies everything from the source to the output until it
finds a node that matches a place that needs to be paramaterized, and
replaces that tag with the parameter.  But the transform currently falls
short in 2 areas:

1. It can place the placeholder in the //Status/Reference node if it has a
sibling of Command=Add but I cannot figure out a way of adding an index
number to the placeholder that increases sequentially for each match. Both
position() and <xsl:number > do not work with the transform constructed
this way.

2. How can I use the same placeholder in the //Map/MapItem/Target/Loc if
infact the number matches the one in the //Status/Reference tag above it.

If I could create a static counter that only got incremented when the
appropriate node in the file was found it would work but since XSLT does
not allow updating of variables I am not sure how to restructure the
transform to effectively do this.

If anyone has had to do a similar type of transform or has some pointers on
how to restructure the XSL file to do this I would appreciate any insight
you could provide.

Transform:
<?xml version="1.0"  ?>
<xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"; >
<xsl:output method="xml" encoding="iso-8859-1" indent="no"/>

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

        <xsl:template match="//Header/ID">
            <ID><xsl:copy-of select="@*" />(id)</ID>
      </xsl:template>

      <xsl:template match="//Body/Status/Reference">
            <xsl:choose>
                    <xsl:when test="preceding-sibling::Command='Add'">
                          <Reference><xsl:copy-of select="@*"
/>(ref)</Reference>
                  </xsl:when>
                  <xsl:otherwise>
                          <xsl:copy-of select="." />
                  </xsl:otherwise>
            </xsl:choose>
      </xsl:template>

</xsl:stylesheet>


Thanks in advance,

Scott

"The universe is driven by the complex interaction between three
ingredients: matter, energy, and enlightened self-interest."
    - G'Kar, Survivors





 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread