Otaka-san: xsl:copy-of-Tag übernimmt Eigenschaften von a-Tag nicht

Hallo,

ich habe eine XML-Datei, in der Buchvorstellungen in folgendem Format stehen:

<liste>
<eintrag>
<autor>A</autor>
<titel>B</titel>
<verlag>C</verlag>
<isbn>123-456-789-0</isbn>
<tag>Tag1</tag>
<tag>Tag2 ...</tag>
<resumee><p>Erster Absatz</p><p>Zweiter Absatz</p></resumee>
</eintrag>

<eintrag>
...
</eintrag>
</liste>

Und desweiteren eine XSL-Datei in der diese Daten mit CSS versehen dargestellt werden. Alles funktioniert einwandfrei, außer folgendem Problem:

In dem XML-Tag <resumee> steht eine Anmerkung von mir selbst. Sie soll allerdings auch die folgenden HTML-Tags enthalten können: <span> <q> <cite> <strong> <a> und genau an diesem <a> hapert es. Ich binde die <p>-Tags aus dem <resumee>-Tag folgendermaßen ein:

<xsl:template match="resumee/p">
xsl:choose<xsl:when test="position()=1"><p class="note"><xsl:copy-of select="." /></p></xsl:when>
xsl:otherwise<p class="note_nextline"><xsl:copy-of select="." /></p></xsl:otherwise></xsl:choose>
</xsl:template>

Das <a>-Tag hat in der CSS-Datei folgende Formatierungen:

a:link, a:visited, a:focus {
 border: 0px none;
 color: #808080;
 font-family: 'Verdana', 'Lucida', 'MSHei', 'Arial', sans-serif;
 font-size: 12px;
 line-height: 15px;
 text-align: left;
 text-decoration: underline;
 text-transform: none;
}

a:active, a:hover {
 border: 0px none;
 color: #cccccc;
 font-family: 'Verdana', 'Lucida', 'MSHei', 'Arial', sans-serif;
 font-size: 12px;
 line-height: 15px;
 text-align: left;
 text-decoration: underline;
 text-transform: none;
}

a[href^="http://"] {
 background-image: url(icons/link_ext.png);
 background-repeat: no-repeat;
 background-position: center right;
 padding-right: 10px;
}

Nun ist das (zumindest für mich) Erstaunliche, dass alle Tags bis auf das <a>-Tag korrekt formatiert werden. Das <a>-Tag verliert allerdings seine Normalformatierung (:hover wird angezeigt) und seine Referenz. Das heißt, es wird offensichtlich nicht mehr als Link dargestellt, was umso merkwürdiger ist, als im Quelltext offenbar alles korrekt erscheint. Wenn ich den betreffenden <p>-Tag mit Inhalt testweise direkt in die XSL-Datei schreibe, dann ist natürlich alles in bester Ordnung.

Wo ist der Denkfehler?

Vielen Dank für eure Unterstützung!

  1. Zusatz:

    Ich habe zuletzt gerade noch versucht, den vom Browser (Firefox auf Linux) generierten Quelltext direkt in die XSL-Datei zu schreiben, und siehe da: Alles wie gewünscht. Was soll ich denn nun davon halten? Ist das ein öfters auftretendes Problem beim Firefox? Liegt es daran, dass ich offline arbeite?

    Mystik!

  2. Hallo,

    <xsl:template match="resumee/p">
    xsl:choose<xsl:when test="position()=1"><p class="note"><xsl:copy-of select="." /></p></xsl:when>
    xsl:otherwise<p class="note_nextline"><xsl:copy-of select="." /></p></xsl:otherwise></xsl:choose>
    </xsl:template>

    Du redest vom Problemen mit <a>, dann stellst du aber dein Template zu <p> hier hinein.
    Wie dem auch: dein Templte produziert immer fehlerhaften Code: du erzeugst <p class="..."><p>text </p></p>.
    Mit: <xsl:template match="resumee/p"> bist du bereits im <p>, und <xsl:copy-of select="." /> kopiert diese <p> in deinem <p clas="..."></p>.

    Das könnte auch dann natürlich andere Probleme im Bowser verursachen, auch welche mit <a>.

    Grüße
    Thomas

    1. Hallo,

      »» <xsl:template match="resumee/p">
      »» xsl:choose<xsl:when test="position()=1"><p class="note"><xsl:copy-of select="." /></p></xsl:when>
      »» xsl:otherwise<p class="note_nextline"><xsl:copy-of select="." /></p></xsl:otherwise></xsl:choose>
      »» </xsl:template>
      »»

      Du redest vom Problemen mit <a>, dann stellst du aber dein Template zu <p> hier hinein.

      Tut mir leid, es ist ein wenig verschachtelt. Die <a>s sind im <p> drin.

      Wie dem auch: dein Templte produziert immer fehlerhaften Code: du erzeugst <p class="..."><p>text </p></p>.
      Mit: <xsl:template match="resumee/p"> bist du bereits im <p>, und <xsl:copy-of select="." /> kopiert diese <p> in deinem <p clas="..."></p>.

      Das könnte auch dann natürlich andere Probleme im Bowser verursachen, auch welche mit <a>.

      Grüße
      Thomas

      Oh, das habe ich übersehen. Ich habe <xsl:copy-of select="." /> jetzt durch <xsl:copy-of select="node()" /> ersetzt. Allerdings muss ich leider sagen, dass das Ergebnis nicht sonderlich vom vorigen unterscheidet ...

      <img alt="#" class="list_pre" src="icons/book.png"/>
      <div class="list_entry">
      <p class="list_top"><strong>Autor:</strong> <cite>Titel</cite>. Verlag.</p>
      <p class="list_sub">ISBN: 123-456-789-0</p>
      <p class="tag">Tag1, Tag2</p>
      <p class="note">Hier steht die Anmerkung mit einem <a href="http://www.example.com">Link</a> drin</p>
      </div><div class="clear"/>

      So sieht der Quelltext jetzt aus, und ich habe wirklich nichts daran auszusetzen, leider auch gar keine Ahnung mehr, woran es nun noch liegen könnte ... oO

      1. Hallo,

        Oh, das habe ich übersehen. Ich habe <xsl:copy-of select="." /> jetzt durch <xsl:copy-of select="node()" /> ersetzt. Allerdings muss ich leider sagen, dass das Ergebnis nicht sonderlich vom vorigen unterscheidet ...

        <xsl:copy-of select="child::node()" />

        Ansonsten bitte doch ein Stück von deinem XML so zu posten wie es tatsächlich vorhanden ist und das gleiche beim XSL.

        Grüße
        Thomas

        1. Gut, also hier der XSL-Code:

          <?xml version="1.0" encoding="utf-8"?>  
            
          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">  
          <xsl:output method="xml" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" indent="yes" />  
            
          <xsl:key name="_sachgebiet" match="eintrag" use="sachgebiet" />  
            
          <xsl:template match="/">  
            
          <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">  
          <head>  
            
          <title>Accipiter Media</title>  
          <meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />  
          <meta http-equiv="content-language" content="de-DE" />  
          <meta http-equiv="content-style-type" content="text/css" />  
            
          <link rel="stylesheet" type="text/css" href="global.css" />  
          <link rel="shortcut icon" type="image/x-icon" href="http://www.accipiter-media.de/design/favicon.ico" />  
            
          </head>  
            
          <body>  
          <div class="main">  
          <div class="content">  
            
          <h2>Literaturverzeichnis</h2>  
            
          <p>Alle Angaben sind ohne Gewähr.</p>  
          <div class="list_entry"><p class="note">Dies ist ein Blindtext, in den ein externer <a href="http://www.google.de">Link</a> eingebettet ist.</p></div>  
            
          <img src="http://www.accipiter-media.de/images/hr.png" alt="&#x00A0;" style="height: 3px; width: 100%;" />  
            
          <xsl:apply-templates select="liste" />  
            
          </div>  
          </div>  
          </body>  
          </html>  
            
          </xsl:template>  
            
          <xsl:template match="liste">  
          <xsl:for-each select="eintrag[count(. | key('_sachgebiet', sachgebiet)[1]) = 1]"><xsl:sort select="sachgebiet" />  
          <h3><a><xsl:attribute name="name"><xsl:value-of select="sachgebiet" /></xsl:attribute></a><xsl:value-of select="sachgebiet" /></h3>  
            
          <xsl:apply-templates select="key('_sachgebiet', sachgebiet)">  
          <xsl:sort select="a_sort" /><xsl:sort select="autor" /><xsl:sort select="t_sort" /><xsl:sort select="titel" />  
          </xsl:apply-templates>  
          </xsl:for-each>  
          </xsl:template>  
            
          <xsl:template match="eintrag">  
            
          <img alt="#" class="list_pre" src="icons/book.png" />  
            
          <div class="list_entry">  
          <p class="list_top"><strong><xsl:value-of select="autor" />:</strong><xsl:text> </xsl:text><cite><xsl:value-of select="titel" /></cite><xsl:choose><xsl:when test="substring(titel,string-length(titel),1)!='!' and substring(titel,string-length(titel),1)!='?'">.</xsl:when></xsl:choose><xsl:text> </xsl:text><xsl:value-of select="verlag" />.</p>  
          <p class="list_sub">ISBN: <xsl:value-of select="isbn" /></p>  
            
          <p class="tag"><xsl:apply-templates select="tag"><xsl:sort select="." /></xsl:apply-templates></p>  
            
          <p class="icon_generic"><img class="list-pre"><xsl:attribute name="src">icons/<xsl:value-of select="sprache/code" />.png</xsl:attribute><xsl:attribute name="alt"><xsl:value-of select="sprache/code" /></xsl:attribute></img>&#x00A0;<xsl:value-of select="sprache/lang" /></p>  
            
          <xsl:choose><xsl:when test="boolean(referenz)"><p class="reference"><a target="_blank"><xsl:attribute name="href"><xsl:value-of select="referenz" /></xsl:attribute>Referenz zur Datenbank <xsl:choose><xsl:when test="referenz[@org = 'dnb']">der Deutschen Nationalbibliothek</xsl:when><xsl:when test="referenz[@org = 'loc']">der <span lang="en">Library of Congress</span></xsl:when></xsl:choose></a></p></xsl:when></xsl:choose>  
            
          <xsl:choose><xsl:when test="boolean(resumee)"><xsl:apply-templates select="resumee/par" /></xsl:when></xsl:choose>  
          </div>  
          <div class="clear"></div>  
            
          </xsl:template>  
            
          <xsl:template match="resumee/par">  
          <xsl:choose><xsl:when test="position()=1"><p class="note"><xsl:copy-of select="child::node()" /></p></xsl:when>  
          <xsl:otherwise><p class="note_nextline"><xsl:copy-of select="child::node()" /></p></xsl:otherwise></xsl:choose>  
          </xsl:template>  
            
          <xsl:template match="tag">  
          <xsl:choose><xsl:when test="position()=last()"><xsl:value-of select="." /></xsl:when>  
          <xsl:otherwise><xsl:value-of select="." />, </xsl:otherwise></xsl:choose>  
          </xsl:template>  
            
          </xsl:stylesheet>
          

          Und der betreffende XML-Code:

            
          <?xml version="1.0" encoding="UTF-8"?>  
            
          <!DOCTYPE liste [  
            
          <!ELEMENT liste (eintrag+)>  
          <!ELEMENT eintrag (sachgebiet,autor,a_sort?,titel,t_sort?,verlag,isbn,sprache,tag+,referenz?,resumee?)>  
          <!ELEMENT autor (#PCDATA)>  
          <!ELEMENT a_sort (#PCDATA)>  
          <!ELEMENT titel (#PCDATA)>  
          <!ELEMENT t_sort (#PCDATA)>  
          <!ELEMENT verlag (#PCDATA)>  
          <!ELEMENT isbn (#PCDATA)>  
          <!ELEMENT sachgebiet (#PCDATA)>  
          <!ELEMENT tag (#PCDATA)>  
          <!ELEMENT sprache (code,lang)>  
          <!ELEMENT code (#PCDATA)>  
          <!ELEMENT lang (#PCDATA)>  
          <!ELEMENT referenz (#PCDATA)>  
          <!ATTLIST referenz org CDATA 'xxx'>  
          <!ELEMENT resumee (par+)>  
          <!ELEMENT par (#PCDATA|a|abbr|cite|q|strong|span)*>  
          <!ELEMENT a (#PCDATA)>  
          <!ATTLIST a href CDATA 'http://www.accipiter-media.de'>  
          <!ELEMENT abbr (#PCDATA)>  
          <!ATTLIST abbr title CDATA 'xxx'>  
          <!ELEMENT cite (#PCDATA)>  
          <!ELEMENT q (#PCDATA)>  
          <!ELEMENT span (#PCDATA|a|abbr|cite|q|strong)*>  
          <!ATTLIST span lang CDATA 'de'>  
          <!ELEMENT strong (#PCDATA)>  
            
          ]>  
            
          <?xml-stylesheet type="text/xsl" href="listebiblio.xsl" ?>  
            
          <liste>  
            
          <eintrag>  
          <sachgebiet>Belletristik und chinesische Literatur</sachgebiet>  
          <autor>Ba Jin</autor>  
          <titel>Die Familie</titel>  
          <t_sort>Familie, Die</t_sort>  
          <verlag>Oberbaum Verlag, Berlin/St. Petersburg 2002</verlag>  
          <isbn>3-933314-38-0</isbn>  
          <sprache><code>de-de</code><lang>Deutsch (Deutschland)</lang></sprache>  
          <tag>Belletristik</tag>  
          <referenz org="dnb">http://d-nb.info/964957752</referenz>  
          <resumee><par>Ba Jin erzählt die Chronik der Gaos, einer vier Generationen umfassenden feudalen Großfamilie im China der 20er Jahre, welche unter dem despotischen Regiment eines Greises leidet, der alles im alten konfuzianistischen alten Trott hält. Eingebundene Mädchenfüße und geldbringende Zwangshochzeiten inbegriffen! Doch die <a href="http://de.wikipedia.org/wiki/Bewegung_des_vierten_Mai">Studentenrebellion vom 4. Mai 1919</a> leitet einen radikalen Umbruch im Hause Gao ein, an dem letztendlich drei der vier weiblichen Hauptpersonen zugrunde gehen werden …</par></resumee>  
          </eintrag>  
            
          </liste>
          

          Puh, viel Code, aber so wird es vielleicht klarer ... Also nochmal: Der Tex innerhalb des <a>-Tags wird angezeigt, aber nur als normaler Text mit dem Hoover-Effekt, aber ohne normale Link-Auszeichnung (also in meinem Falle einfach nur schwarz, ohne Unterstreichung, anstatt wie gewünscht, grau mit Unterstreichung. Beim Drüberfahren mit der Maus allerdings ist es korrekt hellgrau mit Unterstreichung), außerdem fehlt schlicht und ergreifend die Verlinkung.

          Soweit ...

          1. Hallo,

            An sich ist alles in Ordnung und die Seite wird auch richtig angezeigt.... wenn man sie als HTML ansieht.

            Ich nehme an, du läßt die das XML im Browser anzeigen (und damit dort transformieren).

            Wenn du den problematischen Link anschaust, wird folgendes generiert:
            <a xmlns="" href="http://de.wikipedia.org/wiki/Bewegung_des_vierten_Mai">Studentenrebellion vom 4. Mai 1919</a>

            Das leere xmlns="" versursacht dann das Problem (zumindest im FF, Opera und Safari)

            Du hast zwei möglichkeiten: entweder machst du normales HTML 4.01 daraus, oder du machst folgendes:

              
            <xsl:template match="resumee/par">  
            		<xsl:choose>  
            			<xsl:when test="position()=1">  
            				<p class="note">  
            					<xsl:apply-templates />  
            				</p>  
            			</xsl:when>  
            			<xsl:otherwise>  
            				<p class="note_nextline">  
            					<xsl:apply-templates />  
            				</p>  
            			</xsl:otherwise>  
            		</xsl:choose>  
            	</xsl:template>  
              
            	<xsl:template match="resumee/par/a" >  
            		<a href="{@href}"><xsl:value-of select="."/></a>  
            	</xsl:template>  
            
            

            Grüße
            Thomas

            1. Wow! Danke, das habe ich nicht bemerkt! Ich würde gern XHTML ausgeben, daher würde ich mich wohl eher für die zweite Variante entscheiden, wobei mir sich dort allerdings eine weitere Frage aufdrängt:
              Bei den anderen Tags wie <span>, <q> und <abbr> funktioniert es ja auch schon allein mit dem copy-of-Tag und ohne weitere Sonderbehandlung. Müsste ich jetzt korrekterweise für diese Tags genauso verfahren? Denn im Quelltext steht ja vermutlich nachher z.B. im übertragenen Sinne auch

              <span xmlns="" lang="nl">dat is nederlands</span>

              habe ich das richtig verstanden? Ich müsste also diese paar Zeilen

              <xsl:template match="resumee/par/a" >
              <a href="{@href}"><xsl:value-of select="."/></a>
              </xsl:template>

              auch für die anderen Tags übernehmen, oder ist das egal? Ich möchte schließlich am Ende sauberen Quellcode haben :/

              Danke für die Hilfe! Ich muss gestehen, dass das etwas sehr weit in die Materie eingreift und ich mich soweit noch nicht damit befasst habe, aber offenbar komme ich nicht drum herum ...

              Gruß
              Jasper

              1. Gut, ich habe mir meine Frage gerade selbst beantwortet: Ja.

                Macht auch nichts. Nur noch in einem Punkt bin ich mir unsicher: Es kann vorkommen, dass innerhalb eines <span>-Tags noch ein Tag steht, beispielsweise ein <abbr>-Tag. Wie definiere ich das dann hier:

                <xsl:template match="resumee/par/a" >
                <a href="{@href}"><xsl:value-of select="."/></a>
                </xsl:template>

                bei "match" müsste dann ja sozusagen zwischen "par" und "a" noch stehen, dass dort noch weitere Tags stehen dürfen. Wie kennzeichnet man das?

                Danke für die Riesen-Hilfe, es klappt alles jetzt so wie gewünscht!
                *verbeug*

                Jasper

                1. Hallo, ich glaube, ich habe einen Ansatz gefunden ... Der ist allerdings nur möglich, da der <abbr>-Tag normalerweise recht kurz ist, und weder einen <span>- noch einen <a>-Tag umschließt.

                  <xsl:template match="resumee/par/span | resumee/par/a/span" >  
                  <span lang="{@lang}"><xsl:apply-templates /></span>  
                  </xsl:template>  
                    
                  <xsl:template match="resumee/par/a | resumee/par/span/a" >  
                  <a href="{@href}"><xsl:apply-templates /></a>  
                  </xsl:template>  
                    
                  <xsl:template match="resumee/par/abbr | resumee/par/span/abbr | resumee/par/a/abbr | resumee/par/a/span/abbr | resumee/par/span/a/abbr" >  
                  <abbr title="{@title}"><xsl:value-of select="." /></abbr>  
                  </xsl:template>
                  

                  Müsste ich den ganzen Schnodder jetzt auch noch für die <cite>- und <strong>-Tag machen? Wenn ja, dann hoffe ich wirklich um eine Möglichkeit die tausend Möglichkeiten abzukürzen ... Oha ... da habe ich mir offenbar mal wieder was aufgehalst.

                  Naja, ich bleibe tapfer und bastle weiter ...

                  1. Hallo,

                    Müsste ich den ganzen Schnodder jetzt auch noch für die <cite>- und <strong>-Tag machen?

                    Ja.
                    Aber du brauchst nicht unbedingt
                    <xsl:template match="resumee/par/abbr | resumee/par/span/abbr | resumee/par/a/abbr | resumee/par/a/span/abbr | resumee/par/span/a/abbr" >

                    Du kannst einfach  <xsl:template match="abbr"> etc. nehmen und dann immer <xsl:apply-templates /> in den Elementen.

                    Naja, ich bleibe tapfer und bastle weiter ...

                    Spaß muss sein.

                    Grüße
                    Thomas