2012-06-02 22 views
27

ho un XML seguente:XPath selezionare tutti gli elementi tra due elementi specifici

<doc> 
    <divider /> 
    <p>text</p> 
    <p>text</p> 
    <p>text</p> 
    <p>text</p> 
    <p>text</p> 
    <divider /> 
    <p>text</p> 
    <p>text</p> 
    <divider /> 
    <p>text</p> 
    <divider /> 
</doc> 

voglio selezionare tutti i nodi p dopo primo elemento divisore fino alla prossima occorrenza dell'elemento divisore. Ho provato a seguire xpath:

//divider[1]/following-sibling::p[following::divider] 

ma il problema è che seleziona tutti gli elementi p prima dell'ultimo elemento divisore. Non sono sicuro di come farlo utilizzando XPath 1.

risposta

24

stesso concetto bytebuster, ma un diverso XPath:

/*/p[count(preceding-sibling::divider)=1] 
+0

Ottima idea! 'count' è più idiomatico dato che' 1' viene usato una sola volta. – bytebuster

4

Che dire di selezionando tutte p avere esattamente un elemento divider come preceding-sibling?

//doc/p[preceding-sibling::divider[1] and not (preceding-sibling::divider[2])] 
14

Qui è un'espressione XPath generale:

/*/divider[$k] 
    /following-sibling::p 
     [count(.|/*/divider[$k+1]/preceding-sibling::p) 
     = 
     count(/*/divider[$k+1]/preceding-sibling::p) 
     ] 

Se sostituite $k con 1 quindi esattamente la voleva I nodi p sono selezionati.

se si sostituisce $k con 2 poi tutti gli elementi p tra il 2 ° e 3 ° divider, ..., ecc

Spiegazione:

Questa è una semplice applicazione del Kayessian XPath 1.0 formula per l'intersezione del set di nodi:

$ns1[count(.|$ns2) = count($ns2)] 

se Seleziona tutti i nodi che appartengono a sia ai nodesets $ns1 e $ns2.

In questo caso specifico sostituiamo $ns1 con:

/*/divider[$k]/following-sibling::p 

e sostituiamo $ns2 con:

/*/divider[$k+1]/preceding-sibling::p 
+0

+1 Bella implementazione del '' metodo Kayessian''. – Cylian

+0

@ Cylian: prego. –

4

Penso che ci sia una soluzione molto più semplice e probabilmente più veloce: si desidera che tutti i fratelli precedenti di il secondo divisore che ha almeno un precedente parente fratello:

/doc/divider[2]/preceding-sibling::p[preceding-sibling::divider] 

Diventa un po 'più complesso, ovviamente, se vuoi trovare i paras tra il secondo e il terzo divisorio: allora vuoi qualcosa di più come la soluzione di Daniel Haley.

Problemi correlati