Toon posts:

[xsl/xpath] Preceding-sibling werkt niet met xsl:sort

Pagina: 1
Acties:

Verwijderd

Topicstarter
In mijn XSL pagina loop ik door een XML structuur die een aantal categorieën met daaronder "downloads" bevat. Wat ik wil, is de laatste drie toegevoegde uploads selecteren met hun categorie namen.

Ik zit in een for-each loop door een XML file:

code:
1
2
<xsl:for-each 
    select="//data[@table='categorie']/row/data[@table='downloads']/row">


Om een goede categorie naam weg te schrijven in mijn tabel gebruik ik de "preceding-sibling" in xpath. De naam van de voorgaande categorie heb ik nodig om te kunnen beslissen of ik een "kop" wil gaan schrijven voor mijn tabel... om te voorkomen dat ik voor twee downloads - die onder dezelfde categorie vallen - twee dezelfde koppen schrijf.

code:
1
2
<xsl:variable name="prevcatname" 
    select="../../preceding-sibling::*[naam][1]/naam" />


Als je dit gaat uitleggen zou ik zeggen dat hier het volgende gebeurt:
Ga twee lagen terug om bij de categorieën te komen. Selecteer daarna alle voorgaande siblings waar in ieder geval een naam beschikbaar is. Pak de eerst voorgaande node. Selecteer de naam.

Dit gaat gewoonweg fout. Zodra ik niet door de downloads, maar alleen door de categorieën ga loopen, dan gaat dit wel goed (zonder de ../../ natuurlijk.)
Alleen... dit wil ik niet, ik moet door de downloads loopen om er maximaal drie uit te halen.

Maargoed, dat is van latere zorg dacht ik. Ik ging hierna verder met testen. Ik haalde alle xsl:sorts weg, verwijderde alle code die door de downloads loopten en ik ging loopen door de categorieën, en kreeg nu de goede nodes e.d. terug. Heel fijn. Het werkt dus wel, er is gewoon iets anders verkeerd.

Nu wilde ik de categorieën gaan sorteren op naam.

En hier gaat het helemaal fout. De variabele die ik wil opbouwen houdt zich aan de XML file structuur, NIET aan de structuur die ik heb verkregen danzij de "xsl:sort" functionaliteit.

Heeft iemand een idee om een tabel te maken met XML en XSL gesorteerd op "download" niveau met de categorie namen erboven?

Dus:

code:
1
2
3
4
5
6
CATEGORIE 1
    download 1

CATEGORIE 2
    download 2
    download 3


Wat ik nu voorelkaar krijg is:

code:
1
2
3
4
5
6
7
8
CATEGORIE 1
    download 1

CATEGORIE 2
    download 2

CATEGORIE 2
    download 3


Wat natuurlijk niet logisch overkomt naar de gebruiker...

Het probleem lijkt dus te zijn dat de proceeding-sibling mogelijkheid de originele XML stream gebruikt, ongesorteerd. Zodra ik ga sorteren wordt de volgorde in de loop wel aangepast, maar alle tussenliggende variabelen e.d. trekken zich er niks van aan.

Kan iemand me verder helpen? Dit moet toch verschrikkelijk makkelijk zijn... volgens mij denk ik gewoon verkeerd.

Ik gebruik de laatste MSXML4.0 processor.


Mijn XML voorbeeld:
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
<data table="categorie">
    <row id="1">
        <naam>PSA OPLOSSINGEN</naam>
        <files/>
        <data table="uploads">
            <row id="1">
                <naam>PSA Lorem ipsum dolor sit amet</naam>
                <datumtijd>28-08-2003 16:55:52</datumtijd>
                <omschrijving>Duis vel illum dolore eu feugiat nulla facilisis.</omschrijving>
            </row>
            <row id="2">
                <naam>Dit is nog een test</naam>
                <datumtijd>28-08-2003 17:25:21</datumtijd>
                <omschrijving>Duis vel illum dolore eu feugiat nulla facilisis.</omschrijving>
            </row>
        </data>
    </row>
    <row..
    <row..
    <row..
    <row..
</data>
<data.. 
    <row..

  • Juup
  • Registratie: Februari 2000
  • Niet online
Hahaha. Ik weet wel IETS van XSL maar niet genoeg om hier een nuttig antwoord op te geven. Zijn er hier op GoT meerdere XSL kenners?

Een wappie is iemand die gevallen is voor de (jarenlange) Russische desinformatiecampagnes.
Wantrouwen en confirmation bias doen de rest.


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ik zou m'n transformatie iets anders opzetten: eerst ga je categorien produceren. Per geproduceerde categorie ga je de items opzoeken die je in de categorie moet zetten.

Ik heb even een klein voorbeeld gemaakt. Ik maak hier gebruik van EXSLT. Deze verzameling van standaard uitbreidingen maakt XSLT een stuk prettiger. Veel XSL processoren ondersteunen (een subset van) EXSLT. Je kan om het gebruik van de set functie nog wel heen werken door te controleren of je met een nieuwe categorie bezig gaat. Je hebt dus niet percee EXSLT nodig.

Dit is mijn voorbeeld input:
XML:
1
2
3
4
5
6
7
<data>
  <item category="foo">item 1</item>
  <item category="bar">item 2</item>
  <item category="foo">item 3</item>
  <item category="foo">item 4</item>
  <item category="bar">item 5</item>
</data>


transformatie:
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
<?xml version="1.0"?>
 
<xsl:transform version="1.0"
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:set="http://exslt.org/sets"
  extension-element-prefixes="set">
 
  <xsl:template match="data">
    <html>
       <body>
        <xsl:apply-templates select="set:distinct(item/@category)"/>
      </body>
    </html>
  </xsl:template>
 
  <xsl:template match="@category">
    <h1>    
      <xsl:value-of select="current()"/>
    </h1>
 
    <ul>
      <xsl:apply-templates select="/data/item[@category = current()]"/>
    </ul>
  </xsl:template>
 
  <xsl:template match="item">
    <li>
      <xsl:value-of select="text()"/>
    </li>
  </xsl:template>
 
</xsl:transform>


Output:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
    <h1>foo</h1>
    <ul>
      <li>item 1</li>
      <li>item 3</li>
      <li>item 4</li>
    </ul>
 
    <h1>bar</h1>
    <ul>
      <li>item 2</li>
      <li>item 5</li>
    </ul>
  </body>
</html>


Makkelijk he? :)

[ Voor 20% gewijzigd door mbravenboer op 29-08-2003 11:33 ]

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


Verwijderd

Topicstarter
Bedankt voor je input mbravenboer, ik ga EXSLT zo direct even uit testen.

Dan rest mij nog een vraag die je mij misschien direct kunt vertellen, voordat ik uren lang bezig ben met het zelf uit te zoeken; als je een soort van timestamp gebruikt in je XML, zou je je eigen XML ook kunnen sorteren in je output, en zou je hiervan dan ook alleen de laatste drie (of vier of whatever) items kunnen laten zien?

Het zou helemaal mooi zijn als je dat zou kunnen voordoen in mijn xml ;) Maargoed, je hoeft het niet allemaal voor te kauwen, natuurlijk.

In ieder geval bedankt voor de heads-up. 'k Ga met straks even verdiepen in dat EXSLT, nu ga ik eerst m'n deadline halen.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Syntaxis: als je een soort van timestamp gebruikt in je XML, zou je je eigen XML ook kunnen sorteren in je output
Uiteraard:
Sorting is specified by adding xsl:sort elements as children of an xsl:apply-templates or xsl:for-each element. The first xsl:sort child specifies the primary sort key, the second xsl:sort child specifies the secondary sort key and so on.
Als de dataum/tijd/timestamp een stukje gestructureerde xml is, is sorteren dus triviaal. Als het in een string gepropt is die op zich niet logisch sorteerbaar is, zal het je wat meer moeite kosten, maar lukt het ook wel.
en zou je hiervan dan ook alleen de laatste drie (of vier of whatever) items kunnen laten zien?
Geen probleem, maar dat mag je eerst zelf proberen op te lossen ;) .

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


Verwijderd

Topicstarter
Sorteren is een eitje ;)

code:
1
2
3
4
5
6
<xsl:sort order="descending" select="substring(datumtijd, 7,4)"/>
<xsl:sort order="descending" select="substring(datumtijd, 4,2)"/>
<xsl:sort order="descending" select="substring(datumtijd, 1,2)"/>
<xsl:sort order="descending" select="substring(datumtijd, 12,2)"/>
<xsl:sort order="descending" select="substring(datumtijd, 15,2)"/>
<xsl:sort order="descending" select="substring(datumtijd, 18,2)"/>


In geval van een constante 29-08-2003 11:33:30 datum display.


(credits gaan trouwens naar een collega, die dit eerder mooi had op kunnen lossen)

Verwijderd

Topicstarter
Namespace 'http://exslt.org/sets' does not contain any functions.
Oke, da's dus balen. Weet iemand hoe ik dit kan voorkomen?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
xml.com: EXSLT for MSXML

Onder de vele processoren die het by default al ondersteunen, valt niet MSXML.

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

Pagina: 1