droom: XSL erzeugen

Ich habe einige Probleme mit XSL. Also ich habe diese xml Datei:

<start>
   <page id="#2">
    <text id="#3">
     <const>Link 2</const>
     <link>#5</link>
    </text>
   </page>
   <page id="#5">
    <text id="#6">
     <const>Link 1</const>
     <link>#2</link>
    </text>
   </page>
 </start>

Das Ergebnis soll 2 Seiten, die miteinander verknüpft sind. Wenn man vom ersten Seite auf dem "Link 2" klickt, kommt man auf der zweiten Seite, wo man wiederum auf "Link 1" klicken kann, um auf der ersten Seite zu gelangen. Ich komme nicht auf eine geeignete XSL Datei dafür.
Wer kann mir helfen?
Super vielen Dank im Voraus.

  1. Hallo,

    Ich habe einige Probleme mit XSL. Also ich habe diese xml Datei:

    Das Ergebnis soll 2 Seiten, die miteinander verknüpft sind. Wenn man vom ersten Seite auf dem "Link 2" klickt, kommt man auf der zweiten Seite, wo man wiederum auf "Link 1" klicken kann, um auf der ersten Seite zu gelangen. Ich komme nicht auf eine geeignete XSL Datei dafür.
    Wer kann mir helfen?

    Ich habe dazu Rückfragen:
     - geht es um HTML-Seiten oder PDF?
     - Falls HTML: wird die XML/XSL-Transformation am Server oder im Browser ausgeführt?
     - Falls am Server: sollen zwei HTML-Dateien erzeugt werden? (dann brauchst du nämlich entweder einen XSLT 2.0 fähigen Prozessor oder einen der EXSLT-Erweiterungen für XSLT 1.0 unterstützt.)

    Grüße
    Thomas

    1. Hi Thomas!

      Nee die Seiten werden nicht generiert. Diese XML Datei ist halt als Inhalt in einem CMS anzusehen. Die Anbindung ist schon implementiert und funktionniert.
      Nur für diese XML Datei, hätte ich gern die passende XSL schreiben, so dass die Darstellung HTML Konform ist.
      Also ich möchte auf der Seite 1 dieses:
      <a href="#5">Link 2</a> haben und wiederum auf Seite 2

      1. Hallo,

        Nee die Seiten werden nicht generiert. Diese XML Datei ist halt als Inhalt in einem CMS anzusehen. Die Anbindung ist schon implementiert und funktionniert.
        Nur für diese XML Datei, hätte ich gern die passende XSL schreiben, so dass die Darstellung HTML Konform ist.
        Also ich möchte auf der Seite 1 dieses:
        <a href="#5">Link 2</a> haben und wiederum auf Seite 2

        Ich glaube entweder hast du mich missverstanden oder ich dich.

        Wenn du sagst, die Seiten werden nicht generiert: das kann nicht sein, es sei denn du lieferst direkt nur das XML aus. Dann sind Links (<a ...> irrelevant, weil XML das nicht kennt. Irgendwo muss es HTML rauskommen, wenn der Browser was darstellen soll.

        Was hilft es dir, wenn ich schreibe:

        --------------------------------------
        <xsl:stylesheet version="2.0"       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"      xmlns:xhtml="http://www.w3.org/1999/xhtml">
        <xsl:output name="xhtml-page" method="xhtml" indent="no"             doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
                    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>

        <xsl:template match="/">
          <xsl:for-each select="start/page">
            <xsl:result-document href="page{position()}.html" format="xhtml-page">
              <html xmlns="http://www.w3.org/1999/xhtml">
                <head><title><xsl:value-of select="."/></title></head>
                <body>
                 <xsl:apply-templates />

        <a ... was auch immer>

        </body>
              </html>
            </xsl:result-document>
          </xsl:for-each>
        </xsl:template>

        <!-- andere templates -->

        </xsl:stylesheet>
        ---------------------------------------

        aber dein CMS keinen blassen Schimmer vom XSL 2.0 hat?

        Wenn du aber nur _eine_ Seite hast und darin mit Ankers hin und her springen willst:

        <xsl:for-each select="page">

        <xsl:apply-templates />

        xsl:choose
          <xsl:when test="position() = 1">
           <a href="{following-sibling::page[1]/@id}">
            Link <xsl:value-of select="substring(following-sibling::page/@id, 2)" />
           </a>
          </xsl:when>
          <xsl:when test="last()">
           <a href="{preceding-sibling::page[1]/@id}">
            Link <xsl:value-of select="substring(preceding-sibling::page/@id, 2)" />
           </a>
          </xsl:when>
          xsl:otherwise
           <a href="{following-sibling::page[1]/@id}">
            Link <xsl:value-of select="substring(following-sibling::page/@id, 2)" />
           </a>

        <a href="{preceding-sibling::page[1]/@id}">
            Link <xsl:value-of select="substring(preceding-sibling::page/@id, 2)" />
           </a>
          </xsl:otherwise>
         </xsl:choose>
        </xsl:for-each>

        Grüße
        Thomas

        1. Hi Thomas!

          doch du hast rechts. Die erste Lösung ist genau, was ich will. Ich habe es als xsl benutzt und nur so geändert:

          ...
                  <body>
                   <xsl:apply-templates />

          Page

          </body>
                </html>
          ...

          also nur Page reingeschrieben und versucht es auf meiner XML Datei anzuwenden aber ich bekomme von IE die Meldung: Das Schlüsselwort xsl:for-each darf xsl:result-document nicht enthalten.
          mache ich was falsch? ich gehe jetzt nicht mehr über cms sondern öffne die xml datei (die einen Referenz zu XSL Datei hat) mit IE 6.0

          1. Hallo,

            doch du hast rechts. Die erste Lösung ist genau, was ich will. Ich habe es als xsl benutzt und nur so geändert:

            also nur Page reingeschrieben und versucht es auf meiner XML Datei anzuwenden aber ich bekomme von IE die Meldung: Das Schlüsselwort xsl:for-each darf xsl:result-document nicht enthalten.
            mache ich was falsch? ich gehe jetzt nicht mehr über cms sondern öffne die xml datei (die einen Referenz zu XSL Datei hat) mit IE 6.0

            Du machst nichts falsch.
            xsl:result-document gibt es erst in XSLT 2.0 und der IE kann das nicht (das hat Tim schon in deinem Doppelposting auch gesagt) und er untersützt auch die EXSLT-Erweiterungen nicht, die hier helfen könnten.

            Du hast mit dem IE (bzw. überhapt mit einem Browser) fast keine Möglichkeit dein Vorhaben zu verwirklichen.

            Fast, weil es möglich wäre, dass du den Ganzen eine HTML-Seite vorstellst und darau mittels JavaScript und XMLHTTPRequest auf das XML und XSL zugreifst. Dabei kannst du auch einen Parameter mitübergeben, so dass es immer nur die Seite aus dem XML herausgeneriert wird, die du willst.

            Wohlgemerkt, es werden nicht mehrere HTML-Seiten erzeugt: es gibt nur das (eine) XML und das XSL, du läßt aber immer nur die gewünschte Seite darstellen. Diese Möglichkeit würde dafür auch mit Firefox/Mozilla funktionieren.

            Wenn das für dich ein Weg ist, denn du nehmen kannst, findest du unter http://forum.de.selfhtml.org/archiv/2006/3/t126420/#m815491 und http://forum.de.selfhtml.org/archiv/2005/1/t97848/#m597247 so eine JavaScript-XMLHTTPRequest Seite.

            Wenn du dir den Code angesehen hast und Fragen hast, kannst du sie hier stellen, dann können wir das ganz auch Schritt für Schritt durchgehen.

            Grüße
            Thomas

            1. danke Thomas! ich habe dein Beispiel ein bisschen überarbeitet und diese verwende ich zur Zeit:
              <?xml version="1.0" encoding="ISO-8859-1"?>
              <!-- Edited with XML Spy v2006 (http://www.altova.com) -->
              <xsl:stylesheet version="1.0"
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
              <xsl:output method='html' version='1.0' encoding='UTF-8' indent='yes'/>

              <xsl:template match="/">
              <xsl:for-each select="//page">

              <xsl:apply-templates />

              <a href="index.php?id={substring(text/link, 2)}">
                  Link <xsl:value-of select="substring(text/link, 2)" />
                 </a>

              </xsl:for-each>
              </xsl:template>

              </xsl:stylesheet>

              Die Links werden wie gewünscht nun erzeugt ;-) aber ich möchte die nicht alle hintereinander haben sondern wie du schon gedacht hast, als einzelne seite haben.
              Ich benutze phpxslt und benutze die DomDocument Methode von Php um das Dokument zu parsen. also es wird nicht mehr über IE angezeigt ;-)
              Habe deine 2 Beispiele gesehen. Es wäre gut, wenn es eine Lösung ohne Java-script gibt,bzw. wie wäre die einfachste und schöne Lösung zu erreichen was ich will?
              Du hast schon richtig gedacht. Ein guter Weg wäre ja die id nr als Parameter die URL zu übergeben.

              1. Hallo,

                danke Thomas! ich habe dein Beispiel ein bisschen überarbeitet und diese verwende ich zur Zeit:
                   <a href="index.php?id={substring(text/link, 2)}">
                    Link <xsl:value-of select="substring(text/link, 2)" />
                   </a>

                »

                Ich benutze phpxslt und benutze die DomDocument Methode von Php um das Dokument zu parsen. also es wird nicht mehr über IE angezeigt ;-)

                OK, also verarbeitest du das XML am Server *.

                Habe deine 2 Beispiele gesehen. Es wäre gut, wenn es eine Lösung ohne Java-script gibt,bzw. wie wäre die einfachste und schöne Lösung zu erreichen was ich will?
                Du hast schon richtig gedacht. Ein guter Weg wäre ja die id nr als Parameter die URL zu übergeben.

                Dann mache es doch so ;-)
                * --> weil du das XML am Server verarbeitest, kannst du auf das JS verzeichten und mit URL-Parameter arbeiten. Hier nur skizziert:
                -----------------------------------
                <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                 <xsl:param name="id" />
                 <xsl:template match="/">
                  <html>
                  <head>
                   <title>Untitled</title>
                  </head>
                  <body>
                   xsl:choose
                    <xsl:when test="$id = ''">
                     <xsl:apply-templates select="pages/page[@id = '1'] />
                    </xsl:when>
                    xsl:otherwise
                     <xsl:apply-templates select="pages/page[@id = $id] />
                    </xsl:otherwise>
                   </xsl:choose>

                </body>
                  </html>
                 </xsl:template>

                <xsl:template match="page">
                  <!-- was halt für page gewünscht ist -->
                 </xsl:template>
                </xsl:stylesheet>
                -----------------------------------

                Du muss nur noch dafür sorgen, dass dein index.php das Paramter an das XSL übergibt, den Rest erledigt das XSL. D.h. es wird immer nur die "Seite" dargestellt, welche man aufgerufen hat. Es sind zwar keine einzelne HTML-Seiten (nicht im den Sinne, dass die HTML-Seiten auf dem Server liegen würden - wobei du natürlich das Ergebnis der Transformation am Server cachen könntest), aber es sieht so aus.

                Ob du jetzt die Links auf die "andere Seiten" so generierst, wie ich es vorschlug https://forum.selfhtml.org/?t=127564&m=824101 oder eben  anderes, hängt nur davon ab wie du das XML gestaltest.

                Grüße
                Thomas

                1. Hi Thomas!

                  Wir kommen schon näher. ;-) Danke nochmal für deine Mühe.

                  So sieht meine XML Datei zur Zeit aus:
                  -----------------------------------------------
                   <pages startpage="#2" id="#1">
                     <page id="#2">
                      <text id="#3">
                       <const>Link auf zweite Seite</const>
                       <link id="#4">#5</link>
                      </text>
                     </page>
                     <page id="#5">
                      <text id="#6">
                       <const>Link auf erste Seite</const>
                       <link id="#4">#2</link>
                      </text>
                     </page>
                   </pages>
                  ------------------------------------------------

                  Und meine XSL:
                  ------------------------------------------------
                  <?xml version="1.0" encoding="ISO-8859-1"?>
                  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                  <xsl:output method='html' version='1.0' encoding='UTF-8' indent='yes'/>
                   <xsl:param name="pageid" />
                   <xsl:template match="/">
                    <html>
                    <head>
                     <title>Untitled</title>
                    </head>
                    <body>
                     xsl:choose
                      <xsl:when test="$pageid = ''">
                       <xsl:apply-templates select="//page[@id=ancestor::project/@startpage]" />
                      </xsl:when>
                      xsl:otherwise
                       <xsl:apply-templates select="//page[@id = '$pageid']" />
                      </xsl:otherwise>
                     </xsl:choose>

                  </body>
                    </html>
                   </xsl:template>

                  <xsl:template match="page">
                    <a href="index.php?id=1&amp;pageid={text/link}">
                     <xsl:value-of select="text/const" />
                    </a>
                   </xsl:template>
                  </xsl:stylesheet>
                  ------------------------------------------------

                  Ich gebe diesen id also nun als 2. Parameter, weil meine Seite in CMS in einer Seite mit id=1 eingebunden wird. Alles klappt ganz gut und der Link für die Startpage wird richtig ausgegeben und sieht so aus:
                  <a href="index.php?id=1&amp;pageid=#5">Link auf zweite Seite</a>

                  Wenn ich nun drauf klicke, sollte er checken und merken, dass der $pageid nicht leer ist und also machen, was im xsl:otherwise steht. Das tut er aber nicht. Der Link steht richtig in der Adressleiste aber nichts ändert sich am Inhalt. :-(
                  Ist da was du mit Caches gemeint hast? Habe die Seite 100mal neu geladen mit dem Parameter $pageid aber irgendwie checkt er das nicht und nichts ändert sich.

                  1. Hallo,

                    xsl:otherwise
                         <xsl:apply-templates select="//page[@id = '$pageid']" />
                        </xsl:otherwise>

                    Wenn ich nun drauf klicke, sollte er checken und merken, dass der $pageid nicht leer ist und also machen, was im xsl:otherwise steht. Das tut er aber nicht. Der Link steht richtig in der Adressleiste aber nichts ändert sich am Inhalt. :-(
                    Ist da was du mit Caches gemeint hast? Habe die Seite 100mal neu geladen mit dem Parameter $pageid aber irgendwie checkt er das nicht und nichts ändert sich.

                    Der Fehler ligt darin, dass du nicht den Parameter, den du übergibst, prüfst, sondern den String '$pageid' und weil die echte "pageid" nie den Wert "$pageid" hat, wird dir auch nichts angezeigt.

                    <xsl:apply-templates select="pages/page[@id = $pageid]" />

                    Grüße
                    Thomas

                    PS: trage den Pfad "pages/" einfach ein, denn ein "//" kann exterem zeitaufwendig sein.

                    1. trage den Pfad "pages/" einfach ein, denn ein "//" kann exterem zeitaufwendig sein.

                      Stimmt, das habe ich geändert.

                      <xsl:apply-templates select="pages/page[@id = $pageid]" />

                      Auch so hat es nicht funktionniert.
                      Und was interessant ist, wenn ich sondern so was schreibe:
                          <xsl:when test="$pageid='#5'">
                           <xsl:apply-templates select="pages/page[@id='#5']" />
                          </xsl:when>

                      dann wählt er trotzdem nicht diese page und bleibt immer bei der ersten Page. :-(

                      1. Hallo,

                        Stimmt, das habe ich geändert.

                        <xsl:apply-templates select="pages/page[@id = $pageid]" />

                        Auch so hat es nicht funktionniert.
                        Und was interessant ist, wenn ich sondern so was schreibe:
                            <xsl:when test="$pageid='#5'">
                             <xsl:apply-templates select="pages/page[@id='#5']" />
                            </xsl:when>

                        dann wählt er trotzdem nicht diese page und bleibt immer bei der ersten Page. :-(

                        Lasse dir am Anfang der Seite mal den Parameter ausgeben:
                        --------
                        <body>
                        (pageid: <xsl:value-of select="$pageid" />)
                        --------

                        um zu sehen, was eigentlich übergeben wird.
                        Vielleicht stimmt ja was mit der Link-Selection nicht.
                        Ohne jetzt das konkrete XML und XSL zu sehen, kann ich dazu lieder nichts sagen.

                        Grüße
                        Thomas

                        1. Hallo Thomas!

                          Das ist interessant. Irgendwie erkennt er $pageid nicht, denn wenn ich schreibe:
                          pageid: <xsl:value-of select="$pageid" />
                          dann bekomme ich nur:
                          pageid:

                          XML Datei:
                          -----------------------------------------------
                           <pages startpage="#2" id="#1">
                             <page id="#2">
                              <text id="#3">
                               <const>Link auf zweite Seite</const>
                               <link id="#4">#5</link>
                              </text>
                             </page>
                             <page id="#5">
                              <text id="#6">
                               <const>Link auf erste Seite</const>
                               <link id="#4">#2</link>
                              </text>
                             </page>
                           </pages>
                          ------------------------------------------------

                          Und meine XSL:
                          ------------------------------------------------
                          <?xml version="1.0" encoding="ISO-8859-1"?>
                          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                          <xsl:output method='html' version='1.0' encoding='UTF-8' indent='yes'/>
                           <xsl:param name="pageid" />
                           <xsl:template match="/">
                            <html>
                            <head>
                             <title>Untitled</title>
                            </head>
                            <body>
                             xsl:choose
                              <xsl:when test="$pageid = ''">
                               <xsl:apply-templates select="pages/page[@id=ancestor::pages/@startpage]" />
                              </xsl:when>
                              xsl:otherwise
                               <xsl:apply-templates select="pages/page[@id = '$pageid']" />
                              </xsl:otherwise>
                             </xsl:choose>

                          </body>
                            </html>
                           </xsl:template>

                          <xsl:template match="page">
                            <a href="index.php?id=1&amp;pageid={text/link}">
                             <xsl:value-of select="text/const" />
                            </a>
                           </xsl:template>
                          </xsl:stylesheet>
                          ------------------------------------------------

                          Weiss denn XSL, dass er die Value für pageid vom URL übernehmen muss, wenn ich einfach nur <xsl:param name="pageid" /> schreibt?
                          habe gegoogelt und es gab schon Leute mit dem gleichen Problem. Leider hatte auch keine eine Lösung eingegeben. :-(

                          1. Hallo,

                            Das ist interessant. Irgendwie erkennt er $pageid nicht, denn wenn ich schreibe:
                            pageid: <xsl:value-of select="$pageid" />
                            dann bekomme ich nur:
                            pageid:

                            Verstehe. Der Parameter wird von deinem Script also nicht übergeben.

                            Weiss denn XSL, dass er die Value für pageid vom URL übernehmen muss, wenn ich einfach nur <xsl:param name="pageid" /> schreibt?

                            XSL weiss das nicht, das muss dein PHP-Script wissen und er muss den Paramter an das XSL(an den XSL-Prozessor) übergeben. Erst dann weiss das XSL auch was davon.

                            Du hast gesagt, du verwendest die XSL-Funktionen von PHP: https://forum.selfhtml.org/?t=127564&m=825410
                            Und ich habe darauf gesagt, "Du muss nur noch dafür sorgen, dass dein index.php das Paramter an das XSL übergibt, den Rest erledigt das XSL."
                            https://forum.selfhtml.org/?t=127564&m=825825

                            Also sorge bitte dafür, dass das passiert ;-)
                            Schaue dir am besten dazu die Seite http://www.php.net/manual/de/function.xsl-xsltprocessor-set-parameter.php und die Beispiele dort an.

                            Wenn du den Paramter dann richtig an das XSL übergibtst, wird es auch mit dem Rest klappen. An deinem XSL muss du aber die Zeile:
                            <xsl:apply-templates select="pages/page[@id = '$pageid']" /> noch ändern, so dass sie richtig ist:
                            <xsl:apply-templates select="pages/page[@id = $pageid]" />

                            Grüße
                            Thomas

                            1. Hi Thomas!

                              Danke für den Hinweis. So sieht mein PHP Datei aus:
                              -------------------------
                              $xml = new DOMDocument;
                              $xml->load($this->xml);

                              $xsl = new DOMDocument;
                              $xsl->load($this->xsl);

                              // Configure the transformer
                              $proc = new XSLTProcessor;
                              $proc->importStyleSheet($xsl); // attach the xsl rules

                              $proc->setParameter('', 'pageid', $_GET['pageid']);
                              return $proc->transformToXML($xml);
                              -------------------------
                              Der pageid wird nun erkannt aber allerdings nur wenn mein XML numerische pageid hat. Also:<page id="2"> und die Links dementsprechend: <link>2</link>

                              Wenn mein XML aber wie vorher ist (mit id="#2"), dann wird es nicht erkannt.
                              Ich habe versucht in meiner PHP Datei erst den # auszuschneiden
                              $proc->setParameter('', 'pageid', substr($_GET['pageid'],1));
                              und dann im XSL wieder einzubinden:
                              pageid: <xsl:value-of select="concat('#',$pageid)"/>
                              Aber dann habe ich keine Ausgabe. :-(

                              Bitte noch ein letztes Mal einen Tipp Thomas.

                              1. Hallo,

                                Danke für den Hinweis. So sieht mein PHP Datei aus:
                                Der pageid wird nun erkannt aber allerdings nur wenn mein XML numerische pageid hat. Also:<page id="2"> und die Links dementsprechend: <link>2</link>

                                Wenn mein XML aber wie vorher ist (mit id="#2"), dann wird es nicht erkannt.
                                Ich habe versucht in meiner PHP Datei erst den # auszuschneiden
                                $proc->setParameter('', 'pageid', substr($_GET['pageid'],1));
                                und dann im XSL wieder einzubinden:
                                pageid: <xsl:value-of select="concat('#',$pageid)"/>
                                Aber dann habe ich keine Ausgabe. :-(

                                Bitte noch ein letztes Mal einen Tipp Thomas.

                                Leider muss ich dich diesmal entteuschen, ich weiss auch nicht, was PHP mit dem Parameter bzw. mit dem # macht. Ob das ein Sonderzeichen für PHP ist?
                                Mein Tipp wäre, das # in deinem XML zu ersetzen (z.B. duch p).

                                Grüße
                                Thomas

                                1. Hi Thomas!

                                  Ich habe das Problem gelöst. Ich musste sondern in der XSL das # ausschneiden:
                                          <a>
                                              <xsl:attribute name="href">index.php?id=1&amp;pageid=<xsl:value-of select="substring-after(link, '#')"/></xsl:attribute>
                                              <xsl:value-of select="const" />
                                          </a>

                                  und dann in der PHP eingefügt:
                                  if(isset($_GET['pageid'])) {
                                  $ide = "#".$_GET['pageid'];
                                  $proc->setParameter('', 'pageid', strval($ide));
                                  }

                                  nun in der URL habe ich keine Raute mehr. Diese würde nämlich immer als Anker (index.php?id=1&pageid=#3) angesehen, darum war der Pageid immer leer ;-)

                                  Danke nochmal für deine Hilfe Thomas. ;-)

  2. Ich poste es also hier wieder, weil mein anderer Beitrag gesperrt ist.
    Die Anforderungen haben sich geändert und ich bin nicht mehr über IE. Das Problem nun liegt auch woanders.

    -----------------Beitrag----------------------------
    Hallo!

    Meine XML Datei sieht so aus:
    <pages start="3">
      <page id="1">
        <text>Page 1</text>
        <link page="2">Link with page 2</link>
      </page>
      <page id="2">
        <text>Page 2</text>
        <link page="4">Link with page 4</link>
      </page>
      <page id="3">
        <text>Page 3</text>
        <link page="2">Link with page 2</link>
      </page>
      <page id="4">
        <text>Page 4</text>
        <link page="3">Link with page 3</link>
      </page>
    </pages>

    Ich muss also 4 seiten haben, die miteinander verlinkt sind. Die erste seite (Homepage) soll die mit dem id=3 sein (start="3" in pages). Danach enthält die Seite einfach nur einen Link mit einer anderen seite.
    Im Kopf ist es klar aber ich weiss nicht, wie ich überprüfe, damit ich mit page id=3 anfange und die Links auf der Seite setze.
    Ich bin für jede Hilfe dankbar. :-)
    Frohe Ostern.