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

[XPath] xs:date/xs:duration gebruiken als xs:number

Pagina: 1
Acties:

  • r0bert
  • Registratie: September 2001
  • Laatst online: 28-11 00:42
In mijn XSL heb ik een aantal attributen van het type xs:date, genaamd @datum. Nu wil ik van deze attributen graag de vroegste datum in een variabele zien te krijgen. Eerst toen ik de data als xs:number had gedefinieerd ging dat makkelijk, maar nu als xs:date werken de math:max en math:min function niet meer.

Noodoplossing was voor mij het sorteren van de gegeven en het eerste en laatste element uitlezen. Niet mooi, maar omdat ik toch al moest sorteren kon dat wel.

Nu moet ik echter alsnog gaan rekenen met de data (om verhoudingen te achterhalen etc.). Omdat data als getal genoteerd niet te gebruiken zijn voor rekenen (10-tallige stels klopt niet met dagen weken maanden blabla), wou ik met verschillen gaan werken. Ik heb immers het vroegste moment, dan wil ik alles relatief daaraan maken en daarmee gaan rekenen.

Ik krijg een date:difference een xs:duration terug, bijvoorbeeld P40D wat dan 40 dagen voorstelt. Nu kan ik dat gaan substringen etc., maar dat wil ik niet omdat ik het vaak gebruik en ik wel geloof dat hier een normale oplossing zou moeten zijn.

Uiteindelijk gaat het er dus om, om van een xs:duration (of xs:date?) naar een getal (xs:number) te komen. Iemand die weet hoe ik dit op een nette manier voor elkaar krijg? Ik zou die P40D dus graag netjes willen laten vertalen naar bijv "40" of "960" (40d x 24u).
code:
1
<xsl:value-of select="number($date-of-duration)" />

Werkte iig niet.

Die conversie naar een sort van number is even voor mij het belangrijkste. Het sorteren kom ik wel uit, maar mocht iemand daar iets handigs voor weten hoor ik het graag. Ik heb libxslt 1.1... met exslt support in PHP tot mijn beschikking.

[ Voor 8% gewijzigd door r0bert op 19-09-2007 20:11 ]


  • r0bert
  • Registratie: September 2001
  • Laatst online: 28-11 00:42
Is er welke niemand hier die ooit in Xpath/Xquery heeft gerekend met data?

  • r0bert
  • Registratie: September 2001
  • Laatst online: 28-11 00:42
Ik heb inmiddels dit ervan gemaakt:
code:
1
<xsl:value-of select="dtm:seconds(dtm:difference('2007-01-01','2007-08-09'))" />

  • r0bert
  • Registratie: September 2001
  • Laatst online: 28-11 00:42
Vervolgvraag waar ik het antwoord ook niet van kan vinden
code:
1
<xsl:value-of select="math:min(//dtm:seconds(@start))" />

Bovenstaand zou de laagste waarde moeten pakken, maar deze syntax is niet goed.
De code seconds geeft een number terug, waarvan de laagste dus gevonden moet worden (= vroegste datum). Hoe doe ik dat :S

  • foliant
  • Registratie: Juli 2007
  • Laatst online: 19-01-2022
Misschien een beetje laat, maar toch.
Eigenlijk heb je volgens mij je beide vragen al zo goed als zelf beantwoord:

1) xs:date als xs:number
De exslt functie date:seconds() geeft een number (aantal seconden vanaf 1 januari 1970), waar je mee kunt rekenen.

2)
XML:
1
<xsl:value-of select="math:min(//dtm:seconds(@start))" /> 

Dit is inderdaad geen goede syntax. math:min() verwacht een node-set als argument.

Wil je inderdaad math:min gebruiken, dan moet je eerst een node-set gaan maken, met daarin numbers zijn i.p.v. dates. Dit kan wel, maar is volgens mij te omslachtig.
Noodoplossing was voor mij het sorteren van de gegeven en het eerste en laatste element uitlezen. Niet mooi, maar omdat ik toch al moest sorteren kon dat wel.
Als ik naar de implementatie van math:min (b.v. die van Jeni Tennison) kijk dan lijkt me dat geen noodoplossing:

XML:
1
2
3
4
5
6
7
8
... 
<xsl:for-each select="$nodes">
        <xsl:sort data-type="number"/>
    <xsl:if test="position() = 1">
        <exsl:return select="number(.)"/>
        </xsl:if>
</xsl:for-each>
...

N.b. Ik heb een deel van de code weggelaten, zodat alleen de essentie overblijft.

Om b.v. de jongste datum uit de date attributen uit onderstaand xml bestand te selecteren, kun je een analoge oplossing als bovenstaand gebruiken:

Data:
XML:
1
2
3
4
5
6
7
<root>
<item date="2007-09-01"/>
<item date="2007-08-19"/>
<item date="2001-12-19"/>
<item date="1998-01-13"/>
<item date="2007-09-19"/>
</root>


Stylesheet:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:dtm="http://exslt.org/dates-and-times"
                extension-element-prefixes="dtm"> 

<xsl:for-each select="/root/item">
           <xsl:sort select="@date"/> <!-- Dates zijn van formaat YYYY-mm-dd, dus de default text sort is volstaat. -->
            <xsl:if test="position() = 1">
               <xsl:value-of select="@date" /> <!-- select="dtm:seconds(@date)" voor een number-->
            </xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="/">

  • r0bert
  • Registratie: September 2001
  • Laatst online: 28-11 00:42
Ok, daar is het mee gelukt! Nu nog één ding waar ik niet uit kom, ik heb twee attributen waar ik op moet sorteren. Ik wil nu de laatste hebben ipv de eerste.

Er zijn elementen met alleen een @datum
En er zijn elementen met een @datum en @eind
Bij de laatstgenoemde zou dus het @eind gebruikt moeten worden boven @datum. Bij de overige gewoon @datum.

Hoe kan ik dat handig doen? Heb geprobeerd creatief te wezen, maar krijg niets draaiend. Ik heb gewoon bovenstaande methode aangehouden.

  • r0bert
  • Registratie: September 2001
  • Laatst online: 28-11 00:42
Mm laat maar, dat was nu easy:
XML:
1
2
3
4
5
6
7
8
    <xsl:variable name="intTimelineEnd">
        <xsl:for-each select="//snm:filosoof/@datum|//snm:filosoof/@eind"> 
        <xsl:sort select="."/>
        <xsl:if test="position() = last()"> 
            <xsl:value-of select="." />
        </xsl:if> 
        </xsl:for-each>
    </xsl:variable>
Pagina: 1