2012-06-18 8 views
10

Estoy trabajando en XSLT, donde tengo que implementar algo de la siguiente manera. Mi muestra de Source Source XML tiene este aspecto.Implementación del concepto de valor clave en XSLT

<?xml version="1.0" encoding="ISO-8859-1"?> 
    <catalog> 
     <cd> 
      <title>A</title> 
      <title>B</title> 
      <title>C</title> 
     </cd> 
    </catalog> 

Considérese que hay alguna lista de valores clave par está allí.

Key   Value 
    A   Algebra 
    B   Biology 
    C   Chemistry 
    D   Data Analysis 
    ---   --- 

    ----  --- 

Tengo que escribir un XSLT tal que para cada ocurrencia de la llave 'A', la necesidad de reemplazar con el valor apropiado.

También necesito mencionar la lista de pares de valores clave en el mismo XSLT. Ejemplo de salida:

<Data> 
    <Subject>Algebra</Subject> 
    <Subject>Biology</Subject> 
    <Subject>Chemistry</Subject> 
</Data> 

cualquiera puede ayudar a encontrar la manera de hacerlo.

Gracias.

Respuesta

16

I. XSLT 1.0 Solución simple

Esta transformación:

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

<my:codes> 
    <code key="A" value="Algebra"/> 
    <code key="B" value="Biology"/> 
    <code key="C" value="Chemistry"/> 
    <code key="D" value="Data Analysis"/> 
</my:codes> 

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

<xsl:template match= 
    "title/text()[. = document('')/*/my:codes/*/@key]"> 

    <xsl:value-of select= 
    "document('')/*/my:codes/*[@key=current()]/@value"/> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica sobre el documento XML proporcionado:

<catalog> 
    <cd> 
     <title>A</title> 
     <title>B</title> 
     <title>C</title> 
    </cd> 
</catalog> 

produce la querido, resultado correcto:

<catalog> 
    <cd> 
     <title>Algebra</title> 
     <title>Biology</title> 
     <title>Chemistry</title> 
    </cd> 
</catalog> 

Explicación:

Esta es la manera estándar de incluir nodo XML en línea como un elemento global (elemento secundario de xsl:stylesheet) que pertenece a una (no vacío) espacio de nombre, diferente del espacio de nombres xsl.


II. solución más eficiente XSLT 1.0, utilizando las teclas de:

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

    <my:codes> 
     <code key="A" value="Algebra"/> 
     <code key="B" value="Biology"/> 
     <code key="C" value="Chemistry"/> 
     <code key="D" value="Data Analysis"/> 
    </my:codes> 

    <xsl:key name="kCodeByName" match="code" use="@key"/> 

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

    <xsl:template match= 
     "title/text()[. = document('')/*/my:codes/*/@key]"> 

     <xsl:variable name="vCur" select="."/> 

     <xsl:for-each select="document('')"> 
      <xsl:value-of select= 
      "key('kCodeByName', $vCur)/@value"/> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

cuando se aplica esta transformación en el mismo documento XML (arriba), la misma correcta, querían resultado se produce:

<catalog> 
    <cd> 
     <title value="Algebra"/> 
     <title value="Biology"/> 
     <title value="Chemistry"/> 
    </cd> 
</catalog> 

Explicación:

El acceso a los datos a través de la función key() es típicamente sub-lineal - a menudo O (1) y es extremadamente fas ter que la búsqueda lineal (que es importante si la cantidad de nodos a buscar es grande).

El acceso a un nodo de un documento mediante un índice (xsl:key) mientras se procesa un nodo de otro documento es posible si el documento que contiene el nodo que se va a buscar es el documento actual. Para acceder a los nodos desde el otro documento, su raíz (o nodo de interés) debe guardarse y referenciarse en una variable.)


III. solución XSLT 2.0:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vCodes"> 
    <codes> 
    <code key="A" value="Algebra"/> 
    <code key="B" value="Biology"/> 
    <code key="C" value="Chemistry"/> 
    <code key="D" value="Data Analysis"/> 
    </codes> 
</xsl:variable> 

<xsl:key name="kCodeByName" match="code" use="string(@key)"/> 

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

<xsl:template match= 
    "title/text()[key('kCodeByName', ., $vCodes)]"> 

    <xsl:sequence select= 
    "key('kCodeByName', ., $vCodes)/@value"/> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica esta transformación en el mismo documento XML (arriba), la misma correcta, resultado deseado se produce:

<catalog> 
    <cd> 
     <title value="Algebra"/> 
     <title value="Biology"/> 
     <title value="Chemistry"/> 
    </cd> 
</catalog> 

Explicación:

Casi lo mismo que la solución eficiente XSLT 1.0, pero:

  1. En XSLT 2.0 un patrón de coincidencia de plantilla puede contiene una referencia de variable.

  2. En XSLT 2.0 no hay necesidad de trucos acrobáticos para manipular la corriente y los documentos indexados. El tercer argumento de la función key() es especificar el árbol cuyo índice usar.

+0

Gracias por la Respuesta. – Patan

+0

@ User222: De nada. –

+0

@Dimitre ¿Podemos llamar a la plantilla en la solución III. XSLT 2.0 en otra plantilla. Si es así, ¿podría decirme cómo? –

Cuestiones relacionadas