André Laugks: Baum zur Tranformierung anlegen

Hallo!

Ich habe folgendes XML-Dokument gegeben. Ich möchte damit folgendes machen. Es soll nach den Namen sortiert werden und zu jedem Namen dessen Vorgänger und Nachfolger ermittelt werden. Das Problem ist, bei der Ermittlung des Vorgängers und Nachfolgers, wird die Reihenfolge der Elemente im XML-Dokumentes verwendet und nicht die sortierte Reihenfolge.

Das Dokument mit dem ich experimentiere ist viel viel viel umfangreicher als das hier aufgeführte. Kann ich ein virtuelles XML-Dokument generieren bzw. Teilbäume virtuell extrahieren und zusammen fassen, mit denen ich arbeiten kann? Ich baue also für die Tranformierungsvorgang virtuell ein Dokument bzw. Baum auf, in dem alle Element "eintrag" sortiert nach dem Element "name" stehen. In diesem Baum kann ich dann schön den Vorgänger und Nachfolger ermitteln.

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="zappen.xsl" type="text/xsl"?>
<liste>
 <eintrag id="10">
  <name>Berta</name>
 </eintrag>
 <eintrag id="3">
  <name>Anton</name>
 </eintrag>
 <eintrag id="9">
  <name>Dieter</name>
 </eintrag>
 <eintrag id="12">
  <name>Werner</name>
 </eintrag>
 <eintrag id="17">
  <name>Gerd</name>
 </eintrag>
 <eintrag id="8">
  <name>Christian</name>
 </eintrag>
 <eintrag id="6">
  <name>Lisa</name>
 </eintrag>
 <eintrag id="5">
  <name>Inge</name>
 </eintrag>
 <eintrag id="16">
  <name>Friedrich</name>
 </eintrag>
</liste>

<?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"/>

<xsl:template match="liste">
  <table border="1">
   <tr>
    <td>Vorgänger</td>
    <td>x</td>
    <td>Nachfolger</td>
   </tr>
   <xsl:apply-templates select="eintrag">
    <xsl:sort select="name"/>
   </xsl:apply-templates>
  </table>
 </xsl:template>

<xsl:template match="eintrag">
  <tr>
   <td><xsl:value-of select="preceding-sibling::eintrag[1]/name"/></td>
   <td><xsl:value-of select="name"/></td>
   <td><xsl:value-of select="following-sibling::eintrag[1]/name"/></td>
  </tr>
 </xsl:template>

</xsl:stylesheet>

MfG, André Laugks

--
L-Andre @ gmx.de
  1. Hi,

    Ich habe folgendes XML-Dokument gegeben. Ich möchte damit folgendes machen. Es soll nach den Namen sortiert werden und zu jedem Namen dessen Vorgänger und Nachfolger ermittelt werden. Das Problem ist, bei der Ermittlung des Vorgängers und Nachfolgers, wird die Reihenfolge der Elemente im XML-Dokumentes verwendet und nicht die sortierte Reihenfolge.

    <xsl:template match="eintrag">
      <tr>
       <td><xsl:value-of select="preceding-sibling::eintrag[1]/name"/></td>

    kein Wunder, die sibling-Teile gehen auf die Dokumentstruktur.

    Verwende position() - laß Dir das Element mit der aktuellen position() - 1 und das mit der aktuellen position() + 1 auswählen.

    cu,
    Andreas

    --
    Der Optimist: Das Glas  ist halbvoll.  - Der Pessimist: Das Glas ist halbleer. - Der Ingenieur: Das Glas ist doppelt so groß wie nötig.
    http://mud-guard.de/? http://www.andreas-waechter.de/ http://www.helpers.de/
    1. Hallo!

      wird die Reihenfolge der Elemente im XML-Dokumentes verwendet und nicht die sortierte Reihenfolge.

      kein Wunder, die sibling-Teile gehen auf die Dokumentstruktur.

      Das habe ich ja auch schon fest gestellt bzw. ist mir klar.

      Verwende position() - laß Dir das Element mit der aktuellen position() - 1 und das mit der aktuellen position() + 1 auswählen.

      Soweit war ich auch schon, nur irgendwie kommt nichts.

      <xsl:template match="eintrag">
        <tr>
          <td><xsl:value-of select="position()"/></td>
          <td><xsl:value-of select="../eintrag[position() - 1]/name"/></td>
          <td><xsl:value-of select="name"/></td>
          <td><xsl:value-of select="../eintrag[position() + 1]/name"/></td>
        </tr>
      </xsl:template>

      Wenn ich anstatt der XPath-Audrücke "../eintrag[position() - 1]/name" oder "../eintrag[position() + 1]/name" den XPath-Ausdruck "../eintrag/name" schreibe, bekomme ich wie erwartet "Berta", also das erste Element "eintrag/name" aus dem XML-Dokument. Der Pfad stimmt also.

      MfG, André Laugks

      --
      L-Andre @ gmx.de
      1. Hi,

        <td><xsl:value-of select="../eintrag[position() - 1]/name"/></td>

        Müßte m.E. so lauten (ungetestet):
        ../eintrag[position() = (./position()-1)

        cu,
        Andreas

        --
        Der Optimist: Das Glas  ist halbvoll.  - Der Pessimist: Das Glas ist halbleer. - Der Ingenieur: Das Glas ist doppelt so groß wie nötig.
        http://mud-guard.de/? http://www.andreas-waechter.de/ http://www.helpers.de/
        1. Hallo!

          Müßte m.E. so lauten (ungetestet):
          ../eintrag[position() = (./position()-1)

          Nein, das Funktioniert nicht. Der Prozessor regt sich über "./" auf.

          Folgende Konstrukt liefert mir aber auch nur die Reihenfolge des XML-Dakumentes, für den Vorgänger und Nachfolger.

          <xsl:template match="eintrag">

          <xsl:variable name="v">
              <xsl:value-of select="position() + 1"/>
            </xsl:variable>

          <xsl:variable name="z">
              <xsl:value-of select="position() - 1"/>
            </xsl:variable>

          <tr>
              <td><xsl:value-of select="$z"/></td>
              <td><xsl:value-of select="$v"/></td>
              <td><xsl:value-of select="position()"/></td>
              <td><xsl:value-of select="../eintrag[position() = $z]/name"/></td>
              <td><xsl:value-of select="name"/></td>
              <td><xsl:value-of select="../eintrag[position() = $v]/name"/></td>
            </tr>

          </xsl:template>

          Hier lass ich ja die Variablen mitlaufen. Die Werte sind wie erwartet. Schreibe ich nun aber z.B. "../eintrag[position() = $v]/name" um in "../eintrag[$v]/name" bekomme ich immer nur Berta angezeigt, also der erste Name im XML-Dokument. Schreibe ich aber für $v eine Zahl rein, also 1, 2, 3, 4 usw. ("../eintrag[2]/name" -> Anton), bekomme ich immer den betreffenden Namen zurück, wie erwartet.

          MfG, André Laugks

          --
          L-Andre @ gmx.de
          1. Hi,

            <td><xsl:value-of select="../eintrag[position() = $z]/name"/></td>

            War das nicht ${v} ?

            Hab zu lange kein XSL mehr gemacht...

            cu,
            Andreas

            --
            Der Optimist: Das Glas  ist halbvoll.  - Der Pessimist: Das Glas ist halbleer. - Der Ingenieur: Das Glas ist doppelt so groß wie nötig.
            http://mud-guard.de/? http://www.andreas-waechter.de/ http://www.helpers.de/
        2. Hallo Andreas,

          <td><xsl:value-of select="../eintrag[position() - 1]/name"/></td>

          Müßte m.E. so lauten (ungetestet):
          ../eintrag[position() = (./position()-1)

          Kann nicht gehen.
          <td><xsl:value-of select="position()"/></td> liefert die Position die "eintrag" beim sortieren bekommt.
          Alle anderen konstrukte mit position() beziehen sich aber auf die tatsächliche Position vom "eintrag" im Dokument.

          Grüße
          Thomas