frankx: xsl match apply templates

Hellihello,

mit xml <produktliste> und <produkt> kann ich über XPath und xsl auf den Eintrag mit der id='ID1' rausfischen.

<xsl:template match="/produktliste/produkt[id='ID1']">

Wenn ich jetzt für die "id" und alles weitere noch individuelle Formatierung bzw. Zusätze habe, dann muss ich für jeden Unterknoten wieder den kompletten XPath angeben.

<xsl:template match="produkt[id='ID1']/id">

denn

<xsl:template match="id">

spuckt dan alle ids aus (apply templates hab ich jetzt weggelassen). Ist ja irgendwie auch logisch, aber dann auch wieder schade.

Fragen: 1. kann ich denn mit einer "zentralen" Angabe das Produkt rausfiltern und dann in der Folge nur noch mit match="id" etc. auf die Unterknoten zugreifen.

2. Kann ich denn mit Javascript zB. den xsl-file so manipulieren, dass ich zb den Abfragewert von id manipuliere, dass er mir dann ID1 oder ID2 oder ID3 ausspuckt, ja nach Häkchen oder Knopfdruck?

Oder ist da am Ansatz was falsch?

Dank

frankx

  1. Hellihello Ingrid.

    jetzt seh ichs erst, der IE schreibt ja trotzdem die Inhalte aller Elementknoten hintendran, obwohl es dafür kein match-Template gibt. Was das denn?

    Dank

    frankx

  2. Hallo,

    Wenn ich jetzt für die "id" und alles weitere noch individuelle Formatierung bzw. Zusätze habe, dann muss ich für jeden Unterknoten wieder den kompletten XPath angeben.

    Nein, eigentlich nicht.

    denn
    <xsl:template match="id">
    spuckt dan alle ids aus (apply templates hab ich jetzt weggelassen).

    aber gerade das apply-template wäre gut gewesen, denn schließlich entscheidet das wie und wo die Templates aufgerufen werden

    <xsl:template match="/produktliste/produkt">
     <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="id">...</xsl:template>
    <xsl:template match="foo">...</xsl:template>

    Falls in einem <produkt> ein <id> und ein <foo> gibt, werden die dafür vorgesehenen Templetes im jeweiligen produkt ausgeführt (und es werden nur die entsprechenden Unterelemente des aktuellen produkts berücksichtigt).

    Fragen: 1. kann ich denn mit einer "zentralen" Angabe das Produkt rausfiltern und dann in der Folge nur noch mit match="id" etc. auf die Unterknoten zugreifen.

    Ich weiss nicht was du damit meinst.

    1. Kann ich denn mit Javascript zB. den xsl-file so manipulieren,

    Nein. Du kannst mit JavaScript das XSL nicht manipulieren.

    dass ich zb den Abfragewert von id manipuliere, dass er mir dann ID1 oder ID2 oder ID3 ausspuckt, ja nach Häkchen oder Knopfdruck?

    Oder ist da am Ansatz was falsch?

    Das ist was anderes: du willst aus der HTML-Datei heraus mit JavaScript Variablen für die Transfrormation setzen, das ist möglich. Beispiele dazu findest du von mir im Archiv. (Stichwort z.B. xmlhttprequest)

    Wenn du das ganze mit serverseitiger Technologie lösen kannst oder willst, muss du einfach das Formular mittels XSLT erzeugen. Mit JavaScript kannst du dann wie üblich Werte im Formular setzen und das Formular absenden, an der Serverseite auswerten und eine neue Ausgabe generieren.

    Grüße
    Thomas

    1. Hellihello Thomas,

      Wenn ich jetzt für die "id" und alles weitere noch individuelle Formatierung bzw. Zusätze habe, dann muss ich für jeden Unterknoten wieder den kompletten XPath angeben.

      Nein, eigentlich nicht.

      denn
      <xsl:template match="id">
      spuckt dan alle ids aus (apply templates hab ich jetzt weggelassen).

      aber gerade das apply-template wäre gut gewesen, denn schließlich entscheidet das wie und wo die Templates aufgerufen werden

        
      <xsl:stylesheet version="1.0"  
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
        
       <xsl:output method="html"/>  
        
       <xsl:template match="/produktliste/produkt[id='ID1']">  
          <h1>Produkte</h1>  
           <div style="border:1px solid blue">  
           <xsl:apply-templates/>  
          </div>  
       </xsl:template>  
        
       <xsl:template match="id">  
        <div><i>ID:</i><xsl:apply-templates/></div>  
       </xsl:template>  
        
       <xsl:template match="autor">  
        <div style="background-color:#F34;"><b>Autor: </b>  
         <xsl:apply-templates/>  
        </div>  
       </xsl:template>  
        
      </xsl:stylesheet>  
      
      

      Jetzt spuckt er alles aus, was er hat, selbst die Elemente, die garkein match haben.

        
      <?xml version="1.0"?>  
      <?xml-stylesheet type="text/xsl" href="produkt22html.xsl"?>  
      <!DOCTYPE produkt SYSTEM "produkt.dtd">  
      <produktliste>  
       <produkt>  
        <id>ID1</id>  
        <titel>Titel1</titel>  
        <autor>Autor1</autor>  
        <preis>Preis1</preis>  
       </produkt>  
       <produkt>  
        <id>ID2</id>  
        <titel>Titel2</titel>  
        <autor>Autor2</autor>  
        <preis>Preis2</preis>  
       </produkt>  
       <produkt>  
        <id>ID3</id>  
        <titel>Titel3</titel>  
        <autor>Autor3</autor>  
        <preis>Preis3</preis>  
       </produkt>  
       <produkt>  
        <id>ID4</id>  
        <titel>Titel4</titel>  
        <autor>Autor4</autor>  
        <preis>Preis4</preis>  
       </produkt>  
      </produktliste>  
      
      

      Fragen: 1. kann ich denn mit einer "zentralen" Angabe das Produkt rausfiltern und dann in der Folge nur noch mit match="id" etc. auf die Unterknoten zugreifen.

      Ich weiss nicht was du damit meinst.

      Na an obigem Beispiel hätte ich gedacht, der sollte nur id und autor des Elements mit der id="ID1" rausspucken.

      Wenn du das ganze mit serverseitiger Technologie lösen kannst oder willst, muss du einfach das Formular mittels XSLT erzeugen.

      Das Formular mittes XSLT? Kommt da denn was anderes raus, beim senden an den Server, als bei einem "normalen" Formular.

      Gruß,

      frankx

      1. Wie sieht es damit aus?

        <xsl:template match="/produktliste/produkt/*[id='ID1']">

        Gruß, Holger

        1. Hallo,

          Wie sieht es damit aus?

          <xsl:template match="/produktliste/produkt/*[id='ID1']">

          Schlecht, denn das wirkt erstens nur dann wenn er im <produkt> ein <element><id></id></element> hat, und zweitens, es ändert nichts am dem Verhalten was die build-in (ich frage mich wie ich in einem Posting dieses Wörtchen zweimal falsch schreiben konnte) Templates betrifft.

          Grüße
          Thomas

      2. Hallo,

        Jetzt spuckt er alles aus, was er hat, selbst die Elemente, die garkein match haben.

        Jedes Konten eines XML hat ein Template. Bei dir greifen genau diese so geannte build-in Templates, denn du hast paar sachen in deinem XSL vergessen.

        Für Elemente für die du kein Template definert hast, greift das biul-in Template. Du hast ein Template für /produktliste/produkt[id='ID1'] deshalb wird es auch mit dem blauen Rahmen dargestellt, für die anderen <produkt>-Elemente gilt also das buil-in (ebenso für das Wurzelknoten).
        Diese werden also auch ausgegeben, aber ohne den Rahmen.
        Für <id> und <autor> hast du ein Template, deshalb werden sie in allen Fällen entsprechend formatiert ausgegeben. Für <titel> und <preis> greifen wiederum die build-in Templates und auch diese Elemente werden ausgegeben.

        <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

        <xsl:output method="html"/>

        <xsl:template match="/produktliste/produkt[id='ID1']">
            <h1>Produkte</h1>
             <div style="border:1px solid blue">
             xsl:apply-templates/
            </div>
        </xsl:template>

        <xsl:template match="id">
          <div><i>ID:</i>xsl:apply-templates/</div>
        </xsl:template>

        <xsl:template match="autor">
          <div style="background-color:#F34;"><b>Autor: </b>
           xsl:apply-templates/
          </div>
        </xsl:template>

        </xsl:stylesheet>

        
        >   
          
        Und so siehst das "HTML" was du erzeugst dann aus:  
        <h1>Produkte</h1>  
        <div style="border:1px solid blue">  
        <div><i>ID:</i>ID1</div>Titel1<div style="background-color:#F34;"><b>Autor: </b>Autor1</div>Preis1</div>  
        <div><i>ID:</i>ID2</div>Titel2<div style="background-color:#F34;"><b>Autor: </b>Autor2</div>Preis2<div><i>ID:</i>ID3</div>Titel3<div style="background-color:#F34;"><b>Autor: </b>Autor3</div>Preis3<div><i>ID:</i>ID4</div>Titel4<div style="background-color:#F34;"><b>Autor: </b>Autor4</div>Preis4  
          
          
          
        Also muss du dafür sorgen, dass sowohl dein XSL als auch dein HTML richtig ist:  
        \---------------------------------------  
        <?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"/>  
          <xsl:template match="/produktliste">  
          <html>  
           <head>  
            <title>Prduktliste</title>  
           </head>  
           <body>  
            <xsl:apply-templates select="produkt[id='ID1']"  />  
           </body>  
          </html>  
         </xsl:template>  
          
         <xsl:template match="produkt">  
          <h1>Produkte</h1>  
             <div style="border:1px solid blue">  
           <xsl:apply-templates/>  
          </div>  
         </xsl:template>  
          
         <xsl:template match="id">  
          <div><i>ID:</i><xsl:value-of select="." /></div>  
         </xsl:template>  
          
         <xsl:template match="autor">  
          <div style="background-color:#F34;"><b>Autor: </b>  
           <xsl:value-of select="." />  
          </div>  
         </xsl:template>  
          
         <xsl:template match="titel | preis" />  
          
        </xsl:stylesheet>  
        \-----------------------------------------------  
          
          
        Und so sieht dann die Ausgabe dazu:  
        \-----------------------------------  
        <html>  
        <head>  
        <META http-equiv="Content-Type" content="text/html; charset=UTF-16">  
        <title>Prduktliste</title>  
        </head>  
        <body>  
        <h1>Produkte</h1>  
        <div style="border:1px solid blue">  
        <div><i>ID:</i>ID1</div>  
        <div style="background-color:#F34;"><b>Autor: </b>Autor1</div>  
        </div>  
        </body>  
        </html>  
        \-----------------------------------  
          
          
          
        
        > > Wenn du das ganze mit serverseitiger Technologie lösen kannst oder willst, muss du einfach das Formular mittels XSLT erzeugen.  
        >   
        > Das Formular mittes XSLT? Kommt da denn was anderes raus, beim senden an den Server, als bei einem "normalen" Formular.  
        >   
          
        Es ist ein normales Formular, denn am Ende hast du ja "nur" HTML. Aber du erzeugst dieses HTML in der Transformation, also muss du im XSLT deinen Code so gestalten, dass am Ende, das HTML steht, das du eben normal verwenden kannst.  
          
        Grüße  
        Thomas
        
        1. Hellihello Thomas,

          besten Dank.

          <xsl:apply-templates select="produkt[id='ID1']"  />

          Das hat gefehlt, das select in dem apply. Wie generierst Du denn beim Testen die Ausgabe? Ich hatte es jetzt lediglich mit Browserchen probiert, und das klappt bis hierher ganz gut. Nur der Quelltext bleibt eben XML. PHP braucht irgendeine Extension oder so, um XSLTs parsen zu können, oder (ist das bei xampp mit drinne?)?

          Dank und Gruß,

          frankx

          1. Hallo,

            Wie generierst Du denn beim Testen die Ausgabe? Ich hatte es jetzt lediglich mit Browserchen probiert, und das klappt bis hierher ganz gut.

            Im Mozilla/FF ist es relativ einfach das generierte HTML anzusehen:
            XML (mit dem eingebunden Styleseet) aufrufen --> STRG+A --> Rechte Maustaste --> Kontextmenü: View Selection Source (oder eben die deutsche Entsprechung).

            Im IE brauchst du ein Tool dafür:
            "Internet Explorer Tools for Validating XML and Viewing XSLT Output"
            siehe: http://forum.de.selfhtml.org/archiv/2003/9/t56500/#m316428

            bzw: http://www.microsoft.com/downloads/details.aspx?FamilyId=D23C1D2C-1571-4D61-BDA8-ADF9F6849DF9&displaylang=en

            Grüße
            Thomas

      3. Hallo frankx.

        <!DOCTYPE produkt SYSTEM "produkt.dtd">

        <produktliste>

          
        Ist das gewollt?  
          
          
        Einen schönen Mittwoch noch.  
          
        Gruß, Ashura  
        
        -- 
        sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|  
        [<mathbr:del.icio.us/>](http://del.icio.us/mathbr) [<mathbr:w00t/>](http://w00t.noctus.net)
        
        1. Hellihello Ashura,

          wenn Du schon so fragst, bestimmt nicht (;-). Weiß jetzt nicht, was da "gewollt" sein sollte. Ich hab das irgendwie übernommen und dachte, eine dtd damit einzubinden (was irgendwie mit PHP DOMDocument und validate auch mal funktioniert hat).

          Gruß,

          frankx

          1. Hallo frankx.

            wenn Du schon so fragst, bestimmt nicht (;-). Weiß jetzt nicht, was da "gewollt" sein sollte. Ich hab das irgendwie übernommen und dachte, eine dtd damit einzubinden (was irgendwie mit PHP DOMDocument und validate auch mal funktioniert hat).

            Was mich http://de.selfhtml.org/xml/regeln/dokumenttypdeklaration.htm#interne_dtd@title=verwundert:

            Der Name des Dokumenttyps muss mit dem Namen des Dokument-Elements, also dem äußersten Element in der XML Datei, identisch sein.

            Einen schönen Mittwoch noch.

            Gruß, Ashura

            --
            sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
            mathbr:del.icio.us/ mathbr:w00t/
            1. Hellihello Ashura,

              Was mich http://de.selfhtml.org/xml/regeln/dokumenttypdeklaration.htm#interne_dtd@title=verwundert:

              Der Name des Dokumenttyps muss mit dem Namen des Dokument-Elements, also dem äußersten Element in der XML Datei, identisch sein.

              besten Dank (das "Ding" hieß mal anders).

              frankx

    2. Hellihello Thomas,

      Wenn du das ganze mit serverseitiger Technologie lösen kannst oder willst, muss du einfach das Formular mittels XSLT erzeugen. Mit JavaScript kannst du dann wie üblich Werte im Formular setzen und das Formular absenden, an der Serverseite auswerten und eine neue Ausgabe generieren.

      mit PHP XSLTPocessor und ->setParameter kann ich dann aus PHP Parameter ans XSL-Dokument übergeben, zB. sortier oder Filterelemente, bzw. kann via PHP das entsprechende XSL-Dokument einbinden, je nach Aufruf. Oder anders?

      Berlingruß,

      frankx

      1. hallo frankx,

        könntest du mir mal eine php Ausschnitt zusenden, wie man die Parameter bei php (ich verwende php 5.0) übergeben kann, bzw. eine WWW-Seite, die es anschaulich erklärt? Ich mache es z.Z. genauso, dass ich serverseitig das Ganze auswerte und beim Parsing Parameter zuweise. Allerdings läuft das Ganze zur Zeit nur mit asp. Ich wuerde aber gerne die Seite auf einem Linux Rechner mit php realisieren, da dieser wesentlich schneller ist. Schick dir auch gerne ein beispiel, wie ich mit asp die Parameter zuweise.

        Gruß, Holger

        1. Hellihello Holger,

            
          $xml = new DOMDocument(); // Neues Objekt erzeugen  
          // We don't want to bother with white spaces  
          $xml->preserveWhiteSpace = false;  
            
          $xml->load("produkt_liste.xml"); // Obigen String hineinladen  
            
          $xsl = new DOMDocument(); // Neues Objekt erzeugen  
          $xsl->load("produkt_liste2html.xsl"); // Obigen String hineinladen  
            
          $proc = new XSLTProcessor;  
          $proc->importStyleSheet($xsl);  
          $proc->setParameter('','PARAM_NAME',$param_value);  
          echo $proc->transformToXML($xml);  
            
          
          

          soweit die PHP Seite. Wie im xsl die Parameter deklariert werden, lern ich grad, du scheinst es bereits zu können. Sah nicht so kompliziert aus (;-).

          Gruß,

          frankx

          1. Besten Dank Dir und Thomas,

            das sieht angenehm aus und dürfte keine größeren Probleme geben, meine ASP umzuschreiben, bei mir sieht eine davon ua. so aus (zwei Parameter werden übergeben, die vorher aus einer html datei, die selbst ergebnis eines parsing von xml quelle mit xsl stylesheet und mit post-Methode  ausgelesen und dann wieder in neuem parsing verarbeitet werden.

            <% Response.Buffer=True %>
            <html>
            <head>
            <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
            <title>Studie</title>
            </head>
            <body>
            <% Dim xml
               Dim xsl
               Dim template
               Dim processor
            'hier die beiden parameter
               Dim menu_name
               Dim language_id

            Set xml = Server.CreateObject("MSXML2.FreeThreadedDOMDocument.3.0")
               xml.async = false
               xml.load (Server.MapPath("quelle.xml"))

            Set xsl = Server.CreateObject("MSXML2.FreeThreadedDOMDocument.3.0")
               xsl.async = false
               xsl.load (Server.MapPath("quelle.xsl"))

            Set template = Server.CreateObject("MSXML2.XSLTemplate")
               template.stylesheet = xsl
               set processor = template.createProcessor()

            processor.input = xml

            'die Spracheinstellung wird uebergeben

            language_id = request.form("Language_Selection")
               if language_id <> "" then
                 processor.addParameter "Language", language_id
               end if

            'im zweiten Parameter fasse ich alle Werte zusammen die in den
            'Menufeldern ausgewaehlt wurden

            for counter = 1 to request.form("Selection").count
             layer_id = request.form("Selection")(counter)
             layer = layer & "_" & layer_id
            next

            if layer <> "" then
                 processor.addParameter "Layer", layer
               end if

            processor.transform()
               Response.write (processor.output)

            Set xml = Nothing
             Set xsl = Nothing
             Set template = Nothing
             Set processor = Nothing
             Set language_id = Nothing
             Set menu_name = Nothing

            %>
            </body>
            </html>

      2. Hallo,

        mit PHP XSLTPocessor und ->setParameter kann ich dann aus PHP Parameter ans XSL-Dokument übergeben, zB. sortier oder Filterelemente, bzw. kann via PHP das entsprechende XSL-Dokument einbinden, je nach Aufruf. Oder anders?

        Ja, kannst du (http://at.php.net/manual/en/function.xsl-xsltprocessor-set-parameter.php).
        Kurz skizziert:
        Du hast eine XML-Datei und eine XSLT-Datei,
        Du fürst die erste Transformation mittel PHP ohne Parameter aus *,
        Dann ist eine HTML-Seite im Browser mit dem Formular, in dem der Benutzer seine Auswahl trifft und das Formular absendet,
        Dein PHP-Script wertet die Eingaben aus und führt dann erneut eine Transformation durch, wobei es die Paramters für XSLT, die es aus den Eingaben erhalten hat, setzt.

        * du kannst (bzw. musst) natürlich dein XSLT so gestalten, dass es auf Paramtere reagiert, d.h. z.B. wenn es keine Paramter gesetzt sind, erschient nur das Formular in dem der User erst seine auswahl treffen muss.
        Sind Paramter gesetzt, gibt's das Formular und die Ausgabe der gewünschten Daten.

        Grüße
        Thomas