28. oktober 2008 - 15:18
Der er
18 kommentarer og 1 løsning
gruppering af 2 elementer på samme level
Hej Eksperter, Jeg har en XMl struktur der ser således ud: <Root> <Adress> <felter...> </Adress> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Adress> <felter...> </Adress> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Adress> <felter...> </Adress> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Adress> <felter...> </Adress> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> </Root> I xml filen kommer X antal Adress tags og tilførende X antal Reading under hver Adress, De kommer i den rigtige rækkefølge. jeg har et xsl hvor jeg gerne vil vise det som det står i xml filen, men når jeg bruger 2 x "for-each" kommer alle reading under hver adress. Kan man ikke få det således at adress for kun de Readings der findes før den næste Adress kommer osv.? /Werge
Annonceindlæg fra Cepheo
28. oktober 2008 - 15:20
#1
I din anden for-each, skal du have et punktum forand x-pathen "./reading". Så søger den kun undernoder, og ikke i hele dokumentet.
28. oktober 2008 - 15:21
#2
Jeg vil gerne beholde den struktur der er i xml filen, men ved ikke hvordan når der er kommer flere af samme elementer som ikke er grupperet sammen. <Root> <Adress> <felter...> </Adress> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Adress> <felter...> </Adress> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Adress> <felter...> </Adress> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Adress> <felter...> </Adress> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> <Reading> <felter....> </Reading> </Root>
28. oktober 2008 - 15:22
#3
Hvordan ser din XSL ud (prøv at paste den ind i tråden her)?
28. oktober 2008 - 15:33
#4
Jeg havde ikke lige opdaget at det var en flad struktur. En af reglerne omkring xml er, at rækkefølgen af noderne ikke skal betyde noget. Så det du har gang i, modstrider xml specifikationen. Og jeg tror ikke det kan lade sig gøre at tage højde for det i en x-path.
28. oktober 2008 - 15:47
#5
første del af håndtering af Adress ser således ud: <xsl:template> <xsl:for-each select="Adress"> <tr> <td> <b>adresse</b> <br/> <xsl:value-of select="AddressID"/> <br/> <xsl:value-of select="Street"/> <br/> <xsl:value-of select="District"/> <xsl:text> </xsl:text> <xsl:value-of select="CityName"/> <br/> <br/> </td> </tr> <xsl:apply-templates select="Reading"/> </xsl:for-each> </xsl:template> Templaten for Reading ser således ud: <xsl:template match="Reading"> <tr> <td colspan="3" style="border-bottom: gainsboro thin solid;"> <font face="Arial" size="2"> <b>Måler nr. </b> <xsl:value-of select="MeterNumber"/> <b> Faktor: </b> <xsl:value-of select="MeterConstant"/> <br/> </font> </td> </tr> <tr valign="Top"> <td> <font face="Arial" size="2"> <b>Dato for aflæsning</b> </font> </td> <td> <font face="Arial" size="2"> <b>Måler er aflæst til (kWh))</b> </font> </td> <td> <font face="Arial" size="2"> <b>Dit forbrug i kWh</b> </font> </td> </tr> <!-- Start på Meter spec som en liste --> <xsl:for-each select="Reading"> <tr valign="Top"> <td> <xsl:value-of select="ReadingDate"/> </td> <td> <xsl:value-of select="PreviousStand"/> </td> <td style="border-bottom: gainsboro thin solid;"></td> </tr> <tr valign="Top"> <td style="border-bottom: gainsboro thin solid;"> <xsl:value-of select="ReadingDate"/> </td> <td style="border-bottom: gainsboro thin solid;"> <xsl:value-of select="Stand"/> </td> <td style="border-bottom: gainsboro thin solid;"> <xsl:value-of select="Quantity"/> </td> </tr> <tr> <td height="10px" column="3"></td> </tr> </xsl:for-each> <tr valign="Top"> <td valign="Top" colspan="3" style="border-bottom: gainsboro thin solid;"> <br/> <xsl:value-of select="Comments"/> <br/> </td> </tr> </xsl:template>
28. oktober 2008 - 16:02
#6
Du skal bruge <xsl:call-template> med parametre, sæt en bool alt efter hvad næste nodes name() er. Kald den så recursivt fra samme template.
28. oktober 2008 - 16:04
#7
Og væk med den xsl:for-each, det er bad practice ! - Brug apply-template.
28. oktober 2008 - 16:11
#8
jokkejensen: det lyder ret fornemt det du skriver, men jeg er ikke så god til dette endnu, kunne du give et kort eksempel?
28. oktober 2008 - 16:16
#9
yeah, men skal det fungere, vil jeg gerne have noget test xml, hvis du har noget uden person data.. Ellers kan jeg gætte 1000 gange :)
28. oktober 2008 - 16:18
#10
men ellers bare noget ala: following-sibling::node()/name() = 'Adress' Spring ud, eller count(following-sibling::Adress) Når den bliver en mindre, spring ud.
28. oktober 2008 - 16:31
#11
yeah, det kan du tro jeg har :) <?xml version="1.0" encoding="utf-8"?> <Root> <Adress> <AddressID>1a3ee569</AddressID> <Street>malsoparken 1</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Adress> <AddressID>1a3ee579</AddressID> <Street>malsoparken 10</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Adress> <AddressID>1a3ee492</AddressID> <Street>malsoparken 5</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> </Root> og tilhørende xsl: <xsl:template> <xsl:for-each select="Adress"> <tr> <td> <b>adresse</b> <br/> <xsl:value-of select="AddressID"/> <br/> <xsl:value-of select="Street"/> <br/> <xsl:value-of select="District"/> <xsl:text> </xsl:text> <xsl:value-of select="CityName"/> <br/> <br/> </td> </tr> <xsl:apply-templates select="Reading"/> </xsl:for-each> </xsl:template> Templaten for Reading ser således ud: <xsl:template match="Reading"> <tr> <td colspan="3" style="border-bottom: gainsboro thin solid;"> <font face="Arial" size="2"> <b>Måler nr. </b> <!-- <xsl:value-of select="MeterNumber"/> --> <b> Faktor: </b> <!-- <xsl:value-of select="MeterConstant"/> --> <br/> </font> </td> </tr> <tr valign="Top"> <td> <font face="Arial" size="2"> <b>Dato for aflæsning</b> </font> </td> <td> <font face="Arial" size="2"> <b>Måler er aflæst til (kWh))</b> </font> </td> <td> <font face="Arial" size="2"> <b>Dit forbrug i kWh</b> </font> </td> </tr> <!-- Start på Meter spec som en liste --> <xsl:for-each select="Reading"> <tr valign="Top"> <td> <xsl:value-of select="PreviousReadingDate"/> </td> <td> <xsl:value-of select="PreviousStand"/> </td> <td style="border-bottom: gainsboro thin solid;"></td> </tr> <tr valign="Top"> <td style="border-bottom: gainsboro thin solid;"> <xsl:value-of select="ReadingDate"/> </td> <td style="border-bottom: gainsboro thin solid;"> <xsl:value-of select="Stand"/> </td> <td style="border-bottom: gainsboro thin solid;"> <xsl:value-of select="Quantity"/> </td> </tr> <tr> <td height="10px" column="3"></td> </tr> </xsl:for-each> <tr valign="Top"> <td valign="Top" colspan="3" style="border-bottom: gainsboro thin solid;"> <br/> <xsl:value-of select="Comments"/> <br/> </td> </tr> </xsl:template> </xsl:stylesheet>
28. oktober 2008 - 16:43
#12
<template match="/"> <xsl:variable name="MessyXml"> <Root> <Adress> <AddressID>1a3ee569</AddressID> <Street>malsoparken 1</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Adress> <AddressID>1a3ee579</AddressID> <Street>malsoparken 10</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Adress> <AddressID>1a3ee492</AddressID> <Street>malsoparken 5</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> </Root> </xsl:variable> <xsl:apply-templates select="msxml:node-set($MessyXml)//Adress"></xsl:apply-templates> </xsl:template> <xsl:template match="Adress"> <h1> <xsl:value-of select="AddressID"/> </h1> <xsl:apply-templates select="./following-sibling::Reading"></xsl:apply-templates> </xsl:template> <xsl:template match="Reading"> Reading </xsl:template> Så du skal vel bare erstatte : <xsl:apply-templates select="Reading"/> med <xsl:apply-templates select="following-sibling::Reading"/>
28. oktober 2008 - 16:44
#13
hov nej, never mind... der skal den parameter med :)
28. oktober 2008 - 17:01
#14
jokkejensen: Jeg vender stærk tilbage senere på aftenen eller i morgen. jeg kigger på dit forslag - hvor vil du have parameter med når du ikke bruger call-template? eller misforstår jeg det helt? Werge
28. oktober 2008 - 18:37
#15
nej jeg tog helt fejl, skulle lige have noget fodder. aaberg havde vist rimeligt ret i at det er smartest at gruppere xmlen fra start af ordentligt, at transportere resten af kilden rundt med <xsl:call-template> så ryger der lidt performance. Men følende kode grupperer det, så kan du let selv style det: <xsl:template match="/"> <!-- Copy paste af dit xml --> <xsl:variable name="MessyXml"> <Root> <Adress> <AddressID>1a3ee569</AddressID> <Street>malsoparken 1</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Adress> <AddressID>1a3ee579</AddressID> <Street>malsoparken 10</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Adress> <AddressID>1a3ee492</AddressID> <Street>malsoparken 5</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> </Root> </xsl:variable> <!-- Transformere det om til grupper --> <xsl:variable name="NiceXml" xml:space="default"> <xsl:apply-templates select="msxml:node-set($MessyXml)" mode="cleanXml"></xsl:apply-templates> </xsl:variable> <!-- Udskriver det til test --> <textarea> <xsl:copy-of select="$NiceXml"></xsl:copy-of> </textarea> </xsl:template> <!-- Template der rydder det op --> <xsl:template match="*" mode="cleanXml" xml:space="default"> <Root> <xsl:for-each select="*"> <xsl:choose> <xsl:when test="name()='Adress'"> <xsl:text disable-output-escaping="yes"><![CDATA[<Group>]]></xsl:text> <xsl:copy-of select="."/> </xsl:when> <xsl:when test="name()='Reading'"> <xsl:if test="name(following-sibling::*) = 'Adress'"> <xsl:copy-of select="."/> <xsl:text disable-output-escaping="yes"><![CDATA[</Group>]]></xsl:text> </xsl:if> <xsl:if test="name(following-sibling::*) != 'Adress'"> <xsl:copy-of select="."/> </xsl:if> </xsl:when> </xsl:choose> </xsl:for-each> <xsl:text disable-output-escaping="yes"><![CDATA[</Group>]]></xsl:text> </Root> </xsl:template> Output = <Root> <Group> <Adress> <AddressID>1a3ee569</AddressID> <Street>malsoparken 1</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> </Group> <Group> <Adress> <AddressID>1a3ee579</AddressID> <Street>malsoparken 10</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> </Group> <Group> <Adress> <AddressID>1a3ee492</AddressID> <Street>malsoparken 5</Street> <District>Frederiksberg</District> <CityName>kbh</CityName> </Adress> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> <Reading> <PreviousReadingDate>10102008</PreviousReadingDate> <PreviousStand>10</PreviousStand> <PreviousQuantity>1</PreviousQuantity> </Reading> </Group> </Root> Så kan du bare zappe igennem med <xsl:apply-templates> Vh.
28. oktober 2008 - 20:37
#16
jokkejensen: det ser sku da cool ud det der, det må jeg kigge nærmere på i morgen. jeg vender stærkt tilbage. :) /Werge
04. november 2008 - 08:04
#17
hej jokkejensen, Det ser ud til at virke - :) jeg har ikke fået testet det igennem endnu, men jeg er helt klar med på hvad du vil opnå. smid et svar så får du points. PS: undskyld den lange vente tid :( /Werge
04. november 2008 - 14:12
#18
Yeah, bemærk lige at det godt kan være den nye variable med noderne, den jeg udskriver i <textarea> nok skal behandles med msxml:node-set(), der tager en tekst streng og laver om til et node sæt. Så kan du arbede videre med det. Husk at inkludere xml namespace msxml i dit <stylesheet> ala: xmlns:msxml="urn:schemas-microsoft-com:xslt" og evt fjerne prefixet gennem exclude-prefixes="msxml".. Ellers siger du bare til, jeg er ikke lige så go til at vende tilbage, så opret en ny.
07. november 2008 - 09:59
#19
Hey jokkejensen - tak for yderligere info - jeg opretter en ny hvis det bliver nødvendigt :)
Kurser inden for grundlæggende programmering