我正在尝试从Google的地理编码API中解析一些信息,但是我有点麻烦地将数据从XML中获取。 请参阅链接

我真正关心的就是得到 short_nameaddress_component 类型在哪里 administrative_area_level_1long_nameadministrative_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。

当您在C#程序中使用XPATH时,您有两种不同的语言 - 但只有一种在控制中(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 致电一行,但我不喜欢在So上发布带有水平滚动条的代码。请注意,用与上面相同的凹痕编写正确的XPATH版本并避免滚动仍然很讨厌:

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

通常,在Visual Studio中,长线比在堆栈溢出上做得更好...

我建议仅将XPath表达式作为Visual Studio中XSLT文件的一部分键入. 。您将收到错误消息“当您输入时” - 这是一个出色的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#代码中.

这样可以确保我在运行C#程序时不会有XPATH-语法和语义 - 错误。

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

}

结果是枚举“ adversion_component” 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,因为它对于操纵和查询内存对象,查询数据库非常有用,并且比使用XML时使用XPath更容易。我最喜欢的参考网站是 http://www.hookedonlinq.com/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top