[XSLT] unieke waardes filteren

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

  • SouLmaN
  • Registratie: Juli 2001
  • Laatst online: 06-05 16:34
Ik krijg de volgende gegevens in XML uit de database, en wil deze mbv XSLT omzetten naar een betere opmaak. Alleen nu krijg ik het niet voor elkaar om de dubbele waardes eruit te halen.

Hier de data die ik uit de database krijg in XML :

code:
1
2
3
4
5
6
7
8
9
10
 <oda>
  <Row ODA_ID="0" AID="CD46" GROUP_TYPE="08" GROUP_VERSION="A" TIMEOUT="2" ODA_ID_1="0" SHORT_MESSAGE="0066" PORT_NR="1" ACCESS_RIGHT="0" ODA_ID_2="0" /> 
  <Row ODA_ID="0" AID="CD46" GROUP_TYPE="08" GROUP_VERSION="A" TIMEOUT="2" ODA_ID_1="0" SHORT_MESSAGE="0066" PORT_NR="2" ACCESS_RIGHT="0" ODA_ID_2="0" /> 
  <Row ODA_ID="0" AID="CD46" GROUP_TYPE="08" GROUP_VERSION="A" TIMEOUT="2" ODA_ID_1="0" SHORT_MESSAGE="6280" PORT_NR="1" ACCESS_RIGHT="0" ODA_ID_2="0" /> 
  <Row ODA_ID="0" AID="CD46" GROUP_TYPE="08" GROUP_VERSION="A" TIMEOUT="2" ODA_ID_1="0" SHORT_MESSAGE="6280" PORT_NR="2" ACCESS_RIGHT="0" ODA_ID_2="0" /> 
  <Row ODA_ID="1" AID="0008" GROUP_TYPE="06" GROUP_VERSION="A" TIMEOUT="1" ODA_ID_1="1" SHORT_MESSAGE="0062" PORT_NR="1" ACCESS_RIGHT="1" ODA_ID_2="1" /> 
  <Row ODA_ID="1" AID="0008" GROUP_TYPE="06" GROUP_VERSION="A" TIMEOUT="1" ODA_ID_1="1" SHORT_MESSAGE="0062" PORT_NR="2" ACCESS_RIGHT="1" ODA_ID_2="1" /> 
  <Row ODA_ID="1" AID="0008" GROUP_TYPE="06" GROUP_VERSION="A" TIMEOUT="1" ODA_ID_1="1" SHORT_MESSAGE="4689" PORT_NR="1" ACCESS_RIGHT="1" ODA_ID_2="1" /> 
  <Row ODA_ID="1" AID="0008" GROUP_TYPE="06" GROUP_VERSION="A" TIMEOUT="1" ODA_ID_1="1" SHORT_MESSAGE="4689" PORT_NR="2" ACCESS_RIGHT="1" ODA_ID_2="1" /> 
  </oda>


Zo moet het uiteindelijk worden:
code:
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
- <oda>
- <application>
  <aid>CD46</aid> 
- <group>
  <type>08</type> 
  <version>A</version> 
  </group>
  <timeout>2</timeout> 
  <shortmessage>0066</shortmessage> 
  <shortmessage>6280</shortmessage> 
- <odaaccessrights>
- <portaccess>
  <number>1</number> 
  <enabled>0</enabled> 
  </portaccess>
  </odaaccessrights>
  </application>
- <application>
  <aid>0008</aid> 
- <group>
  <type>06</type> 
  <version>A</version> 
  </group>
  <timeout>1</timeout> 
  <shortmessage>0062</shortmessage>  
  <shortmessage>4689</shortmessage> 
- <odaaccessrights>
- <portaccess>
  <number>1</number> 
  <enabled>1</enabled> 
  </portaccess>
  </odaaccessrights>
  </application>
  </oda>


Ik heb nu de volgende code in m'n XSLT file staan:
code:
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
Bovenaan file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:key name="odaid" match="oda/Row" use="@ODA_ID"/>
<xsl:key name="sm" match="oda/Row" use="@AID"/>
<xsl:template match="/">


In file zelf:

<oda>
<xsl:for-each select="oda/Row[generate-id() = generate-id(key('odaid', @ODA_ID)[1])]">
<application>
<aid><xsl:value-of select="@AID"/></aid>
    <group>
    <type><xsl:value-of select="@GROUP_TYPE"/></type> 
    <version><xsl:value-of select="@GROUP_VERSION"/></version> 
    </group>
    <timeout><xsl:value-of select="@TIMEOUT"/></timeout>
<xsl:for-each select="key('sm', @AID)"> 
    <shortmessage><xsl:value-of select="@SHORT_MESSAGE"/></shortmessage>
</xsl:for-each>
<odaaccessrights>   
    <portaccess>
        <number><xsl:value-of select="@PORT_NR" /></number>
        <enabled><xsl:value-of select="@ACCESS_RIGHT" /></enabled>
    </portaccess>
</odaaccessrights>
</application>
</xsl:for-each> 
</oda>


En dit is wat ik als uitvoer krijg:

code:
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
 <oda>
- <application>
  <aid>CD46</aid> 
- <group>
  <type>08</type> 
  <version>A</version> 
  </group>
  <timeout>2</timeout> 
  <shortmessage>0066</shortmessage> 
  <shortmessage>0066</shortmessage> 
  <shortmessage>6280</shortmessage> 
  <shortmessage>6280</shortmessage> 
- <odaaccessrights>
- <portaccess>
  <number>1</number> 
  <enabled>0</enabled> 
  </portaccess>
  </odaaccessrights>
  </application>
- <application>
  <aid>0008</aid> 
- <group>
  <type>06</type> 
  <version>A</version> 
  </group>
  <timeout>1</timeout> 
  <shortmessage>0062</shortmessage> 
  <shortmessage>0062</shortmessage> 
  <shortmessage>4689</shortmessage> 
  <shortmessage>4689</shortmessage> 
- <odaaccessrights>
- <portaccess>
  <number>1</number> 
  <enabled>1</enabled> 
  </portaccess>
  </odaaccessrights>
  </application>
  </oda>


Het gaat dus om het feit dat shortmessage herhaald word maar het moet dus een unieke waarde zijn. Dit zou dus mbv die key en generate-id functies te doen moeten zijn maar ik krijg het niet voor elkaar. Zoeken op GoT/Google leverde wel wat op, maar niets werkends.

Mijn vraag is dus wat ik moet wijzigen aan met XSLT code om dit werkend te krijgen?

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Gebruik een constructie als
code:
1
2
3
<xsl:if test="not( xxx= preceding-sibling::yyy/xxx)">
  <xsl:value-of select="xxx" />
</xsl:if>


In jouw code wordt het dan iets als
XSLT:
1
2
3
4
5
6
7
<xsl:for-each select="key('sm', @AID)">             
    <xsl:if test="not( @SHORT_MESSAGE= preceding-sibling::Row/@SHORT_MESSAGE)">   
        <shortmessage>
            <xsl:value-of select="@SHORT_MESSAGE"/>
        </shortmessage>
    </xsl:if>                   
</xsl:for-each>

[ Voor 22% gewijzigd door Glimi op 27-05-2005 17:55 ]


  • wizzkizz
  • Registratie: April 2003
  • Laatst online: 19-12-2025

wizzkizz

smile...tomorrow will be worse

Kun je niet mbv SELECT DISTINCT in je sql-query voorkomen dat die dubbele waarden uberhaupt in je XML komen?
lijkt mij de gemakkelijkste manier.

Make it idiot proof and someone will make a better idiot.
Real programmers don't document. If it was hard to write, it should be hard to understand.


  • SouLmaN
  • Registratie: Juli 2001
  • Laatst online: 06-05 16:34
Glimi schreef op vrijdag 27 mei 2005 @ 17:54:
Gebruik een constructie als
code:
1
2
3
<xsl:if test="not( xxx= preceding-sibling::yyy/xxx)">
  <xsl:value-of select="xxx" />
</xsl:if>


In jouw code wordt het dan iets als
XSLT:
1
2
3
4
5
6
7
<xsl:for-each select="key('sm', @AID)">             
    <xsl:if test="not( @SHORT_MESSAGE= preceding-sibling::Row/@SHORT_MESSAGE)">   
        <shortmessage>
            <xsl:value-of select="@SHORT_MESSAGE"/>
        </shortmessage>
    </xsl:if>                   
</xsl:for-each>
Gedaan en werkt ook, maar ik krijg nog steeds dezelfde waardes terug als in mijn startpost. Ligt er volgens mij aan dat het AID wel bij alle 4 de resultaten die ik krijg hetzelfde is.
wizzkizz schreef op vrijdag 27 mei 2005 @ 23:38:
Kun je niet mbv SELECT DISTINCT in je sql-query voorkomen dat die dubbele waarden uberhaupt in je XML komen?
lijkt mij de gemakkelijkste manier.
Ik gebruik DISTINCT ook, maar omdat PORT_NR toch voor 2 poorten moet komt elke SHORT_MESSAGE 2x voor in het resultaat van de query.

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
SouLmaN schreef op donderdag 09 juni 2005 @ 09:09:
Gedaan en werkt ook, maar ik krijg nog steeds dezelfde waardes terug als in mijn startpost. Ligt er volgens mij aan dat het AID wel bij alle 4 de resultaten die ik krijg hetzelfde is.
Ik kijk er even vanavond naar.

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
SouLmaN schreef op donderdag 09 juni 2005 @ 09:09:
Gedaan en werkt ook, maar ik krijg nog steeds dezelfde waardes terug als in mijn startpost. Ligt er volgens mij aan dat het AID wel bij alle 4 de resultaten die ik krijg hetzelfde is.
Het heeft even iets langer geduurd, maar ok ;) Ik snap je niet helemaal. Ik krijg de volgende output
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
<?xml version="1.0" encoding="UTF-8"?>
<oda>
    <application>
        <aid>CD46</aid>
        <group>
            <type>08</type>
            <version>A</version>
        </group>
        <timeout>2</timeout>
        <shortmessage>0066</shortmessage>
        <shortmessage>6280</shortmessage>
        <odaaccessrights>
            <portaccess>
                <number>1</number>
                <enabled>0</enabled>
            </portaccess>
        </odaaccessrights>
    </application>
    <application>
        <aid>0008</aid>
        <group>
            <type>06</type>
            <version>A</version>
        </group>
        <timeout>1</timeout>
        <shortmessage>0062</shortmessage>
        <shortmessage>4689</shortmessage>
        <odaaccessrights>
            <portaccess>
                <number>1</number>
                <enabled>1</enabled>
            </portaccess>
        </odaaccessrights>
    </application>
</oda>

Wat volgens mij 100% overeenkomt met je gegeven gewenste output.
Daarvoor heb ik deze XSLT gebruikt
XSLT:
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
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="odaid" match="oda/Row" use="@ODA_ID"/>
    <xsl:key name="sm" match="oda/Row" use="@AID"/>
    <xsl:template match="/">
        <oda>
            <xsl:for-each select="oda/Row[generate-id() = generate-id(key('odaid', @ODA_ID)[1])]">
                <application>
                    <aid>
                        <xsl:value-of select="@AID"/>
                    </aid>
                    <group>
                        <type>
                            <xsl:value-of select="@GROUP_TYPE"/>
                        </type>
                        <version>
                            <xsl:value-of select="@GROUP_VERSION"/>
                        </version>
                    </group>
                    <timeout>
                        <xsl:value-of select="@TIMEOUT"/>
                    </timeout>
                    <xsl:for-each select="key('sm', @AID)">
                        <xsl:if test="not( @SHORT_MESSAGE= preceding-sibling::Row/@SHORT_MESSAGE)">
                            <shortmessage>
                                <xsl:value-of select="@SHORT_MESSAGE"/>
                            </shortmessage>
                        </xsl:if>
                    </xsl:for-each>
                    <odaaccessrights>
                        <portaccess>
                            <number>
                                <xsl:value-of select="@PORT_NR"/>
                            </number>
                            <enabled>
                                <xsl:value-of select="@ACCESS_RIGHT"/>
                            </enabled>
                        </portaccess>
                    </odaaccessrights>
                </application>
            </xsl:for-each>
        </oda>
    </xsl:template>
</xsl:stylesheet>


Kun jij me vertellen wat nou niet goed werkt en hoe je het dan precies wel wilt hebben, incl voorbeeld graag (dat maakt vaak een hoop duidelijk)

Verwijderd

SouLmaN schreef op donderdag 09 juni 2005 @ 09:09:
Ik gebruik DISTINCT ook, maar omdat PORT_NR toch voor 2 poorten moet komt elke SHORT_MESSAGE 2x voor in het resultaat van de query.
toch je query aanpassen. Dit is logica in je view stoppen en domweg teveel data overpompen (en dat twee keer)

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Kijk ook eens naar fn:distinct-values()

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
chris schreef op vrijdag 10 juni 2005 @ 13:34:
Kijk ook eens naar fn:distinct-values()
Da's XPath 2 en XSLT 2, dus als de TS die niet gebruikt, dan gaat het niet werken.

[ Voor 17% gewijzigd door Glimi op 10-06-2005 14:05 ]

Pagina: 1