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);
Related
I have the following code:
XNamespace testNM = "urn:lst-emp:emp";
XDocument xDoc;
string path = "project_data.xml";
if (!File.Exists(path))
{
xDoc = new XDocument(
new XDeclaration("1.0", "UTF-16", null),
new XElement(testNM + "Test")
);
}
else
{
xDoc = XDocument.Load(path);
}
var element = new XElement("key",
new XElement("Type", type),
new XElement("Value", value));
xDoc.Element(testNM + "Test").Add(element);
// Save to Disk
xDoc.Save(path);
which produces an output in the XML file like this:
<?xml version="1.0" encoding="utf-16"?>
<Test xmlns="urn:lst-emp:emp">
<key xmlns="">
<Type>String</Type>
<Value>somestring</Value>
</key>
</Test>
How can I get an output like this in the XML file instead?
<?xml version="1.0" encoding="utf-16"?>
<Tests xmlns="urn:lst-emp:emp">
<key name="someString">
<Type>String</Type>
<Value>somestring</Value>
</key >
</Tests>
Note its only the 3rd line that has changed in the XML file.
You can do it this way:
var element = new XElement("key",
new XAttribute("name", "someString"),
new XElement("Type", "type"),
new XElement("Value", "value"));
To provide a complete version of Bilyukov's answer, this should produce the output expected. Obviously substitute the "someString" static string with a variable populated as you wish. Changes include using XName.Get(string, string) to create the appropriate XName objects for the XElement constructors.
XNamespace testNM = "urn:lst-emp:emp";
XDocument xDoc;
string path = "project_data.xml";
if (!File.Exists(path))
{
xDoc = new XDocument(
new XDeclaration("1.0", "UTF-16", null),
new XElement(XName.Get("Tests", testNM.NamespaceName))
);
}
else
{
xDoc = XDocument.Load(path);
}
var element = new XElement(XName.Get("key", testNM.NamespaceName),
new XAttribute("name", "someString"),
new XElement("Type", type),
new XElement("Value", value));
xDoc.Element(XName.Get("Tests", testNM.NamespaceName)).Add(element);
// Save to Disk
xDoc.Save(path);
Your XML has default namespace. Descendants of the element where default namespace declared is considered in the same default namespace, unless it is explicitly declared with different namespace. That's why you need to use the same XNamespace for <key> element. :
var element = new XElement(testNM +"key",
new XAttribute("name", "someString"),
new XElement(testNM +"Type", type),
new XElement(testNM +"Value", value));
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)
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.
I have the following XElement:
<Assembly name="3">
<Component name="2" />
</Assembly>
I would like to get just the root element. <Assembly name="3"> I cant see any method which suits for me.
XElement.????? I cant find XElement.Root;
Does any clue?
You can try this in VB.NET
Dim elm as XElment = XElement.Parse(<Assembly name="3">
<Component name="2" />
</Assembly>)
Dim strName as string
strName = elm.AncestorsAndSelf.First.Name
Code in C#
XElement elm = XElement.Parse("<Assembly name='3'><Component name='2' /></Assembly>");
string name =elm.AncestorsAndSelf().First().Name;
You can get the root element this way :
XDocument.Root
Here is an example of implementation :
XDocument doc = new XDocument(
new XComment("This is a comment."),
new XElement("Pubs",
new XElement("Book",
new XElement("Title", "Artifacts of Roman Civilization"),
new XElement("Author", "Moreno, Jordao")
),
new XElement("Book",
new XElement("Title", "Midieval Tools and Implements"),
new XElement("Author", "Gazit, Inbar")
)
),
new XComment("This is another comment.")
);
Console.WriteLine(doc.Root.Name.ToString());
link : http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.root.aspx
You could call RemoveNodes on it... create a copy first if you need to preserve the original content for other reasons.
It's not really clear what you're trying to do with this. The element logically contains all its children - there's no concept of XElement.Root because an element "is itself". RemoveNodes will remove all the child nodes, but if you just want to get the name of the element, or its attributes, you can do that without changing the structure at all.
Copy the name & attributes to a new element;
var root = new XElement(el.Name, el.Attributes());
I'm trying to create a RSS 2.0 feed in ASP.NET C# with products to provide to Froogle.
The RSS feed should look like:
http://www.google.com/support/merchants/bin/answer.py?answer=160589&hl=en
I'm using the SyndicationFeed and SyndicationsItems to create the feed. But I'm having trouble adding the extra elements like g:image_link.
I try the extra elements like;
syndicationItem.ElementExtensions.Add(new XElement("image_link", product.ImageLink).CreateReader());
This works, but how can I add the namespace
xmlns:g="http://base.google.com/ns/1.0"
to the first RSS tag and use this for the extension elements?
Thank you
I just wrote something like this last week, as a matter of fact. I didn't have much time, so it's not optimized or pretty.
I used an XDocument, though.
static XDocument GetXDocument(List<GoogleProduct> googleProducts)
{
XNamespace gns = "http://base.google.com/ns/1.0";
XDocument document = new XDocument(
new XElement("rss",
new XAttribute("version", "2.0"),
new XAttribute(XNamespace.Xmlns + "g", gns),
new XElement("channel",
new XElement("title", "X Company Feed"),
new XElement("description", "X Description"),
new XElement("link", "http://www.somecompany.com/"),
from googleProduct in googleProducts
select new XElement("item",
new XElement("title", googleProduct.Title),
new XElement(gns + "brand", googleProduct.ProductRecommendedAttributes.Brand),
new XElement(gns + "manufacturer", googleProduct.ProductRecommendedAttributes.Manufacturer),
new XElement(gns + "condition", googleProduct.Condition),
new XElement("description", googleProduct.Description),
new XElement(gns + "id", googleProduct.ID),
from img in googleProduct.ProductRecommendedAttributes.ImageLinks
select new XElement(gns + "image_link", img),
new XElement("link", googleProduct.Link),
new XElement(gns + "price", googleProduct.Price.ToString("0.00")),
new XElement(gns + "product_type", googleProduct.ProductRecommendedAttributes.ProductType),
from pmt in googleProduct.ProductOptionalAttributes.PaymentAccepteds
select new XElement(gns + "payment_accepted", pmt)))));
//
return document;
}
(FYI: GoogleProduct is just a temporary mapper class I used)
It will generate a document along these lines
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>Blah Data Feed</title>
<description>Stuff from Blah</description>
<link>http://www.blah.com/shopping</link>
<item>
<title>Blah</title>
<g:brand>Blah</g:brand>
<g:manufacturer>Blah</g:manufacturer>
<g:condition>New</g:condition>
<description>blah blah</description>
<g:id>268</g:id>
<g:image_link>http://www.blah.com/shopping/images/PRODUCT/medium/268.jpg</g:image_link>
<link>http://www.blah.com/</link>
<g:price>1747.00</g:price>
<g:product_type>Blah Blah</g:product_type>
<g:payment_accepted>Cash</g:payment_accepted>
<g:payment_accepted>Check</g:payment_accepted>
<g:payment_accepted>Visa</g:payment_accepted>
<g:payment_accepted>Mastercard</g:payment_accepted>
</item>
<item>
<title>Blah</title>
<g:brand>Blah</g:brand>
<g:manufacturer>Blah</g:manufacturer>
<g:condition>New</g:condition>
<description>blah blah</description>
<g:id>269</g:id>
<g:image_link>http://www.blah.com/shopping/images/PRODUCT/medium/269.jpg</g:image_link>
<link>http://www.blah.com/</link>
<g:price>1103.00</g:price>
<g:product_type>blah blah</g:product_type>
<g:payment_accepted>Cash</g:payment_accepted>
<g:payment_accepted>Check</g:payment_accepted>
<g:payment_accepted>Visa</g:payment_accepted>
<g:payment_accepted>Mastercard</g:payment_accepted>
</item>
</channel>
</rss>
XElements have great namespace support. Create your first element like this:
XNamespace aw = "http://base.google.com/ns/1.0";
XElement root = new XElement(aw + "image_link", product.ImageLink);
This will give you XML like this:
<image_link xmlns="http://base.google.com/ns/1.0">
</image_link>
Each subsequent element should also use the same namespace. If you want to use namespace prefixes for your elements, it's a similar approach. You can check out some full examples on MSDN here:
How to: Create a Document with Namespaces