dati ottenendo difficoltà su un file xml
-
29-09-2019 - |
Domanda
Sto cercando di analizzare alcune informazioni da API geocoding di Google, ma io sto avendo un po 'di problemi con ottenere in modo efficiente i dati dal XML. vedi link per esempio
Tutto ciò che ha realmente a cuore è sempre il short_name
dal address_component
dove il tipo è administrative_area_level_1
e il long_name
da administrative_area_level_2
Tuttavia, con il mio programma di test la mia query XPath ha prodotto alcun risultato per entrambe le query.
public static void Main(string[] args)
{
using(WebClient webclient = new WebClient())
{
webclient.Proxy = null;
string locationXml = webclient.DownloadString("http://maps.google.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false");
using(var reader = new StringReader(locationXml))
{
var doc = new XPathDocument(reader);
var nav = doc.CreateNavigator();
Console.WriteLine(nav.SelectSingleNode("/GeocodeResponse/result/address_component[type=administrative_area_level_1]/short_name").InnerXml);
Console.WriteLine(nav.SelectSingleNode("/GeocodeResponse/result/address_component[type=administrative_area_level_2]/long_name").InnerXml);
}
}
}
Qualcuno può aiutarmi a trovare quello che sto facendo male, o di raccomandare un modo migliore?
Soluzione
Hai bisogno di mettere il valore del nodo che stai cercando tra virgolette:
".../address_component[type='administrative_area_level_1']/short_name"
↑ ↑
Altri suggerimenti
Consiglio vivamente usando LINQ to XML, invece di XPathNavigator. Rende XML interrogazione di un gioco da ragazzi, nella mia esperienza. In questo caso non sono sicuro esattamente che cosa c'è che non va ... ma vengo con un LINQ to XML snippet invece.
using System;
using System.Linq;
using System.Net;
using System.Xml.Linq;
class Test
{
public static void Main(string[] args)
{
using(WebClient webclient = new WebClient())
{
webclient.Proxy = null;
string locationXml = webclient.DownloadString
("http://maps.google.com/maps/api/geocode/xml?address=1600"
+ "+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false");
XElement root = XElement.Parse(locationXml);
XElement result = root.Element("result");
Console.WriteLine(result.Elements("address_component")
.Where(x => (string) x.Element("type") ==
"administrative_area_level_1")
.Select(x => x.Element("short_name").Value)
.First());
Console.WriteLine(result.Elements("address_component")
.Where(x => (string) x.Element("type") ==
"administrative_area_level_2")
.Select(x => x.Element("long_name").Value)
.First());
}
}
}
Ora, questa è di più codice 1 ... ma personalmente trovo più facile per ottenere il diritto di XPath, perché il compilatore mi sta aiutando di più.
EDIT: mi sento vale la pena andare in un po 'più particolare circa il motivo per cui in generale preferisco il codice come questo rispetto all'uso di XPath, anche se è nettamente più lunghi
.Quando si utilizza XPath all'interno di un programma C #, si hanno due lingue diverse - ma solo uno è in controllo (C #). XPath è relegata al regno di stringhe: Visual Studio non dà un'espressione XPath alcun trattamento speciale; esso non comprendere che è destinata ad essere un'espressione XPath, in modo che non si può aiutare. Non è che Visual Studio non conosce XPath; come sottolinea Dimitre, è perfettamente in grado di avvistare errori se si sta modificando un file XSLT, non solo un file C #.
Questo è il caso ogni volta che avete una lingua incorporato all'interno di un altro e lo strumento non è a conoscenza di esso. Esempi comuni sono:
- SQL
- Le espressioni regolari
- HTML
- XPath
Quando il codice è presentato come dati all'interno di un'altra lingua, la lingua secondaria perde un sacco di suoi benefici utensili.
Mentre si possono contesto passare tutto il luogo, tirando fuori il XPath (o SQL, o espressioni regolari, ecc) nella propria attrezzatura (possibilmente all'interno dello stesso programma vero e proprio, ma in un file separato o finestra) trovo questo rende più difficile per lettura-codice nel lungo periodo. Se il codice è stato sempre e solo scritto e mai letto poi, che potrebbe essere a posto -. Ma do devono essere in grado di leggere il codice in seguito, e io personalmente credo le soffre di leggibilità quando questo accade
Il LINQ to XML versione sopra sempre e solo utilizza stringhe per i dati puri - i nomi degli elementi, ecc - e il codice utilizzi (chiamate di metodo) per rappresentare le azioni come "trovare elementi con un dato nome" o "applicare il filtro". Questo è più idiomatica codice C #, a mio avviso.
Ovviamente altri non condividono questo punto di vista, ma ho pensato che vale la pena ampliando per mostrare dove vengo.
Si noti che questo non è un regola , naturalmente ... in alcuni casi XPath, espressioni regolari, ecc sono la soluzione migliore duro e veloce. In questo caso, preferisco il LINQ to XML, questo è tutto.
1 Certo che potrebbe hanno mantenuto ogni chiamata Console.WriteLine
su una sola riga, ma non mi piace il codice distacco con barre di scorrimento orizzontali sul SO. Si noti che la scrittura della versione XPath corretta con lo stesso rientro come sopra ed evitare lo scorrimento è ancora piuttosto brutta:
Console.WriteLine(nav.SelectSingleNode("/GeocodeResponse/result/" +
"address_component[type='administrative_area_level_1']" +
"/short_name").InnerXml);
In generale, le linee lungo lavoro molto meglio in Visual Studio di quanto non facciano su Stack Overflow ...
mi sento di raccomandare semplicemente digitando l'espressione XPath come parte di un file XSLT in Visual Studio . Otterrete i messaggi di errore "durante la digitazione" - questa è un'ottima XML / XSLT / XPath Editor
.Ad esempio, sto scrivendo:
<xsl:apply-templates select="@* | node() x"/>
e immediatamente ottenere nella finestra Elenco errori il seguente errore :
Error 9 Expected end of the expression, found 'x'. @* | node() -->x<--
XSLTFile1.xslt 9 14 Miscellaneous Files
Solo quando l'espressione XPath non solleva gli eventuali errori (potrei anche test che seleziona i nodi previsti, anche), dovrei mettere questa espressione nel mio codice C # .
In questo modo, non avrò XPath - sintassi e semantica -. Errori quando si esegue il programma C #
risposta del DTB è accurato. Volevo aggiungere che è possibile utilizzare XPath testare strumenti come il link qui sotto per aiutare a trovare il XPath corretta:
string url = @"http://maps.google.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false";
string value = "administrative_area_level_1";
using(WebClient client = new WebClient())
{
string wcResult = client.DownloadString(url);
XDocument xDoc = XDocument.Parse(wcResult);
var result = xDoc.Descendants("address_component")
.Where(p=>p.Descendants("type")
.Any(q=>q.Value.Contains(value))
);
}
Il risultato è un'enumerazione di s "address_component" che hanno almeno un nodo "tipo" che ha contiene il valore che si sta cercando. Il risultato della query sopra è una XElement che contiene i seguenti dati.
<address_component>
<long_name>California</long_name>
<short_name>CA</short_name>
<type>administrative_area_level_1</type>
<type>political</type>
</address_component>
Consiglio davvero spendere un po 'di apprendimento LINQ tempo, in generale, perché è molto utile per la manipolazione e l'interrogazione oggetti in memoria, interrogazione di banche dati e tende ad essere più facile che usare XPath quando si lavora con XML. Il mio sito internet di riferimento è http://www.hookedonlinq.com/