¿Hay un elemento de nombre de XSLT?

101

En XSLT existe

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

para obtener el valor de un elemento, pero ¿hay algo para seleccionar el nombre de etiqueta del elemento?

En una situación 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 obtener un resultado como este:

name : Robert
profession : programmer
hobby : photography

Por supuesto, el XSLT anterior no se compilará porque

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

no existe. Pero, ¿cómo podría hacerse esto?

Robert Gould
fuente
La etiqueta más relevante para esta pregunta es XPath. Ambas funciones son funciones estándar de XPath y se pueden usar dentro de una expresión XPath en el contexto de cualquier lenguaje de alojamiento (C #, XSLT, XQuery, ...) Por favor, vuelva a etiquetar
Dimitre Novatchev
Este texto: "En XSLT hay <xsd: value-of select =" expression "/>" - contiene un error. El prefijo utilizado habitualmente para las instrucciones XSLT es "xsl". Por lo general, cuando usamos XML Schema usamos el prefijo "xsd" o "xs". Por favor, corrija.
Dimitre Novatchev

Respuestas:

157

Esto le dará el nombre del elemento actual (nombre de etiqueta)

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

OP-Edit: esto también hará el truco:

<xsl:value-of select ="local-name()"/>
SO Usuario
fuente
12
nombre-local es lo que quieres 9 de cada 10 veces
annakata
20
local-name es sin espacio de nombres, por eso suele ser mejor.
Jon W
102

Nadie señaló la sutil diferencia en la semántica de las funciones name()y local-name().

  • name(someNode) devuelve el nombre completo del nodo, y eso incluye el prefijo y los dos puntos en caso de que el nodo sea un elemento o un atributo.
  • local-name(someNode) devuelve solo el nombre local del nodo, y eso no incluye el prefijo y los dos puntos en caso de que el nodo sea un elemento o un atributo.

Por lo tanto, en situaciones en las que un nombre puede pertenecer a dos espacios de nombres diferentes, se debe usar la name()función para que estos nombres aún se distingan.

Y, por cierto, es posible especificar ambas funciones sin ningún argumento :

name() es una abreviatura de name(.)

local-name() es una abreviatura de local-name(.)

Finalmente , recuerde que no solo los elementos y atributos tienen nombres, estas dos funciones también se pueden usar en los PI y en estos son idénticos).

Dimitre Novatchev
fuente
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
fuente
Como una buena práctica, siempre use normalize-space () cuando obtenga el valor del nodo <xsl: value-of select = "normalize-space (.)" /> Esto recortará los espacios adicionales
SO User
Tal normalización / desinfección solo sería necesaria si no se hubiera manejado en la etapa de recolección de entrada. Hacerlo ahorra tener que hacerlo en el momento del acceso, que suele ser mucho más frecuente. Uno lo haría antes de agregarlo a un RDB, y un documento xml es solo otra base de datos.
Patanjali
9

Para los interesados, no hay:

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

Sin embargo, puede volver a crear la etiqueta / elemento yendo a:

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

Esto es útil en una plantilla xslt que, por ejemplo, maneja valores de datos de formato para muchos elementos diferentes. Cuando no conoce el nombre del elemento en el que se está trabajando y aún puede generar el mismo elemento y modificar el valor si es necesario.

Tim
fuente
6
<xsl:value-of select="name(.)" /> : <xsl:value-of select="."/>
Rowland Shaw
fuente
Entonces, ¿por qué se votó esto? De acuerdo, podría haber mencionado local-name () si no quisiera el espacio de nombres también, pero sería útil para la comunidad en general explicar por qué esto no funcionaría.
Rowland Shaw
Quizás, no pudo transformar el XML dado. el nombre (.) será "persona" en este caso. debe ser "nombre", "profesión" y "afición".
Ray Lu
@CodeMelt ¿Por qué entonces no votó en contra de la respuesta aceptada? Es bueno, pero es incluso menos específico que este. Elegí la respuesta de Rowland Shaw, ya que proporciona la respuesta a la pregunta. Por favor, vote en contra solo cuando una respuesta contenga información incorrecta, incorrecta o engañosa
Dimitre Novatchev
4
Se corrigió ese pequeño detalle: personalmente, creo que la gente debería explicar por qué se rechaza algo, ya que ayuda a explicar el conocimiento colectivo ...
Rowland Shaw
Nuestra reputación puede llamar la atención, pero como no garantizan que lo que hemos publicado valga la pena, lo que realmente cuenta es la calidad de nuestra contribución. Ningún razonamiento da lugar a contribuciones de mala calidad.
Patanjali