2010-09-23 6 views
3

Je souhaite obtenir un ensemble d'éléments à partir d'un fichier xml, mais dès que les éléments impliquent des espaces de noms, il échoue.NSXMLDocument, nodesForXPath avec espaces de noms

C'est un fragment du fichier 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> 

Je veux obtenir tous les éléments grounspeak:cache, mais ni //groundspeak:cache, ni //cache semble retourner quoi que ce soit.

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

Une idée? Edit: Y at-il un logiciel basé sur le cacao là-bas, où je peux charger mon xml et tester différents xpaths? Je suis assez nouveau pour l'objectif-c et le cacao, donc ce serait bien de vérifier que c'est vraiment mon xpath qui est faux ..

Répondre

5

Ce //cache signifie: un élément descendant sous aucun espace de noms (ou espace de noms vide)

Votre élément groundspeak:cache est sous un espace de noms URI http://www.groundspeak.com/cache/1/0.

Donc, si vous ne pouvez pas déclarer un espace de noms de liaison préfixe (je pense que vous ne pouvez pas avec le cacao ...), vous pouvez utiliser cette expression XPath:

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

Si vous n'êtes pas veulent être si stricte à propos de l'espace de noms ...

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

Mais ce dernier est une mauvaise pratique, parce que vous pourriez finir par sélectionner des noeuds mal, et parce que lorsqu'ils traitent avec XML, votre outil devrait soutenir namespaces.

Pour preuve, cette feuille de style:

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

Sortie:

<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

Aucun d'entre eux semble retourner des éléments: -/ – Vegar

+0

@Vegar: C'est étrange! Les deux travaille pour moi avec votre document en entrée. –

+0

Cela fonctionne-t-il dans votre transformation de feuille de style ou fonctionne-t-il comme une entrée pour la méthode nodesForXPath ::? – Vegar

0

// groundspeak: le cache devrait fonctionner. Vous pourriez avoir besoin d'un cadre de namespace-uri ainsi

+1

et comment spécifiez-vous un paramètre d'espace de noms-uri? – Vegar

1

Vous devez ajouter un nouvel attribut d'espace de noms au nœud racine de votre document, la définition d'un préfixe que vous pouvez utiliser lorsque interroger les enfants:

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

puis lorsque vous interrogez les choses plus tard, vous pouvez utiliser ce préfixe pour faire référence à l'espace de noms:

NSArray * caches = [xmldoc.rootElement nodesForXPath:@"//mns:caches" error:&error]; 
Questions connexes