Skip to content
This repository has been archived by the owner on Feb 11, 2024. It is now read-only.

Latest commit

 

History

History
265 lines (211 loc) · 13.5 KB

level1-introduction.rst

File metadata and controls

265 lines (211 loc) · 13.5 KB

Level 1 Functional specification

All the lpOD level 0 features are available through the level 1 API, so the applications can create, retrieve or delete any element. They can create, select, update or delete any attribute or sub-element in a previously retrieved element.

The API provides functions and methods.

Functions are mainly used as object constructors, in order to create new ODF elements that could be later attached to a document. The name of an object constructor is like odf_create_xxx() where "xxx" is the object type. These constructors return "free" ODF elements, i.e. elements which don't belong yet to any document; these elements may be attached later through a document or context based method. However, some very specific objects may be created "in place", through set_xxx() element specific methods that create the objects and directly append them to the calling element.

Once created, an object may be changed through the set_text() and set_attribute() level 0 methods; however, the level 1 features allow the user to set the most used properties using a more friendly way.

The level 1 set_attribute() method extends the level 0 one by allowing the user, in some situations, to forget the ODF namespaces. Knowing that every ODF attribute name belong to a namespace, if set_attribute() is called from an ODF element with an attribute name without namespace prefix, the method transparently concatenates the given name to the namespace prefix of the calling object. get_attribute() use the same behaviour. As a consequence, the prefix may be safely omitted with attributes whose namespace is the same as the namespace of the target element. In addition, knowing that an XML attribute name can't contain blank spaces, these methods automatically replace every space by a dash. For example, assuming p is a paragraph (which belongs to the "text" namespace), the three instructions below (that return the style of the given paragraph) are equivalent:

p.get_attribute('text:style-name')
p.get_attribute('style-name')
p.get_attribute('style name')

There is an exception regarding a particular attribute, which is the style name. When get_attribute() or set_attribute() is called with an attribute name without prefix and ending with "style", the namespace prefix is inserted as usual, but in addition a "-name" string is silently appended. Knowing that attributes like "xxx-style-name" are very frequently used, this feature provides a "xxx style" shortcut. As a consequence, the following instruction does the same as each one of the previous example:

p.get_attribute('style')

A get_attributes() method is provided, that returns all the attributes of the calling element (with their real ODF names) and their values as a array of named items. The set_attributes() method allows the user to change or create several attributes a a time; it checks and transforms the given attribute names in the same way as set_attribute().

Some ODF elements own a set_properties() method, which could sound redundant with set_attributes(). However, set_properties() may set element properties that imply element-specific transformations or constructs, makes some consistency checks, and allow the user to provide property names that aren't directly translated in simple attributes using the same name transformation rules as set_attributes(). The same logic apply to get_properties(), when defined.

In the present specification, some element properties or attributes may be named using multiple-word designations (ex: display name, page layout) that include spaces or dashes. Knowing that such designations are not easy to use as variable names in every programming language, spaces and dashes should be replaced by underscore ("_") characters in the lpOD executable. implementations.

Some ODF elements own boolean attributes whose legal values are the "true" and "false" text strings. Knowing that, for most programming languages, such strings are not the same as the true and false boolean values, lpOD provides specialized methods for such attributes. The set_boolean_attribute() method makes sure that, if the provided attribute value is false according to the rules of the host language, the target attribute will be set to the "false" string. In addition, whatever the rules of the host language, any "false", "off" or "no" string value, and the 0 numeric value, are regarded as false, as well as an empty (but defined) string. On the other hand, if the value is null (i.e. not defined), the attribute is deleted and not set to "false", following the common rule. There is a symmetric get_boolean_attribute() that returns a regular true or false programmatic value (depending on the host language) according to the ODF "true" or "false" boolean value.

The following example, assuming p is a paragraph or heading, sets to "false" the text:restart-numbering attribute:

p.set_boolean_attribute('restart numbering', 0);

Some methods are document-based, other are context-based, and other are element-specific.

A document-based method is a method that makes sense at the document level only. As an example, insert_style() is document-based knowing that a style is always defined at the document level.

A context-based method is designed in order to allow the user to insert, search, process or delete content elements either in the whole document body, or in a particular branch in the content tree. For example insert_element() is context-based because it allows the insertion of an element in any context. Of course, a context is always an ODF element, but context-based methods are available whatever the element type (however, a context-based method can raise an error, for example when it's used to execute an operation that is not legal for the current context).

The level 1 insert_element() method supports all the features of the level 0 version, but it accepts the additional parameters before and after, whose value is an ODF element. The element to be inserted takes place immediately after the reference element provided through the after parameter (if set). Alternatively, the insertion will take place before any element which is provided through the after parameter. These parameters are intended to hide the low level XML jargon, and they are, of course, optional and mutually exclusive.

On the other hand, append_element() always attaches an element after the last child of the context element.

An element-specific method works with specific ODF elements only, according to their particular role. For example set_header() is provided with ODF master pages, because a header is an extension of a page style element, while set_background() is available with objects where a background definition makes sense (such as page layouts or paragraph styles). Remember that all the generic methods available for any element are introduced in the lpOD "level0" documentation chapter.

Any ODF element in the level 1 API inherits all the features of the underlying XML element.

Every ODF element comes with methods that directly return its parent, next sibling, previous sibling, and the list of its children. These methods (which are provided by the underlying XML API) are available whatever the element type.

Any element provides a clone method, which creates a new instance of the element with all its children; this instance is free and can be inserted later in any place in the same document or in another document. An element may be removed through a delete method from its parent element; the deletion removes the element itself and all its children.

Some elements are created without any predefined attachment, i.e. as a free elements, by specific constructor functions whose name is like odf_create_xxx(), where xxx is the kind of element to be created. A free element can be inserted later at the right place. Other elements, whose definition doesn't make sens out of a specific context, are directly created in place, through context-based methods whose name is set_xxx(). Beware, every set_xxx() method creates or replaces something in the calling element, but some of them don't create new elements.

A get_document() method, called from any element, allows the user to get the odf_document object to which it belongs. This method returns a null value if, for any reason, the element doesn't belong to a document.

According to the ODF 1.1 specification, some elements may own an identifier attribute (whose XML name is "text:id"). The lpOD API provides a generic get_id() element accessor, that returns the value of the identifier, if any, or a null value otherwise. A set_id() method allows the applications to arbitrarily set or change this identifier with any ODF element. If set_id() is used with a null value, the identifier is deleted if it exists (and nothing is done otherwise). There is no automatic compliance check associated with set_id(), so the user is allowed to set non standard identifiers and/or identifiers that will not be supported or preserved by ODF-compliant applications. On the other hand, identifiers may prove useful in order to retrieve elements whose XML position is unknown or changing. Anyway, it's always possible to set a non-standard identifier for a given processing session and remove it before writing the changed document in a persistent storage.

Any element is able to be serialized and exported as an XML, UTF8-encoded string. Symmetrically, an element can be created from an application- provided XML string. As a consequence, lpOD-based applications can remotely transmit or receive any kind of ODF content.

The level 1 API is not validating, so the user is responsible of the ODF compliance (the API doesn't automatically prevent the applications from inserting an element at the wrong place or to set non-ODF elements).

Any element can be retrieved according to its sequential position in a given context or its text content (if defined), through methods like get_xxx() where "xxx" is the element type (i.e. "paragraph", "heading", etc). The get_xxx() methods allows a content and a position parameters. For example:

element = context.get_xxx(position = p, content='xyz')

When both content and position are set, position specifies the selected element within the result set that matches the given content. If position is not set, the selected element is the first element that matches the given content. Without parameter, the first xxx element is selected. Of course, a null value is returned (without error) if the context doesn't contain any element matching the conditions.

It's possible to get the list of elements of a known type in the context, using get_xxx_list().

Of course, the API doesn't provide a distinct get_xxx() method for any possible element in an ODF-compliant document. On the other hand the list of these specialized methods is growing. However, there is a generic level 1 get_element() that requires the ODF element type as a mandatory argument, and allows the content and position optional parameters. Example:

element = context.get_element('text:user-field-get', content='xyz');

The example above returns the first "user field get" element whose text content includes a "xyz" substring.

The two lines above retrieve an element among the children of context element. The first one selects the child element at the given p position. The given position is an integer; the first position is zero; negative positions are counted back from the last (-1 is the last position). The second instruction retrieves the first element whose text content matches a given regex regular expression. Knowing that the regexp could be matched by more than one element, the same method is available in a list context.

Addtional retrieval methods are available according to the element type.

Every search method operates in context, knowing that the context could be the whole document as well as a particular element (section, table, etc).