2012-06-30 27 views
7

Come ottenere la posizione del nodo genitore nel documento completo usando xpath?Trova la posizione del nodo genitore usando xpath

dire che ho il seguente codice XML:

<catalog> 
    <cd> 
    <title>Empire Burlesque</title> 
    <artist>Bob Dylan</artist> 
    <country>USA</country> 
    <company>Columbia</company> 
    <price>10.90</price> 
    <year>1985</year> 
    </cd> 
    <cd> 
    <title>Hide your heart</title> 
    <artist>Bonnie Tyler</artist> 
    <country>UK</country> 
    <company>CBS Records</company> 
    <price>9.90</price> 
    <year>1988</year> 
    </cd> 
</catalog> 

e ho un XSLT per convertirlo in HTML, che è la seguente (solo frammento):

<xsl:template match="/"> 
<html> 
    <body> 
    <xsl:apply-templates/> 
    </body> 
    </html> 
</xsl:template> 

<xsl:template match="cd"> 
    <p> 
    <xsl:number format="1. "/><br/> 
    <xsl:apply-templates select="title"/> 
    <xsl:apply-templates select="artist"/> 
    </p> 
</xsl:template> 

<xsl:template match="title"> 
    <xsl:number format="1" select="????" /><br/> 
    Title: <span style="color:#ff0000"> 
    <xsl:value-of select="."/></span> 
    <br /> 
</xsl:template> 

Cosa devo scrivere a il posto di ???? per ottenere la posizione del tag cd genitore nel documento. Ho provato molte espressioni ma nulla sembra funzionare. Forse lo sto facendo completamente sbagliato.

  1. <xsl:number format="1" select="catalog/cd/preceding-sibling::..[position()]" />
  2. <xsl:number format="1" select="./parent::..[position()]" /><br/>
  3. <xsl:value-of select="count(cd/preceding-sibling::*)+1" /><br/>

sto interpretando secondo come asse parente Scegliere di nodo corrente e poi dire la posizione del genitore del nodo corrente. Perché non funziona? Qual è il modo corretto per farlo.

FYI: Mi aspetto che il codice stampi la posizione del tag cd del tag corrente del tag corrente.

Per favore qualcuno può dirmi come fare questo.

risposta

16
count(../preceding-sibling::cd) + 1 

È possibile run it here (notare ho rimosso l'altro numero eri l'output, solo per chiarezza).

Eri sulla linea giusta, ma ricorda che i predicati sono usati solo per filtrare i nodi, non per restituire informazioni. Quindi:

../*[position()] 

... dice efficacemente "trovami il genitore che ha una posizione". Restituisce il nodo, non la posizione stessa. Il predicato è solo un filtro.

In ogni caso ci sono scogli con l'utilizzo position(), e può essere usato per restituire la posizione del nodo corrente, contesto solo - non un altro nodo.

+0

Grazie uomo tonnellata, ora che era sciocco da parte mia non provare che. Grazie ancora :) – Harshdeep

+0

Ancora una cosa puoi spiegare l'espressione "count (../ previous-sibling :: cd) + 1" come hai fatto per "position()". Ho usato la tua soluzione e ha funzionato benissimo, ma non sono in grado di capire perché "count (cd/previous-sibling :: ..) + 1" – Harshdeep

+2

Ricorda che i modelli XSLT operano dalla prospettiva del nodo di contesto corrente. Nel modello in questione, il nodo di contesto è il titolo. Pertanto, 'count (cd ...)' non troverà alcun nodo perché non ci sono nodi figli di 'title' chiamato' cd' (infatti, 'title' non ha nodi figli di alcun nome). 'cd' è il genitore di' title', non suo figlio, quindi dobbiamo salire di livello. – Utkanos

1
<xsl:number format="1" select="????" /> 

Cosa devo scrivere nel luogo di ???? per ottenere la posizione del tag cd principale nel documento.

Innanzitutto, l'istruzione XSLT sopra è sintatticamente illegale - l'istruzione <xsl:number> non (non possono) avere un attributo select.

Uso: risposta

<xsl:number format="1" count="cd" /> 
+0

Quindi può essere fatto usando xsl: numero pure. Grazie per le informazioni. puoi dare qualche informazione in più su come funziona. – Harshdeep

+0

@Harshdeep: è possibile imparare meglio "come funziona" facendo clic sul collegamento (sì, il colore blu di "" nella risposta indica che si tratta di un collegamento selezionabile). Per vedere i risultati dell'utilizzo di questa istruzione, copialo e incollalo nel tuo codice. –

+0

Ho fatto clic sul collegamento prima di chiederti ma la documentazione di w3 è così ingombrante che non la trovo molto 'leggibile'. Ma esamineremo ora per una migliore comprensione. – Harshdeep

3

Utkanos delle funziona bene, ma la mia esperienza è che, quando il documento XML è di grandi dimensioni, questo potrebbe portare a problemi di prestazioni.

In questo scenario è possibile semplicemente passare la posizione del genitore in un parametro.

<xsl:template match="/"> 
<html> 
    <body> 
    <xsl:apply-templates/> 
    </body> 
    </html> 
</xsl:template> 

<xsl:template match="cd"> 
    <p> 
    <xsl:number format="1. "/><br/> 
    <xsl:apply-templates select="title"> 
     <xsl:with-param name="parent_position" select="position()"/> <!-- Send here --> 
    </xsl:apply-templates> 
    <xsl:apply-templates select="artist"/> 
    </p> 
</xsl:template> 

<xsl:template match="title"> 
    <xsl:param name="parent_position"/> <!-- Receive here --> 
    <xsl:number format="1" select="$parent_position"/><br/> 
    Title: <span style="color:#ff0000"> 
    <xsl:value-of select="."/></span> 
    <br /> 
</xsl:template> 

risultato:

<html xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><body> 
    <p>1. <br>1<br> 
    Title: <span style="color:#ff0000">Empire Burlesque</span><br>Bob Dylan</p> 
    <p>2. <br>1<br> 
    Title: <span style="color:#ff0000">Hide your heart</span><br>Bonnie Tyler</p> 
</body></html> 
Problemi correlati