2009-02-09 7 views
20

J'essaye d'utiliser XPath pour trouver tous les éléments qui ont un élément dans un espace de noms donné.XPath - Recherche d'éléments par l'espace de nom d'attribut

Par exemple, dans le document suivant je veux trouver le foo: bar et éléments Doodah

<?xml version="1.0" encoding="UTF-8"?> 
<root xmlns:foo="http://foo.example.com"> 
    <foo:bar quux="value">Content</foo:bar> 
    <widget>Content</widget> 
    <doodah foo:quux="value">Content</doodah> 
</root> 

Je sais que je peux utiliser l'expression XPath suivante pour charger tous les attributs d'un espace de noms donné

"//@*[namespace-uri()='http://foo.example.com']" 

Cependant:

  • Cela ne me donne pas les éléments, seulement les attributs et
  • où les éléments contiennent plusieurs attributs de cet espace de noms, ce XPath renvoie un résultat par attribut plutôt que par élément

Est-il possible d'obtenir ce que je veux, ou dois-je simplement de rassembler les attributs et calculer l'ensemble unique d'éléments auxquels ils correspondent?

EDIT: Dimitre Novatchev m'a donné la réponse suivante. Je ne savais pas que vous pourriez nid prédicats à l'intérieur prédicats comme ceci:

"//*[@*[namespace-uri()='http://foo.example.com']]" 

Plus précisément, cela dit: « Tout élément qui a un attribut qui a namespace-uri = « ... » »

+0

Avez-vous oublié d'ajouter un espace de nom pour doodah? Parce que je ne vois pas comment il peut être sélectionné à travers un espace de noms. – potyl

+0

Si les clarifications n'étaient pas claires, j'ai utilisé le mauvais espace de noms dans mon exemple original. Mon erreur. – Gareth

+1

Merci pour ce post, ça m'a vraiment aidé. Pour résumer: - Pour obtenir des éléments avec des attributs d'un espace de noms donné: '// * [@ * [namespace-uri() = 'http: //foo.example.com']]' - Pour obtenir les attributs d'un espace de noms donné: '// @ * [namespace-uri() = 'http: //foo.example.com']' –

Répondre

24

Utilisation:

//*[namespace-uri()='yourNamespaceURI-here' 
    or 
     @*[namespace-uri()='yourNamespaceURI-here'] 
    ] 

le prédicat deux conditions sont ou ed avec l'opérateur XPath or.

L'expression XPath sélectionne donc tout élément qui soit:

  • appartient à l'espace de nommage spécifié

ou

  • possède des attributs qui appartiennent à la spécifiée espace de noms
+0

Ce n'était que la seconde moitié de ce dont j'avais besoin :) Je ne savais pas que vous pouviez imbriquer des prédicats dans les prédicats. Ont mis à jour mon poste en conséquence – Gareth

+0

@Dimitre Novatchev pourriez-vous pls jeter un oeil ici est-ce un problème d'espace de noms? tnx http://stackoverflow.com/questions/7007767/iphone-sdk-xml-mystery-after-adding-child-nodeforxpath-returns-nothing – Spring

4

Je ne sais pas si c'est ce que vous voulez dire, mais que par la suppression de 1 car dans votre XPath vous obtenez tous les éléments dans un certain espace de noms:

//*[namespace-uri()='http://foo.example.com'] 
+0

ne correspond pas aux attributs dans cet espace de noms –

0

vous pouvez essayer

//*[namespace-uri()='http://foo.example.com' or @*[namespace-uri()='http://foo.example.com']] 

Il vous donnera élément foo: bar et Doodah élément (si vous changez tal:quux-foo:quux dans votre XML-données):

<?xml version="1.0" encoding="UTF-8"?> 
<root xmlns:foo="http://foo.example.com" xmlns:tal="xxx"> 
    <foo:bar quux="value">Content</foo:bar> 
    <widget>Content</widget> 
    <doodah foo:quux="value">Content</doodah> 
</root> 

est que ce que vous voulez?

EDIT: Merci d'avoir repéré l'erreur d'attribut, corrigée maintenant.

+0

Pas tout à fait ... namespace-uri (./@*) = 'http: //foo.exemple.com'] renvoie true uniquement si le premier attribut (qui dépend de l'implémentation!) appartient à cet espace de noms. Le message d'origine veut que l'élément soit sélectionné si * un * de ses attributs appartient à l'espace de noms –

+0

Oups, bon point avec le talon que j'ai laissé là par erreur – Gareth

0

Votre expression XPath est presque parfaite. Au lieu de demander des attributs "@" demander des éléments "" et il devrait fonctionner:

"//*[namespace-uri()='http://foo.example.com']" 
+0

Vous n'avez pas compris la question. L'OP souhaite que tout élément soit sélectionné, qu'il appartienne à l'espace de noms ou qu'il possède au moins un attribut appartenant à l'espace de noms. Votre expression ne sélectionne pas un élément qui a des attributs dans l'espace de noms mais l'élément n'appartient pas à l'espace de noms –

+0

Merci pour la clarification. Je sais que je n'ai pas compris la question car j'ai ajouté un commentaire à la question demandant pourquoi "doodah" devrait être choisi. – potyl

Questions connexes