2009-12-30 19 views
55

Dato questo XML:Utilizzo di XPath, come selezionare un nodo in base al contenuto del testo e al valore di un attributo?

<DocText> 
<WithQuads> 
    <Page pageNumber="3"> 
     <Word> 
      July 
      <Quad> 
       <P1 X="84" Y="711.25" /> 
       <P2 X="102.062" Y="711.25" /> 
       <P3 X="102.062" Y="723.658" /> 
       <P4 X="84.0" Y="723.658" /> 
      </Quad> 
     </Word> 
     <Word> 
     </Word> 
     <Word> 
      30, 
      <Quad> 
       <P1 X="104.812" Y="711.25" /> 
       <P2 X="118.562" Y="711.25" /> 
       <P3 X="118.562" Y="723.658" /> 
       <P4 X="104.812" Y="723.658" /> 
      </Quad> 
     </Word> 
    </Page> 
</WithQuads> 

mi piacerebbe trovare i nodi che hanno il testo di 'Luglio' e un Quad/P1/X attribuire maggiore di 90. Così, in questo caso, non dovrebbe restituire alcuna corrispondenza. Tuttavia, se utilizzo GT (>) o LT (<), ottengo una corrispondenza sul primo elemento di Word. Se uso eq (=), non ho corrispondenza.

Quindi:

//Word[text()='July' and //P1[@X < 90]] 

tornerà vero, come si

//Word[text()='July' and //P1[@X > 90]] 

Come faccio a limitare questo correttamente l'attributo P1 @ X?

Inoltre, immagino di avere più elementi Page, per numeri di pagina diversi. Come potrei ulteriormente limitare la ricerca sopra per trovare i nodi con text()='July', [email protected] < 90 e Pagina @pageNumber=3?

+0

Una cosa importante da notare con questo particolare XML che potrebbe non essere ovvio per ogni lettore, è che poiché questo XML utilizza un modello di contenuto misto è complicato abbinare elementi con XPath. Mi sono imbattuto recentemente in questo problema e, essendo arrugginito con il mio XPath, stavo per concludere che non si potevano abbinare elementi di contenuto misti fino a quando non ho trovato la risposta di Michael Kay sotto. Non sono stato in grado di trovare alcun altro riferimento che parli di insidie ​​con contenuti misti e XPath. –

+0

La tua domanda ha risposto alla mia domanda. È molto importante utilizzare "apostrofi singoli" per le stringhe in XPath, non "virgolette doppie". È davvero molto importante Grazie per l'indizio. –

risposta

66

Generalmente considererei l'uso di un prefisso // come cattivo odore in un XPath.

Prova questa: -

/DocText/WithQuads/Page/Word[text()='July' and Quad/P1/@X > 90] 

Il tuo problema è che si utilizza il //P1[@X < 90] che inizia di nuovo all'inizio del documento e inizia la caccia qualsiasi P1 quindi sarà sempre vero. Allo stesso modo //P1[@X > 90] è sempre vero.

+1

Sono sorpreso che questo, in effetti, ha funzionato a causa dei problemi di spazio bianco affrontati nella risposta di Michael Kay. Ho provato questa risposta in un paio di valutatori XPath diversi e non è riuscita a corrispondere con nessuno dei due. Una volta passato al predicato con "normalize-space", ho realizzato una corrispondenza di successo. –

23

A parte il problema "//", questo XML è un uso molto strano del contenuto misto. Il predicato text()='July' corrisponderà all'elemento se qualsiasi nodo di testo figlio è esattamente uguale a luglio, il che non è vero nell'esempio a causa degli spazi bianchi circostanti. A seconda della definizione esatta dell'XML di origine, andrei a [text()[normalize-space(.)='July'] and Quad/P1/@X > 90]

+0

grazie, Michael. Mi stavo chiedendo lo spazio bianco .... Ho formattato l'esempio prima di incollarlo nello stack overflow, ma il mio XML sorgente è tutto "stretto". Quando ho eseguito xpath contro la versione formattata, non funzionava correttamente. Proverò ad usare lo spazio di normalizzazione (.) –

Problemi correlati