I am having trouble with LINQ query for XML and can't solve
I am trying to extract the element values
Here is the XML
<response>
<make>DODGE</make>
<make>CHRYSLER</make>
<make>JEEP</make>
<make>RAM</make>
.......etc
</response>
Here is the code I have so far...
XElement parsedXml3 = XElement.Parse(xml3);
var query2 = from m in parsedXml3.Descendants("response")
select m.Elements("make").Select(e => e.Value);
List<string> ls = new List<string>();
foreach (var o in query2)
{
ls = o.ToList();
}
ls.Sort();
Thanks for your help - extended explanations would be great
Try This.
XElement parsedXml3 = XElement.Parse(xml3); //parse your xml string
There is no need to use parsedXml3.Descendants("response") because response is root node here
var makes= parsedXml3.Elements("make") //Get All make Elements
.Select(x=>x.Value).ToList(); //Select Value from make Element
//and Store in List<string>
makes.Sort();
foreach (var make in makes)
{
Console.WriteLine(make);
}
or you can modify your code to
XElement parsedXml3 = XElement.Parse(xml3);
var ls= (from m in parsedXml3.Descendants("make")
select m.Value).ToList();
//List<string> ls = new List<string>();
//foreach (var o in query2)
//{
// ls.Add(o);
//}
ls.Sort();
Related
I have 5 datasets coming from Database and have saved them in List like below:
var list1 = new List<Class1>
var list2 = new List<Class2>
var list3 = new List<Class3>
var list4 = new List<Class4>
var list5 = new List<Class5>
I need to convert all 5 lists into a csv file (excel type).
I can do this only for lis1 dataset as of now.
How can we merge all list and print the data in CSV?
The format of the csv file is as follows
Year,Make,Model,Length
1997,Ford,E350,2.35
2000,Mercury,Cougar,2.38
The following code shows how to implement it or you can use ready-made libraries.
public void WriteToCSV()
{
var csv = new StringBuilder();
foreach (var item in list1)
{
string line = "field1,field2,...";
csv.AppendLine(line);
line = string.Format("{0},{1},...",item.field1,...);
csv.AppendLine(line);
}
//.........................................
//.........................................
foreach (var item in list5)
{
string line = "field1,field2,...";
csv.AppendLine(line);
line = string.Format("{0},{1},...",item.field1,...);
csv.AppendLine(line);
}
string fileName = #"D:\WriteText.csv";
if (File.Exists(fileName))
System.IO.File.AppendAllText(fileName, csv.ToString());
else
System.IO.File.WriteAllText(fileName, csv.ToString());
}
I created a Yaml that looks like this:
Directories:
- ./Libraries:
- DLLList.yml
- ./Output:
- None
Now I deserialized that yaml into a list of Objects:
List<object> allDirectoriesList = new List<object>();
List<string> allFileNames = new List<string>();
using (var reader = new StringReader(File.ReadAllText("./FileConfig.yml")))
{
allDirectoriesList = deserializer.Deserialize<dynamic>(reader)["Directories"] as List<Object>;
}
foreach (var directory in allDirectoriesList)
{
var directoryAsDictionary = (Dictionary<object, object>)directory;
List<object> list = directoryAsDictionary.Select(kvp => kvp.Value).ToList();
IEnumerable<string> _fileList = list.Select(i => i.ToString());
List<string> fileList = _fileList.ToList<string>();
for (int i = 0; i < fileList.Count(); i++)
{
var x = (string)list[i];
}
}
directory is an object of type Dictionary where I converted it into a List in this part:
var directoryAsDictionary = (Dictionary<object, object>)directory;
List<object> list = directoryAsDictionary.Select(kvp => kvp.Value).ToList();
This list contains 1 object of type string, where the filename is stored. But I can't get these strings out of the objects. If I cast them, or convert them ToString(), I always get "System.Collections.Generic.List`1[System.Object]", but it has to be "DLLList.yml" in this case
Assuming you are using YamlDotNet:
List<object> allDirectoriesList = new List<object>();
using (var reader = new StringReader(File.ReadAllText("./FileConfig.yml")))
{
allDirectoriesList = new DeserializerBuilder().Build().Deserialize<dynamic>(reader)["Directories"] as List<object>;
}
foreach (var directory in allDirectoriesList)
{
var directoryAsDictionary = (Dictionary<object, object>)directory;
List<object> list = directoryAsDictionary.SelectMany(kvp => (List<object>)kvp.Value).ToList();
List<string> _fileList = list.Select(Convert.ToString).ToList();
foreach(var file in _fileList)
Console.WriteLine($"Item: {file} found in {Convert.ToString(directoryAsDictionary.Keys.First())}");
}
Basically you were trying to turn the dictionary value to a string, but it was a List. By using SelectMany, it can flatten all the lists into one and use that. There were a few redundant casts, which I've also removed. For future reference, try to make your structures as simple as possible and deserialise them into structs/classes - you'll find this a lot easier that way.
How to read the elements inside nested descendants in LINQ
My Xml file format
<SmPpProperties>
<PpProperties>
<Project Name="CEESI all 2" CreatedDate="2013-11-18T16:48:54.9452592+01:00" ModifiedDate="2013-11-18T16:48:57.2413905+01:00">
<NuclearSystem>Barium</NuclearSystem>
<TimeLine>
<Clip>
<FilePathFP>FPS\FP001D\Default-wp000-15Oct2012-105001.vxbin</FilePathFP>
</Clip>
</TimeLine>
</Project>
</PpProperties>
</SmPpProperties>
I am trying to use C # code as
var SmPpProperties
= from PpProperties in xmldoc.Descendants("PpProperties")
select new
{
from Project in xmldoc.Descendants("Project ")
select new {
*How to proceed*
var SmPpProperties = from poj in xmldoc.Descendants("Project")
select new {name = poj.Attribute("Name"),
filePath = poj.Element("TimeLine").Element("Clip").Element("FilePathFP").Value};
foreach (var item in SmPpProperties)
{
Console.WriteLine("Name = {0}, File Path = {1}", item.name, item.filePath);
}
I have an log file like this..
This is the segment 1
============================
<MAINELEMENT><ELEMENT1>10-10-2013 10:10:22.444</ELEMENT1><ELEMENT2>1111</ELEMENT2>
<ELEMENT3>Message 1</ELEMENT3></MAINELEMENT>
<MAINELEMENT><ELEMENT1>10-10-2013 10:10:22.555</ELEMENT1><ELEMENT2>1111</ELEMENT2>
<ELEMENT3>Message 2</ELEMENT3></MAINELEMENT>
This is the segment 2
============================
<MAINELEMENT><ELEMENT1>10-11-2012 10:10:22.444</ELEMENT1><ELEMENT2>2222</ELEMENT2>
<ELEMENT3>Message 1</ELEMENT3></MAINELEMENT>
<MAINELEMENT><ELEMENT1>10-11-2012 10:10:22.555</ELEMENT1><ELEMENT2>2222</ELEMENT2>
<ELEMENT3>Message 2</ELEMENT3></MAINELEMENT>
How can I read this into DataTable excluding the data This is the segment 1 and This is the segment 2 and ====== lines completely.
I would like to have the Datatable as with Columns as "ELEMENT1", "ELEMENT2", "ELEMENT3" and fill the details with the content between those tags in the order of print of line.
It should not change the sequence of the order of records in the table while inserting.
HtmlAgilityPack seems to be a good tool for what you need:
using HtmlAgilityPack;
class Program
{
static void Main(string[] args)
{
var doc = new HtmlDocument();
doc.Load("log.txt");
var dt = new DataTable();
bool hasColumns = false;
foreach (HtmlNode row in doc
.DocumentNode
.SelectNodes("//mainelement"))
{
if (!hasColumns)
{
hasColumns = true;
foreach (var column in row.ChildNodes
.Where(node => node.GetType() == typeof(HtmlNode)))
{
dt.Columns.Add(column.Name);
}
}
dt.Rows.Add(row.ChildNodes
.Where(node => node.GetType() == typeof(HtmlNode))
.Select(node => node.InnerText).ToArray());
}
}
}
could do this, where stringData is the data from the file you have
var array = stringData.Split(new[] { "============================" }, StringSplitOptions.RemoveEmptyEntries);
var document = new XDocument(new XElement("Root"));
foreach (var item in array)
{
if(!item.Contains("<"))
continue;
var subDocument = XDocument.Parse("<Root>" + item.Substring(0, item.LastIndexOf('>') + 1) + "</Root>");
foreach (var element in subDocument.Root.Descendants("MAINELEMENT"))
{
document.Root.Add(element);
}
}
var table = new DataTable();
table.Columns.Add("ELEMENT1");
table.Columns.Add("ELEMENT2");
table.Columns.Add("ELEMENT3");
var rows =
document.Descendants("MAINELEMENT").Select(el =>
{
var row = table.NewRow();
row["ELEMENT1"] = el.Element("ELEMENT1").Value;
row["ELEMENT2"] = el.Element("ELEMENT2").Value;
row["ELEMENT3"] = el.Element("ELEMENT3").Value;
return row;
});
foreach (var row in rows)
{
table.Rows.Add(row);
}
foreach (DataRow dataRow in table.Rows)
{
Console.WriteLine("{0},{1},{2}", dataRow["ELEMENT1"], dataRow["ELEMENT2"], dataRow["ELEMENT3"]);
}
I'm not so sure where you problem is.
You can use XElement for reading the xml and manually creating DataTable.
For Reading the XML See Xml Parsing using XElement
Then you can create dynamically the datatable.
Heres an example of creating a datatable in code
https://sites.google.com/site/bhargavaclub/datatablec
But why do you want to use a DataTable ? There are a lot of downsides...
I am trying to get the child nodes in my xml file and print it out..however i cannot. It is just printing one element instead of all. please help.
XDocument doc = XDocument.Load(GlobalClass.GlobalUrl);
XElement xelement = XElement.Load(GlobalClass.GlobalUrl);
var query = from nm in xelement.Elements("EmployeeFinance")
where (int)nm.Element("EmpPersonal_Id") == empID
select new AllowancePaid
{
Income_ID = (decimal)nm.Element("Allowance-Grade")
.Element("Amount")
};
var x = query.ToList();
foreach (var ele in x) {
Debug.WriteLine(ele.Income_ID);
}
My XML File
<EmployeeFinance>
<EmployeeEmploy_Id>4891</EmployeeEmploy_Id>
<EmpPersonal_Id>28407</EmpPersonal_Id>
<Employee_Number>11715</Employee_Number>
<Allowance-Grade>
<Amount BenListID="32">6000.00</Amount>
<Amount BenListID="59">100000.00</Amount>
</Allowance-Grade>
</EmployeeFinance>
Adding the elements
var result = from element in doc.Descendants("EmployeeFinance")
where int.Parse(element.Element("EmpPersonal_Id").Value) == tt.Employee_Personal_InfoEmp_id
select element;
foreach (var ele in result)
{
ele.Element("Allowance-Grade")
.Add(new XElement("Amount", new XAttribute("BenListID", tt.ID), tt.Amount));
doc.Save(GlobalClass.GlobalUrl);
}
problem is you selecting one amount node .Element("Amount") but there are many nodes. Change it to .Elements("Amount") and need to change few places. I haven't tested but logic should something like below will work
`
var query = from nm in xelement.Elements("EmployeeFinance")
where (int)nm.Element("EmpPersonal_Id") == empID
select new AllowancePaid
{
AllowanceList = nm.Element("Allowance-Grade").Elements("Amount").Select( a=>(decimal)a.Value).ToList()
};
foreach (var ele in query) {
foreach (var a in ele.AllowanceList) {
Debug.WriteLine(a);
}
}
XDocument xelement = XDocument.Parse(xml);
var query = from nm in xelement.Elements("EmployeeFinance")
where (int)nm.Element("EmpPersonal_Id") == 28407
select new
{
Amounts = nm.Element("Allowance-Grade")
.Elements("Amount")
.Select(
row =>
new {
id = row.Value
}
).ToList()
};
var x = query.ToList();
foreach (var ele in x)
{
foreach(var a in ele.Amounts)
Console.WriteLine(a);
}