Come posso ottenere un valore di attributo quando utilizzo XSLT con spazio dei nomi sconosciuto?

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

  •  09-06-2019
  •  | 
  •  

Domanda

Ricevo un feed di terze parti di cui non posso essere certo dello spazio dei nomi, quindi attualmente devo utilizzare la funzione local-name() nel mio XSLT per ottenere i valori degli elementi.Tuttavia ho bisogno di ottenere un attributo da uno di questi elementi e non so come farlo quando gli spazi dei nomi sono sconosciuti (quindi è necessaria la funzione local-name()).

N.B.Sto utilizzando .net 2.0 per elaborare XSLT

Ecco un esempio di 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>

Questo è 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>

Sto cercando di sostituire la variabile $CurrentCategory con il codice appropriato da visualizzare mycategorytext

È stato utile?

Soluzione

Non ho un editor XSLT qui, ma hai provato a usarlo

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

Altri suggerimenti

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

"Le dichiarazioni dello spazio dei nomi predefinito non si applicano direttamente ai nomi degli attributi;l'interpretazione degli attributi senza prefisso è determinata dall'elemento su cui compaiono."

Ciò significa che i tuoi attributi non si trovano in uno spazio dei nomi.Basta usare "@term".

Giusto per essere un po' più chiari, non è necessario utilizzare local-name() per risolvere questo problema.Il modo convenzionale per gestirlo sarebbe dichiarare un prefisso per lo spazio dei nomi atom nel tuo XSLT e quindi utilizzarlo nelle query xpath.

Hai già ottenuto questa dichiarazione sul tuo elemento del foglio di stile (xmlns:atom="http://www.w3.org/2005/Atom"), quindi tutto ciò che resta è usarlo.

Come ho già spiegato, l'attributo non è influenzato dallo spazio dei nomi predefinito, quindi il tuo codice sarebbe simile a questo (assumendo che dovessi aggiungere "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() può essere molto utile se non conosci davvero la struttura dell'XML che stai trasformando, ma in questo caso, se ricevi qualcosa di diverso da quello che ti aspetti, si romperà comunque.

Non sono proprio sicuro del motivo per cui devi utilizzare local-name(), ma se condividi qualche informazione in più su quale processore xslt stai utilizzando insieme alla lingua, sarò in grado di capirlo.Lo dico perché dovresti essere in grado di fare qualcosa del tipo:

<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>

Le due cose che spero ti aiutino sono la dichiarazione xmlns in alto senza prefisso.Ciò imposta lo spazio dei nomi predefinito in modo da non dover utilizzare i prefissi dello spazio dei nomi.Allo stesso modo, potresti chiamare do 'xmlns:a="http://www.w3.org/2005/Atom"' e poi fare 'select="a:feed"'.L'altra cosa da notare è l'uso di '@term' che seleziona gli attributi.Se desideri abbinare qualsiasi attributo '@*' funziona esattamente come per gli elementi.

Ancora una volta, a seconda del processore, potrebbero esserci altri strumenti utili a tua disposizione, quindi se puoi fornire qualche informazione in più potrebbe essere utile.Anche il Lista di distribuzione XSL potrebbe essere un'altra risorsa utile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top