Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Vex/ArchitectureGuide

< Vex

The Document Object Model

Vex's domain model representing an XML document consists of two parts: the XML structure and the textual content.

XML Structure Representation

The XML structure is represented by the Document Object Model (DOM).

VexDomClassDiagram.png


Each Node is associated with a range in the representation of the textual content. A Parent node can have other nodes as children.

Text Representation

The textual content of an XML document is managed through the Content interface. One Content instance contains the whole textual content of one document or document fragment. The textual information is enriched with (so called) 'tag markers', which mark the position of XML structual elements (e.g. the start and end tags of XML elements) within the textual content.

Textual content is also presented in the structure representation in form of Text nodes. Those nodes provide a pointer into the Content instance.

Modification

To modify an XML document, Vex provides operations on several levels of granularity.

Level 0: Basic Operations

The lowest level contains only the very basic operations to modify the XML structure and the textual content. Those operations are spread over the DOM and the Content interface. They do not ensure wellformedness or validity of the XML document.

L0 operations are intented to be used only internally! They are not part of Vex's public API.

Level 1: Generic XML Operations

Level one contains the operations to generically modify an XML document according to its document type. The operations on this level do ensure wellformedness and, if a document type is available, validity.

The class Document provides all L1 operations:

  • canInsertText(offset)
  • insertText(offset, String)
  • canInsertElement(offset, QualifiedName)
  • insertElement(offset, QualifiedName)
  • canInsertComment(offset)
  • insertComment(offset)
  • canInsertFragment(offset, DocumentFragment)
  • insertFragment(offset, DocumentFragment)
  • canInsertProcessingInstruction(offset, target)
  • insertProcessingInstruction(offset, target)
  • canInsertCDataSection(offset, ?) (still to be done)
  • insertCDataSection(offset, ?) (still to be done)
  • canInsertEntityReference(offset, ?) (still to be done)
  • insertEntityReference(offset, ?) (still to be done)
  • delete(ContentRange)
  • getFragment(ContentRange)
  • getValidInsertElements(offset)
  • getNodeForInsertion(offset)
  • findCommonNode(offset1, offset2)

Level 2: XML Editing

The second level contains operations to edit an XML document based on a cursor or selection. The operations can be undone and redone, several operations can be combined into one atomic compound operation. The L2 operations have a one-to-one relationship to the basic editing actions present on the UI of Vex. They are all defined in IVexWidget.

Moving Cursor and Selection

  • moveBy(delta)
  • moveBy(delta, select)
  • moveTo(offset)
  • moveTo(offset, select)
  • moveToLineEnd(select)
  • moveToLineStart(select)
  • moveToNextLine(select)
  • moveToNextPage(select)
  • moveToNextWord(select)
  • moveToPreviousLine(select)
  • moveToPreviousPage(select)
  • moveToPreviousWord(select)
  • selectAll()
  • selectWord()
  • selectContentOf(Node)
  • select(Node)

Current Selection and Clipboard

  • hasSelection()
  • cutSelection()
  • copySelection()
  • canDeleteSelection()
  • deleteSelection()
  • canPaste()
  • canPasteText()
  • paste()
  • pasteText()
  • getSelectedFragment()
  • getSelectedRange()
  • getSelectedText()

Undo, Redo and Compound Operations

  • beginWork()
  • endWork()
  • doWork(Runnable)
  • doWork(Runnable, savePosition)
  • canUndo()
  • canRedo()
  • undo()
  • redo()

Simple Editing

  • canInsertText()
  • insertChar(char)
  • insertText(String)
  • getValidInsertElements()
  • canInsertElement(QualifiedName)
  • insertElement(QualifiedName)
  • canInsertComment()
  • insertComment()
  • canInsertProcessingInstruction()
  • insertProcessingInstruction(target)
  • editProcessingInstruction(target, value)
  • canInsertFragment(DocumentFragment)
  • insertFragment(DocumentFragment)
  • insertXML(String)
  • deleteNextChar()
  • deletePreviousChar()

Morphing, Splitting, Joining and Unwrapping

  • getValidMorphElements()
  • canMorph(QualifiedName)
  • morph(QualifiedName)
  • canSplit()
  • split()
  • canJoin()
  • join()
  • canUnwrap()
  • unwrap()

Attributes

  • canSetAttribute(name)
  • setAttribute(name, value)
  • canRemoveAttribute(name)
  • removeAttribute(name)

Namespaces

  • declareNamespace(prefix, uri)
  • removeNamespace(prefix)
  • declareDefaultNamespace(uri)
  • removeDefaultNamespace()

Level 3: Semantic XML Operations

The semantic XML operations provide functionality for a specific document type or sub-structure of an XML document on a semantic level. Editing of tables according to the CALS table model would be an example of such semantic operations.

Navigation

To navigate in the DOM of an XML document, Vex provides a mechanism inspired by the XPath axes.

  • The children axis of a Parent node contains all direct children of the parent, but no further descendants.
  • The ancestors axis of a node contains all subsequent parents of the node.

The class Axis represents an axis of this sort. To ease the navigation purpose, it provides three main features:

  1. It implements Iterable<Node> for convenient use in foreach loops.
  2. It provides a fluent interface to limit the nodes on the axis according to given criteria.
  3. It provides several methods for direct access to single nodes on the axis or other useful properties of the axis.

Examples

Get child nodes before a given offset:

element.children().before(offset)

Get child nodes in a given range:

element.children().in(range)

Get the Parent Element of an Element:

public Element getParentElement(Element element) {
  for (final INode ancestor : element.ancestors()) {
    if (ancestor instanceof Element) {
      return (Element) ancestor;
    }
  }
  return null;
}

Back to the top