[XML/XSLT] Facultatieve getallen optellen

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

  • Redshark
  • Registratie: Mei 2002
  • Laatst online: 20-05 13:08
Ik heb een XML bestand met daarin verschillende velden die altijd een getal zijn.
Met XSLT maak ik hier een HMTL-betand van. Werkt prima.
De getallen wil ik bij elkaar optellen, ook dat gaat goed. Maar, niet alle getallen worden altijd ingevuld. Ik moet dus eerst controleren welke getallen ingevuld zijn voordat ik ze op kan tellen. Dat doe ik als volgt:

code:
1
2
3
4
5
6
<xsl:if test="count(blaat1[name='voorwaarde']/blaat2) != 0 
and count(blaat1[name='voorwaarde1']/blaat2) != 0 
and count(blaat1[name='voorwaarde3']/blaat3) != 0">

Hier dan het optellen en weergeven van de totale som
</xsl:if>


Tot zover niets schokkends. Ik heb hier maar drie getallen die ik gebruik dus met 8 keer deze code ben ik klaar. Het geval wil nu dat ik nu 30 facultatieve velden bij elkaar wil optellen(!). Ik zie het echt niet zitten om dit 230 keer te doen en volgens mij kan het ook makkelijker.

Maar hoe?

Ik zal wel weer in de verkeerde hoek aan het denken zijn en kom er niet op

Inmiddels ben ik begonnen om het geheel op te delen in meerdere kleinere checks door de getallen te splitsen in 5 groepen van 6 stuks. Deze 6 stuks kan ik dan bijvoorbeeld vullen door twee keer de code te gebruiken die ik al eerder gebruikt heb. Dat is al een hele vooruitgang maar gaat nog steeds uit van hetzelfde principe.

Heb ik het goed dat ik dit op een andere manier moet kunnen doen of is dit de enige juiste manier?

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09-2025

djc

Heb je controle over de XML, en hoe ziet die eruit?

Rustacean


  • Redshark
  • Registratie: Mei 2002
  • Laatst online: 20-05 13:08
Nee, de XML staat vast en kan ik niet beinvloeden.

Grofweg ziet de structuur er als volgt uit:

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
<?xml version="1.0" encoding="ISO-8859-1"?>
<dump>
  <pagina>
    <hoofddeel>
      <allerlei info hier die er niet toe doet>
      </allerlei info hier die er niet toe doet>
    </hoofddeel>
    <detaillijst>
      <veld>
        <naam>Getal 1</naam>
        <inhoud>1234</inhoud>
    </veld>
    <veld>
        <naam>Getal 2</naam>
        <inhoud />
    </veld>
    ...
     <veld>
        <naam>Getal 30</naam>
        <inhoud>567</inhoud>
    </veld>
    </detaillijst>
</pagina>
</dump>
</xml>


Het gaat dus om de items <veld> en hun childs waarvan ik de <inhoud> wil optellen. Zoals je ziet in dit voorbeeld is de inhoud van getal2 leeg, itt getal 1 en 30.

Inmiddels ben ik ook al verder gegaan met mijn idee in de SP. ik heb nu 1 van de 5 'deelgroepen' kunnen optellen. Resultaat is een berg code waar ik niet blij word :(

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09-2025

djc

Kan je niet iets met sum('/dump/pagina/detaillijst/veld/inhoud') proberen?

Zie hier.

[ Voor 39% gewijzigd door djc op 28-10-2004 13:32 ]

Rustacean


  • Redshark
  • Registratie: Mei 2002
  • Laatst online: 20-05 13:08
Dat had ik inderdaad al geprobeerd. Op zich natuurlijk een prima methode, maar dan moet iedere node ingevuld zijn. Bij mij werkt het prima, maar zodra ik ook maar 1 node leeg haal gaat het mis:


Even schaamteloos een voorbeeldje gejat van W3Schools :)
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="catalog.xsl"?>
<catalog>
  <cd country="USA">
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <price>10</price>
  </cd>
  <cd country="UK">
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <price />
  </cd>
  <cd country="USA">
    <title>Greatest Hits</title> 
    <artist>Dolly Parton</artist> 
    <price>9</price> 
  </cd>
</catalog>


En dan even deze XSLT eroverheen:

XSLT:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" version="4.0"/>
    <xsl:template match="/" >
        <html>
        <head>
            <title>Facultatief tellen :)</title>
        </head>
        <body>
            <xsl:for-each select="catalog">
                <xsl:value-of select=" sum(cd/price)" /><br />
            </xsl:for-each>
        </body>
    </html>
    </xsl:template>         
</xsl:stylesheet>


Geeft netjes:
NaN :(

Vervang je de lege price-node door een gevulde dan werkt het verhaaltje vanzelfsprekend wel.

Inmiddels ben ik aardig ver met mijn bedachte 'oplossing' maar erg elegant vind ik hem niet als ik eerlijk ben :/

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09-2025

djc

Hm, zou je niet een dubbele transformatie kunnen doen? Je maakt eerst een XML document waar de waarden instaan die wel bestaan, en dan haal je daar nog eens een transformatie overheen die al die dingen bij elkaar optelt.

Rustacean


Verwijderd

Deze doet wel zo'n beetje wat ik denk dat je wilt:


<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="4.0"/>

<xsl:template match="/">
<xsl:variable name="TotalSum" select="sum(catalog/cd/price[boolean(number(.))])"/>
<html>
<head>
<title>Facultatief tellen :)</title>
</head>
<body>
<xsl:value-of select="$TotalSum"/><br/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Verwijderd

En.....

Werkt het al ?

  • Redshark
  • Registratie: Mei 2002
  • Laatst online: 20-05 13:08
Daar ben ik weer, was eventjes druk met sociaal doen de afgelopen dagen :)

Het voorbeeld van saghws werkt prima, waarvoor dank :)
Mijn lange brei van code kan ik nu mooi gaan inkorten, iets wat dus ongeveer 1000 regels code zal gaan schelen (ja, mijn gekozen oplossing wat niet zo fraai :Y) )

Naast dit voorbeeld heb ik nog iets gevonden wat mijn aandacht trok en dat is dit linkje:
http://www.biglist.com/li...ives/200101/msg00491.html

Oftewel dit stukje hiervan:
code:
1
<xsl:decimal-format name="MyFormat" NaN=" 0 " zero-digit="0"/>


And use it with your format statement:

code:
1
format-number(@totalAmt,'#,###','MyFormat')


Oftewel, met dit simpele stukje toevoeging aan een variabele ben je instaat om lege nodes toch een waarde 0 te geven, waarna je hier dus gewoon mee kun rekenen.

Met deze oplossing ben ik waarschijnlijk met 40 regeltjes klaar :)

Ik ga is even kijken welke oplossing bij mij de snelste code oplevert, ik gok de laatste, maar ik weet nog niet hoe ik de oplossing van saghws handig bij mijn situatie kan gebruiken.

Iig thnx voor de replys alvast.
Pagina: 1