-
Notifications
You must be signed in to change notification settings - Fork 0
ediarum
tl;dr: oXbytei does one thing and does it well: editing TEI documents. In contrast, ediarum is a full-fledged editing and publication environment. Metaphorically speaking: oXbytei is an highly configurable next generation speedboat from a flotilla of tools, while ediarum is a huge tanker fully loaded with fossils.
oXbytei has learned a lot from ediarum by TELOTA/BBAW. In an early phase, it even had dependencies on the ediarum.JAR component. However, oXbytei is based on a fundamentally different philosophy than ediarum. So let's compare them!
Ediarum is a full-fledged working environment, i.e., it intends to cover the whole workflow from transcribing manuscripts in a TEI editor, storing them in an XML database, generating indices and the apparatus, generating a print edition and deploying the digital edition to the web.
In contrast, oXbytei is simply an extension of the ≶oXygen/> editor. It supports TEI editing, and that's the only thing it does. But in this domain, it does an excellent job.
This entails freedom of choice in the to domains not covered.
You might think: "Lack of support is the real name of what you want to sell as freedom of choice!" True. However, this leads straight to the core of the design principle: Do one thing and do it well! aka the UNIX philosophy. This means: Further requirements are to be covered by other solutions. And: We can't know all your requirements in advance and thus do not have a valid concept of a full-fledged working environment.
So in the end, taking the oXbytei path, will lead you to an excellent collection of tools, each of them chosen to fit your requirements. You can focus on the tool that is required in the current phase of your project, and you gain momentum. Taking the ediarum path, means that you have to setup a so-called full-fledged working environment and adapt it in many aspects in order to cover your needs, and all this before you get your hands on your first TEI document. A flotilla of specialized agile boats, oXbytei amongst them, vs. the huge ediarum tanker.
Using oXbytei does not entail a decision, where your documents are stored, unlike ediarum, which forces you to have an eXist database. So, with oXbytei you have the freedom to choose the local file system, a webdav server, an eXist database, a shared web folder, or a version control system like git. <oXygen/> gives you excellent options to connect to all these storing and collaboration solutions and oXbytei does not constrain the options.
Here at SCDH, we advice digital edition projects to put TEI documents under version control with git because of its robustness against data loss and its unique collaboration features, but we do not force them in this direction by technical constraints.
How long will your edition be on the web? When you take the ediarum path: Are you sure that you can lift the weights of operating a server, of regularly updating the eXist-db instance and sometimes adjusting your special solutions to the requirements of the updates for the next 10 years or so? Looking for a solution that is operationally leaner a thus more sustainable on the long run?
Having the documents in an eXist-db like required by ediarum does not add any value to the problem of generating a print edition. This is about XSLT and LaTeX and––as is known––project-specific adaptions. No advantange of ediarum compared to self-contained solutions for generating PDF from TEI. The approach of generating PDF from HTML as ediarum sells can not provide results known from critical editions in print.
Similar about generating indices, registers etc.
If you are convinced of both, can go with the ediarum environment, but use oXbytei as the <oXygen/> framework instead of setting up ediarum.BASE.edit.
Let's compare ediarum.BASE.edit, which is the <oXygen/> part of ediarum on the one hand and oXbytei on the other. Both are <oXygen/> frameworks, i.e., extensions for the awesome author mode of the XML Editor, which gives you a MSWord-like editing feeling, where you can work on your text without the triangle brackets in the way. Both are designed for editing TEI files. Both support editing register files like a personography or a register of geographic places, and both support linking named entities to these register files.
It's possible, to get the same editing support out of oXbytei and ediarum.BASE.edit. As you will see from the following, oXbytei is much simpler to set up. It's an agile speedboat in a flotilla.
Framework development has changed fundamentally in
<oXygen/> 23. Before, you had to make changes to a framework-file
in tiny inaccessible framework widgets and––more important––the
framework architecture was constrained to 2 bricks on each other, a
base framework and optionally a derived framework, that inherits all
the base's functions. Since <oXygen/> 23, frameworks can be defined
in exf-files and may be stacked to arbitrary height! The
inaccessible framework widgets are also gone; there's superb support
for editing the exf-files directly. All this has been a real game
changer.
As a result, oXbytei is installed with a click. It comes with reasonable defaults. Adaption to your project's requirements can be done through a configuration file, which can be edited in normal operation just along with your TEI documents without the need to restart the editor. Further requirements can be covered by defining a framework based on oXbytei inheriting all its functions. oXbytei even uses the TEI P5 framework by TEI-C as a base framework, so the awesome facsimile editor is present, too! SCDH provides the community with other frameworks, build on top of oXbytei, e.g., oXbytao with generic support for your templates and some common CSS styles on top of TEI-C's CSS; or ALEA NG for editing arabic literature.
In contrast, ediarum.BASE.edit sticks to the pre-version 23
framework-files. Because architecture is constraint to 2 bricks (and
other reasons discussed below), nothing can be installed with a click,
but you have to go through a complicated
setup. If
the defaults do not exactly fit your requirements, you will find
yourself in a longer development process. Adaptation to project needs
often involves editing author action files and the changes are only
evaluated after restarting the editor. Ediarum also does not build on
top of the TEI P5 framework by TEI-C, obviously due to the height 2
constraint.
Yes, ediarum.BASE.edit obviously offers more actions in its tool bar than oXbytei does. The smaller extend of actions is well considered. On top of its Java code base for building framework actions, oXbytei offers only author actions, that are considered really generic. Things that tend to flavoured (DTA, BBAW, SCDH Münster etc.) have to go into other frameworks on top. The philosophy is to provide generic bricks, that can be stacked and finally topped with a thin layer of project specific needs.

In many aspects, ediarum sticks to <oXygen/> old-school framework customization. where one has to define customized author mode actions.
Example: https://github.com/ediarum/ediarum.BASE.edit/blob/master/ediarum.BASE.framework#L983C1-L1061C1
<action>
<field name="id">
<String>persName</String>
</field>
<field name="name">
<String>Personenname</String>
</field>
<field name="description">
<String>Im Manuskript explizit erwähnte Person kennzeichnen</String>
</field>
<field name="largeIconPath">
<String></String>
</field>
<field name="smallIconPath">
<String></String>
</field>
<field name="accessKey">
<String></String>
</field>
<field name="accelerator">
<null/>
</field>
<field name="actionModes">
<actionMode-array>
<actionMode>
<field name="xpathCondition">
<String>ancestor-or-self::text
or ancestor-or-self::abstract
or ancestor-or-self::correspDesc/note
or ancestor-or-self::note[parent::notesStmt]
or ancestor-or-self::p[parent::physDesc]</String>
</field>
<field name="argValues">
<serializableOrderedMap>
<entry>
<String>URL</String>
<String>${ediarum_project_domain}${ediarum_projects_directory}${ediarum_project_name}${ediarum_index_person}</String>
</entry>
<entry>
<String>element</String>
<String><persName xmlns='http://www.tei-c.org/ns/1.0' key='$ITEMS'></persName></String>
</entry>
<entry>
<String>item rendering</String>
<String>$XPATH{/span}</String>
</entry>
<entry>
<String>item separator</String>
<String> </String>
</entry>
<entry>
<String>item variable</String>
<String>$XPATH{@xml:id}</String>
</entry>
<entry>
<String>multiple selection</String>
<String>true</String>
</entry>
<entry>
<String>namespaces</String>
<String>tei:http://www.tei-c.org/ns/1.0</String>
</entry>
<entry>
<String>node</String>
<String>//li</String>
</entry>
</serializableOrderedMap>
</field>
<field name="operationID">
<String>org.bbaw.telota.ediarum.RegisterSurroundWithElementOperation</String>
</field>
</actionMode>
</actionMode-array>
</field>
<field name="enabledInReadOnlyContext">
<Boolean>false</Boolean>
</field>
</action>
It get's a bit technical. Yes, but that's where you have to go through!
Let's have a closer look: This is the action for wrapping a selected
range of text in a <persName> element and setting the @key
attribute to an @xml:id in the personography. If you want to change
the element or attribute name, you have to change this file. If your
personography does not fit, you have to change the XPaths. You have to
restart the editor, to get the effect of your changes. Then, you have
to re-distribute the customized framework to your staff, since these
things only take effect when they are distributed inside a
framework. I admit: Having the author mode operation
org.bbaw.telota.ediarum.RegisterSurroundWithElementOperation and
parsing a register file with XPaths is a huge advance over using
${ask()} with nested ${xpath_eval()} like in plain <oXygen/>
framework customization––you really do not want to know details about them ;-).
oXbytei is similar, but different. A chain of editing atoms is involved that manipulates the XML tree step by step. First step: surround the selected range with an element. Second step: add an attribute, the value of which contains a selection from a user dialog. Let's look at the second step:
<?xml version="1.0" encoding="UTF-8"?>
<!-- editing atom -->
<a:authorAction xmlns:a="http://www.oxygenxml.com/ns/author/external-action"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.oxygenxml.com/ns/author/external-action http://www.oxygenxml.com/ns/author/external-action/authorAction.xsd"
id="sel.person">
<a:name>Select Person</a:name>
<a:description>Select a person from suggestions.</a:description>
<a:operations>
<a:operation id="de.wwu.scdh.oxbytei.SelectAttributeValueOperation">
<a:xpathCondition>true()</a:xpathCondition>
<a:arguments>
<a:argument name="name">${teilspProp(oxbytei.action.sel.person.name)}</a:argument>
<a:argument name="elementLocation">self::*</a:argument>
<a:argument name="message">Choose a person</a:argument>
<a:argument name="rollbackOnCancel">true</a:argument>
<a:argument name="icon">${framework(oXbytei)}/images/person-24.png</a:argument>
</a:arguments>
</a:operation>
</a:operations>
<a:accessKey/>
</a:authorAction>
The only interesting thing here is <a:argument name="name">${teilspProp(oxbytei.action.sel.person.name)}</a:argument>,
which sets the attribute name to – a variable. This variable is
defined in the configuration file. And the configuration file can
exist inside or outside the framework. So you can leave the oXbytei
framework untouched. For setting the attribute name, all you have to
do is change a line in the config file and pass to your staff:
<property name="oxbytei.action.sel.person.name">ref</property>
Generating a list of persons from a register file or what ever
resource you have, is even better. There is nothing like an XPath in
the action definition above. But how does oXbytei know, how to
generate the list? Answer: The
de.wwu.scdh.oxbytei.SelectAttributeValueOperation delegates it to a
powerful abstraction layer, that binds together the generation of
lists of items (like person IDs) and a user dialog (check boxes or
radio boxes or multi- or single select lists etc.) And all this is
configured in the configuration file. The following generates the list
from the personography given in a <prefixDef> in the current file,
defining psn: URIs.
<plugin>
<class>de.wwu.scdh.teilsp.extensions.LabelledEntriesXSLTWithContext</class>
<type>de.wwu.scdh.teilsp.services.extensions.ILabelledEntriesProvider</type>
<configurations>
<configuration>
<conditions>
<condition domain="context">(self::*:persName | self::*:person | self::*:rs[@type eq 'person']) and //*:teiHeader//*:prefixDef[@ident eq 'psn']</condition>
<condition domain="priority">10</condition>
<condition domain="nodeType">attributeValue</condition>
<condition domain="nodeName">ref</condition>
</conditions>
<arguments>
<argument name="script">${pdu}/resources/xsl/entries-persons.xsl</argument>
<argument name="parameters">prefix=psn</argument>
</arguments>
</configuration>
</configurations>
</plugin>The list is generated for an editing context defined in
<conditions>: the attribute value of @ref in the context
(self::*:persName | self::*:person | self::*rs:[@type eq 'person']) ... given that a certain prefix definition is present in the current
document. As you see, you do not have to repeat yourself for different
editing contexts.
In this example, the list is generated by an XSLT stylesheet. But there are numerous plugins for generating lists:
- by XPath from local or remote files
- by XSLT from local or remote files
- by XQuery from local or remote files
- from values written into the configuration file (handy for small
fixed sets of values like for the
rs/@typeattribute) - from CSV files
- from an SQL database
- by a SPARQL query over a remote endpoint
- by a SPARQL query over a set of RDF files
You can also define multiple sources for the same editing context, which will then be merged to the same user dialog, e.g., resources from the SPARQL endpoints of LoC and GND.
What about the user dialog? User dialogs are defined for editing
contexts. In the example project, we wanted a ComboBox Dialog for the
same editing context (<conditions>) like in the example above:
<plugin>
<class>de.wwu.scdh.teilsp.ui.ComboBoxSelectDialog</class>
<type>de.wwu.scdh.teilsp.ui.ISelectionDialog</type>
<configurations>
<configuration>
<conditions>
<condition domain="context">self::*:persName | self::*:person | self::*:rs[@type eq 'person']</condition>
<condition domain="priority">10</condition>
<condition domain="nodeName">ref</condition>
<condition domain="nodeType">attributeValue</condition>
</conditions>
<arguments>
<argument name="title">Select person</argument>
<argument name="icon">${framework(oXbytei)}/images/person-24.png</argument>
</arguments>
</configuration>
</configurations>
</plugin>In other editing contexts, like rdg/@wit, a check box dialog would
be nice, and having one in oXbytei is straight forward! Simply change
<class>.
The best news is: The configuration can live inside or outside the framework. So if you need to change the default configuration, which ships inside the framework, you can override it with a configuration outside of the framework. As a result, the framework can stay untouched. And that's why we are able to distribute it for easy installation with <oXygen/>'s add-on manager and why we can provide updates that the add-on manager automatically offers to you. Your adaptation to your project-specific needs won't be overwritten, since it leaves outside the framework's code base. When even the configuration needs an update, the extra framework for editing the configuration file has a solution.
Making generic software that can easily be adapted to specific requirements is one of the principles that drive software development at SCDH. Thus, developing an abstraction layer that first introduces a configuration file to <oXygen/> frameworks is a central feature, that makes oXbytei a next generation speedboat.
The critical apparatus is a domain, where oXbytei shines with its overloaded actions, which are unknown in other frameworks.
TEI knows three methods of variant encoding in the critical apparatus:
- parallel segmentation
- double end-point attached
- location referenced
While parallel segmentation can only be internal, both other methods can either be internally or externally realized. An external apparatus is kept outside of the main text and references it by some pointing mechanism.
Ediarum has actions for encoding the critical apparatus, but only following the parallel segmentation method. If you want to follow the double end-point method, which comes with great benefits, you will have to rewrite a bunch of actions in tiny framework widgets. No fun!
With oXbytei, you have support for parallel segmentation, internal and
external double end-point, and internal location referenced encodings
out of the box. (Wondering about an external location referenced
apparatus? We think, that it might be encoded in such a great variety
of ways, that we did not want to erect a norm by an implementation.)
The actions simply evaluate, what you declared in your TEI
header. E.g., with <variantEncoding method="double-end-point" location="internal"/>, oXbytei's actions will generate correct markup
for an internal double end-point apparatus.
Here's an example of an overloaded editing atom, responsible for
adding the markup of an
apparatus
entry. It defines several actions, and only the right one is activated
by the XPath in <a:xpathCondition>, which evaluates the
<variantEncoding> given in the header.
<?xml version="1.0" encoding="UTF-8"?>
<!-- editing atom -->
<a:authorAction xmlns:a="http://www.oxygenxml.com/ns/author/external-action"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.oxygenxml.com/ns/author/external-action http://www.oxygenxml.com/ns/author/external-action/authorAction.xsd"
id="markup.apparatus">
<a:name>Markup apparatus</a:name>
<a:description>Make an apparatus entry on the current user selection.</a:description>
<a:operations>
<a:operation id="SurroundWithFragmentOperation">
<a:xpathCondition>//teiHeader/encodingDesc/variantEncoding[@method eq 'parallel-segmentation' and @location eq 'internal']</a:xpathCondition>
<a:arguments>
<a:argument name="fragment"><![CDATA[<app xmlns="http://www.tei-c.org/ns/1.0"><lem/><rdg>${caret}</rdg></app>]]></a:argument>
</a:arguments>
</a:operation>
<a:operation id="de.wwu.scdh.oxbytei.ExpandingXSLTOperation">
<a:xpathCondition>//teiHeader/encodingDesc/variantEncoding[@method eq 'double-end-point' and @location eq 'internal']</a:xpathCondition>
<a:arguments>
<a:argument name="script">${framework(oXbytei)}/xsl/app-dep-int.xsl</a:argument>
<a:argument name="sourceLocation">${teilspProp(oxbytei.action.app.dep.int.sourceLocation)}</a:argument>
<a:argument name="targetLocation">${teilspProp(oxbytei.action.app.dep.int.targetLocation)}</a:argument>
<a:argument name="action">${teilspProp(oxbytei.action.app.dep.int.action)}</a:argument>
<a:argument name="externalParams">container=${anchorsContainer},startId=${startAnchorId},endId=${endAnchorId},${teilspProp(oxbytei.action.app.dep.int.externalParams)}</a:argument>
</a:arguments>
</a:operation>
<a:operation id="de.wwu.scdh.oxbytei.ExpandingXSLTOperation">
<a:xpathCondition>//teiHeader/encodingDesc/variantEncoding[@method eq 'double-end-point' and @location eq 'external']</a:xpathCondition>
<a:arguments>
<a:argument name="script">${framework(oXbytei)}/xsl/app-dep-ext.xsl</a:argument>
<a:argument name="sourceLocation">${teilspProp(oxbytei.action.app.dep.ext.sourceLocation)}</a:argument>
<a:argument name="targetLocation">${teilspProp(oxbytei.action.app.dep.ext.targetLocation)}</a:argument>
<a:argument name="action">${teilspProp(oxbytei.action.app.dep.ext.action)}</a:argument>
<a:argument name="externalParams">container=${anchorsContainer},startId=${startAnchorId},endId=${endAnchorId},${teilspProp(oxbytei.action.app.dep.ext.externalParams)}</a:argument>
</a:arguments>
</a:operation>
<a:operation id="InsertFragmentOperation">
<a:xpathCondition>//teiHeader/encodingDesc/variantEncoding[@method eq 'location-referenced' and @location eq 'internal']</a:xpathCondition>
<a:arguments>
<a:argument name="fragment"><![CDATA[<app xmlns="http://www.tei-c.org/ns/1.0"><lem>${selection}</lem><rdg>${caret}</rdg></app>]]></a:argument>
</a:arguments>
</a:operation>
</a:operations>
<a:accessKey/>
</a:authorAction>
This is an example of the idea, that led to oXbytei's name: Use the TEI document as a configuration source for the framework, at least as much as possible. Overloaded actions are a key for making this happen.
In this vein, a framework becomes generic, since it provides not only functions for the one encoding technique, that some software developers are in favour of, but the encoding techniques that are specified in the TEI reference.
Yes, at SCDH Münster we also provide XSLT for handling all these encoding methods of the critical apparatus. But that's not part of the framework. oXbytei is for editing TEI. We have other software components, that also Do one thing and do it well!
Ediarum favours using the
@key
attribute for linking named entities to the registers of your
edition. E.g.:
... <persName key="pGundulf">Gundulf</persName>, the architect of the <placeName key="lRochester">Rochester</placeName> cathedral ...
As we've seen above, we can change the attribute to ref, if we need
to.
By default, oXbytei uses the
ref
attribute. Markup will look like this:
... <persName ref="psn:Gundulf">Gundulf</persName>, the architect of the <placeName ref="plc:Rochester">Rochester</placeName> cathedral ...
It can be re-configured for using the key, but ref is
default. Why?
The reason are the datatypes of the key and the ref
attributes. Let's look them up in the TEI
reference:
-
key: "teidata.text", and "The value may be a unique identifier from a database, or any other externally-defined string identifying the referent. No particular syntax is proposed for the values of the@keyattribute, since its form will depend entirely on practice within a given project." -
ref: "1–∞ occurrences of teidata.pointer separated by whitespace" and "The value must point directly to one or more XML elements or other resources by means of one or more URIs, separated by whitespace. If more than one is supplied the implication is that the name identifies several distinct entities."
This means: Using @key always requires some configuration and there
is no means to express in TEI, how the values of the attribute are to
be evaluated. So, @key is based on convention, that has to be
configured for the editor and for all subsequent tools that process
the TEI documents.
In contrast, the values of @ref are simply pointers, i.e., URIs, and
URIs are to be processed in a well-defined way. Moreover, TEI provides
a very elegant way for shortening URIs by
<prefixDef>
in the document header:
<listPrefixDef>
<prefixDef matchPattern="(.+)" replacementPattern="persons.xml#$1" ident="psn"/>
<prefixDef matchPattern="(.+)" replacementPattern="places.xml#$1" ident="plc"/>
<!-- ... -->
</listPrefixDef>This is where the psn: and plc: prefixes in the example above come
from. With the prefix definition in place, the psn custom URI
psn:Gundulf expands to the relative URI person.xml#Gundulf, i.e.,
the fragment with the ID Gundulf in the file person.xml.
@ref and <prefixDef> together provide a suitable configuration
source, that can be evaluated by a framework to provide entity
lists. The XML file, which serves as the personography is mentioned in
the header and the framework can evaluate it. So the choice was clear:
If there's a way to get things working out of the box, that's the way
to go. And it even leads to an elegant encoding style!
Nice side effect: Since this uses URIs, all subsequent components that have to evaluate entity linking (XSLT for generating HTML, etc.) can use generic algorithms, since URIs must be evaluated as URIs.
There have been some discussions on the TEI mailing list on the ref
vs. key issue. Whatever you decide to use: oXbytei can easily be
configured to use key, and ediarum.BASE.edit can also be adapted to
use ref.