Toon posts:

[xml|xslt] groeperen

Pagina: 1
Acties:
  • 204 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Mijn concrete vraag is, hoe transformeer ik met behulp van XSLT de volgende XML:
code:
1
2
3
4
5
<adresboek>
  <contact datum="20010930">Contact 1</contact>
  <contact datum="20011001">Contact 2</contact>
  <contact datum="20011002">Contact 3</contact>
</adresboek>

in zoiets als:
code:
1
2
3
4
5
6
<h1>2001</h1>
<h2>09</h2>
<p>Contact 1</p>
<h2>10</h2>
<p>Contact 2</p>
<p>Contact 3</p>

Tevens, waar vind ik een Reference van XSLT elements enzo. Cursussen en self studies heb ik al gevonden. Bij M$ vind ik allen lange l*lverhalen :r

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Op http://www.zvon.org staat een goede reference.

Op http://www.xfront.com staat een zeer goede tutorial die eenvoudig begint. Als je die doorneemt kan je het bovenstaande zo oplossen :) . Het is denk ik nuttiger voor je om dat te doen dan dat ik een voorbeeld ga geven...

Wat jij wilt is in ieder geval vrij makkelijk mogelijk :)

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ik kan trouwens niet echt een logica ontdekken in jouw transformatie... wat wil je precies voor resultaat bereiken bij dit stukje XML?

edit: oeps domme ik... Ik zie het :) .

Dit komt ik XSLT neer op een goed select attribuut in je apply-templates, maar het is geen heel erg triviaal probleem. Vooral het selecteren van de benodigde jaren en maanden is nog best lastig. Het groeperen is van de contacts is daarna eenvoudig.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Het is ook een optie om de contacts gewoon te sorteren en daarna bij iedere contact te kijken of z'n voorgaande contact een ander jaar of een andere maand had. Indien nodig voeg je dan headings in.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Op dinsdag 16 oktober 2001 22:44 schreef mbravenboer het volgende:
Het is ook een optie om de contacts gewoon te sorteren en daarna bij iedere contact te kijken of z'n voorgaande contact een ander jaar of een andere maand had. Indien nodig voeg je dan headings in.
Maar dat moet toch niet hoeven. Als ik XSLT denk, denk ik funcioneel, geen state. Toch maar even met variabelen proberen :r

Verwijderd

Topicstarter
code:
1
<xsl:value-of select="preceding::element[position()-1]/@datum"/>

Waarom selecteert deze regel niet het datum attribuut van de vorige node? |:(

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ik heb er nog even over na zitten denken en eigenlijk is dit best wel een lastig probleem. Het punt is namelijk dat je in XSLT alleen kan itereren over XML content. Je kunt niet gewoon ff een loopje maken over de jaren, nadat je die geselecteerd hebt. Dat schiet dus niet op :( .
Doekman: Waarom selecteert deze regel niet het datum attribuut van de vorige node? |:(
Nu ik er beter over nadenk gaat die sorteer-check truck helemaal niet werken. Je kan alleen de posities van elementen in de oorspronkelijke XML file gebruiken. Die zijn dus niet gesorteerd.

Ik zie nu eigenlijk maar 1 oplossing (het lijkt me sterk dat het niet anders kan, maar ik zie het niet echt :) ).

Je zou namelijk gewoon de content waarover geitereerd moet worden kunnen opgeven in een apart XML document. Heel ranzig wellicht, maar wel erg makkelijk. De stylesheet is gelijk triviaal.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<jaren>
    <jaar>2000</jaar>
    <jaar>2001</jaar>
    <jaar>2002</jaar>
    <jaar>2003</jaar>
</jaren>

<maanden>
    <maand id="1">
        <naam>Januari</naam>
    </maand>

    <maand id="2">
        <naam>Februari</naam>
    </maand>

    ...
</maanden>

Nu is het probleem veel simpeler :) . Schetsje:
code:
1
2
3
4
5
6
7
apply-templates select=document(bla)/jaren/jaar
als count() van contacts in dit jaar > 0
   -> heading
   -> for-each maand
     als count() van contact in jaar + maand > 0
     -> heading
     -> apply-templates op de bewuste contacts

Zo gaat het dus vrij goed :) .

Ik ben de eerste om toe te geven dat het niet echt netjes is, maar het is wel erg makkelijk vanuit het oogpunt van XSLT. Als er mooiere oplossingen zijn dan laat ik me graag terecht wijzen :) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Otis: Zwarte band XSLT
Heb jij nog een beter idee?

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Rense Klinkenberg
  • Registratie: November 2000
  • Laatst online: 15-09 23:45
kan je niet iets doen met een xsl:sort en die toepassen op substr(@datum, ???????). 'k heb geen idee hoe die functies exact werken, maar http://www.w3c.org/TR/xslt wel.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
freak007 had ook wat ideeen
Ja in die richting denk je natuurlijk snel, maar hoe groepeer je nu de contacts op jaar? Hoe ontdek je de aanwezige jaren en maanden? Ik zie tot nu toe nog steeds geen andere oplossing dan hetgene wat ik al eerdere poste...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
In mijn XML bestand staan de datums al op oplopende volgorde. Als oplossing heb ik zoiets als:
code:
1
2
3
4
for-each element
  if not substring(@datum,1,4) = substring(@datum[vorige],1,4)
    <h2>nieuw jaar kopje</h2>
  /if

Het enige probleem: hoe selecteer ik de datum-attribuut van de vorige element-tag??????? (zie ook hierboven).

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Doekman het volgende:hoe selecteer ik de datum-attribuut van de vorige element-tag?
Als ze al op volgorde staan is er geen enkel punt.... Je kan dan gewoon position() - 1 gebruiken....

Zie deze thread voor allerlei position voorbeelden en hoe je die kan gebruiken om elementen ten opzichte van het huidige element te verkrijgen:

[topic=289102/1/25]

Als het nog niet lukt zal ik wel ff een voorbeeldje bakken...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ik heb maar ff een voorbeeldje gemaakt :)

Ik heb een XML file gemaakt met 'vrienden'. Hierin staat de geboortedatum van deze beste mensen. Daarna haal ik een stylesheet erover die er een verjaardagskalendar in XHTML van maakt (altijd handig voor op de WC ;) ).

Dit is de XML file voor de friends:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0"?>

<friends>
    <friend>
        <name>Kees</name>
        <birthday>
            <month ref="2"/>
            <day-of-month>11</day-of-month>
        </birthday>
    </friend>

    <friend>
        <name>Joep</name>
        <birthday>
            <month ref="2"/>
            <day-of-month>21</day-of-month>
        </birthday>
    </friend>

    <friend>
        <name>Klaas</name>
        <birthday>
            <month ref="4"/>
            <day-of-month>5</day-of-month>
        </birthday>
    </friend>
</friends>

Verder gebruik ik nog een XML file voor de maanden van het jaar, maar die gebruik ik alleen om de naam van een maand in te vullen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0"?>

<months>
    <month id="1">
        <name>Januari</name>
    </month>

    <month id="2">
        <name>Februari</name>
    </month>

    <month id="3">
        <name>Maart</name>
    </month>

    <month id="4">
        <name>April</name>
    </month>

    <month id="5">
        <name>Mei</name>
    </month>
</months>

Uiteindelijk dan de stylesheet, waarin ik position() gebruik om te beoordelen of de vorige vriend in diezelfde maand jarig was.

Dan nu die stylesheet. Er zit nogal wat rommel in, maar ik denk datie wel duidelijk is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0"?>

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

    <xsl:output method="xml" indent="yes"
                doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
                doctype-system="DTD/xhtml1-transitional.dtd"/>

    <xsl:template match="/">
        <html xml:lang="en" lang="en">
            <head>
                <title>Birtday Calendar</title>
            </head>

            <body>
                <h1>Birthday Calendar</h1>

                <xsl:apply-templates/>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="friends">
        <xsl:apply-templates select="friend"/>
    </xsl:template>

    <xsl:template match="friend">
        <xsl:variable name="before" select="position() - 1"/>
        <xsl:variable name="lastmonth"  select="../friend[position() = $before]/birthday/month/@ref"/>

        <xsl:if test="($before &lt; 1) or not($lastmonth = current()/birthday/month/@ref)">
            <h2>
                <xsl:value-of select="document('months.xml')/months/month[@id = current()/birthday/month/@ref]/name/text()"/>
            </h2>
        </xsl:if>

        <xsl:value-of select="birthday/day-of-month"/>
        <xsl:text>: </xsl:text>
        <xsl:value-of select="name"/>
        <br/>
    </xsl:template>

</xsl:stylesheet>

Hoop dat ut helpt, jouw probleem is vrijwel hetzelfde :)

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Oeps... ik vergat het resultaat :)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
    <head>
        <title>Birtday Calendar</title>
    </head>

    <body>
        <h1>Birthday Calendar</h1>

        <h2>Februari</h2>
        11: Kees<br />
        21: Joep<br />

        <h2>April</h2>
        5: Klaas<br />
    </body>
</html>

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Overigens is deze implementatie natuurlijk allerminst prettig.

Ik vind dit wel een interessant probleem, waar eigenlijk toch echt een group constructie voor nodig is. Dit zou welicht op een best wel fraaie manier opgenomen kunnen worden in XSLT....

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Het staat al bij de requirements voor XSLT 2.0 zie ik :)

Zie:
http://www.w3.org/TR/xslt20req

4. Must Simplify Grouping

Het is nogal een belangrijk punt in de requirements, dus we kunnen vast iets goeds verwachten :) . Check the use-cases voor leuke voorbeelden.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Te gek. Het werkt. Je kunt het resultaat bekijken op http://www.xs4all.nl/~zanstra/nrc/index.htm en dan bijtjes-index kiezen.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Mooi :)

Alleen in Mozilla werktie niet ;(
(had overigens mijn voorbeeld ook niet in Mozilla getest).

Ik kan zo helaas niet zien waarom het in Mozilla niet werkt... Zal later nog wel ffies kijken :) .

edit: Hij transformeert dus helemaal niets in Mozilla. Hij pleurt gewoone alleen de tekst tussen de elementen naar...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
edit: Joehoe wat werkt GoT lekker :)

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Het is misschien wel leuk om dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
 <xsl:when test=" 1 = number(substring(@datum,5,2))"> Januari </xsl:when>
<xsl:when test=" 2 = number(substring(@datum,5,2))"> Februari </xsl:when>
<xsl:when test=" 3 = number(substring(@datum,5,2))"> Maart </xsl:when>
<xsl:when test=" 4 = number(substring(@datum,5,2))"> April </xsl:when>
<xsl:when test=" 5 = number(substring(@datum,5,2))"> Mei </xsl:when>
<xsl:when test=" 6 = number(substring(@datum,5,2))"> Juni </xsl:when>
<xsl:when test=" 7 = number(substring(@datum,5,2))"> Juli </xsl:when>
<xsl:when test=" 8 = number(substring(@datum,5,2))"> Augustus </xsl:when>
<xsl:when test=" 9 = number(substring(@datum,5,2))"> September </xsl:when>
<xsl:when test="10 = number(substring(@datum,5,2))"> Oktober </xsl:when>
<xsl:when test="11 = number(substring(@datum,5,2))"> November </xsl:when>
<xsl:when test="12 = number(substring(@datum,5,2))"> December </xsl:when>
<xsl:otherwise>Overig</xsl:otherwise>

ff te doen op de manier zoals ik deed met een aparte file. De code wordt dan een stuk schoner en duidelijker. Je substring staat er nu ook nogal vaak ;)

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Pure focus >:) Ik had dat maand-gebeuren helemaal niet gezien! Werkt mooi, ik heb het er ook in gezet.

Enne, die vele sub-strings. Hoe zou jij dat doen. Met call-template lijkt het me niet handig. Kun je dan zelf functies definieren?

Nog 2 vragen over jou code:
-waarom geen strict xhtml?
-bovenin je document staat encoding="utf-8". Dat bepaald toch het OS (dus webserver). Waarom moet het dan in het xml document staan. En hoe weet je via welke encoding een xml file verzonden wordt?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Doekman: Pure focus >:) Ik had dat maand-gebeuren helemaal niet gezien! Werkt mooi, ik heb het er ook in gezet.
Mooi :) .
Enne, die vele sub-strings. Hoe zou jij dat doen. Met call-template lijkt het me niet handig.
Ik doelde vooral op die maand substring, voor alle 12 gevallen... Als je refereert naar een aparte XML file voor de maand hoef je ook de substring nog maar 1 keer te doen :) . Zie daarvoor het voorbeeldje hierboven. Het komt erop neer dat er geen choose meer nodig is omdat je direct matched op de @id en de @ref.
waarom geen strict xhtml?
Goeie vraag :) . Voor de file waaruit ik dit ff gekopieerd had (ga al dat gebla niet elke keer intikken ;) ) kon ik helaas geen strict gebruiken vanwege de input...
bovenin je document staat encoding="utf-8". Dat bepaald toch het OS (dus webserver). Waarom moet het dan in het xml document staan. En hoe weet je via welke encoding een xml file verzonden wordt?
De encoding mag altijd in een XML document staan. Ook hoeft het niet percee door het OS bepaald te worden.... In principe is dat alleen stuff voor de parser en heb je er zelf vrijwel niets mee te maken.

Ik transformeer zelf met Java via JAXP (en dus Xalan) en die poept standaard UTF-8 uit en geeft dat ook aan... Mij best :) . Elke XML parser zou dat moeten kunnen verwerken.
Encodings zijn eigenlijk alleen echt relevant voor bijzondere talen of bijzondere tekens... Bij normale situaties heb je daar geen last van. Vaak kan je bij het serializeren van een DOM aangeven in welke encoding dit moet gebeuren.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Ik transformeer met m'n browser (IE6). Maar op het werk kon IE5 er niet veel mee. Ik dacht dat we met xml/xsl van dat soort zaken af waren.

Nu maar getransformeerd met MSXSL command-line, en als html versie op webserver gezet. Ik heb even geen zin om versie-verschillen uit te zoeken.

Over encoding: ik kan in m'n editor aangeven of het textbestand unicode/utf-8/plain text is. En dat is handig, want waar transformeren met IE6 goed ging, ging met MSXML command-line fout!! Met de editor als utf-8 saven, en het gaat goed. :P
Pagina: 1