Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[XSLT] Tabel sluiten/openen in choose constructie

Pagina: 1
Acties:

Verwijderd

Topicstarter
Een DOM Document met de volgende inhoud wordt gegenereerd om binnen een webapplicatie verwerkt te worden via XSLT:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
<property group="Groep 1">
     <name>Naam 1</name>
     <value>Waarde 2</value>
</property>
<property group="Groep 1">
     <name>Naam 2</name>
     <value>Waarde 2</value>
</property>
<property group="Groep 2">
     <name>Naam 3</name>
     <value>Waarde 3</value>
</property>


Hier de XSLT code. De EXSLT functie die uitgevoerd wordt is simpelweg het genereren van de tabelrij (zoals de naam al doet vermoeden).

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<xsl:for-each select="property">

    <xsl:choose>
        <xsl:when test="preceding-sibling::*[@group][1]/@group != ./@group or not(preceding-sibling::*)">
            <h3><xsl:value-of select="./@group"/></h3>
            <table class="infotable">
            <xsl:copy-of select="my:renderPropertiesRow('searchHeader')"/>

        </xsl:when>
        <xsl:when test="following-sibling::*[@group][1]/@group != ./@group or not(following-sibling::*)">

            <xsl:copy-of select="my:renderPropertiesRow('searchHeader')"/>
            </table>

        </xsl:when>
        <xsl:otherwise>

            <xsl:copy-of select="my:renderPropertiesRow('searchHeader')"/>

        </xsl:otherwise>
    </xsl:choose>

</xsl:for-each>


Wat het bovenstaande moet doen is de groepsnaam en een <table>-tag weergeven, wanneer deze verschilt van de groepsnaam van de vorige 'property', of wanneer er geen voorgaande 'property' is. De tabel moet gesloten worden wanneer de groepsnaam van de volgende 'property' verschilt van de huidige, of wanneer en geen volgende 'property' bestaat.

Het resultaat zou dus moeten zijn:
HTML:
1
2
3
4
5
6
7
8
<h3>Groepsnaam 1</h3>
<table class="infotable">
[info van eerste en tweede 'property']
</table>
<h3>Groepsnaam 2</h3>
<table class="infotable">
[info van derde 'property']
</table>


De choose-constructie opzich werkt ook prima en is slechts bedoeld op het probleem even te illustreren.

Het probleem is dat het bovenstaande niet wordt geaccepteerd als zijnde correcte XML syntax, aangezien de table-tags verdeeld zijn over twee condities. Mijn vraag is; hoe zou ik dit op kunnen lossen?

Alle suggesties zijn welkom. Het aanpassen van de XML-inhoud heeft echter minder mijn voorkeur, omdat de handeling m.i. presentatielogica is, die in een XSL-bestand afgehandeld zou moeten kunnen worden.

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Je zou het zo kunnen doen (in pseudocode):

code:
1
2
3
voor elk property wiens group niet in een preceding sibling te vinden is
     maak een tabel
          loop over alle properties met dezelfde group als dit property

[ Voor 3% gewijzigd door djc op 17-07-2007 09:42 ]

Rustacean


Verwijderd

Topicstarter
Manuzhai schreef op dinsdag 17 juli 2007 @ 09:42:
Je zou het zo kunnen doen (in pseudocode):

code:
1
2
3
voor elk property wiens group niet in een preceding sibling te vinden is
     maak een tabel
          loop over alle properties met dezelfde group als dit property
Het probleem bij deze suggestie is dat een for-each voor zover ik weet niet werkt met vergelijkende operatoren (de derde zin).

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Verwijderd schreef op dinsdag 17 juli 2007 @ 18:05:
Het probleem bij deze suggestie is dat een for-each voor zover ik weet niet werkt met vergelijkende operatoren (de derde zin).
Heb je dat getest? Ik denk dat foreach in zijn test attribuut min of meer willekeurige XPath-expressies accepteert, dus met iets als property[@group = $crap] moet je er wel komen, denk ik.

Rustacean


Verwijderd

Topicstarter
Manuzhai schreef op woensdag 18 juli 2007 @ 01:14:
[...]
Heb je dat getest? Ik denk dat foreach in zijn test attribuut min of meer willekeurige XPath-expressies accepteert, dus met iets als property[@group = $crap] moet je er wel komen, denk ik.
Je hebt gelijk. Bedankt :) Omdat XSL (als declaratieve taal) voor zover ik het begrijp geen 'state' kent heb ik in plaats van die $crap de current() functie gebruikt. Ik heb nu het volgende, wat prima werkt:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<xsl:for-each select="property[preceding-sibling::*[@group][1]/@group != @group or not(preceding-sibling::*)]">

<h3><xsl:value-of select="@group"/></h3>
<table class="infotable">

    <xsl:for-each select="/root/form/property[@group = current()/@group]">

        <xsl:copy-of select="my:renderPropertiesRow('searchHeader')"/>

    </xsl:for-each>

</table>

</xsl:for-each>


Na wat zoeken kwam ik op deze pagina. Het eerste voorbeeld is feitelijk wat jij in pseudocode suggereerde, en wat ik nu toegepast heb. Dit zou langzaam zijn bij grote documenten, maar daar is bij mijn applicatie geen sprake van. Er wordt ook een sneller alternatief met de key() functie gegeven.

In ieder geval wordt/is dit met XSLT 2.0 een koud kunstje begrijp ik uit dit artikel.

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Verwijderd schreef op woensdag 18 juli 2007 @ 02:32:
In ieder geval wordt/is dit met XSLT 2.0 een koud kunstje begrijp ik uit dit artikel.
Volgens mij is er voorlopig nog geen goede open source implementatie van XSLT 2.0... Dus dat maakt dat het gebruik van dergelijke dingen in bijvoorbeeld PHP nog vrij ver weg is.

Rustacean

Pagina: 1