Orlanski: Links separieren

Guten Morgen,

ich habe ein Problem, welches in Gedanken gelöst ist, ich aber nicht die richtigen Funktionen bzw. wie ich diese anwenden kann, noch nicht gefunden.

Folgende Datei ist gegeben:

<Sect>
<Standard>Hallo
<Link>1 </Link>
</Standard>

<Standard>Hallo
<Link>mail@irgendwas.de</Link>
</Standard>

<Standard>Hallo
<Link>www.yahoo.de </Link>
</Standard>

<Standard>Hallo
<Link>2 </Link>
</Standard>

<!-- Weiter unten stehen dann Fußnoten:-->

<Footnote>
<Fußnotentext>1 erste </Fußnotentext>
<Fußnotentext>2 zweite </Fußnotentext>
</Footnote>

<Sect>

Das Fußnotenzeichen wird dabei als <Link> gespeichert. Ich muss also untersuchen, ob der Link ein 'www' oder '@' oder 'http://' enthält. Bei den anderen Linkelementen muss es sich ja dann um eine Fußnote handeln. Dabei soll der Fußnotentext in den entsprechenden Link in Klammern gesetzt werden - die Fußnotenzahl entfällt.Dies hab ich auch realisiert:

...
<xsl:template match="Standard/Link">
  xsl:choose
    <xsl:when test="contains(current(),'@')">
     <xsl:element name="a">
      <xsl:attribute name="href">mailto:<xsl:value-of select="."/></xsl:attribute>
        <xsl:value-of select="."/>
     </xsl:element>
    </xsl:when>
    <xsl:when test="contains(current(),'www') or contains(current(),'http://')">
      <xsl:element name="a">
       <xsl:attribute name="href"><xsl:value-of select="."/></xsl:attribute>
        <xsl:value-of select="."/>
      </xsl:element>
     </xsl:when>
     xsl:otherwise
<!-- IF- Bedingung -->
      <xsl:element name="span">
       <xsl:attribute name="class">Footnote</xsl:attribute>
     xsl:text( </xsl:text>
     <xsl:copy-of select="substring-after(//Sect/Footnote/Fußnotentext,' ')"/>
     xsl:text) </xsl:text>
      </xsl:element>
     </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="Footnote"/>
<xsl:template match="Fußnotentext"/>

  • Standard als <p>Tag

Das ergibt dann folgende Ausgabe:

<p>Hallo <span class="Footnote">(erste)</span></p>
<p>Hallo <a href="mailto:mail@irgendwas.de">mail@irgendwas.de</a></p>
<p>Hallo <a href="www.yahoo.de">www.yahoo.dey</a></p>
!!<p>Hallo <span class="Footnote">(erste)</span></p>!!

Die Fallunterscheidung zwischen Links,Webadresse und Fußnote funktioniert.
Das Problem: er erkennt die folgenden Fußnotentexte nicht. So sollte er bei der letzten eigentlich ausgeben:
<p>Hallo <span class="Footnote">(zweite)</span></p>

Dann dachte ich mir, ich zähle die Position aller Links, die nicht www, http:// oder @ enthalten und vergleiche den Wert mit der Position der Fußnotentexte. Wenn diese übereinstimmt, dann handelt es sich um den richtigen Fußnotentext für den entsprechenden Link. Dies wollte ich als if- bedingung einbauen -siehe oben. Allerdings bekomme ich keine richtige Syntax hin. Es müsste ja so in der Form von count(nur die Links, welche not contains (.,'www') and not contains(.... usw.) =Position(Footnote/Fußnotentexte).

nur kriege ich das nich hin. Hat jemand ne Idee? Ist das überhaupt richtig, mit count und position ranzugehen?

  1. Hallo,

    Guten Morgen,

    Dir auch ;-)

    [...] Dies hab ich auch realisiert:

    ...
    <xsl:template match="Standard/Link">

    [...]

    </xsl:template>

    Machen wir das etwas kürzer:
     <xsl:template match="Standard/Link">
      xsl:choose
       <xsl:when test="contains(current(),'@')">
        <a href="mailto:{.}">
         <xsl:value-of select="."/>
        </a>
       </xsl:when>
       <xsl:when test="contains(current(),'www') or contains(current(),'http://')">
        <a href="{.}">
         <xsl:value-of select="."/>
        </a>
       </xsl:when>
       xsl:otherwise
        <xsl:variable name="fntNr" select="substring(.,1,1)" />
        <span class="Footnote">
         (<xsl:value-of select="substring-after(/Sect//Footnote[Fußnotentext[starts-with(., $fntNr)]]/Fußnotentext,' ')"/>)
        </span>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>

    Das Problem: er erkennt die folgenden Fußnotentexte nicht. So sollte er bei der letzten eigentlich ausgeben:

    Das copy-of (was eh nicht so eine gute Idee ist) hat keinen Unterschiedungsmerkmal, also nimmt er immer das erste Fußnotentext was im über den Weg läuft.

    nur kriege ich das nich hin. Hat jemand ne Idee? Ist das überhaupt richtig, mit count und position ranzugehen?

    Nein, weil position() immer kontextabhängigist und der Kontext kann sich schon mal schnell ändern.

    Grüße
    Thomas

    1. Guten Morgen,

      also Thomas, ich hab mal noch folgendes geändert, weil es vorher nicht funktioniert hat:

      ...
         xsl:otherwise
          <xsl:variable name="fntNr" select="substring(.,1,1)" />
          <span class="Footnote">
           (<xsl:value-of select="substring-after(//Sect/Footnote/Fußnotentext[starts-with(., $fntNr)],' ')" />)
          </span>
         </xsl:otherwise>

      Das funktioniert, aber eben nur fast.

      Erstellt wird immer <span class="Footnote"></span> und die Fallunterscheidung funktioniert auch.

      Allerdings wird nur jede zweite Fußnote genommen, also:

      <p>Hallo<span class="Footnote"<(erste)</span></p>
      <p>Hallo<a href="www.yahoo.de">www.yahoo.de</a></p>
      <p>Hallo<span class="Footnote"<()</span></p>
      <p>Hallo<span class="Footnote"<(dritte)</span></p>
      usw.
      also wird der Inhalt von jeder zweiten, vierten, sechsten etc. nicht in die Klammern eingeladen.

      Gibt es da ne logische Erklärung? Bzw. ne Lösung?

      1. Hallo,

        also wird der Inhalt von jeder zweiten, vierten, sechsten etc. nicht in die Klammern eingeladen.

        Gibt es da ne logische Erklärung? Bzw. ne Lösung?

        Das sieht _sehr_ danach aus, dass du irgendwo in deinem XSL eine Sortierung mittels position() machst (innerhalb eines for-each, oder gleich im select vom for-each selbst) und dass du dein Template dann in diesen Kontext aufrufst (oder du hast die ganze Sache bereits in einem for-each und nicht in einem Template?).

        Da spielen oft die Zeilenumbrüche (weil white-space) eine Rolle. Eventuell hilft da ein: <xsl:strip-space elements="*" />
        http://de.selfhtml.org/xml/darstellung/xsltelemente.htm#strip_space

        Ohne mehr vonm XLS gesehen zu haben kann ich dir aber auch nichts genaures sagen.

        Grüße
        Thomas

        1. Hallo Thmoas,

          ich habe den Fehler gefunden. der Fehler lag nicht in der XSL, sondern in der XML Datei. Beim erstellen der XML Datei kommt es zu einem Fehler:

          <Footnote>
            <Fußnotentext>1 erster Text</Fußnotentext>
            <Fußnotentext>
              <Superscript/>
            2 zweiter Text
            </Fußnotentext>
          usw.
          </Footnote>

          d.h. in jeden zweiten Fußnotentext wird ein <Superscript> geschrieben. Das ist jedoch nicht weiter schlimm. Durch den Umbruch, scheint die XSL jedoch das Problem zu haben, dass es die $fntNr nicht findet, sondern den Umbruch und damit das einladen nicht ausführt.Ändere ich dies manuell so:
          ...
          <Fußnotentext><Superscript/>2 zweiter Text</Fußnotentext>
          ...
          funktioniert das einladen. Der Umbruch ist nicht als Zeichen erkennbar und es funktioniert keine Verarbeitung mit normalize-space() oder xsl:strip-space. Irgendwie kommt mir das seltsam vor, da man doch gelernt hat, dass Umbrüche keine Auswirkungen haben, bis auf eine Ausgabe mit <pre>. Hat da jemand ne Erklärung dafür?

          1. Hallo,

            ich habe den Fehler gefunden. der Fehler lag nicht in der XSL, sondern in der XML Datei.

            Der Umbruch ist nicht als Zeichen erkennbar und es funktioniert keine Verarbeitung mit normalize-space() oder xsl:strip-space.

            Den Satz verstehe ich nicht.

            Irgendwie kommt mir das seltsam vor, da man doch gelernt hat, dass Umbrüche keine Auswirkungen haben, bis auf eine Ausgabe mit <pre>. Hat da jemand ne Erklärung dafür?

            <pre> (und HTML) hat in der Hinsicht nichts mit XML zu tun.

            <xsl:variable name="fntNr" select="substring(.,1,1)" /> wählt '1', '2', '3', '4' etc,

            <Fußnotentext>
                <Superscript/>
              2 zweiter Text
              </Fußnotentext>

            Hier startet der Inhalt vom Fußnotentext mit einem Zeilenumbruch (und weil der Inhalt aus Unterlement und PCDATA besteht, nimmt der Prozessor "mixed content" an und berücksichtigt ihn.)

            Daher konnte das:

            <xsl:value-of select="substring-after(/Sect//Footnote[Fußnotentext[starts-with(., $fntNr)]]/Fußnotentext,' ')"/>

            eben nicht stimmen, weil das erste Zeichen hier der Umruch ("000A" (&#xA;)) und nicht 1,2,3... war.

            Grüße
            Thomas

            1. Guten Morgen,

              ich hatte mich da wohl falsch ausgedrückt. Ich verstehe die Prozedur soweit, mir ist auch klar, dass diese wegen den Umbruch nicht anläuft. Meine Frage bezog sich darauf, ob es eine Möglichkeit gibt, den Umbruch zu entfernen, per XSL Funktion oder ähnlichen? Quasi eine ähnliche Funktion wie normalize-space(), bloß eben, dass der Umbruch vor der Verarbeitung weggenommen wird - so würde ja auch die Zahl wieder das erste Zeichen sein.

              Und was ich meinte, mit

              Irgendwie kommt mir das seltsam vor, da man doch gelernt hat, dass Umbrüche keine Auswirkungen haben, bis auf eine Ausgabe mit <pre>. Hat da jemand ne Erklärung dafür?

              war, dass wenn ich schreibe:
                <Standard>hallo,
                wie gehts</Standard>
              wird ja der Umbruch bei der Ausgabe nicht berücksichtigt und alles wird auf einer Zeile ausgegeben. Das heißt ja dann, dass Umbrüche bei einer Ausgabe keine Rolle spielen, bei Kontroll- oder Verarbeitunsanweisungen schon (siehe oben).

              1. Hallo,

                ich hatte mich da wohl falsch ausgedrückt. Ich verstehe die Prozedur soweit, mir ist auch klar, dass diese wegen den Umbruch nicht anläuft. Meine Frage bezog sich darauf, ob es eine Möglichkeit gibt, den Umbruch zu entfernen, per XSL Funktion oder ähnlichen? Quasi eine ähnliche Funktion wie normalize-space(), bloß eben, dass der Umbruch vor der Verarbeitung weggenommen wird - so würde ja auch die Zahl wieder das erste Zeichen sein.

                Ja, eben normalize-space()
                <span class="Footnote">
                     (<xsl:value-of select="normalize-space(substring-after(/Sect//Footnote[Fußnotentext[normalize-space(starts-with(., $fntNr))]]/Fußnotentext,' '))"/>)
                    </span>

                Oder z.B. mit <xsl:strip-space elements="*" />: http://de.selfhtml.org/xml/darstellung/xsltelemente.htm#strip_space

                Und was ich meinte, mit

                Irgendwie kommt mir das seltsam vor, da man doch gelernt hat, dass Umbrüche keine Auswirkungen haben, bis auf eine Ausgabe mit <pre>. Hat da jemand ne Erklärung dafür?

                war, dass wenn ich schreibe:
                  <Standard>hallo,
                  wie gehts</Standard>
                wird ja der Umbruch bei der Ausgabe nicht berücksichtigt und alles wird auf einer Zeile ausgegeben.

                Das kommt sehr darauf an, wie die Verarbeitung die Ausgabe steuert.

                Das heißt ja dann, dass Umbrüche bei einer Ausgabe keine Rolle spielen, bei Kontroll- oder Verarbeitunsanweisungen schon (siehe oben).

                Der XML-Prozessor muss jedes Zeichen an die verarbeitende Anwendung weitergeben, so auch die Zeilenumbrüche. Was die Anwendung (z.B. XSLT-Prozessor) dann damit macht, ist Sache des Programmierers (z.B. wie man die Ausgabe bestimmt)

                Grüße
                Thomas

                1. Hallo,

                  ja, ich hab das mit position() und xsl:strip-space probiert, aber ohne Wirkung. In beiden ist auch immer die Rede von Leeraumzeichen. Diese werden auch entfernt,aber Umbrüche bei dieser Verarbeitungsanweisung mit dem einladen des Fußnotentext nicht. Viel verkehrt machen kann man ja nicht.
                  Ist aber erstmal nicht so schlimm. Es hatte mich einfach nur gewundert.

                  Ich bedanke mich für deine Hilfe Thomas.

                  have a nice day