Task 841: .XPL File Format
Task 841: .XPL File Format
The .XPL file format refers to the XML Pipeline Language (XProc) as defined by the W3C specification for XProc: An XML Pipeline Language. This format is used to describe sequences of operations on XML documents. It is fundamentally an XML-based format with the media type application/xproc+xml and the typical file extension .xpl. The following is a comprehensive list of intrinsic properties based on the format's specification, focusing on structural, syntactic, and semantic elements that define its composition and behavior within file systems and processing environments:
- Namespace: The primary namespace is
http://www.w3.org/ns/xproc(prefixp), with supporting namespaces includinghttp://www.w3.org/ns/xproc-step(prefixc) for step input/output andhttp://www.w3.org/ns/xproc-error(prefixerr) for error handling. - Version: Specified via the
versionattribute on top-level elements, typically set to "1.0". - Root Elements: One of
<p:pipeline>,<p:declare-step>, or<p:library>. - Key Structural Elements:
<p:input>: Defines input ports (attributes:port,primary,sequence,kind,select).<p:output>: Defines output ports (attributes:port,primary,sequence).<p:option>: Declares configurable options (attributes:name,required,select).<p:variable>: Declares variables (attributes:name,select).<p:with-option>: Sets option values (attributes:name,select,port).<p:with-param>: Passes parameters (attributes:name,select,port).<p:pipe>: Connects ports (attributes:step,port).<p:inline>: Embeds inline XML (attribute:exclude-inline-prefixes).<p:document>: References external documents (attribute:href).<p:data>: Handles non-XML data (attribute:href).<p:empty>: Represents empty input/output.<p:for-each>: Iterates over sequences.<p:viewport>: Processes node subsets (attribute:match).<p:choose>,<p:when>,<p:otherwise>: Conditional branching (attributes:testfor<p:when>).<p:try>,<p:catch>: Error handling (attribute:codefor<p:catch>).<p:group>: Groups steps.<p:log>: Logs output (attributes:port,href).<p:serialization>: Controls output serialization (attributes:port, plus serialization options likemethod,encoding).<p:documentation>and<p:pipeinfo>: Metadata and annotations.- Core Attributes (applicable across elements):
name: Unique identifier (NCName).port: Port name (NCName).primary: Boolean indicating primary port status.sequence: Boolean for sequence handling.kind: "document" or "parameter".xpath-version: "1.0" or "2.0".psvi-required: Boolean for PSVI support.use-when: XPath for conditional inclusion.select: XPath for value selection.match: XSLT pattern for node matching.test: XPath for conditions.href: URI for resources.required: Boolean for mandatory options.type: QName for step types.exclude-inline-prefixes: List of prefixes to exclude.- Core Steps (built-in operations): Includes
p:identity,p:xslt,p:xinclude,p:load,p:store,p:http-request, and others for transformation, validation, and data manipulation. - Data Flow Properties: Ports support sequences; connections via pipes; automatic namespace fix-up; error propagation with dynamic/static distinctions.
- Serialization Properties: Controlled by options such as
method(e.g., "xml", "html"),encoding,indent,omit-xml-declaration. - Error Handling Properties: Static errors (e.g., syntax issues) and dynamic errors (e.g., runtime failures), with codes like
err:XS0001for cycles. - File System Intrinsic Aspects: As an XML format, it inherits XML properties like UTF-8/UTF-16 encoding, well-formedness requirements, and entity resolution. No binary headers; purely text-based with optional DTD or schema validation.
Two direct download links for example .XPL files (from public GitHub repositories hosting XProc pipelines):
- https://raw.githubusercontent.com/transpect/xproc-util/master/copy-files/xpl/copy-files.xpl
- https://raw.githubusercontent.com/transpect/xproc-util/master/recursive-directory-list/xpl/recursive-directory-list.xpl
The following is an HTML snippet with embedded JavaScript suitable for embedding in a Ghost blog post (or similar platform). It enables drag-and-drop functionality for a .XPL file, parses it as XML, and dumps the properties (as defined in task 1) to the screen by extracting and displaying key elements, attributes, and structural details.
- The following is a Python class for handling .XPL files. It uses the
xml.etree.ElementTreemodule to parse (decode/read), extract and print properties, and write a simple example .XPL file.
import xml.etree.ElementTree as ET
import os
class XPLHandler:
NS = '{http://www.w3.org/ns/xproc}'
def __init__(self, filepath):
self.filepath = filepath
self.tree = None
self.root = None
def read(self):
"""Parse and read the .XPL file."""
self.tree = ET.parse(self.filepath)
self.root = self.tree.getroot()
def print_properties(self):
"""Print all properties from the specification list."""
if not self.root:
raise ValueError("File not read yet.")
props = {
'namespace': self.root.nsmap.get('p', 'Not found'),
'version': self.root.get('version', 'Not specified'),
'root_element': self.root.tag.replace(self.NS, 'p:'),
'inputs': [el.get('port') for el in self.root.findall(f".//{self.NS}input")],
'outputs': [el.get('port') for el in self.root.findall(f".//{self.NS}output")],
'options': [el.get('name') for el in self.root.findall(f".//{self.NS}option")],
'variables': [el.get('name') for el in self.root.findall(f".//{self.NS}variable")],
'steps': [el.get('type') for el in self.root.findall(f".//*[@type]")],
# Additional properties can be extracted similarly
}
for key, value in props.items():
print(f"{key}: {value}")
def write_example(self, output_path):
"""Write a simple example .XPL file."""
root = ET.Element(self.NS + 'pipeline', attrib={'version': '1.0', 'xmlns:p': 'http://www.w3.org/ns/xproc'})
input_el = ET.SubElement(root, self.NS + 'input', {'port': 'source'})
output_el = ET.SubElement(root, self.NS + 'output', {'port': 'result'})
tree = ET.ElementTree(root)
tree.write(output_path, encoding='utf-8', xml_declaration=True)
# Example usage:
# handler = XPLHandler('example.xpl')
# handler.read()
# handler.print_properties()
# handler.write_example('new_example.xpl')
- The following is a Java class for handling .XPL files. It uses
javax.xml.parsersfor parsing (decode/read), extracting and printing properties, and writing a simple example .XPL file.
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;
import java.util.ArrayList;
import java.util.List;
public class XPLHandler {
private static final String NS = "http://www.w3.org/ns/xproc";
private Document doc;
public XPLHandler(String filepath) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
this.doc = builder.parse(new File(filepath));
}
public void printProperties() {
Element root = doc.getDocumentElement();
System.out.println("namespace: " + root.getNamespaceURI());
System.out.println("version: " + root.getAttribute("version"));
System.out.println("root_element: " + root.getLocalName());
List<String> inputs = getAttributeList("input", "port");
System.out.println("inputs: " + inputs);
List<String> outputs = getAttributeList("output", "port");
System.out.println("outputs: " + outputs);
List<String> options = getAttributeList("option", "name");
System.out.println("options: " + options);
List<String> variables = getAttributeList("variable", "name");
System.out.println("variables: " + variables);
// Additional properties can be added
}
private List<String> getAttributeList(String tag, String attr) {
List<String> list = new ArrayList<>();
NodeList nodes = doc.getElementsByTagNameNS(NS, tag);
for (int i = 0; i < nodes.getLength(); i++) {
Element el = (Element) nodes.item(i);
list.add(el.getAttribute(attr));
}
return list;
}
public void writeExample(String outputPath) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document newDoc = builder.newDocument();
Element root = newDoc.createElementNS(NS, "p:pipeline");
root.setAttribute("version", "1.0");
newDoc.appendChild(root);
Element input = newDoc.createElementNS(NS, "p:input");
input.setAttribute("port", "source");
root.appendChild(input);
Element output = newDoc.createElementNS(NS, "p:output");
output.setAttribute("port", "result");
root.appendChild(output);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(new DOMSource(newDoc), new StreamResult(new File(outputPath)));
}
// Example usage:
// public static void main(String[] args) throws Exception {
// XPLHandler handler = new XPLHandler("example.xpl");
// handler.printProperties();
// handler.writeExample("new_example.xpl");
// }
}
- The following is a JavaScript class for handling .XPL files (browser-compatible, using
DOMParserfor parsing). It reads viaFileReader, extracts and prints properties to console, and writes a simple example as a Blob for download.
class XPLHandler {
constructor() {
this.ns = 'http://www.w3.org/ns/xproc';
this.xmlDoc = null;
}
read(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
const parser = new DOMParser();
this.xmlDoc = parser.parseFromString(e.target.result, 'application/xml');
if (this.xmlDoc.getElementsByTagName('parsererror').length > 0) {
reject(new Error('Invalid XML'));
} else {
resolve();
}
};
reader.readAsText(file);
});
}
printProperties() {
if (!this.xmlDoc) throw new Error('File not read yet.');
const root = this.xmlDoc.documentElement;
console.log('namespace:', root.namespaceURI);
console.log('version:', root.getAttribute('version') || 'Not specified');
console.log('root_element:', root.localName);
const inputs = Array.from(this.xmlDoc.getElementsByTagNameNS(this.ns, 'input')).map(el => el.getAttribute('port'));
console.log('inputs:', inputs);
const outputs = Array.from(this.xmlDoc.getElementsByTagNameNS(this.ns, 'output')).map(el => el.getAttribute('port'));
console.log('outputs:', outputs);
const options = Array.from(this.xmlDoc.getElementsByTagNameNS(this.ns, 'option')).map(el => el.getAttribute('name'));
console.log('options:', options);
const variables = Array.from(this.xmlDoc.getElementsByTagNameNS(this.ns, 'variable')).map(el => el.getAttribute('name'));
console.log('variables:', variables);
// Additional properties can be logged similarly
}
writeExample() {
const xml = new DOMParser().parseFromString('<p:pipeline xmlns:p="http://www.w3.org/ns/xproc" version="1.0"></p:pipeline>', 'application/xml');
const input = xml.createElementNS(this.ns, 'p:input');
input.setAttribute('port', 'source');
xml.documentElement.appendChild(input);
const output = xml.createElementNS(this.ns, 'p:output');
output.setAttribute('port', 'result');
xml.documentElement.appendChild(output);
const serializer = new XMLSerializer();
const xmlStr = serializer.serializeToString(xml);
const blob = new Blob([xmlStr], { type: 'application/xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'new_example.xpl';
a.click();
URL.revokeObjectURL(url);
}
}
// Example usage:
// const handler = new XPLHandler();
// handler.read(selectedFile).then(() => handler.printProperties());
// handler.writeExample();
- The following is a C++ class for handling .XPL files. It uses the TinyXML2 library (assumed available; include via
#include <tinyxml2.h>) for parsing, extracting and printing properties, and writing a simple example .XPL file. Note: Compile with TinyXML2 linked.
#include <tinyxml2.h>
#include <iostream>
#include <string>
#include <vector>
class XPLHandler {
private:
tinyxml2::XMLDocument doc;
const char* ns = "http://www.w3.org/ns/xproc"; // Not directly used in TinyXML2, but for reference
public:
XPLHandler(const std::string& filepath) {
doc.LoadFile(filepath.c_str());
}
void printProperties() {
tinyxml2::XMLElement* root = doc.RootElement();
if (!root) {
std::cerr << "Error: Invalid XML." << std::endl;
return;
}
std::cout << "namespace: " << (root->Namespace() ? root->Namespace() : "Not found") << std::endl;
std::cout << "version: " << (root->Attribute("version") ? root->Attribute("version") : "Not specified") << std::endl;
std::cout << "root_element: " << root->Name() << std::endl;
std::vector<std::string> inputs;
for (tinyxml2::XMLElement* el = root->FirstChildElement("input"); el; el = el->NextSiblingElement("input")) {
inputs.push_back(el->Attribute("port") ? el->Attribute("port") : "");
}
std::cout << "inputs: ";
for (const auto& val : inputs) std::cout << val << " ";
std::cout << std::endl;
std::vector<std::string> outputs;
for (tinyxml2::XMLElement* el = root->FirstChildElement("output"); el; el = el->NextSiblingElement("output")) {
outputs.push_back(el->Attribute("port") ? el->Attribute("port") : "");
}
std::cout << "outputs: ";
for (const auto& val : outputs) std::cout << val << " ";
std::cout << std::endl;
// Similar for options, variables, etc.
}
void writeExample(const std::string& outputPath) {
tinyxml2::XMLDocument newDoc;
tinyxml2::XMLElement* root = newDoc.NewElement("p:pipeline");
root->SetAttribute("xmlns:p", ns);
root->SetAttribute("version", "1.0");
newDoc.InsertFirstChild(root);
tinyxml2::XMLElement* input = newDoc.NewElement("p:input");
input->SetAttribute("port", "source");
root->InsertEndChild(input);
tinyxml2::XMLElement* output = newDoc.NewElement("p:output");
output->SetAttribute("port", "result");
root->InsertEndChild(output);
newDoc.SaveFile(outputPath.c_str());
}
};
// Example usage:
// int main() {
// XPLHandler handler("example.xpl");
// handler.printProperties();
// handler.writeExample("new_example.xpl");
// return 0;
// }