90

I have a List<string> "sampleList" which contains

Data1
Data2
Data3...

The file structure is like

<file>
   <name filename="sample"/>
   <date modified ="  "/>
   <info>
     <data value="Data1"/> 
     <data value="Data2"/>
     <data value="Data3"/>
   </info>
</file>

I'm currently using XmlDocument to do this.

Example:

List<string> lst;
XmlDocument XD = new XmlDocument();
XmlElement root = XD.CreateElement("file");
XmlElement nm = XD.CreateElement("name");
nm.SetAttribute("filename", "Sample");
root.AppendChild(nm);
XmlElement date = XD.CreateElement("date");
date.SetAttribute("modified", DateTime.Now.ToString());
root.AppendChild(date);
XmlElement info = XD.CreateElement("info");
for (int i = 0; i < lst.Count; i++) 
{
    XmlElement da = XD.CreateElement("data");
    da.SetAttribute("value",lst[i]);
    info.AppendChild(da);
}
root.AppendChild(info);
XD.AppendChild(root);
XD.Save("Sample.xml");

How can I create the same XML structure using XDocument?

2
  • 8
    Please post the code you have written so far. People generally do not like to just write your code for you. Commented Jun 1, 2010 at 8:33
  • 5
    Agreed - this is actually extremely simple to do in a single statement, but just giving you the answer won't help you learn much. Commented Jun 1, 2010 at 8:37

2 Answers 2

204

LINQ to XML allows this to be much simpler, through three features:

  • You can construct an object without knowing the document it's part of
  • You can construct an object and provide the children as arguments
  • If an argument is iterable, it will be iterated over

So here you can just do:

void Main()
{
    List<string> list = new List<string>
    {
        "Data1", "Data2", "Data3"
    };

    XDocument doc =
      new XDocument(
        new XElement("file",
          new XElement("name", new XAttribute("filename", "sample")),
          new XElement("date", new XAttribute("modified", DateTime.Now)),
          new XElement("info",
            list.Select(x => new XElement("data", new XAttribute("value", x)))
          )
        )
      );

    doc.Save("Sample.xml");
}

I've used this code layout deliberately to make the code itself reflect the structure of the document.

If you want an element that contains a text node, you can construct that just by passing in the text as another constructor argument:

// Constructs <element>text within element</element>
XElement element = new XElement("element", "text within element");
Sign up to request clarification or add additional context in comments.

2 Comments

Note: If you have elements that need to have "inner text" you add them like so: new XElement("description","this is the inner text of the description element."); (similar to how you add attribute/value pairs)
Very nice approach. I strugled a moment how to add attributes and a linq-expression of elements at once. So if somebody is interested, I choose: new XElement("info", new object[] { new XAttribute("foo", "great"), new XAttribute("bar", "not so great") }.Concat(list.Select(x => new XElement("child", ...)))) With the appropriate line wraps, this looks quite ok again.
0

Using the .Save method means that the output will have a BOM, which not all applications will be happy with. If you do not want a BOM, and if you are not sure then I suggest that you don't, then pass the XDocument through a writer:

using (var writer = new XmlTextWriter(".\\your.xml", new UTF8Encoding(false)))
{
    doc.Save(writer);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.