2009-11-26 4 views
0

Il y a un fichier XML avec des taux de change http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml:Pourquoi ma requête XPath vers un fichier XML sur le Web ne fonctionne pas?

<gesmes:Envelope> 
    <gesmes:subject>Reference rates</gesmes:subject> 
    <gesmes:Sender> 
    <gesmes:name>European Central Bank</gesmes:name> 
    </gesmes:Sender> 
    <Cube> 
    <Cube time="2009-11-26"> 
     <Cube currency="USD" rate="1.5071"/> 
     ... 

je demande à côté XPath:

var doc = new XmlDocument(); 
doc.Load(url); 
var node = doc.SelectSingleNode("//Cube[@currency=\"USD\""]); 
var value = node.Attributes["rate"].Value; 

mais il retourne null! Où est mon erreur?

Si je fais cette demande, tout fonctionne très bien:

var node = dic.SelectSingleNode("//*[@currency=\"USD\"]"); 
var name = node.Name; // "Cube" 

Répondre

4

Essayez

var node = doc.SelectSingleNode("//*[local-name()='Cube' and @currency=\"USD\""]); 

vous pouvez toujours ajouter dans l'espace de noms si vous le connaissez

var node = doc.SelectSingleNode("//*[local-name()='Cube' and 
    namespace-uri()='http://www.ecb.int/vocabulary/2002-08-01/eurofxref' and 
    @currency=\"USD\""]); 

Bien qu'il soit longwinded je préfère à essayer de trier les préfixes d'espace de noms. Et il évite également le problème de l'espace de noms par défaut (xmlns="")

+0

Merci! Ça marche! Btw, je pense qu'il est préférable d'utiliser le même symbole pour citation dans XPath: guillemets "ou apostrophe" – abatishchev

+0

Bon - j'utiliserais normalement '...' mais je le laisserais dans vos citations pour ne pas dérouter les lecteurs. comme j'utilise Java et les barres obliques inversées se multiplient assez rapidement –

5

Le problème est l'espace de noms. Si vous pouvez utiliser LINQ to XML, vous pouvez exprimer cette requête assez facilement. Dans le cas contraire, légèrement plus délicat - que vous voudriez quelque chose comme ceci:

var doc = new XmlDocument(); 
doc.Load(url); 
XPathNavigator navigator = doc.CreateNavigator();  
XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable); 
nsMgr.AddNamespace("gesmes", "http://www.gesmes.org/xml/2002-08-01"); 
nsMgr.AddNamespace("ns0", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref"); 

var node = doc.SelectSingleNode("//ns0:Cube[@currency=\"USD\""], nsMgr); 
var value = node.Attributes["rate"].Value; 

(Vous n'avez pas vraiment besoin l'espace de noms GESMES dans le gestionnaire là-bas, mais il sera plus facile si vous avez besoin de regarder tous les autres éléments.)

EDIT: La réponse de Peter Murray-Rust est une bonne alternative ici - quelle approche vous choisissez dépend de la façon dont vous voulez que l'élément puisse trouver. Si vous avez seulement besoin de l'espace de noms pour une requête, il est logique d'inclure l'URI directement dans le XPath; Si vous en avez besoin pour plus que cela, vous obtiendrez des requêtes plus concises en utilisant le gestionnaire d'espace de noms.

2

XPathVisualizer peut être pratique. C'est gratuit. Il ne vous aurait pas dit d'utiliser l'espace de noms, mais il aurait placé l'espace de noms devant vous dans l'interface utilisateur, et il vous aurait permis de tester un tas d'alternatives, très rapidement.

alt text

+0

Merci! Ça a l'air cool! Je vais l'utiliser. – abatishchev

Questions connexes