2011-08-19 17 views
7

mi hanno una struttura simile al seguente:XPath: Seleziona nodo, ma non specifici elementi figlio

<page id='1'> 
    <title>Page 1</title>  
    <page id='2'> 
    <title>Sub Page 1</title> 
    </page> 
    <page id='3'> 
    <title>Sub Page 2</title> 
    </page>  
</page> 
<page id='4'> 
    <title>Page 2</title> 
</page> 

ho bisogno di selezionare una pagina da Id ma se la pagina ha pagine discendenti Non voglio tornare quegli elementi, ma voglio gli altri elementi di quella pagina. Se seleziono Page 1 Voglio tornare il titolo, ma non le pagine figlio ...

//page[@id=1] 

È possibile che questo mi viene pagina 1, ma come faccio a escludere le pagine secondarie? Inoltre, potrebbe esserci un numero arbitrario di elementi in una pagina.

//page[@id=1]/*[not(self::page)] 

Ho trovato che questo mi ottiene i dati che voglio. Tuttavia, quei dati tornano come una matrice di oggetti con un oggetto per elemento e apparentemente esclude i nomi degli elementi ???. Sto usando PHP SimpleXML per quello che vale.

+0

Buona domanda, +1. Vedi la mia risposta per una soluzione breve e semplice. :) –

+1

"Tuttavia, tali dati tornano come una matrice di oggetti con un oggetto per elemento." Com'è diverso da ciò che vuoi/hai bisogno? – LarsH

+0

I dati tornano in un formato diverso a seconda della query xpath, ottengo un array di SimpleXMLElement con una stringa singola in ognuno e mancano i nomi degli elementi. Il primo caso restituisce un singolo oggetto SimpleXMLElement con tutte le coppie di valori chiave previste. Non capisco perché, forse aprirò un'altra domanda. – Ben

risposta

7

Uso:

//page[@id=$yourId]/node()[not(self::page)] 

Questo seleziona tutti i nodi che non sono page e che sono figli di qualsiasi page nel documento, il valore stringa il cui attributo id è uguale alla stringa contenuta in $yourId (molto probabilmente si sostituirà $yourId in precedenza con un stringa specifica e desiderata, ad esempio '1').

Ecco una semplice verifica XSLT basato:

<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:param name="pId" select="3"/> 

<xsl:template match="/"> 
    <xsl:copy-of select="//page[@id=$pId]/node()[not(self::page)]"/> 
</xsl:template> 
</xsl:stylesheet> 

quando questa trasformazione è applicato sul documento XML fornito (avvolto in un singolo nodo superiore per renderlo ben formato):

<pages> 
    <page id='1'> 
     <title>Page 1</title> 
     <page id='2'> 
      <title>Sub Page 1</title> 
     </page> 
     <page id='3'> 
      <title>Sub Page 2</title> 
     </page> 
    </page> 
    <page id='4'> 
     <title>Page 2</title> 
    </page> 
</pages> 

The Wanted, risultato corretto è prodotta:

<title>Sub Page 2</title> 

Do atto: Un'ipotesi fatta è che un valore id identifica in modo univoco un page. In caso contrario, l'espressione XPath proposta selezionerà tutti gli elementipage l'attributo id ha un valore stringa di $yourId.

Se questo è il caso e deve essere selezionato solo un elemento page, l'OP deve specificare quale dei molti elementi page deve essere selezionato con questo id.

Ad esempio, può essere il primo:

(//page[@id=$yourId]/node()[not(self::page)])[1] 

o l'ultima:

(//page[@id=$yourId]/node()[not(self::page)])[last()] 

o ...

+0

Mentre questo sembra esattamente giusto, in realtà non funziona .. Non sono sicuro se c'è qualcosa di sbagliato in xpath nel semplice xml di PHP, ma questo restituisce più copie della pagina richiesta ??? – Ben

+0

@ Ben: questo può accadere solo se più di una 'page' può avere lo stesso valore del suo attributo' id'. Ho aggiornato la mia risposta per coprire questo caso. Fornisco anche una semplice verifica che mostra che l'espressione XPath iniziale seleziona esattamente un elemento 'page' se un valore' id' identifica in modo univoco una 'page'. –

1

Se siete interessati solo l'elemento di titolo, questo dovrebbe funzionare:

//page[@id=1]/title 

Se invece avete bisogno di altri elementi secondari di pagina, non sono sicuro XPath è lo strumento giusto per te. Sembra più qualcosa per cui un XSLT sarebbe adatto, dal momento che ciò che stai facendo è trasformare i tuoi dati.

+0

Purtroppo ho bisogno di un numero qualsiasi di elementi arbitrari tranne la pagina ... – Ben

+0

Risposta aggiornata con ulteriori informazioni. Sentiti libero di andare avanti se è utile in ogni caso. :) –

+0

Grazie, sto iniziando a pensare che Xpath forse non può farlo. Posso sempre scrivere qualcosa per elaborare i dati che desidero ma speravo di farlo a livello di dati. – Ben

0

Se la pagina ha sempre un titolo:

//page[@id='1']/*[not(boolean(./title))] 
Problemi correlati