I am having a bad time trying to consume an XML service.
This is my code to consume the service (it is a public service so you can consume it):
using( var client = new HttpClient() )
{
client.DefaultRequestHeaders
.Accept
.Add( new MediaTypeWithQualityHeaderValue( "text/xml" ) );
var request = new HttpRequestMessage( HttpMethod.Get, "https://gee.bccr.fi.cr/Indicadores/Suscripciones/WS/wsindicadoreseconomicos.asmx/ObtenerIndicadoresEconomicosXML?Indicador=317&FechaInicio=20/04/2022&FechaFinal=20/04/2022&Nombre=José Miguel Torres Gómez&SubNiveles=N&[email protected]&Token=2LOEU2EM8O" );
var returnedXml = client.SendAsync( request ).Result.Content.ReadAsStringAsync().Result;
Console.WriteLine( returnedXml );
}
The response I get from there is the following, adding the console screenshot due to it returns special scape chars:
<string xmlns="http://ws.sdde.bccr.fi.cr">
<Datos_de_INGC011_CAT_INDICADORECONOMIC>
<INGC011_CAT_INDICADORECONOMIC>
<COD_INDICADORINTERNO>317</COD_INDICADORINTERNO>
<DES_FECHA>2022-04-20T00:00:00-06:00</DES_FECHA>
<NUM_VALOR>650.10000000</NUM_VALOR>
</INGC011_CAT_INDICADORECONOMIC>
</Datos_de_INGC011_CAT_INDICADORECONOMIC>
</string>
This is the class I use to try to deserialize:
public class Datos_de_INGC011_CAT_INDICADORECONOMIC
{
public INGC011_CAT_INDICADORECONOMIC INGC011_CAT_INDICADORECONOMIC { get; set; }
}
public class INGC011_CAT_INDICADORECONOMIC
{
public int COD_INDICADORINTERNO { get; set; }
public DateTime DES_FECHA { get; set; }
public double NUM_VALOR { get; set; }
}
But when I try to Deserialize the string I get the error: There is an error in XML document. Data at the root level is invalid. And due to I don't use to work with XML data I am stocked here.
CodePudding user response:
Looks like the problem you are having is because of the outer element you have in your xml (string)
You can use one of the ways mentioned
CodePudding user response:
The problem is that the "outer" XML is a wrapper for the "inner" one, which is encoded as text node for the first. In other words, that's NOT a single document, rather two different documents nested.
My guess is about the outer one, which looks like a descriptor for what itself contains.
That being said, you can extract what you need in a two-step job:
using System;
using System.Xml.Linq;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using( var client = new HttpClient() )
{
client.DefaultRequestHeaders
.Accept
.Add( new MediaTypeWithQualityHeaderValue( "text/xml" ) );
var request = new HttpRequestMessage( HttpMethod.Get, " ... " );
var returnedXml = client.SendAsync( request ).Result.Content.ReadAsStringAsync().Result;
Console.WriteLine( returnedXml );
//create a XML DOM from the returned payload
XDocument xdoc_outer = XDocument.Parse(returnedXml );
//extract the inner document as text (being a true-text node)
string inner_text = (string)xdoc_outer.Root;
//deserialize the text straight to a POCO shaped accordingly
var serializer = new XmlSerializer(typeof(Datos_de_INGC011_CAT_INDICADORECONOMIC));
using (var reader = XmlReader.Create(new StringReader(inner_text)))
{
//'result' contains the deserialized POCO, unless something went wrong!
var result = (Datos_de_INGC011_CAT_INDICADORECONOMIC)serializer.Deserialize(reader);
}
}
Probably there are better yet compact ways to achieve the same result, but I think that's pretty clear.
As final note, I reccomend to use async
/await
than accessing the data through the Result
property.