Task 758: .UXF File Format
Task 758: .UXF File Format
1. List of Properties of the .UXF File Format
The .UXF file format is an XML-based structure designed for exchanging Unified Modeling Language (UML) models, primarily utilized by the UMLet tool. It is text-based, with no binary header or magic number, and relies on standard XML encoding (typically UTF-8). The intrinsic properties refer to the key structural elements and attributes that define the format's content. Based on analysis of the format's usage and examples, the following properties are identified as fundamental:
- Root Element:
diagram- Serves as the container for all diagram components. - Child Elements:
element- Represents individual UML components, such as states, relations, notes, or text blocks. - Common Attributes for
element(present in most or all elements): id: Unique identifier for the element (integer).x: Horizontal position coordinate (integer).y: Vertical position coordinate (integer).w: Width of the element (integer).h: Height of the element (integer).type: Specifies the UML element type (string, e.g., "initial", "state", "relation", "note").- Optional Attributes (dependent on the element type):
substates: Indicates if the element contains substates (boolean, e.g., "true").symbol: Defines a symbolic representation (string, e.g., "substate").lt: Line type for relations or connectors (string, e.g., ".", "-", "<<-").style: Styling parameters, such as coordinates for paths or "wordwrap" for text handling (string).bg: Background color (string, e.g., "red", "blue").name: Name of the element, used for states, classes, or use cases (string).entry: Entry action for states (string).exit: Exit action for states (string).valign: Vertical alignment (string, e.g., "top").customelement: Custom code or definition for the element (string).attr: Attributes section for class elements (string, potentially multiline).method: Methods section for class elements (string, potentially multiline).template: Template identifier for specialized elements (string).title: Title text for elements like synchronization bars (string).lw: Line width for graphical elements (integer).- Text Content: For certain types (e.g., "text", "note", "comment"), the element may contain plain text or structured content as CDATA or direct child text.
- Encoding and Versioning: Standard XML declaration (e.g.,
<?xml version="1.0" encoding="UTF-8"?>), with no explicit version attribute in the root.
These properties ensure the format's interoperability for UML diagrams, focusing on positional, typological, and stylistic data.
2. Direct Download Links for .UXF Files
- https://raw.githubusercontent.com/ReidHonan/UMLreader/master/Playschool Example 1.uxf
- https://raw.githubusercontent.com/aleph2c/umlet-statechart-template/master/Custom UML State Machine.uxf
3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .UXF File Dump
The following is a self-contained HTML snippet with embedded JavaScript suitable for embedding in a Ghost blog post. It enables users to drag and drop a .UXF file, parses the XML, and displays all properties (attributes and text content) of each element on the screen.
4. Python Class for .UXF File Handling
import xml.etree.ElementTree as ET
class UXFHandler:
def __init__(self, filename):
self.filename = filename
self.tree = None
self.root = None
self.read()
def read(self):
"""Reads and decodes the .UXF file."""
self.tree = ET.parse(self.filename)
self.root = self.tree.getroot()
def print_properties(self):
"""Prints all properties to console."""
if self.root.tag != 'diagram':
print("Invalid root element.")
return
for elem in self.root.findall('element'):
print(f"Element ID: {elem.get('id')}")
for key, value in elem.attrib.items():
print(f" {key}: {value}")
text = elem.text.strip() if elem.text else None
if text:
print(f" Text Content: {text}")
print()
def write(self, new_filename=None):
"""Writes the current structure back to a file."""
if not new_filename:
new_filename = self.filename
self.tree.write(new_filename, encoding='utf-8', xml_declaration=True)
def add_element(self, attributes, text=None):
"""Adds a new element for writing/modifying."""
new_elem = ET.SubElement(self.root, 'element')
for key, value in attributes.items():
new_elem.set(key, value)
if text:
new_elem.text = text
5. Java Class for .UXF File Handling
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;
import java.io.File;
public class UXFHandler {
private String filename;
private Document document;
public UXFHandler(String filename) {
this.filename = filename;
read();
}
public void read() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.parse(new File(filename));
} catch (Exception e) {
System.err.println("Error reading file: " + e.getMessage());
}
}
public void printProperties() {
if (!document.getDocumentElement().getTagName().equals("diagram")) {
System.out.println("Invalid root element.");
return;
}
NodeList elements = document.getElementsByTagName("element");
for (int i = 0; i < elements.getLength(); i++) {
Element elem = (Element) elements.item(i);
System.out.println("Element ID: " + elem.getAttribute("id"));
for (int j = 0; j < elem.getAttributes().getLength(); j++) {
String key = elem.getAttributes().item(j).getNodeName();
String value = elem.getAttributes().item(j).getNodeValue();
System.out.println(" " + key + ": " + value);
}
String text = elem.getTextContent().trim();
if (!text.isEmpty()) {
System.out.println(" Text Content: " + text);
}
System.out.println();
}
}
public void write(String newFilename) {
if (newFilename == null) {
newFilename = filename;
}
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new File(newFilename));
transformer.transform(source, result);
} catch (Exception e) {
System.err.println("Error writing file: " + e.getMessage());
}
}
public void addElement(java.util.Map<String, String> attributes, String text) {
Element newElem = document.createElement("element");
for (java.util.Map.Entry<String, String> entry : attributes.entrySet()) {
newElem.setAttribute(entry.getKey(), entry.getValue());
}
if (text != null) {
newElem.setTextContent(text);
}
document.getDocumentElement().appendChild(newElem);
}
}
6. JavaScript Class for .UXF File Handling
This implementation assumes a Node.js environment for file operations, using the xml2js library for parsing (install via npm install xml2js if needed).
const fs = require('fs');
const xml2js = require('xml2js');
class UXFHandler {
constructor(filename) {
this.filename = filename;
this.data = null;
this.read();
}
read() {
const xml = fs.readFileSync(this.filename, 'utf-8');
xml2js.parseString(xml, (err, result) => {
if (err) {
console.error('Error parsing XML:', err);
} else {
this.data = result;
}
});
}
printProperties() {
if (!this.data || !this.data.diagram) {
console.log('Invalid root element.');
return;
}
const elements = this.data.diagram.element || [];
elements.forEach((elem, index) => {
console.log(`Element ${index + 1} (id: ${elem.$.id}):`);
Object.keys(elem.$).forEach(key => {
console.log(` ${key}: ${elem.$[key]}`);
});
if (elem._) {
console.log(` Text Content: ${elem._.trim()}`);
}
console.log();
});
}
write(newFilename = this.filename) {
const builder = new xml2js.Builder({ renderOpts: { pretty: true, indent: ' ', newline: '\n' } });
const xml = builder.buildObject(this.data);
fs.writeFileSync(newFilename, xml);
}
addElement(attributes, text = null) {
if (!this.data.diagram.element) {
this.data.diagram.element = [];
}
const newElem = { $: attributes };
if (text) {
newElem._ = text;
}
this.data.diagram.element.push(newElem);
}
}
7. C++ Class for .UXF File Handling
This implementation uses the TinyXML-2 library for XML handling (include tinyxml2.h and link accordingly).
#include <iostream>
#include <string>
#include "tinyxml2.h"
class UXFHandler {
private:
std::string filename;
tinyxml2::XMLDocument doc;
public:
UXFHandler(const std::string& fn) : filename(fn) {
read();
}
void read() {
if (doc.LoadFile(filename.c_str()) != tinyxml2::XML_SUCCESS) {
std::cerr << "Error reading file." << std::endl;
}
}
void printProperties() {
tinyxml2::XMLElement* root = doc.FirstChildElement("diagram");
if (!root) {
std::cout << "Invalid root element." << std::endl;
return;
}
tinyxml2::XMLElement* elem = root->FirstChildElement("element");
int count = 1;
while (elem) {
std::cout << "Element " << count << " (id: " << elem->Attribute("id") << "):" << std::endl;
const tinyxml2::XMLAttribute* attr = elem->FirstAttribute();
while (attr) {
std::cout << " " << attr->Name() << ": " << attr->Value() << std::endl;
attr = attr->Next();
}
const char* text = elem->GetText();
if (text && std::string(text).find_first_not_of(" \t\n\r") != std::string::npos) {
std::cout << " Text Content: " << text << std::endl;
}
std::cout << std::endl;
elem = elem->NextSiblingElement("element");
++count;
}
}
void write(const std::string& newFilename = "") {
std::string outFile = newFilename.empty() ? filename : newFilename;
if (doc.SaveFile(outFile.c_str()) != tinyxml2::XML_SUCCESS) {
std::cerr << "Error writing file." << std::endl;
}
}
void addElement(const std::map<std::string, std::string>& attributes, const std::string& text = "") {
tinyxml2::XMLElement* root = doc.FirstChildElement("diagram");
if (!root) return;
tinyxml2::XMLElement* newElem = doc.NewElement("element");
for (const auto& pair : attributes) {
newElem->SetAttribute(pair.first.c_str(), pair.second.c_str());
}
if (!text.empty()) {
newElem->SetText(text.c_str());
}
root->InsertEndChild(newElem);
}
};