Cant add data to xml from list using linq - c#

This code doesn't work for me and I can't understand why.
xmlDoc.Element("results").Add(
new XElement("user",
new XAttribute("id", user.Id),
new XAttribute("facebookid", user.FacebookId),
new XAttribute("email", user.Email),
new XAttribute("totalpoints", totalpoints)
).Add(
user.Answers.Select(value => new XElement("question",
new XAttribute("id", value.QuestionId),
new XAttribute("answer_id", value.AnswerId),
new XAttribute("points", value.Points)))
)
);
I'm trying to create this
<results>
<user id="2323" facebookId="3254954795743957" email="david#gmail" totalPoints="">
<question id="1" answer_id="3" points="0" />
<question id="2" answer_id="1" points="1" />
</user>
</results>

xmlDoc.Element("results").Add(
new XElement("user",
new XAttribute("id", user.Id),
new XAttribute("facebookid", user.FacebookId),
new XAttribute("email", user.Email),
new XAttribute("totalpoints", totalpoints),
user.Answers.Select(value => new XElement(
"question",
new XAttribute("id", value.QuestionId),
new XAttribute("answer_id", value.AnswerId),
new XAttribute("points", value.Points)
))
)
);
The problem was that the Add method returns void so you can't continue with another Add over the void result. Also, for attributes you need to use XAttribute, not XElement.

Related

C# XElement how do I add different attributes in a specific order?

I have the following C# code to generate an XML document. The problem is that I need to swap the order of the attributes in the tag "CState". Therefore I have already tried several things. Unfortunately it does not work or I get an exception.
XNamespace ns = "http:dev.test.com/Job/Con";
XNamespace nsi = "http:www.w3.org/2001/XMLSchema-instance";
XElement doc = new XElement(ns + "CState", new XAttribute(XNamespace.Xmlns + "xsi", nsi),
new XElement(ns + "Page",
new XElement(ns + "Field", new XAttribute("dName", "MembershipNumber"), new XAttribute("type", "Text"), new XAttribute("value", "123456")),
new XElement(ns + "Field", new XAttribute("dName", "FirstName"), new XAttribute("type", "Text"), new XAttribute("value", "Michael")),
new XElement(ns + "Field", new XAttribute("dName", "LastName"), new XAttribute("type", "Text"), new XAttribute("value", "Hendly"))
));
This is the output in the XML file.
<?xml version="1.0" encoding="utf-8"?>
<CState xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance" xmlns="http:dev.test.com/Job/Con">
<Page>
<Field dName="MembershipNumber" type="Text" value="123456" />
<Field dName="FirstName" type="Text" value="Michael" />
<Field dName="LastName" type="Text" value="Hendly" />
</Page>
</ControlStatements>
However, the attributes should appear in a different order.
This is how the second line in the XML file is created (incorrect):
<CState xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance" xmlns="http:dev.test.com/Job/Con">
This is how the second line should be created in the XML file (correct):
<CState xmlns="http:dev.test.com/Job/Con" xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance">
How can I achieve this as easily as possible?

Issue creating XML doc from Dictionary

My intention is to iterate through my lovely dictionary (both key and value are strings) and create an xml file from it.
I get the error on the last line (saving the xml).
"InvalidOperationException was unhandled
Token EndDocument in state Document would result in an invalid XML document."
Looking through this using breakpoints it would seem that at reaching the end of this, only the initial bit (outside the for each loop) has been done..
I'm half asking what silly mistake I've made, I'm partly asking if there's a more eloquent way of doing this.
Sorry if I've missed anything, let me know if i have, will add.
XDocument xData = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"));
foreach (KeyValuePair<string, string> kvp in inputDictionary)
{
xData.Element(valuesName).Add(
new XElement(valuesName,
new XAttribute("key", kvp.Key),
new XAttribute("value", kvp.Value)));
}
xData.Save("C:\\xData.xml");
Currently you're adding multiple elements directly to the document - so you'd end up with either no root elements (if the dictionary is empty) or potentially multiple root elements (if there's more than one entry in the dictionary). You want a root element, and then your dictionary elements under that. Additionally, you're trying to find an element called valuesName without ever adding anything, so you'll actually get a NullReferenceException if there are any dictionary entries.
Fortunately, it's even easier than you've made it, because you can just use LINQ to transform your dictionary into a sequence of elements and put that in the doc.
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("root",
inputDictionary.Select(kvp => new XElement(valuesName,
new XAttribute("key", kvp.Key),
new XAttribute("value", kvp.Value)))));
doc.Save(#"c:\data.xml");
Complete sample app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
class Test
{
static void Main()
{
XName valuesName = "entry";
var dictionary = new Dictionary<string, string>
{
{ "A", "B" },
{ "Foo", "Bar" }
};
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("root",
dictionary.Select(kvp => new XElement(valuesName,
new XAttribute("key", kvp.Key),
new XAttribute("value", kvp.Value)))));
doc.Save("test.xml");
}
}
Output (order of entries is not guaranteed):
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root>
<entry key="A" value="B" />
<entry key="Foo" value="Bar" />
</root>
An alternative breakdown for this would be:
var elements = inputDictionary.Select(kvp => new XElement(valuesName,
new XAttribute("key", kvp.Key),
new XAttribute("value", kvp.Value)));
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("root", elements));
You may find this simpler to read.
try the following
XDocument xData = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"));
XElement myXml = new XElement("paramList");// make sure your root and your descendents do not shre same name
foreach (var entry in MyList)
{
myXml.Add(new XElement(valuesName,
new XElement("key", entry.key),
new XElement("value", entry.Value)
));
xData.Add(myXml);

C# XML - Help creating new tag with an ID?

I wish to create a file somewhat like this: http://pastebin.com/89kuK8h2
There is a tag, and in this example I got from MSDN, the customer tag also has a value and still ends in <\Customer>:
Customer CustomerID="HELLO"> // <---- This Line
I want to know how to do that
Currently I am creating tags like:
XmlNode xHeader = xDoc.CreateElement("Customer");
and appending like this:
xDoc.DocumentElement.AppendChild(xHeader);
xHeader.AppendChild(xCustomerID);
XDocument may be a way forward here, as its API is much simpler:
var root = new XDocument("Root",
new XElement("Customers"),
new XElement("Customer",
new XAttribute("CustomerID", "HELLO"),
new XElement("CompanyName", this.CompanyName),
new XElement("ContactName", this.ContactName),
new XElement("ContactTitle", this.ContactTitle),
new XElement("Phone", this.Phone),
new XElement("FullAddress",
new XElement("Address", "..."),
new XElement("Region", "...")
)
)
);
I suggest you to use LINQ to XML. It's easy to build your xml:
var xdoc = new XDocument(
new XElement("Root",
new XElement("Customers",
new XElement("Customer",
new XAttribute("CustomerID", "HELLO"),
new XElement("CompanyName", "Great Lakes Food Market"),
new XElement("ContactName", "Howard Snyder"),
new XElement("ContactTitle", "Marketing Managerr"),
new XElement("Phone", "(503) 555-7555"),
new XElement("FullAddress",
new XElement("Address", "2732 Baker Blvd."),
new XElement("City", "Eugene"),
new XElement("Region", "OR")
new XElement("PostalCode", "97403")
new XElement("Country", "USA")
)
)
)));
Suggested reading: Creating XML Trees in C# (LINQ to XML)

Adding elements to XDocument at runtime from DataTable

I am trying to generate an XML using XDocument by pulling data from a DataTable at runtime. I want to have the output in this format:
<Document>
<Alphabets>
<Data>
<Capital>AAA</Capital>
<Small>aaa</Small>
</Data>
</Alphabets>
<Language>
<Name>English</Name>
</Language>
<Alphabets>
<Data>
<Capital>BBB</Capital>
<Small>bbb</Small>
</Data>
</Alphabets>
<Language>
<Name>English</Name>
</Language>
</Document>
The Language element has to be present after every Alphabets element. I have tried very hard to achieve this but I am unable to put this Alphabets tag after every Language element. What I have achieved is this, where the Language element is falling inside Alphabets element:
<Document>
<Alphabets>
<Data>
<Capital>AAA</Capital>
<Small>aaa</Small>
</Data>
<Language>
<Name>English</Name>
</Language>
</Alphabets>
<Alphabets>
<Data>
<Capital>BBB</Capital>
<Small>bbb</Small>
</Data>
<Language>
<Name>English</Name>
</Language>
</Alphabets>
</Document>
Here is my code :
static void Main(string[] args)
{
DataTable dtAlpha = new DataTable("Alphabetss");
dtAlpha.Columns.Add("Capital", typeof(string));
dtAlpha.Columns.Add("Small", typeof(string));
dtAlpha.Rows.Add("AAA", "aaa");
dtAlpha.Rows.Add("BBB", "bbb");
XDocument doc = new XDocument(
new XDeclaration("1.0", "UTF-8", null),
new XElement("Document",
from row in dtAlpha.AsEnumerable()
select new XElement("Alphabets",
new XElement("Data",
new XElement("Capital", row.Field<string>("Capital")),
new XElement("Small", row.Field<string>("Small"))
),
new XElement("Language",
new XElement("Name", "English")
)))
);
Console.WriteLine(doc.ToString());
Console.ReadKey();
}
Please help me on this.
You can try this way :
XDocument doc = new XDocument(
new XDeclaration("1.0", "UTF-8", null),
new XElement("Document")
);
foreach(var row in dtAlpha.AsEnumerable())
{
var alphabets = new XElement("Alphabets",
new XElement("Data",
new XElement("Capital", row.Field<string>("Capital")),
new XElement("Small", row.Field<string>("Small"))
)
);
var language = new XElement("Language",
new XElement("Name", "English")
);
doc.Root.Add(alphabets);
doc.Root.Add(language);
}

Difficulty appending to XML file using Linq

I have an XML Document that looks like
<Settings>
<Config>
<type>stuff</type>
<length>stuff</length>
<ID>1</ID>
</Config>
</Settings>
I am attempting to append to it using
Document loadedDoc = XDocument.Load (file);
loadedDoc.Element("Settings").Add(new XElement("Config"),
new XElement("type", "stuff"),
new XElement("length", "stuff"),
new XElement("ID", "2"));
loadedDoc.Save(file);
What I am getting when I do this is
<Settings>
//the other configs hidden for readability
<Config /> <--- WHAT DO?! 0_o
<type>stuff</type>
<length>stuff</length>
<ID>2</ID>
</Settings>
Could someone better versed in linq tell me what it is I'm doing wrong to make it create an empty config element like that? Thanks!
You need to add the sub elements through the "Config" element's constructor, rather than through the "Settings" constructor:
loadedDoc.Element("Settings").Add(new XElement("Config",
new XElement("type", "stuff"),
new XElement("length", "stuff"),
new XElement("ID", "2")));
That's because you are appending to Settings, and not to Config
Try:
loadedDoc.Element("Settings").Add(
new XElement("Config",
new XElement("type", "stuff"),
new XElement("length", "stuff"),
new XElement("ID", "2")));
try this
XDocument loadedDoc = XDocument.Load(file);
loadedDoc.Element("Settings").Add(new XElement("Config"));
loadedDoc.Element("Settings").Element("Config").Add(
new XElement("type", "stuff"),
new XElement("length", "stuff"),
new XElement("ID", "2"));
loadedDoc.Save(file);

Categories

Resources