2010-09-09 17 views
7

Estoy en una situación en la que solo puedo probar el nodo hijo, pero tengo que aplicar etiquetas al abuelo de este nodo secundario.Cómo seleccionar el abuelo de un nodo usando xslt

He intentado usar:

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

y:

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

Pero ni las obras.

El nivel del nodo de abuelos no es fijo, por lo que creo que tampoco puedo usar [@ level = #]. Cualquier idea sobre cómo seleccionarla sería muy apreciada.

EDIT: - Esta parte ha sido publicado como una nueva pregunta:

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

Selección del nodo utilizando las sugerencias de abajo trabajado. ¡Gracias! Sin embargo, también debo probar por el atributo del nodo de abuelos o nietos.

que he probado:

<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> 

Sin embargo plantilla "dos" siempre se llama, y ​​"" se inserta siempre. Incluso para nodos de nieto cuyo valor de atributo no es igual a 'attrValue'.

¿Falta algo aquí?

+0

Buena pregunta (+1). Vea mi respuesta para una cantidad de expresiones XPath que puede usar en una instrucción ''. –

+0

@highlightall La parte editada no está clara. Proporcione un documento XML completo (pero lo más breve posible) y la hoja de estilo XSLT completa (una vez más, lo más breve posible) que reproduzca su problema. Preferiblemente, pregunte esto en una nueva pregunta. –

+0

@highlightall: También 'Incluso para nodos de nieto cuyo valor de atributo no es igual a 'attrValue'' no puede ser cierto con este patrón' grandparentnode [*/*/@ grandchildattr =' attrValue '] ' –

Respuesta

17

He intentado usar:

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

y:

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

Pero ni las obras.

Ciertamente no va a "trabajar", porque la instrucción <xsl:call-template> no tiene un atributo select!

Es posible pasar parámetros utilizando <xsl:with-param> hijos de la instrucción <xsl:call-template>, así:

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

Para el atributo select del <xsl:with-param> Uso:

para un abuelo real:

../.. 

para el elemento ancestro más cercano con nombrar someName:

ancestor::someName[1] 

para el elemento antepasado más cercano con el nombre contenido en la variable $ancName:

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

+1 para abreviar gradual Expresión XPath. –

+0

funcionó - ¡gracias! – highlightall

+0

@highlightall: Me alegro de que funcionó. Aquí en SO, la gratitud se expresa al aceptar una respuesta. Sugerencia: Simplemente haga clic en la marca de verificación al lado de la respuesta. :) –

4

Estoy en una situación en la que pueda única prueba para el nodo hijo, pero yo tiene que aplicar etiquetas al abuelo de este nodo hijo.

XSLT no es una programación de procedimientos, por lo que debe pensar las cosas de forma un poco diferente.

Si entiendo correctamente, desea insertar nuevas etiquetas (elementos secundarios adicionales o atributos?) En su XML, pero desea agregarlo a un antecesor cuando encuentre un descendiente específico. Su código de ejemplo parece intentar apuntar al abuelo una vez que se encuentra con el niño. Desafortunadamente, esto puede ser demasiado tarde.

Es posible que necesite inyectar el nuevo elemento/atributo cuando el motor se encuentra con el elemento que desea modificar (los abuelos en su caso), no cuando se encuentra con el niño que coincide con la condición (o de lo contrario termino la adición de elementos o atributos para el niño)

Consider this input (abuelo = "disco", nieto = "etiqueta"):

<?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> 

Quiero modificar la album en base a si un determinado label está presente. Recuerde que el formato general para los nodos de segmentación es: target-node[target-condition].Para modificar cualquier album elementos que tienen un elemento nieto Capitol etiqueta, que haría uso de este:

album[*/label='Capitol'] 

así que considera esta hoja de estilo para añadir un nuevo atributo y 2 nuevos elementos secundarios para album 's que coinciden con mi condición:

<?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> 

de salida (formato manualmente):

recursos de pruebas
<?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> 

Algunos de recinto de seguridad:

+1

@Bert F: +1 para una buena respuesta y explicación sobre el enfoque correcto. –

+0

@Alejandro - Gracias - echa un vistazo a los recursos de prueba: los encuentro extremadamente convenientes y útiles para experimentar. –

+1

Ejemplo de código muy útil. ¡Gracias! – highlightall

Cuestiones relacionadas