This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Selective output of half a tag?
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
OK, I see. So you want to place multiple <mytag>'s around groups of <foo>'s.
Am I right in assuming that
<parent>
<foo/>
<foo/>
<baz/>
<foo/>
<foo/>
</parent>
Would become:
<parent>
<mytag>
<bar/>
<bar/>
</mytag>
<baz/>
<mytag>
<bar/>
<bar/>
</mytag>
</parent>
In that case, you will need to apply-templates to all the children of
<parent>, but make sure that you only select the first out of any group of
<foo>'s. Then, you can have a template match <foo>, output <mytag>, and then
output <bar/> as a child of <mytag> for itself as well as each sibling <foo>.
The following-sibling axis will help, but the trick is to make sure you only
get the immediate closest sibling and not any <foo>'s that are in other
groups. A recursive template can be used to process each following <foo> one
at a time.
<xsl:template match="parent">
<!-- select all nodes that either
* are not a <foo/>
* are a <foo/> that is the first in its group
-->
<xsl:apply-templates
select="node()[not(self::foo and preceding-sibling::*[1][self::foo])]"/>
</xsl:template>
<xsl:template match="node()">
use your normal templates for elements that aren't <foo/>.
</xsl:template>
<xsl:template match="foo">
<!-- I wasn't clear whether you wanted to output <mytag> around all
<foo/>'s, or just <foo/>'s that are part of a group with one or more other
<foo/>'s. If you want the latter, just remove the <xsl:choose>. -->
<xsl:choose>
<xsl:when test="following-sibling::*[1][self::foo]">
<mytag>
<xsl:call-template name="output-foo-group"/>
</mytag>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="output-foo-group"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="output-foo-group">
<bar>
<xsl:apply-templates/>
</bar>
<xsl:for-each select="following-sibling::*[1][self::foo]">
<!-- the for-each is only used to change the context,
but only one <foo> is selected at a time. the next
output-foo-group will then do the for-each again. -->
<xsl:call-template name="output-foo-group"/>
</xsl:for-each>
</xsl:template>
* this has not been tested at all
HTH
Slight modifications may be required if you have text nodes as children of
<parent> in the source tree, in which case you would have to use 'node()'
instead of '*' when testing the preceding- and following-siblings, node()
also selects text nodes that have nothing but whitespace, which means that
you would also have to do <xsl:strip-space elements="parent"/> at the top of
your stylesheet.
On Tuesday 11 June 2002 05:56, Graham Ashton wrote:
> take a series of <foo/> tags in the
> source, convert them all to <bar/> in the output, and then wrap the
> group of <bar/> up in <mytag/>.
Don't think of it in such procedural terms. Remember that you don't ouptut a
<mytag> and a </mytag> separately, they are part of the same element. You
can only output a <mytag> and then children of the <mytag>. That means that
you have to identify all of the children (or at least the start of the group
of children, as in my example), before you can output the <mytag>.
> So,
>
> <foo/>
> <foo/>
>
> becomes
>
> <mytag>
> <bar/>
> <bar/>
> </mytag>
- --
Peter Davis
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)
iD8DBQE9Bo/JNSZCJx7tYycRAk9rAJ9qlTa2hD+whVB+eHTU5wvhc5v9SgCgjMev
KzhsZoskLGtiiJT+QSdnV1g=
=ilZP
-----END PGP SIGNATURE-----
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list