NSXMLDocument, nodesForXPath с пространствами имен

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

Это фрагмент 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 и протестировать разные пути xpath? Я новичок в target-c и какао, поэтому было бы неплохо проверить, действительно ли мой xpath неверен.


person Vegar    schedule 23.09.2010    source источник


Ответы (3)


Этот //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>
person Community    schedule 23.09.2010
comment
Ни один из них, похоже, не возвращает никаких элементов: -/ - person Vegar; 24.09.2010
comment
@Vegar: Это странно! Оба работают для меня с вашим документом в качестве входных данных. - person ; 24.09.2010
comment
Работает ли он в преобразовании вашей таблицы стилей или работает как вход для метода nodesForXPath::? - person Vegar; 29.09.2010
comment
Он работает с таблицей стилей. Таким образом, он должен работать с вашим движком XPath, если только он не является стандартным. - person ; 29.09.2010
comment
Хорошо, это работает. Не знаю, почему у меня сначала были проблемы с этим. Спасибо. - person Vegar; 06.10.2010
comment
@Vegar: я рад, что это было полезно. - person ; 06.10.2010

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

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];
person Amy Worrall    schedule 30.04.2012

//groundspeak:кэш должен работать. Вам также может понадобиться параметр namespace-uri

person abdollar    schedule 23.09.2010
comment
и как указать параметр namespace-uri? - person Vegar; 24.09.2010