2010-09-09 9 views
7

Sono in una situazione in cui posso solo testare il nodo figlio, ma devo applicare tag al nonno di questo nodo figlio.Come selezionare il nonno di un nodo utilizzando xslt

Ho provato con:

<xsl:call-template name="grandparent" select="parent::parent::node()"/> 

e:

<xsl:call-template name="grandparent" select="ancestor::node [@nameofgrandparentnode]"/> 

Ma né opere.

Il livello del nodo grandparent non è fisso, quindi immagino di non poter usare neanche [@ level = #]. Qualsiasi idea su come selezionarla sarebbe molto apprezzata.

EDIT: - Questa parte è stata pubblicata una nuova domanda:

xslt select grandparent node depending on an attribute value of its grandchild node

Selezione del nodo utilizzando i suggerimenti dal basso funzionato. Grazie! Tuttavia ho anche bisogno di testare l'attributo del nodo grandparent o grandchild.

ho provato:

<xsl:template name"one" match="grandparentnode"> 
<Tag1> 
    <xsl:apply-templates select="parentNode" /> 
</Tag1> 
</xsl:template> 

<xsl:template name="two" match="grandparentnode[*/*/@grandchildattr='attrValue']"> 
<Tag2> 
    <xsl:apply-templates select="parentNode" /> 
</Tag2> 
</xsl:template> 

Tuttavia modello "due" ottiene sempre chiamato, e "è sempre inserito". Anche per i nodi grandchild il cui valore di attributo non è uguale a "attrValue".

Mi manca qualcosa qui?

+0

Buona domanda (+1). Vedere la mia risposta per un numero di espressioni XPath che è possibile utilizzare in un'istruzione ''. –

+0

@highlightall La parte modificata non è chiara. Per favore, fornisci un documento XML completo (ma il più breve possibile) e il foglio di stile XSLT completo (ancora, il più breve possibile), che riproponga il tuo problema. Preferibilmente, chiedi questo in una nuova domanda. –

+0

@highlightall: anche 'Anche per i nodi grandchild il cui valore dell'attributo non è uguale a 'attrValue'' non può essere vero con questo modello' grandparentnode [*/*/@ grandchildattr =' attrValue '] ' –

risposta

17

Ho provato con:

<xsl:call-template name="grandparent" select="parent::parent::node()"/> 

e:

<xsl:call-template name="grandparent" select="ancestor::node[@nameofgrandparentnode]"/> 

Ma né opere.

Certamente non "lavoro", perché l'istruzione <xsl:call-template> non avere un attributo select!

Si può passare parametri utilizzando <xsl:with-param> figli dell'istruzione <xsl:call-template>, in questo modo:

<xsl:call-template name="compute"> 
    <xsl:param name="pAncestor" select="someExpression"/> 
</xsl:call-template> 

Per l'attributo select del <xsl:with-param> Usa:

Per un vero e proprio nonno:

../.. 

per l'elemento antenato più vicino con nome someName:

ancestor::someName[1] 

per l'elemento antenato più vicino con il nome contenuto nella variabile $ancName:

ancestor::*[name()=$ancName][1] 
+0

+1 per abbreviate gradparent Espressione XPath. –

+0

ha funzionato - grazie! – highlightall

+0

@highlightall: Felice ha funzionato. Qui a SO la gratitudine si esprime accettando una risposta. Suggerimento: basta cliccare sul segno di spunta accanto alla risposta. :) –

4

mi trovo in una situazione in cui posso solo test per il nodo figlio, ma io devono applicare tag al nonno di questo nodo figlio.

XSLT non è una programmazione procedurale, quindi è necessario pensare alle cose in modo leggermente diverso.

Se ho capito bene, si desidera iniettare nuovi tag (ulteriori elementi figlio o attributi?) Nel proprio XML, ma si desidera aggiungerlo a un antenato quando si trova un discendente specifico. Il tuo codice di esempio sembra cercare di colpire il nonno una volta incontrato il bambino. Sfortunatamente, potrebbe essere troppo tardi.

Potrebbe essere necessario inserire il nuovo elemento/attributo quando il motore trova l'elemento che si desidera modificare (il nonno nel tuo caso), non quando incontra il bambino che soddisfa la condizione (oppure lo farai finisco l'aggiunta di elementi o attributi al bambino)

Consider this input (nonni = "album", nipote = "label"):

<?xml version="1.0" encoding="UTF-8"?> 

<album> 
    <title>Sgt. Pepper's Lonely Hearts Club Band</title> 
    <artist>The Beatles</artist> 
    <year>1967</year> 
    <labels> 
    <label>Parlophone</label> 
    <label>Capitol</label> 
    </labels> 
</album> 

voglio modificare il album base al fatto che un certo label è presente. Ricorda che il formato generale per i nodi di targeting è: target-node[target-condition].Per modificare eventuali album elementi che hanno un elemento nipotino Capitol etichetta, userei questo:

album[*/label='Capitol'] 

Così considerano questo foglio di stile per aggiungere un nuovo attributo e 2 nuovi elementi figli di album 's che corrispondono alla mia condizione:

<?xml version="1.0" encoding="UTF-8"?> 

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

    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="album[*/label='Capitol']"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:attribute name="new-attribute">A Capitol Record</xsl:attribute> 
     <new-element1/> 
     <xsl:apply-templates select="node()"/> 
     <new-element2/> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

uscita (formattato manualmente):

risorse di test
<?xml version="1.0" encoding="UTF-8"?> 
<album new-attribute="A Capitol Record"> 
    <new-element1/> 
    <title>Sgt. Pepper's Lonely Hearts Club Band</title> 
    <artist>The Beatles</artist> 
    <year>1967</year> 
    <labels> 
    <label>Parlophone</label> 
    <label>Capitol</label> 
    </labels> 
    <new-element2/> 
</album> 

Alcuni sandbox:

+1

@Bert F: +1 per una buona risposta e una spiegazione sull'approccio corretto. –

+0

@ Alejandro - Grazie - controlla le risorse di prova - le trovo estremamente convenienti e utili per la sperimentazione. –

+1

Esempio di codice molto utile. Grazie! – highlightall

Problemi correlati