2009-08-14 10 views
5

Sto prelevando ciò che resta dei miei capelli cercando di ottenere una semplice ricerca esterna che funzioni utilizzando Saxon 9.1.0.7.XSLT 2.0 Ricerca esterna tramite chiave() e documento()

Ho un semplice file sorgente dummy.xml:

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

Poi il file di ricerca è 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> 

Quello che ho' Sto cercando di ottenere semplicemente di ottenere il "Genere" "valore basato sul valore" DepartmentCode ".

Quindi il mio XSL assomiglia:

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

...


Il problema che ho è che non ottengo niente di nuovo. Io attualmente appena ottenere

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

Ho spostato tutti i dati di ricerca per essere attributi di GenreMapping, in precedenza come elementi figlio di GenreMapping ogni volta che sono entrato nel template match = "GetGenreMappingObjectsResponse" sarebbe solo stampare tutto il testo da ogni GenreMapping (DepartmentCode, DepartmentName, Genere)!

Non riesco, per la vita di me, a capire cosa sto facendo male. Qualsiasi aiuto/suggerimento sarebbe molto apprezzato.

si prega di trovare la corrente attuale elenco XSLT:.

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

Il TransformationID e 'sempre 124 (in modo che il file di ricerca corretto viene aperto il tipo è solo un nome che sto attualmente non si utilizza, ma con l'intenzione di

.
+0

Quale compilatore XSLT stai utilizzando? – Welbog

+0

Saxon-B 9.1.0.7 –

+0

Figure. Non ho familiarità con quello. Forse più tardi Tomalak verrà in giro e ti aiuterà. Il metodo keyless ha funzionato? – Welbog

risposta

7

In XSLT 2.0 ci sono due modi in cui puoi fare quello che vuoi:

Uno è la versione a tre parametri della funzione key il terzo parametro consente di specificare il nodo principale che si desidera la chiave su cui lavorare (. di default è sempre la radice del documento principale):

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

Un altro modo è quello di utilizzare la funzione key nel nodo $lookupDoc:

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

Entrambi questi metodi sono documentati nella XSLT 2.0 specification on keys, e non verranno lavoro in XSLT 1.0.

Per motivi di completezza, è necessario riscriverlo per non utilizzare le chiavi se si è limitati a XSLT 1.0.

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

Aha! Il problema è il select="$lookupDoc" nella chiamata apply-templates che chiama un modello predefinito anziché quello previsto, quindi il parametro si sta perdendo.

Change a questo:

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

che chiamerà il modello correttamente e il tasto dovrebbe funzionare.

Così il foglio XSLT finale dovrebbe essere qualcosa di simile:

<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 lì, Grazie per la risposta. Ho già provato (e ora ritentato) entrambi questi (dal modello principale, non chiamo apply-template utilizzando questo modulo) ed entrambi non restituiscono nulla. Ho ancora gli elementi vuoti ?! Deve esserci qualcosa che sto sbagliando nella configurazione della chiave, forse? saluti –

+0

Questo potrebbe essere un problema specifico con il compilatore XSLT, ma l'uso di '$ lookupDoc/*' dovrebbe coprire le vostre basi. – Welbog

+0

Ciao di nuovo, Utilizzo del codice aggiornato Non ottengo più elementi vuoti. Li ho riempiti di spazi bianchi (24 righe). Ora sono davvero perplesso. –

0

OK, quindi questo è un po 'mentale e io non pretendo di capirlo ma funziona (sembra una carriera nel software).

Il problema che ho riscontrato è che quando chiamo i modelli di applicazione e passiamo il documento esterno come variabile, non corrisponde mai a nessun modello, nemmeno quelli chiamati "Genremapping".

Quindi ho usato un carattere jolly per catturarlo, anche quando chiamavo i modelli di applicazione ho ristretto il nodo impostato per essere il bambino a cui ero interessato. Questo è stato molto gratificante e ho potuto stampare il nome del nodo e vedi "GenreMapping" eppure non è mai entrato in nessun modello che avevo chiamato "GenreMapping" scegliendo invece di andare sempre al template "*".

Ciò significa che la mia nuova corrispondenza modello viene chiamata per ogni singolo nodo GenreMapping, pertanto potrebbe essere un po 'inefficiente. Quello che ho capito allora era tutto ciò che dovevo fare era stampare qualcosa se un predicato corrispondeva.

Quindi sembra che adesso (senza chiave utilizzata di sorta):

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

Tutto ciò uscita: nota, l'ultimo key_value correttamente non ha una voce di codice in quanto non v'è alcuna corrispondenza nella documento di ricerca

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

Risposta su un codice postale. Grazie per l'aiuto Welbog.

+0

Sono contento che tu abbia trovato una soluzione funzionante, anche se è strana. – Welbog