¿Cómo obtengo un valor de atributo cuando uso XSLT con un espacio de nombres desconocido?

StackOverflow https://stackoverflow.com/questions/76204

  •  09-06-2019
  •  | 
  •  

Pregunta

Recibo una fuente de terceros cuyo espacio de nombres no puedo estar seguro, por lo que actualmente tengo que usar la función local-name() en mi XSLT para obtener los valores de los elementos.Sin embargo, necesito obtener un atributo de uno de esos elementos y no sé cómo hacerlo cuando los espacios de nombres son desconocidos (de ahí la necesidad de la función local-name()).

NÓTESE BIEN.Estoy usando .net 2.0 para procesar el XSLT

Aquí hay una muestra del XML:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
   <id>some id</id>
   <title>some title</title>
   <updated>2008-09-11T15:53:31+01:00</updated>
   <link rel="self" href="http://www.somefeedurl.co.uk" />
   <author>
      <name>some author</name>
      <uri>http://someuri.co.uk</uri>
   </author>
   <generator uri="http://aardvarkmedia.co.uk/">AardvarkMedia script</generator>
   <entry>
      <id>http://soemaddress.co.uk/branded3/80406</id>
      <title type="html">My Ttile</title>
      <link rel="alternate" href="http://www.someurl.co.uk" />
      <updated>2008-02-13T00:00:00+01:00</updated>
      <published>2002-09-11T14:16:20+01:00</published>
      <category term="mycategorytext" label="restaurant">Test</category>
      <content type="xhtml">
         <div xmlns="http://www.w3.org/1999/xhtml">
            <div class="vcard">
               <p class="fn org">some title</p>
               <p class="adr">
                  <abbr class="type" title="POSTAL" />
                  <span class="street-address">54 Some Street</span>
                  ,
                  <span class="locality" />
                  ,
                  <span class="country-name">UK</span>
               </p>
               <p class="tel">
                  <span class="value">0123456789</span>
               </p>
               <div class="geo">
                  <span class="latitude">51.99999</span>
                  ,
                  <span class="longitude">-0.123456</span>
               </div>
               <p class="note">
                  <span class="type">Review</span>
                  <span class="value">Some content</span>
               </p>
               <p class="note">
                  <span class="type">Overall rating</span>
                  <span class="value">8</span>
               </p>
            </div>
         </div>
      </content>
      <category term="cuisine-54" label="Spanish" />
      <Point xmlns="http://www.w3.org/2003/01/geo/wgs84_pos#">
         <lat>51.123456789</lat>
         <long>-0.11111111</long>
      </Point>
   </entry>
</feed>

Esto es XSLT

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:wgs="http://www.w3.org/2003/01/geo/wgs84_pos#" exclude-result-prefixes="atom wgs">
  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="uniqueVenuesKey" match="entry" use="id"/>
  <xsl:key name="uniqueCategoriesKey" match="entry" use="category/@term"/>

  <xsl:template match="/">
    <locations>
      <!-- Get all unique venues -->
      <xsl:for-each select="/*[local-name()='feed']/*[local-name()='entry']">
        <xsl:variable name="CurrentVenueKey" select="*[local-name()='id']" ></xsl:variable>
        <xsl:variable name="CurrentVenueName" select="*[local-name()='title']" ></xsl:variable>
        <xsl:variable name="CurrentVenueAddress1" select="*[local-name()='content']/*[local-name()='div']/*[local-name()='div']/*[local-name()='p'][@class='adr']/*[local-name()='span'][@class='street-address']" ></xsl:variable>
        <xsl:variable name="CurrentVenueCity" select="*[local-name()='content']/*[local-name()='div']/*[local-name()='div']/*[local-name()='p'][@class='adr']/*[local-name()='span'][@class='locality']" ></xsl:variable>
        <xsl:variable name="CurrentVenuePostcode" select="*[local-name()='postcode']" ></xsl:variable>
        <xsl:variable name="CurrentVenueTelephone" select="*[local-name()='telephone']" ></xsl:variable>
        <xsl:variable name="CurrentVenueLat" select="*[local-name()='Point']/*[local-name()='lat']" ></xsl:variable>
        <xsl:variable name="CurrentVenueLong" select="*[local-name()='Point']/*[local-name()='long']" ></xsl:variable>
        <xsl:variable name="CurrentCategory" select="WHATDOIPUTHERE"></xsl:variable>

            <location>
              <locationName>
                <xsl:value-of select = "$CurrentVenueName" />
              </locationName>
              <category>
                <xsl:value-of select = "$CurrentCategory" />
              </category>
              <description>
                  <xsl:value-of select = "$CurrentVenueName" />
              </description>
              <venueAddress>
                <streetName>
                  <xsl:value-of select = "$CurrentVenueAddress1" />
                </streetName>
                <town>
                  <xsl:value-of select = "$CurrentVenueCity" />
                </town>
                <postcode>
                  <xsl:value-of select = "$CurrentVenuePostcode" />
                </postcode>
                <wgs84_latitude>
                  <xsl:value-of select = "$CurrentVenueLat" />
                </wgs84_latitude>
                <wgs84_longitude>
                  <xsl:value-of select = "$CurrentVenueLong" />
                </wgs84_longitude>
              </venueAddress>
              <venuePhone>
                <phonenumber>
                  <xsl:value-of select = "$CurrentVenueTelephone" />
                </phonenumber>
              </venuePhone>
          </location>
        </xsl:for-each>
    </locations>
  </xsl:template>
</xsl:stylesheet>

Estoy intentando reemplazar la variable $CurrentCategory con el código apropiado para mostrar micategoríatexto

¿Fue útil?

Solución

No tengo un editor XSLT aquí, pero ¿has intentado usar?

*[local-name()='category']/@*[local-name()='term']

Otros consejos

De acuerdo a http://www.w3.org/TR/2006/REC-xml-names-20060816/#scoping-defaulting

"Las declaraciones de espacios de nombres predeterminadas no se aplican directamente a los nombres de atributos;la interpretación de los atributos sin prefijo está determinada por el elemento en el que aparecen."

Esto significa que sus atributos no están en un espacio de nombres.Simplemente use "@term".

Para ser un poco más claro, no es necesario utilizar local-name() para resolver este problema.La forma convencional de lidiar con esto sería declarar un prefijo para el espacio de nombres atom en su XSLT y luego usarlo en sus consultas xpath.

Ya tienes esta declaración en tu elemento de hoja de estilo (xmlns:atom="http://www.w3.org/2005/Atom"), así que todo lo que queda es usarla.

Como ya he explicado, el atributo no se ve afectado por el espacio de nombres predeterminado, por lo que su código se vería así (suponiendo que agregara "xmlns:xhtml='http://www.w3.org/1999/xhtml'"):

      <xsl:for-each select="/atom:feed/atom:entry">
        <xsl:variable name="CurrentVenueKey" select="atom:id" />
        <xsl:variable name="CurrentVenueName" select="atom:title" />
        <xsl:variable name="CurrentVenueAddress1" 
             select="atom:content/xhtml:div/xhtml:div/xhtml:p[@class='adr']/xhtml:span[@class='street-address']" />
        <xsl:variable name="CurrentVenueCity" 
             select="atom:content/xhtml:div/xhtml:div'/xhtml:p[@class='adr']/xhtml:span[@class='locality'] />
...
        <xsl:variable name="CurrentCategory" select="atom:category/@term" />

..... 

local-name() puede ser muy útil si realmente no conoces la estructura del XML que estás transformando, pero en este caso, si recibes algo diferente a lo que esperabas, se romperá de todos modos.

No estoy realmente seguro de por qué tienes que usar local-name(), pero si compartes un poco más de información sobre qué procesador xslt estás usando junto con el idioma, sabré que se puede resolver.Digo esto porque deberías poder hacer algo como:

<xsl:stylesheet xmlns="http://www.w3.org/2005/Atom" ..>

<xsl:template match="feed">
  <xsl:apply-templates />
</xsl:template>

<xsl:template match="entry">
  ... 
  <xsl:variable name="current-category" select="category/@term" />
  ...
</xsl:template>

Las dos cosas que espero que te ayuden son la declaración xmlns en la parte superior sin prefijo.Eso establece el espacio de nombres predeterminado para que no tenga que usar los prefijos del espacio de nombres.Del mismo modo, podrías llamar a do 'xmlns:a="http://www.w3.org/2005/Atom"' y luego hacer 'select="a:feed"'.La otra cosa a tener en cuenta es el uso del '@term' que selecciona atributos.Si desea hacer coincidir cualquier atributo, '@*' funciona igual que lo haría con los elementos.

Nuevamente, dependiendo del procesador, es posible que haya otras herramientas útiles a su disposición, por lo que si puede proporcionar un poco más de información, podría resultar útil.También el lista de correo XSL podría ser otro recurso útil.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top