XSLT with following-sibling

P

peter_hanzel

Hello, I'am writing xslt transformation and want to achieve this.
I have this xml:

<Info>
<CtrlUnit>unit1</CtrlUnit>
<Freq>1</Freq>
<Freq>2</Freq>
<CtrlUnit>unit2</CtrlUnit>
<Freq>100</Freq>
</Info>

And I want to translate it to this:

<Info>
<CtrlUnit>unit1<x:br/>1<x:br/>2</CtrlUnit>
<CtrlUnit>unit2<x:br/>100</CtrlUnit>
</Info>

So to select following Freqs but only to next CtrUnit.
How can I achieve this?


I can't use XLST 2.0 with for-each-group. Only XSLT 1.1 is available
 
M

Martin Honnen

Hello, I'am writing xslt transformation and want to achieve this.
I have this xml:

<Info>
<CtrlUnit>unit1</CtrlUnit>
<Freq>1</Freq>
<Freq>2</Freq>
<CtrlUnit>unit2</CtrlUnit>
<Freq>100</Freq>
</Info>

And I want to translate it to this:

<Info>
<CtrlUnit>unit1<x:br/>1<x:br/>2</CtrlUnit>
<CtrlUnit>unit2<x:br/>100</CtrlUnit>
</Info>

So to select following Freqs but only to next CtrUnit.
How can I achieve this?

Here is an XSLT 1.0 example:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://www.w3.org/1999/xhtml" version="1.0">

<xsl:eek:utput method="xml" indent="yes"/>

<xsl:key name="unit-group" match="Freq"
use="generate-id(preceding-sibling::CtrlUnit[1])"/>

<xsl:template match="Info">
<xsl:copy>
<xsl:copy-of select="document('')/*/namespace::x"/>
<xsl:apply-templates select="CtrlUnit"/>
</xsl:copy>
</xsl:template>

<xsl:template match="CtrlUnit">
<xsl:copy>
<xsl:value-of select="."/>
<xsl:apply-templates select="key('unit-group', generate-id())"/>
</xsl:copy>
</xsl:template>

<xsl:template match="Freq">
<x:br/><xsl:value-of select="."/>
</xsl:template>

</xsl:stylesheet>

Result applied to your input XML with Saxon 6.5 is

<Info xmlns:x="http://www.w3.org/1999/xhtml">
<CtrlUnit>unit1<x:br/>1<x:br/>2</CtrlUnit>
<CtrlUnit>unit2<x:br/>100</CtrlUnit>
</Info>
 
P

p.lepin

<Info>
<CtrlUnit>unit1</CtrlUnit>
<Freq>1</Freq>
<Freq>2</Freq>
<CtrlUnit>unit2</CtrlUnit>
<Freq>100</Freq>
</Info>

And I want to translate it to this:

<Info>
<CtrlUnit>unit1<x:br/>1<x:br/>2</CtrlUnit>
<CtrlUnit>unit2<x:br/>100</CtrlUnit>
</Info>

So to select following Freqs but only to next CtrUnit.

First of all, apply your evil-removal tool (I favour
shovels) to whoever designed that XML.

<Info>
<CtrlUnit name="unit1">
<Freq>1</Freq>
<Freq>2</Freq>
</CtrlUnit>
<CtrlUnit name="unit2">
<Freq>100</Freq>
</CtrlUnit>
</Info>

Is way more logical, and you wouldn't have to face your
present problems if it was designed that way from the
start.
How can I achieve this?

However, since it is possible that you have no power over
your source XML's structure, and since grouping problems
are sometimes unavoidable anyway, here's a way to do this:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="ctrl-unit" match="Freq"
use="generate-id(preceding-sibling::CtrlUnit[1])"/>
<xsl:template match="Info">
<xsl:copy>
<xsl:apply-templates select="CtrlUnit"/>
</xsl:copy>
</xsl:template>
<xsl:template match="CtrlUnit">
<xsl:copy>
<xsl:apply-templates/>
<xsl:apply-templates
select="key('ctrl-unit',generate-id(.))"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Freq">
<br/>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>

Google XSL FAQ, it has a lot of highly useful info on
grouping, as well as about a zillion other problems.
 
P

peter_hanzel

Oki thanks a lot. That thing with xsl:key is new for me.

(e-mail address removed) napísal(a):
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,001
Messages
2,570,254
Members
46,851
Latest member
CliftonCor

Latest Threads

Top