【问题标题】:Loading Descendants of XML using XDocument.Load使用 XDocument.Load 加载 XML 的后代
【发布时间】:2016-09-15 13:58:11
【问题描述】:

我正在尝试使用 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();

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

【问题讨论】:

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


    【解决方案1】:

    如果您想获取所有GeocodePoint 节点,则不需要在多个级别调用Descendants 方法。你只能这样做:

    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 方法的方式。第二个问题是您需要将命名空间考虑在内,如上所示。

    【讨论】:

    • 感谢您的宝贵时间和帮助。不幸的是,这仍然返回两个空字符串给我。
    • 是的,我注意到你现在使用的是Attribute 方法,你应该改用Element
    • 不幸的是,当我调用这些方法时仍然是空字符串。
    • 是的,经过测试,我发现您需要在查询中包含命名空间。
    • 不错的复制人:)
    【解决方案2】:

    您没有使用命名空间。您的 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; 
    

    或不使用命名空间,按元素的LocalName 进行搜索

    string value = doc.Root
                      .Descendants
                      .Where(element => element.Name.LocalName.Equals("Latitude"))
                      .FirstOrDefault()
                      .Value;
    

    如果你使用Descendats方法,那么你可以直接搜索你需要的元素。

    【讨论】:

      猜你喜欢
      • 2011-03-02
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-23
      相关资源
      最近更新 更多