Marc: Eine Schleiefe in XSLT

Moin moin liebes Forum

ich komme ohne Deine Hilfe nicht mehr weiter...

Es geht um folgendes: Ich erhalte ein XML-File mit Artikeln, die bestimmten Kategorien zugeordnet sind. Aus dieser Datei möchte ich mittels XSLT eine menschenlesbare HTML-Datei erstellen.

Es gibt eine endliche Anzahl von Kategorien, die allerdings eine unbekannte Anzahl von Unterkategorien enthalten:

Beispiel:

Autos          Küchengeräte
+-BMW          +-Phillips
+-Mercedes     ++Moulinex
+-Porsche      |++Toaster
+-Rover        | ++Sandwich-Toaster
               |  +-Dreieckige Sandwich-Toaster
               |  +-Viereckige Sandwich-Toaster
               |
               +Küchenmaschinen

Bei Autos gibt es jetzt zufälligerweise nur eine ebene von Unterkategorien, im Falle der Küchengeräte gibt es manchmal eine, manchmal mehrere, unterschiedlich tief verschachtelt.

Die Autos auszugeben wäre keine Problem, ich habe das für die erste Ebene bisher immer so gelöst:

<xsl:for-each select="menue/menueCategory/">
<h3><xsl:value-of select="cat_name"/></li>
<ul>
 <xsl:for-each select="menue/menueCategory/menueCategory">
  <li><xsl:value-of select="cat_name"/></li>
 </xsl:for-each>
</ul>

Wie kann ich nun
1.) eine Bedingung einfügen, die prüft, ob es ein weiteres Child "menueCategory" gibt und
2.) zweitens dieses so oft ausgeben, bis kein weiteres Child "menueCategory" gegeben ist?

Also etwas in der Art

if
 {
  child menueCategory
   <li>
   <ul>
   for each menueCategory
    {
     <li><xsl:value-of select="cat_name"/></li>
    }
   </ul>
   </li>
 }

Gruß,
Marc.

--
Und immer schön
validieren (http://validator.w3c.org)
sh:( fo:| ch:? rl:? br:> n4:& ie:% mo:} va:} de:] zu:) fl:( ss:| ls: js:(
http://www.peter.in-berlin.de/projekte/selfcode/?code=sh%3A%28+fo%3A%7C+ch%3A%3F+rl%3A%3F+br%3A%3E+n4%3A%26+ie%3A%25+mo%3A%7D+va%3A%7D+de%3A%5D+zu%3A%29+fl%3A%28+ss%3A%7C+ls%3A+js%3A%28
  1. hi!

    poste mal ne beispiel-XML hier bitte

    gruss
    Rondra

    1. Moin moin

      hi!

      poste mal ne beispiel-XML hier bitte

      Gerne, vorweg noch eine Anmerkung. Es geht darum, daß sich ein Kunde Artikel aus einem bestehenden Fundus auswählen kann, die er einkauft, um sie z. B. in seiner eigenen Website zu veröffentlichen. Dabei kann er ganze Kategorien (inklusive Unterkategorien) oder auch einzelne Artikel auswählen. Daher weiß man vorher nie, wie hoch die Verschachtelungstiefe ist.

      Der Kunde erhält die Original-XML-Datei, die er z. B. per Skript auswerten kann. Um ihm vor dem Kauf aber die Möglichkeit zu geben, sich die gewählten Artikel noch einmal anzusehen, möchte ich sie ihm ansehnlich präsentieren...

      Hier *ein* mögliches Beispiel:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE unser_portal SYSTEM "C:\NT4\Profiles\mh\Desktop\oeko-news\news-xslt\Version1.1\unser_portal_04.dtd">
      <?xml-stylesheet href="news.xsl" type="text/xsl"?>
      <chosenContributions>
       <copyright>Copyright liegt bei uns</copyright>
       <description>Ihre Artikelauswahl aus unserem Portal</description>
       <link>http://www.sag-ich-nicht.de</link>
       <pubDate>Thu, 19 Aug 2004 13:57:58 GMT</pubDate>
       <menueCategory>
        <cat_id>256</cat_id>
        <cat_name>Category A</cat_name>
        <menueCategory>
         <cat_id>356</cat_id>
         <cat_name>Category A1</cat_name>
         <menueCategory>
          <cat_id>456</cat_id>
          <cat_name>Category A2</cat_name>
         </menueCategory>
        </menueCategory>
       </menueCategory>
       <menueCategory>
        <cat_id>556</cat_id>
        <cat_name>Category B</cat_name>
        <menueCategory>
         <cat_id>656</cat_id>
         <cat_name>Category B1</cat_name>
         <menueCategory>
          <cat_id>756</cat_id>
          <cat_name>Category B1a</cat_name>
         </menueCategory>
         <menueCategory>
          <cat_id>856</cat_id>
          <cat_name>Category B1b</cat_name>
         </menueCategory>
        </menueCategory>
        <menueCategory>
         <cat_id>956</cat_id>
         <cat_name>Category B2</cat_name>
        </menueCategory>
       </menueCategory>
       <contributions>(...)</contributions>
      </chosenContributions>

      Gruß,
      Marc.

      --
      Und immer schön
      validieren (http://validator.w3c.org)
      sh:( fo:| ch:? rl:? br:> n4:& ie:% mo:} va:} de:] zu:) fl:( ss:| ls: js:(
      http://www.peter.in-berlin.de/projekte/selfcode/?code=sh%3A%28+fo%3A%7C+ch%3A%3F+rl%3A%3F+br%3A%3E+n4%3A%26+ie%3A%25+mo%3A%7D+va%3A%7D+de%3A%5D+zu%3A%29+fl%3A%28+ss%3A%7C+ls%3A+js%3A%28
      1. Hi,

        schau mal ob Dir das hier weiterhilft..

        <xsl:template match="/">
        <html>
         <body>
          <xsl:for-each select="//menueCategory">
          <ul>
           xsl:apply-templates/
          </ul>
          </xsl:for-each>
         </body>
        </html>
        </xsl:template>
        <xsl:template match="menueCategory">

        <li><xsl:value-of select="."/></li>

        </xsl:template>

        lg
        Rondra

        1. Moin moin

          erst mal vielen Dank für die Hilfe bei diesem kniffligen problem!

          schau mal ob Dir das hier weiterhilft..

          <xsl:template match="/">
          <html>
          <body>
            <xsl:for-each select="//menueCategory">
            <ul>
             xsl:apply-templates/
            </ul>
            </xsl:for-each>
          </body>
          </html>
          </xsl:template>
          <xsl:template match="menueCategory">

          <li><xsl:value-of select="."/></li>

          </xsl:template>

          Jein, das Ergebnis kommt meinen Vorstellungen schon näher, aber es ist doch ein wenig wirr. Meine Ausbesserungs-Versuche haben aber nicht geholfen...

          Hier der Zwischenstand:

          --------------------------------------------
          XSLT-Datei:

          <?xml version="1.0" encoding="iso-8859-1"?>
          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
           <xsl:template match="/">
            <html>
             <body>
              <xsl:for-each select="//menueCategory">
               <ul>
                <li>
                 xsl:apply-templates/
                </li>
               </ul>
              </xsl:for-each>
             </body>
            </html>
           </xsl:template>

          <xsl:template match="//menueCategory">
            <ul>
             <li><xsl:value-of select="cat_name"/></li>
            </ul>
           </xsl:template>
          </xsl:stylesheet>
          ---------------------------------------------
          #############################################
          #############################################
          ---------------------------------------------
          Browser-Ausgabe:

          • (A)Category A
              + Category A1

          • (A1)Category A1
              + Category A2

          • (A2)Category A2

          • (B)Category B
              + Category B1
              + Category B2

          • (B1)Category B1
              + Category B1a
              + Category B1b

          • (B1a)Category B1a

          • (B1b)Category B1b

          • (B2)Category B2
            --------------------------------------------------

          Zwei neue Fragen:
          1.) Warum geht die Verschachtelung der Listen nicht bis zur untersten Ebene weiter?
          2.) Warum werden die bereits in verschachtelten Listen erschienenen Ebenen nochmals wie eine Kazegorie 1. ordnung gelistet?

          Gruß,
          Marc.

          --
          Und immer schön
          validieren (http://validator.w3c.org)
          sh:( fo:| ch:? rl:? br:> n4:& ie:% mo:} va:} de:] zu:) fl:( ss:| ls: js:(
          http://www.peter.in-berlin.de/projekte/selfcode/?code=sh%3A%28+fo%3A%7C+ch%3A%3F+rl%3A%3F+br%3A%3E+n4%3A%26+ie%3A%25+mo%3A%7D+va%3A%7D+de%3A%5D+zu%3A%29+fl%3A%28+ss%3A%7C+ls%3A+js%3A%28
          1. Moin moin

            ich bin wieder ein Stückchen weiter gekommen:

            Die Ausgabe im Browser sieht nun schon ganz gut aus:

            *  (A) Category A (A1) Category A1 (A2) Category A2

            * (B) Category B (B1) Category B1 (B1a) Category B1a (B1b) Category B1b (B2) Category B2

            Jetzt fehlt mir nur noch die Einrückung...

            Die dazugehörige XSLT-Datei:

            <?xml version="1.0" encoding="iso-8859-1"?>
            <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
             <xsl:template match="/">
              <html>
               <body>
                <xsl:for-each select="oekolandbau/menueCategory">
                 <ul>
                  <li>
                   xsl:apply-templates/
                  </li>
                 </ul>
                </xsl:for-each>
               </body>
              </html>
             </xsl:template>

            <xsl:template match="oekolandbau/menueCategory">
              <xsl:for-each select="/">
              <ul>
               <li><xsl:value-of select="menueCategory"/></li>
              </ul>
              </xsl:for-each>
             </xsl:template>
            </xsl:stylesheet>

            Gruß,
            Marc.

            --
            Und immer schön
            validieren (http://validator.w3c.org)
            sh:( fo:| ch:? rl:? br:> n4:& ie:% mo:} va:} de:] zu:) fl:( ss:| ls: js:(
            http://www.peter.in-berlin.de/projekte/selfcode/?code=sh%3A%28+fo%3A%7C+ch%3A%3F+rl%3A%3F+br%3A%3E+n4%3A%26+ie%3A%25+mo%3A%7D+va%3A%7D+de%3A%5D+zu%3A%29+fl%3A%28+ss%3A%7C+ls%3A+js%3A%28
            1. Hallo,

              ich bin wieder ein Stückchen weiter gekommen:
              Jetzt fehlt mir nur noch die Einrückung...

              Für die XML-Datei die do weiter Oben gepostet hast geht das z.B. auch mit apply-templates:

              <?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" indent="yes" encoding="iso-8859-1" />

              <xsl:template match="/">
                <html>
                 <head>
                  <title>Untitled</title>
                 </head>
                 <body>
                  <xsl:apply-templates select="chosenContributions" />
                 </body>
                </html>
               </xsl:template>

              <xsl:template match="menueCategory">
                <ul>
                 xsl:choose
                  <xsl:when test="menueCategory">
                   <li>
                    (<xsl:value-of select="cat_id" />)<xsl:value-of select="cat_name" />
                    <xsl:apply-templates select="menueCategory" />
                   </li>
                  </xsl:when>
                  xsl:otherwise
                   <li>(<xsl:value-of select="cat_id" />)<xsl:value-of select="cat_name" /></li>
                  </xsl:otherwise>
                 </xsl:choose>
                </ul>
               </xsl:template>
              </xsl:stylesheet>

              Grüße
              Thomas

              1. Hallo Thomas,

                vielen Dank, genauso soll es sein!

                Gruß,
                Marc.

                --
                Und immer schön
                validieren (http://validator.w3c.org)
                sh:( fo:| ch:? rl:? br:> n4:& ie:% mo:} va:} de:] zu:) fl:( ss:| ls: js:(
                http://www.peter.in-berlin.de/projekte/selfcode/?code=sh%3A%28+fo%3A%7C+ch%3A%3F+rl%3A%3F+br%3A%3E+n4%3A%26+ie%3A%25+mo%3A%7D+va%3A%7D+de%3A%5D+zu%3A%29+fl%3A%28+ss%3A%7C+ls%3A+js%3A%28