molily: Alternative im XPath-Ausdruck

Hallo Leute,

ich habe folgenden XPath-Ausdruck:

descendant::li[contains(@class, 'own-posting')]/ul/li[not(contains(@class, 'visited'))]/span[contains(@class, 'posting')]
|
descendant::li[contains(@class, 'own-posting')]/ul/li[not(contains(@class, 'visited'))]/span/span[contains(@class, 'posting')]

D.h. da kann noch ein zusätzliches span dazwischen stehen.

(Anmerkung: Ich kann nicht einfach descendant::span verwenden, das würde falsche Resultate liefern.)

Durch diese Oder-Verknüpfung ist der Ausdruck natürlich genau doppelt so lahm. Im Prinzip bräuchte ich ja nur ein

descendant::li[contains(@class, 'own-posting')]/ul/li[not(contains(@class, 'visited'))]/(span | /span/span)[contains(@class, 'posting')]

Aber dieses (span | /span/span) in der Mitte ist ein Syntaxfehler. Anscheinend kann ich die Klammerung nur auf den gesamten Ausdruck anwenden, was ihn aber stark verlangsamt.

Wie kann ich das hinsichtlich Performance optimieren und weniger redundant notieren?

Mathias

  1. Hallo Mathias,

    (Anmerkung: Ich kann nicht einfach descendant::span verwenden, das würde falsche Resultate liefern.)

    Liefert auch descendant::span[last()] falsche Resultate?

    Grüße,
    Thomas

    1. Hallo,

      Erstmal danke für die Antwort!

      Liefert auch descendant::span[last()] falsche Resultate?

      Es geht um die Postingliste hier im Forum, da ist die Struktur folgendermaßen:

      ...
      <li>
         (<span>)<span class="posting">P1</span>(</span>)
         <ul>
            <li>
               (<span>)<span class="posting">P2</span>(</span>)
               (mglw. wieder verschachtelte ul-Elemente, ad infinitum)
            </li>
         </ul>
      </li>
      ...

      Ausgehend vom oberen gefundenen li-Element benötige ich das zugehörige span (im Beispiel das mit P1), nicht aber die spans auf einer tieferen Verschachtelungsebene (wie P2).

      descendant::span[last()] würde mir, soweit ich das verstehe, keines der beiden liefern.

      Dieses blöde optionale span (das kommt vom Scoring-Filter) vermiest mir alles.

      Mathias

      1. Hallo Mathias,

        Ausgehend vom oberen gefundenen li-Element benötige ich das zugehörige span (im Beispiel das mit P1), nicht aber die spans auf einer tieferen Verschachtelungsebene (wie P2).

        Probiere es mal so: li[not(@class='visited')][span[@class='posting'] | span/span[@class='posting']]

        Grüße,
        Thomas

        1. Hallo!

          Probiere es mal so: li[not(@class='visited')][span[@class='posting'] | span/span[@class='posting']]

          Die Idee hatte ich auch schon, aber wie ich vermutete, liefert mir das alle li-Elemente, für die die Bedingung im [...] zutrifft.

          Nun brauche ich letztlich die span-Elemente, weil ich aus deren Kindelementen Daten auslesen will. Ich müsste mich also noch im DOM herunter hangeln oder den (span | span/span)-Teil mit weiteren XPath-Abfragen wiederholen.

          Ich habe jetzt mal folgende Variante gewählt und die Sache vereinfacht:

          Zuerst hole ich mir alle li-Elemente:
          descendant::li[contains(@class, 'own-posting')]/ul/li[not(contains(@class, 'visited'))]

          Durchlaufe diese Elemente und hole mir jeweils das span-Element:
          (span | span/span)[contains(@class, 'posting')]

          Und letztlich die Daten, die ich daraus brauche:
          span[contains(@class, 'subject')]/a
          span[contains(@class, 'author')]

          Jetzt bin ich bei Firefox 2 bei 32ms, und da ich für neuere Browser auf das viel schnellere querySelectorAll setze, lohnt es sich glaube ich nicht mehr, das weiter zu optimieren.

          Danke aber für deine Vorschläge!

          Mathias