Existe um elemento de nome XSLT?

101

Em XSLT existe o

<xsl:value-of select="expression"/>

para obter o valor de um elemento, mas há algo para selecionar o nome da tag do elemento?

Em uma situação como esta:

<person>
  <!-- required stuff -->
  <name>Robert</name>
  <!-- optional stuff, free form for future extension. 
       Using XMLSchema's xsd:any -->
  <profession>programmer</profession>
  <hobby>photography</hobby>
</person>

<xsl:for-each select="person">
   <xsl:tag-of select="."/> : <xsl:value-of select="."/>
</xsl:for-each>

Para obter resultados como este:

name : Robert
profession : programmer
hobby : photography

Claro que o XSLT acima não compilará porque

 <xsl:tag-of select="expression"/>

não existe. Mas como isso poderia ser feito?

Robert Gould
fonte
A tag mais relevante para esta questão é XPath. Ambas as funções são funções padrão XPath e podem ser usadas em uma expressão XPath no contexto de qualquer linguagem de hospedagem (C #, XSLT, XQuery, ...) Por favor,
remarque
Este texto: "Em XSLT existe o <xsd: value-of select =" expression "/>" - contém um erro. O prefixo normalmente usado para instruções XSLT é "xsl". Normalmente, ao usar o XML Schema, usamos o prefixo "xsd" ou "xs". Por favor corrija.
Dimitre Novatchev

Respostas:

156

Isso lhe dará o nome do elemento atual (nome da tag)

<xsl:value-of select ="name(.)"/>

OP-Edit: Isso também resolverá o problema:

<xsl:value-of select ="local-name()"/>
Usuário SO
fonte
12
nome-local é o que você quer 9 de 10 vezes
annakata
20
local-name é sans namespace, é por isso que geralmente é melhor.
Jon W
102

Ninguém apontou a diferença sutil na semântica das funções name()e local-name().

  • name(someNode) retorna o nome completo do nó, e isso inclui o prefixo e dois pontos, caso o nó seja um elemento ou atributo.
  • local-name(someNode) retorna apenas o nome local do nó, e isso não inclui o prefixo e dois pontos caso o nó seja um elemento ou um atributo.

Portanto, em situações em que um nome pode pertencer a dois namespaces diferentes, deve-se usar a name()função para que esses nomes ainda sejam distinguidos.

E, BTW, é possível especificar ambas as funções sem nenhum argumento :

name() é uma abreviatura para name(.)

local-name() é uma abreviatura para local-name(.)

Por fim , lembre-se de que não apenas os elementos e atributos têm nomes, essas duas funções também podem ser usadas em PIs e neles são idênticas).

Dimitre Novatchev
fonte
15
<xsl:for-each select="person">
  <xsl:for-each select="*">
    <xsl:value-of select="local-name()"/> : <xsl:value-of select="."/>
  </xsl:for-each>  
</xsl:for-each>
Ray Lu
fonte
Como uma boa prática, sempre use normalize-space () ao obter o valor do nó <xsl: value-of select = "normalize-space (.)" /> Isso irá cortar os espaços extras
SO Usuário
Essa normalização / higienização só seria necessária se não tivesse sido tratada no estágio de coleta de entrada. Fazê-lo evita a necessidade de fazê-lo no momento do acesso, o que geralmente é muito mais frequente. Alguém faria isso antes de adicionar a um RDB, e um documento xml é apenas outro banco de dados.
Patanjali
9

Para os interessados, não há:

<xsl:tag-of select="."/>

No entanto, você pode recriar a tag / elemento indo:

<xsl:element name="{local-name()}">
  <xsl:value-of select="substring(.,1,3)"/>
</xsl:element>

Isso é útil em um modelo xslt que, por exemplo, lida com a formatação de valores de dados para muitos elementos diferentes. Quando você não sabe o nome do elemento que está sendo trabalhado e ainda pode gerar o mesmo elemento e modificar o valor, se necessário.

Tim
fonte
6
<xsl:value-of select="name(.)" /> : <xsl:value-of select="."/>
Rowland Shaw
fonte
Então, por que isso foi rejeitado? Concedido, você poderia ter mencionado o local-name () se você não quisesse o namespace também, mas seria útil para a comunidade mais ampla explicar por que isso não funcionaria.
Rowland Shaw
Talvez ele não pudesse transformar o XML fornecido. o nome (.) será "pessoa" neste caso. deve ser "nome", "profissão" e "hobby".
Ray Lu
@CodeMelt Por que então você não votou contra a resposta aceita? É bom, mas é ainda menos específico do que este. Votei na resposta de Rowland Shaw, pois fornece a resposta para a pergunta. Por favor, vote negativamente apenas quando uma resposta contiver informações erradas, incorretas ou enganosas
Dimitre Novatchev
4
Corrigido aquele pequeno detalhe - pessoalmente, acho que as pessoas deveriam explicar por que algo foi rejeitado, pois ajuda a explicar o conhecimento coletivo ...
Rowland Shaw
Nossas reputações podem chamar a atenção, mas como não garantem que o que postamos valha a pena, é a qualidade de nossa contribuição que realmente conta. Nenhum raciocínio contribui para contribuições de baixa qualidade.
Patanjali