Task 276: .GXL File Format

Task 276: .GXL File Format

GXL File Format Specifications

The .GXL file format, known as Graph eXchange Language, is an XML-based standard designed for the exchange of graph data between tools. It supports typed, attributed, directed, ordered, and hypergraphs. The format is defined by a Document Type Definition (DTD) available at http://www.gupro.de/GXL/gxl-1.0.dtd (note that access to this resource may be restricted in some cases). The structure allows for representing graphs with nodes, edges, attributes, and complex data types. The format is open and extensible, facilitating interoperability in software engineering and graph-based applications.

  1. List of all the properties of this file format intrinsic to its file system:
  • The format is encoded in XML 1.0, with a typical header .
  • Optional DOCTYPE declaration referencing the DTD: .
  • Root element: , which may include an xmlns:xlink attribute for linking.
  • Child of : , with attributes id (required, CDATA), edgeids (boolean, default "false"), edgemode (enumerated: "defaultdirected", "directed", "undirected", "defaultundirected", default "defaultdirected"), hypergraph (boolean, default "false").
  • Child of : , with attribute id (required, ID).
  • Child of : , with attributes from (required, IDREF), to (required, IDREF), id (ID, optional depending on edgeids), fromorder (CDATA, optional), toorder (CDATA, optional), isdirected (boolean, optional).
  • Child of :  for hyperedges, with attribute id (ID, optional).
  • Child of : , with attributes target (IDREF, required), role (CDATA, optional), direction (enumerated: "in", "out", "none", optional).
  • Child of , , , , : , with attribute name (required, CDATA).
  • Child of : Value elements including  (content: "true" or "false"),  (content: integer value),  (content: floating point value),  (content: text),  (content: enumerated value),  (with xlink:href attribute),  (sequence of values),  (set of values),  (bag of values),  (tuple of values).
  • Additional elements:  for typing, with xlink:href attribute for referencing schemas.
  • The format supports nesting of value elements in , , ,  for complex data structures.
  • Intrinsic file system properties include text-based encoding (UTF-8 typical), no binary header or magic number (as it is XML), and file extension .gxl.
  1. Two direct download links for files of format .GXL:
  1. Ghost blog embedded HTML JavaScript for drag and drop .GXL file to dump properties:

The following is an embedded HTML and JavaScript code snippet suitable for integration into a Ghost blog post. It enables users to drag and drop a .GXL file, parses the XML, and displays the properties listed in section 1 on the screen.

Drag and drop a .GXL file here
  1. Python class for opening, decoding, reading, writing, and printing .GXL properties:

The following Python class uses the xml.etree.ElementTree library to handle .GXL files.

import xml.etree.ElementTree as ET

class GXLHandler:
    def __init__(self, filepath=None):
        self.filepath = filepath
        self.tree = None
        self.root = None
        if filepath:
            self.read(filepath)

    def read(self, filepath):
        self.tree = ET.parse(filepath)
        self.root = self.tree.getroot()
        if self.root.tag != 'gxl':
            raise ValueError("Invalid GXL file.")

    def print_properties(self):
        if not self.root:
            print("No file loaded.")
            return
        print("GXL Properties:")
        print("- Root element: gxl")
        graph = self.root.find('graph')
        if graph is not None:
            print("- Graph ID:", graph.attrib.get('id'))
            print("- Edge mode:", graph.attrib.get('edgemode'))
            print("- Edge IDs:", graph.attrib.get('edgeids'))
            print("- Hypergraph:", graph.attrib.get('hypergraph'))
        nodes = self.root.findall('.//node')
        print("- Number of nodes:", len(nodes))
        for node in nodes:
            print("  - Node ID:", node.attrib.get('id'))
        edges = self.root.findall('.//edge')
        print("- Number of edges:", len(edges))
        for edge in edges:
            print("  - Edge from:", edge.attrib.get('from'), "to:", edge.attrib.get('to'))
        attrs = self.root.findall('.//attr')
        print("- Attributes:")
        for attr in attrs:
            print("  - Name:", attr.attrib.get('name'), ", Value:", attr.text.strip() if attr.text else "")

    def write(self, filepath):
        if self.tree:
            self.tree.write(filepath, encoding='utf-8', xml_declaration=True)
        else:
            raise ValueError("No data to write.")

# Example usage:
# handler = GXLHandler('example.gxl')
# handler.print_properties()
# handler.write('output.gxl')
  1. Java class for opening, decoding, reading, writing, and printing .GXL properties:

The following Java class uses javax.xml.parsers for handling .GXL files.

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class GXLHandler {
    private Document doc;

    public GXLHandler(String filepath) throws Exception {
        read(filepath);
    }

    public void read(String filepath) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        doc = builder.parse(filepath);
        if (!doc.getDocumentElement().getTagName().equals("gxl")) {
            throw new IllegalArgumentException("Invalid GXL file.");
        }
    }

    public void printProperties() {
        if (doc == null) {
            System.out.println("No file loaded.");
            return;
        }
        System.out.println("GXL Properties:");
        System.out.println("- Root element: gxl");
        Element graph = (Element) doc.getElementsByTagName("graph").item(0);
        if (graph != null) {
            System.out.println("- Graph ID: " + graph.getAttribute("id"));
            System.out.println("- Edge mode: " + graph.getAttribute("edgemode"));
            System.out.println("- Edge IDs: " + graph.getAttribute("edgeids"));
            System.out.println("- Hypergraph: " + graph.getAttribute("hypergraph"));
        }
        NodeList nodes = doc.getElementsByTagName("node");
        System.out.println("- Number of nodes: " + nodes.getLength());
        for (int i = 0; i < nodes.getLength(); i++) {
            Element node = (Element) nodes.item(i);
            System.out.println("  - Node ID: " + node.getAttribute("id"));
        }
        NodeList edges = doc.getElementsByTagName("edge");
        System.out.println("- Number of edges: " + edges.getLength());
        for (int i = 0; i < edges.getLength(); i++) {
            Element edge = (Element) edges.item(i);
            System.out.println("  - Edge from: " + edge.getAttribute("from") + " to: " + edge.getAttribute("to"));
        }
        NodeList attrs = doc.getElementsByTagName("attr");
        System.out.println("- Attributes:");
        for (int i = 0; i < attrs.getLength(); i++) {
            Element attr = (Element) attrs.item(i);
            System.out.println("  - Name: " + attr.getAttribute("name") + ", Value: " + attr.getTextContent().trim());
        }
    }

    public void write(String filepath) throws Exception {
        if (doc == null) {
            throw new IllegalArgumentException("No data to write.");
        }
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer();
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(filepath);
        transformer.transform(source, result);
    }

    // Example usage:
    // public static void main(String[] args) throws Exception {
    //     GXLHandler handler = new GXLHandler("example.gxl");
    //     handler.printProperties();
    //     handler.write("output.gxl");
    // }
}
  1. JavaScript class for opening, decoding, reading, writing, and printing .GXL properties:

The following JavaScript class uses DOMParser for parsing and XMLSerializer for writing. Note that file reading requires a file input in a browser context.

class GXLHandler {
    constructor(file) {
        this.xmlDoc = null;
        if (file) {
            this.read(file);
        }
    }

    read(file) {
        const reader = new FileReader();
        reader.onload = (e) => {
            const parser = new DOMParser();
            this.xmlDoc = parser.parseFromString(e.target.result, 'text/xml');
            if (this.xmlDoc.documentElement.tagName !== 'gxl') {
                console.error('Invalid GXL file.');
            }
        };
        reader.readAsText(file);
    }

    printProperties() {
        if (!this.xmlDoc) {
            console.log('No file loaded.');
            return;
        }
        console.log('GXL Properties:');
        console.log('- Root element: gxl');
        const graph = this.xmlDoc.getElementsByTagName('graph')[0];
        if (graph) {
            console.log('- Graph ID:', graph.getAttribute('id'));
            console.log('- Edge mode:', graph.getAttribute('edgemode'));
            console.log('- Edge IDs:', graph.getAttribute('edgeids'));
            console.log('- Hypergraph:', graph.getAttribute('hypergraph'));
        }
        const nodes = this.xmlDoc.getElementsByTagName('node');
        console.log('- Number of nodes:', nodes.length);
        for (let node of nodes) {
            console.log('  - Node ID:', node.getAttribute('id'));
        }
        const edges = this.xmlDoc.getElementsByTagName('edge');
        console.log('- Number of edges:', edges.length);
        for (let edge of edges) {
            console.log('  - Edge from:', edge.getAttribute('from'), 'to:', edge.getAttribute('to'));
        }
        const attrs = this.xmlDoc.getElementsByTagName('attr');
        console.log('- Attributes:');
        for (let attr of attrs) {
            console.log('  - Name:', attr.getAttribute('name'), ', Value:', attr.textContent.trim());
        }
    }

    write() {
        if (!this.xmlDoc) {
            console.error('No data to write.');
            return;
        }
        const serializer = new XMLSerializer();
        return serializer.serializeToString(this.xmlDoc);
    }
}

// Example usage:
// const input = document.getElementById('fileInput'); // Assume <input type="file" id="fileInput">
// const file = input.files[0];
// const handler = new GXLHandler(file);
// handler.printProperties();
// const serialized = handler.write();
// // Save serialized to file using Blob or other method
  1. C class for opening, decoding, reading, writing, and printing .GXL properties:

Since C does not support classes natively, the following is a C++ class using TinyXML2 (a lightweight XML library; assume it is included in the environment). If pure C is required, a struct with functions can be used, but C++ is assumed here for "class".

#include <iostream>
#include <tinyxml2.h>

using namespace tinyxml2;

class GXLHandler {
private:
    XMLDocument doc;

public:
    GXLHandler(const char* filepath) {
        read(filepath);
    }

    void read(const char* filepath) {
        if (doc.LoadFile(filepath) != XML_SUCCESS) {
            std::cerr << "Failed to load file." << std::endl;
        }
        if (std::string(doc.RootElement()->Name()) != "gxl") {
            std::cerr << "Invalid GXL file." << std::endl;
        }
    }

    void printProperties() {
        if (doc.Error()) {
            std::cout << "No file loaded." << std::endl;
            return;
        }
        std::cout << "GXL Properties:" << std::endl;
        std::cout << "- Root element: gxl" << std::endl;
        XMLElement* graph = doc.RootElement()->FirstChildElement("graph");
        if (graph) {
            std::cout << "- Graph ID: " << graph->Attribute("id") << std::endl;
            std::cout << "- Edge mode: " << graph->Attribute("edgemode") << std::endl;
            std::cout << "- Edge IDs: " << graph->Attribute("edgeids") << std::endl;
            std::cout << "- Hypergraph: " << graph->Attribute("hypergraph") << std::endl;
        }
        int nodeCount = 0;
        for (XMLElement* node = doc.RootElement()->FirstChildElement("node"); node; node = node->NextSiblingElement("node")) {
            nodeCount++;
            std::cout << "  - Node ID: " << node->Attribute("id") << std::endl;
        }
        std::cout << "- Number of nodes: " << nodeCount << std::endl;
        int edgeCount = 0;
        for (XMLElement* edge = doc.RootElement()->FirstChildElement("edge"); edge; edge = edge->NextSiblingElement("edge")) {
            edgeCount++;
            std::cout << "  - Edge from: " << edge->Attribute("from") << " to: " << edge->Attribute("to") << std::endl;
        }
        std::cout << "- Number of edges: " << edgeCount << std::endl;
        std::cout << "- Attributes:" << std::endl;
        for (XMLElement* attr = doc.RootElement()->FirstChildElement("attr"); attr; attr = attr->NextSiblingElement("attr")) {
            std::cout << "  - Name: " << attr->Attribute("name") << ", Value: " << attr->GetText() << std::endl;
        }
    }

    void write(const char* filepath) {
        if (doc.SaveFile(filepath) != XML_SUCCESS) {
            std::cerr << "Failed to save file." << std::endl;
        }
    }
};

// Example usage:
// int main() {
//     GXLHandler handler("example.gxl");
//     handler.printProperties();
//     handler.write("output.gxl");
//     return 0;
// }