At 2004-04-06 13:05 +0100, Rob Exley wrote:
This is the first time I have looked at XSLT in anger and have what I thought
was a simple question.
It turns out your perspective and expectations of XSLT were not consistent
with the system design.
Given an input document containing amongst other things a recurring element I
would like to create a container element in the output document.
Fine ... you add node of the container element to the output tree and place
all of the recurring elements underneath that node. The processor worries
about the pedestrian concerns such as start and end tags, not the
stylesheet writer.
To my mind
this was a case of output an opening container tag prior to the first
occurrent of the recurrent element and a closing tag after the last
occurrence.
If XSLT focused on syntax then that might have been available, but XSLT is
not an angle-bracket processor, it is a node processor. As a stylesheet
writer your obligation is to build a result node tree, not to build result
syntax.
When I first approached this I tried using something such as
<xsl:if test="postion() = 1">
<container>
</xsl:if>
but this complained as it was not valid XML.
It isn't even well-formed ... wouldn't you agree? An XML file cannot have
a start tag without a corresponding end tag, one needs to use an empty tag
for that kind of behaviour.
Upon seeking advice from a colleague it was suggested I use modes to control
the output and output the container element in the template matching the
first element.
That can work, yes.
Given the following test document
<foo>
<bar id="bar-1">
<barfoo id="barfoo-1"/>
</bar>
<bar id="bar-2">
<barfoo id="barfoo-2"/>
</bar>
<bar id="bar-3">
<barfoo id="barfoo-3"/>
</bar>
</foo>
You don't state the criteria by which a container is triggered.
You also don't state your criteria for translating "bar" into "foobar".
Which seems to have spurious <barfoo> elements following the closing
</container> element.
Sounds like all you need to do is ignore <bar> elements when not the first.
From my continued efforts I seem to have this down to
the behaviour when using the mode and I can resolve this be added the mode
attribute to my <barfoo> template match. I am suprised I need this as I would
have thought it would work without this.
But you haven't considered that you've pushed elements at your stylesheet
without providing for their construction of the result tree ... the
built-in template rules are being engaged since you did nothing about these
nodes, and those template rules are contributing to the construction of the
result.
I would appreciate any help anyone can give regarding this. How should
this be
done
Add a template rule that says "add nothing to the tree for this node".
and any explanation as to why this occurs.
Because built-in template rules are being engaged and you want to prevent that.
FYI - the following is the required information regarding the xslt engine
I am
using which for this was Xalan-J 2.5.2
<?xml version="1.0" encoding="UTF-8"?>
xmlns:msxsl="http://www.w3.org/TR/WD-xsl">
That information is not consistent with your other evidence as it
references a non-standard preliminary experimental dialect of pre-finalized
XSLT.
I hope the example below helps.
................. Ken
T:\ftemp>type exley.xml
<foo>
<bar id="bar-1">
<barfoo id="barfoo-1"/>
</bar>
<bar id="bar-2">
<barfoo id="barfoo-2"/>
</bar>
<bar id="bar-3">
<barfoo id="barfoo-3"/>
</bar>
</foo>
T:\ftemp>type exley.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xslt" exclude-result-prefixes="xalan">
<xsl:output method="xml" indent="yes" xalan:indent-amount="2" />
<xsl:template match="foo">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="bar[1]">
<container>
<xsl:apply-templates select="../bar" mode="standard"/>
</container>
</xsl:template>
<xsl:template match="bar"/><!--all other bars don't construct result-->
<xsl:template match="bar" mode="standard">
<foobar id="{(_at_)id}">
<xsl:apply-templates />
</foobar>
</xsl:template>
<xsl:template match="barfoo">
<barfoo>
<xsl:value-of select="@id"/>
</barfoo>
</xsl:template>
</xsl:stylesheet>
T:\ftemp>saxon exley.xml exley.xsl
<?xml version="1.0" encoding="utf-8"?>
<foo>
<container>
<foobar id="bar-1">
<barfoo>barfoo-1</barfoo>
</foobar>
<foobar id="bar-2">
<barfoo>barfoo-2</barfoo>
</foobar>
<foobar id="bar-3">
<barfoo>barfoo-3</barfoo>
</foobar>
</container>
</foo>
T:\ftemp>
--
Public courses: Spring 2004 world tour of hands-on XSL instruction
Each week: Monday-Wednesday: XSLT/XPath; Thursday-Friday: XSL-FO
Hong Kong May 17-21; Bremen Germany May 24-28; Helsinki June 14-18
World-wide on-site corporate, govt. & user group XML/XSL training.
G. Ken Holman mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/
Box 266, Kars, Ontario CANADA K0A-2E0 +1(613)489-0999 (F:-0995)
Male Breast Cancer Awareness http://www.CraneSoftwrights.com/s/bc