Retrieve fields in key value pair from XML using C# - c#

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; }
}
}

Related

How to resolve System.InvalidOperationException. Inaccessible due to its protection level. Only public types can be processed

I am trying to do an exercise about write and read data to file. The program have room, customer and hotel class and after i create object and give value for it, i try to serilize and write it to file in XML format but i encounter the exception above. I have try an example about this and it is running normally. Am i missing some declaration somewhere?
This is my XMLSerializer.cs:
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace Assignment7
{
class XMLSerializer
{
string filePath;
public XMLSerializer(string filePath)
{
this.filePath = filePath;
}
//This generic method serializes (writes) the object of generic data type to the file.
public string WriteXML<T>(T type)
{
StringBuilder feedback = new StringBuilder();
feedback.AppendLine("Provided data is invalid!");
if (type == null)
return feedback.ToString();
//Here we define an XmlSerializer object
XmlSerializer xmlSerializer = new XmlSerializer(type.GetType());
//Here we define an XmlWriter object and define settings for it.
XmlWriter xmlWriter = XmlWriter.Create(filePath,
new XmlWriterSettings()
{
OmitXmlDeclaration = true,
//ConformanceLevel specifies the level of conformance
//(document, fragment, or automatic detection).
//The default is Document.
ConformanceLevel = ConformanceLevel.Auto,
Indent = true
});
//Here we serialize data to the file
xmlSerializer.Serialize(xmlWriter, type);
//Here we clos ehe stream
xmlWriter.Close();
FileInfo fileInfo = new FileInfo(filePath);
if (fileInfo.Exists)
{
feedback.Clear();
feedback.AppendLine(fileInfo.FullName + " exists? " + fileInfo.Exists + ". Current length: " + fileInfo.Length);
}
return feedback.ToString();
}
}
}
This is my Program.cs:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Asignment7
{
class Program
{
static void Main(string[] args)
{
string filePath = #"D:\Study\Windows\hotel.xml";
Room tulip = new Room("A01", "South", "Single", 20, "Small room suitable for 1 person.");
Room lily = new Room("A11", "North", "Double", 40, "Big room for couple.");
Room blossom = new Room("B01", "East", "President", 150, "Luxury experience room.");
ArrayList rooms = new ArrayList { tulip, lily, blossom };
Customer Cus1 = new Customer("Trung", "401 Voyrinkatu", "14/02", 1);
Customer Cus2 = new Customer("Viet", "52 Handel", "14/03", 3);
Customer Cus3 = new Customer("David", "50 Palosarentie", "28/02", 2);
ArrayList customers = new ArrayList { Cus1, Cus2, Cus3 };
Hotel hotel = new Hotel("Lion Head", "18-03-1999", "Korsholm 89, Vaasa", 50, rooms, customers);
XMLSerializer xmlSerializer = new XMLSerializer(filePath);
Console.WriteLine(xmlSerializer.WriteXML<Room>(tulip));
Console.ReadLine();
}
}
}
This is my Hotel.cs:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace Assignment7
{
[XmlRoot("hotel")]
class Hotel
{
[XmlElement("name")]
public string HotelName { get; set; }
[XmlElement("date")]
public string ConstructionDate { get; set; }
[XmlElement("address")]
public string Address { get; set; }
[XmlElement("staff")]
public int Staff { get; set; }
[XmlIgnore]
public ArrayList Rooms { get; set; }
[XmlIgnore]
public ArrayList Customers { get; set; }
public Hotel() { }
public Hotel(string name, string constructionDate, string address, int staff, ArrayList rooms, ArrayList customers)
{
this.HotelName = name;
this.ConstructionDate = constructionDate;
this.Address = address;
this.Staff = staff;
this.Rooms = rooms;
this.Customers = customers;
}
}
}
This is my Room.cs:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace Assignment7
{
[XmlRoot("room")]
class Room
{
[XmlElement("number")]
public string RoomNumber { get; set; }
[XmlElement("area")]
public string Area { get; set; }
[XmlElement("type")]
public string Type { get; set; }
[XmlElement("price")]
public double PricePerNight { get; set; }
[XmlElement("description")]
public string Description { get; set; }
public Room() { }
public Room(string roomNumber, string area, string type, double pricePerNight, string description)
{
this.RoomNumber = roomNumber;
this.Area = area;
this.Type = type;
this.PricePerNight = pricePerNight;
this.Description = description;
}
}
}
This is my Customer.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace Assignment7
{
[XmlRoot("customer")]
class Customer
{
[XmlElement("name")]
public string CustomerName
{
get; set;
}
[XmlElement("room")]
public string RoomNumber
{
get; set;
}
[XmlElement("arrival")]
public string ArrivalDate
{
get; set;
}
[XmlElement("length")]
public int LengthOfStay
{
get; set;
}
public Customer() { }
public Customer(string name, string roomNumber, string arrivalDate, int lengthOfStay)
{
this.CustomerName = name;
this.RoomNumber = roomNumber;
this.ArrivalDate = arrivalDate;
this.LengthOfStay = lengthOfStay;
}
}
}

How I can deserialize a System.Xml.Linq.XElement?

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.

Parsing XML metadata containing conditional statements with C# in Unity

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();
}
}
}
}

C#, Ignore case sensitivity for XML deserialization

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();
}
}

What will be the way to read xml here?

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; }
}
}

Categories