Re: [xsl] creating container elements

Subject: Re: [xsl] creating container elements
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Tue, 06 Apr 2004 08:54:15 -0400
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="{@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@xxxxxxxxxxxxxxxxxxxx
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

Current Thread