2

I'm wanting to offer a way to save work in an application. It is a sort of project functionality. The projects need to be serialized to XML. I've got DataContractSerializer generating the XML, but I need to be able to select a location in an XML file for it to serialize to instead of writing a complete file for itself since there will be multiple projects and I will need to be able to de/serialize these projects individually from a Projects XML file.

What I would like for XML:

<Projects>
    <Project>
        <ID>...</ID>
        <Name>...</Name>
        <LastEdited>...</LastEdited>
        ...
    </Project>
    <Project>...</Project>
    <Project>...</Project>
</Projects>

I would then serialize and deserialize based on the Project ID using Linq to XML to navigate the doc.

Any suggestions? Much thanks in advance.

Ethan
  • 628
  • 2
  • 6
  • 20

1 Answers1

1

Found a way to do this. It has its hitches but once you get everything included it works pretty smoothly.

To generate the XML:

DataContractSerializer ser = new DataContractSerializer(typeof(Project));
StringBuilder objectSB = new StringBuilder();
XmlWriter objectWriter = XmlWriter.Create(objectSB);
//I'm using this method in the object I want to serialize (hence the 'this')
ser.WriteObject(objectWriter, this);
objectWriter.Flush();

Then you can turn the StringBuilder into an XElement for Linq to XML with:

Xelement xProject = Xelement.Parse(objectSB.ToString());

For deserialization:

DataContractSerializer ser = new DataContractSerializer(typeof(Project));
Project project = (CoilProject)ser.ReadObject(xProject.CreateReader());

There are a few times when I edit the XML using Linq to XML without deserializing and reserializing. Due to the namespaces that the DataContractSerializer adds, this becomes necessary:

//place this somewhere in your project's namespace
public static class MyExtensions
{
    public static IEnumerable<XElement> ElementsAnyNS(this XElement source, string localName)
    {
        return source.Elements().Where(e => e.Name.LocalName == localName);
    }

    public static XElement ElementAnyNS(this XElement source, string localName)
    {
        return source.Elements().Where(e => e.Name.LocalName == localName).Select(e => e).Single();
    }
}

Those extension methods allow you to select one or many elements from the serialized object without worrying about namespace. I adapted these extension methods from Pavel Minaev's answer on Ignore namespaces in LINQ to XML.

Community
  • 1
  • 1
Ethan
  • 628
  • 2
  • 6
  • 20