ti-enxame.com

XSLT: Criando um mapa em XSLT

Eu quero ter um mapa de valores-chave no xsl e, assim, defini uma variável que possui um fragmento xml, mas mais tarde, quando tento acessar os nós xml na variável, recebo um erro que o tipo de xpression xpath não pode ser resolvido.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:variable name="map">
            <map>
                <entry key="key-1">value1</entry>
                <entry key="key-2">value2</entry>
                <entry key="key-3">value3</entry>
            </map>
        </xsl:variable>
        <output>
            <xsl:value-of select="$map/entry[@key='key-1']"/>
        </output>
    </xsl:template>
</xsl:stylesheet>
22
keshav84

XSLT 2.0

Usando o XSLT 2.0, a seguinte solução funciona:

  <xsl:variable name="map">
    <entry key="key-1">value1</entry>
    <entry key="key-2">value2</entry>
    <entry key="key-3">value3</entry>
  </xsl:variable>

  <xsl:template match="/">
    <output>
      <xsl:value-of select="$map/entry[@key='key-1']"/>
    </output>
  </xsl:template>

XSLT 1.0

Você não pode usar um fragmento da árvore de resultados em uma expressão XPath no XSLT 1.0, mas fn:document() pode recuperar valores do mapa. Uma resposta a um pergunta semelhante funcionará aqui :.

<xsl:value-of select="document('')//xsl:variable[@name='map']/map/entry[@key='key-1']"/>

Conforme descrito em especificação XSLT 1. :

document('') refere-se ao nó raiz da folha de estilo; a representação em árvore da folha de estilo é exatamente a mesma como se o documento XML que continha a folha de estilo fosse o documento de origem inicial.

No entanto, você não precisa usar xsl:variable Para isso. Você pode especificar seu nó de mapa diretamente em xsl:stylesheet, Mas lembre-se de que os elementos de nível superior devem ter um URI de espaço para nome não nulo:

<xsl:stylesheet 
  version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:my="some.uri" exclude-result-prefixes="my">

  <my:map>
    <entry key="key-1">value1</entry>
    <entry key="key-2">value2</entry>
    <entry key="key-3">value3</entry>
  </my:map>

  <xsl:template match="/">
    <output>
      <xsl:value-of select="document('')/*/my:map/entry[@key='key-1']"/>
    </output>
  </xsl:template>
</xsl:stylesheet>
40
Per T

Você pode resolver o suporte ausente do XSLT 1.0 para usar o conteúdo da variável como um conjunto de nós. Você precisará confiar nas extensões adicionadas pelo fabricante do analisador. Por exemplo, a Microsoft ofereceu uma função para contornar isso: node-set ()

Seu XSL ficará assim:

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-Microsoft-com:xslt">
    <xsl:template match="/">
        <xsl:variable name="map">
            <map>
                <entry key="key-1">value1</entry>
                <entry key="key-2">value2</entry>
                <entry key="key-3">value3</entry>
            </map>
        </xsl:variable>
        <output>
            <xsl:value-of select="msxsl:node-set($map)/map/entry[@key='key-1']"/>
        </output>
    </xsl:template>
</xsl:stylesheet>

Observe o espaço para nome e o prefixo msxsl aqui. Isso funcionará apenas em aplicativos baseados no analisador da Microsoft (por exemplo: o Internet Explorer o utiliza e também o .NET). Outros analisadores podem ou não ter essa extensão (Saxxon possui, por exemplo, mas tem um nome um pouco diferente). Porém, ele elimina dependendo do XSLT 2.0, pois isso funcionará bem no XSLT 1.0 e a Microsoft ainda não oferece suporte ao XSLT 2.0 em sua biblioteca XML (a menos que o tenha adicionado recentemente).

Dependendo do analisador que você estiver usando, as opções acima podem funcionar bem para você, caso contrário, a resposta de Per T é melhor para você.

7
Rob

No Rascunho de Trabalho do XSLT 3.0 , é proposto um novo tipo de item XPath (mapa), consulte mapas no XSLT 3.0 WD Spec .

Portanto, se o seu processador XSLT suportar 3.0 e mapas (por exemplo, Saxon 9.4), você poderá usar o seguinte código:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  exclude-result-prefixes="xs" 
  version="3.0">
  <xsl:output indent="yes"/>

  <xsl:template match="/">
    <xsl:variable name="map" select="
      map { 
      'key-1' := 'value1', 
      'key-2' := 'value2',
      'key-3' := 'value3' }">      
    </xsl:variable>
    <output>
      <xsl:value-of select="
        $map('key-1') || ', ' || $map('key-2') || ', ' || $map('key-3')"/> 
    </output>
  </xsl:template>
</xsl:stylesheet> 
5
j_maly