2011-02-11 18 views
5

que necesita para obtener el CountryName de este XML: http://api.hostip.info/?ip=12.215.42.19Cómo obtener un elemento que tiene: ¿en su nombre?

La respuesta XML es:

<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>12.215.42.19</ip> 
     <gml:name>Sugar Grove, IL</gml:name> 
     <countryName>UNITED STATES</countryName> 
     <countryAbbrev>US</countryAbbrev> 
     <!-- Co-ordinates are available as lng,lat --> 
     <ipLocation> 
     <gml:pointProperty> 
      <gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 

      <gml:coordinates>-88.4588,41.7696</gml:coordinates> 
      </gml:Point> 
     </gml:pointProperty> 
     </ipLocation> 
    </Hostip> 
    </gml:featureMember> 
</HostipLookupResultSet> 

El problema es que no puedo incluir : en el método Descendants porque arroja:

XmlException: El ':' chracater, valor hexadecimal 0x3A, no puede ser incluido en un nombre.

Gracias

+0

por cierto su título y pregunta no coinciden. en realidad no necesitas el elemento con: en el nombre. que sesgó sus respuestas hacia las soluciones de espacio de nombres –

Respuesta

5

probar esto

var descendants = from i in XDocument.Load(xml).Descendants("Hostip") 
select i.Element("countryName"); 

actualización

código completo para descargar el xml y encontrar el nombre de countryName

string xml; 
using(var web = new WebClient()) 
{ 
xml = web.DownloadString("http://api.hostip.info/?ip=12.215.42.19"); 
} 
var descendants = from i in XDocument.Parse(xml).Descendants("Hostip") 
select i.Element("countryName"); 
+0

Se me ocurrió una solución más grande en la que tuve que hacer referencia a los espacios de nombres, pero la tuya es más simple y no necesita hacer referencia a las ns. Gracias – emzero

+0

XDocument.Load() tomará una URL, descárguelo y analícelo guardando un par de líneas. –

+0

¡Me alegro de que haya sido útil! –

1

Es necesario hacer referencia al espacio de nombres GML; Una vez que hayas hecho esto usted debe ser capaz de navegar utilizando los nombres de las etiquetas que aparecen a la derecha de "GML:"

ACTUALIZACIÓN

No estoy seguro de qué contexto va a aplicar a este , pero aquí es una aplicación de consola de ejemplo que funciona:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml.Linq; 

namespace LinqToXmlSample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      XElement x = XElement.Load("http://api.hostip.info/?ip=12.215.42.19"); 
      foreach (XElement hostip in x.Descendants("Hostip")) 
      { 
       string country = Convert.ToString(hostip.Element("countryName").Value); 
       Console.WriteLine(country); 
      } 
      Console.ReadLine(); 
     } 
    } 
} 
+0

¿Y cómo lo hago referencia? – emzero

3

Un pequeño ejemplo de cómo aplicar los espacios de nombres en LINQ para XML:

XElement doc = XElement.Load("test.xml"); 
XNamespace ns = "http://www.opengis.net/gml"; 

var firstName = doc.Descendants(ns + "name").First().Value; 
+0

Realmente no necesitaba atravesar los elementos de "espacio de nombres" en mi problema. Pero +1 para el registro de cómo aplicar espacios de nombres en LINQ a XML =) – emzero

0
var gml = (XNamespace)"http://www.opengis.net/gml"; 
var doc = XDocument.Load(...) or XDocument.Parse(...); 
var name = doc.Descendants(gml + "featureMember").Descendants("countryName").First().Value; 

o podría ir fuerza bruta y quitar todos los espacios de nombres:

void RemoveNamespace(XDocument xdoc) 
{ 
    foreach (XElement e in xdoc.Root.DescendantsAndSelf()) 
    { 
     if (e.Name.Namespace != XNamespace.None) 
     { 
      e.Name = XNamespace.None.GetName(e.Name.LocalName); 
     } 

     if (e.Attributes().Any(a => a.IsNamespaceDeclaration || a.Name.Namespace != XNamespace.None)) 
     { 
      e.ReplaceAttributes(e.Attributes().Select(a => a.IsNamespaceDeclaration ? null : a.Name.Namespace != XNamespace.None ? new XAttribute(XNamespace.None.GetName(a.Name.LocalName), a.Value) : a)); 
     } 
    } 
} 
+0

Lo hice desde la memoria, puede haber errores –

+0

Tienes razón. No hay constructor para un 'XNamespace'. Use 'XNamespace.Get()' o copie la cadena a uno. ;) –

+0

gracias ... actualizaré –

Cuestiones relacionadas