2009-08-14 13 views
5

Estoy tirando de lo que queda de mi pelo tratando de obtener una búsqueda externa simple trabajando con Saxon 9.1.0.7.XSLT 2.0 Búsqueda externa usando la tecla() y el documento()

Tengo un archivo de fuente simple dummy.xml:

<something> 
    <monkey> 
     <genrecode>AAA</genrecode> 
    </monkey> 
    <monkey> 
     <genrecode>BBB</genrecode> 
    </monkey> 
    <monkey> 
     <genrecode>ZZZ</genrecode> 
    </monkey> 
    <monkey> 
     <genrecode>ZER</genrecode> 
    </monkey> 
</something> 

A continuación, el archivo de búsqueda es GenreSet_124.xml:

<GetGenreMappingObjectsResponse> 
    <tuple> 
     <old> 
     <GenreMapping DepartmentCode="AAA" 
         DepartmentName="AND - NEWS AND CURRENT AFFAIRS" 
         Genre="10 - NEWS"/> 
     </old> 
    </tuple> 
    <tuple> 
     <old> 
     <GenreMapping DepartmentCode="BBB" 
         DepartmentName="AND - NEWS AND CURRENT AFFAIRS" 
         Genre="11 - NEWS"/> 
     </old> 
    </tuple> 

    ... lots more 
</GetGenreMappingObjectsResponse> 

What I Estoy tratando de lograr es simplemente para agarrar el "Género "valor basado en el valor" DepartmentCode ".

Así que mi XSL se parece a:

... 
<!-- Set up the genre lookup key --> 
<xsl:key name="genre-lookup" match="GenreMapping" use="@DepartmentCode"/> 


<xsl:variable name="lookupDoc" select="document('GenreSet_124.xml')"/> 

<xsl:template match="/something"> 
<stuff> 
    <xsl:for-each select="monkey"> 
     <Genre> 

     <xsl:apply-templates select="$lookupDoc"> 
     <xsl:with-param name="curr-label" select="genrecode"/> 
     </xsl:apply-templates> 

     </Genre> 
    </xsl:for-each> 
</stuff> 
</xsl:template> 

<xsl:template match="GetGenreMappingObjectsResponse"> 
    <xsl:param name="curr-genrecode"/> 

    <xsl:value-of select="key('genre-lookup', $curr-genrecode)/@Genre"/> 

</xsl:template> 

...


El problema que tengo es que me sale nada. Yo actualmente apenas consigo

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

he movido todos los datos de búsqueda de ser atributos de GenreMapping, anteriormente como elementos secundarios de GenreMapping cada vez que entré en el partido de la plantilla = "GetGenreMappingObjectsResponse" sería simplemente imprimir todo el texto de cada GenreMapping (DepartmentCode, DepartmentName, Genre)!

No puedo entender por qué estoy equivocado. Cualquier helpo/sugerencia sería muy apreciada.

Aquí encontrará la actual inclusión XSLT real:.

<?xml version="1.0"?> 
<xsl:stylesheet version="2.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

<!-- Define the global parameters --> 
<xsl:param name="TransformationID"/> 
<xsl:param name="TransformationType"/> 

<!-- Specify that XML is the desired output type --> 
<xsl:output method="xml" encoding="UTF-8" indent="yes"/> 

<!-- Set up the genre matching capability --> 
<xsl:key name="genre-lookup" match="GenreMapping" use="@DepartmentCode"/> 

<xsl:variable name="documentPath"><xsl:value-of select="concat('GenreSet_',$TransformationID,'.xml')"/></xsl:variable> 
<xsl:variable name="lookupDoc" select="document($documentPath)"/> 

<!-- Start the first match on the Root level --> 
<xsl:template match="/something"> 
<stuff> 
    <xsl:for-each select="monkey"> 
     <Genre> 
     <xsl:apply-templates select="$lookupDoc/*"> 
     <xsl:with-param name="curr-genrecode" select="string(genrecode)"/> 
     </xsl:apply-templates> 
     </Genre> 
    </xsl:for-each> 
</stuff> 
</xsl:template > 

<xsl:template match="GetGenreMappingObjectsResponse"> 
    <xsl:param name="curr-genrecode"/> 
    <xsl:value-of select="key('genre-lookup', $curr-genrecode, $lookupDoc)/@Genre"/> 
</xsl:template> 
</xsl:stylesheet> 

El TransformationID es todos los días 124 (por lo que se abre el archivo de búsqueda correcta el tipo es simplemente un nombre que actualmente no estoy usando, pero con la intención de

.
+0

¿Qué compilador XSLT está utilizando? – Welbog

+0

Saxon-B 9.1.0.7 –

+0

Figuras. No estoy familiarizado con eso. Tal vez más tarde Tomalak vendrá y te ayudará. ¿Ha funcionado el método sin llave? – Welbog

Respuesta

7

en XSLT 2.0, hay dos maneras en que puede hacer lo que quiera:

Una de ellas es la versión de tres parámetros de la función key el tercer parámetro le permite especificar el nodo raíz desea que la clave para trabajar en (. por defecto es siempre la raíz del documento principal):

<xsl:value-of select="key('genre-lookup', $curr-genrecode,$lookupDoc)/@Genre"/> 

Otra forma es utilizar la función de key bajo el nodo $lookupDoc:

<xsl:value-of select="$lookupDoc/key('genre-lookup', $curr-genrecode)/@Genre"/> 

Ambos métodos están documentados en la XSLT 2.0 specification on keys, y no lo hará trabajar en XSLT 1.0.

Para completar, tendría que volver a escribir esto para no utilizar las teclas si está restringido a XSLT 1.0.

<xsl:value-of select="$lookupDoc//GenreMapping[@DepartmentCode = $curr-genrecode]/@Genre"/> 

Aha! El problema es select="$lookupDoc" en su llamada apply-templates está llamando a una plantilla predeterminada en lugar de la que espera, por lo que el parámetro se pierde.

Cambio a esto:

<xsl:apply-templates select="$lookupDoc/*"> 
    <xsl:with-param name="curr-genrecode" select="string(genrecode)"/> 
</xsl:apply-templates> 

que llamará a su plantilla adecuada y la clave debería funcionar.

Así que la hoja XSLT final debe ser algo como esto:

<xsl:variable name="lookupDoc" select="document('XMLFile2.xml')"/> 
    <xsl:key name="genre-lookup" match="GenreMapping" use="@DepartmentCode"/> 
    <xsl:template match="/something"> 
    <stuff> 
     <xsl:for-each select="monkey"> 
     <Genre> 
      <xsl:apply-templates select="$lookupDoc/*"> 
      <xsl:with-param name="curr-genrecode" select="string(genrecode)"/> 
      </xsl:apply-templates> 
     </Genre> 
     </xsl:for-each> 
    </stuff> 
    </xsl:template> 
    <xsl:template match="GetGenreMappingObjectsResponse"> 
    <xsl:param name="curr-genrecode"/> 
    <xsl:value-of select="key('genre-lookup',$curr-genrecode,$lookupDoc)/@Genre"/> 
    </xsl:template> 

(Source of information)

+0

HI allí, Gracias por la respuesta. Ya he intentado (y ahora reintentado) ambos (desde la plantilla maestra, no llamo aplicar-plantilla usando este formulario) y ninguno devuelve nada. Todavía tengo los elementos vacíos ?! Debe haber algo que estoy haciendo mal en la configuración de la clave, tal vez? respetos –

+0

Esto podría ser un problema específico con su compilador XSLT, pero usar '$ lookupDoc/*' debería cubrir sus bases. – Welbog

+0

Hola otra vez, Al usar el código actualizado ya no obtengo elementos vacíos, los obtengo llenos de espacios en blanco (vale 24 líneas). Ahora estoy realmente desconcertado. –

0

bien, así que esto es un poco mental y que no pretenden entenderlo pero funciona (suena como una carrera en software).

El problema que estaba teniendo es que cuando llamo a apply-templates y paso el documento externo como una variable nunca coincidió con ninguna plantilla, incluso las llamadas "Genremapping".

Así que utilicé un comodín para atraparlo, también cuando llamé a apply-templates reduje el conjunto de nodos para que fuera el niño que me interesaba. Esto era bastante absurdo para poder imprimir el nombre del nodo y vea "GenreMapping" pero nunca entró en ninguna plantilla que yo haya llamado "GenreMapping" eligiendo en su lugar ir a la plantilla "*".

Lo que esto significa es que mi nueva coincidencia de plantilla se llama para cada nodo GenreMapping, por lo que puede ser un poco ineficiente. Lo que me di cuenta entonces fue que todo lo que tenía que hacer era imprimir algo si un predicado coincidía.

lo que parece que esto ahora (sin clave utilizada en absoluto):

... 
<xsl:template match="/something"> 
<stuff> 
    <xsl:for-each select="monkey"> 
     <Genre> 
     <key_value><xsl:value-of select="genrecode"/></key_value> 
     <xsl:variable name="key_val"><xsl:value-of select="genrecode"/></xsl:variable> 
     <code> 
     <xsl:apply-templates select="$lookupDoc/*/*/*/*"> 
     <xsl:with-param name="curr-genrecode" select="string(genrecode)"/> 
     </xsl:apply-templates> 

     </code> 
     </Genre> 
    </xsl:for-each> 
</stuff> 
</xsl:template > 


<xsl:template match="*"> 
    <xsl:param name="curr-genrecode"/> 
    <xsl:value-of select=".[@DepartmentCode = $curr-genrecode]/@Genre"/> 
</xsl:template> 
... 

Todo lo cual de salida: Nota , el último key_value correctamente no tiene un registro de código ya que no hay coincidencia en la documento de búsqueda.

<?xml version="1.0" encoding="UTF-8"?> 
<stuff xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <Genre> 
     <key_value>AAA</key_value> 
     <code>10 - NEWS</code> 
    </Genre> 
    <Genre> 
     <key_value>AAA</key_value> 
     <code>10 - NEWS</code> 
    </Genre> 
    <Genre> 
     <key_value>BBB</key_value> 
     <code>11 - NEWS</code> 
    </Genre> 
    <Genre> 
     <key_value>SVVS</key_value> 
     <code/> 
    </Genre> 
</stuff> 

Responder en un código postal. Gracias por la ayuda de Welbog.

+0

Me alegro de que hayas encontrado una solución funcional, a pesar de que es una solución extraña. – Welbog

Cuestiones relacionadas