2012-05-02 8 views
7

Ho un documento XML con chapters e nidificato sections. Sto cercando di trovare, per qualsiasi sezione, il primo antenato della sezione di secondo livello. Questa è la penultima sezione nell'asse ancestor-or-self. pseudo-codice:trova il prossimo all'ultimo nodo con xpath

<chapter><title>mychapter</title> 
    <section><title>first</title> 
    <section><title>second</title> 
     <more/><stuff/> 
    </section> 
    </section> 
</chapter> 

mio selettore:

<xsl:apply-templates 
    select="ancestor-or-self::section[last()-1]" mode="title.markup" /> 

Naturalmente che funziona fino all'ultimo() - 1 non è definito (nodo corrente è la sezione first).

Se il nodo corrente è inferiore alla sezione second, voglio il titolo second. Altrimenti voglio il titolo first.

+0

Voto superiore per l'utilizzo di DocBook. –

risposta

4

Sostituisci il tuo XPath con questo:

ancestor-or-self::section[position()=last()-1 or count(ancestor::section)=0][1] 

Dal momento che si può già trovare il nodo giusto in tutti i casi tranne uno, ho aggiornato il vostro XPath per anche trovare la sezione first (or count(ancestor::section)=0), quindi selezionare ([1]) la prima corrispondenza (in ordine inverso, poiché stiamo usando l'asse ancestor-or-self).

+0

Questo funziona - grazie. Dopo aver provato la tua soluzione, ho pensato che avrei potuto semplificarlo con questo, ma purtroppo sembra sempre selezionare la sezione corrente. 'ancestor-or-self :: d: section [last() - 1 o last()] [1]' – Tim

+0

@Tim 'ancestor-or-self :: section [last() - boolean (ancestor :: section) ] [1] ' –

+0

@Aleh, soluzione elegante! – Tim

2

Ecco una soluzione più breve e più efficiente:

(ancestor-or-self::section[position() > last() -2])[last()] 

Questo seleziona l'ultimo dei eventualmente primi due antenati più in alto denominati section. Se c'è solo uno di questi antenati, allora è esso stesso l'ultimo.

Ecco una completa trasformazione:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:template match="section"> 
    <xsl:value-of select="title"/> 
    <xsl:text> --> </xsl:text> 

    <xsl:value-of select= 
    "(ancestor-or-self::section[position() > last() -2])[last()]/title"/> 
    <xsl:text>&#xA;</xsl:text> 
    <xsl:apply-templates/> 
</xsl:template> 

<xsl:template match="text()"/> 
</xsl:stylesheet> 

Quando questa trasformazione viene applicata la seguente documento (basato sul previsto, ma aggiungono più nested section elementi):

<chapter> 
    <title>mychapter</title> 
    <section> 
     <title>first</title> 
     <section> 
      <title>second</title> 
      <more/> 
      <stuff/> 
     <section> 
      <title>third</title> 
     </section> 
     </section> 
    </section> 
</chapter> 

vengono prodotti i risultati corretti:

first --> first 
second --> second 
third --> second