by Robert Kendall
Revised 5/11/2008
The concept of an X-Literature (X-Lit) specification was proposed by the Electronic Literature Organization's committee for the Preservation, Archiving, and Dissemination of Electronic Literature. The purpose of such a specification would be to provide a standardized XML file format for storing works of electronic literature in a way that would make them more easily portable between delivery systems and hence more resistant to software obsolescence. The X-Lit file format would store all the work's text and the addresses of all media files used by the work, providing a way to organize this content, access it in a structured way, and make it easily human readable. The format would also store metadata, formatting information, and parameters that describe how the content is to be rendered, including details of user interaction, network interaction, and onscreen animated elements.
The current document is not a formal specification for an X-Literature format. It is a description of a functional proof-of-concept project intended to serve as an experimental starting point for a formal spec. Documents that conform to the XML format described here can be read by Flash SWF files that incorporate the X-Lit ActionScript Library (XAL), which is available for free download.
A sample work called Pieces demonstrates the use of the prototype file format and XAL. The XAL classes are used in Pieces to read an XML file that stores all the work's text organized into groups with tags that specify the conditional display of some text elements.
To conform to the prototype X-Lit format, a document must have a root element called xlit. This means it must begin with the tag <xlit> and end with the tag </xlit>. The second-level elements are as follows:
metadata
contents
containers
formats
behaviors
controls
state
The X-Lit ActionScript Library currently supports only the contents element, which is therefore the only element documented below.
The contents element holds content of any media type: text, graphics, audio, video, or animation. Within contents, unit elements contain individual sections of text or pointers to media files. Unit elements are grouped together within group elements, which should reflect the organizational structure of the work. Each unit may contain either a text element that holds text, or a media element with attributes specifying a media file to load. Currently the XAL supports only text. The syntax is as follows:
<contents>
<group name="group_name">
<unit [name="unit_name"]>
<text>text content goes here</text>
</unit>
<unit [name="unit_name"]>
<media type="image | audio | swf | flv" src="filepath" [h="heightValue" w="widthValue"] />
</unit>
</group>
</contents>
Textual content within a unit element can be modified conditionally by means of a choose element. Within the choose element, one or more when elements specify text that is to be displayed if a specified condition is met. An optional otherwise element specifies text that is to be displayed if none of the conditions in the when elements are met. This syntax is derived from XSL.
<unit>
<choose>
<when attributes>
<text>text to display if condition is met</text>
</when>
[<when attributes>
<text>text to display if condition is met</text>
</when>]
[<otherwise>
<text>text to display if no condition is met</text>
</otherwise>]
</choose>
</unit>
The possible attribute combinations for the when element are as follows:
<when condition="presented" group="group_name[, group_name...]" unit="unit_name[, unit_name...]" quantity="all | some | none | n[,n]" age="n[,n]" preceded_by="all | some | none | n, group_name | unit_name[, group_name | unit_name...]" value="true | false">
or
<when variable="variable_name" value="variable_paramter">
If the value of the condition attribute is "presented," the condition relates to content units that have been presented—that is, content displayed onscreen at some previous point but not currently onscreen. Of the following attributes, only condition and group are currently supported by the XAL.
condition="presented"
When this attribute's value is "presented," the condition is true if the units specified in group and/or unit have been presented in the manners specified by the other attributes.
group="group_name[, group_name]"
Specifies one or more groups that must have been presented for the condition to be true. Specifying the name of a group is the same as specifying all the units in that group. If their units have been presented in the manner specified by other attributes of the element, the condition is true.
unit="unit_name[, unit_name]"
Specifies one or more units. If both groups and individual units are specified, the individual units and the contents of the groups must have been presented in the manner specified for the condition to be true.
quantity="all | some | none | n[,n]"
Determines whether all, some, or a specified number of the units must have been presented for the condition to be true. If two numeric values are given, the number of units presented must be equal to or greater than the first value and not more than the second value. If one numeric value is given, the number of units must be equal to or greater than that value.
age="n[,n]"
Age represents the position of a presented unit in the presentation history. The most recently presented unit (the one immediately preceding the one currently displayed) has an age of 1, the unit presented before that has an age of 2, and so on. If the specified units have ages not less than the first number in the age attribute and not greater than the second number, the condition is true. If the second number is omitted, the units must have an age of n or greater.
preceded_by="all | some | none | n, group_name | unit_name[, group_name | unit_name]"
This attribute specifies whether certain units were immediately preceded by other units when they were presented. The condition is true if the units listed in this attribute preceded the units listed in groups or units during the presentation history. The first parameter of this attribute specifies whether all, some, none, or a specified number of the appearances of the units in groups or units must have been preceded by appearances of the units listed in preceded_by.
value="true | false"
This attribute specifies whether the content within the when element should be displayed if the condition is true or if the condition is false. If omitted the value defaults to "true."
A choose element can also respond to variable values using the following syntax:
<when variable="variable_name" value="variable_paramter">
Variable values can be set via ActionScript in the SWF file at runtime and passed to the choose element by means of the XAL to alter the content that is displayed.
The name of the variable to check.
The value to check.
<unit>
<choose>
<when condition="presented" group="CivilWar1,CivilWar2" quantity="none" value="true">
<text>You haven't read about the Civil War yet.</text>
</when>
<otherwise>
<text>You've now read all the text about the Civil War.</text>
</otherwise>
</choose>
</unit>
The X-Lit ActionScript Library provides ActionScript 3.0 code that you can incorporate into a Flash CS3 .FLA file to allow your Flash project to load and parse content from an X-Lit file. The library requires Flash CS3, since earlier versions of Flash don't support ActionScript 3.0. The library consists of three classes, each stored in an .AS file:
Xlit.as
State.as
Utilities.as
To use the library, download xal.zip and extract the three .AS files. In the folder containing the .FLA file with which you want to use the library, create a new folder called /xal. Copy the three .AS files into /xal. Then follow these steps to add the library to your own ActionScript .AS class file:
1. Add the following line inside the package definition in your class and before the class definition:
import xal.Xlit;
2. Inside the class definition, add this line to declare the xlit variable:
private var xlit:Xlit;
3. In the main body of your code, create an instance of the Xlit class by adding the following line, substituting the name of your X-Lit XML file for filename:
var xlit:Xlit = new Xlit("filename");
You can then use the functions described below to read content from the X-Lit file.
The XAL lets you access the content within a group without having to keep track of individual units. You can use the getUnit() function to iterate either forwards or backwards through all the units in a group, or jump to a unit at a specified location. If any conditional content modification is specified by a choose element within the unit, the text will be modified before it is returned.
xlit.contents.groupName.getUnit(position)
The position of the unit within the group to be selected. The possible values are "first," "last," "next," "previous," or a number. (Numbers must be enclosed in quotation marks.) If the value is a positive number, the unit in that position will be returned. If the value is a negative number, it indicates a position counting back from the last unit, with "0" representing the last unit. "-1" would represent the second to last unit.
Since Xlit keeps track of the currently displayed unit, you can iterate through all the units of a group with successive calls to getUnit(). The "next" and "previous" identifiers move forwards and backwards through the group, respectively. If the position parameter is "first," the first unit of the group is returned. The following code will return the first 3 units of myGroup:
text1:String = xlit.contents.myGroup.getUnit("next");
text2:String = xlit.contents.myGroup.getUnit("next");
text3:String = xlit.contents.myGroup.getUnit("next");
If the last unit in the group is the current unit and position is "next", an empty string will be returned.
This code will retrieve the text of the second unit in myGroup:
secondUnit:String = xlit.contents.myGroup.getUnit("2");
You can also access content units directly through the xlit.content object and the getContent() function, in the following way:
xlit.contents.groupName.unitName.getContent()
The following code retrieves the text of a unit called "myUnit" that is part of a group called "myGroup" and assigns the text to a variable called unitText:
var unitText:String = xlit.contents.myGroup.myUnit.getContent();
The _units property of a group is an array of all the names of the group. You can use it to access a unit that occupies a particular position within a group.
xlit.contents.groupName._units[unitIndex]
For example, this code will retrieve the name of the second unit in "myGroup":
var secondUnitName:String = xlit.contents.myGroup._units[1];
To access the names of all the content groups, use the xlit.contents._groups object. The following code will retrieve the name of the second group:
var secondGroupName: String = xlit.contents._groups[1];
The State class is used by Xlit to store the following state information:
If all the data in the State class is saved to the Flash Shared Object or to a file, an interrupted reading can be resumed exactly where it was left off by restoring the saved State data.
The xlit.currentState.current object holds the name of the currently displayed group:
xlit.currentState.current.contents[0].group
and the currently displayed unit within that group:
xlit.currentState.current.contents[0].units[0]
(The values are stored in arrays so that a future version of the library can support multiple current groups and units, if several units are displayed simultaneously. Currently on a single group and unit are supported.)
The following code will retrieve the names of the current group and unit:
var currentGroupName:String = xlit.currentState.contents[0].group;
var currentunitName:String = xlit.currentState.contents[0].units[0];
To get the names of all the groups that have been presented, use the xlit.currentState.groupsPresented() function. It returns an array of the names of all the groups that have been presented. If a group has been presented more than once, it's name will appear only once in the array.
var groupsPresentedArray = xlit.currentState.groupsPresented();
Use the xlit.currentState.presented object to retrieve the names of units within groups that have been presented. This object also stores the name of the unit most recently presented within a group.
The following example returns an array of the names of all the units presented in the group "myGroup." Duplicate names are not included.
var unitNamesArray:Array = xlit.currentState.presented.groups.myGroup.allUnits;
This line returns the name of the most recently presented unit from "myGroup."
var lastUnitName:String = xlit.currentState.presented.groups.myGroup.lastUnit;
To get the names of all the groups that have been presented, use xlit.currentState.presented.allGroups. It contains an array of the names of all the groups that have been presented. If a group has been presented more than once, it's name will appear only once in the array.
var firstGroupPresented = xlit.currentState.presented.allGroups[0];
The object xlit.currentState.presented.units holds an array of the names of all units in the order in which they were presented. Duplicates are included.
To determine whether a group has been presented, use the xlit.currentState.wasPresented() function.
xlit.currentState.wasPresented(quantity:Number, groupName1:String[, groupName2:String,...])
Specifies how many units within the groups must be visited for the function to return true. The possible values are "some" (one or more) and "all."
Names of groups to be evaluated.
The following expression will return true if one or more units from either "chapter1" or "chapter2" have been presented.
xlit.currentState.wasPresented("some", "chapter1", "chapter2")
This function is used to create or change variables that can be read by the choose elements in units in order to display content conditionally.
setVar(name:String, value:String)
The name of the variable, following the conventions of variable naming.
A string representing the value of the variable.
This code creates a variable called "finished" and sets its value to "false."
xlit.currentState.setVar("finished", "false");
The variables object contains the values of all variables created using setVar(). The following code retrieves the value of the variable "finished."
var isFinished:String = xlit.currentState.variables.finished;