Вопрос

Я пытаюсь проанализировать некоторую информацию из Google Geoocoding API, но у меня есть небольшие проблемы с эффективным выводом данных из XML. См. Например, ссылка

Все, что меня действительно волнует, это получение short_name от address_component где тип administrative_area_level_1 и long_name от administrative_area_level_2Однако с моей тестовой программой мой запрос XPath не возвращает результатов для обоих запросов.

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

        }
    }
}

Может ли кто -нибудь помочь мне найти то, что я делаю не так, или рекомендую лучше?

Это было полезно?

Решение

Вам нужно поместить значение узела, который вы ищете в кавычках:

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

Другие советы

Я определенно рекомендую использовать LINQ для XML вместо Xpathnavigator. По моему опыту, это заставляет XML -запрос на ветерок. В этом случае я не уверен, что именно не так ... но вместо этого я приду к фрагменту LINQ в XML.

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

Сейчас является больше кода1... но лично мне легче получить правильно, чем XPath, потому что компилятор помогает мне больше.

РЕДАКТИРОВАТЬ: Я чувствую, что стоит узнать немного больше о том, почему я в целом Предпочитайте такой код, как это, используя XPath, хотя он явно дольше.

Когда вы используете XPath в программе C#, у вас есть два разных языка, но только один находится в контроле (C#). XPath переживается в сферу строк: Visual Studio не дает выражению XPath какую -либо специальную обработку; это не так понимать что это должно быть выражением XPath, так что это не может вам помочь. Дело не в том, что Visual Studio не знает о XPath; Как указывает Dimitre, он вполне способен обнаружить ошибки, если вы редактируете файл XSLT, просто не файл C#.

Это тот случай, когда у вас есть один язык, встроенный в другой, и инструмент не знает об этом. Общие примеры:

  • SQL
  • Обычные выражения
  • HTML
  • Xpath

Когда код представлен как данные на другом языке, вторичный язык теряет много своих преимуществ инструмента.

Пока ты могу Контекст переключатель повсюду, вытягивая XPath (или SQL, или регулярные выражения и т. Д.) В свой собственный инструмент (возможно, в рамках той же фактической программы, но в отдельном файле или окне) я считаю, что это делает более труднее для чтения код в долгосрочной перспективе. Если код был написан только когда -либо и никогда не читал потом, это может быть хорошо - но вы делать Нужно иметь возможность читать код впоследствии, и я лично верю, что читаемость страдает, когда это происходит.

Версия LINQ -XML выше используется только строки для чистых данных - имена элементов и т. Д. - и использует код (методы вызовы) для представления таких действий, как «Найдите элементы с данным именем» или «применить этот фильтр». Это более идиоматический код C#, по моему мнению.

Очевидно, что другие не разделяют эту точку зрения, но я подумал, что стоит расширить, чтобы показать, откуда я.

Обратите внимание, что это не сложно и быстро правило Конечно ... в некоторых случаях XPATH, регулярные выражения и т. Д. - лучшее решение. В этом случае я бы предпочел LINQ XML, вот и все.


1 Конечно я мог сохранили каждый Console.WriteLine Позвоните в одну строку, но я не люблю публиковать код с горизонтальными полосами свитки. Обратите внимание, что написание правильной версии xPath с тем же углублением, что и вышеупомянутое, и избегать прокрутки все еще довольно неприятно:

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

В целом, длинные линии работают намного лучше в Visual Studio, чем на переполнении стека ...

Я бы порекомендовал просто ввести выражение XPath как часть файла XSLT в Visual Studio. Отказ Вы получите сообщения об ошибках «при печати» - это отличный редактор XML/XSLT/XPath.

Например, я печатаю:

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

и немедленно попасть в окно списка ошибок следующей ошибкой:

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

XSLTFile1.xslt  9   14  Miscellaneous Files

Только когда выражение xPath не выражает никаких ошибок (я также могу проверить, что оно выбирает также намеченные узлы), я бы вложил это выражение в свой код C#.

Это гарантирует, что у меня не будет XPath - Syntax и Semantic - ошибки, когда я запускаю программу C#.

Ответ DTB является точным. Я хотел добавить, что вы можете использовать инструменты тестирования XPath, такие как ссылка ниже, чтобы помочь найти правильный XPath:

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

}

Результатом является перечисление «ADDRED_CONONTEN» S, у которого есть хотя бы один узел типа «типа», который содержит значение, которое вы ищете. Результатом приведенного выше запроса является Xelement, который содержит следующие данные.

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

Я бы действительно рекомендовал потратить немного времени на изучение LINQ в целом, потому что он очень полезен для манипулирования и запроса объектов в памяти, запроса баз данных и, как правило, проще, чем использование XPath при работе с XML. Мой любимый сайт для ссылки http://www.hookedonlinq.com/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top