How to Create XSLT Documents

05 Nov 2001 19:20

1. Take one document and transform it into a document of a similar schema

Start with the identity transform:

<xsl:template>
    <xsl:copy>
        <xsl:apply-templates select="@* | * | comment() | pi() | text()" />
    </xsl:copy>
</xsl:template>

Then I simply add an <xsl:template> for every special case.

For example, to filter out all nodes called Bob and their children, add

<xsl:template match="Bob"/>

To rename Bob to Joe:

<xsl:template match="Bob">
    <Joe>
        <xsl:apply-templates/>
    </Joe>
</xsl:template>


2. Take one document and transform it into a document of a very different
schema

This one is more complex.  I take a sample input document and a sample
output document.

Sample input:
    <Entry>
        <Identification>
            <Name firstname="Joe" surname="Cool/>
            <Id number="000000000123"/>
            <Nationality>Canadian</Nationality>
         </Identification>
        <Employment>
            <Company name="Microsoft"/>
             <Occupation department="facilities">Janitor</Occupation>
        </Employment>
    </Entry>

Sample output:
    <Person>
        <Name>
            <FirstName>Joe</FirstName>
            <LastName>Cool</LastName>
        </Name>
        <Job>Janitor</Job>
    </Person>

I add the defailt behavior templates and put them into my stylesheet

<xsl:template><xsl:apply-templates/></xsl:template>
<xsl:template match="textnode()"><xsl:value-of/></xsl:template>

I create a <xsl:template match="/"> to match the root and put the
sample output document into that template.

<xsl:template match="/">
    <Person>
        <PersonsName>
            <FirstName>Joe</FirstName>
            <LastName>Cool</LastName>
        </PersonsName>
        <Job>Janitor</Job>
    </Person>
</xsl:template>

The I look at the sample input doc and my stylesheet and see how to
go from one to another.  I leave the stuff that doesn't change, and put
the other stuff into an new template, adding an apply-templates call:

<xsl:template match="/">
    <Person>
        <xsl:apply-templates select="/Entry/Identification"/>
        <Job>Janitor</Job>
    </Person>
</xsl:template>

<xsl:template match="Identification">
        <PersonsName>
            <FirstName>Joe</FirstName>
            <LastName>Cool</LastName>
        </PersonsName>

</xsl:template>

Then replace the insides of the new template with xsl:


<xsl:template match="Identification">
        <PersonsName>
            <FirstName><xsl:value-of select="Name/@firstname"/></FirstName>
            <LastName><xsl:value-of select="Name/@surname"/></LastName>
        </PersonsName>

</xsl:template>

and continue the process till the doc is built up:

<xsl:template><xsl:apply-templates/></xsl:template>
<xsl:template match="textnode()"><xsl:value-of/></xsl:template>

<xsl:template match="/">
    <Person>
        <xsl:apply-templates select="/Entry/Identification"/>
        <xsl:apply-templates select="/Entry/Employment/Occupation"/>
    </Person>
</xsl:template>

<xsl:template match="Identification">
        <PersonsName>
            <FirstName><xsl:value-of select="Name/@firstname"/></FirstName>
            <LastName><xsl:value-of select="Name/@surname"/></LastName>
        </PersonsName>

</xsl:template>

<xsl:template match="Occupation">
        <Job><xsl:value-of select="./text()"/></Job>

</xsl:template>