How to execute a LINQ query while constructing an XDocument? - c#

I want to create a table that list the count of each file type. I've created a query to get that data. When I create the XDocument, how do I execute the query and create rows in the table with data from query?
var query = listFiles.GroupBy(f => Path.GetExtension(f).ToLower())
.Select(g => new
{
Extension = g.Key,
Count = g.Count(),
});
var doc = new XDocument(
new XElement("html",
new XElement("body",
new XElement("table", new XAttribute("border", 2),
foreach (var f in query)
{
new XElement("tr",
new XElement("td", f.Extension),
new XElement("td", f.Count));
}))));

Try following :
var doc = new XDocument(
new XElement("html",
new XElement("body",
new XElement("table", new object[] {
new XAttribute("border", 2),
query.Select(f =>
new XElement("tr",
new XElement("td", f.Extension),
new XElement("td", f.Count)))
}))));

Related

Liquid c# context initialize variable with T type

ITemplateContext ctx = new TemplateContext();
List<Orders> ProductList = new List<Orders> {
new Orders {OrderId = 1,ProductName="Some name",Quantity =30},
new Orders {OrderId = 1,ProductName="Some name1",Quantity =30},
new Orders {OrderId = 1,ProductName="Some name2",Quantity =30} };
ctx.DefineLocalVariable("context", new LiquidCollection(ProductList));
Define Liquid Collection with List throws error. Is it possible to define T type generic collection as ITemplateContext-> LocalVariable
ITemplateContext ctx = new TemplateContext();
List<Orders> ProductList = new List<Orders>
{
new Orders {OrderId = 1,ProductName="Some name",Quantity =30},
new Orders {OrderId = 1,ProductName="Some name1",Quantity =30},
new Orders {OrderId = 1,ProductName="Some name2",Quantity =30}
};
ctx.DefineLocalVariable("context", ProductList.ToLiquid());
Using using Liquid.NET.Utils;

How can I add XElement iterating elements?

This is my code:
var xml = new XElement("test", new[] {
new XElement("group", new[] {
new XElement("date", dateNow.ToString("dd/MM/yyyy HH:mm:ss"))
}),
new XElement("users", new[] {
foreach(var item in in PlaceHolderCustom.Controls)
{
new XElement("nome", ((TextBox)item.FindControl("myTextBox")).Text)
}
})
});
I'd like to set in the xml some fixed fields (within the element "group") and some that would iterate across a placeholder. But the syntax seems to be wrong when I try to add a new "iterating" list.
Where am I wrong?
Use linq .Select to perform the foreach. Also when you create the array the new [] {} syntax is valid only for new string[]. In your case use:
new XElement[] {}
Or because the method gets a params object[] you can just give each new XElement independently without wrapping with an array
So showing both ways of passing the collection of XElements:
var xml = new XElement("test",
new XElement("group", new XElement[] {
new XElement("date", dateNow.ToString("dd/MM/yyyy HH:mm:ss"))
}),
new XElement("users", PlaceHolderCustom.Control.Select(item =>
new XElement("nome", ((TextBox)item.FindControl("myTextBox")).Text)).ToArray())
);

LINQ-To-XML Query on Mulitple Identical Elements

I am fairly new to LINQ and XML and am trying to work with an existing large 500k line XML file which has the same structure as the XML below. I have figured out how to test for multiple null XElements but am totally stuck on how to search for multiple Identical XElements.
How do I get LINQ to return just contacts that work for google?
Thank you all in advanced.
void Main()
{
XDocument AddressBook = CreateAddressBookXML();
var query =
from contact in AddressBook.Descendants("Contact")
let companyelement = contact.Element("Company")
where companyelement != null
let companyname = companyelement.Descendants("CompanyName")
where companyname != null && companyname == "Google"
select contact;
Console.Write(query);
}
public XDocument CreateAddressBookXML() {
XDocument result =
new XDocument(
new XComment("My phone book"),
new XElement("phoneBook",
new XComment("My friends"),
new XElement("Contact",
new XAttribute("name", "Ralph"),
new XElement("homephone", "555-234-4567"),
new XElement("cellphone", "555-345-75656"),
new XElement("Company",
new XElement("CompanyName","Ralphs Web Design"),
new XElement("CompanyName","Google")
)
),
new XElement("Contact",
new XAttribute("name", "Dave"),
new XElement("homephone", "555-756-9454"),
new XElement("cellphone", "555-762-1546"),
new XElement("Company",
new XElement("CompanyName","Google")
)
),
new XComment("My family"),
new XElement("Contact",
new XAttribute("name", "Julia"),
new XElement("homephone", "555-578-1053"),
new XElement("cellphone", "")
),
new XComment("My team"),
new XElement("Contact",
new XAttribute("name", "Robert"),
new XElement("homephone", "555-565-1653"),
new XElement("cellphone", "555-456-2567"),
new XElement("Company",
new XElement("CompanyName","Yahoo")
)
)
)
);
return result;
}
var query = from contacts in CreateAddressBookXML().Root.Descendants("Contact")
where contacts.Element("Company") != null &&
contacts.Element("Company").Elements("CompanyName").
FirstOrDefault(c => c.Value == "Google") != null
select contacts;
I generally prefer to mix in a bit of XPath to write these queries, it's far more compact than the LINQ equivalent.
var query =
from contact in doc.XPathSelectElements("/phoneBook/Contact")
where contact.XPathSelectElements("Company/CompanyName[.='Google']").Any()
select contact;
Otherwise, using LINQ:
var query =
from contact in doc.Elements("phoneBook").Elements("Contact")
where contact.Elements("Company").Elements("CompanyName")
.Any(c => (string)c == "Google")
select contact;

How to add XElements dynamically in a loop?

I get an HybridDictionary with all the child XElements.
I don't know ahead how many items I have there.
So instead of doing this:
xmlDoc.Element("Parent").Add(
new XElement("Child", new XAttribute("Name", "Child1"),
new XElement("Id", "796"),
new XElement("Name", "gdsa")
etc..
));
I'm trying to do something like that:
Strung [] allKeys = new String[ChildElements.Count];
TheHybridDictionary.Keys.CopyTo(allKeys, 0);
xmlDoc.Element("Parent").Add(
new XElement("Child", new XAttribute("Name", "Child1"),
for (int i = 0; i < TheHybridDictionary.Count; i++)
new XElement(allKeys[i], TheHybridDictionary[allKeys[i]])
But how to connect whatever is inside the for loop to be part of the XML document construction?
Problem is, your HybridDictionary class does not implement IEnumerable, so you can't use LINQ on it directly.
But you can use allKeys string array instead:
string [] allKeys = new String[ChildElements.Count];
TheHybridDictionary.Keys.CopyTo(allKeys, 0);
xmlDoc.Element("Parent").Add(
new XElement("Child", new XAttribute("Name", "Child1"),
allKeys.Select(x => new XElement(x, TheHybridDictionary[x])))
You can use .Add() method as in Stefan's comment, or use LINQ:
xmlDoc.Element("Parent").Add(
new XElement("Child", new XAttribute("Name", "Child1"),
TheHybridDictionary.Select(kvp => new XElement(kvp.Key, kvp.Value)));

Linq to XML - From table to XDocument

I would like to generate an XDocument from my table (the structure is different) but I keep getting the following error :
LINQ to Entities does not recognize the method 'System.String ToString()' method.
I know this is caused by the Birthdate and I would need to use SqlFunctions.StringConvert but I'm working with Framework 4.0
Any ideas on how to solve that?
// Newsletter subscriptions
var news = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
new XElement("USER",
from n in _dc.Newsletter_Datas
where n.Timestamp >= startDate
select
new XElement("ROW",
new XElement("UTI", n.ID),
new XElement("FIRSTNAME", n.FirstName),
new XElement("FAMILYNAME", n.LastName),
new XElement("GENDER", n.Gender),
new XElement("BIRTHDATE", n.BirthDate != null ? n.BirthDate.Value.ToString("yyyy-MM-dd") : "2003-01-01"),
new XElement("LANGUAGE", n.Language),
new XElement("EMAIL", n.Email),
new XElement("STREETNAME", n.StreetName),
new XElement("HOUSENR", n.HouseNr),
new XElement("BOXNR", n.BoxNr),
new XElement("ZIPCODE", n.Zipcode),
new XElement("CITY", n.City),
new XElement("COUNTRY", n.Country),
new XElement("TS", n.Timestamp.ToString("yyyy-MM-dd hh:mm:ss")),
new XElement("MESSAGE_ID", "SCNEWS02"),
new XElement("OPT_INS",
new XElement("OPT_IN",
new XElement("OPT_IN_CBP", "01000000000"),
new XElement("OPT_IN_INSERT_TS", n.Timestamp.ToString("yyyy-MM-dd hh:mm:ss")),
new XElement("OPT_IN_METHOD", "1"),
new XElement("OPT_IN_TYPE", n.OptIn),
new XElement("OPT_IN_CHANNEL", "2"))))));
Thank you very much
Break your query into separate parts, the first part is the query itself. That will be handled by the entity framework. Then cast that query to an IEnumerable<NewsletterData> to finish it off using LINQ to objects. Entity Framework can't do more than a simple projection (which you are clearly not doing).
var query =
from n in _dc.Newsletter_Datas
where n.Timestamp >= startDate
select n;
var news = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
new XElement("USER",
from n in query.AsEnumerable() // LINQ to objects
select new XElement("ROW",
new XElement("UTI", n.ID),
new XElement("FIRSTNAME", n.FirstName),
new XElement("FAMILYNAME", n.LastName),
new XElement("GENDER", n.Gender),
new XElement("BIRTHDATE", n.BirthDate != null ? n.BirthDate.Value.ToString("yyyy-MM-dd") : "2003-01-01"),
new XElement("LANGUAGE", n.Language),
new XElement("EMAIL", n.Email),
new XElement("STREETNAME", n.StreetName),
new XElement("HOUSENR", n.HouseNr),
new XElement("BOXNR", n.BoxNr),
new XElement("ZIPCODE", n.Zipcode),
new XElement("CITY", n.City),
new XElement("COUNTRY", n.Country),
new XElement("TS", n.Timestamp.ToString("yyyy-MM-dd hh:mm:ss")),
new XElement("MESSAGE_ID", "SCNEWS02"),
new XElement("OPT_INS",
new XElement("OPT_IN",
new XElement("OPT_IN_CBP", "01000000000"),
new XElement("OPT_IN_INSERT_TS", n.Timestamp.ToString("yyyy-MM-dd hh:mm:ss")),
new XElement("OPT_IN_METHOD", "1"),
new XElement("OPT_IN_TYPE", n.OptIn),
new XElement("OPT_IN_CHANNEL", "2")
)
)
)
)
);

Categories

Resources