Mike Deuter: Elementknoten im Xpath ausdruck abfragen?

Hi,

irgendwie hänge ich gerade wieder an einem kleinen Problem und sehe den Wald vor lauter Bäumen nicht. Ich möchte in einer for-each abfrage nur bestimmte knoten abfragen, und zwar nur auf solche, die genau die gleichen Unterknoten (childs) haben. Mit steht xslt 2.0 zur verfügung. Und zwar habe ich es mir so gedacht, dass ich zuerst die unterknoten, die ich aus anderen abfragen zusammenbaue als parameter etwa

<xsl:param name="PassendeUnterknoten">
<xsl:elemet name="child1" select="new1"/>
<xsl:elemet name="child2" select="new2"/>
<xsl:elemet name="child4" select="new4"/>
</xsl:param>

und eine abfrage wie folgt:

<xsl:for-each select="knotenmitchilds[????paramterabfrage_moeglich?????]>
<xsl:value select="NurDieKnotenMitDenGleichenChilds"/>
</xsl:for-each>

für eine for-each Abfrage auf folgen Baum sollten nur entsprechend der letzte ausgewählt werden. Ich kann das Ganze nur in einer select abfrage implementieren.

<root>
<knotenmitchilds>
<child1>new1</child1>
<child1>new2</child2>
<child1>new3</child3>
<child1>new4</child4>
</knotenmitchilds>
<knotenmitchilds>
<child1>new1</child1>
<child2>new2</child2>
<child3>new4</child3>
</knotenmitchilds>
<knotenmitchilds>
<child1>new1</child1>
<child2>new2</child2>
<child3>new3</child3>
<child4>new4</child4>
</knotenmitchilds>
<knotenmitchilds>
<child1>new1</child1>
<child2>new2</child2>
<child4>new4</child4>
</knotenmitchilds>
</root>

Die for-each Abfrage sollte jetzt entsprechen nur das letzte auswählen:
<knotenmitchilds>
<child1>new1</child1>
<child1>new2</child2>
<child1>new4</child4>
</knotenmitchilds>

Wie muss ich den Xpath Ausdruck setzten? Kann mir jemand einen Tipp geben?
Gruß, M.

  1. Hallo,

    irgendwie hänge ich gerade wieder an einem kleinen Problem und sehe den Wald vor lauter Bäumen nicht. Ich möchte in einer for-each abfrage nur bestimmte knoten abfragen, und zwar nur auf solche, die genau die gleichen Unterknoten (childs) haben. Mit steht xslt 2.0 zur verfügung. Und zwar habe ich es mir so gedacht, dass ich zuerst die unterknoten, die ich aus anderen abfragen zusammenbaue als parameter etwa

    <xsl:param name="PassendeUnterknoten">
    <xsl:elemet name="child1" select="new1"/>
    <xsl:elemet name="child2" select="new2"/>
    <xsl:elemet name="child4" select="new4"/>
    </xsl:param>

    Ich weiss nicht was das brngen soll, xsl:element erzeugt Elemente für die Ausgabe.

    und eine abfrage wie folgt:

    für eine for-each Abfrage auf folgen Baum sollten nur entsprechend der letzte ausgewählt werden. Ich kann das Ganze nur in einer select abfrage implementieren.

    Die for-each Abfrage sollte jetzt entsprechen nur das letzte auswählen:
    <knotenmitchilds>
    <child1>new1</child1>
    <child1>new2</child2>
    <child1>new4</child4>
    </knotenmitchilds>

    Wie muss ich den Xpath Ausdruck setzten? Kann mir jemand einen Tipp geben?

    Amn einfachsten:
    <xsl:for-each select="knotenmitchilds[child1 and child2 and child4 and (count(child::*) = 3)][position() = last()]">
      <xsl:copy-of select="." />
                    <!-- oder value-of -->
     </xsl:for-each>

    Aber ich weiss nicht so genau was du machen/erreichen willst.

    Grüße
    Thomas

    1. Hallo Thomas,

      genau so hatte ich auch das Ganze zuerst geschrieben, aber die Anzahl der Unterknoten 8die ich aus anderen Abfragen erhalte) ändert sich und ich moechte den Code sauber halten und nicht für alle Verianten von Childs eine separate for-each anweisung schreiben. Vielmehr dachte ich daran, eine variable zu benutzen, die die Child "aufnimmt" und mit der ich dann ein for-each anweisung benutzen kann.

      Das Ergebnis einer anderen Anfrage ist etwa so, dass ich entweder 2 unterknoten oder 4 unterknoten erhalte. Nun moechte ich nicht einmal

      for-each select="something[child1 and child2 and child3 and child4]

      bzw.

      for-each select="something[child1 and child2] schreiben sonder das Ganze in ein for-each Anweisung packen

      Etwas verständlicher?

      1. Hallo,

        Das Ergebnis einer anderen Anfrage ist etwa so, dass ich entweder 2 unterknoten oder 4 unterknoten erhalte. Nun moechte ich nicht einmal

        for-each select="something[child1 and child2 and child3 and child4]
        for-each select="something[child1 and child2] schreiben sonder das Ganze in ein for-each Anweisung packen

        Etwas verständlicher?

        Ja.
        Was mir einfällt ist, dass du sowohl die Kindelemente als auch deren Anzahl asl Paramter übergibst: was du ja versucht hast, nur dass das mit xsl:element nicht klappen kann.
        Also ist die Frage eher: woher holst du die Informationen in den/die Parameter hinein.

        Grüße
        Thomas

        1. Nun ja, ich lasse eine Abfrage starten, und bei gewissen Merkmalen soll er mir die Ergebnisse herausgeben, Als Ergebnis bekomme ich dann zum Beispiel drei Werte (oder auch vier oder nur eine usw.). Abhängig von den Ergebnissen soll er mir (sagen wir aus einer anderen xml datei, genau die knoten selektieren in einer for-each anweisung, die eben genau diese drei Werte als unterelemente in form von textknoten enthalten.

          Also neuer Versuch ;-)

          <xsl:template match="somenodes">
          <xsl:if test="bestimmteskriterium>
          <xsl:for-each select="ergbnisholen">
          <!-- hier werden nun ergebnisse ausgelesen -->
          <ergbnis>
          <xsl:value-of select="."/>
          </ergbnis>
          </xsl:for-each>
          </xsl:if>

          <xsl:for-each select="document('some.xml')/knoten[???????]>
          <!-- hier sollen nun die knoten ausgewählt werden, die gerade als unterknoten genau die enthalten, die bei der ersten for-each anweisung herausgekommen sind -->

          </for-each>

          </xsl:template>

          Ein etwas unschönes Beispiel auf die kürze, aber es geht mir einfach nur darum, ob man in einem Xpath ausdruck das child nodeset mit einem selbst erstellten nodeset vergleichen kann und sofern das child nodeset mit einem nodeset von einer variable übereinstimmt den knoten auswählen soll.

        2. Hallo Thomas,

          gibt es eine Methode vergleichbar der XPath intersect (ab XPath 2.0). Dachte nun, dass ich es mit intersect hinbekomme, aber scheinbar zielt es auf eindeutigkeit und vergleicht nicht einfach nur ein knotenset mit einem anderen, schade eigentlich.

          1. Hallo,

            gibt es eine Methode vergleichbar der XPath intersect (ab XPath 2.0).

            Das wäre in XPath 1.0 so (Leerzeichen wegen Übersichtlichkeit):

            $nodeset1 [ count( . | $nodeset2 ) = count( $nodeset2 ) ]

            Der Ausdruck selektiert Knoten die sowohl im $nodeset1 als auch im $nodeset2 erhalten sind.

            Das Gegenteil wäre:
              $nodeset1 [ count( . | $nodeset2 ) != count( $nodeset2 ) ]

            Dachte nun, dass ich es mit intersect hinbekomme, aber scheinbar zielt es auf eindeutigkeit und vergleicht nicht einfach nur ein knotenset mit einem anderen, schade eigentlich.

            Ja, denn der Equivalent von den XPath 1 Ausdrücken wäre:

            "$nodeset1 interset $nodeset2" bzw. "$nodeset1 except $nodeset2"

            Ein anderen Test wäre in XPath 2:
             if($node interset $andereNode/descendant::node()) then ...

            Wenn $node ist unter den Nachfolger von $andereNode, dann lifert die Abfrage "wahr".

            Ich denke, dass mein Problem ist, dass ich nicht wirklich verstehe, was zu erreichen willst bzw. was du machen willst.
            Aber eines geht nicht: wenn du neue Elemente generierst (xsl:element etc.) kannst du diese nicht mit vorhandenen Elemente vergleichen: zumindest nicht mit einfach Funktionen oder boolschen Vergleichen, weil die meisten solche Funktionen auf Gleichheit (identisch) prüfen. Dazu müsstest du auf local-name(), text() etc. prüfen.

            Grüße
            Thomas

            1. Hallo Thomas,

              habe mich nun durch verschiedene Seite gekämpft. Also kurz beschrieben, ich möchte ein knotenset mit einem anderen knotenset vergleichen, so einfach. Für den Vergleich ist es notwendig, das bei dem knotenset folgende bedingen erfüllt sind:

              liefere boolean true wenn:

              • anzahl der knoten in beiden knotensets gleich ist;
              • local-name und namespace des Elements sowie Attribute als auch Textknoden (text())gleich sind
              • Die Reihenfolge der Knoten ist egal.

              Gegenwärtig habe ich es mit einer xsl Funktion gelöst, die das knotenset in einen string umwandelt und dann vergleich ich beide strings, diese lösung ist aber nicht gerade sehr schnell.

              Gruß, M.