473,396 Members | 2,033 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

How to create sections from a linear structure with title nodes?

Hi there,

Maybe this is a faq, if so, point me the URL please.

I have to do some xml to xml transformations in xslt, where I have -
simplified - the following:

input:
<doc>
<a/><a/><b/><a><a><a><b/><a><b/><a><a>
</doc>

output:
<doc>
<section><x/><x/></section>
<section><y/><x/><x/><x/></section>
<section><y/><x/></section>
<section><y/><x/><x/>
</doc>

e.g. I want to transform <a/> to <x/> and <b/> to <y/>, but start a
new section at each <b/>

For Example, you could think of a Text with headlines and paragraphs
and I want to start a new Page at each Headline.

Now there is the question, how to do this in xslt. Some Idea was the
following:

<section>
<xsl:apply-templates select="All a-nodes before the first b-node"/>
</section>
<xsl:for-each select="b">
<section>
<xsl:apply-templates select="b"/>
<xsl:apply-templates select="all following a-nodes up to the next
b-node"/>
</section>
</xsl:for-each>

My Problem are now the two xpath-Expressions "All a-nodes before the
first b-node" and "all following a-nodes up to the next b". Googling
around I did not find any useful tips on this, so perhaps someone here
has an Idea?

MfG,

--
Erhard Schwenk
Jul 20 '05 #1
3 1952
Erhard

you're going about the problem the wrong way. your XML is essentially
document-oriented rather than strongly structured so you should process it
by matching templates. something like:

<xsl:template match="a">
<x><xsl:apply-templates/></x>
</xsl:template>

<xsl:template match="b">
<section><y><xsl:apply-templates/></y></section>
</xsl:template>

don't think of XSL as a programming language - it's a declarative way of
specifying how you want the XML transformed. I suggest you read a good book
like Jeni Tennison's 'beginning xslt' which will explain it all in a
sensible order and show you the various techniques.

Andy

"Erhard Schwenk" <es******@fto.de> wrote in message
news:ed**************************@posting.google.c om...
Hi there,

Maybe this is a faq, if so, point me the URL please.

I have to do some xml to xml transformations in xslt, where I have -
simplified - the following:

input:
<doc>
<a/><a/><b/><a><a><a><b/><a><b/><a><a>
</doc>

output:
<doc>
<section><x/><x/></section>
<section><y/><x/><x/><x/></section>
<section><y/><x/></section>
<section><y/><x/><x/>
</doc>

e.g. I want to transform <a/> to <x/> and <b/> to <y/>, but start a
new section at each <b/>

For Example, you could think of a Text with headlines and paragraphs
and I want to start a new Page at each Headline.

Now there is the question, how to do this in xslt. Some Idea was the
following:

<section>
<xsl:apply-templates select="All a-nodes before the first b-node"/>
</section>
<xsl:for-each select="b">
<section>
<xsl:apply-templates select="b"/>
<xsl:apply-templates select="all following a-nodes up to the next
b-node"/>
</section>
</xsl:for-each>

My Problem are now the two xpath-Expressions "All a-nodes before the
first b-node" and "all following a-nodes up to the next b". Googling
around I did not find any useful tips on this, so perhaps someone here
has an Idea?

MfG,

--
Erhard Schwenk

Jul 20 '05 #2
Andy Fish wrote:

The problem is that 'context' that you need to use to generate the sections
depends on nodes that have already been processed, not on ancestor nodes of
your current node. If you were to write this program in a 'proper'
programming language you would basically have a state machine with a
variable saying whether you are already in a section or not, and this is
exactly what XSL (being a functional language) is bad at.

I think you might be able to do something with following-sibling and
preceding-sibling but I've racked my brains and I can't figure out how you'd
apply it

Hmm meanwhile I got some solution like this:

<xsl:template match="/">
<section>
<xsl:apply-templates
select="*[(count(preceding-sibling::a)) = 0 and name != 'a']"/>
</section>

<xsl:for-each select="a">
<xsl:variable name="number" select="1+count(preceding-sibling::a"/>

<section>
<x/>
<xsl:apply-templates
select="../*[count(preceding-sibling::a) = $number
and name != 'a'"
/>
</section>
</xsl:for-each>
</xsl:template>

<xsl:template match="b">
<y/>
</xsl:template>
Seems to work, maybe there is something better. Thanks for your hints
anyway.

BTW: if there is someone who maintains a faq with XSL Snippets, I think
this one would be a great addition. Feel free to copy.


--
Erhard Schwenk

Akkordeonjugend Baden-Württemberg - http://www.akkordeonjugend.de
K-ITX Webhosting - http://webhosting.k-itx.net

Jul 20 '05 #3
In article <ed**************************@posting.google.com >,
Erhard Schwenk <es******@fto.de> wrote:
Maybe this is a faq, if so, point me the URL please.
It's certainly very similar to the question posted here by Marc
Baumgartner (mo***@gmx.de) in June.
input:
<doc>
<a/><a/><b/><a><a><a><b/><a><b/><a><a>
</doc>

output:
<doc>
<section><x/><x/></section>
<section><y/><x/><x/><x/></section>
<section><y/><x/></section>
<section><y/><x/><x/>
</doc>

e.g. I want to transform <a/> to <x/> and <b/> to <y/>, but start a
new section at each <b/>


Here's a general approach to this kind of problem.

Construct an XPath that will identify one member of each group. In
this case, the first <a> is the obvious thing to choose (if there was
always a <b> in the group, the <b> would be a better choice). We can
identify the first <a> in each group as being an <a> whose immediate
preceding-sibling is not an <a>:

a[local-name(preceding-sibling::*[1]) != 'a']

(If there is an <a> at the start without a preceding b, this will
still work because local-name retrns an exmpty string for an empty
node-set.)

Call apply-templates on that path. Use a mode, for reasons that will
be apparent later:

<xsl:template match="doc">
<doc>
<xsl:apply-templates mode="group"
select="a[local-name(preceding-sibling::*[1]) != 'a']"/>
</doc>
</xsl:template>

In the template for the selected representative, output the group
wrapper.

<xsl:template match="a" mode="group">
<section>
...
</section>
</xsl:template>

Now construct an XPath that will select all the elements in the same
group as the representative.

The XPath to select the group members will use something they have in
common with the representative element. Thinking up a test for this
is often the tricky bit. In this case, we want the <b> before the
representative <a> (if there is one) and the <a>s that are following
siblings of the representative <a> without any intervening <b>s. We
can do it by selecting the siblings that have the same number of
following-sibling <b>s as the representative <a>:

../*[count(following-sibling::b) = count(current()/following-sibling::b)]

Note the use of current() to get hold of the representative <a> inside
the predicate. We could have assigned it to a variable instead, but
this is simpler.

Sometimes the obvious test involves comparing two nodes for identity.
For that you can use the trick generate-id(node1) = generate-id(node2).

Inside the wrapper, call apply-templates on the members of the group.
This is why we used a mode for the group template; we are going to
call apply-templates on the representative again in its role as a
member of the group.

<xsl:template match="a" mode="group">
<section>
<xsl:apply-templates select="../*[count(following-sibling::b) =
count(current()/following-sibling::b)]"/>
</section>
</xsl:template>

Now write templates for the group members, which is trivial in this case.

<xsl:template match="a">
<a/>
</xsl:template>

<xsl:template match="b">
<y/>
</xsl:template>

-- Richard
--
Spam filter: to mail me from a .com/.net site, put my surname in the headers.

FreeBSD rules!
Jul 20 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Wolf | last post by:
Hi to all! With your past help I make a new block in wich you can see last articles I inserted in my phpnuke. You can see it at http://www.italialibri.org, under the title. But I have a problem:...
1
by: Perttu Pulkkinen | last post by:
Hi all freaks! I have been thinking hard, what would be good solution for a straight-forward content management. I want to forget polls and forms etc.. and concentrate first only on different...
8
by: Scott David Daniels | last post by:
I am sorry, but in the Python 2.4 description of "heapify", I find the description of "Transform list x into a heap, in-place, in linear time," unbelievable. I understand the hand-wave that makes...
4
by: Marek Mänd | last post by:
var criterions = { subconds:{ tree: } } // MUSIC , {condID:17, strrep:'Music', subconds:{ tree:
2
by: Jake Barnes | last post by:
Using javascript closures to create singletons to ensure the survival of a reference to an HTML block when removeChild() may remove the last reference to the block and thus destory the block is...
10
by: Simon Brooke | last post by:
Here's my problem: <xsl:template match="/category"> .... <script type="text/javascript"> &lt;!]&gt; </script> .... </xsl:template>
3
by: shapper | last post by:
Hello, I need to add a XML file from an Access database. Could someone tell me what would be the best approach? Thanks, Miguel
4
by: etuncer | last post by:
Hello All, I have Access 2003, and am trying to build a database for my small company. I want to be able to create a word document based on the data entered through a form. the real question is...
3
by: CrazyAtlantaGuy | last post by:
I am working on creating an XSLT that transforms Html into an XML format that can be imported into Framemaker. The challenge, it turns out, is correctly transforming the flat html header tags...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.