Paste text from EditText to xml string - c#

I have EditText field and WebClient.
In EditText user write city.
EditText misto = FindViewById<EditText>(Resource.Id.misto) ;
TextView one = FindViewById<TextView>(Resource.Id.parentContainer);
TextView two = FindViewById<TextView>(Resource.Id.clicklistener1);
TextView three = FindViewById<TextView>(Resource.Id.clicklistener2);
TextView four = FindViewById<TextView>(Resource.Id.clicklistener3);
misto.TextChanged += (object sender, Android.Text.TextChangedEventArgs e) => {
var city = e.Text.ToString ();
};
I need to place text from EditText to xml string.
Code of POST request with xml
nadislati.Click += delegate
{
using (var client = new WebClient())
{
var values = new NameValueCollection();
values["Order"] = "<Order \n CallConfirm=\"1\"\n PayMethod=\"Безнал\" \n QtyPerson=\"2\" \n Type=\"2\" \n PayStateID=\"0\" \n Remark=\"тестовый заказ с мобильного приложения. просьба при получении заказа переслать скриншот на имейл ....#\" \n RemarkMoney=\"0\" \n TimePlan=\"\" \n Brand=\"1\" \n DiscountPercent=\"0\" \n BonusAmount=\"0\"\n Department=\"\"\n >\n <Customer Login=\"suhomlineugene#gmail.com\" FIO=\"Evgenyi Sukhomlin\"/>\n <Address \n CityName=\"\" \n StationName=\"\" \n StreetName=\"\" \n House=\"\" \n Corpus=\"\" \n Building=\"\" \n Flat=\"\" \n Porch=\"\" \n Floor=\"\" \n DoorCode=\"\"\n />\n\n <Phone Code=\" 096\" Number=\"50 526-43-19\" />\n <Products>\n <Product Code=\"574\" Qty=\"1\" />\n </Products>\n </Order>";
values["OrderText"] = "hello";
var response = client.UploadValues("http://193.203.48.54:5000/fastoperator.asmx/AddOrder", values);
var responseString = Encoding.UTF8.GetString(response);
}
Vibrator vib = (Vibrator)this.GetSystemService(Context.VibratorService);
vib.Vibrate(30);
var intent31 = new Intent(this, typeof(Cart3Activity));
StartActivity(intent31);
};
How I can realize this?

Normally you would have a data contract (a set of classes which represent the XML). You then populate this data contract with values. When you are done and want to send it as XML to the server, you take that object and serialize it into XML or JSON or whatever format the service requires. Taking the XML you have shown in the Order and throwing it through a XML 2 C# generator you get this:
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace Xml2CSharp
{
[XmlRoot(ElementName="Customer")]
public class Customer {
[XmlAttribute(AttributeName="Login")]
public string Login { get; set; }
[XmlAttribute(AttributeName="FIO")]
public string FIO { get; set; }
}
[XmlRoot(ElementName="Address")]
public class Address {
[XmlAttribute(AttributeName="CityName")]
public string CityName { get; set; }
[XmlAttribute(AttributeName="StationName")]
public string StationName { get; set; }
[XmlAttribute(AttributeName="StreetName")]
public string StreetName { get; set; }
[XmlAttribute(AttributeName="House")]
public string House { get; set; }
[XmlAttribute(AttributeName="Corpus")]
public string Corpus { get; set; }
[XmlAttribute(AttributeName="Building")]
public string Building { get; set; }
[XmlAttribute(AttributeName="Flat")]
public string Flat { get; set; }
[XmlAttribute(AttributeName="Porch")]
public string Porch { get; set; }
[XmlAttribute(AttributeName="Floor")]
public string Floor { get; set; }
[XmlAttribute(AttributeName="DoorCode")]
public string DoorCode { get; set; }
}
[XmlRoot(ElementName="Phone")]
public class Phone {
[XmlAttribute(AttributeName="Code")]
public string Code { get; set; }
[XmlAttribute(AttributeName="Number")]
public string Number { get; set; }
}
[XmlRoot(ElementName="Product")]
public class Product {
[XmlAttribute(AttributeName="Code")]
public string Code { get; set; }
[XmlAttribute(AttributeName="Qty")]
public string Qty { get; set; }
}
[XmlRoot(ElementName="Products")]
public class Products {
[XmlElement(ElementName="Product")]
public Product Product { get; set; }
}
[XmlRoot(ElementName="Order")]
public class Order {
[XmlElement(ElementName="Customer")]
public Customer Customer { get; set; }
[XmlElement(ElementName="Address")]
public Address Address { get; set; }
[XmlElement(ElementName="Phone")]
public Phone Phone { get; set; }
[XmlElement(ElementName="Products")]
public Products Products { get; set; }
[XmlAttribute(AttributeName="CallConfirm")]
public string CallConfirm { get; set; }
[XmlAttribute(AttributeName="PayMethod")]
public string PayMethod { get; set; }
[XmlAttribute(AttributeName="QtyPerson")]
public string QtyPerson { get; set; }
[XmlAttribute(AttributeName="Type")]
public string Type { get; set; }
[XmlAttribute(AttributeName="PayStateID")]
public string PayStateID { get; set; }
[XmlAttribute(AttributeName="Remark")]
public string Remark { get; set; }
[XmlAttribute(AttributeName="RemarkMoney")]
public string RemarkMoney { get; set; }
[XmlAttribute(AttributeName="TimePlan")]
public string TimePlan { get; set; }
[XmlAttribute(AttributeName="Brand")]
public string Brand { get; set; }
[XmlAttribute(AttributeName="DiscountPercent")]
public string DiscountPercent { get; set; }
[XmlAttribute(AttributeName="BonusAmount")]
public string BonusAmount { get; set; }
[XmlAttribute(AttributeName="Department")]
public string Department { get; set; }
}
}
You probably need to fix some of the types on some of the properties as the generator is not super clever about this.
Anyways, populate those properties with your values and when you want to create XML from it:
public static string SerializeObject<T>(this T toSerialize)
{
var xmlSerializer = new XmlSerializer(toSerialize.GetType());
using(var textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, toSerialize);
return textWriter.ToString();
}
}
var myXml = SerializeObject<Order>(order);
Where order is an instance of Order. myXml will be your XML string you can pass on to the server.
EDIT
Since you already have that XML string, you will need to deserialize it into the object, so you can manipulate it:
public static T DeserializeObject<T>(string xml)
{
using (var ms = new MemoryStream())
using (var writer = new StreamWriter(ms))
{
writer.Write(xml);
ms.Position = 0;
var serializer = new XmlSerializer(typeof(T));
using (var reader = XmlReader.Create(ms))
return (T)serializer.Deserialize(reader);
}
}
var order = DeserializeObject<Order>(xmlOrder);
Then you can manipulate order and when you are done, convert it back to XML with:
var myXml = SerializeObject<Order>(order);
You have to make sure your XML is well formed when you use these methods.

Related

Deserialize XML classes to one class for writing to database

I am trying to deserialize XML and save the results to a database using entity framework.
The first section of code is just to get the needed xml file from an API.
Please see below:
public static void Main()
{
Program semoAPI = new Program();
using (WebClient webClient = new WebClient())
{
WebClient n = new WebClient();
//Bid Ask Curves
var bidAskCurves = n.DownloadString("https://reports.semopx.com/api/v1/documents/static-reports?" +
"page=1&page_size=1&order_by=ASC&ReportName=Bid/Ask%20Curves&Group=Market%20Data");
semoReports = JsonConvert.DeserializeObject<SemoReports>(bidAskCurves);
Console.WriteLine("Bid Ask Curves Report: ");
Console.WriteLine(semoReports.ResourceBaseUri + "/" + semoReports.Items[0].ResourceName);
string bidAskCurvesXML = semoReports.ResourceBaseUri + "/" + semoReports.Items[0].ResourceName;
XDocument bacDoc = XDocument.Load(bidAskCurvesXML);
//Execute DeserializeBidAskCurves
semoAPI.DeserializeBidAskCurves(bidAskCurvesXML);
}
}
Below is how my class is setup which contains the XML Elements I need:
namespace SEMO_app
{
[XmlRoot("BidAskCurves")]
public class BidAskCurves
{
[Key]
public int ReportID { get; set; }
[XmlElement("MarketArea")]
public MarketArea[] MarketAreas{ get; set; }
}
public class MarketArea
{
public string MarketAreaName { get; set; }
[XmlElement("DeliveryDay")]
public DeliveryDay[] DeliveryDays { get; set; }
}
public class DeliveryDay
{
public string Day { get; set; }
[XmlElement("TimeStep")]
public TimeStep[] TimeSteps{ get; set; }
}
public class TimeStep
{
public string TimeStepID { get; set; }
[XmlElement("Purchase")]
public Purchase[] Purchases { get; set; }
}
public class Purchase
{
public string Price { get; set; }
public string Volume { get; set; }
}
}
From here i would like to deserialize the XML and save the information to a database, below is the code I have so far which deserialize's the XML and gives the results back fine in the console.writesection.
However I am unable to save these values to the database table. The code complies and executes fine and a the database table updates, however the table only contains a report id column. Where I would like it to contain the items listed in the console.write section.
private void DeserializeBidAskCurves(string filename)
{
//Visual only not needed
Console.WriteLine("\n" + "Reading BidAskCurves XML File");
Console.WriteLine("===========================================================");
// Create an instance of the XmlSerializer.
XmlSerializer serializer = new XmlSerializer(typeof(BidAskCurves));
// Declare an object variable of the type to be deserialized.
BidAskCurves item;
using (XmlReader reader = XmlReader.Create(filename))
{
// Call the Deserialize method to restore the object's state.
item = (BidAskCurves)serializer.Deserialize(reader);
//Write out the properties of the object. (Visual Only, not needed)
Console.Write(
item.MarketAreas[0].MarketAreaName + "\t" +
item.MarketAreas[0].DeliveryDays[0].Day + "\t" +
item.MarketAreas[0].DeliveryDays[0].TimeSteps[0].TimeStepID + "\t" +
item.MarketAreas[0].DeliveryDays[0].TimeSteps[0].Purchases[0].Price + "\t" +
item.MarketAreas[0].DeliveryDays[0].TimeSteps[0].Purchases[0].Volume);
//write the properties to the db
using (SEMOContext context = new SEMOContext())
{
context.BidAskCurvesReports.Add(item);
context.SaveChanges();
}
}
}
Link to xml file: https://reports.semopx.com/documents/BidAskCurves_NI-IDA3_20190401_20190401161933.xml
Thanks for any help in advance.
Initially, it's hard to know what's the problem actually is?
But after visiting URI generated by
string bidAskCurvesXML = semoReports.ResourceBaseUri + "/" + semoReports.Items[0].ResourceName;
And that is https://reports.semopx.com/documents/BidAskCurves_NI-IDA3_20190401_20190401161933.xml
So, The class structure that you are using is different than xml generated by URI.
You need to use below class structure for your xml
[XmlRoot("Purchase")]
public class Purchase
{
[XmlElement("Price")]
public string Price { get; set; }
[XmlElement("Volume")]
public string Volume { get; set; }
}
[XmlRoot("Sell")]
public class Sell
{
[XmlElement("Price")]
public string Price { get; set; }
[XmlElement("Volume")]
public string Volume { get; set; }
}
[XmlRoot("TimeStep")]
public class TimeStep
{
[XmlElement("TimeStepID")]
public string TimeStepID { get; set; }
[XmlElement("Purchase")]
public List<Purchase> Purchase { get; set; }
[XmlElement("Sell")]
public List<Sell> Sell { get; set; }
}
[XmlRoot("DeliveryDay")]
public class DeliveryDay
{
[XmlElement("Day")]
public string Day { get; set; }
[XmlElement("TimeStep")]
public List<TimeStep> TimeStep { get; set; }
}
[XmlRoot("MarketArea")]
public class MarketArea
{
[XmlElement("MarketAreaName")]
public string MarketAreaName { get; set; }
[XmlElement("DeliveryDay")]
public DeliveryDay DeliveryDay { get; set; }
}
[XmlRoot("BidAskCurves")]
public class BidAskCurves
{
[XmlElement("MarketArea")]
public MarketArea MarketArea { get; set; }
}
And after using above class structure with XmlSerializer there are total 12 timestamp available
Usage:
XmlSerializer serializer = new XmlSerializer(typeof(BidAskCurves));
BidAskCurves item;
using (XmlReader reader = XmlReader.Create("https://reports.semopx.com/documents/BidAskCurves_NI-IDA3_20190401_20190401161933.xml"))
{
item = (BidAskCurves)serializer.Deserialize(reader);
//Your code to add above parsed data into database.
}
Output: (From Debugger)
Edit1:
To add first purchase's volume and price and sell's volume and price then,
...
item = (BidAskCurves)serializer.Deserialize(reader);
foreach (var ts in item.MarketArea.DeliveryDay.TimeStep)
{
BidAskCurvesData bidAskCurvesData = new BidAskCurvesData
{
ReportID = 123,
MarketAreaName = item.MarketArea.MarketAreaName,
Day = item.MarketArea.DeliveryDay.Day,
TimeSetID = ts.TimeStepID,
PurchasePrice = ts.Purchase[0].Price,
PurchaseVolume = ts.Purchase[0].Volume,
SellPrice = ts.Sell[0].Price,
SellVolume = ts.Sell[0].Volume
};
using (SEMOContext context = new SEMOContext())
{
context.BidAskCurvesReports.Add(item);
context.SaveChanges();
}
}
static void Main(string[] args)
{
using (WebClient webClient = new WebClient())
{
//Bid Ask Curves
var bidAskCurves = webClient.DownloadString("https://reports.semopx.com/documents/BidAskCurves_NI-IDA3_20190401_20190401161933.xml");
var serializer = new XmlSerializer(typeof(BidAskCurves));
BidAskCurves result;
using (TextReader reader = new StringReader(bidAskCurves))
{
// here it is
result = (BidAskCurves)serializer.Deserialize(reader);
}
}
Console.ReadKey();
}
and xml objects:
[XmlRoot(ElementName = "Purchase")]
public class Purchase
{
[XmlElement(ElementName = "Price")]
public string Price { get; set; }
[XmlElement(ElementName = "Volume")]
public string Volume { get; set; }
}
[XmlRoot(ElementName = "Sell")]
public class Sell
{
[XmlElement(ElementName = "Price")]
public string Price { get; set; }
[XmlElement(ElementName = "Volume")]
public string Volume { get; set; }
}
[XmlRoot(ElementName = "TimeStep")]
public class TimeStep
{
[XmlElement(ElementName = "TimeStepID")]
public string TimeStepID { get; set; }
[XmlElement(ElementName = "Purchase")]
public List<Purchase> Purchase { get; set; }
[XmlElement(ElementName = "Sell")]
public List<Sell> Sell { get; set; }
}
[XmlRoot(ElementName = "DeliveryDay")]
public class DeliveryDay
{
[XmlElement(ElementName = "Day")]
public string Day { get; set; }
[XmlElement(ElementName = "TimeStep")]
public List<TimeStep> TimeStep { get; set; }
}
[XmlRoot(ElementName = "MarketArea")]
public class MarketArea
{
[XmlElement(ElementName = "MarketAreaName")]
public string MarketAreaName { get; set; }
[XmlElement(ElementName = "DeliveryDay")]
public DeliveryDay DeliveryDays { get; set; }
}
[XmlRoot(ElementName = "BidAskCurves")]
public class BidAskCurves
{
[XmlElement(ElementName = "MarketArea")]
public MarketArea MarketAreas { get; set; }
}
EDIT
loop over the result:
foreach (var item in deliveryDays.TimeStep)
{
// var day = deliveryDays.Day
var timeStep_Purchase = item.Purchase;
var timeStep_Sell = item.Sell;
var timeStep_Id = item.TimeStepID;
}

Why an XML string cannot be deserialized due to prefixes in root elements?

I have the XML below:
<y:input xmlns:y='http://www.blahblah.com/engine/42'>
<y:datas>
<y:instance yclass='ReportPeriod' yid="report">
<language yid='en'/>
<threshold>0.6</threshold>
<typePeriod>predefinedPeriod</typePeriod>
<interval>month</interval>
<valuePeriod>April</valuePeriod>
<fund yclass="Fund">
<name>K</name>
<indexName>CAC40</indexName>
</fund>
</y:instance>
</y:datas>
</y:input>
That I am trying to deserialize to
[XmlRoot(ElementName="fund")]
public class Fund
{
[XmlElement(ElementName="name")]
public string Name { get; set; }
[XmlElement(ElementName="indexName")]
public string IndexName { get; set; }
[XmlAttribute(AttributeName="yclass")]
public string Yclass { get; set; }
}
[XmlRoot(ElementName="instance", Namespace="http://www.blahblah.com/engine/42")]
public class Instance
{
[XmlElement(ElementName="language")]
public Language Language { get; set; }
[XmlElement(ElementName="threshold")]
public string Threshold { get; set; }
[XmlElement(ElementName="typePeriod")]
public string TypePeriod { get; set; }
[XmlElement(ElementName="interval")]
public string Interval { get; set; }
[XmlElement(ElementName="valuePeriod")]
public string ValuePeriod { get; set; }
[XmlElement(ElementName="fund")]
public Fund Fund { get; set; }
[XmlAttribute(AttributeName="yclass")]
public string Yclass { get; set; }
[XmlAttribute(AttributeName="yid")]
public string Yid { get; set; }
}
[XmlRoot(ElementName="datas", Namespace="http://www.blahblah.com/engine/42")]
public class Datas
{
[XmlElement(ElementName="instance", Namespace="http://www.blahblah.com/engine/42")]
public Instance Instance { get; set; }
}
[XmlRoot(ElementName="input", Namespace="http://www.blahblah.com/engine/42")]
public class Input
{
[XmlElement(ElementName="datas", Namespace="http://www.blahblah.com/engine/42")]
public Datas Datas { get; set; }
[XmlAttribute(AttributeName="y", Namespace="http://www.blahblah.com/engine/42", Form = XmlSchemaForm.Qualified)]
public string Y { get; set; }
}
However, when deserializing the XML above:
public static class Program
{
public static void Main(params string[] args)
{
var serializer = new XmlSerializer(typeof(Input));
using (var stringReader = new StringReader(File.ReadAllText("file.xml")))
{
using(var xmlReader = XmlReader.Create(stringReader))
{
var instance = (Input)serializer.Deserialize(stringReader);
}
}
}
}
I get an error due to the y prefix...
There is an error in XML document (1, 1). ---> System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
Reading some posts like that one: https://stackoverflow.com/a/36163079/4636721 it seems that there is maybe a bug with the XmlSerializer.
The cause of the exception is that you are passing stringReader rather than xmlReader to serializer.Deserialize(). You should be passing the XML reader instead:
Input instance = null;
var serializer = new XmlSerializer(typeof(Input));
using (var stringReader = new StreamReader("file.xml"))
{
using(var xmlReader = XmlReader.Create(stringReader))
{
instance = (Input)serializer.Deserialize(xmlReader);
}
}
(Apparently XmlReader.Create(stringReader) advances the text reader a bit, so if you later attempt to read from the stringReader directly, it has been moved past the root element.)
You also have some errors in your data model. It should look like:
[XmlRoot(ElementName="fund")]
public class Fund
{
[XmlElement(ElementName="name")]
public string Name { get; set; }
[XmlElement(ElementName="indexName")]
public string IndexName { get; set; }
[XmlAttribute(AttributeName="yclass")]
public string Yclass { get; set; }
}
[XmlRoot(ElementName="instance")]
[XmlType(Namespace = "")] // Add this
public class Instance
{
[XmlElement(ElementName="language")]
public Language Language { get; set; }
[XmlElement(ElementName="threshold")]
public string Threshold { get; set; }
[XmlElement(ElementName="typePeriod")]
public string TypePeriod { get; set; }
[XmlElement(ElementName="interval")]
public string Interval { get; set; }
[XmlElement(ElementName="valuePeriod")]
public string ValuePeriod { get; set; }
[XmlElement(ElementName="fund")]
public Fund Fund { get; set; }
[XmlAttribute(AttributeName="yclass")]
public string Yclass { get; set; }
[XmlAttribute(AttributeName="yid")]
public string Yid { get; set; }
}
[XmlRoot(ElementName="datas", Namespace="http://www.blahblah.com/engine/42")]
public class Datas
{
[XmlElement(ElementName="instance", Namespace="http://www.blahblah.com/engine/42")]
public Instance Instance { get; set; }
}
[XmlRoot(ElementName="input", Namespace="http://www.blahblah.com/engine/42")]
public class Input
{
[XmlElement(ElementName="datas", Namespace="http://www.blahblah.com/engine/42")]
public Datas Datas { get; set; }
//Remove This
//[XmlAttribute(AttributeName="y", Namespace="http://www.blahblah.com/engine/42", Form = XmlSchemaForm.Qualified)]
//public string Y { get; set; }
}
// Add this
[XmlRoot(ElementName="language")]
public class Language
{
[XmlAttribute(AttributeName="yid")]
public string Yid { get; set; }
}
Notes:
xmlns:y='http://www.blahblah.com/engine/42' is an XML namespace declaration and thus should not be mapped to a member in the data model.
The child elements of <y:instance ...> are not in any namespace. Unless the namespace of the child elements is specified by attributes somehow, XmlSerializer will assume that they should be in the same namespace as the containing element, here http://www.blahblah.com/engine/42".
Thus it is necessary to add [XmlType(Namespace = "")] to Instance to indicate the correct namespace for all child elements created from Instance. (Another option would be to add [XmlElement(Form = XmlSchemaForm.Unqualified)] to each member, but I think it is easier to set a single attribute on the type.)
A definition for Language is not included in your question, so I included one.
It will be more efficient to deserialize directly from your file using a StreamReader than to read first into a string, then deserialize from the string using a StringReader.
Working sample fiddle here.

Convert xml string to C# object

Below is my XML code.
<programs>
<program>
<ProgrameName>Test</ProgrameName>
<deviceTypes>
<DeviceType>POS</DeviceType>
<deviceTargets>
<DeviceNames>
<DeviceName>POS0001</DeviceName>
<DeviceName>POS0001</DeviceName>
<DeviceName>POS0001</DeviceName>
</DeviceNames>
<AttemptToIstall>True</AttemptToIstall>
<Mandetory>False</Mandetory>
<SkipIfOffline>False</SkipIfOffline>
</deviceTargets>
<AttemptToIstall>True</AttemptToIstall>
<Mandatory>False</Mandatory>
<SkipIfOffline>False</SkipIfOffline>
</deviceTypes>
</program>
please help me to write C# code using XmlSerializer.I want to create an object and serialize those object according to above XML.
below are my C# class.
public class ProgramP
{
public string ProgrameName { get; set; }
[XmlRoot("")]
public class DeviceTypes
{
public string DeviceType { get; set; }
[XmlRoot("")]
public class DeviceTargets
{
public string DeviceNames { get; set; }
public string AttemptToIstall { get; set; }
public string Mandetory { get; set; }
public string SkipIfOffline { get; set; }
}
[XmlElement("DeviceTargets")]
public DeviceTargets[] ArDeviceTargets { get; set; }
public string AttemptToIstall { get; set; }
public string Mandetory { get; set; }
public string SkipIfOffline { get; set; }
}
[XmlElement("DeviceTypes")]
public DeviceTypes[] ArDeviceType { get; set; }
}
Below is my C# code.can any body please correct me or suggest me where i have to add more class or how can i arrange my class so that i can get above XML as output.
public void ExportClass(string strFilePathExportedXML)
{
ProgramP ProgramP = new ProgramP
{
ProgrameName = "Test",
ArDeviceType = new ProgramP.DeviceTypes[] {
new ProgramP.DeviceTypes {
DeviceType = "POS1",
AttemptToIstall="True",
Mandetory="True",
SkipIfOffline="True",
ArDeviceTargets = new ProgramP.DeviceTypes.DeviceTargets[] {
new ProgramP.DeviceTypes.DeviceTargets {
DeviceNames="POS01",
AttemptToIstall="True",
Mandetory="True",
SkipIfOffline="True"
},
new ProgramP.DeviceTypes.DeviceTargets {
DeviceNames="POS02",
AttemptToIstall="True",
Mandetory="True",
SkipIfOffline="True"
}
}
};
TextWriter writer = new StreamWriter(strFilePathExportedXML);
XmlSerializer serializerOut = new XmlSerializer(typeof(ProgramP));
serializerOut.Serialize(writer, ProgramP);
writer.Close();
After mapping, you can use this:
public static YourClass LoadFromXMLString(string xmlText)
{
var stringReader = new System.IO.StringReader(xmlText);
var serializer = new XmlSerializer(typeof(YourClass ));
return serializer.Deserialize(stringReader) as YourClass ;
}
From this topic: Convert Xml to Object

Parse XML string with LINQ, create new object from xml

Given the following requirements and code, I have not yet found ONE answer that actually works.
I have an XML field in a SQL Server Database table. Why is it in there? I have no idea. I didn't put it in there. I just have to get the data out and into a List that I can combine with another List to populate a grid in a WPF app that has an MVVM architecture.
Here is that List:
List QAItems = new List();
The QADailyXValueCalCheck type is as follows:
using System.Xml.Serialization;
namespace ConvertXmlToList {
[XmlRoot(ElementName = "column")]
public class QADailyXValueCalCheck {
[XmlElement]
public string Regs { get; set; }
[XmlElement]
public string BasisTStamp { get; set; }
[XmlElement]
public string DAsWriteTStamp { get; set; }
[XmlElement]
public string InjEndTime { get; set; }
[XmlElement]
public bool Manual { get; set; }
[XmlElement]
public decimal RefValue { get; set; }
[XmlElement]
public decimal MeasValue { get; set; }
[XmlElement]
public string Online { get; set; }
[XmlElement]
public decimal AllowableDrift { get; set; }
[XmlElement]
public bool FailOoc { get; set; } = false;
[XmlElement]
public bool FailAbove { get; set; }
[XmlElement]
public bool FailBelow { get; set; }
[XmlElement]
public bool FailOoc5Day { get; set; }
[XmlElement]
public decimal InstSpan { get; set; }
[XmlElement]
public decimal GasLevel { get; set; }
[XmlElement]
public string CId { get; set; }
[XmlElement]
public string MId { get; set; }
[XmlElement]
public string CylinderId { get; set; }
[XmlElement]
public string CylinderExpDate { get; set; }
[XmlElement]
public string CylinderVendorId { get; set; }
[XmlElement]
public string CylinderGasTypeCode { get; set; }
}
}
The XML is being stored in a string, xmlString and comes out of the db in the following form:
<Regs>40CFR75</Regs>
<BasisTStamp>2016-02-15 05:18</BasisTStamp>
<DASWriteTStamp>2016-02-15 05:40</DASWriteTStamp>
<InjEndTime>2016-02-15 05:23</InjEndTime>
<Manual>0</Manual>
<RefValue>169.7</RefValue>
<MeasValue>169.27</MeasValue>
<Online>14</Online>
<AllowableDrift>15</AllowableDrift>
<FailAbove>0</FailAbove>
<FailBelow>0</FailBelow>
<InstSpan>300</InstSpan>
<GasLevel>MID</GasLevel>
<CID>111</CID>
<MID>N10</MID>
<CylinderID>CC357464</CylinderID>
<CylinderExpDate>2022-08-12</CylinderExpDate>
<CylinderVendorID>B22014</CylinderVendorID>
<CylinderGasTypeCode>BALN,SO2,NO,CO2</CylinderGasTypeCode>
Now, in order to get past the XML API's problem with "rootless" xml, I've added a root:
xmlString = "<columns>" + xmlString + "</columns>";
To parse this, I use:
XDocument doc = XDocument.Parse(xmlString);
Finally, to attempt to extract the VALUES from the XML and populate an instance of QADailyXValueCalCheck, I have the following code - which was adapted to work from other examples - THAT DO NOT WORK.
var xfields =
from r in doc.Elements("columns")
select new QADailyXValueCalCheck
{
Regs = (string) r.Element("Regs"),
BasisTStamp = (string) r.Element("BasisTStamp"),
DAsWriteTStamp = (string) r.Element("DASWriteTStamp"),
InjEndTime = (string) r.Element("InjEndTime"),
Manual = (bool) r.Element("Manual"),
RefValue = (decimal) r.Element("RefValue"),
MeasValue = (decimal)r.Element("MeasValue"),
Online = (string)r.Element("Online"),
AllowableDrift = (decimal)r.Element("AllowableDrift"),
//FailOoc = (bool)r.Element("FailOoc"),
//FailAbove = (bool)r.Element("FailAbove"),
//FailBelow = (bool)r.Element("FailBelow"),
//FailOoc5Day = (bool)r.Element("FailOoc5Day"),
//InstSpan = (decimal)r.Element("InstSpan"),
//GasLevel = (decimal)r.Element("GasLevel"),
CId = (string)r.Element("CID"),
MId = (string)r.Element("MID"),
CylinderId = (string)r.Element("CylinderId"),
CylinderExpDate = (string)r.Element("CylinderExpDate"),
CylinderVendorId = (string)r.Element("CylinderVendorId"),
CylinderGasTypeCode = (string)r.Element("CylinderGasTypeCode")
};
The code immediately above does NOT create a new instance of the class, "QADailyXValueCalCheck" which can be added to the List. I have a few null values that are causing a problem with that code, but that is a separate issue that I will deal with another time.
For now, can anyone tell me how that "var xfields = " query instantiates a new QADailyXValueCalCheck object that can be added to my List of the same type?
What code is missing? Thank you to the LINQ/XML genius that can answer this.
I had a similar question on XML parsing the other day from someone else here:
Create a List from XElements Dynamically
I think in the end you would be better served using a class with xml adornments and then have extension classes that serialize or deserialize the data. This makes it better IMHO in two ways:
1. You don't have to rewrite the parser and the POCO class, just the POCO class.
2. You can be free to reuse the extension method in other places.
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
namespace GenericTesting.Models
{
[XmlRoot(ElementName = "column")]
public class QADailyXValueCalCheck
{
[XmlElement]
public string Regs { get; set; }
[XmlElement]
public string BasisTStamp { get; set; }
[XmlElement]
public string DAsWriteTStamp { get; set; }
[XmlElement]
public string InjEndTime { get; set; }
[XmlElement]
public int Manual { get; set; }
[XmlElement]
public decimal RefValue { get; set; }
[XmlElement]
public decimal MeasValue { get; set; }
[XmlElement]
public int Online { get; set; }
[XmlElement]
public decimal AllowableDrift { get; set; }
[XmlElement]
public bool FailOoc { get; set; } = false;
[XmlElement]
public int FailAbove { get; set; }
[XmlElement]
public int FailBelow { get; set; }
[XmlElement]
public bool FailOoc5Day { get; set; }
[XmlElement]
public decimal InstSpan { get; set; }
[XmlElement]
public string GasLevel { get; set; }
[XmlElement]
public string CId { get; set; }
[XmlElement]
public string MId { get; set; }
[XmlElement]
public string CylinderId { get; set; }
[XmlElement]
public string CylinderExpDate { get; set; }
[XmlElement]
public string CylinderVendorId { get; set; }
[XmlElement]
public string CylinderGasTypeCode { get; set; }
}
}
And for the purpose of serializing/deserializing let me give extension methods for those:
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace GenericTesting
{
static class ExtensionHelper
{
public static string SerializeToXml<T>(this T valueToSerialize)
{
dynamic ns = new XmlSerializerNamespaces();
ns.Add("", "");
StringWriter sw = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings { OmitXmlDeclaration = true }))
{
dynamic xmler = new XmlSerializer(valueToSerialize.GetType());
xmler.Serialize(writer, valueToSerialize, ns);
}
return sw.ToString();
}
public static T DeserializeXml<T>(this string xmlToDeserialize)
{
dynamic serializer = new XmlSerializer(typeof(T));
using (TextReader reader = new StringReader(xmlToDeserialize))
{
return (T)serializer.Deserialize(reader);
}
}
}
}
And a simple main entry point in a console app:
static void Main(string[] args)
{
var thingie = new QADailyXValueCalCheck
{
Regs = "40CFR75",
BasisTStamp = "2016-02-15 05:18",
DAsWriteTStamp = "2016-02-15 05:40",
InjEndTime = "2016-02-15 05:23",
Manual = 0, //Boolean This will probably mess up Changed to Int
RefValue = 169.7M,
MeasValue = 169.27M,
Online = 14, //Mismatch Type? Change to Int
AllowableDrift = 15,
FailAbove = 0, //Boolean This will probably mess up Changed to Int
FailBelow = 0, //Boolean This will probably mess up Changed to Int
InstSpan = 300,
GasLevel = "MID", //This is marked as a decimal? Changed to string
CId = "111",
MId = "N10",
CylinderId= "CC357464",
CylinderExpDate ="2022-08-12",
CylinderVendorId = "B22014",
CylinderGasTypeCode = "BALN,SO2,NO,CO2"
};
var serialized = thingie.SerializeToXml();
var deserialized = serialized.DeserializeXml<QADailyXValueCalCheck>();
Console.ReadLine();
}
This serializes just like this and I can get it back to deserialized as well.

JavaScriptSerializer, Parsing Json from HttpRequest, put pars into a table to be displayed

I made a call to a web server called Sample ApI. I want to be able to parse that data that's in json or xml, either would be nice and display it in a table format. This is what I have so far.
All I want is to be able to parse the data that's in this string _responseAsString and display a table. I don't know how to start it, I just know JavaScriptSerialzer parseXXX = new Java...lizer(). Please help me or assist in the right direction.
public class Event
{
public string event_key { get; set; }
public string user_token { get; set; }
public string event_set_key { get; set; }
public string event_type { get; set; }
public string event_date { get; set; }
public string event_amount { get; set; }
public string event_location_key { get; set; }
public string event_location_name { get; set; }
public string event_location_city { get; set; }
public string event_location_state { get; set; }
public string event_location_country { get; set; }
public string event_acknowledged { get; set; }
}
public ActionResult GetEvent()
{
try
{
string at = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
string et = "KI2XfwQNByLPFdK4i3a74slLT7sjjzYRi9RR7zEtCoQ%3D";
string t = "20111128183020";
string _checkingUrl = String.Format("http://172.22.22.10/SampleAPI/Event/GetEvents?at={0}&et={1}&t={2}&responseFormat=json", at, et, t);
System.Net.HttpWebRequest request=System.Net.WebRequest.Create(_checkingUrl) as System.Net.HttpWebRequest;
System.Net.HttpWebResponse response=request.GetResponse() as System.Net.HttpWebResponse;
System.IO.StreamReader _readResponse=new System.IO.StreamReader(response.GetResponseStream());
//The encrypted dynamics response in either xml or json
string _responseAsString=_readResponse.ReadToEnd();
JavaScriptSerializer parseResponse = new JavaScriptSerializer();
List<Event> events = parseResponse.Deserialize<List<Event>>(_responseAsString);
// this below is to make sure i was receiving my json data.
return Content(_responseAsString);
_readResponse.Close();
}
catch (Exception e)
{
//log error
}
return View();
}
This is the json data I receive when I make the http request:
"[{\"event_key\":\"cc2a1802-2b04-4530-ad50-0d4f0ed19dd3\",\"user_token\":\"40e62a11-40c4-408d-8cdd-1293cbaf9a41\",\"event_set_key\":\"615017f2-ae28-4b8d-9def-cf043642b928\",\"event_type\":\"Arrival\",\"event_date\":\"6/20/2011
4:15:28
PM\",\"event_amount\":\"100\",\"event_location_key\":\"50fc1c22-d77b-4a91-b31d-da036827060b\",\"event_location_name\":\"Store2\",\"event_location_city\":\"Pittsburgh\",\"event_location_state\":\"PA\",\"event_location_country\":\"US\",\"event_location_lat\":\"\",\"event_location_long\":\"\",\"event_description\":\"\",\"event_acknowledged\":\"True\"},{\"event_key\":\"2ac9e25e-137c-4a72-8cc5-157d67ea66c1\",\"user_token\":\"58cb4fcd-e140-4232-88c9-06eecb95b63d\",\"event_set_key\":\"00710ca7-f5d7-4c7a-bbfb-95491ae278ef\",\"event_type\":\"Arrival\",\"event_date\":\"9/23/2011
4:15:28
PM\",\"event_amount\":\"45\",\"event_location_key\":\"5a732dd5-9459-4cdd-a980-f3daf1a07343\",\"event_location_name\":\"Store4\",\"event_location_city\":\"Pittsburgh\",\"event_location_state\":\"PA\",\"event_location_country\":\"US\",\"event_location_lat\":\"\",\"event_location_long\":\"\",\"event_description\":\"\",\"event_acknowledged\":\"False\"},{\"event_key\":\"386b1fa1-11b2-48d9-b7f1-4bbe21ced487\",\"user_token\":\"c3d8b7ff-d85f-42a8-98f6-e091b48c2280\",\"event_set_key\":\"dc55843b-f8cf-4e8a-9091-188ce0609fe1\",\"event_type\":\"Arrival\",\"event_date\":\"9/18/2011
4:15:28
PM\",\"event_amount\":\"100\",\"event_location_key\":\"be6d4fb4-c0e3-4303-b70d-7a22b721aa56\",\"event_location_name\":\"Store1\",\"event_location_city\":\"Pittsburgh\",\"event_location_state\":\"PA\",\"event_location_country\":\"US\",\"event_location_lat\":\"\",\"event_location_long\":\"\",\"event_description\":\"\",\"event_acknowledged\":\"False\"}]"
The JSON website has some good information on this.
For older browsers, you would eval the string (with some brackets to make it work):
var myObject = eval('(' + myJsonText + ')');
And these days, we tend to use
JSON.parse(myJsonText);
And server side, in C#
var serializer = new JavaScriptSerializer();
T obj = serializer.Deserialize<T>(myJsonText);
First of all...
If you're just passing through the JSON message returned from some other API, why not just return their response string verbatim (in other words, why deserialize it at all)?
public ActionResult GetEvent()
{
string at = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
string et = "KI2XfwQNByLPFdK4i3a74slLT7sjjzYRi9RR7zEtCoQ%3D";
string t = "20111128183020";
string _checkingUrl = String.Format("http://172.22.22.10/SampleAPI/Event/GetEvents?at={0}&et={1}&t={2}&responseFormat=json", at, et, t);
System.Net.HttpWebRequest request=System.Net.WebRequest.Create(_checkingUrl) as System.Net.HttpWebRequest;
System.Net.HttpWebResponse response=request.GetResponse() as System.Net.HttpWebResponse;
using (var readResponse= new StreamReader(response.GetResponseStream()))
{
return Content(readResponse.ReadToEnd(), "application/json");
}
}
Then read on
It's possible to use a JSON text reader to break apart the JSON message into a table of name/value pairs, but I think that's missing the point in your case. If the message is constant, just create a class that represents each element in the JSON message and parse it. I used json2csharp to stub such a class:
public class Event
{
public string event_key { get; set; }
public string user_token { get; set; }
public string event_set_key { get; set; }
public string event_type { get; set; }
public string event_date { get; set; }
public string event_amount { get; set; }
public string event_location_key { get; set; }
public string event_location_name { get; set; }
public string event_location_city { get; set; }
public string event_location_state { get; set; }
public string event_location_country { get; set; }
public string event_location_lat { get; set; }
public string event_location_long { get; set; }
public string event_description { get; set; }
public string event_acknowledged { get; set; }
}
Then use your favorite JSON serializer to deserialize into a list of these objects:
var serializer = new JavaScriptSerializer();
var events = serializer.Deserialize<List<Event>>(responseAsString);
(I prefer JSON.NET, here's the equivalent to the block above)
var events = JsonConvert.DeserializeObject<List<Event>>(responseAsString);
If you actually do need to be able to read a stream of text and generically create a table of name/value pairs, I'd use JSON.NET's LINQ-to-JSON or the JsonTextReader.

Categories

Resources