2010-04-29 28 views
5

Tengo algunos xml que quiero procesar usando xslt. Una buena cantidad de los datos aparece en pares clave de valores (ver a continuación). Estoy luchando con la forma de extraer la base de valor de la clave en una variable. Me gustaría poder hacer algo como esto:¿Cómo puedo obtener un valor de un par clave/valor xml con xpath en mi xslt?

<xsl:variable name="foo" select="/root/entry[key = 'foo']/value"/> 

pero eso no parece funcionar. Aquí está la muestra xml.

<?xml version="1.0" encoding="ISO-8859-1"?> 
<root> 
    <entry> 
    <key> 
     foo 
    </key> 
    <value> 
     bar 
    </value> 
    </entry> 
</root> 

¿Cuál sería el xpath correcto para esto?

+0

Buena pregunta (+1). ¿Sabías que la respuesta que seleccionaste generalmente no es correcta? Vea mi respuesta para una explicación y para dos soluciones verdaderas. :) –

Respuesta

5

La siguiente La transformación muestra dos formas de lograr esto - con y sin el uso de <xsl:key> y la función key():

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes"/> 

<xsl:key name="kValueByKey" 
    match="value" use="normalize-space(../key)"/> 

<xsl:template match="/"> 
    1. By key: <xsl:text/> 

    <xsl:copy-of select="key('kValueByKey', 'foo')"/> 

    2. Not using key: <xsl:text/> 

    <xsl:copy-of select="/*/*[normalize-space(key)='foo']/value"/> 
</xsl:template> 
</xsl:stylesheet> 

hacer la nota el uso de la funciónnormalize-space() para despojar a cualquier espacio en blanco iniciales o finales a partir del valor de <key>.

+0

parece ser lo mejor de ambos mundos, ¿correcto? – TahoeWolverine

+0

@TahoeWolverine: en XPath puro, uno * tiene * para usar esta expresión. Cada vez que XPath está alojado en XSLT, siempre preferiría usar claves. ¿No es evidente cómo la expresión clave es más simple que la XPath "pura"? Otro argumento muy fuerte a favor de las claves es que, en la mayoría de los casos, el uso de claves es mucho más rápido. –

+0

Sí, ya veo eso. Estaba un poco confundido porque no vi dónde estaban definiendo las variables. Una vez que comencé a crear las variables de esta manera, las cosas se volvieron bastante más limpias. Gracias. – TahoeWolverine

4

Su XPath funciona bien para el (equivalente) siguiente documento:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<root> 
<entry> 
    <key>foo</key> 
    <value> 
    bar 
    </value> 
</entry> 
</root> 

Usted puede utilizar la función XPath contains para obtener el mismo resultado sin tener que reestructurar el código XML:

<xsl:variable name="foo" select="/root/entry[contains(key,'foo')]/value"/> 
+0

Debería haber sabido que habría sido algo así. Lamentablemente, explicar el cambio xml a las personas que crean el xml sería demasiado difícil. Usaré el xpath. Muchas gracias. – TahoeWolverine

+0

Solución muy directa pero si en su XML era 'fooz', entonces todavía contiene 'foo', y tendrá una coincidencia incorrecta. – derloopkat

2
<xsl:variable name="foo" select="/root/entry[key='foo']/value" /> 

Ésta es una coincidencia exacta por lo asegurarse de que no hay espacios de repuesto o caracteres de nueva línea alrededor foo en el código XML. De lo contrario, use replace function y una expresión regular para recortarlos.

Cuestiones relacionadas