2010-09-23 2 views
3

Я хочу получить набор элементов из xml-файла, но как только элементы будут занимать пространства имен, он терпит неудачу.NSXMLDocument, nodesForXPath с пространствами имен

Это фрагмент файла XML:

<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    version="1.0" creator="Groundspeak Pocket Query" 
    xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0 http://www.groundspeak.com/cache/1/0/cache.xsd" 
    xmlns="http://www.topografix.com/GPX/1/0"> 
    <name>My Finds Pocket Query</name> 
    <desc>Geocache file generated by Groundspeak</desc> 
    <author>Groundspeak</author> 
    <email>[email protected]</email> 
    <time>2010-09-15T16:18:55.9846906Z</time> 
    <keywords>cache, geocache, groundspeak</keywords> 
    <bounds minlat="41.89687" minlon="5.561883" maxlat="70.669967" maxlon="25.74735" />  
    <wpt lat="62.244933" lon="25.74735"> 
    <time>2010-01-11T08:00:00Z</time> 
    <name>GC22W1T</name> 
    <desc>Kadonneet ja karanneet by ooti, Traditional Cache (1.5/2)</desc> 
    <url>http://www.geocaching.com/seek/cache_details.aspx?guid=4af28fe9-401b-44df-b058-5fd5399fc083</url> 
    <urlname>Kadonneet ja karanneet</urlname> 
    <sym>Geocache Found</sym> 
    <type>Geocache|Traditional Cache</type> 
    <groundspeak:cache id="1521507" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0"> 
     <groundspeak:name>Kadonneet ja karanneet</groundspeak:name> 
     <groundspeak:placed_by>ooti</groundspeak:placed_by> 
     <groundspeak:owner id="816431">ooti</groundspeak:owner> 
     <groundspeak:type>Traditional Cache</groundspeak:type> 
     <groundspeak:container>Small</groundspeak:container> 
     <groundspeak:difficulty>1.5</groundspeak:difficulty> 
     <groundspeak:terrain>2</groundspeak:terrain> 
     <groundspeak:country>Finland</groundspeak:country> 
     <groundspeak:state> 
     </groundspeak:state> 
     <groundspeak:short_description html="True"> 
     </groundspeak:short_description> 
     <groundspeak:encoded_hints> 
     </groundspeak:encoded_hints> 
     <groundspeak:travelbugs /> 
    </groundspeak:cache> 
    </wpt> 
</gpx> 

Я хочу, чтобы получить все grounspeak:cache элементы, но ни //groundspeak:cache, ни //cache кажется, ничего возвращать.

NSArray *caches = [self.xml nodesForXPath:@"//cache" error:&error]; 

Любые подсказки?

Редактировать: Есть ли какое-либо программное обеспечение на основе какао, где я могу загрузить свой xml и протестировать разные xpaths? Я совершенно новичок в объективе-c и какао, поэтому было бы неплохо проверить, что это действительно мой xpath, это неправильно.

ответ

5

Это //cache означает: потомок элемента под нет имен (или пустое пространство имен)

Ваш groundspeak:cache элемент находится под пространством имен URI http://www.groundspeak.com/cache/1/0.

Так что, если вы не можете объявить связывание имен префикса (я думаю, вы не можете с какао ...), вы можете использовать это выражение XPath:

//*[namespace-uri()='http://www.groundspeak.com/cache/1/0' and 
    local-name()='cache'] 

Если вы не хотят быть настолько строги имен ...

//*[local-name()='cache'] 

Но это последнее плохая практика, потому что вы могли бы в конечном итоге выбор неправильных узлов, и потому, что при работе с XML, ваш инструмент должен поддерживать пространство имен.

В качестве доказательства, таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
      <xsl:copy-of select="//*[namespace-uri() = 
            'http://www.groundspeak.com/cache/1/0' and 
            local-name() = 'cache']"/> 
    </xsl:template> 
</xsl:stylesheet> 

Выход:

<groundspeak:cache id="1521507" available="True" archived="False" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns="http://www.topografix.com/GPX/1/0" 
      xmlns:groundspeak="http://www.groundspeak.com/cache/1/0"> 
    <groundspeak:name>Kadonneet ja karanneet</groundspeak:name> 
    <groundspeak:placed_by>ooti</groundspeak:placed_by> 
    <groundspeak:owner id="816431">ooti</groundspeak:owner> 
    <groundspeak:type>Traditional Cache</groundspeak:type> 
    <groundspeak:container>Small</groundspeak:container> 
    <groundspeak:difficulty>1.5</groundspeak:difficulty> 
    <groundspeak:terrain>2</groundspeak:terrain> 
    <groundspeak:country>Finland</groundspeak:country> 
    <groundspeak:state></groundspeak:state> 
    <groundspeak:short_description html="True"></groundspeak:short_description> 
    <groundspeak:encoded_hints></groundspeak:encoded_hints> 
    <groundspeak:travelbugs /> 
</groundspeak:cache> 
+0

Ни один из них, кажется, не возвращает никаких элементов: -/ – Vegar

+0

@Vegar: Это странно! Оба работают для меня с вашим документом в качестве входных данных. – 2010-09-24 12:06:30

+0

Работает ли это в вашем преобразовании таблиц стилей или работает в качестве входа для метода nodeForXPath ::? – Vegar

0

// reasonpeak: cache должен работать. Вам может понадобиться настройка пространства имен URI, а

+1

и как вы определяете настройку пространства имен? – Vegar

1

Вам нужно добавить новый атрибут пространства имен для корневого узла документа, определяющего префикс, который можно использовать при спрашивая детей:

NSXMLDocument *xmldoc = ... 
NSXMLElement *namespace = [NSXMLElement namespaceWithName:@"mns" stringValue:@"http://mynamespaceurl.com/mynamespace"]; 
[xmldoc.rootElement addNamespace:namespace]; 

, а затем, когда вы запрашиваете вещи позже, вы можете использовать этот префикс для ссылки на пространство имен:

NSArray * caches = [xmldoc.rootElement nodesForXPath:@"//mns:caches" error:&error]; 
Смежные вопросы