SaveGraphCore
    (
        IGraph graph,
        Stream stream
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(stream != null);
        AssertValid();

        GraphMLXmlDocument oGraphMLXmlDocument = new GraphMLXmlDocument(
            graph.Directedness == GraphDirectedness.Directed);

        String [] asEdgeAttributeNames = GetAttributeNames(graph, false);
        String [] asVertexAttributeNames = GetAttributeNames(graph, true);

        // Define the GraphML-attributes.

        const String VertexAttributeIDPrefix = "V-";
        const String EdgeAttributeIDPrefix = "E-";

        foreach (String sVertexAttributeName in asVertexAttributeNames)
        {
            oGraphMLXmlDocument.DefineGraphMLAttribute(false,
                VertexAttributeIDPrefix + sVertexAttributeName,
                sVertexAttributeName, "string", null);
        }

        foreach (String sEdgeAttributeName in asEdgeAttributeNames)
        {
            oGraphMLXmlDocument.DefineGraphMLAttribute(true,
                EdgeAttributeIDPrefix + sEdgeAttributeName,
                sEdgeAttributeName, "string", null);
        }

        // Add the vertices and their GraphML-attribute values.

        foreach (IVertex oVertex in graph.Vertices)
        {
            XmlNode oVertexXmlNode = oGraphMLXmlDocument.AppendVertexXmlNode(
                oVertex.Name);

            AppendGraphMLAttributeValues(oVertex, oGraphMLXmlDocument,
                oVertexXmlNode, asVertexAttributeNames,
                VertexAttributeIDPrefix);
        }

        // Add the edges and their GraphML-attribute values.

        foreach (IEdge oEdge in graph.Edges)
        {
            IVertex [] oVertices = oEdge.Vertices;

            XmlNode oEdgeXmlNode = oGraphMLXmlDocument.AppendEdgeXmlNode(
                oVertices[0].Name, oVertices[1].Name);

            AppendGraphMLAttributeValues(oEdge, oGraphMLXmlDocument,
                oEdgeXmlNode, asEdgeAttributeNames, EdgeAttributeIDPrefix);
        }

        oGraphMLXmlDocument.Save(stream);
    }