Pregunta

Me gustaría construir una consulta XPath que devolverá un "div" o elemento de "mesa", con tal de que tiene un descendiente que contiene el texto "abc". La única advertencia es que no puede tener ningún div o tabla descendientes.

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

Así que el resultado sólo correcto de esta consulta sería:

/div/table/form/div 

Mi mejor apariencia intento algo como esto:

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

pero no devuelve el resultado correcto.

Gracias por su ayuda.

¿Fue útil?

Solución

Algo diferente :)

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

Parece mucho más corta que las otras soluciones, no es cierto? :)

Traducido al Inglés simple . Para cualquier nodo de texto en el documento que contiene la cadena de "abc" seleccionar su primer antepasado que es o bien un div o una table

Esto es más eficiente , ya que sólo un análisis completo de la estructura del documento (y no cualquier otro) es necesaria, y el recorrido ancestor::* es muy barato en comparación con un descendent:: (árbol) de exploración.

Para verificar que esta solución "realmente funciona":

<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>

cuando esta transformación se lleva a cabo en el documento XML proporcionado

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

el, resultado correcto querido se produce

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

Nota :. No es necesario usar XSLT - cualquier XPath 1.0 anfitrión - como DOM, debe obtener el mismo resultado

Otros consejos

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

El problema con contains(//text(), "abc") es que las funciones echaron conjuntos de nodos teniendo el primer nodo.

usted podría intentar:

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

¿Le ayuda?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top