Pregunta

Estoy tratando de analizar algunos datos del API de codificación geográfica de Google pero estoy teniendo un pequeño problema con conseguir de manera eficiente los datos del xml. Ver enlace por ejemplo

Todo lo que realmente importa es conseguir que el short_name de address_component donde el tipo es administrative_area_level_1 y la long_name de administrative_area_level_2 Sin embargo, con mi programa de prueba de mi consulta XPath devuelve ningún resultado para ambas consultas.

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

        }
    }
}

Puede alguien ayudarme a encontrar lo que estoy haciendo mal, o recomendar una mejor manera?

¿Fue útil?

Solución

Es necesario poner el valor del nodo que busca entre comillas:

".../address_component[type='administrative_area_level_1']/short_name"
                            ↑                           ↑

Otros consejos

Sin duda recomiendo el uso de LINQ to XML en lugar de XPathNavigator. Hace que la consulta XML una brisa, en mi experiencia. En este caso no estoy seguro exactamente lo que está mal ... pero voy a llegar a un fragmento de código XML LINQ a su lugar.

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());
        }
    }
}

Ahora bien, este es más código 1 ... pero yo personalmente encuentro más fácil conseguir la derecha de XPath, porque el compilador me está ayudando mucho más.

EDIT: me siento que vale la pena entrar en detalles un poco más acerca de por qué general prefiero código como este sobre el uso de XPath, aunque es evidente que ya

.

Cuando se utiliza XPath dentro de un programa en C #, tiene dos idiomas diferentes - pero sólo uno tiene el control (C #). XPath es relegada a la esfera de cuerdas: Visual Studio no da una expresión XPath ningún manejo especial; no hace entender que está destinado a ser una expresión XPath, por lo que no puede ayudarle. No es que Visual Studio no sabe nada de XPath; como señala Dimitre, es perfectamente capaz de detectar errores si está editando un archivo XSLT, pero no es un archivo de C #.

Este es el caso cada vez que tenga un idioma incrustado dentro de otro y la herramienta no es consciente de ello. Los ejemplos más comunes son:

  • SQL
  • Las expresiones regulares
  • HTML
  • XPath

Cuando el código se presenta como datos dentro de otro idioma, el idioma secundario pierde una gran cantidad de sus beneficios de herramientas.

Mientras que puede cambio de contexto por todo el lugar, sacando el XPath (o SQL o expresiones regulares, etc.) en sus propias herramientas (posiblemente dentro del mismo programa en sí, sino en un archivo separado o ventana) encuentro esto lo convierte en código más difícil de leer en el largo plazo. Si el código se sólo ha escrito y nunca leyó después, que podría estar bien -. Pero DO necesidad de ser capaz de leer el código después, y personalmente creo que la sufre de legibilidad cuando esto sucede

El LINQ a la versión XML anterior solamente siempre utiliza cadenas de datos puros - los nombres de los elementos, etc - y el código de usos (las llamadas a métodos) para representar acciones como "encontrar elementos con un nombre dado" o "aplicar este filtro". Eso es más idiomático código C #, en mi opinión.

Es evidente que otros no comparten este punto de vista, pero pensé que vale la expansión de mostrar dónde vengo.

Tenga en cuenta que esto no es un regla , por supuesto ... en algunos casos XPath, etc expresiones regulares son la mejor solución fuerte y rápido. En este caso, preferiría el LINQ to XML, eso es todo.


1 Por supuesto que podría han mantenido cada llamada Console.WriteLine en una sola línea, pero no me gusta código de mensaje con barras de desplazamiento horizontal en SO. Nota que la escritura de la versión de XPath correcta con el mismo sangrado que el anterior y evitar el desplazamiento sigue siendo bastante desagradable:

            Console.WriteLine(nav.SelectSingleNode("/GeocodeResponse/result/" +
                "address_component[type='administrative_area_level_1']" +
                "/short_name").InnerXml);

En general, las líneas largas funcionan mucho mejor en Visual Studio que lo hacen en desbordamiento de pila ...

lo recomiendo solo teclear la expresión XPath como parte de un archivo XSLT en Visual Studio . Usted obtendrá mensajes de error "mientras escribe" - esta es una excelente / XSLT / XPath editor XML

.

Por ejemplo, estoy escribiendo:

<xsl:apply-templates select="@* | node() x"/>

e inmediatamente entrar en la ventana Lista de errores el siguiente error

Error   9   Expected end of the expression, found 'x'.  @* | node()  -->x<--

XSLTFile1.xslt  9   14  Miscellaneous Files

Sólo cuando la expresión XPath no plantea ningún error (que puede ser que también prueba que selecciona los nodos destinados, también), voy a poner esta expresión en mi código C # .

Esto asegura que no tendrá ningún XPath - sintaxis y semántica -. Errores al ejecutar el programa de C #

La respuesta de DTB es exacta. Quería añadir que se puede utilizar XPath prueba de herramientas como el enlace de abajo para ayudar a encontrar el XPath correcta:

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

}

El resultado es una enumeración de "s" address_component que tienen al menos un nodo "tipo" que tiene contiene el valor que está buscando. El resultado de la consulta anterior es un XElement que contiene los datos siguientes.

<address_component>
  <long_name>California</long_name>
  <short_name>CA</short_name>
  <type>administrative_area_level_1</type>
  <type>political</type>
</address_component> 

Realmente recomendaría pasar un poco de tiempo en aprender LINQ, en general, porque es muy útil para manipular y consulta de objetos en memoria, la consulta de bases de datos y tiende a ser más fácil que usar XPath cuando se trabaja con XML. Mi sitio favorito de referencia es http://www.hookedonlinq.com/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top