Identification system

To allow WYSIWYG editing of document graphical presentation directly in the canvas we must first identify the original data placement in the source document. This is achieved by using emp:id attributes, identifying elements. Because text nodes cannot have attributes, their IDs have to be computed using their position.

You may compute IDs of source nodes in your stylesheet using these rules:

  • If the node is an element, simply take the value of its emp:id attribute. This ID attribute value is an integer number.
  • If the node is not an element nor an attribute then it is a child of some element and it has an order number. Just compute its ID from the ID of its parent and its zero-based position. Use a semicolon (;) to separate those two values.
  • Attributes are not ordered so use their qname (in the form of foo or bar:foo if it does have a prefix) instead of their position and separate it by a @ character.
The IdManager class is used to map those IDs back to nodes, please look there for further information.

Some applications (for example FOP) requires that each ID is unique. However we may want to identify same element from different places. We must ensure that two different ID strings denote the same element. Hence, we define the ID structure as follows:

[parent-id]{; or @} position or attribute-name [:any_string]

where [] denotes an optional part and {} represents choice between two strings. No whitespaces are allowed. The any_string part is ignored when IDs are compared - two IDs are equal if and only if their parent-id are equal or both are missing and position or attribute-name are equal.

We say that ID is synthetic when it is not present in the source document and needs to be created from another ID. We say that ID is native if it is not synthetic. We see that only the ID denoting an element is native - all other IDs (text, comment, attribute, ...) are synthetic.

Transporting IDs

Your stylesheet (exporter) should transport these IDs to renderer and editor to allow on-screen figures to be identifiable. Here are some tips you may find useful:

  • You should transport ids of text, comment and PIs (processing instructions), otherwise the text won't be editable. There is no general rule, how these ids should be transported - text can't contain any attributes. For example, for built-in FO plugin, these ids are transported by encapsulating text into <fo:inline> element that contains the emp:id attribute containing the value of this id.
  • Comments and PIs are mostly not displayed in resulting tree. However, if they are, then they have same transportation semantics as text. For example, text of comment should be simply enclosed in <fo:inline> element, as if text was transported. The type of source node will be get from id, so there is no need to specify this type explicitly.
  • Even if comment and/or PI is lost (no visible item is produced), it may specify the position of this node in original document, so that this comment/PI is still WYSIWYG editable. For example, in FO we may specify this position with <fo:inline id="..."/> - it doesn't occupy no canvas space and doesn't harm the presentation in any way.
  • Text, comment, PIs and attributes values may be displayed and edited in canvas. There are some restrictions in these nodes' ID transporting. If value is modified somehow (text is added in the middle of text, or some characters are erased (this does not apply to whitespaces in string), then this node's id should not be transported into this place otherwise WYSIWYG text modification may insert text at incorrect place.
There are several possibilities, how source nodes can be transformed:
  • 1:1 - one node is transformed to exactly one node. Simple transfer emp:id to new node.
  • 1:n - node is transformed to one or node elements. Simple transfer emp:id to all new nodes (it may be enough to transfer emp:id to all roots of trees being created - it is logical that node inherits ID from its ascendant).
  • n:0 - node is lost, thus invisible when rendered. Just lose the emp:id attribute aswell.
  • n:1 - more elements are transformed into one. Let's assume that this possibility is not reducible, for example into 1:1 and n:0 possibility. We must then lose some ids, thus render source nodes editable only indirectly (via the document tree). However, there is a way - you may wrap the IDs into a non-visible elements.

    Let's have foo element containing bar element that contains baz element containing some text, and we are trying to render only the text in a FO output document. The result may look like this: <fo:inline emp:id="foo_id"><fo:inline emp:id="bar_id"><fo:inline emp:id="baz_id"><fo:inline emp:id="text_id">text</fo:inline>.... etc
  • n:m - again let's assume that this possibility is not reducible. You should try to solve this case in a similar way as the n:1 case.