Hi,
How about this? You repeat over all type attributes, rebuild the ancestor tree
for each of them, and recurse untill the next type attribute. In (pseudo) code
something like this:
<template match="root">
<copy>
<for-each select="//*[(_at_)type]">
<apply-templates select="." mode="build-type" />
</for-each>
</copy>
</template>
<template match="*" mode="build-type">
<type name="{(_at_)type}">
<apply-templates select="." mode="rebuild-tree">
<with-param name="ancestors"
select="ancestor::*[not(self::root)]" />
</apply-templates>
</type>
</template>
<template match="*" mode="rebuild-tree">
<param name="ancestors" />
<choose>
<when test="count($ancestors) > 0">
<element name="{name($ancestors[1])}">
<copy-of select="$ancetors[1]/@*" />
<attribute name="tag-id"><value-of
select="generate-id()"/></attribute>
<apply-templates select="." mode="rebuild-tree">
<parameter name="ancestors"
select="$ancestors[position() > 1]" />
</apply-templates>
</element>
</when>
<otherwise>
<copy>
<copy-of select="@*" />
<attribute name="tag-id"><value-of
select="generate-id()"/></attribute>
<apply-templates select="*" mode="recurse" />
</copy>
</otherwise>
</choose>
</template>
<template match="*[(_at_)type]" mode="recurse">
<!-- terminate recursion when next @type is discovered -->
</template>
<template match="*" mode="recurse">
<copy>
<copy-of select="@*" />
<attribute name="tag-id"><value-of
select="generate-id()"/></attribute>
<apply-templates select="*" mode="recurse" />
</copy>
</template>
Note: this DOES require that all important content parts are wrapped in
elements with a type attribute, otherwise those will get lost..
Kind regards,
Geert
Drs. G.P.H. Josten
Consultant
Daidalos BV
Source of Innovation
Hoekeindsehof 1-4
2665 JZ Bleiswijk
Tel.: +31 (0) 10 850 1200
Fax: +31 (0) 10 850 1199
www.daidalos.nl
KvK 27164984
De informatie - verzonden in of met dit emailbericht - is afkomstig van
Daidalos BV en is uitsluitend bestemd voor de geadresseerde. Indien u dit
bericht onbedoeld hebt ontvangen, verzoeken wij u het te verwijderen. Aan dit
bericht kunnen geen rechten worden ontleend.
From: Owens, Stephen P
[mailto:Stephen(_dot_)P(_dot_)Owens(_at_)pfizer(_dot_)com]
Sent: woensdag 5 september 2007 20:54
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Cc: Parnell, Ryan A
Subject: [xsl] Brain Teaser
I have a problem in XSLT that I simply do not know how to solve.
Perhaps someone smarter than me can show their stuff.
Suppose you have a document such as the following:
<root>
<section type="foo">
<a>Text 1</a>
<a type="bar">Mixed Content
<b type="foo">Text 2</b>
<b>Mixed Content
<c>Text 3</c>
<c type="bar">Text 4</c>
</b>
</a>
</section>
</root>
The root tag can contain any number of section type tags.
Section and single letter tags a-z support the type attribute
which can be any string value.
Further suppose that the schema allows section tags to
contain any single letter tag a-z. Also any single letter tag
a-z may contain any combination and number of single letter
tags a-z. All single letter tags support mixed content as well.
How is it possible using XSLT to convert the document to one
such as the following.
<root>
<type name="foo">
<section type="foo" tag-id="001">
<a tag-id="002">Text 1</a>
</section>
</type>
<type name="bar">
<section tag-cont="001">
<a tag-cont="002">
<b tag-id="003">Text 2</b>
<b tag-id="004">Mixed Content
<c>Text 3</c>
</b>
</a>
</section>
</type>
<type name="foo">
<section tag-cont="001">
<a tag-cont="002">
<b tag-cont="004">
<c tag-id="005">Text 4</c>
</b>
</a>
</section>
</type>
</root>
The idea is that wherever a tag appears with a type attribute
in the source document, that tag and the tags that follow
appear in a well formed structure wrapped by a "type" tag in
the target document, thus whenever a new type attribute is
encountered on a tag, we close everything up to a
pre-determined certain stopping point somewhere before the
top such as the child of root in this case, and then we
re-open duplicates of everything, and continue on with the processing.
Examining the above source and target example should give you
a clearer idea. Also, for anything we re-open from the
previous we tie to the previous as a continuation by adding
an tag-id attribute to the original tag, and a tag-cont
attribute to the subsequent continuation.
I think it is fairly trivial to write a transform that goes
from the latter to the former, but I can think of no way to
go from the former to the latter.
For those of you thinking this is a trivial exercise consider
the real world application of translating DocBook XML or
similar schemas into XSL-FO.
Anyone out there up for a challenge?
----------------------------------------------------------------------
LEGAL NOTICE
Unless expressly stated otherwise, this message is
confidential and may be privileged. It is intended for the
addressee(s) only. Access to this E-mail by anyone else is
unauthorized. If you are not an addressee, any disclosure or
copying of the contents of this E-mail or any action taken
(or not taken) in reliance on it is unauthorized and may be
unlawful. If you are not an addressee, please inform the
sender immediately.
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail:
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--