get int value from XmlTextAttribute when deserialize xml to class in c# - c#

xml as below :
<Item>
<Winner>2</Winner>
</Item>
For my class definition I have the following:
public enum HomeOrAwayTeamType {Home =1,Away =2,Draw =3,NA = 0};
class Item
{
[XmlIgnore]
public virtual HomeOrAwayTeamType Winner { get; set; }
[XmlElement(ElementName = "Winner"), XmlText]
public virtual string WinnerSerializer
{
get { return this.Winner.ToString(); }
set
{
//get 'Away' from HomeOrAwayTeamType
this.Winner = (HomeOrAwayTeamType)2; //ok
this.Winner = (HomeOrAwayTeamType)Convert.ToInt32("2"); //ok
this.Winner = (HomeOrAwayTeamType)int.parse("2"); //ok
//get 'NA' from HomeOrAwayTeamType
this.Winner = (HomeOrAwayTeamType)Convert.ToInt32(value); //fail
this.Winner = (HomeOrAwayTeamType)int.parse(value); //fail
}
}
}
string xml = ""; //xml code
Item model = default(Item);
using (var reader = XmlReader.Create(new StringReader(xml)))
{
var serializer = new XmlSerializer(typeof(Item));
model = (Item)serializer.Deserialize(reader);
}
hi, guys..
How get int value from XmlTextAttribute?
Please help~

Your xml string is empty. This works for me:
string xml = "<Item><Winner>2</Winner></Item>"; //xml code
this.Winner gets set to Away

Related

By pass XmlElement serilization inside a Property with XmlText attribute

I have a class with a string property.
[Serializable]
public class Gather
{
[XmlAttribute("action")]
public string Action { get; set; }
[XmlAttribute("method")]
public string Method { get; set; }
[XmlAttribute("timeout")]
public string Timeout { get; set; }
[XmlAttribute("finishOnKey")]
public string FinishOnKey { get; set; }
[XmlElement]
public Say Say;
}
[Serializable]
public class Say
{
[XmlText]
public string Value;
}
I was doing xml serilization successfully from the following code then i got to know that inside Value property of Say class i need to pass plain xml some time
private string GetSpeechwithGatherXml(string value)
{
Say speechToText = new Say { Value = value };
Gather gather = new Gather
{
Action = txtCallback.Text,
Method = "Get",
Timeout = Convert.ToInt32(numericMaxTime.Value).ToString(),
FinishOnKey = "#",
Say = speechToText
};
GatherResponse response = new GatherResponse { Gather = gather };
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(response.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, response, emptyNamespaces);
return stream.ToString();
}
}
But xml tags are changing to < and > understandingly.
Any way I can by-pass this behavior in one propery (Value of Say class)
I wanted to send something like
<Response>
<Say>John’s phone number is, <say-as interpret-as="telephone">1234</say-as></Say>
</Response>
which is a valid xml

XML - Get Element Value - C#

I am trying to find if an element value exists then get a element value below it. i.e.
<Reply>
<customer id="1223">
<group>A</group>
<class>
<custclass>AB</custclass>
<custval>1</custval>
</class>
<class>
<custclass>CD</custclass>
<custval>2</custval>
</class>
</customer>
</Reply>
I need to get the custval element value if the custclass = "CD". What is the best way to set this into a string in C# "2"? So I am looking for if custclass element value of "CD" exists then return the custval element value of 2.
Thanks for any info.
We can read the property value using various ways-
Method 1 - using XmlDocument
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList xnl = doc.SelectNodes("/Reply/customer/class");
foreach (XmlNode node in xnl)
{
if (node.ChildNodes[0].InnerText == "CD")
{
Console.WriteLine(node.ChildNodes[1].InnerText);
}
}
Method 2 - using XDcoument and LINQ
XDocument xml = XDocument.Load(xmlFile);
var result = xml.Root.DescendantsAndSelf("class")
.Where(r => (string)r.Element("custclass").Value == "CD")
.Select(s=> (string)s.Element("custval").Value).Single();
Console.WriteLine(result);
Method 3 - using XDocument and XPathSelectElement
var custval = xml.XPathSelectElement("Reply/customer/class[custclass='CD']/custval").Value;
Console.WriteLine(custval);
Method 4 - using XmlSerializer
Create C# classes using xmltocsharp & use Deserialize to convert the xml to object
[XmlRoot(ElementName = "class")]
public class Class
{
[XmlElement(ElementName = "custclass")]
public string Custclass { get; set; }
[XmlElement(ElementName = "custval")]
public string Custval { get; set; }
}
[XmlRoot(ElementName = "customer")]
public class Customer
{
[XmlElement(ElementName = "group")]
public string Group { get; set; }
[XmlElement(ElementName = "class")]
public List<Class> Class { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "Reply")]
public class Reply
{
[XmlElement(ElementName = "customer")]
public Customer Customer { get; set; }
}
static async System.Threading.Tasks.Task Main(string[] args)
{
string xmlFile = #"xxxxxx.xml";
using (StreamReader r = new StreamReader(xmlFile))
{
string xmlString = r.ReadToEnd();
XmlSerializer ser = new XmlSerializer(typeof(Reply));
using (TextReader reader = new StringReader(xmlString))
{
var result = (Reply)ser.Deserialize(reader);
var custvalue = result.Customer.Class.Where(i => i.Custclass == "CD").Select(a => a.Custval).Single();
Console.WriteLine(custvalue);
}
}
}

LINQ2XML approach to generalize iteration through xml

I am trying to parse some xml files (using LINQ) to use that data to store in DB. Following is the format for one of the service, and there are dozens of them more, each with different node patterns and structure.
Is there a way to generalize this approach, so that I can iterate all these services through a single method/lines of code? without being bothered by how the childNodes are arranged ?
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<deviceState>
<id>203948-2908093-203984902-29348020-290lk</id>
<device>Mirron</device>
<variable>
<id>Plug - Meter.VI</id>
<text>
<textValue>
<value>0.000000</value>
</textValue>
</text>
</variable>
<variable>
<id>AEB</id>
<text>
<textStr>-</textStr>
</text>
</variable>
<variable>
<id>DESCRIPTION</id>
<text>
<textStr />
</text>
</variable>
<variable>
<id>VDTTM</id>
<text>
<textDate>
<date>01042016103658</date>
</textDate>
</text>
</variable>
<variable>
<id>STATUS</id>
<text>
<textValue>
<value>1.000000</value>
</textValue>
</text>
</variable>
</deviceState>
I want to achieve a functionality, where I can access values of every variable id by specifying a search filter and then access it's value directly, without being bothered by following meaningless tags.
<text><textValue> or <text><textDate> or <text><textStr/> or <text>
<textvalue><value>
something like, lets say new devices {a.id=node("id"), a.value=node("valu")}.
Currently I am using following code which does the trick but its not efficient, neither in speed, nor in manageability.
XDocument x = XDocument.Parse(_back);
string back = "";
string xvalue, yvalue;
foreach (XElement xe in x.Descendants().Take(1))
{
var s = xe.Value.IndexOf("Plug - Meter.VI");
var val = xe.Value.Substring(s, 25);
back= val.Substring(val.LastIndexOf("I")+1, 10);
break;
}
Any guidance will be highly appreciated. Thanks
Based on Monty's feedback, this is what I am using.
public protoDCM_CornerL08UMS_View()
{
InitializeComponent();
synchronizationContext = SynchronizationContext.Current;
StartingMeter();
}
private async void StartingMeter()
{
string val="0";
max = min = 0;
await Task.Run(() =>
{
do
{
UpdateUI(val,max,min);
val = fetchData();
Double temp =0;
if (Double.TryParse(val,out temp))
{
if(min==0&&max==0)
{
min = max = temp;
}
if(temp>max)
{
max = temp;
}
if(temp<min)
{
min = temp;
}
}
val = temp.ToString();
}
while (true);
});
}
private void UpdateUI(string value, Double _max , Double _min)
{
var timeNow = DateTime.Now;
if ((DateTime.Now - previousTime).Milliseconds <= 50) return;
synchronizationContext.Post(new SendOrPostCallback(o =>
{
lblInstant.Text= (string)o;
}), value);
synchronizationContext.Post(new SendOrPostCallback(o =>
{
lblMax.Text = (string)o;
}), _max.ToString());
synchronizationContext.Post(new SendOrPostCallback(o =>
{
lblMin.Text = (string)o;
}), _min.ToString());
previousTime = timeNow;
}
public Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
private string fetchData()
{
String _back = HttpGet("http://xxx.xxx.xxx"+Global.Node.Current.Device.Address+"/services/devices/deviceState.xml?id=D83AE139-E0C9-4B15-B2A9-6E0B57B28ED1?type=ALL");
//_back = FormatXML(Response);
try
{
DeviceState deserializedXML = new DeviceState();
XmlSerializer serializer = new XmlSerializer(typeof(DeviceState));
using (Stream stream = GenerateStreamFromString(_back))
{
deserializedXML = (DeviceState)serializer.Deserialize(stream);
var x = (from z in deserializedXML.Variable
where z.Id == "Plug - Meter.VI"
select new
{
Id = z.Id,
value= (z.Text.TextDate == null?
(z.Text.TextStr == null
? (z.Text.TextValue == null
? "No Text Value!" : z.Text.TextValue.Value.ToString()) : z.Text.TextStr.ToString()) : z.Text.TextDate.Date.ToString()) }).FirstOrDefault();
return x.value;
}
}
catch (Exception w)
{
MessageBox.Show(w.ToString());
return "0.0";
}
}
public static string HttpGet(string URI)
{
try
{
System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
req.Method = "GET";
System.Net.WebResponse resp = req.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
return sr.ReadToEnd().Trim();
}
catch (Exception sl)
{
return sl.ToString();
}
}
Try this....
Usings
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
Classes
[XmlRoot(ElementName = "textValue")]
public class TextValue
{
[XmlElement(ElementName = "value")]
public string Value { get; set; }
}
[XmlRoot(ElementName = "text")]
public class Text
{
[XmlElement(ElementName = "textValue")]
public TextValue TextValue { get; set; }
[XmlElement(ElementName = "textStr")]
public string TextStr { get; set; }
[XmlElement(ElementName = "textDate")]
public TextDate TextDate { get; set; }
}
[XmlRoot(ElementName = "variable")]
public class Variable
{
[XmlElement(ElementName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "text")]
public Text Text { get; set; }
}
[XmlRoot(ElementName = "textDate")]
public class TextDate
{
[XmlElement(ElementName = "date")]
public string Date { get; set; }
}
[XmlRoot(ElementName = "deviceState")]
public class DeviceState
{
[XmlElement(ElementName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "device")]
public string Device { get; set; }
[XmlElement(ElementName = "variable")]
public List<Variable> Variable { get; set; }
}
code
try
{
DeviceState deserializedXML = new DeviceState();
// Deserialize to object
XmlSerializer serializer = new XmlSerializer(typeof(DeviceState));
using (FileStream stream = File.OpenRead(#"xml.xml"))
{
deserializedXML = (DeviceState)serializer.Deserialize(stream);
// Now get all your IDs
List<string> IDs = (from xml in deserializedXML.Variable select xml.Id).ToList();
} // Put a break-point here, then mouse-over IDs and you will see all your IDs... deserializedXML contains the entire object if you want anythin else ....
}
catch (Exception)
{
throw;
}
I read your XML from a file (xml.xml) that is in the application *.exe folder, you will need to adapt this solution depending on your specific requirements....
Is this what you need?....
try
{
XmlSerializer DeserializerPlaces = new XmlSerializer(typeof(DeviceState));
string html = string.Empty;
string url = #"https://<Your URL>";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
//request.AutomaticDecompression = DecompressionMethods.GZip;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
DeviceState dezerializedXML = (DeviceState)DeserializerPlaces.Deserialize(reader);
//html = reader.ReadToEnd();
}
//Console.WriteLine(html);
}
catch (System.Exception)
{
throw;
}
You would call that every 5 seconds and update your UI (from dezerializedXML properties)

Problems deserializing List of objects

I am having trouble deserializing a list of objects. I can get just one object to serialize into an object but cannot get the list. I get no error it just returns an empty List. This is the XML that gets returned:
<locations>
<location locationtype="building" locationtypeid="1">
<id>1</id>
<name>Building Name</name>
<description>Description of Building</description>
</location>
</locations>
This is the class I have and I am deserializing in the GetAll method:
[Serializable()]
[XmlRoot("location")]
public class Building
{
private string method;
[XmlElement("id")]
public int LocationID { get; set; }
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("description")]
public string Description { get; set; }
[XmlElement("mubuildingid")]
public string MUBuildingID { get; set; }
public List<Building> GetAll()
{
var listBuildings = new List<Building>();
var building = new Building();
var request = WebRequest.Create(method) as HttpWebRequest;
var response = request.GetResponse() as HttpWebResponse;
var streamReader = new StreamReader(response.GetResponseStream());
TextReader reader = streamReader;
var serializer = new XmlSerializer(typeof(List<Building>),
new XmlRootAttribute() { ElementName = "locations" });
listBuildings = (List<Building>)serializer.Deserialize(reader);
return listBuildings;
}
}
Try this:
[XmlRoot("locations")]
public class BuildingList
{
public BuildingList() {Items = new List<Building>();}
[XmlElement("location")]
public List<Building> Items {get;set;}
}
Then deserialize the whole BuildingList object.
var xmlSerializer = new XmlSerializer(typeof(BuildingList));
var list = (BuildingList)xmlSerializer.Deserialize(xml);
I know this is an old(er) question, but I struggled with this today, and found an answer that doesn't require encapsulation.
Assumption 1: You have control over the source Xml and how it is constructed.
Assumption 2: You are trying to serialise the Xml directly into a List<T> object
You must name the Root element in the Xml as ArrayOfxxx where xxx is the name of your class (or the name specified in XmlType (see 2.))
If you wish your xml Elements to have a different name to the class, you should use XmlType on the class.
NB: If your Type name (or class name) starts with a lowercase letter, you should convert the first character to uppercase.
Example 1 - Without XmlType
class Program
{
static void Main(string[] args)
{
//String containing the xml array of items.
string xml =
#"<ArrayOfItem>
<Item>
<Name>John Doe</Name>
</Item>
<Item>
<Name>Martha Stewart</Name>
</Item>
</ArrayOfItem>";
List<Item> items = null;
using (var mem = new MemoryStream(Encoding.Default.GetBytes(xml)))
using (var stream = new StreamReader(mem))
{
var ser = new XmlSerializer(typeof(List<Item>)); //Deserialising to List<Item>
items = (List<Item>)ser.Deserialize(stream);
}
if (items != null)
{
items.ForEach(I => Console.WriteLine(I.Name));
}
else
Console.WriteLine("No Items Deserialised");
}
}
public class Item
{
public string Name { get; set; }
}
Example 2 - With XmlType
class Program
{
static void Main(string[] args)
{
//String containing the xml array of items.
//Note the Array Name, and the Title case on stq.
string xml =
#"<ArrayOfStq>
<stq>
<Name>John Doe</Name>
</stq>
<stq>
<Name>Martha Stewart</Name>
</stq>
</ArrayOfStq>";
List<Item> items = null;
using (var mem = new MemoryStream(Encoding.Default.GetBytes(xml)))
using (var stream = new StreamReader(mem))
{
var ser = new XmlSerializer(typeof(List<Item>)); //Deserialising to List<Item>
items = (List<Item>)ser.Deserialize(stream);
}
if (items != null)
{
items.ForEach(I => Console.WriteLine(I.Name));
}
else
Console.WriteLine("No Items Deserialised");
}
}
[XmlType("stq")]
public class Item
{
public string Name { get; set; }
}
Not sure how Building corresponds with the location you have in your xml, but to me it makes more sense if they're named equivalently. Instead of using a List use a LocationList, and it becomes:
[Serializable()]
[XmlRoot("locations")]
public class LocationCollection{
[XmlElement("location")]
public Location[] Locations {get;set;}
}
[Serializable()]
[XmlRoot("location")]
public class Location
{
[XmlElement("id")]
public int LocationID { get; set; }
[XmlAttribute("locationtype")]
public string LocationType {get;set;}
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("description")]
public string Description { get; set; }
[XmlElement("mubuildingid")]
public string MUBuildingID { get; set; }
}
You can then deserialize as follows:
var request = WebRequest.Create(method) as HttpWebRequest;
var response = request.GetResponse() as HttpWebResponse;
var streamReader = new StreamReader(response.GetResponseStream());
TextReader reader = streamReader;
var serializer = new XmlSerializer(typeof(LocationCollection),
new XmlRootAttribute() { ElementName = "locations" });
var listBuildings = (LocationCollection)serializer.Deserialize(reader);
return listBuildings;
I know, old question, but came across it when faced by a similar issue.
Building on #ricovox's answer and in context of the OP's question, this is the model I would use to serialize his xml:
[Serializable, XmlRoot("locations")]
public class BuildingList
{
[XmlArrayItem("location", typeof(Building))]
public List<Building> locations { get; set; }
}
[Serializable]
public class Building
{
public int LocationID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string MUBuildingID { get; set; }
public List<Building> GetAll()
{
...
}
}
The OP's mistake was to create the list item as the root
Use [XMLArray] for collection properties.

Deserialize a restful uri

I'm trying to deserialize a rest uri located at http://ws.geonames.org/countryInfo?lang=it&country=DE and keep getting error (There is an error in XML document (1, 1)). Plug http://ws.geonames.org/countryInfo?lang=it&country=DE into the browser and you can see the result.
I have a class
public class Country
{
public string CountryName {get;set;}
public string CountryCode {get;set;}
}
and the method in my console app is as follows:
static void DeserializeTheXML()
{
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "countryName";
xRoot.IsNullable = true;
XmlSerializer ser = new XmlSerializer(typeof(Country), xRoot);
XmlReader xRdr = XmlReader.Create(new StringReader("http://ws.geonames.org/countryInfo?lang=it&country=DE"));
Country tvd = new Country();
tvd = (Country)ser.Deserialize(xRdr);
Console.WriteLine("Country Name = " + tvd.CountryName);
Console.ReadKey();
}
any ideas on how to deserialize this rest service? thanks..
For serialization to work successfully you need to decorate your objects with the proper serialization attributes or use the XmlAttributeOverrides constructor. Also don't forget that XML is case sensitive and your objects must reflect the XML structure you are deserializing:
public class GeoNames
{
[XmlElement("country")]
public Country[] Countries { get; set; }
}
public class Country
{
[XmlElement("countryName")]
public string CountryName { get; set; }
[XmlElement("countryCode")]
public string CountryCode { get; set; }
}
class Program
{
static void Main()
{
var url = "http://ws.geonames.org/countryInfo?lang=it&country=DE";
var serializer = new XmlSerializer(typeof(GeoNames), new XmlRootAttribute("geonames"));
using (var client = new WebClient())
using (var stream = client.OpenRead(url))
{
var geoNames = (GeoNames)serializer.Deserialize(stream);
foreach (var country in geoNames.Countries)
{
Console.WriteLine(
"code: {0}, name: {1}",
country.CountryCode,
country.CountryName
);
}
}
}
}

Categories