Как получить значение атрибута при использовании XSLT с неизвестным пространством имен? - PullRequest
3 голосов
/ 16 сентября 2008

Я получаю сторонний фид, в котором я не могу быть уверен в пространстве имен, поэтому в настоящее время мне приходится использовать функцию local-name () в моем XSLT для получения значений элементов. Однако мне нужно получить атрибут от одного такого элемента, и я не знаю, как это сделать, когда пространства имен неизвестны (следовательно, необходима функция local-name ()).

N.B. Я использую .net 2.0 для обработки XSLT

Вот пример 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>

Это 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>

Я пытаюсь заменить переменную $ CurrentCategory соответствующим кодом для отображения mycategorytext

Ответы [ 3 ]

12 голосов
/ 17 сентября 2008

У меня нет редактора XSLT здесь, но вы пробовали использовать

*[local-name()='category']/@*[local-name()='term']
2 голосов
/ 17 сентября 2008

Согласно http://www.w3.org/TR/2006/REC-xml-names-20060816/#scoping-defaulting

"Объявления пространства имен по умолчанию не применяются непосредственно к именам атрибутов; интерпретация нефиксированных атрибутов определяется элементом, на котором они появляются."

Это означает, что ваши атрибуты не находятся в пространстве имен. Просто используйте "@term".

Просто, чтобы прояснить ситуацию, нет необходимости использовать local-name () для решения этой проблемы. Обычный способ справиться с этим - объявить префикс для пространства имен atom в вашем XSLT, а затем использовать его в запросах xpath.

У вас уже есть это объявление в вашем элементе таблицы стилей (xmlns: atom = "http://www.w3.org/2005/Atom"),, поэтому все, что остается, - это использовать его.

Как я уже объяснил, на атрибут не влияет пространство имен по умолчанию, поэтому ваш код будет выглядеть следующим образом (при условии, что вы добавите "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 () может быть очень полезен, если вы действительно не знаете структуру XML-файла, который вы преобразовываете, но в этом случае, если вы получите что-то, отличное от того, что вы ожидаете, он сломается дело.

0 голосов
/ 17 сентября 2008

Я не совсем уверен, почему вы должны использовать local-name (), но если вы поделитесь немного большей информацией о том, какой процессор xslt вы используете вместе с языком, я буду, что это можно выяснить , Я говорю это б / к, вы должны быть в состоянии сделать что-то вроде:

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

Две вещи, которые я надеюсь вам помочь, - это объявление xmlns вверху без префикса. Это устанавливает пространство имен по умолчанию, поэтому вам не нужно использовать префиксы пространства имен. Аналогично, вы можете вызвать do 'xmlns: a = "http://www.w3.org/2005/Atom"', а затем do' select =" a: feed "'. Другая вещь, на которую стоит обратить внимание, - это использование @term, который выбирает атрибуты. любой атрибут '@ *' работает так же, как и для элементов.

Опять же, в зависимости от процессора, в вашем распоряжении могут быть и другие полезные инструменты, поэтому, если вы сможете предоставить немного больше информации, это может помочь. Кроме того, список рассылки XSL может быть другим полезным ресурсом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...