Task 485: .OSB File Format
Task 485: .OSB File Format
File Format Specifications for .OSC
The .OSC file format is the OpenStreetMap Change file format (OsmChange). It is an XML-based format used to describe differences (changes) between two versions of OpenStreetMap (.OSM) data dumps. It supports operations to create, modify, or delete map elements like nodes, ways, and relations. The format is text-based, with no binary header, and is often compressed (e.g., .osc.gz) for distribution. The structure is defined in the OpenStreetMap wiki and related documentation.
- List of all the properties of this file format intrinsic to its file system:
- Root element: osmChange
- Attributes:
- version: The API version (e.g., "0.6")
- generator: The name of the tool that generated the file (string, optional)
- Child elements (operations):
- create: Contains new elements to add
- modify: Contains existing elements to update
- delete: Contains elements to remove
- Within create, modify, or delete:
- node: Represents a point on the map
- Attributes:
- id: Unique identifier (integer)
- version: Version number (integer)
- changeset: Changeset ID (integer)
- timestamp: Timestamp of the change (string, ISO 8601 format)
- user: Username of the editor (string, optional)
- uid: User ID (integer, optional)
- lat: Latitude (float)
- lon: Longitude (float)
- Child elements:
- tag: Key-value metadata
- Attributes:
- k: Key (string)
- v: Value (string)
- way: Represents a line or area (sequence of nodes)
- Attributes: id, version, changeset, timestamp, user, uid (same as node, without lat/lon)
- Child elements:
- nd: Reference to a node in the way
- Attributes:
- ref: Node ID (integer)
- tag: (same as above)
- relation: Represents relationships between elements
- Attributes: id, version, changeset, timestamp, user, uid (same as way)
- Child elements:
- member: Reference to a member element
- Attributes:
- type: Type of member ("node", "way", or "relation")
- ref: Member ID (integer)
- role: Role in the relation (string, optional)
- tag: (same as above)
- Two direct download links for files of format .OSC:
- https://download.geofabrik.de/europe/albania-updates/000/000/001.osc.gz (Note: Gzipped; unzip to get .osc)
- https://download.geofabrik.de/europe/andorra-updates/000/000/001.osc.gz (Note: Gzipped; unzip to get .osc)
- Ghost blog embedded html javascript for drag n drop .OSC file to dump properties to screen:
Drag and drop .OSC file here
- Python class for .OSC file:
import xml.etree.ElementTree as ET
class OSCFile:
def __init__(self, filename):
self.filename = filename
self.tree = None
self.root = None
def read(self):
with open(self.filename, 'r') as f:
data = f.read()
self.tree = ET.ElementTree(ET.fromstring(data))
self.root = self.tree.getroot()
def print_properties(self):
if self.root is None:
print("No file loaded. Call read() first.")
return
def traverse(node, indent=''):
print(f"{indent}Element: {node.tag}")
for key, value in node.attrib.items():
print(f"{indent} - {key}: {value}")
for child in node:
traverse(child, indent + ' ')
traverse(self.root)
def write(self, new_filename):
if self.tree is None:
print("No file loaded. Call read() first.")
return
self.tree.write(new_filename, encoding='utf-8', xml_declaration=True)
# Example usage:
# osc = OSCFile('example.osc')
# osc.read()
# osc.print_properties()
# osc.write('new.osc')
- Java class for .OSC file:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
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 OSCFile {
private String filename;
private Document doc;
public OSCFile(String filename) {
this.filename = filename;
this.doc = null;
}
public void read() {
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
this.doc = dBuilder.parse(filename);
doc.getDocumentElement().normalize();
} catch (Exception e) {
e.printStackTrace();
}
}
public void printProperties() {
if (doc == null) {
System.out.println("No file loaded. Call read() first.");
return;
}
traverse(doc.getDocumentElement(), "");
}
private void traverse(Node node, String indent) {
System.out.println(indent + "Element: " + node.getNodeName());
if (node.hasAttributes()) {
for (int i = 0; i < node.getAttributes().getLength(); i++) {
Node attr = node.getAttributes().item(i);
System.out.println(indent + " - " + attr.getNodeName() + ": " + attr.getNodeValue());
}
}
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
traverse(child, indent + " ");
}
}
}
public void write(String newFilename) {
if (doc == null) {
System.out.println("No file loaded. Call read() first.");
return;
}
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(newFilename));
transformer.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
// Example usage:
// public static void main(String[] args) {
// OSCFile osc = new OSCFile("example.osc");
// osc.read();
// osc.printProperties();
// osc.write("new.osc");
// }
}
- Javascript class for .OSC file:
class OSCFile {
constructor(filename) {
this.filename = filename;
this.xmlDoc = null;
}
async read() {
const response = await fetch(this.filename);
const text = await response.text();
const parser = new DOMParser();
this.xmlDoc = parser.parseFromString(text, 'text/xml');
}
printProperties() {
if (!this.xmlDoc) {
console.log('No file loaded. Call read() first.');
return;
}
function traverse(node, indent = '') {
console.log(`${indent}Element: ${node.tagName}`);
for (let attr of node.attributes) {
console.log(`${indent} - ${attr.name}: ${attr.value}`);
}
for (let child of node.children) {
traverse(child, indent + ' ');
}
}
traverse(this.xmlDoc.documentElement);
}
write(newFilename) {
if (!this.xmlDoc) {
console.log('No file loaded. Call read() first.');
return;
}
const serializer = new XMLSerializer();
const xmlStr = serializer.serializeToString(this.xmlDoc);
// For browser, use Blob to download
const blob = new Blob([xmlStr], {type: 'application/xml'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = newFilename;
a.click();
URL.revokeObjectURL(url);
}
}
// Example usage:
// const osc = new OSCFile('example.osc');
// await osc.read();
// osc.printProperties();
// osc.write('new.osc');
- C class for .OSC file (using libxml2 for XML parsing; assume libxml2 is included):
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
typedef struct {
const char* filename;
xmlDocPtr doc;
} OSCFile;
OSCFile* OSCFile_create(const char* filename) {
OSCFile* osc = (OSCFile*)malloc(sizeof(OSCFile));
osc->filename = filename;
osc->doc = NULL;
return osc;
}
void OSCFile_read(OSCFile* osc) {
osc->doc = xmlReadFile(osc->filename, NULL, 0);
if (osc->doc == NULL) {
printf("Failed to parse %s\n", osc->filename);
}
}
void traverse(xmlNode* node, const char* indent) {
printf("%sElement: %s\n", indent, node->name);
xmlAttr* attr = node->properties;
while (attr) {
printf("%s - %s: %s\n", indent, attr->name, xmlNodeGetContent(attr->children));
attr = attr->next;
}
xmlNode* child = node->children;
char newIndent[256];
snprintf(newIndent, sizeof(newIndent), "%s ", indent);
while (child) {
if (child->type == XML_ELEMENT_NODE) {
traverse(child, newIndent);
}
child = child->next;
}
}
void OSCFile_print_properties(OSCFile* osc) {
if (osc->doc == NULL) {
printf("No file loaded. Call read first.\n");
return;
}
xmlNode* root = xmlDocGetRootElement(osc->doc);
traverse(root, "");
}
void OSCFile_write(OSCFile* osc, const char* newFilename) {
if (osc->doc == NULL) {
printf("No file loaded. Call read first.\n");
return;
}
xmlSaveFormatFileEnc(newFilename, osc->doc, "UTF-8", 1);
}
void OSCFile_destroy(OSCFile* osc) {
if (osc->doc) xmlFreeDoc(osc->doc);
free(osc);
}
// Example usage:
// int main() {
// OSCFile* osc = OSCFile_create("example.osc");
// OSCFile_read(osc);
// OSCFile_print_properties(osc);
// OSCFile_write(osc, "new.osc");
// OSCFile_destroy(osc);
// return 0;
// }