使用XDocument.Load

时间:2016-09-15 13:58:11

标签: c# xml linq linq-to-xml

我正在尝试使用XDocument.Load来访问一些纬度和经度数字。这是示例XML文档;

<?xml version="1.0" encoding="utf-8"?>
<Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1">
  <Copyright>Copyright © 2016 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.</Copyright>
  <BrandLogoUri>http://dev.virtualearth.net/Branding/logo_powered_by.png</BrandLogoUri>
  <StatusCode>200</StatusCode>
  <StatusDescription>OK</StatusDescription>
  <AuthenticationResultCode>ValidCredentials</AuthenticationResultCode>
  <TraceId>31a206847f9341d28689e0e7185e163d|DB40051719|7.7.0.0|DB4SCH010061262</TraceId>
  <ResourceSets>
    <ResourceSet>
      <EstimatedTotal>1</EstimatedTotal>
      <Resources>
        <Location>
          <Name>SW1A 1AA, London, London, United Kingdom</Name>
          <Point>
            <Latitude>51.501018524169922</Latitude>
            <Longitude>-0.14159967005252838</Longitude>
          </Point>
          <BoundingBox>
            <SouthLatitude>51.497155806599245</SouthLatitude>
            <WestLongitude>-0.14987251765942367</WestLongitude>
            <NorthLatitude>51.5048812417406</NorthLatitude>
            <EastLongitude>-0.1333268224456331</EastLongitude>
          </BoundingBox>
          <EntityType>Postcode1</EntityType>
          <Address>
            <AdminDistrict>England</AdminDistrict>
            <AdminDistrict2>London</AdminDistrict2>
            <CountryRegion>United Kingdom</CountryRegion>
            <FormattedAddress>SW1A 1AA, London, London, United Kingdom</FormattedAddress>
            <Locality>London</Locality>
            <PostalCode>SW1A 1AA</PostalCode>
          </Address>
          <Confidence>High</Confidence>
          <MatchCode>Good</MatchCode>
          <GeocodePoint>
            <Latitude>51.501018524169922</Latitude>
            <Longitude>-0.14159967005252838</Longitude>
            <CalculationMethod>Rooftop</CalculationMethod>
            <UsageType>Display</UsageType>
          </GeocodePoint>
        </Location>
      </Resources>
    </ResourceSet>
  </ResourceSets>
</Response>

以下是我尝试访问纬度和经度的代码;

    string latitude = XDocument.Load(@"test.xml").Root
                                            .Descendants("ResourceSets")
                                            .Descendants("ResourceSet")
                                            .Descendants("Resources")
                                            .Descendants("Location")
                                            .Descendants("GeocodePoint")
                                            .Select(element => element.Attribute("Latitude").Value).FirstOrDefault();

但是这会返回一个空字符串。如何正确浏览文档?

2 个答案:

答案 0 :(得分:1)

如果要获取所有Descendants节点,首先不需要调用多级GeocodePoint方法。你只能这样做:

XNamespace ns =  "http://schemas.microsoft.com/search/local/ws/rest/v1";
string latitude = XDocument.Load(@"test.xml")
                  .Descendants(ns+"GeocodePoint")
                  .Select(e=> (string)e.Element(ns+"Latitude"))
                  .FirstOrDefault();

通过该调用,Linq to XML将检索xml中的所有GeocodePoints

如果你想获得lat和long值,那么你可以投射到匿名类型或自定义类(DTO),如下所示:

XNamespace ns =  "http://schemas.microsoft.com/search/local/ws/rest/v1";

var coord= XDocument.Load(@"xml.xml")
          .Descendants(ns+"GeocodePoint").Select(e => new { Lat = (string)e.Element(ns+"Latitude"), Lng = (string)e.Element(ns+"Longitude") })
          .FirstOrDefault();

关于您的问题

您的问题是您正在调用Attribute方法来获取Latitude值,但正如您在xml结构中看到的那样GeocodePoint节点没有将其作为属性,是一个嵌套元素。这就是你需要使用Element方法的方法。第二个问题是你需要考虑名称空间,如上所示。

答案 1 :(得分:1)

您没有使用命名空间。您的Xml提供了命名空间

<Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1">

所以你需要在搜索元素时使用它。

XDocument doc = XDocument.Load(@"C:\tmp\data.xml");

XNamespace ns = doc.Root.Name.Namespace;
string value = doc.Root.Descendants(ns + "Latitude").FirstOrDefault().Value; 

或者在没有名称空间的情况下搜索元素<{1}}

LocalName

如果您使用string value = doc.Root .Descendants .Where(element => element.Name.LocalName.Equals("Latitude")) .FirstOrDefault() .Value; 方法,则可以直接搜索所需的元素。