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?

È stato utile?

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:

http://www.bit-101.com/xpath/

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/

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top