Announcement

Collapse
No announcement yet.

Elemente gruppieren über XSLT bzw. XPath

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Elemente gruppieren über XSLT bzw. XPath

    Hallo Forum,

    habe ein Problem mit der Gruppierung von Knoten.

    <ROOT>
    <ELEMENT>
    <TITEL>Überschrift</TITEL>
    <INHALT>Inhaltsangabe</INHALT>
    </ELEMENT>
    <ELEMENT>
    <TITEL>Kapitel</TITEL>
    <INHALT>Inhaltsangabe</INHALT>
    </ELEMENT>
    <ELEMENT>
    <TITEL>Kapitel</TITEL>
    <INHALT>Inhaltsangabe</INHALT>
    </ELEMENT>
    <ELEMENT>
    <TITEL>Überschrift</TITEL>
    <INHALT>Inhaltsangabe</INHALT>
    </ELEMENT>
    </ROOT>

    Mache dann eine Schleife um die Überschriften herauszufiltern mit:

    <xsl:for-each select="ROOT/ELEMENT[TITEL='Überschrift']">

    Als nächsten Schritt würde ich gerne die nachfolgenden ELEMENTE-Elemente mit TITEL="Kapitel" zusammenfassen. Sprich bis zum nächsten TITEL="Überschrift".

    Auf den folgenden Knoten kann ich ja auch zugreifen mit:

    <xsl:if test="/ROOT/ELEMENT/following-sibling::ELEMENT/TITEL='Kapitel'">

    Aber wie kann ich jetzt auf die folgenden Knoten zugreifen, bis sich der Titel wieder ändert?

    Bräuchte eine Art "break" aus PHP, um eine Schleife abzubrechen.

    Danke für eure Hilfe

    Stryke

  • #2
    XSLT 2.0 oder 1.0? Mit XSLT 2.0 solltest du einfach for-each-group select="/ROOT/ELEMENT" group-starting-with="ELEMENT[TITEL='Überschrift']" benutzen.
    Mit 1.0 ist das komplizierter, erzähl uns erst mal, welche Version du benutzt.

    Comment


    • #3
      Xslt 1.0

      Hi Martin,

      natürlich leider XSLT 1.0 :-(

      Möchte gerne aus dem gelieferten XML-File alle TITEL=Überschrift in eine Tabelle packen, in der dann innerhalb wieder eine Tabelle aufgebaut wird, in der sämtliche TITEL=Kapitel zusammengefasst werden.

      Und das ganze dann bis zum nächsten TITEL=Überschrift.

      Also ungefähr so:

      <table width="100%" border="1" cellspacing="0" cellpadding="0">
      <tr>
      <td colspan="2">Überschrift</td>
      </tr>
      <tr>
      <td>Hier kommt das Cover rein</td>
      <td valign="top"><table align ="top" width="100%" border="1" cellpadding="0" cellspacing="0">
      <tr>
      <td>Kapitel</td>
      <td>Inhalte</td>
      </tr>
      <tr>
      <td>Kapitel</td>
      <td>Inhalte</td>
      </tr>
      usw....

      </table></td>
      </tr>
      <tr>
      <td colspan="2">Überschrift</td>
      </tr>
      <tr>
      <td>Hier kommt das Cover rein</td>
      <td valign="top"><table align ="top" width="100%" border="1" cellpadding="0" cellspacing="0">
      <tr>
      <td>Kapitel</td>
      <td>Inhalte</td>
      </tr>
      usw....

      </table></td>
      </tr>
      </table>

      Wäre klasse, wenn Du eine Ahnung hättest. ;-)

      Lieben Gruß

      Stryke

      Comment


      • #4
        Auch mit XSLT 1.0 schlage ich vor, dass als Gruppierung anzupacken, dann halt per key:
        Code:
        <xsl:stylesheet
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
          version="1.0">
          
          <xsl:output method="html" indent="yes"/>
          
          <xsl:key name="k1" match="ELEMENT[TITEL = 'Kapitel']" use="generate-id(preceding-sibling::ELEMENT[TITEL = 'Überschrift'][1])"/>
          
          <xsl:template match="ROOT">
            <table width="100%" border="1" cellspacing="0" cellpadding="0">
              <tbody>
                <xsl:apply-templates select="ELEMENT[TITEL = 'Überschrift']"/>
              </tbody>
            </table>
          </xsl:template>
          
          <xsl:template match="ELEMENT[TITEL = 'Überschrift']">
            <tr>
              <td colspan="2"><xsl:value-of select="TITEL"/></td>
            </tr>
            <tr>
              <td>...</td>
              <td>
                <table align ="top" width="100%" border="1" cellpadding="0" cellspacing="0">
                  <tbody>
                    <xsl:apply-templates select="key('k1', generate-id())"/>
                  </tbody>
                </table>
              </td>
            </tr>
          </xsl:template>
          
          <xsl:template match="ELEMENT[TITEL = 'Kapitel']">
            <tr>
              <td><xsl:value-of select="TITEL"/></td>
              <td><xsl:value-of select="INHALT"/></td>
            </tr>
          </xsl:template>
        
        </xsl:stylesheet>

        Comment


        • #5
          Hallo Martin,

          schon mal ein ganz lieben Dank für Deine Hilfe!!!

          Funktioniert soweit auch ganz gut.

          Das einzige was mir noch Probleme bereitet ist die Sortierung der Kapitel.

          Du springst doch vom ersten "Überschrift" zur nächsten "Überschrift" und arbeitest Dich dann rückwärts zurück durch die Kapitel, oder?

          Dadurch müsste ja eigentlich die Liste der Kapitel auch verkehrt herum sein.

          Also:

          Überschrift
          - Titel 4
          - Titel 3
          - Titel 2
          - Titel 1

          Teilweise mach er es auch so.
          Ich habe aber bei einem Abschnitt mit 8 Kapiteln komischerweise folgende Ausgabe:

          Überschrift
          - Titel 3
          - Titel 1
          - Titel 2
          - Titel 6
          - Titel 7
          - Titel 8
          - Titel 5
          - Titel 4

          Hast Du eine Ahnung wie diese Sortierung zustandekommt? Es ist weder nach der Stelle im XML-File, noch alphabetisch nach Titel oder Beschreibung sortiert.

          Besten Gruß

          Stryke

          Comment


          • #6
            Zu der Sortierung der Kapitel ist mir gerade was aufgefallen:

            - Benutze ich eine lokale XML und XSL-Datei ist die Sortierung der Kapitel vollkommen in Ordnung.

            - Setze ich das dagegen in Dreamweaver in eine neue new MM_XSLTransform(); um die entfernte XML-Datei auszuwerten, ist die Sortierung durcheinander.

            Also scheint doch der Fehler in der MM_XSLTransform.class.php von Dreamweaver zu liegen, oder?

            Besten Gruß

            Stryke

            Comment


            • #7
              Sowohl die Ausgabe der Überschriften als auch der Kapitel sollte in der Reihenfolge erfolgen, die im Eingabedokument vorgegeben ist.
              Das funktioniert bei mir mit Saxon 6.5.5. auch.
              Eingabe ist
              Code:
              <ROOT>
                <ELEMENT>
                  <TITEL>Überschrift</TITEL>
                  <INHALT>Inhaltsangabe 1</INHALT>
                </ELEMENT>
                <ELEMENT>
                  <TITEL>Kapitel</TITEL>
                  <INHALT>Inhaltsangabe 1.1</INHALT>
                </ELEMENT>
                <ELEMENT>
                  <TITEL>Kapitel</TITEL>
                  <INHALT>Inhaltsangabe 1.2</INHALT>
                </ELEMENT>
                <ELEMENT>
                  <TITEL>Überschrift</TITEL>
                  <INHALT>Inhaltsangabe 2</INHALT>
                </ELEMENT>
                <ELEMENT>
                  <TITEL>Kapitel</TITEL>
                  <INHALT>Inhaltsangabe 2.1</INHALT>
                </ELEMENT>
                <ELEMENT>
                  <TITEL>Kapitel</TITEL>
                  <INHALT>Inhaltsangabe 2.2</INHALT>
                </ELEMENT>
                <ELEMENT>
                  <TITEL>Kapitel</TITEL>
                  <INHALT>Inhaltsangabe 2.3</INHALT>
                </ELEMENT>
              </ROOT>
              XSLT:
              Code:
              <xsl:stylesheet
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">
                
                <xsl:output method="html" indent="yes"/>
                
                <xsl:key name="k1" match="ELEMENT[TITEL = 'Kapitel']" use="generate-id(preceding-sibling::ELEMENT[TITEL = 'Überschrift'][1])"/>
                
                <xsl:template match="ROOT">
                  <table width="100%" border="1" cellspacing="0" cellpadding="0">
                    <tbody>
                      <xsl:apply-templates select="ELEMENT[TITEL = 'Überschrift']"/>
                    </tbody>
                  </table>
                </xsl:template>
                
                <xsl:template match="ELEMENT[TITEL = 'Überschrift']">
                  <tr>
                    <td colspan="2"><xsl:value-of select="TITEL"/></td>
                  </tr>
                  <tr>
                    <td><xsl:value-of select="INHALT"/></td>
                    <td>
                      <table align ="top" width="100%" border="1" cellpadding="0" cellspacing="0">
                        <tbody>
                          <xsl:apply-templates select="key('k1', generate-id())"/>
                        </tbody>
                      </table>
                    </td>
                  </tr>
                </xsl:template>
                
                <xsl:template match="ELEMENT[TITEL = 'Kapitel']">
                  <tr>
                    <td><xsl:value-of select="TITEL"/></td>
                    <td><xsl:value-of select="INHALT"/></td>
                  </tr>
                </xsl:template>
              
              </xsl:stylesheet>
              Ausgabe
              Code:
              <table width="100%" border="1" cellspacing="0" cellpadding="0">
                 <tbody>
                    <tr>
                       <td colspan="2">&Uuml;berschrift</td>
                    </tr>
                    <tr>
                       <td>Inhaltsangabe 1</td>
                       <td>
                          <table align="top" width="100%" border="1" cellpadding="0" cellspacing="0">
                             <tbody>
                                <tr>
                                   <td>Kapitel</td>
                                   <td>Inhaltsangabe 1.1</td>
                                </tr>
                                <tr>
                                   <td>Kapitel</td>
                                   <td>Inhaltsangabe 1.2</td>
                                </tr>
                             </tbody>
                          </table>
                       </td>
                    </tr>
                    <tr>
                       <td colspan="2">&Uuml;berschrift</td>
                    </tr>
                    <tr>
                       <td>Inhaltsangabe 2</td>
                       <td>
                          <table align="top" width="100%" border="1" cellpadding="0" cellspacing="0">
                             <tbody>
                                <tr>
                                   <td>Kapitel</td>
                                   <td>Inhaltsangabe 2.1</td>
                                </tr>
                                <tr>
                                   <td>Kapitel</td>
                                   <td>Inhaltsangabe 2.2</td>
                                </tr>
                                <tr>
                                   <td>Kapitel</td>
                                   <td>Inhaltsangabe 2.3</td>
                                </tr>
                             </tbody>
                          </table>
                       </td>
                    </tr>
                 </tbody>
              </table>
              Keine Ahnung, warum da mit Dreamweaver eine andere, zufällige Reihenfolge herauskommt.

              Comment


              • #8
                Habe jetzt leider schon 3 Tests durchlaufen lassen, wo beim Aufruf der XML-Datei im Browser die Sortierung richtig dargestellt wird, und sobald die Transformation über Dreamweaver erfolgt funktioniert es nicht mehr richtig! :-(

                Leider lässt sich bei Dreamweaver auch überhaupt kein Muster erkennen, wonach er die <tr>'s erstellen könnte.

                Habe auch schon überlegt, ob man die zwischen 2 Überschriften enthaltenen Kapitel nicht zwischenspeichern und über <xsl:sort> wieder in die richtige Reihenfolge bringen könnte.
                Aber das übersteigt dann doch meine Fähigkeiten! ;-)

                Aber zumindest habe ich Dank Dir wieder eine ganze Menge gelernt! ;-)

                Lieben Gruß

                Stryke

                Comment


                • #9
                  Habe jetzt mal extra das Beispiel von http://www.jenitennison.com/xslt/gro...muenchian.html in Dreamweaver nachgebaut um zu schauen, ob der Prozessor von Dreamweaver überhaupt vollständig mit der Muenchian Methode umgehen kann.

                  Funktionert leider in Dreamweaver. Daran kann es also auch nicht liegen! :-(

                  Comment


                  • #10
                    Hallo Martin,

                    ich hoffe, dass ich nicht zu aufdringlich bin.
                    Habe inzwischen gesehen, dass die gelieferte XML-Datei zwischen dem <ROOT> und dem ersten <ELEMENT> noch 2 neue, weitere Knoten hat.


                    <ROOT>
                    <SEITE>Sachbücher</SEITE>
                    <ANZAHL>3604452</ANZAHL>

                    <ELEMENT>
                    <TITEL>Überschrift</TITEL>
                    <INHALT>Inhaltsangabe</INHALT>
                    </ELEMENT>
                    <ELEMENT>
                    <TITEL>Kapitel</TITEL>
                    <INHALT>Inhaltsangabe</INHALT>
                    </ELEMENT>

                    Komischerweise scheinen diese zusätzlichen Knoten sich auf die Sortierung auszuwirken.
                    Leider verstehe ich die Zeile

                    <xsl:key name="k1" match="ELEMENT[TITEL = 'Kapitel']" use="generate-id(preceding-sibling::ELEMENT[TITEL = 'Überschrift'][1])"/>

                    noch nicht hundertprozentig um nachvollziehen zu können, inwieweit sich das auswirken könnte.

                    Wäre klasse, wenn Du mir nochmal kurz helfen könntest! ;-)

                    Besten Gruß

                    Stryke

                    Comment


                    • #11
                      Die xsl: key Anweisung sagt dem XSLT-Prozessor, dass wir uns für dem match-Muster entsprechende Knoten, als für Elemente mit dem Namen ELEMENT und dem Kindselement TITEL mit Wert 'Kapitel' interessieren, und zwar soll für diese Elemente der Wert generate-id(preceding-sibling::ELEMENT[TITEL = 'Überschrift'][1]) berechnet werden und die Elemente sollen unter diesem Wert indiziert werden, so dass ein effizienter Zugriff möglich ist.
                      Es wird also für die Elemente die generierte id des ersten vorhergehenden ELEMENT[TITEL = 'Überschrift'] berechet und dann kann über diese id auf alle entsprechenden Elemente zugegriffen werden. Damit können dann bei der Verarbeitung eines ELEMENT[TITEL = 'Überschrift'] direkt alle darauf folgenden ELEMENT[TITEL = 'Kapitel'] Elemente einfach per key('k1', generate-id()) ermittelt werden.

                      Warum andere Elemente, auf die die verwendeten Muster nicht zutreffen, auf die Verarbeitung oder Sortierung eine Auswirking haben sollen, sehe ich so nicht.

                      Wenn doch, dann poste bitte minimale aber komplette Beispiele, die das demonstrieren, also XML-Eingabe, XSLT-Stylesheet, und die Ausgabe, die du haben willst, und die, die du bekommst. Dann erwähne auch, welchen XSLT-Prozessor du benutzt.

                      Comment


                      • #12
                        Hi Martin,

                        habe Dir jetzt mal die Beispiele online gestellt:

                        http://www.telereisen.com/test1/angebote.xml

                        Das dazugehörige Stylesheet:

                        http://www.telereisen.com/test1/angebote2.xsl

                        Hier funktioniert alles, wenn man die XML aufruft.

                        Dann habe ich das ganze einfach mal in Dreamweaver in eine PHP gepackt mit dem XSLT-Prozessor von Dreamweaver:

                        http://www.telereisen.com/test1/test1.php

                        Hier der Quellcode der PHP-Seite:

                        <?php
                        require_once('includes/MM_XSLTransform/MM_XSLTransform.class.php');

                        $mm_xsl = new MM_XSLTransform();
                        $mm_xsl->setXML("angebote.xml");
                        $mm_xsl->setXSL("angebote2.xsl");
                        echo $mm_xsl->Transform();
                        ?>

                        Also wenn Du da einen Fehler findest gibt es ein dickes Bier!!! ;-)

                        Lieben Gruß

                        Stryke

                        Comment


                        • #13
                          Welche PHP-Version ist das? PHP 5 benutzt doch libxslt als XSLT-Prozessor? Was passiert denn, wenn du die API http://www.php.net/manual/en/book.xsl.php benutzt?

                          Comment

                          Working...
                          X