difficulty with GraphML deserialization

Topics: serialization
Jan 25, 2011 at 9:35 PM

I apologize in advance if this is a stupid question...

I have the following custom vertex class:

public class PositionableGraphVertex : IPositionable
    public int Id { get; private set; }

    public double X { get; set; }
    public double Y { get; set; }
    public double Z { get; set; }

    public PositionableGraphVertex(int id, double x, double y, double z)
        Id = id;
        X = x;
        Y = y;
        Z = z;

    public PositionableGraphVertex(int id)
        Id = id;

I am able to serialize this as follows:

myGraph.SerializeToGraphML(writer, v => v.Id.ToString(), myGraph.GetEdgeIdentity());

However, I am stumped as to how to deserialize it and reconstruct the vertices with the proper position information. I am doing the following, without expecting it to give me position information:

 myGraph1.DeserializeFromGraphML(reader, v => new PositionableGraphVertex(int.Parse(v)), (source, target, id) => new Edge<PositionableGraphVertex>(source, target));

This reconstructs the vertices with the correct Ids as expected, however, it also fills the X, Y, and Z properties incorrectly (I did not even expect it to do anything?). How should I call this to also get the position information (with correct data)?

In addition, why am I able to call SerializeToGraphML on an UndirectedGraph, but there is no corresponding DeserializeFromGraphML?

Jan 26, 2011 at 5:48 PM

After looking at the source code and playing with my own implementation a bit, it seems that this may be a bug (I have not yet tracked down the offending code, so I cannot be sure). When serializing the graph into the graphML document, the additional properties X, Y, and Z are appropriately added as <data> elements to the graphML, with the appropriate values. However, when deserializing, the values are not correctly reconstructed. For instance, with the following vertices:

var vertex1 = new PositionableGraphVertex(5, 0.0, 1.0, 0.0);
var vertex2 = new PositionableGraphVertex(6, 1.0, 1.0, 0.0);
var vertex3 = new PositionableGraphVertex(7, 0.0, 1.0, 1.0);
var vertex4 = new PositionableGraphVertex(8, 1.0, 1.0, 1.0);

I add these to the graph and serialize it. The GraphML looks just as expected (sample for vertex2):

<node id="6"><data key="xValue">1</data><data key="yValue">1</data><data key="zValue">0</data></node>

However, when I deserialize it, it has the values x=1.0, y=0.0, z=0.0.

In fact, all of my vertices have 0.0 for the y value, even though they all clearly have 1.0 in the original objects, and <data key="yValue">1</data> as an element in the GraphML. The X and Z values are reconstructed correctly. I have changed both the property names and the XmlAttribute names to see if there were some issue there, but the deserialization is always the same.

Oct 11, 2011 at 10:23 AM

I have same problem, have you solved in any way?

Apr 3, 2014 at 12:13 AM
Hey, I realize it has been awhile since this was posted, but I was still having trouble with it. I don't have a code fix (I'm of the same opinion that this is a bug, but I couldn't quite nail it down - there's some pretty obscure code around serialization). But I do have a relatively simple work around.

I noticed as I was examining the XML output by the GraphMLSerializer, that it was Deserializing properly after I would pretty-print the xml (I was using a Notepad++ plugin to make the XML easier to read). So, presuming that your full serialization code looks something like this:
using (XmlWriter writer = XmlWriter.Create(filename)) {
    myGraph.SerializeToGraphML(writer, v => v.Id.ToString(), myGraph.GetEdgeIdentity());
Try altering your XmlWriter so that it does some pretty-printing for you:
using (XmlWriter writer = XmlWriter.Create(filename, new XmlWriterSettings { Indent = true, WriteEndDocumentOnClose = false })) {
    myGraph.SerializeToGraphML(writer, v => v.Id.ToString(), myGraph.GetEdgeIdentity());
Deserialization should be just as you had it before.
I don't have a full explanation for the WriteEndDocumentOnClose, except that it avoided an exception for me.

Hope that helps somebody.