Task 685: .SRX File Format

Task 685: .SRX File Format

The .SRX file format refers to the SPARQL Query Results XML Format, an XML-based format standardized by the W3C for serializing results from SPARQL queries (variable bindings from SELECT queries or boolean results from ASK queries). It uses the namespace http://www.w3.org/2005/sparql-results#.

The properties (elements, attributes, and fields) intrinsic to the .SRX file format are as follows, based on its XML structure:

  • Root element: sparql (with namespace xmlns="http://www.w3.org/2005/sparql-results#"; optional xsi:schemaLocation attribute for validation).
  • head element: Contains metadata about query variables and optional links.
  • variable elements: Each with a required name attribute (string, e.g., "x") representing a query variable.
  • link elements: Each with a required href attribute (relative URI) linking to external metadata.
  • Either results element (for SELECT queries) or boolean element (for ASK queries):
  • results element: Contains zero or more result elements.
  • result element: Represents one query solution, containing zero or more binding elements.
  • binding element: With required name attribute (string matching a variable name); contains exactly one child: uri, literal, or bnode.
  • uri element: Text content is the URI string.
  • literal element: Text content is the literal string; optional xml:lang attribute (language tag) or datatype attribute (datatype URI).
  • bnode element: Text content is the blank node label (string).
  • boolean element: Text content is "true" or "false" (case-sensitive).

Two direct download links for example .SRX files:

Here is an embeddable HTML snippet with JavaScript for a Ghost blog (or any web page) that allows drag-and-drop of a .SRX file and dumps all properties to the screen (parses the XML and displays elements, attributes, and values in a readable format):

Drag and drop .SRX file here
  1. Here is a Python class for handling .SRX files (uses xml.etree.ElementTree for parsing/decoding; reads properties, prints them to console, and can write a sample .SRX file):
import xml.etree.ElementTree as ET

class SRXHandler:
    NS = '{http://www.w3.org/2005/sparql-results#}'

    def __init__(self, filename):
        self.filename = filename
        self.tree = None
        self.root = None

    def read_and_decode(self):
        self.tree = ET.parse(self.filename)
        self.root = self.tree.getroot()

    def print_properties(self):
        if not self.root:
            print("No file loaded.")
            return

        print(f"Root: sparql (schemaLocation: {self.root.get('{http://www.w3.org/2001/XMLSchema-instance}schemaLocation', 'none')})")

        head = self.root.find(f'{self.NS}head')
        if head is not None:
            print("Head:")
            for var in head.findall(f'{self.NS}variable'):
                print(f"  Variable name: {var.get('name')}")
            for link in head.findall(f'{self.NS}link'):
                print(f"  Link href: {link.get('href')}")

        results = self.root.find(f'{self.NS}results')
        if results is not None:
            print("Results:")
            for i, result in enumerate(results.findall(f'{self.NS}result'), 1):
                print(f"  Result {i}:")
                for binding in result.findall(f'{self.NS}binding'):
                    name = binding.get('name')
                    child = list(binding)[0]
                    value = child.text or ''
                    if child.tag == f'{self.NS}literal':
                        lang = child.get('{http://www.w3.org/XML/1998/namespace}lang', '')
                        datatype = child.get('datatype', '')
                        value += f" (lang: {lang}, datatype: {datatype})"
                    print(f"    Binding {name}: {child.tag.replace(self.NS, '')} = {value}")

        boolean = self.root.find(f'{self.NS}boolean')
        if boolean is not None:
            print(f"Boolean: {boolean.text}")

    def write_sample(self, output_filename):
        root = ET.Element('sparql', xmlns='http://www.w3.org/2005/sparql-results#')
        head = ET.SubElement(root, 'head')
        ET.SubElement(head, 'variable', name='x')
        results = ET.SubElement(root, 'results')
        result = ET.SubElement(results, 'result')
        binding = ET.SubElement(result, 'binding', name='x')
        ET.SubElement(binding, 'uri').text = 'http://example.org'
        tree = ET.ElementTree(root)
        tree.write(output_filename, encoding='utf-8', xml_declaration=True)

# Example usage:
# handler = SRXHandler('example.srx')
# handler.read_and_decode()
# handler.print_properties()
# handler.write_sample('output.srx')
  1. Here is a Java class for handling .SRX files (uses javax.xml.parsers for parsing/decoding; reads properties, prints them to console, and can write a sample .SRX file using Transformer):
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;

public class SRXHandler {
    private static final String NS = "http://www.w3.org/2005/sparql-results#";
    private String filename;
    private Document doc;

    public SRXHandler(String filename) {
        this.filename = filename;
    }

    public void readAndDecode() throws Exception {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        dbFactory.setNamespaceAware(true);
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        doc = dBuilder.parse(new File(filename));
        doc.getDocumentElement().normalize();
    }

    public void printProperties() {
        if (doc == null) {
            System.out.println("No file loaded.");
            return;
        }

        Element root = doc.getDocumentElement();
        System.out.println("Root: sparql (schemaLocation: " + root.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation") + ")");

        NodeList heads = root.getElementsByTagNameNS(NS, "head");
        if (heads.getLength() > 0) {
            Element head = (Element) heads.item(0);
            System.out.println("Head:");
            NodeList variables = head.getElementsByTagNameNS(NS, "variable");
            for (int i = 0; i < variables.getLength(); i++) {
                Element var = (Element) variables.item(i);
                System.out.println("  Variable name: " + var.getAttribute("name"));
            }
            NodeList links = head.getElementsByTagNameNS(NS, "link");
            for (int i = 0; i < links.getLength(); i++) {
                Element link = (Element) links.item(i);
                System.out.println("  Link href: " + link.getAttribute("href"));
            }
        }

        NodeList resultsList = root.getElementsByTagNameNS(NS, "results");
        if (resultsList.getLength() > 0) {
            Element results = (Element) resultsList.item(0);
            System.out.println("Results:");
            NodeList resultNodes = results.getElementsByTagNameNS(NS, "result");
            for (int i = 0; i < resultNodes.getLength(); i++) {
                Element result = (Element) resultNodes.item(i);
                System.out.println("  Result " + (i + 1) + ":");
                NodeList bindings = result.getElementsByTagNameNS(NS, "binding");
                for (int j = 0; j < bindings.getLength(); j++) {
                    Element binding = (Element) bindings.item(j);
                    String name = binding.getAttribute("name");
                    Element child = (Element) binding.getFirstChild().getNextSibling(); // Skip text nodes
                    String value = child.getTextContent();
                    String tag = child.getLocalName();
                    if (tag.equals("literal")) {
                        String lang = child.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang");
                        String datatype = child.getAttribute("datatype");
                        value += " (lang: " + (lang.isEmpty() ? "" : lang) + ", datatype: " + (datatype.isEmpty() ? "" : datatype) + ")";
                    }
                    System.out.println("    Binding " + name + ": " + tag + " = " + value);
                }
            }
        }

        NodeList booleans = root.getElementsByTagNameNS(NS, "boolean");
        if (booleans.getLength() > 0) {
            System.out.println("Boolean: " + booleans.item(0).getTextContent());
        }
    }

    public void writeSample(String outputFilename) throws Exception {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        dbFactory.setNamespaceAware(true);
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document newDoc = dBuilder.newDocument();
        Element root = newDoc.createElementNS(NS, "sparql");
        newDoc.appendChild(root);
        Element head = newDoc.createElementNS(NS, "head");
        root.appendChild(head);
        Element var = newDoc.createElementNS(NS, "variable");
        var.setAttribute("name", "x");
        head.appendChild(var);
        Element results = newDoc.createElementNS(NS, "results");
        root.appendChild(results);
        Element result = newDoc.createElementNS(NS, "result");
        results.appendChild(result);
        Element binding = newDoc.createElementNS(NS, "binding");
        binding.setAttribute("name", "x");
        result.appendChild(binding);
        Element uri = newDoc.createElementNS(NS, "uri");
        uri.setTextContent("http://example.org");
        binding.appendChild(uri);

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource source = new DOMSource(newDoc);
        StreamResult streamResult = new StreamResult(new File(outputFilename));
        transformer.transform(source, streamResult);
    }

    // Example usage:
    // public static void main(String[] args) throws Exception {
    //     SRXHandler handler = new SRXHandler("example.srx");
    //     handler.readAndDecode();
    //     handler.printProperties();
    //     handler.writeSample("output.srx");
    // }
}
  1. Here is a JavaScript class for handling .SRX files (uses DOMParser for browser or xml2js for Node.js; reads properties, prints them to console, and can write a sample .SRX string to console or file in Node.js):
class SRXHandler {
  constructor(filename) {
    this.filename = filename;
    this.xmlDoc = null;
  }

  async readAndDecode() {
    // For browser: assume file content is passed; for Node.js, use fs
    const fs = require('fs'); // Node.js only
    const content = fs.readFileSync(this.filename, 'utf8');
    const parser = new DOMParser(); // Browser; for Node, use xml2js or similar
    this.xmlDoc = parser.parseFromString(content, 'text/xml');
    if (this.xmlDoc.getElementsByTagName('parsererror').length > 0) {
      console.log('Error parsing XML.');
      return;
    }
  }

  printProperties() {
    if (!this.xmlDoc) {
      console.log('No file loaded.');
      return;
    }
    const NS = 'http://www.w3.org/2005/sparql-results#';
    const sparql = this.xmlDoc.getElementsByTagNameNS(NS, 'sparql')[0];
    console.log(`Root: sparql (schemaLocation: ${sparql.getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation') || 'none'})`);

    const head = sparql.getElementsByTagNameNS(NS, 'head')[0];
    if (head) {
      console.log('Head:');
      Array.from(head.getElementsByTagNameNS(NS, 'variable')).forEach(v => {
        console.log(`  Variable name: ${v.getAttribute('name')}`);
      });
      Array.from(head.getElementsByTagNameNS(NS, 'link')).forEach(l => {
        console.log(`  Link href: ${l.getAttribute('href')}`);
      });
    }

    const results = sparql.getElementsByTagNameNS(NS, 'results')[0];
    if (results) {
      console.log('Results:');
      Array.from(results.getElementsByTagNameNS(NS, 'result')).forEach((r, i) => {
        console.log(`  Result ${i + 1}:`);
        Array.from(r.getElementsByTagNameNS(NS, 'binding')).forEach(b => {
          const name = b.getAttribute('name');
          const child = b.firstElementChild;
          let value = child.textContent;
          if (child.tagName.endsWith('literal')) {
            const lang = child.getAttribute('xml:lang') || '';
            const datatype = child.getAttribute('datatype') || '';
            value += ` (lang: ${lang}, datatype: ${datatype})`;
          }
          console.log(`    Binding ${name}: ${child.localName} = ${value}`);
        });
      });
    }

    const boolean = sparql.getElementsByTagNameNS(NS, 'boolean')[0];
    if (boolean) {
      console.log(`Boolean: ${boolean.textContent}`);
    }
  }

  writeSample(outputFilename) {
    const xml = `<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
  <head>
    <variable name="x"/>
  </head>
  <results>
    <result>
      <binding name="x">
        <uri>http://example.org</uri>
      </binding>
    </result>
  </results>
</sparql>`;
    if (outputFilename) {
      const fs = require('fs'); // Node.js only
      fs.writeFileSync(outputFilename, xml);
    } else {
      console.log(xml);
    }
  }
}

// Example usage (Node.js):
// const handler = new SRXHandler('example.srx');
// await handler.readAndDecode();
// handler.printProperties();
// handler.writeSample('output.srx');
  1. Here is a C++ class for handling .SRX files (assumes use of TinyXML-2 library for parsing, as C++ has no built-in XML parser; include tinyxml2.h and link to tinyxml2; reads properties, prints them to console, and can write a sample .SRX file):
#include <iostream>
#include <fstream>
#include "tinyxml2.h"  // Assume TinyXML-2 is available: https://github.com/leethomason/tinyxml2

using namespace tinyxml2;

class SRXHandler {
private:
    std::string filename;
    XMLDocument doc;

public:
    SRXHandler(const std::string& fn) : filename(fn) {}

    bool readAndDecode() {
        if (doc.LoadFile(filename.c_str()) != XML_SUCCESS) {
            std::cout << "Error loading file." << std::endl;
            return false;
        }
        return true;
    }

    void printProperties() {
        XMLElement* sparql = doc.FirstChildElement("sparql");
        if (!sparql) {
            std::cout << "Invalid .SRX format." << std::endl;
            return;
        }
        const char* schemaLoc = sparql->Attribute("xsi:schemaLocation");
        std::cout << "Root: sparql (schemaLocation: " << (schemaLoc ? schemaLoc : "none") << ")" << std::endl;

        XMLElement* head = sparql->FirstChildElement("head");
        if (head) {
            std::cout << "Head:" << std::endl;
            for (XMLElement* var = head->FirstChildElement("variable"); var; var = var->NextSiblingElement("variable")) {
                std::cout << "  Variable name: " << var->Attribute("name") << std::endl;
            }
            for (XMLElement* link = head->FirstChildElement("link"); link; link = link->NextSiblingElement("link")) {
                std::cout << "  Link href: " << link->Attribute("href") << std::endl;
            }
        }

        XMLElement* results = sparql->FirstChildElement("results");
        if (results) {
            std::cout << "Results:" << std::endl;
            int i = 1;
            for (XMLElement* result = results->FirstChildElement("result"); result; result = result->NextSiblingElement("result"), ++i) {
                std::cout << "  Result " << i << ":" << std::endl;
                for (XMLElement* binding = result->FirstChildElement("binding"); binding; binding = binding->NextSiblingElement("binding")) {
                    const char* name = binding->Attribute("name");
                    XMLElement* child = binding->FirstChildElement();
                    std::string tag = child->Name();
                    std::string value = child->GetText() ? child->GetText() : "";
                    if (tag == "literal") {
                        const char* lang = child->Attribute("xml:lang");
                        const char* datatype = child->Attribute("datatype");
                        value += " (lang: " + std::string(lang ? lang : "") + ", datatype: " + std::string(datatype ? datatype : "") + ")";
                    }
                    std::cout << "    Binding " << name << ": " << tag << " = " << value << std::endl;
                }
            }
        }

        XMLElement* booleanElem = sparql->FirstChildElement("boolean");
        if (booleanElem) {
            std::cout << "Boolean: " << (booleanElem->GetText() ? booleanElem->GetText() : "") << std::endl;
        }
    }

    void writeSample(const std::string& outputFilename) {
        XMLDocument newDoc;
        XMLDeclaration* decl = newDoc.NewDeclaration();
        newDoc.InsertFirstChild(decl);
        XMLElement* root = newDoc.NewElement("sparql");
        root->SetAttribute("xmlns", "http://www.w3.org/2005/sparql-results#");
        newDoc.InsertEndChild(root);
        XMLElement* head = newDoc.NewElement("head");
        root->InsertEndChild(head);
        XMLElement* var = newDoc.NewElement("variable");
        var->SetAttribute("name", "x");
        head->InsertEndChild(var);
        XMLElement* results = newDoc.NewElement("results");
        root->InsertEndChild(results);
        XMLElement* result = newDoc.NewElement("result");
        results->InsertEndChild(result);
        XMLElement* binding = newDoc.NewElement("binding");
        binding->SetAttribute("name", "x");
        result->InsertEndChild(binding);
        XMLElement* uri = newDoc.NewElement("uri");
        uri->SetText("http://example.org");
        binding->InsertEndChild(uri);
        newDoc.SaveFile(outputFilename.c_str());
    }
};

// Example usage:
// int main() {
//     SRXHandler handler("example.srx");
//     if (handler.readAndDecode()) {
//         handler.printProperties();
//     }
//     handler.writeSample("output.srx");
//     return 0;
// }