[xsl] More Multi-Document Mambo

Subject: [xsl] More Multi-Document Mambo
From: Larry Garfield <lgarfiel@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 18 Jul 2001 01:44:33 -0500
Thanks again to David for his help.  I'm still a bit curious about how
exactly multi-document trees interact.

Suppose I have a simple XML file, source.xml:

    <title>A source file</title>
            <title>Hello World!</title>
            <para>Some stuff</para>
            <para>More stuff</para>
            <title>Hello Universe!</title>
            <para>Some stuff</para>
            <para>More stuff</para>
            <title>Hello Voices Everywhere!</title>
            <para>Some stuff</para>
            <para>More stuff</para>
                <para>Evil stuff</para>
                    <para>Bad stuff</para>
                    <para>More bad stuff</para>

And I have another file, template.xml:

        <insert:title />
        <insert:body />

(Yes, this is a very simple and stupid example, I just want to
illustrate what I'm trying to do and simplify it conceptually so that I
can wrap my brain around it.)

I want to have an XSLT sheet that transforms source.xml into multiple
output files that are based on the template via insertions.  I'm using a
technique presented in an article on xml.com a while back that someone
posted here (http://www.xml.com/pub/a/2000/07/26/xslt/xsltstyle.html),
combined with engine-specific output redirection to create a separate
file for each <section>.  The XSLT file begins like:

<xsl:stylesheet> <!-- various attributes omitted for the moment for
simplicity -->

<xsl:variable name="sourcefile" select="/" />
<xsl:variable name="template" select="document('template.xml')" />

<xsl:template match ="/">
    <xsl:for-each select="//section">
    <xsl:variable name="sectNum" select="position()" />
    <xsl:variable name="sectFile">sect<xsl:value-of select="position()"
        <redirect:write href="$sectFile">
                <xsl:apply-templates select="$template/html/*">
                    <xsl:with-param name="sectNum"><xsl:value-of
select="$sectNum" /></xsl:with-param>

<xsl:template match ="insert:title">
    <xsl:param name="sectTitle"/>
select="$sourcefile/source/body/section[position()=$sectNum]/title" />

<xsl:template match ="insert:body">
    <xsl:param name="sectTitle"/>
            <!-- Point A -->
select="$sourcefile/source/body/section[position()=$sectNum]" />

<xsl:template match="para">
    <!-- Point B -->
    <p><xsl:apply-templates /></p>

<!-- Identity transformation -->
<xsl:template match="@*|*|text()">
    <xsl:param name="sectTitle"/>
        <xsl:apply-templates select="@*|node()|text()">
            <xsl:with-param name="sectNum"><xsl:value-of
select="$sectNum" /></xsl:with-param>


OK, so far, so good.  Assuming I retyped all of that right (I'm going
from memory of the files I'm working with), when this stylesheet is
applied to the source.xml file, it will loop over each <section> tag and
call the template tree on it for each separate output.  That part is
working.  The identity transformation will pass through the contents of
the template untouched, passing the current section number along, until
it gets to <insert:title />, which will be caught by the other
template.  That template will catch <insert:title /> and should call
back out to the source tree for the value of the title of this section.
However, it is returning NULL when I run it.  That's question number

Question number two involves the evil contents of the <footer> tag in
the original source.xml file.  I do not want the contents of <footer> to
be present in the result files at all.  Normally the default rule would
pass it through without copying it into the result tree (just its
textual content), but here the identity transformation, necessary for
the template file, catches it and passes it through as is.  So my final
output file has bits and pieces of untransformed source hanging around
in it.  In the actual project I'm working on, there are too many such
nodes to have a specific null rule for each one, it would be unfeasible.

Which brings me to generalized question number three, which is, in the
above example, what precisely is happening with the separate trees, and
how can I differentiate between a node that originated in one tree as
opposed to the other?  At <!-- Point A --> above, the ancestor path
would be source/body/section/output/main/insert:body, by my reading.  So
when I call apply-templates, and eventually get to <!-- Point B -->, the
ancestor path would be
source/body/section/output/main/insert:body/section/para.  That means
that when it hits the footer, both of the two root nodes (<source> and
<output>) are in its ancestor path, so I cannot put a test into the
identity transformation to determine which tree it is part of, as they
are now the same tree.  Am I making any sense here? :-)

I suppose what I want to do boils down to having two separate default
templates (one identity, one null) based on which root node a given
element originates from, regardless of the crisscrossed path by which
the processor got there.  Is that even possible?  Is my interpretation
of what is going on correct?

Thanks in advance for any information anyone can provide.

Larry Garfield

Do you have a PalmOS Organizer?  Click here to add me to your address

-- "If at first you don't succeed, skydiving isn't for you." :-)

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

Current Thread