I am having trouble deserializing XML. I get AccountInformation to work but it won't work with the Leauge elements. The XML doesn't contain any tag for "Leauges" and I don't want to add that tag to get it to work. Is there any other way to "fix" it? I have tried diffrent solutions but the deserialized result of the leauges comes back empty. What am I missing?
Any help appreciated!
Se my code below:
Update:
I have modified the code and the XML but I won't work anyway. What am I missing here?
[Serializable]
[XmlRoot(ElementName = "LeaugeCollection", Namespace = "")]
public class LeagueCollection
{
[XmlArray("Leagues")]
[XmlArrayItem("League",typeof(League))]
public League[] League { get; set; }
[XmlElement(ElementName = "AccountInformation")]
public string AccountInformation { get; set; }
}
[Serializable()]
public class League
{
[XmlElement(ElementName = "Id")]
public int Id { get; set; }
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "Country")]
public string Country { get; set; }
[XmlElement(ElementName = "Historical_Data")]
public string Historical_Data { get; set; }
[XmlElement(ElementName = "Fixtures")]
public string Fixtures { get; set; }
[XmlElement(ElementName = "LiveScore")]
public string Livescore { get; set; }
[XmlElement(ElementName = "NumberOfMatches")]
public int NumberOfMatches { get; set; }
[XmlElement(ElementName = "LatestMatch")]
public DateTime LatestMatch { get; set; }
}
Deserialize code:
public static void Main(string[] args)
{
XmlSerializer deserializer = new XmlSerializer(typeof(LeagueCollection));
TextReader reader = new StreamReader(#"C:\XmlFiles\XmlSoccer.xml");
object obj = deserializer.Deserialize(reader);
LeagueCollection XmlData = (LeagueCollection)obj;
reader.Close();
}
Link to XML:
Thanks in advance!
The XML you have in the image is missing the actual array element (Leauges), it has only the array items elements (Leauge), that is why you cannot get it deserialized!
UPDATE:
Ok, trying to reproduce your code, I now see that in your XML your elements are spelled "League" while in your code "Leauge"
FIX that first!
UPDATE2:
After the edits you have done according to my comments,it seems to work fine!
You are missing a namespace. I don't like both Leagues and League. Leagues is unnecessary.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
LeagueCollection leagueCollection = new LeagueCollection() {
leagues = new Leagues() {
League = new List<League>() {
new League() {
Id = 1,
Name = "English Premier League",
Country = "England",
Historical_Data = "Yes",
Fixtures = "Yes",
Livescore = "Yes",
NumberOfMatches = 5700,
LatestMatch = DateTime.Parse( "2015-05-24T16:00:00+00:00")
},
new League() {
Id = 2,
Name = "English League Championship",
Country = "England",
Historical_Data = "Yes",
Fixtures = "Yes",
Livescore = "Yes",
NumberOfMatches = 5700,
LatestMatch = DateTime.Parse("2015-05-24T16:00:00+00:00")
}
}
},
AccountInformation = "Confidential info"
};
XmlSerializer serializer = new XmlSerializer(typeof(LeagueCollection));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, leagueCollection);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer deserializer = new XmlSerializer(typeof(LeagueCollection));
XmlTextReader reader = new XmlTextReader(FILENAME);
LeagueCollection XmlData = (LeagueCollection)deserializer.Deserialize(reader);
reader.Close();
}
}
[XmlRoot(ElementName = "LeaugeCollection")]
public class LeagueCollection
{
[XmlElement("Leagues")]
public Leagues leagues { get; set; }
[XmlElement(ElementName = "AccountInformation")]
public string AccountInformation { get; set; }
}
[XmlRoot("Leagues")]
public class Leagues
{
[XmlElement("League")]
public List<League> League { get; set; }
}
[XmlRoot("League")]
public class League
{
[XmlElement(ElementName = "Id")]
public int Id { get; set; }
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "Country")]
public string Country { get; set; }
[XmlElement(ElementName = "Historical_Data")]
public string Historical_Data { get; set; }
[XmlElement(ElementName = "Fixtures")]
public string Fixtures { get; set; }
[XmlElement(ElementName = "LiveScore")]
public string Livescore { get; set; }
[XmlElement(ElementName = "NumberOfMatches")]
public int NumberOfMatches { get; set; }
[XmlElement(ElementName = "LatestMatch")]
public DateTime LatestMatch { get; set; }
}
}
Related
I cannot bind my c# model with this kind of xml file. Because there is multiple element with same.
This is a example of my XML File.
<Type>
<Loop LoopId="2100A" Name="MEMBER NAME">
<PER>
<!--Contact Function Code-->
<PER01>IP<!--Insured Party--></PER01>
<PER02 />
<!--Communication Number Qualifier-->
<PER03>HP<!--Home Phone Number--></PER03>
<!--Communication Number-->
<PER04>6235834409</PER04>
</PER>
</Loop>
<Loop LoopId="2100C" Name="MEMBER MAILING ADDRESS">
<NM1>
<!--Entity Identifier Code-->
<NM101>31<!--Postal Mailing Address--></NM101>
<!--Entity Type Qualifier-->
<NM102>1<!--Person--></NM102>
</NM1>
</Loop>
<Loop LoopId="2100G" Name="RESPONSIBLE PERSON">
<PER>
<!--Contact Function Code-->
<PER01>IP<!--Insured Party--></PER01>
<PER02 />
<!--Communication Number Qualifier-->
<PER03>HP<!--Home Phone Number--></PER03>
<!--Communication Number-->
<PER04>6235834409</PER04>
</PER>
<LM>
<!--Contact Function Code-->
<LM01>RP<!--Responsible Person--></LM01>
<LM02 />
</LM>
</Loop>
</Type>
I have use this following code to bind. But Code is not working, cause data binding get confused.
[XmlElement(ElementName = "Loop")]
public L3_L1_MemberName L3_L1_MemberName { get; set; }
[XmlElement(ElementName = "Loop")]
public L3_L2_MemberMailingAddress L3_L2_MemberMailingAddress { get; set; }
[XmlElement(ElementName = "Loop")]
public L3_L3_ResponsiblePerson L3_L3_ResponsiblePerson { get; set; }
based your XML, the model looks like
[XmlRoot(ElementName = "PER")]
public class PER
{
[XmlElement(ElementName = "PER01")]
public string PER01 { get; set; }
[XmlElement(ElementName = "PER02")]
public string PER02 { get; set; }
[XmlElement(ElementName = "PER03")]
public string PER03 { get; set; }
[XmlElement(ElementName = "PER04")]
public string PER04 { get; set; }
}
[XmlRoot(ElementName = "Loop")]
public class Loop
{
[XmlElement(ElementName = "PER")]
public PER PER { get; set; }
[XmlAttribute(AttributeName = "LoopId")]
public string LoopId { get; set; }
[XmlAttribute(AttributeName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "NM1")]
public NM1 NM1 { get; set; }
[XmlElement(ElementName = "LM")]
public LM LM { get; set; }
}
[XmlRoot(ElementName = "NM1")]
public class NM1
{
[XmlElement(ElementName = "NM101")]
public string NM101 { get; set; }
[XmlElement(ElementName = "NM102")]
public string NM102 { get; set; }
}
[XmlRoot(ElementName = "LM")]
public class LM
{
[XmlElement(ElementName = "LM01")]
public string LM01 { get; set; }
[XmlElement(ElementName = "LM02")]
public string LM02 { get; set; }
}
[XmlRoot(ElementName = "Type")]
public class Type
{
[XmlElement(ElementName = "Loop")]
public List<Loop> Loop { get; set; }
}
Here is the logic to DeSerialize the XML to Object
XmlSerializer serializer = new XmlSerializer(typeof(Type));
string xml = File.ReadAllText("XMLFile3.xml");
using (TextReader reader = new StringReader(xml))
{
var results = (Type)serializer.Deserialize(reader);
foreach (var item in results.Loop)
{
Console.WriteLine($"{item.LoopId} {item.Name}");
if (item.PER != null)
{
Console.WriteLine($"PER:{Regex.Replace(item.PER.PER01, #"\s+", "")}-{Regex.Replace(item.PER.PER02, #"\s+", "")}-{Regex.Replace(item.PER.PER03, #"\s+", "")}-{Regex.Replace(item.PER.PER04, #"\s+", "")}");
}
if (item.NM1 != null)
{
Console.WriteLine($"NM1:{Regex.Replace(item.NM1.NM101, #"\s+", "")}-{Regex.Replace(item.NM1.NM102, #"\s+", "")}");
}
if (item.LM != null)
{
Console.WriteLine($"LM:{Regex.Replace(item.LM.LM01, #"\s+", "")}-{Regex.Replace(item.LM.LM02, #"\s+", "")}");
}
}
}
OUTPUT
2100A MEMBER NAME
PER:IP--HP-6235834409
2100C MEMBER MAILING ADDRESS
NM1:31-1
2100G RESPONSIBLE PERSON
PER:IP--HP-6235834409
LM:RP-
I'm still struggling with deserialization of XML containing arrays of items.
The response I want to deserialize:
<ns1:OperationResult xmlns:ns1="http://xxxx.com">
<done>false</done>
<errorEntities>
<elements>
<entityID>100014</entityID>
<entityType>GROUP</entityType>
<errors>
<errorCode>INVALID_DATA</errorCode>
<errorMessage>s: d3f62887-a2a3-4cde-8f8b-09812a7bd011ed8d385e-f4c4-4fae-9a4b-1ba405db54b6-MessageTemplate:{k2.constraints.numberFormat.length}|length:5|; </errorMessage>
</errors>
</elements>
</errorEntities>
</ns1:OperationResult>
And this is my corresponding class:
[XmlRootAttribute(Namespace = "http://xxxx.", IsNullable = false, ElementName = "OperationResult")]
public class GroupCreateUpdateResult
{
[XmlElement(ElementName = "done")]
public string done { get; set; }
[XmlElement(ElementName = "errorEntities")]
public ErrorEntities errorEntities { get; set; }
public bool hasErrors => done == "true" ? true : false;
}
[XmlRoot(ElementName = "errorEntities")]
public class ErrorEntities
{
[XmlElement(ElementName = "elements")]
public List<ErrorElements> elements { get; } = new List<ErrorElements>();
}
[XmlRoot(ElementName = "elements")]
public class ErrorElements
{
[XmlElement(ElementName = "entityId")]
public string entityId { get; set; }
[XmlElement(ElementName = "entityType")]
public string entityType { get; set; }
[XmlElement(ElementName = "errors")]
Errors errors { get; set; }
}
[XmlRoot(ElementName = "errors")]
public class Errors
{
[XmlElement(ElementName = "errorCode")]
public string errorCode { get; set; }
[XmlElement(ElementName = "errorMessage")]
public string errorMessage { get; set; }
}
I have already a method deserializing my responses. Actually I am struggling with this specific one. Alle others without arrays are working fine.
What I finally get is this:
Any advice is highly appreciated.
You have a few issues
1) The namespace in the xml and the classes have to be the same
2) The tags names in the classes are case sensitive so you have to make sure the spelling is correct (Upper/Lower Case)
3) The class object have to be public otherwise the tags are ignored.
4) Where there are no namespaces in XML (and parent has a namespace) you need the empty string for the namespaces
See corrected code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(GroupCreateUpdateResult));
GroupCreateUpdateResult group = (GroupCreateUpdateResult)serializer.Deserialize(reader);
}
}
[XmlRootAttribute(Namespace = "http://com.f24.soap.fwi.schema", IsNullable = false, ElementName = "OperationResult")]
public class GroupCreateUpdateResult
{
[XmlElement(ElementName = "done", Namespace = "")]
public string done { get; set; }
[XmlElement(ElementName = "errorEntities", Namespace = "")]
public ErrorEntities errorEntities { get; set; }
//public bool hasErrors => done == "true" ? true : false;
}
[XmlRoot(ElementName = "errorEntities")]
public class ErrorEntities
{
[XmlElement(ElementName = "elements", Namespace = "")]
public List<ErrorElements> elements { get; set;}
}
[XmlRoot(ElementName = "elements")]
public class ErrorElements
{
[XmlElement(ElementName = "entityID")]
public string entityId { get; set; }
[XmlElement(ElementName = "entityType")]
public string entityType { get; set; }
[XmlElement(ElementName = "errors", Namespace = "")]
public Errors errors { get; set; }
}
[XmlRoot(ElementName = "errors")]
public class Errors
{
[XmlElement(ElementName = "errorCode")]
public string errorCode { get; set; }
[XmlElement(ElementName = "errorMessage")]
public string errorMessage { get; set; }
}
}
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;
}
I want to Deserialize and get values of 2 attributes with different ID.
<Attributes><AddressAttribute ID="18"><AddressAttributeValue><Value>Sala 305</Value></AddressAttributeValue></AddressAttribute><AddressAttribute ID="17"><AddressAttributeValue><Value>3434</Value></AddressAttributeValue></AddressAttribute></Attributes>
I treid this C# code but it only returns the 1st attribute.
please help
[XmlRoot(ElementName = "AddressAttributeValue")]
public class AddressAttributeValue
{
[XmlElement(ElementName = "Value")]
public string Value { get; set; }
}
[XmlRoot(ElementName = "AddressAttribute")]
public class AddressAttribute
{
[XmlElement(ElementName = "AddressAttributeValue")]
public AddressAttributeValue AddressAttributeValue { get; set; }
[XmlAttribute(AttributeName = "ID")]
public string ID { get; set; }
}
[XmlRoot(ElementName = "Attributes")]
public class Attributes
{
[XmlElement(ElementName = "AddressAttribute")]
public AddressAttribute AddressAttribute { get; set; }
}
var xmlData= customer.BillingAddress.CustomAttributes;
XmlSerializer serializer = new XmlSerializer(typeof(Attributes));
Attributes data;
using (TextReader reader = new StringReader(xmlData))
{
data = (Attributes)serializer.Deserialize(reader);
}
Should I change classes of Deserialize logic???
Sometimes using Linq instead of xml serialization can be simpler
var list = XDocument.Parse(xmlstring).Descendants("AddressAttribute")
.Select(x => new
{
Id = (int)x.Attribute("ID"),
Value = (string)x.Element("AddressAttributeValue").Element("Value")
})
.ToList();
[XmlRoot(ElementName = "Attributes")]
public class Attributes
{
[XmlElement(ElementName = "AddressAttribute")]
public AddressAttribute AddressAttribute { get; set; }
}
Change it to:
[XmlRoot(ElementName = "Attributes")]
public class Attributes
{
[XmlElement(ElementName = "AddressAttribute")]
public AddressAttribute[] AddressAttribute { get; set; }
}
As you need to have collection of AddressAttribute you need to declare as an array.
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.