Toon posts:

[xml/xsl] waarden selecteren en sorteren nav. veld in .xml

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

Verwijderd

Topicstarter
Titel is misschien niet helemaal duidelijk, maar kon niets beters bedenken..

Stel ik heb de volgende .xml:
XML:
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
46
<root>
   <items>
     <item>
       <item_naam>item 1</item_naam>
       <onderdelen>
         <onderdeel>
           <onderdeel_naam>onderdeel 1</onderdeel_naam>
           <onderdeel_batch_nummer>1</onderdeel_batch_nummer>
         </onderdeel>
         <onderdeel>
           <onderdeel_naam>onderdeel 2</onderdeel_naam>
           <onderdeel_batch_nummer>1</onderdeel_batch_nummer>
         </onderdeel>
       </onderdelen>       
     </item> 
     <item>
       <item_naam>item 2</item_naam>
       <onderdelen>   
         <onderdeel>
           <onderdeel_naam>onderdeel 1</onderdeel_naam>
           <onderdeel_batch_nummer>4</onderdeel_batch_nummer>
         </onderdeel>
         <onderdeel>
           <onderdeel_naam>onderdeel 2</onderdeel_naam>
           <onderdeel_batch_nummer>4</onderdeel_batch_nummer>
         </onderdeel>
       </onderdelen>       
     </item>
     <item>
       <item_naam>item 3</item_naam>
       <onderdelen>   
         <onderdeel>
           <onderdeel_naam>onderdeel 1</onderdeel_naam>
           <onderdeel_batch_nummer>2</onderdeel_batch_nummer>
         </onderdeel>
         <onderdeel>
           <onderdeel_naam>onderdeel 2</onderdeel_naam>
           <onderdeel_batch_nummer>3</onderdeel_batch_nummer>
         </onderdeel>
       </onderdelen>       
     </item>

     [..] enzovoort [..]

   </items>
</root>


Hierbij is voor elk item de lijst van onderdelen gelijk, elk item bestaat uit dezelfde onderdelen. Deze .xml is gesorteerd op item_naam.

Wat ik nu wil is een lijst als volgt:
code:
1
2
3
4
5
6
7
8
9
onderdeel 1
  item 1 | batch nummer 1
  item 3 | batch nummer 2
  item 2 | batch nummer 4

onderdeel 2
  item 1 | batch nummer 1
  item 3 | batch nummer 3
  item 2 | batch nummer 4


Dus per onderdeel de items die dat onderdeel bevatten (=allemaal) en dan per batch_nummer gesorteerd.

Hoe pak ik dit aan zonder gebruik te maken van een XQuery, zuiver alleen van een .xsl welke als stylesheet gekoppeld wordt?

Ik krijg wel een lijst van onderdelen eruit, op een al vrij smerige manier (denk ik):

code:
1
2
3
4
5
6
7
8
9
10
11
12
<xsl:stylesheet>
  <xsl:template match="/">
    <xsl:for-each select="items/item">
      <xsl:if test="position()=1">
        <xsl:for-each select="onderdelen/onderdeel">
          <xsl:value-of select="onderdeel_naam"/>
           [onthoudt dit punt in de code even :)]
        </xsl:for-each>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>


Dit levert als output op:

Text output:
1
2
onderdeel 1
onderdeel 2


Wat nu nog ontbreekt is een methode om per onderdeel alle items te selecteren en dan te sorteren op batch_nummer van het betreffende onderdeel.

Ik weet dat xsl:for-each hier een niet al te populaire methode is, maar ben door andere oorzaken gedwongen deze te gebruiken.

Hoe pak ik dit aan? Hoe kan ik aan de hand van de onderdeel_naam die ik nu al heb verder de selectie maken? als ik bv op het punt waar 'onthoudt dit punt even' dit ga neerzetten:

code:
1
  <xsl:for-each select="../../../items | //onderdeel_naam=onderdeel_naam">


oid, dan werkt dat natuurlijk niet.. :P

Je hoeft overigens niet echt te zoeken naar typo's oid in de .xml of .xsl hier, dit zijn zelfverzonnen voorbeelden om het principe van mijn vraag duidelijk te maken..

dus: heeft iemand een idee hoe ik hier verder ga?

Verwijderd

Topicstarter
Niemand een hint in welke richting ik het moet zoeken?

Verwijderd

Mmm, je wilt dit met XSL dit gaan doen. XSL is officieel alleen maar een opmaaktaal net zoals CSS dat bij HTML is. Zonder XSLT zal dit zowiezo niet gaan lukken.
Je hebt een aantal manieren om dit op te lossen. (1)Verander je XML structuur zodanig, zodat je geen ingewikkelde XSLT constructies hoeft te maken. (2)Maak een lijst aan en loop vervolgens de lijst af list[1]= 'item 1' etc. (3). Maak een custom functie aan in xslt die dit alles voor je regelt(bijv. met javascript...jajaja XSLT rules !!!!) :+ Verder doet google wonderen...

Verwijderd

Topicstarter
imo valt xslt 'onder' xsl, maar zoals jij het omschrijft bedoelde ik xslt :P

  • Xlnt
  • Registratie: Oktober 2000
  • Laatst online: 03-05 18:18
Verwijderd schreef op 03 juli 2004 @ 13:30:
XML:
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
46
<root>
   <items>
     <item>
       <item_naam>item 1</item_naam>
       <onderdelen>
         <onderdeel>
           <onderdeel_naam>onderdeel 1</onderdeel_naam>
           <onderdeel_batch_nummer>1</onderdeel_batch_nummer>
         </onderdeel>
         <onderdeel>
           <onderdeel_naam>onderdeel 2</onderdeel_naam>
           <onderdeel_batch_nummer>1</onderdeel_batch_nummer>
         </onderdeel>
       </onderdelen>       
     </item> 
     <item>
       <item_naam>item 2</item_naam>
       <onderdelen>   
         <onderdeel>
           <onderdeel_naam>onderdeel 1</onderdeel_naam>
           <onderdeel_batch_nummer>4</onderdeel_batch_nummer>
         </onderdeel>
         <onderdeel>
           <onderdeel_naam>onderdeel 2</onderdeel_naam>
           <onderdeel_batch_nummer>4</onderdeel_batch_nummer>
         </onderdeel>
       </onderdelen>       
     </item>
     <item>
       <item_naam>item 3</item_naam>
       <onderdelen>   
         <onderdeel>
           <onderdeel_naam>onderdeel 1</onderdeel_naam>
           <onderdeel_batch_nummer>2</onderdeel_batch_nummer>
         </onderdeel>
         <onderdeel>
           <onderdeel_naam>onderdeel 2</onderdeel_naam>
           <onderdeel_batch_nummer>3</onderdeel_batch_nummer>
         </onderdeel>
       </onderdelen>       
     </item>

     [..] enzovoort [..]

   </items>
</root>
Om de location paths kort te houden, kun je dit vereenvoudigen naar het volgende.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<items>
 <item naam"item 1">
  <onderdeel naam="onderdeel 1" batch="1"/>
  <onderdeel naam="onderdeel 2" batch="1"/>
 </item>
 <item naam"item 2">
  <onderdeel naam="onderdeel 1" batch="4"/>
  <onderdeel naam="onderdeel 2" batch="4"/>
 </item>
 <item naam"item 3">
  <onderdeel naam="onderdeel 1" batch="2"/>
  <onderdeel naam="onderdeel 2" batch="3"/>
 </item>
</items>

Ik vind dat het zo ook een stuk duidelijker wordt. Een aantal overbodige elementen zijn verwijderd. En de attributen zijn gerangschikt in kolommen. Niet dat je hiermee ook maar één stap dichter bij de oplossing komt :Y).
Hierbij is voor elk item de lijst van onderdelen gelijk, elk item bestaat uit dezelfde onderdelen. Deze .xml is gesorteerd op item_naam.

Wat ik nu wil is een lijst als volgt:
code:
1
2
3
4
5
6
7
8
9
onderdeel 1
  item 1 | batch nummer 1
  item 3 | batch nummer 2
  item 2 | batch nummer 4

onderdeel 2
  item 1 | batch nummer 1
  item 3 | batch nummer 3
  item 2 | batch nummer 4


Dus per onderdeel de items die dat onderdeel bevatten (=allemaal) en dan per batch_nummer gesorteerd.

Hoe pak ik dit aan zonder gebruik te maken van een XQuery, zuiver alleen van een .xsl welke als stylesheet gekoppeld wordt?

Ik krijg wel een lijst van onderdelen eruit, op een al vrij smerige manier (denk ik):

code:
1
2
3
4
5
...
 <xsl:for-each select="items/item">
  <xsl:if test="position()=1">
   <xsl:for-each select="onderdelen/onderdeel">
    ...
Je denkt te veel in statements ;). Dit stukje kun je veel eenvoudiger uitdrukken.

code:
1
2
3
...
 <xsl:for-each select="items/item[1]/onderdelen/onderdeel">
  ...
Dit levert als output op:

Text output:
1
2
onderdeel 1
onderdeel 2


Wat nu nog ontbreekt is een methode om per onderdeel alle items te selecteren en dan te sorteren op batch_nummer van het betreffende onderdeel.

Ik weet dat xsl:for-each hier een niet al te populaire methode is, maar ben door andere oorzaken gedwongen deze te gebruiken.
Stok achter de deur >:)?
Hoe pak ik dit aan? Hoe kan ik aan de hand van de onderdeel_naam die ik nu al heb verder de selectie maken? als ik bv op het punt waar 'onthoudt dit punt even' dit ga neerzetten:

code:
1
2
 <xsl:for-each select="../../../items
  | //onderdeel_naam=onderdeel_naam">


oid, dan werkt dat natuurlijk niet.. :P
Is dit de | van 'onder de voorwaarde'? Hoe dan ook, in XPath noteer je zo'n predikaat tussen [ en ]. In de context van dat predikaat is er geen referentie meer naar de onderdeel_naam waarmee je wilt vergelijken. Je kunt daarvoor echter een variabele introduceren.

code:
1
<xsl:variable name="onderdeel_naam" select="onderdeel_naam"/>


Je kunt dan voortaan naar deze onderdeel_naam referenen met $onderdeel_naam.
Je hoeft overigens niet echt te zoeken naar typo's oid in de .xml of .xsl hier, dit zijn zelfverzonnen voorbeelden om het principe van mijn vraag duidelijk te maken..
In dat geval mag je mijn eerste alinea schrappen ;).
dus: heeft iemand een idee hoe ik hier verder ga?
Zoiets zou het moeten worden.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<xsl:stylesheet>
 <xsl:template match="/">
   <xsl:for-each select="/root/items/item[1]/onderdelen/onderdeel">
    <xsl:variable name="onderdeel_naam" select="onderdeel_naam"/>
    <xsl:value-of select="$onderdeel_naam"/>
    <BR/>

    <xsl:for-each select="/root/items/item/onderdelen/
     onderdeel[onderdeel_naam = $onderdeel_naam]">
     <xsl:sort select="onderdeel_batch_nummer"/>
     <xsl:value-of select="../../item_naam"/>
     <xsl:text> | </xsl:text>
     <xsl:value-of select="onderdeel_batch_nummer"/>
     <BR/>
    </xsl:for-each>

    <BR/>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>


Als je overigens te maken krijgt met een variabel aantal onderdelen per item, dan kun je de onderdelen groeperen per onderdeelnaam met een <xsl:key>. De sleutelwaarden uit die sleutel halen is weer een stuk lastiger, maar het kan. Met zo'n sleutel zal het zoiets als het volgende worden.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<xsl:stylesheet>
 <xsl:key name="onderdeel" match="/root/items/item/onderdelen/onderdeel"
  use="onderdeel_naam"/>
 <xsl:template match="/">
  <xsl:for-each select="root/items/item/onderdelen/onderdeel[
   generate-id(onderdeel_naam) =
   generate-id(key('onderdeel', onderdeel_naam)[1]/onderdeel_naam)]">

   <xsl:value-of select="onderdeel_naam"/>
   <BR/>
   <xsl:for-each select="key('onderdeel',  onderdeel_naam)">
    <xsl:sort select="onderdeel_batch_nummer"/>
    <xsl:value-of select="../../item_naam"/>
    <xsl:text> | </xsl:text>
    <xsl:value-of select="onderdeel_batch_nummer"/>
    <BR/>
   </xsl:for-each>

   <BR/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

[ Voor 14% gewijzigd door Xlnt op 04-07-2004 23:29 . Reden: Word wrap ]

"It's not that I'm lazy. It's that I just don't care."


Verwijderd

Topicstarter
Xlnt schreef op 04 juli 2004 @ 23:24:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<xsl:stylesheet>
 <xsl:template match="/">
   <xsl:for-each select="/root/items/item[1]/onderdelen/onderdeel">
    <xsl:variable name="onderdeel_naam" select="onderdeel_naam"/>
    <xsl:value-of select="$onderdeel_naam"/>
    <BR/>

    <xsl:for-each select="/root/items/item/onderdelen/onderdeel[onderdeel_naam = $onderdeel_naam]">
     <xsl:sort select="onderdeel_batch_nummer"/>
     <xsl:value-of select="../../item_naam"/>
     <xsl:text> | </xsl:text>
     <xsl:value-of select="onderdeel_batch_nummer"/>
     <BR/>
    </xsl:for-each>

    <BR/>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
_/-\o_

Dank voor de (voor mij) zeer verhelderende uitleg, er vielen hier een paar puzzelstukjes op de plaats.. het zal niet helemaal het bovenstaande worden, maar ik had wel even echt iets van 'aaaaahhh... zit dat zo' :)
Pagina: 1