简体   繁体   中英

accessing descendant elements from an xml returned null using linq to xml in c#

Please people help me out I need to consume a web service that returns an xml from my application, The code that downloads xml works fine, but I need to extract values from the xml file, but I keep getting a null return value from the code, precisely the GetLocationFromXml() method is the method returning null, the GetLocationAsXMLFromHost() method works fine.

this is the complete class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AMIS.Core.DTOs;
using System.Net;
using System.Xml.Linq;
using System.Xml;
using System.Linq;

public class GeoLocationService
{
   private string _hostWebSite = "http://api.hostip.info";
    private readonly XNamespace _hostNameSpace = "http://www.hostip.info/api";
    private readonly XNamespace _hostGmlNameSpace = "http://www.opengis.net/gml";

public LocationInfo GetLocationInfoFromIPAddress(string userHostIpAddress)
{
    IPAddress ipAddress = null;
    IPAddress.TryParse(userHostIpAddress, out ipAddress);
    string xmlData = GetLocationAsXMLFromHost(ipAddress.ToString());
    LocationInfo locationInfo = GetLocationFromXml(xmlData);
    return locationInfo;
}

private string GetLocationAsXMLFromHost(string userHostIpAddress)
{
    WebClient webClient= new WebClient();
    string formattedUrl = string.Format(_hostWebSite + "/?ip={0}", userHostIpAddress);
    var xmlData = webClient.DownloadString(formattedUrl);
    return xmlData;
}

private LocationInfo GetLocationFromXml(string xmlData)
{
    LocationInfo locationInfo = new LocationInfo();
    var xmlResponse = XDocument.Parse(xmlData);
    var nameSpace = (XNamespace)_hostNameSpace;
    var gmlNameSpace = (XNamespace)_hostGmlNameSpace;

    try
    {
        locationInfo = (from x in xmlResponse.Descendants(nameSpace + "Hostip")
                        select new LocationInfo
                        {
                            CountryName = x.Element(nameSpace + "countryName").Value,
                            CountryAbbreviation = x.Element(nameSpace + "countryAbbrev").Value,
                            LocationInCountry = x.Element(gmlNameSpace + "name").Value
                        }).SingleOrDefault();
    }
    catch (Exception)
    {
        throw;
    }
    return locationInfo;
}
}

and the xml file is below

<?xml version="1.0" encoding="iso-8859-1"?>
<HostipLookupResultSet version="1.0.1" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:noNamespaceSchemaLocation="http://www.hostip.info/api/hostip-1.0.1.xsd">
<gml:description>This is the Hostip Lookup Service</gml:description>
<gml:name>hostip</gml:name>
<gml:boundedBy>
<gml:Null>inapplicable</gml:Null>
</gml:boundedBy>
<gml:featureMember>
<Hostip>
  <ip>41.78.8.3</ip>
  <gml:name>(Unknown city)</gml:name>
  <countryName>NIGERIA</countryName>
  <countryAbbrev>NG</countryAbbrev>
  <!-- Co-ordinates are unavailable -->
  </Hostip>
</gml:featureMember>
</HostipLookupResultSet>

Given the comments, I suspect the problem may be as simple as:

private string _hostNameSpace = "hostip.info/api";

should be:

private string _hostNameSpace = "http://hostip.info/api";

(Ditto for the others.) Personally I'd make then XNamespace values to start with:

private static readonly XNamespace HostNameSpace = "http://hostip.info/api";

EDIT: Okay, after messing around with your example (which could have been a lot shorter and a lot more complete) I've worked out what's wrong: you're looking for elements using the "host namespace" - but the elements in the XML aren't in any namespace. Just get rid of those namespace bits, and it works fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM