2011-08-24 15 views
11

che ho visto su SO e in altri luoghi che si suppone quanto segue per lavorare (questo esempio viene sollevato direttamente da O'Reilly XSLT Cookbook):Come eseguire le operazioni di set in XPath 1.0

(: intersection :) 
$set1[count(. | $set2) = count($set2)] 

(: difference :) 
$set1[count(. | $set2) != count($set2)] 

e sembra che dovrebbe essere OK, tuttavia questo sembra fallire se usato con percorsi effettivi piuttosto che variabili. Ad esempio, dato il seguente documento

<a> 
    <new> 
    <val>1</val> 
    <val>2</val> 
    </new> 
    <old> 
    <val>2</val> 
    <val>3</val> 
    </old> 
</a> 

e l'espressione XPath /a/new/val[count(. | /a/old/val)=count(/a/old/val)]/text() mi aspetto di ottenere il set-nodo { 2 } ma invece che ottiene { 1 2 }. Qualche idea su cosa sto facendo male?

+0

Buona domanda, +1. Vedi la mia risposta per la spiegazione del tuo problema e per un'espressione XPath semplice e facile con un solo liner - soluzione - nessuna altra risposta propone una soluzione in questo momento. :) –

risposta

8

Le formule per l'intersezione del set di nodi utilizzano l'identità del nodo e non l'identità del valore.

due nodi sono identici se e solo se count($n1|$n2) =1

Tuttavia, si vuole intersecano in base all'identità di valore.

Soluzione:

Uso:

/a/new/val[. = /a/old/val] 

questo seleziona qualsiasi /a/new/val per i quali esiste almeno un elemento /a/old/val tale che i valori stringa di questi due elementi è la stessa.

+0

Impressionante - posto su, che funziona come un fascino! –

+0

@Ian Phillips, siete i benvenuti :) –

+0

Bella risposta! Possiamo anche implementare le operazioni set * Minus *? –

1

Osservazione che intersezione risulta sempre in un unico nodo-set composto dai nodi in comune tra i due nodi-set originali.

anche nota che due nodi con lo stesso nome e contenuti devono essere trattate come due distinte nodi. Pertanto, /a/new/val/text() e /a/old/val/text() hanno lo stesso valore ma sono nodi di testo completamente distinti.

Così la vostra intersezione corrente:

/a/new/val[count(. | /a/old/val)=count(/a/old/val)] 

dovrebbe valutare a un set di nodi vuoto, perché si intersecano due nodi-set senza alcun nodo comune (count() operazione non sarà mai soddisfatta). Si sta facendo qualcosa del genere:

/a/new/val & # x2229; /a/old/val = & # x2205;

Mentre /a/new & # x2229; /a/old/preceding::new produrrà new.

Problemi correlati