tags:

views:

13863

answers:

7

I have a simple class that essentially just holds some values. I have overridden the ToString() method to return a nice string representation.

Now, I want to create a ToXml() method, that will return something like this:

<Song>
    <Artist>Bla</Artist>
    <Title>Foo</Title>
</Song>

Of course, I could just use a StringBuilder here, but I would like to return an XmlNode or XmlElement, to be used with XmlDocument.AppendChild.

I do not seem to be able to create an XmlElement other than calling XmlDocument.CreateElement, so I wonder if I have just overlooked anything, or if I really either have to pass in either a XmlDocument or ref XmlElement to work with, or have the function return a String that contains the XML I want?

+1  A: 

You need Linq - System.Xml.Linq to be precise.

You can create XML using XElement from scratch - that should pretty much sort you out.

Murph
+5  A: 

From W3C Document Object Model (Core) Level 1 specification (bold is mine):

Most of the APIs defined by this specification are interfaces rather than classes. That means that an actual implementation need only expose methods with the defined names and specified operation, not actually implement classes that correspond directly to the interfaces. This allows the DOM APIs to be implemented as a thin veneer on top of legacy applications with their own data structures, or on top of newer applications with different class hierarchies. This also means that ordinary constructors (in the Java or C++ sense) cannot be used to create DOM objects, since the underlying objects to be constructed may have little relationship to the DOM interfaces. The conventional solution to this in object-oriented design is to define factory methods that create instances of objects that implement the various interfaces. In the DOM Level 1, objects implementing some interface "X" are created by a "createX()" method on the Document interface; this is because all DOM objects live in the context of a specific Document.

AFAIK, you can not create any XmlNode (XmlElement, XmlAttribute, XmlCDataSection, etc) except XmlDocument from a constructor.

Moreover, note that you can not use XmlDocument.AppendChild() for nodes that are not created via the factory methods of the same document. In case you have a node from another document, you must use XmlDocument.ImportNode().

Panos
+13  A: 

I would recommend to use XDoc and XElement of System.Xml.Linq instead of XmlDocument stuff. This would be better and you will be able to make use of the LINQ power in querying and parsing your XML:

Using XElement, your ToXml() method will look like the following:

public XElement ToXml()
{
    XElement element = new XElement("Song",
                        new XElement("Artist", "bla"),
                        new XElement("Title", "Foo"));

    return element;
}
mnour
I think you meant: **instead of X_ml_Document**
JarrettV
+2  A: 

You may want to look at how you can use the built-in futures of .NET to serialize and deserilize an object into XML, rather than creating ToXML() method on every class that essentially just Data Transfer Object.

I have used these techniques successfully on a couple of projects but don’t have the implementation details handy right now. I will try to update my answer with my own examples sometime later.

Here's a couple of examples that Google returned:

XML Serialization in .NET by Venkat Subramaniam http://www.agiledeveloper.com/articles/XMLSerialization.pdf

How to Serialize and DeSerialize an object into XML http://www.dotnetfunda.com/articles/article98.aspx

Customize your .NET object XML serialization with .NET XML attributes http://blogs.microsoft.co.il/blogs/rotemb/archive/2008/07/27/customize-your-net-object-xml-serialization-with-net-xml-attributes.aspx

Vlad N
+2  A: 

You can't return an XmlElement or an XmlNode, because those objects always and only exist within the context of an owning XmlDocument.

XML serialization is a little easier than returning an XElement, because all you have to do is mark properties with attributes and the serializer does all the XML generation for you. (Plus you get deserialization for free, assuming you have a parameterless constructor and, well, a bunch of other things.)

On the other hand, a) you have to create an XmlSerializer to do it, b) dealing with collection properties isn't quite the no-brainer you might like it to be, and c) XML serialization is pretty dumb; you're out of luck if you want to do anything fancy with the XML you're generating.

In a lot of cases, those issues don't matter one bit. I for one would rather mark my properties with attributes than write a method.

Robert Rossney
+1  A: 

You could return an XmlDocument for the ToXML method in your class, then when you are going to add the Element with the result document just use something like:

XmlDocument returnedDocument = Your_Class.ToXML();

XmlDocument finalDocument = new XmlDocument();
XmlElement createdElement = finalDocument.CreateElement("Desired_Element_Name");
createdElement.InnerXML = docResult.InnerXML;
finalDocument.AppendChild(createdElement);

That way the entire value for "Desired_Element_Name" on your result XmlDocument will be the entire content of the returned Document.

I hope this helps.

someone
A: 

I got it, but the statement

XmlDocument returnedDocument = Your_Class.ToXML().

I´m getting the error

cannot implicity convert XElement in XmlDocument...

etoktar