XSLT Wordcount - doppelte Elementinhalte zählen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • XSLT Wordcount - doppelte Elementinhalte zählen

    Hallo!
    Bin neu hier und habe ein wichtige Frage...
    Hab folgende XML Datei:

    Quellcode

    1. <haus>
    2. <bereich>Wohnzimmer</bereich>
    3. <bereich>Wohnzimmer</bereich>
    4. <bereich>Wohnzimmer</bereich>
    5. <bereich>Wohnzimmer</bereich>
    6. <bereich>Wohnzimmer</bereich>
    7. <bereich>Schlafzimmer</bereich>
    8. <bereich>Küche</bereich>
    9. <bereich>Küche</bereich>
    10. <bereich>Küche</bereich>
    11. <bereich>Küche</bereich>
    12. <bereich>WC</bereich>
    13. </haus>
    Alles anzeigen


    und will das hier mit xsl ausgeben:

    -Bereich Wohnzimmer (Anzahl: 5)
    -Bereich Schlafzimmer (Anzahl: 1)
    -Bereich Küche (Anzahl: 4)
    -Bereich WC(Anzahl: 1)

    Probleme:
    - Jeden Bereich nur 1x ausgeben
    - Die Anzahl anzeigen

    Hab schon alles probiert und bin ziemlich verzweifelt! :)
    Bitte um Hilfe!!

    casbar
  • Wenn du die Liste sortierst, kannst du immer mit dem vorherigen Knoten vergleichen. So kommst auf auf die eine eindeutige Liste.
    Das Zählen musst du noch implementieren. Ich hab mal eine Strichliste gemacht ;)

    Quellcode

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    3. <xsl:template match="/">
    4. <html><body>
    5. <xsl:for-each select="/haus/bereich">
    6. <xsl:sort select="." />
    7. <xsl:choose>
    8. <xsl:when test="not(preceding-sibling::bereich = .)">
    9. <xsl:value-of select="." />
    10. </xsl:when>
    11. <xsl:otherwise>
    12. <xsl:text>|</xsl:text>
    13. </xsl:otherwise>
    14. </xsl:choose>
    15. </xsl:for-each>
    16. </body></html>
    17. </xsl:template>
    18. </xsl:stylesheet>
    Alles anzeigen
  • Ich habe ein ähnliches Problem. und zwar müsste ich die unterschiedlichen belongsto zählen, irgendwie stehe ich aber auf dem Schlauch. Mit dem Code aus dem zweiten Post schaffe ich dass er mir folgendes ausgibt: 1111222
    Warum aber schreibt er nie den senkrechten Strich, das sollte er doch machen um die Einträge voneinander zu trennen oder?? also eigentlich sollte das so aussehen: 1111|222 -> oder irre ich mich da??

    Was ich gerne haben würde ist "4: 1er 3: 2er".

    XSLT File:

    Quellcode

    1. <xsl:for-each select="//belongsto">
    2. <xsl:sort select="." />
    3. <xsl:choose>
    4. <xsl:when test="not(preceding-sibling::belongsto = .)">
    5. <xsl:value-of select="." />
    6. </xsl:when>
    7. <xsl:otherwise>
    8. <xsl:text>|</xsl:text>
    9. </xsl:otherwise>
    10. </xsl:choose>
    11. </xsl:for-each>
    Alles anzeigen

    XML File:

    Quellcode

    1. <config>
    2. <linelist>
    3. <line id="1">
    4. 239.24.24.13
    5. </line>
    6. <line id="2">
    7. 239.24.24.24
    8. </line>
    9. </linelist>
    10. <routerlist>
    11. <router id="1" promiscuous="on">
    12. <belongsto>1</belongsto>
    13. <belongsto>2</belongsto>
    14. <in>1/2/2</in>
    15. </router>
    16. </routerlist>
    17. <devicelist>
    18. <device id="1" promiscuous="on">
    19. <belongsto>1</belongsto>
    20. <inout>1/2/2</inout>
    21. </device>
    22. <device id="2" promiscuous="on">
    23. <belongsto>1</belongsto>
    24. <inout>1/2/2</inout>
    25. <inout>1/1/2</inout>
    26. </device>
    27. <device id="3" promiscuous="on">
    28. <belongsto>2</belongsto>
    29. <inout>1/2/2</inout>
    30. <inout>1/1/2</inout>
    31. </device>
    32. <device id="4" promiscuous="off">
    33. <belongsto>2</belongsto>
    34. <inout>1/1/2</inout>
    35. </device>
    36. <device id="5" promiscuous="off">
    37. <belongsto>1</belongsto>
    38. <inout>1/1/2</inout>
    39. </device>
    40. </devicelist>
    41. </config>
    Alles anzeigen
  • Die Striche sollen eigentlich als Zähler dienen. Aber bei dir klappt das zählen nicht.
    preceding-sibling::belongsto hat keinen Wert. Probier mal ihn auszugeben:

    Quellcode

    1. <xsl:when test="not(preceding-sibling::belongsto = .)">
    2. <br/><xsl:value-of select="preceding-sibling::belongsto" />:
    3. </xsl:when>


    Ich glaube du du musst noch über parent eine Ebene zurückgehen. Dann kannst du jedoch nicht mehr mit preceding-sibling arbeiten, sondern musst vermutlich die position() nutzen...
    Hab spontan auch keine Idee und muss gleich offline.
    Experimentier mal noch ein wenig, ansonsten schau ich es mir morgen Abend nochmal an.
  • So hab jetzt etwas herumgespielt (etwas lange) und bin bis hierher gekommen:

    Quellcode

    1. <xsl:for-each select="distinct-values(//belongsto)">
    2. <xsl:value-of select="." /> <xsl:text>. </xsl:text>
    3. <xsl:value-of select="count(//belongsto[self::belongsto = .])"/>
    4. <xsl:text> Eintraege </xsl:text>
    5. </xsl:for-each>

    Warum aber funktioniert Zeile 3 nicht?? (übrigens, ich verwende: saxonsa9-1-0-6n)

    Quellcode

    1. Error at xsl:template on line 5 column 15 of trans02.xsl:
    2. XPTY0020: Cannot select a node here: the context item is an atomic value
    3. Failed to compile stylesheet. 1 error detected.

    Hab dazu im Internet folgendes gefunden: stylusstudio.com/xsllist/200510/post40440.html
    xpty0020:
    Because "absolute paths" are not absolute at all: they select relative to
    the root of the tree containing the context node. You've got to know which
    document to look in.

    Was bedeutet das ?( Was muss ich ändern damit mein Code funktioniert?

    ------------------------------------
    Habe jetzt noch folgendes probiert, da ich mich schlau gemacht habe was es da mit den absoluten Pfade auf sich haben könnte.

    Quellcode

    1. <xsl:for-each select="distinct-values(//belongsto)">
    2. <xsl:value-of select="." /> <xsl:text>. </xsl:text>
    3. <xsl:value-of select="count(ancestor::belongsto[self::belongsto = .])"/>
    4. <xsl:text> Eintraege </xsl:text>
    5. </xsl:for-each>

    Worauf ich einen neuen Fehler bekomme:

    Quellcode

    1. XPTY0020: Axis step ancestor::element(belongsto, xs:anyType) cannot be used here: the
    2. context item is an atomic value
    3. Failed to compile stylesheet. 1 error detected.

    Nun weiß ich wirklich nicht mehr weiter. ;(

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Apfelstrudl ()

  • hallo unbekannter Weisse

    benutze Key

    Quellcode

    1. <?xml version="1.0"?>
    2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    3. <xsl:output method="html" indent="yes"/>
    4. <xsl:key name="only" match="//bereich" use="."/>
    5. <xsl:template match="/">
    6. <table border="solid black 2px">
    7. <tr><th>Bereich</th><th>Anzahl</th></tr>
    8. <xsl:apply-templates select="haus"/>
    9. </table>
    10. </xsl:template>
    11. <xsl:template match="haus">
    12. <xsl:for-each select="bereich[generate-id()= generate-id(key('only', .)[1])]">
    13. <tr>
    14. <td>
    15. <!--<xsl:for-each select="bereich">-->
    16. <xsl:value-of select="."/>
    17. </td>
    18. <td>
    19. <xsl:value-of select="count(key('only',.))"/>
    20. </td>
    21. </tr>
    22. </xsl:for-each>
    23. </xsl:template>
    24. </xsl:stylesheet>
    Alles anzeigen



    ergebis

    Quellcode

    1. <table border="solid black 2px">
    2. <tr>
    3. <th>Bereich</th>
    4. <th>Anzahl</th>
    5. </tr>
    6. <tr>
    7. <td>Wohnzimmer</td>
    8. <td>5</td>
    9. </tr>
    10. <tr>
    11. <td>Schlafzimmer</td>
    12. <td>1</td>
    13. </tr>
    14. <tr>
    15. <td>Küche</td>
    16. <td>4</td>
    17. </tr>
    18. <tr>
    19. <td>WC</td>
    20. <td>1</td>
    21. </tr>
    22. </table>
    Alles anzeigen


    Helmut Hagemann
    Helmut Hagemann
    Derjenige, der sagt: Das geht nicht, soll den nicht stören, der's gerade tut.
  • für den Fall belongto

    Quellcode

    1. <?xml version="1.0"?>
    2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    3. <xsl:output indent="yes" method="html"/>
    4. <xsl:key name="only" match="//belongsto" use="."/>
    5. <xsl:template match="/">
    6. <html>
    7. <table>
    8. <tr>
    9. <th>belongto</th>
    10. <th>nr</th>
    11. </tr>
    12. <xsl:apply-templates select="config"/>
    13. </table>
    14. </html>
    15. </xsl:template>
    16. <xsl:template match="config">
    17. <xsl:for-each select="child::*//belongsto[generate-id()= generate-id(key('only', .)[1])]">
    18. <tr>
    19. <td>
    20. <xsl:value-of select="."/>
    21. </td>
    22. <td>
    23. <xsl:value-of select="count(key('only',.))"/>
    24. </td>
    25. </tr>
    26. </xsl:for-each>
    27. </xsl:template>
    28. </xsl:stylesheet>
    Alles anzeigen


    Quellcode

    1. <html>
    2. <table>
    3. <tr>
    4. <th>belongto</th>
    5. <th>nr</th>
    6. </tr>
    7. <tr>
    8. <td>1</td>
    9. <td>4</td>
    10. </tr>
    11. <tr>
    12. <td>2</td>
    13. <td>3</td>
    14. </tr>
    15. </table>
    16. </html>
    Alles anzeigen


    Helmut Hagemann
    Helmut Hagemann
    Derjenige, der sagt: Das geht nicht, soll den nicht stören, der's gerade tut.
  • nur für Apfelstrudl

    Hallo Apfelstrudl

    hat ein wenig länger gedauert virus in meinen System


    HTML-Quellcode

    1. <?xml version="1.0"?>
    2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    3. <xsl:output method="html" indent="yes"/>
    4. <xsl:template match="/">
    5. <html>
    6. <body>
    7. <h2>My Router</h2>
    8. <xsl:variable name="only" select="//belongsto[not(text()=preceding::belongsto/text())]"/>
    9. <table border="solid 2px black">
    10. <tr>
    11. <th>Anschluß</th>
    12. <th>Anzahl</th>
    13. </tr>
    14. <xsl:for-each select="$only">
    15. <xsl:variable name="wert" select="string(.)"/>
    16. <tr>
    17. <td>
    18. <xsl:value-of select="."/>
    19. </td>
    20. <td>
    21. <xsl:value-of name="all" select="count(//belongsto[.=$wert])"/>
    22. </td>
    23. </tr>
    24. </xsl:for-each>
    25. </table>
    26. </body>
    27. </html>
    28. </xsl:template>
    29. </xsl:stylesheet>
    Alles anzeigen

    nach meiner Meinung sind die Predikate von Xpath die besten Filter

    der Umgang mit Achsen ist durch viel übenung zufinden
    zur bildlichen Anschauung benutzte ich selfhtml
    de.selfhtml.org/xml/darstellung/xpathsyntax.htm

    Helmut Hagemann
    Helmut Hagemann
    Derjenige, der sagt: Das geht nicht, soll den nicht stören, der's gerade tut.
  • Hallo!

    Danke genau das wollte ich. (In Zeile 21 hast du noch einen kleine Fehler: dort gehört:

    Quellcode

    1. <xsl:value-of select="count(//belongsto[.=$wert])"/>

    also ohne name="all")

    was ich mich aber eigentlich frage ist: wo ist der Unterschied zwischen:

    Quellcode

    1. <xsl:variable name="only" select="distinct-values(//belongsto)"/>

    und

    Quellcode

    1. <xsl:variable name="only" select="//belongsto[not(text()=preceding::belongsto/text())]"/>


    weil wenn ich meine Zeile in deinem Code verwende, funktioniert das ganze nämlich nicht. Und ich würde gerne wissen warum?
    Was macht distinct-values genau. Eigentlich sollte es ja genau das selbe machen wie deine Zeile. Aber eben nicht ganz das gleich denn sonst würde mein Code ja auch funktionieren und das tut er eben nicht.

    Ps.:
    dank dir sieht meine aktuelle Lösung so aus (habe noch rausgefunden das man den Textvergleich gar nicht braucht, oder sollte man diesen besser drinnen lassen?) :

    Quellcode

    1. <?xml version="1.0"?>
    2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    3. <xsl:output method="html" indent="yes"/>
    4. <xsl:template match="/">
    5. <html>
    6. <body>
    7. <h2>My Router</h2>
    8. <table border="solid 2px black">
    9. <tr>
    10. <th>Anschluss</th>
    11. <th>Anzahl</th>
    12. </tr>
    13. <xsl:for-each select="//belongsto[not(preceding::belongsto = .)]">
    14. <xsl:variable name="wert" select="string(.)"/>
    15. <tr>
    16. <td>
    17. <xsl:value-of select="."/>
    18. </td>
    19. <td>
    20. <xsl:value-of select="count(//belongsto[.=$wert])"/>
    21. </td>
    22. </tr>
    23. </xsl:for-each>
    24. </table>
    25. </body>
    26. </html>
    27. </xsl:template>
    28. </xsl:stylesheet>
    Alles anzeigen

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Apfelstrudl ()

  • ich benutze text() damit ich sehe was ich vergleiche

    nach anderen projekten vergisst man sehr viel

    wo eigentlich das problem lag


    ich benutze wegen den Browser (die nur xpath version 1 beherrschen)

    xpath 2 nicht vielleicht liegt es am namespace fn:

    w3.org/TR/xpath-functions/#func-distinct-values


    Danke genau das wollte ich. (In Zeile 21 hast du noch einen kleine Fehler: dort gehört:

    <xsl:value-of select="count(//belongsto[.=$wert])"/>

    also ohne name="all")


    bei kopieren (copy past) passieren solche dinge
    Helmut Hagemann
    Helmut Hagemann
    Derjenige, der sagt: Das geht nicht, soll den nicht stören, der's gerade tut.