I tried:
using (XmlReader reader = XmlReader.Create(_xmlPath))
{
while (reader.Read())
{
if (reader.NodeType.Equals(XmlNodeType.Element) && reader.Name.Equals("Obj"))
{
Obj obj = new Obj();
while (reader.Read())
{
if (reader.NodeType.Equals(XmlNodeType.EndElement) && reader.Name.Equals("Obj"))
break;
if (reader.NodeType.Equals(XmlNodeType.Element))
{
switch (reader.Name)
{
case "Code":
obj.Code = reader.ReadElementContentAsString();
break;
case "Data":
XElement el = (XElement) XNode.ReadFrom(reader);
XmlReader r = el.CreateReader();
XmlSerializer serializer = new XmlSerializer(typeof(Data));
Data data = (Data) serializer.Deserialize(r);
obj.Data = data;
break;
}
}
}
}
}
}
Xml :
<Root>
<Obj>
<Code>code</Code>
<Data>
<Date>2020-08-07</Date>
<Amount>1000</Amount>
</Data>
</Obj>
</Root>
Data class :
public class Data{
public DateTime Date {get;set;}
public decimal Amount {get;set;}
}
Normally, it's a large XML file, this is why I try to cut it to fragments and I use XmlReader to parse it.
The deserialization doesn't work, if you have other ways I'm a taker
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Data data = doc.Descendants("Data")
.Select(x => new Data() { Date = (DateTime)x.Element("Date"), Amount = (decimal)x.Element("Amount") }).FirstOrDefault();
}
}
public class Data
{
public DateTime Date { get; set; }
public decimal Amount { get; set; }
}
}
For huge files use following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
List<Data> data = new List<Data>();
while (!reader.EOF)
{
if (reader.Name != "Data")
{
reader.ReadToFollowing("Data");
}
if (!reader.EOF)
{
XElement xData = (XElement)XElement.ReadFrom(reader);
Data newData = new Data() { Date = (DateTime)xData.Element("Date"), Amount = (decimal)xData.Element("Amount") };
data.Add(newData);
}
}
}
}
public class Data
{
public DateTime Date { get; set; }
public decimal Amount { get; set; }
}
}
I simplified your code. It should work.
var serializer = new XmlSerializer(typeof(Obj));
using (XmlReader reader = XmlReader.Create(_xmlPath))
{
while (reader.ReadToFollowing("Obj"))
{
Obj obj = (Obj)serializer.Deserialize(reader);
}
}
If the actual xml has a more complex structure and this code doesn't work, let us know.
Related
I am currently serializing my XML objects like this:
public static string Serialize<T>(T value) {
XmlSerializer xsSubmit = new XmlSerializer(typeof(T));
using (var sww = new StringWriter())
{
using (XmlTextWriter writer = new XmlTextWriter(sww))
{
xsSubmit.Serialize(writer, value);
}
return sww.ToString();
}
}
However, I want some custom MetaData in my XML document:
<myXML>
<META>
<timeStamp>Sunday, November 11, 2020</timeStamp>
...
</META>
<DATA>
// Serialized Object
</DATA>
</myXML>
Is there anyway I can achieve this without manually building the whole document with something like XDocument, or adding fields to all of my objects?
There are many ways to do it.
For example
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConApp
{
public class Data
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Meta
{
[XmlElement("timeStamp")]
public DateTime Timestamp { get; set; }
// other meta properties
}
class Program
{
static void Main()
{
var data = new Data { Id = 5, Name = "Five" };
var meta = new Meta { Timestamp = DateTime.UtcNow };
var result = Serialize(data, meta);
Console.WriteLine(result);
}
public static string Serialize<T>(T value, Meta meta)
{
var metaSerializer = new XmlSerializer(typeof(Meta));
var typeSerializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings { Indent = true };
using (var stringWriter = new StringWriter())
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
xmlWriter.WriteStartElement("myXML");
metaSerializer.Serialize(xmlWriter, meta);
typeSerializer.Serialize(xmlWriter, value);
xmlWriter.WriteEndElement();
xmlWriter.Flush();
return stringWriter.ToString();
}
}
}
}
I have an XML as below:
<test-run>
<test-suite>
<test-suite>
<test-case id="1234" name="ABC" result="Passed">
</test-case>
</test-suite>
</test-suite>
</test-run>
This is an example XML file that I am using.
How to retrieve id,name and Result from this using C#?
Using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<Result> results = doc.Descendants("test-case").Select(x => new Result()
{
id = (string)x.Attribute("id"),
name = (string)x.Attribute("name"),
result = (string)x.Attribute("result")
}).ToList();
}
}
public class Result
{
public string id { get; set; }
public string name { get; set; }
public string result { get; set; }
}
}
I have an XML file full of events like this one with multiple statements to check.
How is this action even called? I'm so lost that I don't even know where to start looking.
<BENEvents>
<BENDescisionQ1 flagBEN_00="true" flagBEN_01="true" flagBEN_28="true" flagBEN_29="false">
<AskQuestions caption='Looking today again at you glass with milk you decide....'>
<Question event='DescisionQ1Yes'>Cowcostumes look great.</Question>
<Question event='DescisionQ1No'>Flatnesss is justice, so NO</Question>
</AskQuestions>
</BENDescisionQ1>
<BENDescisionQ2 ....>
.....
</BENDescisionQ2>
<BENEvents>
Please help to point me in the right direction.
EDIT: THe answer solved my question, thatnk you
This is how my code ended up for now to deal with more general events.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
using System.IO;
public class mllhildTestLinq : MonoBehaviour
{
public mllhildTestController controller;
public void QueryXML(string filename, string parentNode, GameObject listForDisplay)//(string[] args)
{
List<GeneralEvent> listEvents = new List<GeneralEvent>();
GeneralEvent GeneralEvents = new GeneralEvent();
listEvents = GeneralEvents.parse(filename, parentNode);
// just printing for testing
//Debug.Log("Is this shit getting here?");
int i = 0;
foreach (GeneralEvent newEvent in listEvents)
{
//Debug.Log(i);
listForDisplay.GetComponent<PrefabListButtoms>().AddNewButton(newEvent.nodeName, listForDisplay);
Debug.Log(newEvent.nodeName);
i++;
foreach (KeyValuePair<string, string> keyValuePair in newEvent.general)
{
Debug.Log(keyValuePair.Key + " " + keyValuePair.Value);
}
//for (int i = 0; i < newEvent.general.Count; i++)
//{
// controller.AddText(" key: " + newEvent.general[i].Key + " value: " + newEvent.general[i].Value);
//}
//controller.AddText("\n");
}
}
}
public class GeneralEvent
{
public static List<GeneralEvent> listEvents = new List<GeneralEvent>();
public string nodeName { get; set; }
public List<KeyValuePair<string, string>> general { get; set; }
//string patternNumber = #"\d+$";
string patternGeneral = #"[^\d]+[^\$]+";
public List<GeneralEvent> parse(string filename, string parentNode)
{
listEvents.Clear();
XElement generalEvents;
XDocument doc = XDocument.Load(filename);
try
{
generalEvents = doc.Descendants(parentNode).First();
//generalEvents = doc.Elements(parentNode).FirstOrDefault();
}
catch
{
generalEvents = null;
}
//XElement generalEvents = doc.Descendants(parentNode).FirstOrDefault();
if (generalEvents != null)
{
//Debug.Log("---------------------------------------------------------------------");
foreach (XElement descision in generalEvents.Elements())
{
GeneralEvent newEvent = new GeneralEvent();
listEvents.Add(newEvent);
//Debug.Log(descision.Name);
// newEvent.nodeName = string.Parse(Regex.Match(descision.Name.LocalName, patternGeneral).Value);
newEvent.nodeName = descision.Name.ToString();
newEvent.general = descision.Attributes()
.Select(x => new KeyValuePair<string, string>(Regex.Match(x.Name.LocalName, patternGeneral).Value, (string)x)).ToList();
}
}
else
{
Debug.Log("null");
}
return listEvents;
}
}
This is not a simple Xml Parse. See my Xml Linq solution using Regex
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
BenEvent benEvent = new BenEvent();
benEvent.parse(FILENAME);
}
}
public class BenEvent
{
public static List<BenEvent> listEvents = new List<BenEvent>();
public int number { get; set; }
public List<KeyValuePair<int, Boolean>> flags { get; set; }
public string question { get; set; }
public List<KeyValuePair<string, string>> answers { get; set; }
string patternNumber = #"\d+$";
string patternYesNo = #"[^\d]+$";
public void parse(string filename)
{
XDocument doc = XDocument.Load(filename);
XElement benEvents = doc.Descendants("BENEvents").FirstOrDefault();
foreach (XElement descision in benEvents.Elements())
{
BenEvent newEvent = new BenEvent();
listEvents.Add(newEvent);
newEvent.number = int.Parse(Regex.Match(descision.Name.LocalName, patternNumber).Value);
newEvent.flags = descision.Attributes()
.Select(x => new KeyValuePair<int, Boolean>(int.Parse(Regex.Match(x.Name.LocalName, patternNumber).Value), (Boolean)x)).ToList();
newEvent.question = (string)descision.Element("AskQuestions").Attribute("caption");
newEvent.answers = descision.Descendants("Question")
.Select(x => new KeyValuePair<string, string>(Regex.Match((string)x.Attribute("event"), patternYesNo).Value, (string)x)).ToList();
}
}
}
}
1.Xml file contains xml elements: "INSTITUTION" and "institution" and each xml element contains attributes like name,code and INN.
My code works fine if xml element name is:"INSTITUTION" and fails when it reaches to xml element name:"institution".
I found some solutions from stackoverflow but it didn't help me...
How can I ignore case sensitivity for xml deserialization?
<institutions>
<INSTITUTION name= "some_value" CODE="some_value" INN="some_value"/>
<INSTITUTION name= "some_value" CODE="some_value" INN="some_value"/>
<INSTITUTION name= "some_value" CODE="some_value" INN="some_value"/>
<institution name= "some_value" code="some_value" inn="some_value"/>
<institution name= "some_value" code="some_value" inn="some_value"/>
<institution name= "some_value" code="some_value" inn="some_value"/>
<institution name= "some_value" code="some_value" inn="some_value"/>
</institutions>
</treasury>
C# Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Test_for_finding_file_type.XmlSynonymDeserializer;
//This is the class that will be deserialized
[XmlRoot("treasury")]
public class Treasury
{
[XmlElement("institutions")]
public institutions Institutions { get; set; }
}
public class institutions
{
[XmlElement("INSTITUTION")]
public List<Institution> InstitutionList { get; set; }
}
public class Institution
{
[XmlAttribute("name")]
public string Name;
[XmlAttribute("CODE")]
public string Code;
[XmlAttribute("INN")]
public string Inn;
}
public class Program
{
public static void Main(String[] args)
{
Program pro = new Program();
pro.DeserializeObject("test.xml");
}
private void DeserializeObject(string filename)
{
Console.WriteLine("Reading with XML Reader");
XmlSerializer serializer = new XmlSerializer(typeof(Treasury));
FileStream fs = new FileStream(filename, FileMode.Open);
XmlReader reader = XmlReader.Create(fs);
Treasury treasuryAccounts;
treasuryAccounts = (Treasury)serializer.Deserialize(reader);
fs.Close();
Console.WriteLine("\n------------------------------------------Institutions---------------------------------------------------------\n");
foreach (var institition in treasuryAccounts.Institutions.InstitutionList)
{
Console.Write("Treasury Account Name:" + institition.Name
+ "\tCODE:" + institition.Code
+ "\tINN:" + institition.Inn
+ "\n\n"
);
}
Console.ReadKey();
}
}
The whole issue is the missing XmlRoot attribute. See code below :
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
[XmlRoot("treasury")]
public class Treasury
{
[XmlElement("institutions")]
public Institutions institutions { get; set; }
}
[XmlRoot("institutions")]
public class Institutions
{
[XmlElement("INSTITUTION")]
public List<Institution> InstitutionList { get; set; }
}
public class Institution
{
[XmlAttribute("name")]
public string Name;
[XmlAttribute("CODE")]
public string Code;
[XmlAttribute("INN")]
public string Inn;
}
public class Program
{
const string FILENAME = #"c:\temp\test.xml";
public static void Main(String[] args)
{
Program pro = new Program();
pro.DeserializeObject(FILENAME);
}
private void DeserializeObject(string filename)
{
Console.WriteLine("Reading with XML Reader");
XmlSerializer serializer = new XmlSerializer(typeof(Institutions));
XmlReader reader = XmlReader.Create(FILENAME);
Treasury treasuryAccounts = new Treasury();
treasuryAccounts.institutions = (Institutions)serializer.Deserialize(reader);
reader.Close();
Console.WriteLine("\n------------------------------------------Institutions---------------------------------------------------------\n");
foreach (var institition in treasuryAccounts.institutions.InstitutionList)
{
Console.Write("Treasury Account Name:" + institition.Name
+ "\tCODE:" + institition.Code
+ "\tINN:" + institition.Inn
+ "\n\n"
);
}
Console.ReadKey();
}
}
I have this below xml file:-
<?xml version="1.0" encoding="utf-8" ?>
<LoanProduct xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Program>
<ProgramID>6</ProgramID>
<Name>Primary Loan</Name>
<InterestRate>0.23</InterestRate>
<StartDate>2018-12-20</StartDate>
<EndDate>2019-03-31</EndDate>
</Program>
<Program>
<ProgramID>6</ProgramID>
<Name>Primary Loan</Name>
<InterestRate>0.25</InterestRate>
<StartDate>2019-04-1</StartDate>
<EndDate>2099-12-31</EndDate>
</Program>
</LoanProduct>
In my class file I have to read from xml file and run some query on it:-
String xml = Server.MapPath("/Resources/LoanProduct.xml");
DataSet dataSet = new DataSet();
dataSet.ReadXml(xml);
Suppose I want to retrieve where ProgramID= 6 and EndDate = '2099-12-31'
How can I achieve that?
You can achieve your desired result by using XDocument under the namespace System.Xml.Linq.
XDocument doc = XDocument.Load(#"Path to your xml file");
var ns = doc.Root.GetDefaultNamespace();
var result = (from program in doc.Descendants(ns + "Program")
where Convert.ToInt32(program.Element(ns + "ProgramID").Value) == 6 && program.Element(ns + "EndDate").Value == "2099-12-31"
select program).FirstOrDefault();
Output: (From Debugger)
You can use serialization. The date should be consistent otherwise you will get an error with this code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication3
{
class Program1
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(LoanProduct));
LoanProduct loanProduct = (LoanProduct)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "LoanProduct", Namespace = "")]
public class LoanProduct
{
[XmlElement("Program", Namespace = "")]
public List<Program> programs { get; set; }
}
[XmlRoot(ElementName = "Program", Namespace = "")]
public class Program
{
public int ProgramID { get; set; }
public string Name { get; set; }
public decimal InterestRate { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
}