Frage

Ich mag eine XPath-Abfrage erstellen, die eine „div“ oder „Tabelle“ Element zurückkehren, solange es einen Nachkommen mit dem Text „abc“ hat. Die einzige Einschränkung ist, dass es keine div oder Tisch Nachkommen haben kann.

<div>
  <table>
    <form>
      <div>
        <span>
          <p>abcdefg</p>
        </span>
      </div>
      <table>
        <span>
          <p>123456</p>
        </span>
      </table>
    </form>
  </table>
</div>

So ist das einzige richtige Ergebnis dieser Abfrage wäre:

/div/table/form/div 

Mein bester Versuch sieht etwa so aus:

//div[contains(//text(), "abc") and not(descendant::div or descendant::table)] | //table[contains(//text(), "abc") and not(descendant::div or descendant::table)]

aber nicht zurück das korrekte Ergebnis.

Danke für Ihre Hilfe.

War es hilfreich?

Lösung

Etwas anderes :)

//text()[contains(.,'abc')]/ancestor::*[self::div or self::table][1]

Es scheint, viel kürzer als die anderen Lösungen, nicht wahr? :)

übersetzte auf einfaches Englisch :. Für jeden Textknoten in dem Dokument, das die Zeichenfolge "abc" wählen Sie die ersten Vorfahren enthält, die entweder ein div oder ein table

Das ist effizienter , da nur ein Scan des Dokumentbaums (und nicht irgendeine andere) erforderlich ist, und der ancestor::* Traversal ist sehr günstig im Vergleich zu einem descendent:: (Baum) Scan.

Um sicherzustellen, dass diese Lösung "wirklich funktioniert":

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:copy-of select=
  "//text()[contains(.,'abc')]/ancestor::*[self::div or self::table][1] "/>
 </xsl:template>
</xsl:stylesheet>

, wenn diese Transformation auf dem mitgelieferten XML-Dokument ausgeführt wird, :

<div>
  <table>
    <form>
      <div>
        <span>
          <p>abcdefg</p>
        </span>
      </div>
      <table>
        <span>
          <p>123456</p>
        </span>
      </table>
    </form>
  </table>
</div>

das wollte, ist richtige Ergebnis erzeugt :

<div>
   <span>
      <p>abcdefg</p>
   </span>
</div>

Hinweis . Es ist nicht notwendig, XSLT zu verwenden - jeder XPath 1.0 Host - wie DOM, muß das gleiche Ergebnis erhalten

Andere Tipps

//*[self::div|self::table] 
   [descendant::text()[contains(.,"abc")]]  
   [not(descendant::div|descendant::table)]

Das Problem ist, dass contains(//text(), "abc") Funktionen Knotenmengen gegossen den ersten Knoten nehmen.

Sie könnten versuchen:

//div[
  descendant::text()[contains(., "abc")] 
  and not(descendant::div or descendant::table)
] | 
//table[
  descendant::text()[contains(., "abc")] 
  and not(descendant::div or descendant::table)
]

tut diese Hilfe?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top