extract interfaces of nodes as public API

Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FilterIteratorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FilterIteratorTest.java
index 38b9202..892211c 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FilterIteratorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/core/FilterIteratorTest.java
@@ -18,6 +18,7 @@
 import java.util.Collections;

 import java.util.Iterator;

 

+import org.eclipse.vex.core.IFilter;

 import org.junit.Test;

 

 public class FilterIteratorTest {

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java
index f69c7fb..e1ccb12 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java
@@ -16,6 +16,8 @@
 import java.net.URL;
 
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.core.Color;
 import org.eclipse.vex.core.internal.core.DisplayDevice;
 import org.eclipse.vex.core.internal.dom.Document;
@@ -168,8 +170,8 @@
 
 	@Test
 	public void testDefaultInheritance() throws Exception {
-		final Document doc = new Document(new QualifiedName(null, "simple"));
-		final Element defaults = doc.insertElement(2, new QualifiedName(null, "defaults"));
+		final IDocument doc = new Document(new QualifiedName(null, "simple"));
+		final IElement defaults = doc.insertElement(2, new QualifiedName(null, "defaults"));
 
 		final StyleSheet ss = parseStyleSheetResource("test2.css");
 		final Styles styles = ss.getStyles(defaults);
@@ -429,8 +431,8 @@
 
 	@Test
 	public void testForcedInheritance() throws Exception {
-		final Document doc = new Document(new QualifiedName(null, "simple"));
-		final Element inherit = doc.insertElement(2, new QualifiedName(null, "inherit"));
+		final IDocument doc = new Document(new QualifiedName(null, "simple"));
+		final IElement inherit = doc.insertElement(2, new QualifiedName(null, "inherit"));
 
 		final StyleSheet ss = parseStyleSheetResource("test2.css");
 		final Styles styles = ss.getStyles(inherit);
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java
index abfffa3..432bd2e 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java
@@ -14,10 +14,11 @@
 import static org.junit.Assert.assertNull;
 
 import java.io.StringReader;
+import java.util.Iterator;
 
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.core.DisplayDevice;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Element;
 import org.eclipse.vex.core.internal.io.DocumentReader;
 import org.junit.Test;
 import org.w3c.css.sac.InputSource;
@@ -112,10 +113,11 @@
 		final LexicalUnit attrSrc = MockLU.createAttr("src");
 		final Styles styles = new Styles();
 		final Styles parentStyles = new Styles();
-		final Document document = new DocumentReader().read("<root><image/><image src=\"image.jpg\"/><image src=\"\"/></root>");
-		final Element noAttribute = document.getRootElement().getChildElements().get(0);
-		final Element setAttribute = document.getRootElement().getChildElements().get(1);
-		final Element emptyAttribute = document.getRootElement().getChildElements().get(2);
+		final IDocument document = new DocumentReader().read("<root><image/><image src=\"image.jpg\"/><image src=\"\"/></root>");
+		final Iterator<? extends IElement> childElements = document.getRootElement().childElements().iterator();
+		final IElement noAttribute = childElements.next();
+		final IElement setAttribute = childElements.next();
+		final IElement emptyAttribute = childElements.next();
 		final BackgroundImageProperty property = new BackgroundImageProperty();
 
 		assertNull(property.calculate(attrSrc, parentStyles, styles, noAttribute));
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/RuleTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/RuleTest.java
index 91f3ea4..28166b9 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/RuleTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/RuleTest.java
@@ -17,8 +17,9 @@
 import java.util.List;
 
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Element;
 import org.junit.Test;
 
 /**
@@ -33,13 +34,13 @@
 		final StyleSheet ss = reader.read(url);
 		final List<Rule> rules = ss.getRules();
 
-		final Document doc = new Document(new QualifiedName(null, "a"));
-		final Element a = doc.getRootElement();
-		final Element b = doc.insertElement(2, new QualifiedName(null, "b"));
-		final Element c = doc.insertElement(3, new QualifiedName(null, "c"));
-		final Element d = doc.insertElement(4, new QualifiedName(null, "d"));
-		final Element e = doc.insertElement(5, new QualifiedName(null, "e"));
-		final Element f = doc.insertElement(6, new QualifiedName(null, "f"));
+		final IDocument doc = new Document(new QualifiedName(null, "a"));
+		final IElement a = doc.getRootElement();
+		final IElement b = doc.insertElement(2, new QualifiedName(null, "b"));
+		final IElement c = doc.insertElement(3, new QualifiedName(null, "c"));
+		final IElement d = doc.insertElement(4, new QualifiedName(null, "d"));
+		final IElement e = doc.insertElement(5, new QualifiedName(null, "e"));
+		final IElement f = doc.insertElement(6, new QualifiedName(null, "f"));
 
 		b.setAttribute("color", "blue");
 		c.setAttribute("color", "blue red");
@@ -270,9 +271,9 @@
 		final StyleSheet ss = reader.read(url);
 		final List<Rule> rules = ss.getRules();
 
-		final Document doc = new Document(new QualifiedName(null, "a"));
-		final Element a = doc.getRootElement();
-		final Element ns = doc.insertElement(2, new QualifiedName("http://namespace/uri", "b"));
+		final IDocument doc = new Document(new QualifiedName(null, "a"));
+		final IElement a = doc.getRootElement();
+		final IElement ns = doc.insertElement(2, new QualifiedName("http://namespace/uri", "b"));
 
 		ns.setAttribute("color", "blue");
 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AxisTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AxisTest.java
index 478cd08..bb20130 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AxisTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AxisTest.java
@@ -21,7 +21,13 @@
 import java.util.NoSuchElementException;

 

 import org.eclipse.core.runtime.AssertionFailedException;

-import org.eclipse.vex.core.internal.core.IFilter;

+import org.eclipse.vex.core.IFilter;

+import org.eclipse.vex.core.dom.BaseNodeVisitor;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IAxis;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.INodeVisitor;

+import org.eclipse.vex.core.dom.INodeVisitorWithResult;

 import org.junit.Before;

 import org.junit.Test;

 

@@ -76,8 +82,8 @@
 

 	@Test

 	public void givenAxis_whenNotEmpty_shouldProvideNodesAsList() throws Exception {

-		final List<Node> expectedNodes = Arrays.<Node> asList(new TestNode("one"), new TestNode("two"), new TestNode("three"));

-		final List<Node> actualNodes = axis(source, expectedNodes).asList();

+		final List<INode> expectedNodes = Arrays.<INode> asList(new TestNode("one"), new TestNode("two"), new TestNode("three"));

+		final List<? extends INode> actualNodes = axis(source, expectedNodes).asList();

 		assertTrue(Arrays.equals(expectedNodes.toArray(), actualNodes.toArray()));

 	}

 

@@ -106,8 +112,8 @@
 	@Test

 	public void givenAxisWithElements_whenFilterIsGiven_shouldProvideOnlyMatchingNodes() throws Exception {

 		int actualNodeCount = 0;

-		for (final Node actualNode : axis(source, nodes("matching", "matching", "not", "not", "matching")).matching(new IFilter<Node>() {

-			public boolean matches(final Node node) {

+		for (final INode actualNode : axis(source, nodes("matching", "matching", "not", "not", "matching")).matching(new IFilter<INode>() {

+			public boolean matches(final INode node) {

 				return "matching".equals(((TestNode) node).getName());

 			}

 		})) {

@@ -119,7 +125,7 @@
 

 	@Test

 	public void givenAxisWithElements_whenEndIndexIsGiven_shouldProvideOnlyNodesUpToEndIndex() throws Exception {

-		final Iterator<Node> actualNodes = axis(source, nodes("one", "two", "three")).to(1).iterator();

+		final Iterator<? extends INode> actualNodes = axis(source, nodes("one", "two", "three")).to(1).iterator();

 		assertEquals("one", actualNodes.next().toString());

 		assertEquals("two", actualNodes.next().toString());

 		assertFalse(actualNodes.hasNext());

@@ -132,7 +138,7 @@
 

 	@Test

 	public void givenAxisWithElements_whenStartIndexIsGiven_shouldProvideOnlyNodesFromStartIndex() throws Exception {

-		final Iterator<Node> actualNodes = axis(source, nodes("one", "two", "three")).from(1).iterator();

+		final Iterator<? extends INode> actualNodes = axis(source, nodes("one", "two", "three")).from(1).iterator();

 		assertEquals("two", actualNodes.next().toString());

 		assertEquals("three", actualNodes.next().toString());

 		assertFalse(actualNodes.hasNext());

@@ -145,28 +151,28 @@
 

 	@Test

 	public void givenAxisWithElements_whenStartAndEndIndexAreGiven_shouldProvideOnlyNodesFromStartToEndIndex() throws Exception {

-		final Iterator<Node> actualNodes = axis(source, nodes("one", "two", "three", "four", "five")).from(1).to(2).iterator();

+		final Iterator<?> actualNodes = axis(source, nodes("one", "two", "three", "four", "five")).from(1).to(2).iterator();

 		assertEquals("two", actualNodes.next().toString());

 		assertEquals("three", actualNodes.next().toString());

 		assertFalse(actualNodes.hasNext());

 	}

 

-	private static Axis axis(final Node sourceNode, final Iterable<Node> source) {

-		return new Axis(sourceNode) {

+	private static IAxis<INode> axis(final INode sourceNode, final Iterable<INode> source) {

+		return new Axis<INode>(sourceNode) {

 			@Override

-			protected Iterator<Node> createRootIterator(final ContentRange contentRange, final boolean includeText) {

+			protected Iterator<INode> createRootIterator(final ContentRange contentRange, final boolean includeText) {

 				return source.iterator();

 			}

 

 		};

 	}

 

-	private static Iterable<Node> nodes(final String... nodeNames) {

+	private static Iterable<INode> nodes(final String... nodeNames) {

 		return nodes(null, nodeNames);

 	}

 

-	private static Iterable<Node> nodes(final int[] visits, final String... nodeNames) {

-		final ArrayList<Node> result = new ArrayList<Node>();

+	private static Iterable<INode> nodes(final int[] visits, final String... nodeNames) {

+		final ArrayList<INode> result = new ArrayList<INode>();

 		for (final String nodeName : nodeNames) {

 			result.add(new TestNode(nodeName, visits));

 		}

@@ -196,12 +202,10 @@
 			return name;

 		}

 

-		@Override

-		public boolean isKindOf(final Node node) {

+		public boolean isKindOf(final INode node) {

 			return false;

 		}

 

-		@Override

 		public void accept(final INodeVisitor visitor) {

 			if (visits == null) {

 				throw new IllegalStateException();

@@ -209,7 +213,6 @@
 			visits[0]++;

 		}

 

-		@Override

 		public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 			throw new UnsupportedOperationException();

 		}

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BasicNodeTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BasicNodeTest.java
index 324e5b8..bd138f1 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BasicNodeTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BasicNodeTest.java
@@ -10,6 +10,10 @@
  *******************************************************************************/

 package org.eclipse.vex.core.internal.dom;

 

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.INodeVisitor;

+import org.eclipse.vex.core.dom.INodeVisitorWithResult;

+

 /**

  * @author Florian Thienel

  */

@@ -18,18 +22,15 @@
 	@Override

 	protected Node createNode() {

 		return new Node() {

-			@Override

 			public void accept(final INodeVisitor visitor) {

 				throw new UnsupportedOperationException();

 			}

 

-			@Override

 			public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 				throw new UnsupportedOperationException();

 			}

 

-			@Override

-			public boolean isKindOf(final Node node) {

+			public boolean isKindOf(final INode node) {

 				return false;

 			}

 		};

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BlockElementBoxTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BlockElementBoxTest.java
index 9504720..523f9e8 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BlockElementBoxTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/BlockElementBoxTest.java
@@ -17,6 +17,7 @@
 import java.lang.reflect.Method;
 import java.util.List;
 
+import org.eclipse.vex.core.dom.IDocument;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
@@ -55,7 +56,7 @@
 		final String docString = "<root><small/><medium/><large/></root>";
 		final DocumentReader docReader = new DocumentReader();
 		docReader.setDebugging(true);
-		final Document doc = docReader.read(docString);
+		final IDocument doc = docReader.read(docString);
 		context.setDocument(doc);
 
 		final RootBox parentBox = new RootBox(context, doc, 500);
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/RangeTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentRangeTest.java
similarity index 97%
rename from org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/RangeTest.java
rename to org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentRangeTest.java
index b77910d..560a412 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/RangeTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentRangeTest.java
@@ -15,12 +15,10 @@
 import static org.junit.Assert.assertTrue;

 

 import org.eclipse.core.runtime.AssertionFailedException;

+import org.eclipse.vex.core.dom.ContentRange;

 import org.junit.Test;

 

-/**

- * @author Florian Thienel

- */

-public class RangeTest {

+public class ContentRangeTest {

 

 	@Test

 	public void hasStartAndEndOffset() throws Exception {

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentTest.java
index d967e26..9b092d0 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ContentTest.java
@@ -14,19 +14,22 @@
 import static org.junit.Assert.assertFalse;

 import static org.junit.Assert.assertTrue;

 

+import org.eclipse.vex.core.dom.IContent;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IPosition;

 import org.junit.Before;

 import org.junit.Test;

 

 public abstract class ContentTest {

 

-	private Content content;

+	private IContent content;

 

 	@Before

 	public void setUp() throws Exception {

 		content = createContent();

 	}

 

-	protected abstract Content createContent();

+	protected abstract IContent createContent();

 

 	@Test

 	public void insertText() throws Exception {

@@ -64,7 +67,7 @@
 	public void shouldReturnAPartialCopy() throws Exception {

 		final String text = "Hello World";

 		content.insertText(0, text);

-		final Content partialCopy = content.getContent(new ContentRange(3, 7));

+		final IContent partialCopy = content.getContent(new ContentRange(3, 7));

 		assertEquals("lo Wo", partialCopy.getText());

 

 		// make shure, it is a copy

@@ -77,7 +80,7 @@
 	public void shouldReturnAFullCopy() throws Exception {

 		final String text = "Hello World";

 		content.insertText(0, text);

-		final Content fullCopy = content.getContent();

+		final IContent fullCopy = content.getContent();

 		assertEquals(text, fullCopy.getText());

 

 		// make shure, it is a copy

@@ -89,7 +92,7 @@
 	@Test

 	public void insertContent() throws Exception {

 		content.insertText(0, "Hello World");

-		final Content other = createContent();

+		final IContent other = createContent();

 		other.insertTagMarker(0);

 		other.insertText(1, "New");

 		other.insertTagMarker(4);

@@ -121,8 +124,8 @@
 	@Test

 	public void shouldIncreasePositionsOnInsertText() throws Exception {

 		content.insertText(0, "Hello World");

-		final Position helloPosition = content.createPosition(0);

-		final Position worldPosition = content.createPosition(6);

+		final IPosition helloPosition = content.createPosition(0);

+		final IPosition worldPosition = content.createPosition(6);

 		assertEquals("Hello", content.getText(new ContentRange(helloPosition.getOffset(), helloPosition.getOffset() + 4)));

 		assertEquals("World", content.getText(new ContentRange(worldPosition.getOffset(), worldPosition.getOffset() + 4)));

 

@@ -136,8 +139,8 @@
 	@Test

 	public void shouldIncreasePositionsOnInsertTagMarker() throws Exception {

 		content.insertText(0, "Hello World");

-		final Position worldStartPosition = content.createPosition(6);

-		final Position worldEndPosition = content.createPosition(10);

+		final IPosition worldStartPosition = content.createPosition(6);

+		final IPosition worldEndPosition = content.createPosition(10);

 		assertEquals("d", content.getText(new ContentRange(worldEndPosition.getOffset(), worldEndPosition.getOffset())));

 		assertEquals("World", content.getText(new ContentRange(worldStartPosition.getOffset(), worldEndPosition.getOffset())));

 

@@ -156,8 +159,8 @@
 		content.insertText(0, "Hello New World");

 		content.insertTagMarker(8);

 		content.insertTagMarker(6);

-		final Position worldStartPosition = content.createPosition(12);

-		final Position worldEndPosition = content.createPosition(16);

+		final IPosition worldStartPosition = content.createPosition(12);

+		final IPosition worldEndPosition = content.createPosition(16);

 		assertEquals("d", content.getText(new ContentRange(worldEndPosition.getOffset(), worldEndPosition.getOffset())));

 		assertEquals("World", content.getText(new ContentRange(worldStartPosition.getOffset(), worldEndPosition.getOffset())));

 

@@ -171,9 +174,9 @@
 	@Test

 	public void shouldMovePositionsWithinRemovedRangeToRangeStart() throws Exception {

 		content.insertText(0, "Hello New World");

-		final Position nPosition = content.createPosition(6);

-		final Position ePosition = content.createPosition(7);

-		final Position wPosition = content.createPosition(8);

+		final IPosition nPosition = content.createPosition(6);

+		final IPosition ePosition = content.createPosition(7);

+		final IPosition wPosition = content.createPosition(8);

 

 		content.remove(new ContentRange(6, 8));

 

@@ -186,7 +189,7 @@
 	public void canRemovePosition() throws Exception {

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

-		final Position position = content.createPosition(1);

+		final IPosition position = content.createPosition(1);

 		assertEquals(1, position.getOffset());

 

 		content.removePosition(position);

@@ -198,7 +201,7 @@
 	public void invalidatesPositionsOnRemoval() throws Exception {

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

-		final Position position = content.createPosition(1);

+		final IPosition position = content.createPosition(1);

 		assertTrue(position.isValid());

 		content.removePosition(position);

 		assertFalse(position.isValid());

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/CopyVisitorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/CopyVisitorTest.java
index eafd060..3d2b94a 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/CopyVisitorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/CopyVisitorTest.java
@@ -16,6 +16,8 @@
 import java.util.Collections;

 

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IElement;

 import org.junit.Test;

 

 /**

@@ -50,7 +52,7 @@
 		element.declareNamespace("ns1", "additionalNamespaceUri1");

 		element.declareNamespace("ns2", "additionalNamespaceUri2");

 

-		final Element copy = (Element) element.accept(new CopyVisitor());

+		final IElement copy = (IElement) element.accept(new CopyVisitor());

 

 		assertEquals(new QualifiedName(null, "element"), copy.getQualifiedName());

 		assertEquals(2, copy.getAttributes().size());

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DTDValidatorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DTDValidatorTest.java
index 5a23556..9ab7bc9 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DTDValidatorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DTDValidatorTest.java
@@ -23,6 +23,9 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.IValidator;
 import org.eclipse.vex.core.internal.validator.AttributeDefinition;
 import org.eclipse.vex.core.internal.validator.WTPVEXValidator;
 import org.eclipse.vex.core.tests.TestResources;
@@ -31,7 +34,7 @@
 
 public class DTDValidatorTest {
 
-	private Validator validator = null;
+	private IValidator validator = null;
 
 	@Before
 	public void setUp() {
@@ -44,9 +47,9 @@
 
 	@Test
 	public void testAttributeDefinition() throws Exception {
-		final Document doc = new Document(new QualifiedName(null, "section"));
+		final IDocument doc = new Document(new QualifiedName(null, "section"));
 		doc.setValidator(validator);
-		final Element sectionElement = doc.getRootElement();
+		final IElement sectionElement = doc.getRootElement();
 		final AttributeDefinition.Type adType = validator.getAttributeDefinitions(sectionElement).get(0).getType();
 		final AttributeDefinition.Type adType2 = validator.getAttributeDefinitions(sectionElement).get(0).getType();
 
@@ -55,9 +58,9 @@
 
 	@Test
 	public void testEnumAttribute() throws Exception {
-		final Document doc = new Document(new QualifiedName(null, "section"));
+		final IDocument doc = new Document(new QualifiedName(null, "section"));
 		doc.setValidator(validator);
-		final Element sectionElement = doc.getRootElement();
+		final IElement sectionElement = doc.getRootElement();
 		final AttributeDefinition attributeDefinition = validator.getAttributeDefinitions(sectionElement).get(0);
 		assertEquals("enatt", attributeDefinition.getName());
 
@@ -96,7 +99,7 @@
 	public void testSectionElement() {
 		// <section> <title> a b </title> <para> </para> </section>
 		// 1 2 3 4 5 6 7
-		final Document doc = new Document(new QualifiedName(null, "section"));
+		final IDocument doc = new Document(new QualifiedName(null, "section"));
 		doc.setValidator(validator);
 		doc.insertElement(2, new QualifiedName(null, "title"));
 		doc.insertText(3, "ab");
@@ -115,18 +118,18 @@
 
 	@Test
 	public void testOneKindOfChild() {
-		final Document doc = new Document(new QualifiedName(null, "one-kind-of-child"));
+		final IDocument doc = new Document(new QualifiedName(null, "one-kind-of-child"));
 		doc.setValidator(validator);
 		assertValidItemsAt(doc, 2, "section");
 	}
 
-	private static void assertValidItemsAt(final Document doc, final int offset, final String... expectedItems) {
+	private static void assertValidItemsAt(final IDocument doc, final int offset, final String... expectedItems) {
 		final Set<QualifiedName> expected = new HashSet<QualifiedName>(expectedItems.length);
 		for (final String expectedItem : expectedItems) {
 			expected.add(new QualifiedName(null, expectedItem));
 		}
 
-		Element element = doc.getElementForInsertionAt(offset);
+		IElement element = doc.getElementForInsertionAt(offset);
 		if (element == null) {
 			assertEquals(0, expectedItems.length);
 			return;
@@ -172,7 +175,7 @@
 
 	@Test
 	public void testValidateDocumentWithDTDAndNamespaces() throws Exception {
-		final Document doc = new Document(new QualifiedName("http://namespace/uri/is/not/registered", "section"));
+		final IDocument doc = new Document(new QualifiedName("http://namespace/uri/is/not/registered", "section"));
 		doc.setValidator(validator);
 		doc.insertElement(2, new QualifiedName(null, "title"));
 		doc.insertText(3, "ab");
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DeepCopyTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DeepCopyTest.java
index 9c3535c..27f82a0 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DeepCopyTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DeepCopyTest.java
@@ -19,6 +19,11 @@
 import java.util.Iterator;

 import java.util.List;

 

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IContent;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.IText;

 import org.junit.Test;

 

 /**

@@ -48,7 +53,7 @@
 		content.insertText(1, "Hello World");

 

 		final DeepCopy deepCopy = new DeepCopy(element);

-		final Content copiedContent = deepCopy.getContent();

+		final IContent copiedContent = deepCopy.getContent();

 

 		assertNotNull(copiedContent);

 		assertNotSame(content, copiedContent);

@@ -68,7 +73,7 @@
 		content.insertText(0, "Hello");

 

 		final DeepCopy deepCopy = new DeepCopy(element);

-		final Content copiedContent = deepCopy.getContent();

+		final IContent copiedContent = deepCopy.getContent();

 

 		assertEquals(7, copiedContent.length());

 		assertEquals(" New ", copiedContent.getText());

@@ -104,16 +109,16 @@
 

 		final DeepCopy deepCopy = new DeepCopy(parent);

 		final Element copiedParent = (Element) deepCopy.getNodes().get(0);

-		final Iterator<Node> copiedChildren = copiedParent.children().iterator();

+		final Iterator<INode> copiedChildren = copiedParent.children().iterator();

 

-		assertEquals("1", ((Element) copiedChildren.next()).getAttribute("order").getValue());

-		assertEquals("2", ((Element) copiedChildren.next()).getAttribute("order").getValue());

+		assertEquals("1", ((IElement) copiedChildren.next()).getAttribute("order").getValue());

+		assertEquals("2", ((IElement) copiedChildren.next()).getAttribute("order").getValue());

 		assertFalse(copiedChildren.hasNext());

 	}

 

 	@Test

 	public void givenOneParentWithTwoChildrenAndContent_shouldCopyParentChildrenAndContent() throws Exception {

-		final Content content = new GapContent(10);

+		final IContent content = new GapContent(10);

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

@@ -134,7 +139,7 @@
 

 		final DeepCopy deepCopy = new DeepCopy(parent);

 		final Element copiedParent = (Element) deepCopy.getNodes().get(0);

-		final Iterator<Node> copiedChildren = copiedParent.children().iterator();

+		final Iterator<INode> copiedChildren = copiedParent.children().iterator();

 

 		assertNodeIsAssociatedElementWithText("Hello", copiedChildren.next());

 		assertNodeIsAssociatedText(" New ", copiedChildren.next());

@@ -144,7 +149,7 @@
 

 	@Test

 	public void givenOneParentWithTwoChildrenInHugeContent_shouldCopyOnlyRelevantContent() throws Exception {

-		final Content content = new GapContent(10);

+		final IContent content = new GapContent(10);

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

@@ -172,7 +177,7 @@
 

 	@Test

 	public void givenOneParentWithTwoChildrenAndContent_whenGivenRange_shouldOnlyCopyChildrenAndContentWithinRange() throws Exception {

-		final Content content = new GapContent(10);

+		final IContent content = new GapContent(10);

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

@@ -202,7 +207,7 @@
 

 	@Test

 	public void givenOneParentWithTwoCommentChildren_shouldCopyParentAndChildren() throws Exception {

-		final Content content = new GapContent(10);

+		final IContent content = new GapContent(10);

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

 		content.insertTagMarker(0);

@@ -222,22 +227,22 @@
 

 		final DeepCopy deepCopy = new DeepCopy(parent);

 		final Element copiedParent = (Element) deepCopy.getNodes().get(0);

-		final Iterator<Node> copiedChildren = copiedParent.children().iterator();

+		final Iterator<INode> copiedChildren = copiedParent.children().iterator();

 

 		assertEquals("Hello", copiedChildren.next().getText());

 		assertEquals("World", copiedChildren.next().getText());

 		assertFalse(copiedChildren.hasNext());

 	}

 

-	private static void assertNodeIsAssociatedElementWithText(final String expectedText, final Node actualNode) {

+	private static void assertNodeIsAssociatedElementWithText(final String expectedText, final INode actualNode) {

 		assertTrue(actualNode.isAssociated());

 		assertTrue(actualNode instanceof Element);

 		assertEquals(expectedText, actualNode.getText());

 	}

 

-	private static void assertNodeIsAssociatedText(final String expectedText, final Node actualNode) {

+	private static void assertNodeIsAssociatedText(final String expectedText, final INode actualNode) {

 		assertTrue(actualNode.isAssociated());

-		assertTrue(actualNode instanceof Text);

+		assertTrue(actualNode instanceof IText);

 		assertEquals(expectedText, actualNode.getText());

 	}

 }

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentFragmentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentFragmentTest.java
index 2bc078b..d734cc5 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentFragmentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentFragmentTest.java
@@ -21,6 +21,9 @@
 import java.util.Iterator;

 

 import org.eclipse.core.runtime.AssertionFailedException;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.IText;

 import org.junit.Test;

 

 /**

@@ -48,8 +51,8 @@
 		final GapContent content = new GapContent(3);

 		content.insertText(0, "abc");

 		final DocumentFragment fragment = new DocumentFragment(content, Collections.<Node> emptyList());

-		final Iterator<Node> actualChildren = fragment.children().iterator();

-		assertTrue(actualChildren.next() instanceof Text);

+		final Iterator<INode> actualChildren = fragment.children().iterator();

+		assertTrue(actualChildren.next() instanceof IText);

 		assertFalse(actualChildren.hasNext());

 	}

 

@@ -66,7 +69,7 @@
 		child2.associate(content, new ContentRange(2, 3));

 

 		final DocumentFragment fragment = new DocumentFragment(content, Arrays.<Node> asList(child1, child2));

-		final Iterator<Node> actualChildren = fragment.children().iterator();

+		final Iterator<INode> actualChildren = fragment.children().iterator();

 		assertSame(child1, actualChildren.next());

 		assertSame(child2, actualChildren.next());

 		assertFalse(actualChildren.hasNext());

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java
index 9a07a4c..66eca6a 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java
@@ -20,6 +20,12 @@
 

 import org.eclipse.core.runtime.AssertionFailedException;

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IDocumentFragment;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.IParent;

 import org.junit.Test;

 

 /**

@@ -54,69 +60,69 @@
 

 	@Test

 	public void createFragmentWithTextAndChild() throws Exception {

-		final Document document = new Document(new QualifiedName(null, "root"));

-		final Element childElement = document.insertElement(2, new QualifiedName(null, "child"));

+		final IDocument document = new Document(new QualifiedName(null, "root"));

+		final IElement childElement = document.insertElement(2, new QualifiedName(null, "child"));

 		document.insertText(childElement.getStartOffset(), "Hello ");

 		document.insertText(childElement.getEndOffset(), "Child");

 		document.insertText(childElement.getEndOffset() + 1, " World");

 		final ContentRange range = childElement.getRange().resizeBy(-2, 2);

-		final DocumentFragment fragment = document.getFragment(range);

+		final IDocumentFragment fragment = document.getFragment(range);

 		assertEquals(11, fragment.getLength());

 		assertNodesEqual(document.getNodes(range), fragment.getNodes(), range.getStartOffset());

 	}

 

 	@Test

 	public void createFragmentWithExactlyOneChild() throws Exception {

-		final Document document = new Document(new QualifiedName(null, "root"));

-		final Element childElement = document.insertElement(2, new QualifiedName(null, "child"));

+		final IDocument document = new Document(new QualifiedName(null, "root"));

+		final IElement childElement = document.insertElement(2, new QualifiedName(null, "child"));

 		document.insertText(childElement.getEndOffset(), "Child");

 		final ContentRange range = childElement.getRange();

-		final DocumentFragment fragment = document.getFragment(range);

+		final IDocumentFragment fragment = document.getFragment(range);

 		assertEquals(7, fragment.getLength());

 		assertNodesEqual(document.getNodes(range), fragment.getNodes(), range.getStartOffset());

 	}

 

 	@Test

 	public void givenElementWithText_whenRangeBeginsFromStartOffset_shouldProvideParentAsCommenNode() throws Exception {

-		final Document document = new Document(new QualifiedName(null, "root"));

-		final Element childElement = document.insertElement(2, new QualifiedName(null, "child"));

+		final IDocument document = new Document(new QualifiedName(null, "root"));

+		final IElement childElement = document.insertElement(2, new QualifiedName(null, "child"));

 		document.insertText(childElement.getEndOffset(), "Hello World");

 

-		final Node commonNode = document.findCommonNode(childElement.getStartOffset(), childElement.getEndOffset() - 5);

+		final INode commonNode = document.findCommonNode(childElement.getStartOffset(), childElement.getEndOffset() - 5);

 

 		assertSame(document.getRootElement(), commonNode);

 	}

 

 	@Test

 	public void givenElementWithText_whenRangeWithinText_shouldProvideElementAsCommonNode() throws Exception {

-		final Document document = new Document(new QualifiedName(null, "root"));

-		final Element childElement = document.insertElement(2, new QualifiedName(null, "child"));

+		final IDocument document = new Document(new QualifiedName(null, "root"));

+		final IElement childElement = document.insertElement(2, new QualifiedName(null, "child"));

 		document.insertText(childElement.getEndOffset(), "Hello World");

 

-		final Node commonNode = document.findCommonNode(childElement.getStartOffset() + 2, childElement.getEndOffset() - 5);

+		final INode commonNode = document.findCommonNode(childElement.getStartOffset() + 2, childElement.getEndOffset() - 5);

 

 		assertSame(childElement, commonNode);

 	}

 

 	@Test

 	public void insertFragmentWithChildGrandChildAndText() throws Exception {

-		final Document document = new Document(new QualifiedName(null, "root"));

-		final Element child = document.insertElement(2, new QualifiedName(null, "child"));

+		final IDocument document = new Document(new QualifiedName(null, "root"));

+		final IElement child = document.insertElement(2, new QualifiedName(null, "child"));

 		document.insertText(child.getEndOffset(), "Hello ");

-		final Element grandChild = document.insertElement(child.getEndOffset(), new QualifiedName(null, "grandchild"));

+		final IElement grandChild = document.insertElement(child.getEndOffset(), new QualifiedName(null, "grandchild"));

 		document.insertText(grandChild.getEndOffset(), "Grandchild");

 		document.insertText(child.getEndOffset(), " World");

 

-		final DocumentFragment expectedFragment = document.getFragment(child.getRange());

+		final IDocumentFragment expectedFragment = document.getFragment(child.getRange());

 		document.insertFragment(document.getRootElement().getEndOffset(), expectedFragment);

-		final DocumentFragment actualFragment = document.getFragment(new ContentRange(child.getEndOffset() + 1, document.getRootElement().getEndOffset() - 1));

+		final IDocumentFragment actualFragment = document.getFragment(new ContentRange(child.getEndOffset() + 1, document.getRootElement().getEndOffset() - 1));

 

 		assertNodeEquals(expectedFragment, actualFragment, 0);

 	}

 

-	private static void assertNodesEqual(final Iterable<Node> expected, final Iterable<Node> actual, final int rangeOffsetExpected) {

-		final Iterator<Node> expectedIterator = expected.iterator();

-		final Iterator<Node> actualIterator = actual.iterator();

+	private static void assertNodesEqual(final Iterable<? extends INode> expected, final Iterable<? extends INode> actual, final int rangeOffsetExpected) {

+		final Iterator<? extends INode> expectedIterator = expected.iterator();

+		final Iterator<? extends INode> actualIterator = actual.iterator();

 		while (expectedIterator.hasNext() && actualIterator.hasNext()) {

 			assertNodeEquals(expectedIterator.next(), actualIterator.next(), rangeOffsetExpected);

 		}

@@ -124,16 +130,16 @@
 		assertFalse("less elements expected", actualIterator.hasNext());

 	}

 

-	private static void assertNodeEquals(final Node expected, final Node actual, final int rangeOffsetExpected) {

+	private static void assertNodeEquals(final INode expected, final INode actual, final int rangeOffsetExpected) {

 		assertSame("node class", expected.getClass(), actual.getClass());

 		assertEquals("node range", expected.getRange(), actual.getRange().moveBy(rangeOffsetExpected));

 		assertEquals("node text", expected.getText(), actual.getText());

-		if (expected instanceof Parent) {

-			assertNodesEqual(((Parent) expected).children(), ((Parent) actual).children(), rangeOffsetExpected);

+		if (expected instanceof IParent) {

+			assertNodesEqual(((IParent) expected).children(), ((IParent) actual).children(), rangeOffsetExpected);

 		}

 	}

 

-	private static void assertDocumentConnectedToRootElement(final Element rootElement, final Document document) {

+	private static void assertDocumentConnectedToRootElement(final IElement rootElement, final Document document) {

 		assertNotNull(document.getContent());

 		assertTrue(document.isAssociated());

 		assertTrue(rootElement.isAssociated());

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DummyValidator.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DummyValidator.java
index 64503c9..7e0be59 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DummyValidator.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DummyValidator.java
@@ -15,18 +15,21 @@
 import java.util.Set;

 

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.IAttribute;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.dom.IValidator;

 import org.eclipse.vex.core.internal.validator.AttributeDefinition;

 

 /**

  * @author Florian Thienel

  */

-public class DummyValidator implements Validator {

+public class DummyValidator implements IValidator {

 

-	public AttributeDefinition getAttributeDefinition(final Attribute attribute) {

+	public AttributeDefinition getAttributeDefinition(final IAttribute attribute) {

 		return null;

 	}

 

-	public List<AttributeDefinition> getAttributeDefinitions(final Element element) {

+	public List<AttributeDefinition> getAttributeDefinitions(final IElement element) {

 		return Collections.emptyList();

 	}

 

@@ -34,7 +37,7 @@
 		return Collections.emptySet();

 	}

 

-	public Set<QualifiedName> getValidItems(final Element element) {

+	public Set<QualifiedName> getValidItems(final IElement element) {

 		return Collections.emptySet();

 	}

 

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/GapContentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/GapContentTest.java
index 7e273c9..e43ba34 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/GapContentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/GapContentTest.java
@@ -15,6 +15,9 @@
 import static org.junit.Assert.fail;
 
 import org.eclipse.core.runtime.AssertionFailedException;
+import org.eclipse.vex.core.dom.IContent;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.IPosition;
 import org.junit.Test;
 
 /**
@@ -23,7 +26,7 @@
 public class GapContentTest extends ContentTest {
 
 	@Override
-	protected Content createContent() {
+	protected IContent createContent() {
 		return new GapContent(100);
 	}
 
@@ -44,9 +47,9 @@
 	public void givenAnOffset_whenInvokedMultipleTimes_shouldNotCreateMultiplePositionInstances() throws Exception {
 		final GapContent gapContent = new GapContent(4);
 		gapContent.insertTagMarker(0);
-		final Position firstPosition = gapContent.createPosition(0);
+		final IPosition firstPosition = gapContent.createPosition(0);
 		assertEquals(1, gapContent.getPositionCount());
-		final Position secondPosition = gapContent.createPosition(0);
+		final IPosition secondPosition = gapContent.createPosition(0);
 		assertEquals(1, gapContent.getPositionCount());
 		assertSame(firstPosition, secondPosition);
 	}
@@ -70,11 +73,11 @@
 		content.insertText(1, "b");
 		assertEquals(4, content.length());
 
-		final Position pa = content.createPosition(0);
-		final Position pb = content.createPosition(1);
-		final Position pc = content.createPosition(2);
-		final Position pd = content.createPosition(3);
-		final Position pe = content.createPosition(4);
+		final IPosition pa = content.createPosition(0);
+		final IPosition pb = content.createPosition(1);
+		final IPosition pc = content.createPosition(2);
+		final IPosition pd = content.createPosition(3);
+		final IPosition pe = content.createPosition(4);
 
 		try {
 			content.getText(new ContentRange(-1, 0));
@@ -142,8 +145,8 @@
 		assertEquals(5, pd.getOffset());
 		assertEquals(6, pe.getOffset());
 
-		final Position px = content.createPosition(2);
-		final Position py = content.createPosition(3);
+		final IPosition px = content.createPosition(2);
+		final IPosition py = content.createPosition(3);
 
 		assertEquals("xy", content.getText(new ContentRange(2, 3)));
 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1CommentHandlingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1CommentHandlingTest.java
index c40e0c1..7711884 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1CommentHandlingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1CommentHandlingTest.java
@@ -19,6 +19,9 @@
 import java.util.List;

 

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.INode;

 import org.junit.Before;

 import org.junit.Test;

 

@@ -51,11 +54,11 @@
 

 	@Test

 	public void shouldInsertCommentAtValidInsertionPoint() throws Exception {

-		final Comment comment = document.insertComment(titleElement.getStartOffset());

+		final IComment comment = document.insertComment(titleElement.getStartOffset());

 

 		assertSame(rootElement, comment.getParent());

 		assertTrue(comment.isAssociated());

-		final Iterator<Node> actualChildren = rootElement.children().iterator();

+		final Iterator<INode> actualChildren = rootElement.children().iterator();

 		assertSame(comment, actualChildren.next());

 		assertSame(titleElement, actualChildren.next());

 	}

@@ -75,7 +78,7 @@
 				return "title".equals(element.getLocalName());

 			}

 		});

-		final Comment comment = document.insertComment(titleElement.getStartOffset());

+		final IComment comment = document.insertComment(titleElement.getStartOffset());

 		document.insertText(comment.getEndOffset(), "Hello World");

 

 		assertEquals("Hello World", comment.getText());

@@ -88,8 +91,8 @@
 

 	@Test

 	public void shouldInsertCommentBeforeRootElement() throws Exception {

-		final Comment comment = document.insertComment(rootElement.getStartOffset());

-		final Iterator<Node> actualChildren = document.children().iterator();

+		final IComment comment = document.insertComment(rootElement.getStartOffset());

+		final Iterator<INode> actualChildren = document.children().iterator();

 		assertSame(comment, actualChildren.next());

 		assertSame(rootElement, actualChildren.next());

 		assertFalse(actualChildren.hasNext());

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ElementHandlingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ElementHandlingTest.java
index c7f9b9b..986494d 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ElementHandlingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1ElementHandlingTest.java
@@ -19,6 +19,9 @@
 

 import org.eclipse.core.runtime.AssertionFailedException;

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IContent;

+import org.eclipse.vex.core.dom.ContentRange;

 import org.junit.Before;

 import org.junit.Test;

 

@@ -59,7 +62,7 @@
 

 	@Test

 	public void insertElementAtValidInsertionPoint() throws Exception {

-		final Content content = document.getContent();

+		final IContent content = document.getContent();

 		final int contentLengthBefore = content.length();

 		final Element newElement = document.insertElement(rootElement.getEndOffset(), VALID_CHILD);

 		assertEquals("validChild", newElement.getLocalName());

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1FragmentHandlingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1FragmentHandlingTest.java
index 43279fe..3ceffd4 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1FragmentHandlingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1FragmentHandlingTest.java
@@ -18,6 +18,11 @@
 import java.util.List;

 

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IContent;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IElement;

 import org.junit.Before;

 import org.junit.Test;

 

@@ -29,8 +34,8 @@
 	private static final QualifiedName VALID_CHILD = new QualifiedName(null, "validChild");

 	private static final QualifiedName INVALID_CHILD = new QualifiedName(null, "invalidChild");

 

-	private Document document;

-	private Element rootElement;

+	private IDocument document;

+	private IElement rootElement;

 

 	@Before

 	public void setUp() throws Exception {

@@ -71,8 +76,8 @@
 	public void insertFragmentAtValidInsertionPoint() throws Exception {

 		document.insertFragment(rootElement.getEndOffset(), createFragment(VALID_CHILD, VALID_CHILD));

 		assertTrue(rootElement.hasChildren());

-		assertEquals(VALID_CHILD, ((Element) rootElement.children().get(0)).getQualifiedName());

-		assertEquals(VALID_CHILD, ((Element) rootElement.children().get(1)).getQualifiedName());

+		assertEquals(VALID_CHILD, ((IElement) rootElement.children().get(0)).getQualifiedName());

+		assertEquals(VALID_CHILD, ((IElement) rootElement.children().get(1)).getQualifiedName());

 	}

 

 	@Test(expected = DocumentValidationException.class)

@@ -81,7 +86,7 @@
 	}

 

 	private static DocumentFragment createFragment(final QualifiedName... elementNames) {

-		final Content content = new GapContent(10);

+		final IContent content = new GapContent(10);

 		final List<Node> nodes = new ArrayList<Node>();

 		for (final QualifiedName elementName : elementNames) {

 			final int insertOffset = content.length();

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1TextHandlingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1TextHandlingTest.java
index 6cf5bd3..bb02195 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1TextHandlingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1TextHandlingTest.java
@@ -18,6 +18,7 @@
 

 import org.eclipse.core.runtime.AssertionFailedException;

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.DocumentValidationException;

 import org.junit.Before;

 import org.junit.Test;

 

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NamespaceTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NamespaceTest.java
index d4487ff..ee2a83c 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NamespaceTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NamespaceTest.java
@@ -22,6 +22,9 @@
 import javax.xml.parsers.ParserConfigurationException;

 

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.IAttribute;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IElement;

 import org.eclipse.vex.core.internal.io.DocumentReader;

 import org.eclipse.vex.core.internal.io.DocumentWriter;

 import org.junit.Test;

@@ -34,15 +37,15 @@
 

 	@Test

 	public void attributeQualifiedName() throws Exception {

-		final Attribute attributeWithoutNamespace = new Attribute(null, "localName", "value");

+		final IAttribute attributeWithoutNamespace = new Attribute(null, "localName", "value");

 		assertEquals("localName", attributeWithoutNamespace.getQualifiedName().toString());

-		final Attribute attributeWithNamespace = new Attribute(null, new QualifiedName("http://namespace/uri", "localName"), "value");

+		final IAttribute attributeWithNamespace = new Attribute(null, new QualifiedName("http://namespace/uri", "localName"), "value");

 		assertEquals("http://namespace/uri:localName", attributeWithNamespace.getQualifiedName().toString());

 	}

 

 	@Test

 	public void declareNamespace() throws Exception {

-		final Element element = new Element("element");

+		final IElement element = new Element("element");

 		assertNull(element.getNamespaceURI("nsPrefix"));

 		assertNull(element.getNamespacePrefix("http://namespace/uri"));

 

@@ -66,7 +69,7 @@
 

 	@Test

 	public void removeNamespaceDeclaration() throws Exception {

-		final Element element = new Element("element");

+		final IElement element = new Element("element");

 		element.declareNamespace("nsPrefix", "http://namespace/uri");

 		assertEquals("http://namespace/uri", element.getNamespaceURI("nsPrefix"));

 		assertEquals("nsPrefix", element.getNamespacePrefix("http://namespace/uri"));

@@ -78,7 +81,7 @@
 

 	@Test

 	public void overloadNamespaceDeclaration() throws Exception {

-		final Element element = new Element("element");

+		final IElement element = new Element("element");

 		element.declareNamespace("nsPrefix", "http://namespace/uri");

 		element.declareNamespace("nsPrefix2", "http://namespace/uri");

 		assertEquals("http://namespace/uri", element.getNamespaceURI("nsPrefix"));

@@ -103,7 +106,7 @@
 

 	@Test

 	public void ignoreEmptyNamespaceURI() throws Exception {

-		final Element element = new Element("element");

+		final IElement element = new Element("element");

 		element.declareNamespace("nsPrefix", null);

 		assertNull(element.getNamespaceURI("nsPrefix"));

 		assertNull(element.getNamespacePrefix(null));

@@ -120,7 +123,7 @@
 

 	@Test

 	public void handleDefaultNamespace() throws Exception {

-		final Element element = new Element("element");

+		final IElement element = new Element("element");

 		assertNull(element.getDefaultNamespaceURI());

 		element.declareDefaultNamespace("http://namespace/uri");

 		assertEquals("http://namespace/uri", element.getDefaultNamespaceURI());

@@ -167,51 +170,51 @@
 

 	@Test

 	public void elementLocalName() throws Exception {

-		final Element elementWithoutNamespace = new Element("localName");

+		final IElement elementWithoutNamespace = new Element("localName");

 		assertEquals("localName", elementWithoutNamespace.getLocalName());

-		final Element elementWithNamespace = new Element(new QualifiedName("http://namespace/uri", "localName"));

+		final IElement elementWithNamespace = new Element(new QualifiedName("http://namespace/uri", "localName"));

 		assertEquals("localName", elementWithNamespace.getLocalName());

 	}

 

 	@Test

 	public void elementQualifiedName() throws Exception {

-		final Element elementWithoutNamespace = new Element("localName");

+		final IElement elementWithoutNamespace = new Element("localName");

 		assertEquals("localName", elementWithoutNamespace.getQualifiedName().toString());

-		final Element elementWithNamespace = new Element(new QualifiedName("http://namespace/uri", "localName"));

+		final IElement elementWithNamespace = new Element(new QualifiedName("http://namespace/uri", "localName"));

 		assertEquals("http://namespace/uri:localName", elementWithNamespace.getQualifiedName().toString());

 	}

 

 	@Test

 	public void elementPrefix() throws Exception {

-		final Element elementWithoutNamespace = new Element("element");

+		final IElement elementWithoutNamespace = new Element("element");

 		assertNull(elementWithoutNamespace.getPrefix());

 

-		final Element elementWithNamespace = new Element(new QualifiedName("http://namespace/uri", "element"));

+		final IElement elementWithNamespace = new Element(new QualifiedName("http://namespace/uri", "element"));

 		elementWithNamespace.declareNamespace("nsPrefix", "http://namespace/uri");

 		assertEquals("nsPrefix", elementWithNamespace.getPrefix());

 

-		final Element elementWithDefaultNamespace = new Element(new QualifiedName("http://namespace/uri", "element"));

+		final IElement elementWithDefaultNamespace = new Element(new QualifiedName("http://namespace/uri", "element"));

 		elementWithDefaultNamespace.declareDefaultNamespace("http://namespace/uri");

 		assertNull(elementWithDefaultNamespace.getPrefix());

 	}

 

 	@Test

 	public void elementPrefixedName() throws Exception {

-		final Element elementWithoutNamespace = new Element("element");

+		final IElement elementWithoutNamespace = new Element("element");

 		assertEquals("element", elementWithoutNamespace.getPrefixedName());

 

-		final Element elementWithNamespace = new Element(new QualifiedName("http://namespace/uri", "element"));

+		final IElement elementWithNamespace = new Element(new QualifiedName("http://namespace/uri", "element"));

 		elementWithNamespace.declareNamespace("nsPrefix", "http://namespace/uri");

 		assertEquals("nsPrefix:element", elementWithNamespace.getPrefixedName());

 

-		final Element elementWithDefaultNamespace = new Element(new QualifiedName("http://namespace/uri", "element"));

+		final IElement elementWithDefaultNamespace = new Element(new QualifiedName("http://namespace/uri", "element"));

 		elementWithDefaultNamespace.declareDefaultNamespace("http://namespace/uri");

 		assertEquals("element", elementWithDefaultNamespace.getPrefixedName());

 	}

 

 	@Test

 	public void attributePrefixedName() throws Exception {

-		final Element element = new Element(new QualifiedName("http://namespace/uri/1", "element"));

+		final IElement element = new Element(new QualifiedName("http://namespace/uri/1", "element"));

 		element.declareDefaultNamespace("http://namespace/uri/default");

 		element.declareNamespace("ns1", "http://namespace/uri/1");

 		element.declareNamespace("ns2", "http://namespace/uri/2");

@@ -226,23 +229,23 @@
 

 	@Test

 	public void readNamespaceDeclarations() throws Exception {

-		final Document document = readDocumentFromString("<ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\"/>");

-		final Element rootElement = document.getRootElement();

+		final IDocument document = readDocumentFromString("<ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\"/>");

+		final IElement rootElement = document.getRootElement();

 

 		assertEquals("http://namespace/default", rootElement.getDefaultNamespaceURI());

 		assertEquals("http://namespace/uri/1", rootElement.getNamespaceURI("ns1"));

 	}

 

-	private Document readDocumentFromString(final String documentContent) throws IOException, ParserConfigurationException, SAXException {

+	private IDocument readDocumentFromString(final String documentContent) throws IOException, ParserConfigurationException, SAXException {

 		return new DocumentReader().read(documentContent);

 	}

 

 	@Test

 	public void readNestedNamespaceDeclarations() throws Exception {

-		final Document document = readDocumentFromString("<ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\">" + "<ns2:b xmlns:ns2=\"http://namespace/uri/2\"/>"

+		final IDocument document = readDocumentFromString("<ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\">" + "<ns2:b xmlns:ns2=\"http://namespace/uri/2\"/>"

 				+ "</ns1:a>");

-		final Element rootElement = document.getRootElement();

-		final Element nestedElement = rootElement.getChildElements().get(0);

+		final IElement rootElement = document.getRootElement();

+		final IElement nestedElement = rootElement.childElements().first();

 		assertEquals("http://namespace/default", nestedElement.getDefaultNamespaceURI());

 		assertEquals("http://namespace/uri/1", nestedElement.getNamespaceURI("ns1"));

 		assertEquals("http://namespace/uri/2", nestedElement.getNamespaceURI("ns2"));

@@ -251,19 +254,19 @@
 

 	@Test

 	public void evaluateElementPrefix() throws Exception {

-		final Document document = readDocumentFromString("<ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\">" + "<ns2:b xmlns:ns2=\"http://namespace/uri/2\"/>" + "<c />"

+		final IDocument document = readDocumentFromString("<ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\">" + "<ns2:b xmlns:ns2=\"http://namespace/uri/2\"/>" + "<c />"

 				+ "</ns1:a>");

-		final Element rootElement = document.getRootElement();

+		final IElement rootElement = document.getRootElement();

 		assertEquals("http://namespace/uri/1", rootElement.getQualifiedName().getQualifier());

 		assertEquals("a", rootElement.getLocalName());

 		assertEquals("ns1:a", rootElement.getPrefixedName());

 

-		final Element firstNestedElement = rootElement.getChildElements().get(0);

+		final IElement firstNestedElement = rootElement.childElements().first();

 		assertEquals("http://namespace/uri/2", firstNestedElement.getQualifiedName().getQualifier());

 		assertEquals("b", firstNestedElement.getLocalName());

 		assertEquals("ns2:b", firstNestedElement.getPrefixedName());

 

-		final Element secondNestedElement = rootElement.getChildElements().get(1);

+		final IElement secondNestedElement = rootElement.childElements().get(1);

 		assertEquals("http://namespace/default", secondNestedElement.getQualifiedName().getQualifier());

 		assertEquals("c", secondNestedElement.getLocalName());

 		assertEquals("c", secondNestedElement.getPrefixedName());

@@ -271,20 +274,20 @@
 

 	@Test

 	public void evaluateAttributePrefix() throws Exception {

-		final Document document = readDocumentFromString("<ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\" attr1=\"value1\">"

+		final IDocument document = readDocumentFromString("<ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\" attr1=\"value1\">"

 				+ "<ns2:b xmlns:ns2=\"http://namespace/uri/2\" ns1:attr2=\"value2\" ns2:attr3=\"value3\" attr4=\"value4\" />" + "<c ns1:attr5=\"value5\" attr6=\"value6\" />" + "</ns1:a>");

-		final Element rootElement = document.getRootElement();

+		final IElement rootElement = document.getRootElement();

 		assertTrue(rootElement.getAttributeNames().contains(new QualifiedName("http://namespace/uri/1", "attr1")));

 		assertFalse(rootElement.getAttributeNames().contains(new QualifiedName("http://namespace/default", "attr1")));

 		assertFalse(rootElement.getAttributeNames().contains(new QualifiedName("", "attr1")));

 		assertFalse(rootElement.getAttributeNames().contains(new QualifiedName(null, "attr1")));

 

-		final Element firstNestedElement = rootElement.getChildElements().get(0);

+		final IElement firstNestedElement = rootElement.childElements().first();

 		assertTrue(firstNestedElement.getAttributeNames().contains(new QualifiedName("http://namespace/uri/1", "attr2")));

 		assertTrue(firstNestedElement.getAttributeNames().contains(new QualifiedName("http://namespace/uri/2", "attr3")));

 		assertTrue(firstNestedElement.getAttributeNames().contains(new QualifiedName("http://namespace/uri/2", "attr4")));

 

-		final Element secondNestedElement = rootElement.getChildElements().get(1);

+		final IElement secondNestedElement = rootElement.childElements().get(1);

 		assertTrue(secondNestedElement.getAttributeNames().contains(new QualifiedName("http://namespace/uri/1", "attr5")));

 		assertTrue(secondNestedElement.getAttributeNames().contains(new QualifiedName("http://namespace/default", "attr6")));

 	}

@@ -293,7 +296,7 @@
 	public void readWriteCycle() throws Exception {

 		final String inputContent = "<?xml version='1.0' encoding='UTF-8'?> <ns1:a xmlns=\"http://namespace/default\" xmlns:ns1=\"http://namespace/uri/1\" attr1=\"value1\"> "

 				+ "<ns2:b xmlns:ns2=\"http://namespace/uri/2\" ns1:attr2=\"value2\" attr3=\"value3\"/> " + "<c attr4=\"value4\" ns1:attr5=\"value5\"/>" + "</ns1:a> ";

-		final Document document = readDocumentFromString(inputContent);

+		final IDocument document = readDocumentFromString(inputContent);

 

 		final DocumentWriter documentWriter = new DocumentWriter();

 		final ByteArrayOutputStream buffer = new ByteArrayOutputStream();

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NodeTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NodeTest.java
index 3bccbf4..79b8247 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NodeTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/NodeTest.java
@@ -18,6 +18,7 @@
 import static org.junit.Assert.assertTrue;

 

 import org.eclipse.core.runtime.AssertionFailedException;

+import org.eclipse.vex.core.dom.ContentRange;

 import org.junit.Before;

 import org.junit.Test;

 

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ParentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ParentTest.java
index 1e1a249..7157594 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ParentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/ParentTest.java
@@ -11,6 +11,12 @@
 import java.util.List;

 

 import org.eclipse.core.runtime.AssertionFailedException;

+import org.eclipse.vex.core.dom.BaseNodeVisitor;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.INodeVisitor;

+import org.eclipse.vex.core.dom.INodeVisitorWithResult;

+import org.eclipse.vex.core.dom.IText;

 import org.junit.Before;

 import org.junit.Test;

 

@@ -74,7 +80,7 @@
 

 		parent.removeChild(secondChild);

 		assertTrue(parent.hasChildren());

-		for (final Node child : parent.children()) {

+		for (final INode child : parent.children()) {

 			assertTrue(child != secondChild);

 		}

 	}

@@ -127,7 +133,7 @@
 		addTestChild();

 		addTestChild();

 		addTestChild();

-		final Iterator<Node> iterator = parent.children().iterator();

+		final Iterator<INode> iterator = parent.children().iterator();

 		iterator.next();

 		iterator.remove();

 	}

@@ -139,10 +145,10 @@
 		content.insertText(child.getStartOffset(), "Hello ");

 		content.insertText(parent.getEndOffset(), "World");

 

-		final Iterator<Node> children = parent.children().iterator();

-		assertTrue(children.next() instanceof Text);

+		final Iterator<INode> children = parent.children().iterator();

+		assertTrue(children.next() instanceof IText);

 		assertSame(child, children.next());

-		assertTrue(children.next() instanceof Text);

+		assertTrue(children.next() instanceof IText);

 		assertFalse(children.hasNext());

 	}

 

@@ -155,7 +161,7 @@
 		assertEquals(1, child.getStartOffset());

 		assertEquals(2, child.getEndOffset());

 

-		final Iterator<Node> children = parent.children().iterator();

+		final Iterator<INode> children = parent.children().iterator();

 		assertSame(child, children.next());

 		assertFalse(children.hasNext());

 	}

@@ -167,7 +173,7 @@
 		final TestChild child3 = addTestChild();

 		addTestChild();

 

-		final Iterator<Node> children = parent.children().in(new ContentRange(child2.getStartOffset(), child3.getEndOffset())).iterator();

+		final Iterator<? extends INode> children = parent.children().in(new ContentRange(child2.getStartOffset(), child3.getEndOffset())).iterator();

 		assertSame(child2, children.next());

 		assertSame(child3, children.next());

 		assertFalse(children.hasNext());

@@ -181,7 +187,7 @@
 		content.insertText(child1.getStartOffset(), "Hello");

 		content.insertText(child2.getStartOffset(), "World!");

 

-		final Iterator<Node> children = parent.children().in(child1.getRange().resizeBy(-2, 2)).iterator();

+		final Iterator<? extends INode> children = parent.children().in(child1.getRange().resizeBy(-2, 2)).iterator();

 		assertTextNodeEquals("lo", 4, 5, children.next());

 		assertChildNodeEquals("", 6, 7, children.next());

 		assertTextNodeEquals("Wo", 8, 9, children.next());

@@ -207,7 +213,7 @@
 		}

 

 		int i = 0;

-		for (final Node actualChild : parent.children()) {

+		for (final INode actualChild : parent.children()) {

 			assertTrue(i < expectedChildren.size());

 			assertSame(expectedChildren.get(i++), actualChild);

 		}

@@ -220,7 +226,7 @@
 			expectedChildren.add(addTestChild());

 		}

 

-		final Iterator<Node> actualChildren = parent.children().in(new ContentRange(expectedChildren.get(1).getStartOffset(), expectedChildren.get(3).getEndOffset())).iterator();

+		final Iterator<? extends INode> actualChildren = parent.children().in(new ContentRange(expectedChildren.get(1).getStartOffset(), expectedChildren.get(3).getEndOffset())).iterator();

 		assertSame(expectedChildren.get(1), actualChildren.next());

 		assertSame(expectedChildren.get(2), actualChildren.next());

 		assertSame(expectedChildren.get(3), actualChildren.next());

@@ -234,7 +240,7 @@
 			expectedChildren.add(addTestChild());

 		}

 

-		final Iterator<Node> actualChildren = parent.children().in(new ContentRange(expectedChildren.get(1).getStartOffset(), expectedChildren.get(3).getStartOffset())).iterator();

+		final Iterator<? extends INode> actualChildren = parent.children().in(new ContentRange(expectedChildren.get(1).getStartOffset(), expectedChildren.get(3).getStartOffset())).iterator();

 		assertSame(expectedChildren.get(1), actualChildren.next());

 		assertSame(expectedChildren.get(2), actualChildren.next());

 		assertFalse(actualChildren.hasNext());

@@ -247,7 +253,7 @@
 			expectedChildren.add(addTestChild());

 		}

 

-		final Iterator<Node> actualChildren = parent.children().in(new ContentRange(expectedChildren.get(1).getEndOffset(), expectedChildren.get(3).getStartOffset())).iterator();

+		final Iterator<? extends INode> actualChildren = parent.children().in(new ContentRange(expectedChildren.get(1).getEndOffset(), expectedChildren.get(3).getStartOffset())).iterator();

 		assertSame(expectedChildren.get(2), actualChildren.next());

 		assertFalse(actualChildren.hasNext());

 	}

@@ -259,7 +265,7 @@
 			expectedChildren.add(addTestChild());

 		}

 

-		final Iterator<Node> actualChildren = parent.children().in(new ContentRange(expectedChildren.get(1).getEndOffset(), expectedChildren.get(3).getEndOffset())).iterator();

+		final Iterator<? extends INode> actualChildren = parent.children().in(new ContentRange(expectedChildren.get(1).getEndOffset(), expectedChildren.get(3).getEndOffset())).iterator();

 		assertSame(expectedChildren.get(2), actualChildren.next());

 		assertSame(expectedChildren.get(3), actualChildren.next());

 		assertFalse(actualChildren.hasNext());

@@ -275,7 +281,7 @@
 		}

 

 		int i = 0;

-		for (final Node actualChild : parent.children()) {

+		for (final INode actualChild : parent.children()) {

 			assertSame(expectedChildren.get(i++), actualChild);

 		}

 	}

@@ -284,7 +290,7 @@
 	public void shouldProvideSingleText() throws Exception {

 		content.insertText(parent.getEndOffset(), "Hello World");

 

-		final Iterator<Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertTextNodeEquals("Hello World", 1, 11, actualChildren.next());

 		assertFalse(actualChildren.hasNext());

 	}

@@ -293,7 +299,7 @@
 	public void shouldProvideSingleCharacterText() throws Exception {

 		content.insertText(parent.getEndOffset(), "x");

 

-		final Iterator<Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertTextNodeEquals("x", 1, 1, actualChildren.next());

 		assertFalse(actualChildren.hasNext());

 	}

@@ -303,7 +309,7 @@
 		content.insertText(parent.getEndOffset(), "Hello World");

 		addTestChild();

 

-		final Iterator<Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertTextNodeEquals("Hello World", 1, 11, actualChildren.next());

 		assertChildNodeEquals("", 12, 13, actualChildren.next());

 		assertFalse(actualChildren.hasNext());

@@ -314,7 +320,7 @@
 		content.insertText(parent.getEndOffset(), "x");

 		addTestChild();

 

-		final Iterator<Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertTextNodeEquals("x", 1, 1, actualChildren.next());

 		assertChildNodeEquals("", 2, 3, actualChildren.next());

 		assertFalse(actualChildren.hasNext());

@@ -325,7 +331,7 @@
 		addTestChild();

 		content.insertText(parent.getEndOffset(), "Hello World");

 

-		final Iterator<Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertChildNodeEquals("", 1, 2, actualChildren.next());

 		assertTextNodeEquals("Hello World", 3, 13, actualChildren.next());

 		assertFalse(actualChildren.hasNext());

@@ -336,7 +342,7 @@
 		addTestChild();

 		content.insertText(parent.getEndOffset(), "x");

 

-		final Iterator<Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertChildNodeEquals("", 1, 2, actualChildren.next());

 		assertTextNodeEquals("x", 3, 3, actualChildren.next());

 		assertFalse(actualChildren.hasNext());

@@ -345,7 +351,7 @@
 	@Test

 	public void shouldProvideAllChildNodesIncludingText() throws Exception {

 		setUpChildNodes();

-		final Iterator<Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertTextNodeEquals("Hello ", 1, 6, actualChildren.next());

 		assertChildNodeEquals("Child1", 7, 14, actualChildren.next());

 		assertChildNodeEquals("Child2", 15, 22, actualChildren.next());

@@ -357,7 +363,7 @@
 	public void shouldHandleSmallerStartOffset() throws Exception {

 		setUpChildNodes();

 		content.insertText(parent.getStartOffset(), "prefix");

-		final Iterator<Node> actualChildren = parent.children().in(parent.getRange().resizeBy(-2, 0)).iterator();

+		final Iterator<? extends INode> actualChildren = parent.children().in(parent.getRange().resizeBy(-2, 0)).iterator();

 		assertTextNodeEquals("Hello ", 7, 12, actualChildren.next());

 		assertChildNodeEquals("Child1", 13, 20, actualChildren.next());

 		assertChildNodeEquals("Child2", 21, 28, actualChildren.next());

@@ -368,7 +374,7 @@
 	public void shouldHandleBiggerEndOffset() throws Exception {

 		setUpChildNodes();

 		content.insertText(parent.getEndOffset() + 1, "suffix");

-		final Iterator<Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertTextNodeEquals("Hello ", 1, 6, actualChildren.next());

 		assertChildNodeEquals("Child1", 7, 14, actualChildren.next());

 		assertChildNodeEquals("Child2", 15, 22, actualChildren.next());

@@ -384,7 +390,7 @@
 	@Test

 	public void shouldReturnTextWithinBoundaries() throws Exception {

 		content.insertText(parent.getEndOffset(), "Hello World");

-		final Node text = parent.children().first();

+		final INode text = parent.children().first();

 		assertTextNodeEquals("Hello World", text.getStartOffset(), text.getEndOffset(), parent.getChildAt(text.getStartOffset()));

 		assertTextNodeEquals("Hello World", text.getStartOffset(), text.getEndOffset(), parent.getChildAt(text.getStartOffset() + 1));

 		assertTextNodeEquals("Hello World", text.getStartOffset(), text.getEndOffset(), parent.getChildAt(text.getEndOffset() - 1));

@@ -400,7 +406,7 @@
 		parent.addChild(child);

 		child.associate(content, new ContentRange(offset, offset + 1));

 		content.insertText(child.getEndOffset(), "Hello World");

-		final Node text = child.children().first();

+		final INode text = child.children().first();

 		assertTextNodeEquals("Hello World", text.getStartOffset(), text.getEndOffset(), parent.getChildAt(text.getStartOffset()));

 		assertTextNodeEquals("Hello World", text.getStartOffset(), text.getEndOffset(), parent.getChildAt(text.getStartOffset() + 1));

 		assertTextNodeEquals("Hello World", text.getStartOffset(), text.getEndOffset(), parent.getChildAt(text.getEndOffset() - 1));

@@ -426,12 +432,12 @@
 		final TestChild child2 = addTestChild();

 		final TestChild child3 = addTestChild();

 

-		final Iterator<Node> childNodes12 = parent.children().before(child3.getStartOffset()).iterator();

+		final Iterator<? extends INode> childNodes12 = parent.children().before(child3.getStartOffset()).iterator();

 		assertSame(child1, childNodes12.next());

 		assertSame(child2, childNodes12.next());

 		assertFalse(childNodes12.hasNext());

 

-		final Iterator<Node> childNodes123 = parent.children().before(parent.getEndOffset()).iterator();

+		final Iterator<? extends INode> childNodes123 = parent.children().before(parent.getEndOffset()).iterator();

 		assertSame(child1, childNodes123.next());

 		assertSame(child2, childNodes123.next());

 		assertSame(child3, childNodes123.next());

@@ -447,7 +453,7 @@
 		final TestChild child3 = addTestChild();

 		content.insertText(child3.getEndOffset(), "Hello World");

 

-		final Iterator<Node> childNodes12 = parent.children().before(child3.getStartOffset() + 5).iterator();

+		final Iterator<? extends INode> childNodes12 = parent.children().before(child3.getStartOffset() + 5).iterator();

 		assertSame(child1, childNodes12.next());

 		assertSame(child2, childNodes12.next());

 		assertFalse(childNodes12.hasNext());

@@ -459,12 +465,12 @@
 		final TestChild child2 = addTestChild();

 		final TestChild child3 = addTestChild();

 

-		final Iterator<Node> childNodes23 = parent.children().after(child1.getEndOffset()).iterator();

+		final Iterator<? extends INode> childNodes23 = parent.children().after(child1.getEndOffset()).iterator();

 		assertSame(child2, childNodes23.next());

 		assertSame(child3, childNodes23.next());

 		assertFalse(childNodes23.hasNext());

 

-		final Iterator<Node> childNodes123 = parent.children().after(parent.getStartOffset()).iterator();

+		final Iterator<? extends INode> childNodes123 = parent.children().after(parent.getStartOffset()).iterator();

 		assertSame(child1, childNodes123.next());

 		assertSame(child2, childNodes123.next());

 		assertSame(child3, childNodes123.next());

@@ -480,7 +486,7 @@
 		final TestChild child2 = addTestChild();

 		final TestChild child3 = addTestChild();

 

-		final Iterator<Node> childNodes23 = parent.children().after(child1.getEndOffset() - 5).iterator();

+		final Iterator<? extends INode> childNodes23 = parent.children().after(child1.getEndOffset() - 5).iterator();

 		assertSame(child2, childNodes23.next());

 		assertSame(child3, childNodes23.next());

 		assertFalse(childNodes23.hasNext());

@@ -490,7 +496,7 @@
 	public void givenChildNodesAndText_shouldProvideChildrenAxisIncludingText() throws Exception {

 		setUpChildNodes();

 

-		final Iterator<? extends Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertTextNodeEquals("Hello ", 1, 6, actualChildren.next());

 		assertChildNodeEquals("Child1", 7, 14, actualChildren.next());

 		assertChildNodeEquals("Child2", 15, 22, actualChildren.next());

@@ -503,7 +509,7 @@
 		final TestChild child2 = addTestChild();

 		final TestChild child3 = addTestChild();

 

-		final Iterator<? extends Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertSame(child1, actualChildren.next());

 		assertSame(child2, actualChildren.next());

 		assertSame(child3, actualChildren.next());

@@ -513,7 +519,7 @@
 	public void givenOnlyText_shouldProvideTextOnChildrenAxis() throws Exception {

 		content.insertText(parent.getEndOffset(), "Hello World");

 

-		final Iterator<? extends Node> actualChildren = parent.children().iterator();

+		final Iterator<INode> actualChildren = parent.children().iterator();

 		assertTextNodeEquals("Hello World", 1, 11, actualChildren.next());

 	}

 

@@ -525,7 +531,7 @@
 	@Test

 	public void whenTextExcludedOnAxis_shouldNotProvideTextOnChildrenAxis() throws Exception {

 		setUpChildNodes();

-		final Iterator<Node> actualChildren = parent.children().withoutText().iterator();

+		final Iterator<? extends INode> actualChildren = parent.children().withoutText().iterator();

 		assertEquals("Child1", actualChildren.next().getText());

 		assertEquals("Child2", actualChildren.next().getText());

 		assertFalse(actualChildren.hasNext());

@@ -534,7 +540,7 @@
 	@Test

 	public void shouldProvideChildrenAxisAsList() throws Exception {

 		setUpChildNodes();

-		final List<Node> actualList = parent.children().asList();

+		final List<? extends INode> actualList = parent.children().asList();

 		assertEquals(4, actualList.size());

 		assertTextNodeEquals("Hello ", 1, 6, actualList.get(0));

 		assertChildNodeEquals("Child1", 7, 14, actualList.get(1));

@@ -579,14 +585,14 @@
 		assertEquals(4, parent.children().count());

 	}

 

-	private static void assertTextNodeEquals(final String text, final int startOffset, final int endOffset, final Node actualNode) {

-		assertTrue(actualNode instanceof Text);

+	private static void assertTextNodeEquals(final String text, final int startOffset, final int endOffset, final INode actualNode) {

+		assertTrue(actualNode instanceof IText);

 		assertEquals(text, actualNode.getText());

 		assertEquals(startOffset, actualNode.getStartOffset());

 		assertEquals(endOffset, actualNode.getEndOffset());

 	}

 

-	private static void assertChildNodeEquals(final String text, final int startOffset, final int endOffset, final Node actualNode) {

+	private static void assertChildNodeEquals(final String text, final int startOffset, final int endOffset, final INode actualNode) {

 		assertTrue(actualNode instanceof TestChild);

 		assertEquals(text, actualNode.getText());

 		assertEquals(startOffset, actualNode.getStartOffset());

@@ -613,35 +619,29 @@
 	}

 

 	private static class TestParent extends Parent {

-		@Override

 		public void accept(final INodeVisitor visitor) {

 			throw new UnsupportedOperationException();

 		}

 

-		@Override

 		public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 			throw new UnsupportedOperationException();

 		}

 

-		@Override

-		public boolean isKindOf(final Node node) {

+		public boolean isKindOf(final INode node) {

 			return false;

 		}

 	}

 

 	private static class TestChild extends Node {

-		@Override

 		public void accept(final INodeVisitor visitor) {

 			throw new UnsupportedOperationException();

 		}

 

-		@Override

 		public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 			throw new UnsupportedOperationException();

 		}

 

-		@Override

-		public boolean isKindOf(final Node node) {

+		public boolean isKindOf(final INode node) {

 			return false;

 		}

 	}

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentContentModelTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java
similarity index 96%
rename from org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentContentModelTest.java
rename to org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java
index e8bf5be..aad9ff7 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentContentModelTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java
@@ -8,7 +8,7 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.dom;

+package org.eclipse.vex.core.internal.io;

 

 import static org.junit.Assert.assertEquals;

 import static org.junit.Assert.assertFalse;

@@ -19,6 +19,8 @@
 import java.net.URL;

 

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.internal.dom.Element;

+import org.eclipse.vex.core.internal.io.DocumentContentModel;

 import org.eclipse.vex.core.tests.TestResources;

 import org.eclipse.vex.core.tests.VEXCoreTestPlugin;

 import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentReaderTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentReaderTest.java
index 6bab62d..ef87ee7 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentReaderTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentReaderTest.java
@@ -21,11 +21,10 @@
 import java.net.URL;

 import java.util.Iterator;

 

-import org.eclipse.vex.core.internal.dom.Comment;

-import org.eclipse.vex.core.internal.dom.Document;

-import org.eclipse.vex.core.internal.dom.DocumentContentModel;

-import org.eclipse.vex.core.internal.dom.Element;

-import org.eclipse.vex.core.internal.dom.Node;

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.dom.INode;

 import org.eclipse.vex.core.tests.TestResources;

 import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;

 import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager;

@@ -39,7 +38,7 @@
 	@Test

 	public void readDocumentWithDtdPublic() throws Exception {

 		final DocumentReader reader = new DocumentReader();

-		final Document document = reader.read(TestResources.get("documentWithDtdPublic.xml"));

+		final IDocument document = reader.read(TestResources.get("documentWithDtdPublic.xml"));

 		assertEquals("-//Eclipse Foundation//DTD Vex Test//EN", document.getPublicID());

 		assertEquals("test1.dtd", document.getSystemID());

 	}

@@ -48,7 +47,7 @@
 	public void readDocumentWithDtdSystem() throws Exception {

 		final DocumentReader reader = new DocumentReader();

 		final URL documentUrl = TestResources.get("documentWithDtdSystem.xml");

-		final Document document = reader.read(documentUrl);

+		final IDocument document = reader.read(documentUrl);

 		assertNull(document.getPublicID());

 		assertEquals("test1.dtd", document.getSystemID());

 	}

@@ -138,26 +137,26 @@
 	public void readDocumentWithComments() throws Exception {

 		final DocumentReader reader = new DocumentReader();

 

-		final Document document = reader.read(TestResources.get("documentWithComments.xml"));

-		final Iterator<Node> documentChildren = document.children().iterator();

+		final IDocument document = reader.read(TestResources.get("documentWithComments.xml"));

+		final Iterator<INode> documentChildren = document.children().iterator();

 

-		final Comment documentComment1 = (Comment) documentChildren.next();

+		final IComment documentComment1 = (IComment) documentChildren.next();

 		assertEquals("A comment before the root element.", documentComment1.getText());

 		assertSame(document.getRootElement(), documentChildren.next());

-		final Comment documentComment2 = (Comment) documentChildren.next();

+		final IComment documentComment2 = (IComment) documentChildren.next();

 		assertEquals("A final comment after the root element.", documentComment2.getText());

 		assertFalse(documentChildren.hasNext());

 

-		final Element rootElement = document.getRootElement();

-		final Iterator<Node> rootChildren = rootElement.children().iterator();

+		final IElement rootElement = document.getRootElement();

+		final Iterator<INode> rootChildren = rootElement.children().iterator();

 

-		final Comment comment1 = (Comment) rootChildren.next();

+		final IComment comment1 = (IComment) rootChildren.next();

 		assertEquals("A comment within the root element.", comment1.getText());

 

-		final Comment comment2 = (Comment) ((Element) rootChildren.next()).children().get(1);

+		final IComment comment2 = (IComment) ((IElement) rootChildren.next()).children().get(1);

 		assertEquals("A comment within text.", comment2.getText());

 

-		final Comment comment3 = (Comment) rootChildren.next();

+		final IComment comment3 = (IComment) rootChildren.next();

 		assertEquals("Another comment between two child elements.", comment3.getText());

 

 		rootChildren.next();

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentWriterTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentWriterTest.java
index c2890b4..7cea3f2 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentWriterTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentWriterTest.java
@@ -20,9 +20,9 @@
 
 import javax.xml.parsers.ParserConfigurationException;
 
+import org.eclipse.vex.core.dom.IDocument;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
-import org.eclipse.vex.core.internal.dom.Document;
 import org.eclipse.vex.core.internal.widget.CssWhitespacePolicy;
 import org.eclipse.vex.core.tests.TestResources;
 import org.junit.Test;
@@ -60,7 +60,7 @@
 		final StyleSheetReader reader = new StyleSheetReader();
 		final StyleSheet styleSheet = reader.read(TestResources.get("test.css"));
 
-		final Document expectedDocument = readDocument(new InputSource(documentUrl.toString()));
+		final IDocument expectedDocument = readDocument(new InputSource(documentUrl.toString()));
 
 		final DocumentWriter documentWriter = new DocumentWriter();
 		documentWriter.setWhitespacePolicy(new CssWhitespacePolicy(styleSheet));
@@ -70,12 +70,12 @@
 		final InputStream inputStream = new ByteArrayInputStream(buffer.toByteArray());
 		final InputSource inputSource = new InputSource(inputStream);
 		inputSource.setSystemId(documentUrl.toString());
-		final Document actualDocument = readDocument(inputSource);
+		final IDocument actualDocument = readDocument(inputSource);
 
 		assertDocumentsEqual(expectedDocument, actualDocument);
 	}
 
-	private static Document readDocument(final InputSource inputSource) throws IOException, ParserConfigurationException, SAXException {
+	private static IDocument readDocument(final InputSource inputSource) throws IOException, ParserConfigurationException, SAXException {
 		final DocumentReader documentReader = new DocumentReader();
 		return documentReader.read(inputSource);
 	}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/RoundTrip.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/RoundTrip.java
index b01901b..f7f750a 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/RoundTrip.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/RoundTrip.java
@@ -16,16 +16,15 @@
 

 import java.util.Collection;

 import java.util.Iterator;

-import java.util.List;

 

 import org.eclipse.core.runtime.QualifiedName;

-import org.eclipse.vex.core.internal.dom.BaseNodeVisitor;

-import org.eclipse.vex.core.internal.dom.Comment;

-import org.eclipse.vex.core.internal.dom.Document;

-import org.eclipse.vex.core.internal.dom.Element;

-import org.eclipse.vex.core.internal.dom.Node;

-import org.eclipse.vex.core.internal.dom.Parent;

-import org.eclipse.vex.core.internal.dom.Text;

+import org.eclipse.vex.core.dom.BaseNodeVisitor;

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.IParent;

+import org.eclipse.vex.core.dom.IText;

 

 /**

  * This class provides some special assertions for round trip tests.

@@ -34,34 +33,34 @@
  */

 public class RoundTrip {

 

-	public static void assertDocumentsEqual(final Document expected, final Document actual) {

+	public static void assertDocumentsEqual(final IDocument expected, final IDocument actual) {

 		assertEquals(expected.getPublicID(), actual.getPublicID());

 		assertEquals(expected.getSystemID(), actual.getSystemID());

 		assertContentEqual(expected, actual);

 	}

 

-	public static void assertContentEqual(final Parent expected, final Parent actual) {

+	public static void assertContentEqual(final IParent expected, final IParent actual) {

 		assertContentRangeEqual(expected, actual);

-		final Iterator<Node> expectedChildren = expected.children().iterator();

-		final Iterator<Node> actualChildren = actual.children().iterator();

+		final Iterator<INode> expectedChildren = expected.children().iterator();

+		final Iterator<INode> actualChildren = actual.children().iterator();

 		while (expectedChildren.hasNext() && actualChildren.hasNext()) {

-			final Node expectedNode = expectedChildren.next();

-			final Node actualNode = actualChildren.next();

+			final INode expectedNode = expectedChildren.next();

+			final INode actualNode = actualChildren.next();

 			assertContentRangeEqual(expectedNode, actualNode);

 			assertEquals(expectedNode.getClass(), actualNode.getClass());

 			expectedNode.accept(new BaseNodeVisitor() {

 				@Override

-				public void visit(final Element element) {

-					assertElementsEqual((Element) expectedNode, (Element) actualNode);

+				public void visit(final IElement element) {

+					assertElementsEqual((IElement) expectedNode, (IElement) actualNode);

 				}

 

 				@Override

-				public void visit(final Comment comment) {

+				public void visit(final IComment comment) {

 					assertEquals(expectedNode.getText(), actualNode.getText());

 				}

 

 				@Override

-				public void visit(final Text text) {

+				public void visit(final IText text) {

 					assertEquals(expectedNode.getText(), actualNode.getText());

 				}

 			});

@@ -70,28 +69,29 @@
 		assertFalse("less children expected", actualChildren.hasNext());

 	}

 

-	public static void assertContentRangeEqual(final Node expected, final Node actual) {

+	public static void assertContentRangeEqual(final INode expected, final INode actual) {

 		assertEquals("content range of " + expected, expected.getRange(), actual.getRange());

 	}

 

-	public static void assertElementsEqual(final Element expected, final Element actual) {

+	public static void assertElementsEqual(final IElement expected, final IElement actual) {

 		assertEquals("qualified name of " + expected, expected.getQualifiedName(), actual.getQualifiedName());

 		assertAttributesEqual(expected, actual);

 		assertNamespacesEqual(expected, actual);

 		assertContentEqual(expected, actual);

 	}

 

-	public static void assertAttributesEqual(final Element expected, final Element actual) {

-		final List<QualifiedName> expectedAttrs = expected.getAttributeNames();

-		final List<QualifiedName> actualAttrs = actual.getAttributeNames();

+	public static void assertAttributesEqual(final IElement expected, final IElement actual) {

+		final Iterator<QualifiedName> expectedAttrs = expected.getAttributeNames().iterator();

+		final Iterator<QualifiedName> actualAttrs = actual.getAttributeNames().iterator();

 

-		assertEquals("attributes of " + expected, expectedAttrs.size(), actualAttrs.size());

-		for (int i = 0; i < expectedAttrs.size(); i++) {

-			assertEquals(expectedAttrs.get(i), actualAttrs.get(i));

+		while (expectedAttrs.hasNext() && actualAttrs.hasNext()) {

+			assertEquals("attributes of " + expected, expectedAttrs.next(), actualAttrs.next());

 		}

+		assertFalse(expected + ": expected more attributes", expectedAttrs.hasNext());

+		assertFalse(expected + ": expected less attributes", actualAttrs.hasNext());

 	}

 

-	public static void assertNamespacesEqual(final Element expected, final Element actual) {

+	public static void assertNamespacesEqual(final IElement expected, final IElement actual) {

 		assertEquals("declared default namespace of " + expected, expected.getDeclaredDefaultNamespaceURI(), actual.getDeclaredDefaultNamespaceURI());

 

 		final Collection<String> expectedNamespacePrefixes = expected.getDeclaredNamespacePrefixes();

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/SpaceNormalizerTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/SpaceNormalizerTest.java
index de87f6c..3410d25 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/SpaceNormalizerTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/SpaceNormalizerTest.java
@@ -40,16 +40,14 @@
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Platform;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IText;
 import org.eclipse.vex.core.internal.core.DisplayDevice;
 import org.eclipse.vex.core.internal.css.MockDisplayDevice;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentContentModel;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.IWhitespacePolicy;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Text;
 import org.eclipse.vex.core.internal.widget.CssWhitespacePolicy;
 import org.eclipse.vex.core.tests.VEXCoreTestPlugin;
 import org.junit.Before;
@@ -182,36 +180,36 @@
 
 		final StyleSheet ss = getStyleSheet();
 
-		final Document doc = createDocument(input, ss);
-		Element element;
+		final IDocument doc = createDocument(input, ss);
+		IElement element;
 
 		element = doc.getRootElement();
 		assertContent(element, "<block>", "<block>", "<block>", "<block>");
 
-		final List<Element> children = element.getChildElements();
+		final List<? extends IElement> children = element.childElements().asList();
 
 		// --- Block 0 ---
 
 		assertContent(children.get(0), "foo ", "<inline>", " baz");
-		List<Element> c2 = children.get(0).getChildElements();
+		List<? extends IElement> c2 = children.get(0).childElements().asList();
 		assertContent(c2.get(0), "foo bar");
 
 		// --- Block 1 ---
 
 		assertContent(children.get(1), "foo", "<block>", "baz");
-		c2 = children.get(1).getChildElements();
+		c2 = children.get(1).childElements().asList();
 		assertContent(c2.get(0), "bar");
 
 		// --- Block 2 ---
 
 		assertContent(children.get(2), "foo", "<inline>", "baz");
-		c2 = children.get(2).getChildElements();
+		c2 = children.get(2).childElements().asList();
 		assertContent(c2.get(0), "foo bar");
 
 		// --- Block 3 ---
 
 		assertContent(children.get(3), "foo", "<block>", "baz");
-		c2 = children.get(3).getChildElements();
+		c2 = children.get(3).childElements().asList();
 		assertContent(c2.get(0), "bar");
 
 	}
@@ -222,12 +220,12 @@
 
 		final String input = "<doc>\n " + "<pre>\n foo\n</pre>\n " + "\n </doc>";
 
-		final Document doc = createDocument(input, getStyleSheet());
+		final IDocument doc = createDocument(input, getStyleSheet());
 
-		final Element element = doc.getRootElement();
+		final IElement element = doc.getRootElement();
 		assertContent(element, "<pre>");
 
-		final Element pre = element.getChildElements().get(0);
+		final IElement pre = element.childElements().first();
 		assertContent(pre, "\n foo\n");
 	}
 
@@ -237,11 +235,11 @@
 
 		final String input = "<doc>\n " + "<pre>\n foo\n <inline>\n foo\n bar\n </inline></pre>\n " + "\n </doc>";
 
-		final Document doc = createDocument(input, getStyleSheet());
+		final IDocument doc = createDocument(input, getStyleSheet());
 
-		final Element element = doc.getRootElement();
-		final Element pre = element.getChildElements().get(0);
-		final Element inline = pre.getChildElements().get(0);
+		final IElement element = doc.getRootElement();
+		final IElement pre = element.childElements().first();
+		final IElement inline = pre.childElements().first();
 		assertContent(inline, "\n foo\n bar\n ");
 	}
 
@@ -251,15 +249,15 @@
 
 		final String input = "<doc>\n  " + "<pre>\n\t foo\n\t <inline>\n\t foo\n\t bar\n\t </inline>\n\t baz\n\t </pre>\n " + "\n </doc>";
 
-		final Document doc = createDocument(input, getStyleSheet());
+		final IDocument doc = createDocument(input, getStyleSheet());
 
-		final Element element = doc.getRootElement();
+		final IElement element = doc.getRootElement();
 		assertContent(element, "<pre>");
 
-		final Element pre = element.getChildElements().get(0);
+		final IElement pre = element.childElements().first();
 		assertContent(pre, "\n\t foo\n\t ", "<inline>", "\n\t baz\n\t ");
 
-		final Element inline = pre.getChildElements().get(0);
+		final IElement inline = pre.childElements().first();
 		assertContent(inline, "\n\t foo\n\t bar\n\t ");
 	}
 
@@ -278,16 +276,16 @@
 	 * Asserts the content of the given element matches the given list. If a string in content is enclosed in angle
 	 * brackets, it's assume to refer to the name of an element; otherwise, it represents text content.
 	 */
-	private void assertContent(final Element element, final String... strings) {
-		final Iterator<Node> children = element.children().iterator();
+	private void assertContent(final IElement element, final String... strings) {
+		final Iterator<INode> children = element.children().iterator();
 		for (final String string : strings) {
-			final Node node = children.next();
+			final INode node = children.next();
 			if (string.startsWith("<")) {
 				final String name = string.substring(1, string.length() - 1);
-				assertTrue(node instanceof Element);
-				assertEquals(name, ((Element) node).getPrefixedName());
+				assertTrue(node instanceof IElement);
+				assertEquals(name, ((IElement) node).getPrefixedName());
 			} else {
-				assertTrue(node instanceof Text);
+				assertTrue(node instanceof IText);
 				final String contentText = node.getText();
 				assertEquals(string, contentText);
 			}
@@ -295,7 +293,7 @@
 		assertFalse("more strings expected", children.hasNext());
 	}
 
-	private Document createDocument(final String s, final StyleSheet ss) throws ParserConfigurationException, SAXException, IOException {
+	private IDocument createDocument(final String s, final StyleSheet ss) throws ParserConfigurationException, SAXException, IOException {
 		final SAXParserFactory factory = SAXParserFactory.newInstance();
 		final XMLReader xmlReader = factory.newSAXParser().getXMLReader();
 		final StyleSheet mySS = ss;
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTestSuite.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTestSuite.java
index c74de8a..d590a5b 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTestSuite.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTestSuite.java
@@ -25,15 +25,15 @@
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
+import org.eclipse.vex.core.dom.BaseNodeVisitorWithResult;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
-import org.eclipse.vex.core.internal.dom.BaseNodeVisitorWithResult;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentContentModel;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.IWhitespacePolicy;
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.internal.io.DocumentContentModel;
 import org.eclipse.vex.core.internal.io.DocumentReader;
+import org.eclipse.vex.core.internal.io.IWhitespacePolicy;
 import org.eclipse.vex.core.internal.widget.CssWhitespacePolicy;
 import org.junit.runner.RunWith;
 import org.junit.runners.AllTests;
@@ -109,7 +109,7 @@
 				return policy;
 			}
 		});
-		final Document doc = docReader.read(this.doc);
+		final IDocument doc = docReader.read(this.doc);
 		context.setDocument(doc);
 
 		final RootBox rootBox = new RootBox(context, doc, layoutWidth);
@@ -169,10 +169,10 @@
 
 	}
 
-	private static String getPrefixedNameOfElement(final Node node) {
+	private static String getPrefixedNameOfElement(final INode node) {
 		return node.accept(new BaseNodeVisitorWithResult<String>("") {
 			@Override
-			public String visit(final Element element) {
+			public String visit(final IElement element) {
 				return element.getPrefixedName();
 			}
 		});
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/MockBoxFactory.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/MockBoxFactory.java
index b92585e..863ff2a 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/MockBoxFactory.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/MockBoxFactory.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
-import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.dom.IElement;
 
 /**
  * A box factory that, for an element named &lt;space&gt;, returns a SpaceBox with height and width given by attributes
@@ -20,7 +20,7 @@
 
 	private static final long serialVersionUID = 1L;
 
-	public Box createBox(final LayoutContext context, final Element element, final BlockElementBox parent, final int width) {
+	public Box createBox(final LayoutContext context, final IElement element, final BlockElementBox parent, final int width) {
 		if (element.getPrefixedName().equals("space")) {
 			int w = 0;
 			int h = 0;
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestBlockElementBox.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestBlockElementBox.java
index c389950..23e06f3 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestBlockElementBox.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestBlockElementBox.java
@@ -15,10 +15,10 @@
 import java.net.URL;
 
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
 import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Element;
 import org.junit.Test;
 
 public class TestBlockElementBox {
@@ -42,7 +42,7 @@
 	@Test
 	public void testBeforeAfter() throws Exception {
 		final Document doc = new Document(new QualifiedName(null, "root"));
-		final Element root = doc.getRootElement();
+		final IElement root = doc.getRootElement();
 		doc.insertElement(2, new QualifiedName(null, "beforeBlock"));
 		context.setDocument(doc);
 
@@ -68,7 +68,7 @@
 		assertEquals(1, children.length);
 		assertEquals(BlockElementBox.class, children[0].getClass());
 		beb = (BlockElementBox) children[0];
-		assertEquals("beforeBlock", ((Element) beb.getNode()).getPrefixedName());
+		assertEquals("beforeBlock", ((IElement) beb.getNode()).getPrefixedName());
 	}
 
 }
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestDocumentTextBox.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestDocumentTextBox.java
index cb0a690..887f4a2 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestDocumentTextBox.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestDocumentTextBox.java
@@ -17,12 +17,13 @@
 import java.net.URL;
 
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.ContentRange;
 import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Element;
 import org.junit.Test;
 
 /**
@@ -49,8 +50,8 @@
 
 	@Test
 	public void testSplit() throws Exception {
-		final Document doc = new Document(new QualifiedName(null, "root"));
-		final Element root = doc.getRootElement();
+		final IDocument doc = new Document(new QualifiedName(null, "root"));
+		final IElement root = doc.getRootElement();
 
 		final Styles styles = context.getStyleSheet().getStyles(root);
 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/SchemaValidatorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/SchemaValidatorTest.java
similarity index 83%
rename from org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/SchemaValidatorTest.java
rename to org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/SchemaValidatorTest.java
index 930040a..90bd51d 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/SchemaValidatorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/SchemaValidatorTest.java
@@ -8,9 +8,9 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.dom;

+package org.eclipse.vex.core.internal.validator;

 

-import static org.eclipse.vex.core.internal.dom.Validator.PCDATA;

+import static org.eclipse.vex.core.dom.IValidator.PCDATA;

 import static org.eclipse.vex.core.tests.TestResources.CONTENT_NS;

 import static org.eclipse.vex.core.tests.TestResources.STRUCTURE_NS;

 import static org.eclipse.vex.core.tests.TestResources.TEST_DTD;

@@ -27,8 +27,13 @@
 import java.util.Set;

 

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.dom.IValidator;

+import org.eclipse.vex.core.internal.dom.Document;

+import org.eclipse.vex.core.internal.dom.Element;

+import org.eclipse.vex.core.internal.io.DocumentContentModel;

 import org.eclipse.vex.core.internal.io.DocumentReader;

-import org.eclipse.vex.core.internal.validator.WTPVEXValidator;

 import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;

 import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;

 import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;

@@ -56,10 +61,10 @@
 

 		final DocumentReader reader = new DocumentReader();

 		reader.setDebugging(true);

-		final Document document = reader.read(documentInputSource);

+		final IDocument document = reader.read(documentInputSource);

 		assertNotNull(document);

 

-		final Element rootElement = document.getRootElement();

+		final IElement rootElement = document.getRootElement();

 		assertNotNull(rootElement);

 		assertEquals("chapter", rootElement.getLocalName());

 		assertEquals("chapter", rootElement.getPrefixedName());

@@ -67,11 +72,11 @@
 		assertEquals(STRUCTURE_NS, rootElement.getDefaultNamespaceURI());

 		assertEquals(CONTENT_NS, rootElement.getNamespaceURI("c"));

 

-		final Element subChapterElement = rootElement.getChildElements().get(1);

+		final IElement subChapterElement = rootElement.childElements().get(1);

 		assertEquals("chapter", subChapterElement.getPrefixedName());

 		assertEquals(CHAPTER, subChapterElement.getQualifiedName());

 

-		final Element paragraphElement = subChapterElement.getChildElements().get(1);

+		final IElement paragraphElement = subChapterElement.childElements().get(1);

 		assertEquals("p", paragraphElement.getLocalName());

 		assertEquals("c:p", paragraphElement.getPrefixedName());

 		assertEquals(P, paragraphElement.getQualifiedName());

@@ -111,20 +116,20 @@
 

 	@Test

 	public void createValidatorWithNamespaceUri() throws Exception {

-		final Validator validator = new WTPVEXValidator(CONTENT_NS);

+		final IValidator validator = new WTPVEXValidator(CONTENT_NS);

 		assertEquals(1, validator.getValidRootElements().size());

 		assertTrue(validator.getValidRootElements().contains(P));

 	}

 

 	@Test

 	public void createValidatorWithDTDPublicId() throws Exception {

-		final Validator validator = new WTPVEXValidator(TEST_DTD);

+		final IValidator validator = new WTPVEXValidator(TEST_DTD);

 		assertEquals(10, validator.getValidRootElements().size());

 	}

 

 	@Test

 	public void validateSimpleSchema() throws Exception {

-		final Validator validator = new WTPVEXValidator(CONTENT_NS);

+		final IValidator validator = new WTPVEXValidator(CONTENT_NS);

 		assertIsValidSequence(validator, P, PCDATA);

 		assertIsValidSequence(validator, P, B, I);

 		assertIsValidSequence(validator, B, B, I);

@@ -137,8 +142,8 @@
 

 	@Test

 	public void validItemsFromSimpleSchema() throws Exception {

-		final Validator validator = new WTPVEXValidator();

-		final Document doc = new Document(P);

+		final IValidator validator = new WTPVEXValidator();

+		final IDocument doc = new Document(P);

 		doc.setValidator(validator);

 		doc.insertElement(2, B);

 		doc.insertElement(3, I);

@@ -150,7 +155,7 @@
 

 	@Test

 	public void validateComplexSchema() throws Exception {

-		final Validator validator = new WTPVEXValidator(STRUCTURE_NS);

+		final IValidator validator = new WTPVEXValidator(STRUCTURE_NS);

 		assertIsValidSequence(validator, CHAPTER, TITLE, P);

 		assertIsValidSequence(validator, CHAPTER, P);

 		assertIsValidSequence(validator, P, PCDATA, B, I);

@@ -162,8 +167,8 @@
 		 * We have to check this using a document, because B and I are not defined as standalone elements. The Validator

 		 * needs their parent to find the definition of their content model.

 		 */

-		final Validator validator = new WTPVEXValidator();

-		final Document doc = new Document(CHAPTER);

+		final IValidator validator = new WTPVEXValidator();

+		final IDocument doc = new Document(CHAPTER);

 		doc.setValidator(validator);

 		doc.insertElement(2, TITLE);

 		doc.insertElement(4, P);

@@ -179,21 +184,21 @@
 

 	@Test

 	public void getAllRequiredNamespacesForSimpleSchema() throws Exception {

-		final Validator validator = new WTPVEXValidator(new DocumentContentModel(null, null, null, new Element(P)));

+		final IValidator validator = new WTPVEXValidator(new DocumentContentModel(null, null, null, new Element(P)));

 		final Set<String> requiredNamespaces = validator.getRequiredNamespaces();

 		assertEquals(1, requiredNamespaces.size());

 	}

 

 	@Test

 	public void getAllRequiredNamespacesForComplexSchema() throws Exception {

-		final Validator validator = new WTPVEXValidator(new DocumentContentModel(null, null, null, new Element(CHAPTER)));

+		final IValidator validator = new WTPVEXValidator(new DocumentContentModel(null, null, null, new Element(CHAPTER)));

 		final Set<String> requiredNamespaces = validator.getRequiredNamespaces();

 		assertEquals(2, requiredNamespaces.size());

 		assertTrue(requiredNamespaces.contains(CONTENT_NS));

 		assertTrue(requiredNamespaces.contains(STRUCTURE_NS));

 	}

 

-	private void assertIsValidSequence(final Validator validator, final QualifiedName parentElement, final QualifiedName... sequence) {

+	private void assertIsValidSequence(final IValidator validator, final QualifiedName parentElement, final QualifiedName... sequence) {

 		for (int i = 0; i < sequence.length; i++) {

 			final List<QualifiedName> prefix = createPrefix(i, sequence);

 			final List<QualifiedName> toInsert = Collections.singletonList(sequence[i]);

@@ -219,7 +224,7 @@
 		return suffix;

 	}

 

-	private static void assertValidItems(final Validator validator, final Element element, final QualifiedName... expectedItems) {

+	private static void assertValidItems(final IValidator validator, final IElement element, final QualifiedName... expectedItems) {

 		final Set<QualifiedName> expected = new HashSet<QualifiedName>(expectedItems.length);

 		for (final QualifiedName expectedItem : expectedItems) {

 			expected.add(expectedItem);

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2CommentEditingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2CommentEditingTest.java
index bb8efe1..34ded74 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2CommentEditingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2CommentEditingTest.java
@@ -19,9 +19,9 @@
 import static org.junit.Assert.assertSame;

 import static org.junit.Assert.assertTrue;

 

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.IElement;

 import org.eclipse.vex.core.internal.css.StyleSheet;

-import org.eclipse.vex.core.internal.dom.Comment;

-import org.eclipse.vex.core.internal.dom.Element;

 import org.junit.Before;

 import org.junit.Test;

 

@@ -30,8 +30,8 @@
  */

 public class L2CommentEditingTest {

 

-	private VexWidgetImpl widget;

-	private Element rootElement;

+	private IVexWidget widget;

+	private IElement rootElement;

 

 	@Before

 	public void setUp() throws Exception {

@@ -42,7 +42,7 @@
 

 	@Test

 	public void givenAnElement_whenInsertingAComment_elementShouldContainComment() throws Exception {

-		final Comment comment = widget.insertComment();

+		final IComment comment = widget.insertComment();

 		assertTrue(rootElement.getRange().contains(comment.getRange()));

 		assertSame(rootElement, comment.getParent());

 		assertEquals(comment.getEndOffset(), widget.getCaretOffset());

@@ -50,15 +50,15 @@
 

 	@Test

 	public void givenAnElementWithComment_whenInsertingTextWithinComment_shouldAddTextToComment() throws Exception {

-		final Comment comment = widget.insertComment();

+		final IComment comment = widget.insertComment();

 		widget.insertText("Hello World");

 		assertEquals("Hello World", comment.getText());

 	}

 

 	@Test

 	public void givenAnEmptyComment_whenCaretInCommentAndHittingBackspace_shouldDeleteComment() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

-		final Comment comment = widget.insertComment();

+		final IElement titleElement = widget.insertElement(TITLE);

+		final IComment comment = widget.insertComment();

 		widget.deletePreviousChar();

 		assertFalse(titleElement.hasChildren());

 		assertFalse(comment.isAssociated());

@@ -67,8 +67,8 @@
 

 	@Test

 	public void givenAnEmptyComment_whenCaretInCommentAndHittingDelete_shouldDeleteComment() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

-		final Comment comment = widget.insertComment();

+		final IElement titleElement = widget.insertElement(TITLE);

+		final IComment comment = widget.insertComment();

 		widget.deleteNextChar();

 		assertFalse(titleElement.hasChildren());

 		assertFalse(comment.isAssociated());

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java
index 40f41e9..fdce256 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java
@@ -17,9 +17,9 @@
 import static org.junit.Assert.assertEquals;

 import static org.junit.Assert.assertTrue;

 

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.IElement;

 import org.eclipse.vex.core.internal.css.StyleSheet;

-import org.eclipse.vex.core.internal.dom.Comment;

-import org.eclipse.vex.core.internal.dom.Element;

 import org.junit.Before;

 import org.junit.Test;

 

@@ -28,19 +28,17 @@
  */

 public class L2SelectionTest {

 

-	private VexWidgetImpl widget;

-	private Element rootElement;

+	private IVexWidget widget;

 

 	@Before

 	public void setUp() throws Exception {

 		widget = new VexWidgetImpl(new MockHostComponent());

 		widget.setDocument(createDocumentWithDTD(TEST_DTD, "section"), StyleSheet.NULL);

-		rootElement = widget.getDocument().getRootElement();

 	}

 

 	@Test

 	public void givenCaretInElement_whenSelectionIncludesStartOffset_shouldExpandSelectionToEndOffset() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.moveBy(-1, true);

 		assertTrue(widget.hasSelection());

 		assertEquals(titleElement.getRange(), widget.getSelectedRange());

@@ -49,7 +47,7 @@
 

 	@Test

 	public void givenCaretInElementWith_whenSelectionIncludesStartOffset_shouldExpandSelectionToEndOffset() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveBy(-5, false);

 		widget.moveTo(titleElement.getStartOffset(), true);

@@ -60,7 +58,7 @@
 

 	@Test

 	public void givenCaretInElementAtEndOffset_whenMovedByOneBehindEndOffset_shouldExpandSelectionToStartOffset() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveBy(1, true);

 		assertTrue(widget.hasSelection());

@@ -70,7 +68,7 @@
 

 	@Test

 	public void givenCaretInElementAtEndOffset_whenMovedOneBehindStartOffset_shouldNotIncludeEndOffsetInSelectedRange() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveTo(titleElement.getStartOffset() + 1, true);

 		assertEquals(titleElement.getRange().resizeBy(1, -1), widget.getSelectedRange());

@@ -79,7 +77,7 @@
 

 	@Test

 	public void givenCaretAtStartOffsetOfElementWithText_whenMovedByOneForward_shouldExpandSelectionBehindEndOffset() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveTo(titleElement.getStartOffset(), false);

 		widget.moveBy(1, true);

@@ -89,7 +87,7 @@
 

 	@Test

 	public void givenCaretAtStartOffsetOfElementWithText_whenMovedOneForwardAndOneBackward_shouldSelectNothing() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveTo(titleElement.getStartOffset(), false);

 		widget.moveBy(1, true);

@@ -99,10 +97,10 @@
 

 	@Test

 	public void givenCaretInElementWithText_whenMovedBehindFollowingElementAndMovedBackOnce_shouldSelectOnlyFirstElement() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveBy(1);

-		final Element paraElement = widget.insertElement(PARA);

+		final IElement paraElement = widget.insertElement(PARA);

 		widget.insertText("Hello Again");

 		widget.moveTo(titleElement.getStartOffset() + 3);

 		widget.moveTo(paraElement.getEndOffset() + 1, true);

@@ -113,10 +111,10 @@
 

 	@Test

 	public void givenCaretInElementWithText_whenMovedBehindFollowingElementAndMovedBackTwice_shouldSelectOnlyTextFragementOfFirstElement() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveBy(1);

-		final Element paraElement = widget.insertElement(PARA);

+		final IElement paraElement = widget.insertElement(PARA);

 		widget.insertText("Hello Again");

 		widget.moveTo(titleElement.getStartOffset() + 3);

 		widget.moveTo(paraElement.getEndOffset() + 1, true);

@@ -128,10 +126,10 @@
 

 	@Test

 	public void givenCaretInElementWithText_whenMovedBeforePrecedingElementAndMovedForwardOnce_shouldSelectOnlySecondElement() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveBy(1);

-		final Element paraElement = widget.insertElement(PARA);

+		final IElement paraElement = widget.insertElement(PARA);

 		widget.insertText("Hello Again");

 		widget.moveTo(paraElement.getEndOffset() - 3);

 		widget.moveTo(titleElement.getStartOffset(), true);

@@ -142,10 +140,10 @@
 

 	@Test

 	public void givenCaretInElementWithText_whenMovedBeforePrecedingElementAndMovedForwardTwice_shouldSelectOnlyTextFragementOfSecondElement() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 		widget.moveBy(1);

-		final Element paraElement = widget.insertElement(PARA);

+		final IElement paraElement = widget.insertElement(PARA);

 		widget.insertText("Hello Again");

 		widget.moveTo(paraElement.getEndOffset() - 3);

 		widget.moveTo(titleElement.getStartOffset(), true);

@@ -157,7 +155,7 @@
 

 	@Test

 	public void givenCarentInEmptyComment_whenMovedBeforeComment_shouldExpandSelectionToIncludeEndOffset() throws Exception {

-		final Comment comment = widget.insertComment();

+		final IComment comment = widget.insertComment();

 		widget.moveBy(-1, true);

 		assertTrue(widget.hasSelection());

 		assertEquals(comment.getRange(), widget.getSelectedRange());

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
index e20f2db..bd92663 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
@@ -20,9 +20,9 @@
 import static org.junit.Assert.assertSame;

 import static org.junit.Assert.assertTrue;

 

+import org.eclipse.vex.core.dom.IDocumentFragment;

+import org.eclipse.vex.core.dom.IElement;

 import org.eclipse.vex.core.internal.css.StyleSheet;

-import org.eclipse.vex.core.internal.dom.DocumentFragment;

-import org.eclipse.vex.core.internal.dom.Element;

 import org.junit.Before;

 import org.junit.Test;

 

@@ -32,7 +32,7 @@
 public class L2SimpleEditingTest {

 

 	private VexWidgetImpl widget;

-	private Element rootElement;

+	private IElement rootElement;

 

 	@Before

 	public void setUp() throws Exception {

@@ -49,13 +49,13 @@
 

 	@Test

 	public void shouldMoveCaretIntoInsertedElement() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		assertEquals(titleElement.getEndOffset(), widget.getCaretOffset());

 	}

 

 	@Test

 	public void shouldProvideInsertionElementAsCurrentElement() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.moveBy(-1);

 		assertEquals(titleElement.getStartOffset(), widget.getCaretOffset());

 		assertSame(rootElement, widget.getCurrentElement());

@@ -63,7 +63,7 @@
 

 	@Test

 	public void givenAnElementWithText_whenAtEndOfTextAndHittingBackspace_shouldDeleteLastCharacter() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello");

 		widget.deletePreviousChar();

 		assertEquals("Hell", titleElement.getText());

@@ -72,7 +72,7 @@
 

 	@Test

 	public void givenAnElementWithText_whenAtBeginningOfTextAndHittingDelete_shouldDeleteFirstCharacter() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello");

 		widget.moveBy(-5);

 		widget.deleteNextChar();

@@ -84,7 +84,7 @@
 	public void givenAnEmptyElement_whenCaretBetweenStartAndEndTagAndHittingBackspace_shouldDeleteEmptyElement() throws Exception {

 		widget.insertElement(TITLE);

 		widget.moveBy(1);

-		final Element paraElement = widget.insertElement(PARA);

+		final IElement paraElement = widget.insertElement(PARA);

 		widget.deletePreviousChar();

 		assertEquals(1, rootElement.children().count());

 		assertNull(paraElement.getParent());

@@ -95,7 +95,7 @@
 	public void givenAnEmptyElement_whenCaretBetweenStartAndEndTagAndHittingDelete_shouldDeleteEmptyElement() throws Exception {

 		widget.insertElement(TITLE);

 		widget.moveBy(1);

-		final Element paraElement = widget.insertElement(PARA);

+		final IElement paraElement = widget.insertElement(PARA);

 		widget.deleteNextChar();

 		assertEquals(1, rootElement.children().count());

 		assertNull(paraElement.getParent());

@@ -106,7 +106,7 @@
 	public void givenAnEmptyElement_whenCaretAfterEndTagAndHittingDelete_shouldDeleteEmptyElement() throws Exception {

 		widget.insertElement(TITLE);

 		widget.moveBy(1);

-		final Element paraElement = widget.insertElement(PARA);

+		final IElement paraElement = widget.insertElement(PARA);

 		widget.moveBy(1);

 		widget.deletePreviousChar();

 		assertEquals(1, rootElement.children().count());

@@ -118,7 +118,7 @@
 	public void givenAnEmptyElement_whenCaretBeforeStartTagAndHittingDelete_shouldDeleteEmptyElement() throws Exception {

 		widget.insertElement(TITLE);

 		widget.moveBy(1);

-		final Element paraElement = widget.insertElement(PARA);

+		final IElement paraElement = widget.insertElement(PARA);

 		widget.moveBy(-1);

 		widget.deleteNextChar();

 		assertEquals(1, rootElement.children().count());

@@ -130,10 +130,10 @@
 	public void givenTwoMatchingElements_whenCaretBetweenEndAndStartTagAndHittingBackspace_shouldJoinElements() throws Exception {

 		widget.insertElement(TITLE);

 		widget.moveBy(1);

-		final Element para1 = widget.insertElement(PARA);

+		final IElement para1 = widget.insertElement(PARA);

 		widget.insertText("Hello");

 		widget.moveBy(1);

-		final Element para2 = widget.insertElement(PARA);

+		final IElement para2 = widget.insertElement(PARA);

 		widget.insertText("World");

 

 		widget.moveTo(para2.getStartOffset());

@@ -151,10 +151,10 @@
 	public void givenTwoMatchingElements_whenCaretBetweenEndAndStartTagAndHittingDelete_shouldJoinElements() throws Exception {

 		widget.insertElement(TITLE);

 		widget.moveBy(1);

-		final Element para1 = widget.insertElement(PARA);

+		final IElement para1 = widget.insertElement(PARA);

 		widget.insertText("Hello");

 		widget.moveBy(1);

-		final Element para2 = widget.insertElement(PARA);

+		final IElement para2 = widget.insertElement(PARA);

 		widget.insertText("World");

 

 		widget.moveTo(para2.getStartOffset());

@@ -172,10 +172,10 @@
 	public void givenTwoMatchingElements_whenCaretAfterStartTagOfSecondElementAndHittingBackspace_shouldJoinElements() throws Exception {

 		widget.insertElement(TITLE);

 		widget.moveBy(1);

-		final Element para1 = widget.insertElement(PARA);

+		final IElement para1 = widget.insertElement(PARA);

 		widget.insertText("Hello");

 		widget.moveBy(1);

-		final Element para2 = widget.insertElement(PARA);

+		final IElement para2 = widget.insertElement(PARA);

 		widget.insertText("World");

 

 		widget.moveTo(para2.getStartOffset() + 1);

@@ -193,10 +193,10 @@
 	public void givenTwoMatchingElements_whenCaretBeforeEndTagOfFirstElementAndHittingDelete_shouldJoinElements() throws Exception {

 		widget.insertElement(TITLE);

 		widget.moveBy(1);

-		final Element para1 = widget.insertElement(PARA);

+		final IElement para1 = widget.insertElement(PARA);

 		widget.insertText("Hello");

 		widget.moveBy(1);

-		final Element para2 = widget.insertElement(PARA);

+		final IElement para2 = widget.insertElement(PARA);

 		widget.insertText("World");

 

 		widget.moveTo(para1.getEndOffset());

@@ -212,7 +212,7 @@
 

 	@Test

 	public void givenElementWithText_whenAllTextSelectedAndInsertingACharacter_shouldReplaceAllTextWithNewCharacter() throws Exception {

-		final Element titleElement = widget.insertElement(TITLE);

+		final IElement titleElement = widget.insertElement(TITLE);

 		widget.insertText("Hello World");

 

 		widget.moveTo(titleElement.getStartOffset() + 1, true);

@@ -255,8 +255,8 @@
 	public void whenReadOnly_shouldNotInsertFragment() throws Exception {

 		widget.insertElement(TITLE);

 		widget.moveBy(1);

-		final Element para = widget.insertElement(PARA);

-		final DocumentFragment fragment = widget.getDocument().getFragment(para.getRange());

+		final IElement para = widget.insertElement(PARA);

+		final IDocumentFragment fragment = widget.getDocument().getFragment(para.getRange());

 		widget.moveTo(widget.getDocument().getRootElement().getEndOffset());

 

 		widget.setReadOnly(true);

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java
index b2843db..cb4eda3 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java
@@ -18,13 +18,13 @@
 import java.util.Arrays;
 
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.IDocumentFragment;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IText;
+import org.eclipse.vex.core.dom.IValidator;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentFragment;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Text;
-import org.eclipse.vex.core.internal.dom.Validator;
 import org.eclipse.vex.core.internal.validator.WTPVEXValidator;
 import org.junit.Test;
 
@@ -81,7 +81,7 @@
 		widget.insertElement(new QualifiedName(CONTENT_NS, "p"));
 		widget.insertText("1text before comment1");
 		widget.insertComment();
-		final Node comment = widget.getDocument().getChildAt(widget.getCaretOffset());
+		final INode comment = widget.getDocument().getChildAt(widget.getCaretOffset());
 		widget.insertText("2comment text2");
 		widget.moveBy(1);
 		widget.insertText("3text after comment3");
@@ -92,7 +92,7 @@
 			public void run() {
 				widget.moveTo(comment.getStartOffset() + 1, false);
 				widget.moveTo(comment.getEndOffset() - 1, true);
-				final DocumentFragment fragment = widget.getSelectedFragment();
+				final IDocumentFragment fragment = widget.getSelectedFragment();
 				widget.deleteSelection();
 
 				widget.moveBy(-1, false);
@@ -109,14 +109,14 @@
 	}
 
 	public static Document createDocumentWithDTD(final String dtdIdentifier, final String rootElementName) {
-		final Validator validator = new WTPVEXValidator(dtdIdentifier);
+		final IValidator validator = new WTPVEXValidator(dtdIdentifier);
 		final Document document = new Document(new QualifiedName(null, rootElementName));
 		document.setValidator(validator);
 		return document;
 	}
 
 	public static Document createDocument(final String rootSchemaIdentifier, final String rootElementName) {
-		final Validator validator = new WTPVEXValidator();
+		final IValidator validator = new WTPVEXValidator();
 		final Document document = new Document(new QualifiedName(rootSchemaIdentifier, rootElementName));
 		document.setValidator(validator);
 		return document;
@@ -137,17 +137,17 @@
 		return result;
 	}
 
-	public static String getContentStructure(final Element element) {
+	public static String getContentStructure(final IElement element) {
 		final StringBuilder result = new StringBuilder();
 		result.append("<").append(element.getQualifiedName()).append(" (").append(element.getStartOffset()).append("-").append(element.getEndOffset()).append(")");
 		result.append(" ").append(element.getText());
 		if (!element.hasChildren()) {
 			result.append(" [");
-			for (final Node child : element.children()) {
-				if (child instanceof Element) {
-					result.append(getContentStructure((Element) child));
-				} else if (child instanceof Text) {
-					result.append(getContentStructure((Text) child));
+			for (final INode child : element.children()) {
+				if (child instanceof IElement) {
+					result.append(getContentStructure((IElement) child));
+				} else if (child instanceof IText) {
+					result.append(getContentStructure((IText) child));
 				}
 			}
 			result.append("]");
@@ -156,7 +156,7 @@
 		return result.toString();
 	}
 
-	public static String getContentStructure(final Text text) {
+	public static String getContentStructure(final IText text) {
 		final StringBuilder result = new StringBuilder();
 		result.append("'(").append(text.getStartOffset()).append("-").append(text.getEndOffset()).append(") ").append(text.getText()).append("'");
 		return result.toString();
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestSuite.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestSuite.java
index 7f6b8bc..bb85ba2 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestSuite.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestSuite.java
@@ -25,7 +25,6 @@
 import org.eclipse.vex.core.internal.dom.CopyVisitorTest;
 import org.eclipse.vex.core.internal.dom.DTDValidatorTest;
 import org.eclipse.vex.core.internal.dom.DeepCopyTest;
-import org.eclipse.vex.core.internal.dom.DocumentContentModelTest;
 import org.eclipse.vex.core.internal.dom.DocumentFragmentTest;
 import org.eclipse.vex.core.internal.dom.DocumentTest;
 import org.eclipse.vex.core.internal.dom.GapContentTest;
@@ -35,8 +34,8 @@
 import org.eclipse.vex.core.internal.dom.L1TextHandlingTest;
 import org.eclipse.vex.core.internal.dom.NamespaceTest;
 import org.eclipse.vex.core.internal.dom.ParentTest;
-import org.eclipse.vex.core.internal.dom.RangeTest;
-import org.eclipse.vex.core.internal.dom.SchemaValidatorTest;
+import org.eclipse.vex.core.internal.dom.ContentRangeTest;
+import org.eclipse.vex.core.internal.io.DocumentContentModelTest;
 import org.eclipse.vex.core.internal.io.DocumentReaderTest;
 import org.eclipse.vex.core.internal.io.DocumentWriterTest;
 import org.eclipse.vex.core.internal.io.NamespaceStackTest;
@@ -49,6 +48,7 @@
 import org.eclipse.vex.core.internal.layout.TestBlocksInInlines;
 import org.eclipse.vex.core.internal.layout.TestDocumentTextBox;
 import org.eclipse.vex.core.internal.layout.TestStaticTextBox;
+import org.eclipse.vex.core.internal.validator.SchemaValidatorTest;
 import org.eclipse.vex.core.internal.widget.L2CommentEditingTest;
 import org.eclipse.vex.core.internal.widget.L2SelectionTest;
 import org.eclipse.vex.core.internal.widget.L2SimpleEditingTest;
@@ -58,7 +58,7 @@
 
 @RunWith(Suite.class)
 @Suite.SuiteClasses({ FilterIteratorTest.class, FirstNIteratorTest.class, AfterNIteratorTest.class, AxisTest.class, NamespaceStackTest.class, NamespaceTest.class, DocumentReaderTest.class,
-		DocumentContentModelTest.class, SchemaValidatorTest.class, CssTest.class, BatikBehaviorTest.class, RangeTest.class, BasicNodeTest.class, ParentTest.class, DocumentTest.class,
+		DocumentContentModelTest.class, SchemaValidatorTest.class, CssTest.class, BatikBehaviorTest.class, ContentRangeTest.class, BasicNodeTest.class, ParentTest.class, DocumentTest.class,
 		L1TextHandlingTest.class, L1CommentHandlingTest.class, L1ElementHandlingTest.class, L1FragmentHandlingTest.class, DocumentFragmentTest.class, CopyVisitorTest.class, DeepCopyTest.class,
 		PropertyTest.class, RuleTest.class, BlockElementBoxTest.class, ImageBoxTest.class, DocumentWriterTest.class, DTDValidatorTest.class, GapContentTest.class, SpaceNormalizerTest.class,
 		TextWrapperTest.class, TestBlockElementBox.class, TestBlocksInInlines.class, TestDocumentTextBox.class, TestStaticTextBox.class, TableLayoutTest.class, LayoutTestSuite.class,
diff --git a/org.eclipse.vex.core/META-INF/MANIFEST.MF b/org.eclipse.vex.core/META-INF/MANIFEST.MF
index 8ff5370..34c0768 100644
--- a/org.eclipse.vex.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.vex.core/META-INF/MANIFEST.MF
@@ -17,14 +17,16 @@
  org.w3c.css.sac;bundle-version="[1.3.0,2.0.0)",
  org.apache.batik.css;bundle-version="1.7.0",
  org.apache.batik.util;bundle-version="1.7.0"
-Export-Package: org.eclipse.vex.core.internal;x-friends:="org.eclipse.vex.ui",
+Export-Package: org.eclipse.vex.core,
+ org.eclipse.vex.core.dom;uses:="org.eclipse.vex.core.internal.dom",
+ org.eclipse.vex.core.internal;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
  org.eclipse.vex.core.internal.core;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
  org.eclipse.vex.core.internal.css;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
  org.eclipse.vex.core.internal.dom;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
- org.eclipse.vex.core.internal.io,
+ org.eclipse.vex.core.internal.io;x-friends:="org.eclipse.vex.core.tests,org.eclipse.vex.ui",
  org.eclipse.vex.core.internal.layout;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
- org.eclipse.vex.core.internal.undo;x-internal:=true,
- org.eclipse.vex.core.internal.validator;x-friends:="org.eclipse.vex.ui",
+ org.eclipse.vex.core.internal.undo;x-friends:="org.eclipse.vex.core.tests,org.eclipse.vex.ui",
+ org.eclipse.vex.core.internal.validator;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests",
  org.eclipse.vex.core.internal.widget;x-friends:="org.eclipse.vex.ui,org.eclipse.vex.core.tests"
 Bundle-Activator: org.eclipse.vex.core.internal.VEXCorePlugin
 Bundle-Localization: plugin
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/IFilter.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/IFilter.java
similarity index 94%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/IFilter.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/IFilter.java
index ac816da..dc0f246 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/IFilter.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/IFilter.java
@@ -8,7 +8,7 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.core;

+package org.eclipse.vex.core;

 

 /**

  * A simple filtering facility.

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/BaseNodeVisitor.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/BaseNodeVisitor.java
similarity index 71%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/BaseNodeVisitor.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/BaseNodeVisitor.java
index 07b35ec..60683cc 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/BaseNodeVisitor.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/BaseNodeVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2012 Florian Thienel and others.

+ * Copyright (c) 2012, 2013 Florian Thienel and others.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -8,7 +8,7 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.dom;

+package org.eclipse.vex.core.dom;

 

 /**

  * This class provides default implementations for the methods defined by the <code>INodeVisitor</code> interface.

@@ -18,23 +18,23 @@
  */

 public class BaseNodeVisitor implements INodeVisitor {

 

-	public void visit(final Document document) {

+	public void visit(final IDocument document) {

 		// ignore

 	}

 

-	public void visit(final DocumentFragment fragment) {

+	public void visit(final IDocumentFragment fragment) {

 		// ignore

 	}

 

-	public void visit(final Element element) {

+	public void visit(final IElement element) {

 		// ignore

 	}

 

-	public void visit(final Text text) {

+	public void visit(final IText text) {

 		// ignore

 	}

 

-	public void visit(final Comment comment) {

+	public void visit(final IComment comment) {

 		// ignore

 	}

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/BaseNodeVisitorWithResult.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/BaseNodeVisitorWithResult.java
similarity index 79%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/BaseNodeVisitorWithResult.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/BaseNodeVisitorWithResult.java
index ca15eb2..6df85fd 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/BaseNodeVisitorWithResult.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/BaseNodeVisitorWithResult.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2012 Florian Thienel and others.

+ * Copyright (c) 2012, 2013 Florian Thienel and others.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -8,7 +8,7 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.dom;

+package org.eclipse.vex.core.dom;

 

 /**

  * This class provides default implementations for the methods defined by the <code>INodeVisitorWithResult</code>

@@ -30,23 +30,23 @@
 		this.defaultValue = defaultValue;

 	}

 

-	public T visit(final Document document) {

+	public T visit(final IDocument document) {

 		return defaultValue;

 	}

 

-	public T visit(final DocumentFragment fragment) {

+	public T visit(final IDocumentFragment fragment) {

 		return defaultValue;

 	}

 

-	public T visit(final Element element) {

+	public T visit(final IElement element) {

 		return defaultValue;

 	}

 

-	public T visit(final Text text) {

+	public T visit(final IText text) {

 		return defaultValue;

 	}

 

-	public T visit(final Comment comment) {

+	public T visit(final IComment comment) {

 		return defaultValue;

 	}

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/ContentRange.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/ContentRange.java
similarity index 95%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/ContentRange.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/ContentRange.java
index a332523..4a7ae73 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/ContentRange.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/ContentRange.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2012 Florian Thienel and others.

+ * Copyright (c) 2012,2013 Florian Thienel and others.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -8,16 +8,16 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.dom;

+package org.eclipse.vex.core.dom;

 

 import java.text.MessageFormat;

 

 import org.eclipse.core.runtime.Assert;

 

 /**

- * An immutable representation of a range within Content.

+ * An immutable representation of a range within <code>IContent</code>.

  * 

- * @see Content

+ * @see IContent

  * @author Florian Thienel

  */

 public class ContentRange {

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/DocumentEvent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/DocumentEvent.java
new file mode 100644
index 0000000..309d2a3
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/DocumentEvent.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2013 John Krasnay and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     John Krasnay - initial API and implementation
+ *     Florian Thienel - support for attribute changes
+ *******************************************************************************/
+package org.eclipse.vex.core.dom;
+
+import java.util.EventObject;
+
+import org.eclipse.core.runtime.QualifiedName;
+
+/**
+ * Encapsulation of the details of a document change.
+ */
+public class DocumentEvent extends EventObject {
+
+	private static final long serialVersionUID = -9028980559838712720L;
+
+	private final IDocument document;
+	private final IParent parent;
+	private final ContentRange range;
+	private final QualifiedName attributeName;
+	private final String oldAttributeValue;
+	private final String newAttributeValue;
+
+	/**
+	 * Create an event.
+	 * 
+	 * @param document
+	 *            the document that changed
+	 * @param parent
+	 *            the parent node containing the change
+	 * @param range
+	 *            the range which was changed
+	 */
+	public DocumentEvent(final IDocument document, final IParent parent, final ContentRange range) {
+		super(document);
+		this.document = document;
+		this.parent = parent;
+		this.range = range;
+		attributeName = null;
+		oldAttributeValue = null;
+		newAttributeValue = null;
+	}
+
+	/**
+	 * Create an event with attribute information.
+	 * 
+	 * @param document
+	 *            Document that changed.
+	 * @param parent
+	 *            Parent containing the attribute that changed
+	 * @param attributeName
+	 *            name of the attribute that changed
+	 * @param oldAttributeValue
+	 *            value of the attribute before the change.
+	 * @param newAttributeValue
+	 *            value of the attribute after the change.
+	 */
+	public DocumentEvent(final IDocument document, final IParent parent, final QualifiedName attributeName, final String oldAttributeValue, final String newAttributeValue) {
+		super(document);
+		this.document = document;
+		this.parent = parent;
+		range = parent.getRange();
+		this.attributeName = attributeName;
+		this.oldAttributeValue = oldAttributeValue;
+		this.newAttributeValue = newAttributeValue;
+	}
+
+	/**
+	 * @return the range which was changed
+	 */
+	public ContentRange getRange() {
+		return range;
+	}
+
+	/**
+	 * @return the Parent containing the change
+	 */
+	public IParent getParent() {
+		return parent;
+	}
+
+	/**
+	 * @return the value of the attribute before the change. If null, indicates that the attribute was removed
+	 */
+	public String getNewAttributeValue() {
+		return newAttributeValue;
+	}
+
+	/**
+	 * @return the value of the attribute after the change. If null, indicates the attribute did not exist before the
+	 *         change
+	 */
+	public String getOldAttributeValue() {
+		return oldAttributeValue;
+	}
+
+	/**
+	 * @return the qualified name of the attribute that was changed
+	 */
+	public QualifiedName getAttributeName() {
+		return attributeName;
+	}
+
+	/**
+	 * @return the document for which this event was generated
+	 */
+	public IDocument getDocument() {
+		return document;
+	}
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentValidationException.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/DocumentValidationException.java
similarity index 95%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentValidationException.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/DocumentValidationException.java
index 2324331..61f38fe 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentValidationException.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/DocumentValidationException.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     John Krasnay - initial API and implementation
  *******************************************************************************/
-package org.eclipse.vex.core.internal.dom;
+package org.eclipse.vex.core.dom;
 
 /**
  * Exception thrown when an change would have compromised document validity.
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/Filters.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/Filters.java
new file mode 100644
index 0000000..849b3bd
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/Filters.java
@@ -0,0 +1,78 @@
+/*******************************************************************************

+ * Copyright (c) 2013 Florian Thienel and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ * 		Florian Thienel - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.vex.core.dom;

+

+import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.IFilter;

+

+/**

+ * This class provides several useful node filters which can for example be used on axes.

+ * 

+ * @author Florian Thienel

+ * @see IFilter

+ * @see IAxis#matching(IFilter)

+ */

+public final class Filters {

+

+	/**

+	 * This filter matches only element nodes.

+	 * 

+	 * @see IElement

+	 */

+	public static IFilter<INode> elements() {

+		return new IFilter<INode>() {

+			public boolean matches(final INode node) {

+				return node instanceof IElement;

+			}

+		};

+	}

+

+	/**

+	 * This filter matches only element nodes with the given name.

+	 * 

+	 * @param localName

+	 *            the local name to match

+	 */

+	public static IFilter<INode> elementsNamed(final String localName) {

+		return new IFilter<INode>() {

+			public boolean matches(final INode node) {

+				return node.accept(new BaseNodeVisitorWithResult<Boolean>(false) {

+					@Override

+					public Boolean visit(final IElement element) {

+						return element.getLocalName().equals(localName);

+					}

+				});

+			}

+		};

+	}

+

+	/**

+	 * This filter matches only element nodes with the given name.

+	 * 

+	 * @param name

+	 *            the qualified name to match

+	 */

+	public static IFilter<INode> elementsNamed(final QualifiedName name) {

+		return new IFilter<INode>() {

+			public boolean matches(final INode node) {

+				return node.accept(new BaseNodeVisitorWithResult<Boolean>(false) {

+					@Override

+					public Boolean visit(final IElement element) {

+						return element.getQualifiedName().equals(name);

+					}

+				});

+			}

+		};

+	}

+

+	private Filters() {

+	}

+}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IAttribute.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IAttribute.java
new file mode 100644
index 0000000..324f61d
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IAttribute.java
@@ -0,0 +1,58 @@
+/*******************************************************************************

+ * Copyright (c) 2013 Florian Thienel and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ * 		Florian Thienel - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.vex.core.dom;

+

+import org.eclipse.core.runtime.QualifiedName;

+

+/**

+ * A representation of an attribute within the start tag of an element. An attribute consists of a qualified name and a

+ * value. It is comparable by its qualified name, which is the natural order of attributes.

+ * 

+ * @author Florian Thienel

+ */

+public interface IAttribute extends Comparable<IAttribute> {

+

+	/**

+	 * @return the element to which this attribute belongs

+	 */

+	IElement getParent();

+

+	/**

+	 * @return the qualified name of this attribute

+	 */

+	QualifiedName getQualifiedName();

+

+	/**

+	 * @return prefix:localName, or localName if prefix is null or this attribute is in the same namespace as the parent

+	 *         element.

+	 */

+	String getPrefixedName();

+

+	/**

+	 * @return the local name of this attribute

+	 */

+	String getLocalName();

+

+	/**

+	 * @return the value of this attribute .

+	 */

+	String getValue();

+

+	/**

+	 * Compares two attributes by their qualified name.

+	 * 

+	 * @param otherAttribute

+	 *            the other attribute

+	 * @see Comparable

+	 */

+	int compareTo(IAttribute otherAttribute);

+

+}
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IAxis.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IAxis.java
new file mode 100644
index 0000000..96a376c
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IAxis.java
@@ -0,0 +1,173 @@
+/*******************************************************************************

+ * Copyright (c) 2013 Florian Thienel and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ * 		Florian Thienel - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.vex.core.dom;

+

+import java.util.List;

+

+import org.eclipse.vex.core.IFilter;

+

+/**

+ * An Axis represents an iterable sequence of nodes. It is the main concept to navigate in the DOM, inspired by the

+ * XPath axes. Besides implementing the Iterable interface, Axis provides a fluent interface to limit the sequence by

+ * several criteria which are evaluated in the following order:

+ * <ol>

+ * <li>only nodes within a range in the content</li>

+ * <li>omit text nodes</li>

+ * <li>only nodes which match a given chain of filters</li>

+ * <li>only nodes within a range of indices</li>

+ * </ol>

+ * 

+ * Example:

+ * 

+ * <pre>

+ * Iterator&lt;Node&gt; elementsInRange = parent.children().in(new ContentRange(1, 24)).matching(new IFilter&lt;Node&gt;() {

+ * 	public boolean matches(Node node) {

+ * 		return node instanceof Element;

+ * 	}

+ * }).iterator();

+ * </pre>

+ * 

+ * The Iterable interface makes it very convenient to use the axis in a foreach loop.

+ * 

+ * @author Florian Thienel

+ * @see <a href="http://www.w3.org/TR/xpath/#axes">http://www.w3.org/TR/xpath/#axes</a>

+ */

+public interface IAxis<T extends INode> extends Iterable<T> {

+

+	/**

+	 * @return the source node of this axis

+	 */

+	INode getSourceNode();

+

+	/**

+	 * Limit the nodes of this axis to the given content range. Cannot be combined with 'before' or 'after'. Can be

+	 * applied only once.

+	 * 

+	 * @param range

+	 *            the content range

+	 * @return a reference to this axis

+	 * @see IAxis#before

+	 * @see IAxis#after

+	 */

+	IAxis<? extends T> in(ContentRange range);

+

+	/**

+	 * Limit the nodes of this axis to nodes before the given offset. Cannot be combined with 'in' or 'after'. Can be

+	 * applied only once.

+	 * 

+	 * @param beforeOffset

+	 *            the offset

+	 * @return a reference to this axis

+	 * @see IAxis#in

+	 * @see IAxis#after

+	 */

+	IAxis<? extends T> before(int beforeOffset);

+

+	/**

+	 * Limit the nodes of this axis to nodes after the given offset. Cannot be combined with 'in' or 'before'. Can be

+	 * applied only once.

+	 * 

+	 * @param afterOffset

+	 *            the offset

+	 * @return a reference to this axis

+	 * @see IAxis#in

+	 * @see IAxis#before

+	 */

+	IAxis<? extends T> after(int afterOffset);

+

+	/**

+	 * Do not include Text nodes in this axis.

+	 * 

+	 * @return a reference to this axis

+	 */

+	IAxis<? extends T> withoutText();

+

+	/**

+	 * Limit the nodes of this axis to nodes matching the given filter. Can be applied multiple times to chain multiple

+	 * filters.

+	 * 

+	 * @param filter

+	 *            the filter

+	 * @return a reference to this axis

+	 * @see Filters

+	 */

+	IAxis<? extends T> matching(IFilter<INode> filter);

+

+	/**

+	 * Start the sequence of this axis at the given index. Can be applied only once.

+	 * 

+	 * @param startIndex

+	 *            the start index

+	 * @return a reference to this axis

+	 * @see IAxis#to

+	 */

+	IAxis<? extends T> from(int startIndex);

+

+	/**

+	 * End the sequence of this axis at the given index. Can be applied only once.

+	 * 

+	 * @param endIndex

+	 *            the end index

+	 * @return a reference to this axis

+	 * @see IAxis#from

+	 */

+	IAxis<? extends T> to(int endIndex);

+

+	/**

+	 * @return true if this sequence of this axis with all given criteria applied is empty

+	 */

+	boolean isEmpty();

+

+	/**

+	 * Create a list with all nodes of this axis that satisfy all given criteria. Be aware that this method goes through

+	 * the whole sequence to collect all matching nodes.

+	 * 

+	 * @return all nodes to which the given criteria apply as list

+	 */

+	List<T> asList();

+

+	/**

+	 * @return the first node of this axis that satisfies all given critera

+	 */

+	T first();

+

+	/**

+	 * Find the last node of this axis which satisfies all given criteria. Be aware that this method goes through the

+	 * whole sequence to find the last matching node.

+	 * 

+	 * @return the last node of this axis that satisfies all given criteria

+	 */

+	T last();

+

+	/**

+	 * @param index

+	 *            the index

+	 * @return the node with the given index in the resulting sequence of nodes

+	 */

+	T get(int index);

+

+	/**

+	 * Visit all nodes of this axis that satisfy all given criteria.

+	 * 

+	 * @param visitor

+	 *            the visitor

+	 */

+	void accept(INodeVisitor visitor);

+

+	/**

+	 * Count all nodes of this axis that satisfy all given criteria. Be aware that this method goes through the whole

+	 * sequence to count all matching nodes.

+	 * 

+	 * @return the number of nodes of this axis that satisfy all given criteria

+	 */

+	int count();

+

+}
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/IFilter.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IComment.java
similarity index 69%
copy from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/IFilter.java
copy to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IComment.java
index ac816da..3682518 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/IFilter.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IComment.java
@@ -8,19 +8,14 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.core;

+package org.eclipse.vex.core.dom;

+

 

 /**

- * A simple filtering facility.

+ * A representation of an XML comment in the DOM. Comments have textual content, a start and an end tag.

  * 

  * @author Florian Thienel

  */

-public interface IFilter<T> {

+public interface IComment extends INode {

 

-	/**

-	 * @param t

-	 *            the object to evaluate

-	 * @return true if the given object matches this filter

-	 */

-	boolean matches(T t);

-}

+}
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Content.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IContent.java
similarity index 81%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Content.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IContent.java
index 37d8d36..48c31d9 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Content.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IContent.java
@@ -9,12 +9,12 @@
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - refactoring to full fledged DOM
  *******************************************************************************/
-package org.eclipse.vex.core.internal.dom;
+package org.eclipse.vex.core.dom;
 
 /**
  * Interface for classes that manage a string of characters representing the textual content of a document.
  */
-public interface Content extends CharSequence {
+public interface IContent extends CharSequence {
 
 	/**
 	 * Create a new Position object at the given initial offset.
@@ -22,7 +22,7 @@
 	 * @param offset
 	 *            initial offset of the position
 	 */
-	public Position createPosition(int offset);
+	IPosition createPosition(int offset);
 
 	/**
 	 * Remove the given Position from the list of positions. A removed position is not updated anymore when this content
@@ -31,7 +31,7 @@
 	 * @param position
 	 *            the position to remove
 	 */
-	public void removePosition(Position position);
+	void removePosition(IPosition position);
 
 	/**
 	 * Insert the given text at the given offset into this content.
@@ -41,7 +41,7 @@
 	 * @param text
 	 *            the text to insert
 	 */
-	public void insertText(int offset, String text);
+	void insertText(int offset, String text);
 
 	/**
 	 * Get the plain text of a range in this content. The plain text does not contain any tag markers in this content.
@@ -52,14 +52,14 @@
 	 *            the range of the text to return
 	 * @return the plain text of the given range, not including tag markers
 	 */
-	public String getText(final ContentRange range);
+	String getText(final ContentRange range);
 
 	/**
 	 * Get the whole plain text of this content. The plain text does not contain any tag markers.
 	 * 
 	 * @return the whole plain text, not including tag markers
 	 */
-	public String getText();
+	String getText();
 
 	/**
 	 * Get the raw text of a range in this content. The plain text does also contain the tag markers in this content.
@@ -68,14 +68,14 @@
 	 *            the range of the text to return
 	 * @return the text of the given range, including element markers
 	 */
-	public String getRawText(final ContentRange range);
+	String getRawText(final ContentRange range);
 
 	/**
 	 * Get the whole raw text of this content. The raw text does also contain the tag markers in this content.
 	 * 
 	 * @return the whole text, including tag markers
 	 */
-	public String getRawText();
+	String getRawText();
 
 	/**
 	 * Insert the given content into this content at the given offset.
@@ -85,7 +85,7 @@
 	 * @param content
 	 *            content to insert
 	 */
-	public void insertContent(final int offset, final Content content);
+	void insertContent(final int offset, final IContent content);
 
 	/**
 	 * Get a copy of a range in this content.
@@ -94,12 +94,12 @@
 	 *            the range to copy
 	 * @return the copy of the given range
 	 */
-	public Content getContent(final ContentRange range);
+	IContent getContent(final ContentRange range);
 
 	/**
 	 * @return a full copy of this content
 	 */
-	public Content getContent();
+	IContent getContent();
 
 	/**
 	 * Insert a tag marker at the given offset into this content.
@@ -107,7 +107,7 @@
 	 * @param offset
 	 *            offset at which to insert the tag marker.
 	 */
-	public void insertTagMarker(int offset);
+	void insertTagMarker(int offset);
 
 	/**
 	 * Indicate if there is a tag marker at the given offset.
@@ -115,7 +115,7 @@
 	 * @param offset
 	 *            offset at which to check if a tag marker is present.
 	 */
-	public boolean isTagMarker(int offset);
+	boolean isTagMarker(int offset);
 
 	/**
 	 * Delete the given range of characters.
@@ -123,15 +123,15 @@
 	 * @param range
 	 *            the range to delete from this content
 	 */
-	public void remove(ContentRange range);
+	void remove(ContentRange range);
 
 	/**
 	 * @return the length of the content including tag markers
 	 */
-	public int length();
+	int length();
 
 	/**
 	 * @return the range of this content = [0, length - 1].
 	 */
-	public ContentRange getRange();
+	ContentRange getRange();
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IDocument.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IDocument.java
new file mode 100644
index 0000000..f7b4bf2
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IDocument.java
@@ -0,0 +1,277 @@
+/*******************************************************************************

+ * Copyright (c) 2013 Florian Thienel and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ * 		Florian Thienel - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.vex.core.dom;

+

+import java.util.List;

+

+import org.eclipse.core.runtime.QualifiedName;

+

+/**

+ * A representation of an XML document in the DOM.

+ * 

+ * @author Florian Thienel

+ */

+public interface IDocument extends IParent {

+

+	/**

+	 * @return the base URI of this document

+	 * @see INode#getBaseURI()

+	 * @see http://www.w3.org/TR/xmlbase/

+	 */

+	String getDocumentURI();

+

+	/**

+	 * Set the root base URI of this document, which is used to resolve resources with relative location information.

+	 * 

+	 * @param documentURI

+	 *            the base URI of this document

+	 * @see INode#getBaseURI()

+	 * @see http://www.w3.org/TR/xmlbase/

+	 */

+	void setDocumentURI(String documentURI);

+

+	/**

+	 * @return the encoding of this document

+	 */

+	String getEncoding();

+

+	/**

+	 * Set the encoding of this document.

+	 * 

+	 * @param encoding

+	 *            the encoding of this document

+	 */

+	void setEncoding(String encoding);

+

+	/**

+	 * @return the public identifier of this document

+	 */

+	String getPublicID();

+

+	/**

+	 * Set the public identifier of this document

+	 * 

+	 * @param publicID

+	 *            the public identifier of this document

+	 */

+	void setPublicID(String publicID);

+

+	/**

+	 * @return the system identifier of this document

+	 */

+	String getSystemID();

+

+	/**

+	 * Set the system identifier of this document.

+	 * 

+	 * @param systemID

+	 *            the system identifier of this document

+	 */

+	void setSystemID(String systemID);

+

+	/**

+	 * @return the validator of this document

+	 */

+	IValidator getValidator();

+

+	/**

+	 * Set the validator of this document.

+	 * 

+	 * @param validator

+	 *            the validator of this document

+	 */

+	void setValidator(IValidator validator);

+

+	/**

+	 * A document can have only one element node as child. This element is called the 'root element'. While the root

+	 * element is the only child element of an document, the document can have further child nodes of other types (e.g.

+	 * comments or processing instructions) before or (less common but legal) after the root element.

+	 * 

+	 * @return the root element of this document

+	 */

+	IElement getRootElement();

+

+	/**

+	 * @return the length of the textual content of this document plus 1 for each opening or closing XML tag (element

+	 *         tags, comment tags, PI tags and entity references).

+	 */

+	int getLength();

+

+	/**

+	 * Create a Position for the given offset. A position is automatically updated if it "moves" due to content

+	 * modifications.

+	 * 

+	 * <p>

+	 * All created positions are referenced by this document. <b>Make sure to remove positions you don't need

+	 * anymore.</b>

+	 * 

+	 * @see IPosition

+	 * @see IDocument#removePosition(IPosition)

+	 * @return the Position for the given offset

+	 */

+	IPosition createPosition(int offset);

+

+	/**

+	 * Remove the given Position. A removed position is not updated anymore.

+	 * 

+	 * @param position

+	 *            the position to remove

+	 * @see IDocument#createPosition(int)

+	 */

+	void removePosition(IPosition position);

+

+	/**

+	 * @return true if text can be inserted at the given offset

+	 */

+	boolean canInsertText(int offset);

+

+	/**

+	 * Insert the given text at the given offset.

+	 * 

+	 * @param offset

+	 *            the offset at which the text should be inserted

+	 * @param text

+	 *            The text to insert. Control characters are automatically converted to \s (except for \n).

+	 * @throws DocumentValidationException

+	 *             if text is not allowed at the given offset

+	 */

+	void insertText(int offset, String text) throws DocumentValidationException;

+

+	/**

+	 * @return true if a comment can be inserted a the given offset

+	 */

+	boolean canInsertComment(int offset);

+

+	/**

+	 * Insert a new comment at the given offset.

+	 * 

+	 * @see IComment

+	 * @param offset

+	 *            the offset at which the comment should be inserted

+	 * @return the new comment

+	 * @throws DocumentValidationException

+	 *             if a comment is not allowed a the given offset (e.g. within an existing comment)

+	 */

+	IComment insertComment(int offset) throws DocumentValidationException;

+

+	/**

+	 * @return true if a new element with the given qualified name can be inserted at the given offset

+	 */

+	boolean canInsertElement(int offset, QualifiedName elementName);

+

+	/**

+	 * Insert a new element with the given qualified name a the given offset.

+	 * 

+	 * @see IElement

+	 * @see QualifiedName

+	 * @param offset

+	 *            the offset at which the element should be inserted

+	 * @param elementName

+	 *            the qualified name of the new element

+	 * @return the new element

+	 * @throws DocumentValidationException

+	 *             if an element with the given qualified name is not allowed a the given offset

+	 */

+	IElement insertElement(int offset, QualifiedName elementName) throws DocumentValidationException;

+

+	/**

+	 * @return true if the given DocumentFragment can be inserted at the given offset

+	 */

+	boolean canInsertFragment(int offset, IDocumentFragment fragment);

+

+	/**

+	 * Insert the given DocumentFragment at the given offset.

+	 * 

+	 * @see IDocumentFragment

+	 * @param offset

+	 *            the offset at which the fragment should be inserted

+	 * @param fragment

+	 *            the fragment to insert

+	 * @throws DocumentValidationException

+	 *             if the given fragment may not be inserted at the given offset

+	 */

+	void insertFragment(int offset, IDocumentFragment fragment) throws DocumentValidationException;

+

+	/**

+	 * Delete everything in the given range. The range must be balanced i.e. it must start in the same node as it ends.

+	 * 

+	 * @param range

+	 *            the range to delete

+	 * @throws DocumentValidationException

+	 *             if the deletion would lead to an invalid document

+	 */

+	void delete(ContentRange range) throws DocumentValidationException;

+

+	/**

+	 * @return the character at the given offset. If there is an XML tag at the given offset \0 is returned.

+	 */

+	char getCharacterAt(int offset);

+

+	/**

+	 * Find the nearest common node of the given offsets going from each offset to the root element.

+	 * 

+	 * @param offset1

+	 *            the first offset

+	 * @param offset2

+	 *            the second offset

+	 * @return the nearest common node for both offsets

+	 */

+	INode findCommonNode(int offset1, int offset2);

+

+	/**

+	 * @return the node in which an insertion at the given offset will end

+	 */

+	INode getNodeForInsertionAt(int offset);

+

+	/**

+	 * @return the element in which an insertion at the given offset will end

+	 */

+	IElement getElementForInsertionAt(int offset);

+

+	/**

+	 * @return true if there is an XML tag at the given offset (element tags, comment tags, PI tags and entity

+	 *         references)

+	 */

+	boolean isTagAt(int offset);

+

+	/**

+	 * Create a new DocumentFragment with a deep copy of the given range in this document. The range must be balanced

+	 * i.e. it must start in the same node as it ends.

+	 * 

+	 * @see IDocumentFragment

+	 * @param range

+	 *            the range to copy into the fragment

+	 * @return a new fragment with a deep copy of the given range

+	 */

+	IDocumentFragment getFragment(ContentRange range);

+

+	/**

+	 * @return all nodes in the given range in this document

+	 */

+	List<? extends INode> getNodes(ContentRange range);

+

+	/**

+	 * Add a listener that is notified about modifications to this document.

+	 * 

+	 * @param listener

+	 *            the listener

+	 */

+	void addDocumentListener(IDocumentListener listener);

+

+	/**

+	 * Remove a listener that has been added before.

+	 * 

+	 * @param listener

+	 *            the listener to remove

+	 */

+	void removeDocumentListener(IDocumentListener listener);

+

+}
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IDocumentFragment.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IDocumentFragment.java
new file mode 100644
index 0000000..3274ffd
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IDocumentFragment.java
@@ -0,0 +1,40 @@
+/*******************************************************************************

+ * Copyright (c) 2013 Florian Thienel and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ * 		Florian Thienel - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.vex.core.dom;

+

+import java.util.List;

+

+import org.eclipse.core.runtime.QualifiedName;

+

+/**

+ * Represents a wellformed fragment of an XML document.

+ * 

+ * @author Florian Thienel

+ */

+public interface IDocumentFragment extends IParent {

+

+	/**

+	 * @return the length of the textual content of this fragment plus 1 for each opening or closing XML tag (element

+	 *         tags, comment tags, PI tags and entity references)

+	 */

+	int getLength();

+

+	/**

+	 * @return a list with the qualified names off all nodes on the root level of this fragment

+	 */

+	List<QualifiedName> getNodeNames();

+

+	/**

+	 * @return all nodes on the root level of this fragment

+	 */

+	List<? extends INode> getNodes();

+

+}
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentListener.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IDocumentListener.java
similarity index 67%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentListener.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IDocumentListener.java
index 8db9707..65ff63b 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentListener.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IDocumentListener.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2008 John Krasnay and others.
+ * Copyright (c) 2004, 2013 John Krasnay and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,60 +7,61 @@
  * 
  * Contributors:
  *     John Krasnay - initial API and implementation
+ *     Florian Thienel - promoted to the public API
  *******************************************************************************/
-package org.eclipse.vex.core.internal.dom;
+package org.eclipse.vex.core.dom;
 
 /**
  * Receives notifications of document changes.
  */
-public interface DocumentListener extends java.util.EventListener {
+public interface IDocumentListener extends java.util.EventListener {
 
 	/**
 	 * Called when an attribute is changed in one of the document's elements.
 	 * 
-	 * @param e
+	 * @param event
 	 *            the document event.
 	 */
-	public void attributeChanged(DocumentEvent e);
+	void attributeChanged(DocumentEvent event);
 
 	/**
 	 * Called when a namespace delcaration is changed in one of the document's elements.
 	 * 
-	 * @param e
+	 * @param event
 	 *            the document event.
 	 */
-	public void namespaceChanged(DocumentEvent e);
+	void namespaceChanged(DocumentEvent event);
 
 	/**
 	 * Called before content is deleted from a document.
 	 * 
-	 * @param e
+	 * @param event
 	 *            the document event
 	 */
-	public void beforeContentDeleted(DocumentEvent e);
+	void beforeContentDeleted(DocumentEvent event);
 
 	/**
 	 * Called before content is inserted into a document.
 	 * 
-	 * @param e
+	 * @param event
 	 *            the document event
 	 */
-	public void beforeContentInserted(DocumentEvent e);
+	void beforeContentInserted(DocumentEvent event);
 
 	/**
 	 * Called when content is deleted from a document.
 	 * 
-	 * @param e
+	 * @param event
 	 *            the document event
 	 */
-	public void contentDeleted(DocumentEvent e);
+	void contentDeleted(DocumentEvent event);
 
 	/**
 	 * Called when content is inserted into a document.
 	 * 
-	 * @param e
+	 * @param event
 	 *            the document event
 	 */
-	public void contentInserted(DocumentEvent e);
+	void contentInserted(DocumentEvent event);
 
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IElement.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IElement.java
new file mode 100644
index 0000000..da00c76
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IElement.java
@@ -0,0 +1,223 @@
+/*******************************************************************************

+ * Copyright (c) 2013 Florian Thienel and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ * 		Florian Thienel - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.vex.core.dom;

+

+import java.util.Collection;

+

+import org.eclipse.core.runtime.QualifiedName;

+

+/**

+ * A representation of an XML element in the DOM. Elements have attributes, namespace declarations and children, as well

+ * as a start and an end tag. The textual content of an element is represented by its child text nodes.

+ * 

+ * @author Florian Thienel

+ */

+public interface IElement extends IParent {

+

+	/**

+	 * This element is the same kind as the given node if the node is also an element and both have the same qualified

+	 * name.

+	 * 

+	 * @see INode#isKindOf(INode)

+	 * @return true if this element and the given node are of the same kind

+	 */

+	boolean isKindOf(INode node);

+

+	/**

+	 * Set the base URI of this element. The xml:base attribute re-defines the base URI for a part of an XML document,

+	 * according to the XML Base Recommendation.

+	 * 

+	 * @param baseURI

+	 *            the base URI of this element

+	 * @see http://www.w3.org/TR/xmlbase/

+	 */

+	void setBaseURI(String baseURI);

+

+	/**

+	 * @return the qualified name of this element

+	 */

+	QualifiedName getQualifiedName();

+

+	/**

+	 * @return the local name of this element

+	 */

+	String getLocalName();

+

+	/**

+	 * @return the declared namespace prefix for this element

+	 */

+	String getPrefix();

+

+	/**

+	 * @return the declared namespace prefix and the local name of this element separated by a colon (e.g.

+	 *         "prefix:localName")

+	 */

+	String getPrefixedName();

+

+	/**

+	 * Qualify the given local name with the namespace qualifier of this element.

+	 * 

+	 * @param localName

+	 *            the local name to be qualified

+	 * @return the qualified variant of the given local name

+	 */

+	QualifiedName qualify(String localName);

+

+	/**

+	 * @return the attribute with the given local name, or null if the attribute is not set

+	 */

+	IAttribute getAttribute(String localName);

+

+	/**

+	 * @return the attribute with the given qualified name, or null if the attribute is not set

+	 */

+	IAttribute getAttribute(QualifiedName name);

+

+	/**

+	 * @return the attribute with the given local name, or null if the attribute is not set

+	 */

+	String getAttributeValue(String localName);

+

+	/**

+	 * @return the value of the attribute with the given qualified name, or null if the attribute is not set

+	 */

+	String getAttributeValue(QualifiedName name);

+

+	/**

+	 * Remove the attribute with the given local name.

+	 * 

+	 * @param localName

+	 *            the local name of the attribute to be removed

+	 * @throws DocumentValidationException

+	 *             if the removal of the attribute would make the document invalid

+	 */

+	void removeAttribute(String localName) throws DocumentValidationException;

+

+	/**

+	 * Remove the attribute with the given qualified name.

+	 * 

+	 * @param name

+	 *            the qualified name of the attribute to be removed

+	 * @throws DocumentValidationException

+	 *             if the removal of the attribute would make the document invalid

+	 */

+	void removeAttribute(QualifiedName name) throws DocumentValidationException;

+

+	/**

+	 * Set the attribute with the given local name to the given value.

+	 * 

+	 * @param localName

+	 *            the local name of the attribute

+	 * @param value

+	 *            the new attribute value

+	 * @throws DocumentValidationException

+	 *             if the new attribute value would make the document invalid

+	 */

+	void setAttribute(String localName, String value) throws DocumentValidationException;

+

+	/**

+	 * Set the attribute with the given qualified name to the given value.

+	 * 

+	 * @param name

+	 *            the qualified name of the attribute

+	 * @param value

+	 *            the new attribute value

+	 * @throws DocumentValidationException

+	 *             if the new attribute value would make the document invalid

+	 */

+	void setAttribute(QualifiedName name, String value) throws DocumentValidationException;

+

+	/**

+	 * @return all attributes currently set on this element

+	 */

+	Collection<IAttribute> getAttributes();

+

+	/**

+	 * @return the qualified names of all attributes currently set on this element

+	 */

+	Collection<QualifiedName> getAttributeNames();

+

+	/**

+	 * @return the parent element of this element

+	 */

+	IElement getParentElement();

+

+	/**

+	 * @return the child elements of this element in form of an axis

+	 * @see IAxis

+	 */

+	IAxis<? extends IElement> childElements();

+

+	/**

+	 * @return the namespace URI of the given namespace prefix, or null if no namespace with the given prefix is

+	 *         declared

+	 */

+	String getNamespaceURI(String namespacePrefix);

+

+	/**

+	 * @return the default namespace URI or null, if no default namespace is declared

+	 */

+	String getDefaultNamespaceURI();

+

+	/**

+	 * @return the URI of the default namespace declared on this element, or null if no default namespace is declared on

+	 *         this element

+	 */

+	String getDeclaredDefaultNamespaceURI();

+

+	/**

+	 * @return the declared namespace prefix for the given namespace URI, or null if the namespace with the given URI is

+	 *         not declared in the document

+	 */

+	String getNamespacePrefix(String namespaceURI);

+

+	/**

+	 * @return the prefixes of the namespaces that are declared on this element

+	 */

+	Collection<String> getDeclaredNamespacePrefixes();

+

+	/**

+	 * @return the prefixes of the declared namespaces

+	 */

+	Collection<String> getNamespacePrefixes();

+

+	/**

+	 * Declare a namespace with the given prefix and URI on this element.

+	 * 

+	 * @param namespacePrefix

+	 *            the prefix of the namespace to be declared

+	 * @param namespaceURI

+	 *            the URI of the namespace to be declared

+	 */

+	void declareNamespace(String namespacePrefix, String namespaceURI);

+

+	/**

+	 * Remove the namespace declaration with the given prefix from this element.

+	 * 

+	 * @param namespacePrefix

+	 *            the prefix of the namespace to be removed

+	 */

+	void removeNamespace(String namespacePrefix);

+

+	/**

+	 * Declare the default namespace with the given URI on this element.

+	 * 

+	 * @param namespaceURI

+	 *            the URI of the default namespace

+	 */

+	void declareDefaultNamespace(String namespaceURI);

+

+	/**

+	 * Remove the declaration of the default namespace from this element.

+	 */

+	void removeDefaultNamespace();

+

+}
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/INode.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/INode.java
new file mode 100644
index 0000000..26ac014
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/INode.java
@@ -0,0 +1,146 @@
+/*******************************************************************************

+ * Copyright (c) 2013 Florian Thienel and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ * 		Florian Thienel - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.vex.core.dom;

+

+/**

+ * A representation of one node in the XML structure. A node is associated to a range of the textual content.

+ * <p>

+ * This is the base for all representatives of the XML structure in the document object model (DOM).

+ * 

+ * @author Florian Thienel

+ */

+public interface INode {

+

+	/**

+	 * @see IParent

+	 * @return the parent of this node, maybe null if this node has no parent

+	 */

+	IParent getParent();

+

+	/**

+	 * The ancestors axis contains all subsequent parents of this node.

+	 * 

+	 * @return the ancestors axis of this node

+	 * @see IAxis

+	 */

+	IAxis<IParent> ancestors();

+

+	/**

+	 * @return if this node is associated to content

+	 */

+	boolean isAssociated();

+

+	/**

+	 * @return the content to which this node is associated or null if this node is not associated to any content yet

+	 */

+	IContent getContent();

+

+	/**

+	 * The start offset of this node, which eventually also includes the position of a tag marker.

+	 * 

+	 * @return the start offset of this node within the textual content

+	 */

+	int getStartOffset();

+

+	/**

+	 * The end offset of this node, which eventually also includes the position of a tag marker.

+	 * 

+	 * @return the end offset of this node within the textual content

+	 */

+	int getEndOffset();

+

+	/**

+	 * @return the range in the content to which this node is associated, eventually including tag markers

+	 */

+	ContentRange getRange();

+

+	/**

+	 * Indicate whether this node has no content beside its tag markers. If this node is not associated with textual

+	 * content, this method returns false.

+	 * 

+	 * @return true if this node has no content beside its tag markers

+	 */

+	boolean isEmpty();

+

+	/**

+	 * Indicate whether the given offset is within the boundaries of this node. If this node is not associated with

+	 * textual content, this method returns false.

+	 * 

+	 * @param offset

+	 *            the offset

+	 * @return true if the given offset is withing [startOffset; endOffset], or false if not associated

+	 */

+	boolean containsOffset(int offset);

+

+	/**

+	 * Indicate whether this node is fully within the given range. If this node is not associated with textual content,

+	 * this method returns false.

+	 * 

+	 * @param range

+	 *            the range

+	 * @return true if this node is fully within the given range

+	 */

+	boolean isInRange(ContentRange range);

+

+	/**

+	 * @return the textual content of this node, not including any tag markers

+	 */

+	String getText();

+

+	/**

+	 * The textual content in the given range, not including any element markers.

+	 * 

+	 * @param range

+	 *            the range of the textual content

+	 * @return the textual content in the given range

+	 */

+	String getText(ContentRange range);

+

+	/**

+	 * @return the document to which this node belongs, or null if this node does not belong to any document

+	 */

+	IDocument getDocument();

+

+	/**

+	 * Indicate whether this and the given node are of the same kind (e.g. elements with the same qualified name).

+	 * 

+	 * @return true if this and the given node are of the same kind

+	 */

+	boolean isKindOf(INode node);

+

+	/**

+	 * The xml:base attribute re-defines the base URI for a part of an XML document, according to the XML Base

+	 * Recommendation.

+	 * 

+	 * @see http://www.w3.org/TR/xmlbase/

+	 * @return the base URI of this node

+	 */

+	String getBaseURI();

+

+	/**

+	 * Accept the given visitor.

+	 * 

+	 * @see INodeVisitor

+	 * @param visitor

+	 *            the visitor

+	 */

+	void accept(INodeVisitor visitor);

+

+	/**

+	 * Accept the given visitor.

+	 * 

+	 * @see INodeVisitorWithResult

+	 * @param visitor

+	 *            the visitor

+	 */

+	<T> T accept(INodeVisitorWithResult<T> visitor);

+

+}
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/INodeVisitor.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/INodeVisitor.java
similarity index 79%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/INodeVisitor.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/INodeVisitor.java
index 7c73aed..3f46152 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/INodeVisitor.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/INodeVisitor.java
@@ -8,7 +8,7 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.dom;

+package org.eclipse.vex.core.dom;

 

 /**

  * An incarantion of the <a href="http://en.wikipedia.org/wiki/Visitor_pattern">Visitor pattern</a> which handles the

@@ -18,14 +18,14 @@
  */

 public interface INodeVisitor {

 

-	void visit(Document document);

+	void visit(IDocument document);

 

-	void visit(DocumentFragment fragment);

+	void visit(IDocumentFragment fragment);

 

-	void visit(Element element);

+	void visit(IElement element);

 

-	void visit(Text text);

+	void visit(IText text);

 

-	void visit(Comment comment);

+	void visit(IComment comment);

 

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/INodeVisitorWithResult.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/INodeVisitorWithResult.java
similarity index 81%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/INodeVisitorWithResult.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/INodeVisitorWithResult.java
index d49383a..7b7b4b1 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/INodeVisitorWithResult.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/INodeVisitorWithResult.java
@@ -8,7 +8,7 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.dom;

+package org.eclipse.vex.core.dom;

 

 /**

  * An incarantion of the <a href="http://en.wikipedia.org/wiki/Visitor_pattern">Visitor pattern</a> which handles the

@@ -18,14 +18,14 @@
  */

 public interface INodeVisitorWithResult<T> {

 

-	T visit(Document document);

+	T visit(IDocument document);

 

-	T visit(DocumentFragment fragment);

+	T visit(IDocumentFragment fragment);

 

-	T visit(Element element);

+	T visit(IElement element);

 

-	T visit(Text text);

+	T visit(IText text);

 

-	T visit(Comment comment);

+	T visit(IComment comment);

 

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IParent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IParent.java
new file mode 100644
index 0000000..38285f3
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IParent.java
@@ -0,0 +1,44 @@
+/*******************************************************************************

+ * Copyright (c) 2013 Florian Thienel and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ * 		Florian Thienel - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.vex.core.dom;

+

+/**

+ * A parent node is a node which can contain other nodes as children. This interface defines the tree-like structure of

+ * the DOM. It handles the merging of the child nodes and the textual content of one node within the structure of the

+ * document.

+ * 

+ * @author Florian Thienel

+ */

+public interface IParent extends INode {

+

+	/**

+	 * Indicates whether this parent node has child nodes, including text nodes.

+	 * 

+	 * @return true if this parent node has any child nodes

+	 */

+	public abstract boolean hasChildren();

+

+	/**

+	 * @return the children axis of this parent.

+	 * @see IAxis

+	 */

+	public abstract IAxis<INode> children();

+

+	/**

+	 * Returns the child node which contains the given offset, or this node, if no child contains the offset.

+	 * 

+	 * @param offset

+	 *            the offset

+	 * @return the node at the given offset

+	 */

+	public abstract INode getChildAt(int offset);

+

+}
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Position.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IPosition.java
similarity index 91%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Position.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IPosition.java
index 4eb5ca6..823f034 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Position.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IPosition.java
@@ -9,7 +9,7 @@
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - NULL object
  *******************************************************************************/
-package org.eclipse.vex.core.internal.dom;
+package org.eclipse.vex.core.dom;
 
 /**
  * Represents a logical location in a document. As the document is modified, existing <code>Position</code> objects are
@@ -18,9 +18,9 @@
  * Positions can be invalid if they were removed from their associated Content instance. Invalid positions do not get
  * updated on content modifications. They must not be used for anything anymore.
  */
-public interface Position {
+public interface IPosition {
 
-	static Position NULL = new Position() {
+	static IPosition NULL = new IPosition() {
 		public int getOffset() {
 			return -1;
 		}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/IFilter.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IText.java
similarity index 62%
copy from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/IFilter.java
copy to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IText.java
index ac816da..b263eb7 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/IFilter.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IText.java
@@ -8,19 +8,14 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.core;

+package org.eclipse.vex.core.dom;

 

 /**

- * A simple filtering facility.

+ * A representation of textual content of an XML document within the DOM. Text objects are not used in the internal

+ * document structure; they are dynamically created as needed by the <code>IElement.children()</code> axis.

  * 

- * @author Florian Thienel

+ * @see IElement#children()

  */

-public interface IFilter<T> {

+public interface IText extends INode {

 

-	/**

-	 * @param t

-	 *            the object to evaluate

-	 * @return true if the given object matches this filter

-	 */

-	boolean matches(T t);

-}

+}
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Validator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IValidator.java
similarity index 76%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Validator.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IValidator.java
index 6e4842f..b241929 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Validator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/dom/IValidator.java
@@ -10,7 +10,7 @@
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
  *     Florian Thienel - support for XML namespaces (bug 253753)
  *******************************************************************************/
-package org.eclipse.vex.core.internal.dom;
+package org.eclipse.vex.core.dom;
 
 import java.util.List;
 import java.util.Set;
@@ -19,18 +19,14 @@
 import org.eclipse.vex.core.internal.validator.AttributeDefinition;
 
 /**
- * Represents an object that can validate the structure of a document. Validators must be serializable.
- * 
- * @model
+ * Represents an object that can validate the structure of a document.
  */
-public interface Validator {
+public interface IValidator {
 
 	/**
 	 * QualifiedName indicating that character data is allowed at the given point in the document.
-	 * 
-	 * @model
 	 */
-	public static final QualifiedName PCDATA = new QualifiedName(null, "#PCDATA");
+	final QualifiedName PCDATA = new QualifiedName(null, "#PCDATA");
 
 	/**
 	 * Returns the AttributeDefinition for a particular attribute.
@@ -41,23 +37,20 @@
 	 *            Name of the attribute.
 	 * @model
 	 */
-	public AttributeDefinition getAttributeDefinition(Attribute attribute);
+	AttributeDefinition getAttributeDefinition(IAttribute attribute);
 
 	/**
 	 * Returns the attribute definitions that apply to the given element.
 	 * 
 	 * @param element
 	 *            the element to check.
-	 * @model
 	 */
-	public List<AttributeDefinition> getAttributeDefinitions(Element element);
+	List<AttributeDefinition> getAttributeDefinitions(IElement element);
 
 	/**
 	 * Returns a set of QualifiedNames representing valid root elements for the given document type.
-	 * 
-	 * @model
 	 */
-	public Set<QualifiedName> getValidRootElements();
+	Set<QualifiedName> getValidRootElements();
 
 	/**
 	 * Returns a set of QualifiedNames representing items that are valid at point in the child nodes of a given element.
@@ -65,9 +58,8 @@
 	 * 
 	 * @param element
 	 *            the parent element.
-	 * @model
 	 */
-	public Set<QualifiedName> getValidItems(final Element element);
+	Set<QualifiedName> getValidItems(final IElement element);
 
 	/**
 	 * Returns true if the given sequence is valid for the given element. Accepts three sequences, which will be
@@ -79,9 +71,8 @@
 	 *            Array of element names and Validator.PCDATA.
 	 * @param partial
 	 *            If true, an valid but incomplete sequence is acceptable.
-	 * @model
 	 */
-	public boolean isValidSequence(QualifiedName element, List<QualifiedName> nodes, boolean partial);
+	boolean isValidSequence(QualifiedName element, List<QualifiedName> nodes, boolean partial);
 
 	/**
 	 * Returns true if the given sequence is valid for the given element. Accepts three sequences, which will be
@@ -97,10 +88,12 @@
 	 *            List of element names and Validator.PCDATA. May be null or empty.
 	 * @param partial
 	 *            If true, an valid but incomplete sequence is acceptable.
-	 * @model
 	 */
-	public boolean isValidSequence(QualifiedName element, List<QualifiedName> seq1, List<QualifiedName> seq2, List<QualifiedName> seq3, boolean partial);
+	boolean isValidSequence(QualifiedName element, List<QualifiedName> seq1, List<QualifiedName> seq2, List<QualifiedName> seq3, boolean partial);
 
-	public Set<String> getRequiredNamespaces();
+	/**
+	 * @return the namespaces which are used and hence required in the document type represented by this validator
+	 */
+	Set<String> getRequiredNamespaces();
 
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/AfterNIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/AfterNIterator.java
index 3e7d8d3..82ae090 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/AfterNIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/AfterNIterator.java
@@ -19,7 +19,7 @@
  */

 public class AfterNIterator<T> implements Iterator<T> {

 

-	private final Iterator<T> source;

+	private final Iterator<? extends T> source;

 

 	/**

 	 * @param source

@@ -27,7 +27,7 @@
 	 * @param n

 	 *            the number of the element to start with

 	 */

-	public AfterNIterator(final Iterator<T> source, final int n) {

+	public AfterNIterator(final Iterator<? extends T> source, final int n) {

 		this.source = source;

 		forward(source, n);

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FilterIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FilterIterator.java
index de3d612..909a9a1 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FilterIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FilterIterator.java
@@ -13,6 +13,8 @@
 import java.util.Iterator;

 import java.util.NoSuchElementException;

 

+import org.eclipse.vex.core.IFilter;

+

 /**

  * This iterator fiters the sequence of a given source iterator. It provides only the elements which match a given

  * filter.

@@ -22,7 +24,7 @@
  */

 public class FilterIterator<T> implements Iterator<T> {

 

-	private final Iterator<T> source;

+	private final Iterator<? extends T> source;

 	private final IFilter<T> filter;

 	private T current;

 

@@ -32,7 +34,7 @@
 	 * @param filter

 	 *            the filter to apply to the elements of the original sequence

 	 */

-	public FilterIterator(final Iterator<T> source, final IFilter<T> filter) {

+	public FilterIterator(final Iterator<? extends T> source, final IFilter<T> filter) {

 		this.source = source;

 		this.filter = filter;

 		current = null;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FirstNIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FirstNIterator.java
index 0a3cb80..a8af25c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FirstNIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/core/FirstNIterator.java
@@ -20,7 +20,7 @@
  */

 public class FirstNIterator<T> implements Iterator<T> {

 

-	private final Iterator<T> source;

+	private final Iterator<? extends T> source;

 	private final int n;

 	private int cursor;

 

@@ -30,7 +30,7 @@
 	 * @param n

 	 *            the number of elements to provide

 	 */

-	public FirstNIterator(final Iterator<T> source, final int n) {

+	public FirstNIterator(final Iterator<? extends T> source, final int n) {

 		this.source = source;

 		this.n = n;

 		cursor = 0;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BackgroundImageProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BackgroundImageProperty.java
index c88aaa2..3a89d9f 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BackgroundImageProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BackgroundImageProperty.java
@@ -14,10 +14,10 @@
 

 import org.eclipse.core.runtime.IStatus;

 import org.eclipse.core.runtime.Status;

+import org.eclipse.vex.core.dom.BaseNodeVisitorWithResult;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.dom.INode;

 import org.eclipse.vex.core.internal.VEXCorePlugin;

-import org.eclipse.vex.core.internal.dom.BaseNodeVisitorWithResult;

-import org.eclipse.vex.core.internal.dom.Element;

-import org.eclipse.vex.core.internal.dom.Node;

 import org.w3c.css.sac.LexicalUnit;

 

 /**

@@ -31,7 +31,7 @@
 		super(CSS.BACKGROUND_IMAGE);

 	}

 

-	public Object calculate(final LexicalUnit lexicalUnit, final Styles parentStyles, final Styles styles, final Node node) {

+	public Object calculate(final LexicalUnit lexicalUnit, final Styles parentStyles, final Styles styles, final INode node) {

 		if (lexicalUnit == null) {

 			return DEFAULT;

 		}

@@ -41,7 +41,7 @@
 		case LexicalUnit.SAC_ATTR:

 			return node.accept(new BaseNodeVisitorWithResult<Object>(DEFAULT) {

 				@Override

-				public Object visit(final Element element) {

+				public Object visit(final IElement element) {

 					final String attributeValue = element.getAttributeValue(lexicalUnit.getStringValue());

 					if (attributeValue != null) {

 						return attributeValue;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderSpacingProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderSpacingProperty.java
index 9b26a07..cc5436f 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderSpacingProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderSpacingProperty.java
@@ -10,8 +10,8 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.DisplayDevice;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -57,7 +57,7 @@
 		super(CSS.BORDER_SPACING);
 	}
 
-	public Object calculate(LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 
 		int horizontal = 0;
 		int vertical = 0;
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderStyleProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderStyleProperty.java
index 0276302..99c30e3 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderStyleProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderStyleProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -46,7 +46,7 @@
 		return false;
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isBorderStyle(lu)) {
 			return lu.getStringValue();
 		} else if (isInherit(lu) && parentStyles != null) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderWidthProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderWidthProperty.java
index c8e4558..c2c4185 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderWidthProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/BorderWidthProperty.java
@@ -10,8 +10,8 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.DisplayDevice;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -87,7 +87,7 @@
 		}
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		return Integer.valueOf(calculateInternal(lu, parentStyles, styles));
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ColorProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ColorProperty.java
index 91b86fb..e50d375 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ColorProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ColorProperty.java
@@ -13,8 +13,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.Color;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -64,7 +64,7 @@
 		super(name);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 
 		final boolean inherit = isInherit(lu) || getName().equals(CSS.COLOR);
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/DisplayProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/DisplayProperty.java
index e69498e..0a76d0c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/DisplayProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/DisplayProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -25,7 +25,7 @@
 		super(CSS.DISPLAY);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 
 		if (isDisplay(lu)) {
 			return lu.getStringValue();
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontFamilyProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontFamilyProperty.java
index 8ccf964..1c2d175 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontFamilyProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontFamilyProperty.java
@@ -15,7 +15,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -30,7 +30,7 @@
 		super(CSS.FONT_FAMILY);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isFontFamily(lu)) {
 			return getFontFamilies(lu);
 		} else {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontSizeProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontSizeProperty.java
index 2c5cbd0..95016ff 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontSizeProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontSizeProperty.java
@@ -10,8 +10,8 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.DisplayDevice;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -27,7 +27,7 @@
 		super(CSS.FONT_SIZE);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		return new Float(calculateInternal(lu, parentStyles, styles));
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontStyleProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontStyleProperty.java
index d5fb721..7929325 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontStyleProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontStyleProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -25,7 +25,7 @@
 		super(CSS.FONT_STYLE);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isFontStyle(lu)) {
 			return lu.getStringValue();
 		} else {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontVariantProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontVariantProperty.java
index 58e2c78..7142326 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontVariantProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontVariantProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -25,7 +25,7 @@
 		super(CSS.FONT_VARIANT);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isFontVariant(lu)) {
 			return lu.getStringValue();
 		} else {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontWeightProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontWeightProperty.java
index cd4f17b..7568592 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontWeightProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/FontWeightProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -28,7 +28,7 @@
 		super(CSS.FONT_WEIGHT);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		return Integer.valueOf(calculateInternal(lu, parentStyles, styles));
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IProperty.java
index 5849ce0..069e4a3 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -40,6 +40,6 @@
 	 * @param node
 	 *            The current node for which this property is calculated. May be null.
 	 */
-	public Object calculate(LexicalUnit lu, Styles parentStyles, Styles styles, Node node);
+	public Object calculate(LexicalUnit lu, Styles parentStyles, Styles styles, INode node);
 
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LengthProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LengthProperty.java
index e910769..f4ba61c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LengthProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LengthProperty.java
@@ -15,11 +15,11 @@
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.vex.core.dom.BaseNodeVisitorWithResult;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.VEXCorePlugin;
 import org.eclipse.vex.core.internal.core.DisplayDevice;
-import org.eclipse.vex.core.internal.dom.BaseNodeVisitorWithResult;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.w3c.css.sac.CSSException;
 import org.w3c.css.sac.InputSource;
 import org.w3c.css.sac.LexicalUnit;
@@ -37,12 +37,12 @@
 		this.axis = axis;
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		final int ppi = getPpi();
 		if (isAttr(lu)) {
 			return node.accept(new BaseNodeVisitorWithResult<Object>(RelativeLength.createAbsolute(0)) {
 				@Override
-				public Object visit(final Element element) {
+				public Object visit(final IElement element) {
 					return calculate(parseAttribute(lu, element), parentStyles, styles, element);
 				}
 			});
@@ -64,7 +64,7 @@
 		return lexicalUnit != null && lexicalUnit.getLexicalUnitType() == LexicalUnit.SAC_ATTR;
 	}
 
-	private static LexicalUnit parseAttribute(final LexicalUnit lexicalUnit, final Element element) {
+	private static LexicalUnit parseAttribute(final LexicalUnit lexicalUnit, final IElement element) {
 		final String attributeName = lexicalUnit.getStringValue();
 		final String attributeValue = element.getAttributeValue(attributeName);
 		if (attributeValue == null) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LineHeightProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LineHeightProperty.java
index 37514cf..0c594ae 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LineHeightProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/LineHeightProperty.java
@@ -10,8 +10,8 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.DisplayDevice;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -32,7 +32,7 @@
 	 * Calculates the value of the property given a LexicalUnit. Returns a RelativeLength that is relative to the
 	 * current font size.
 	 */
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 
 		final int ppi = DisplayDevice.getCurrent().getVerticalPPI();
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ListStyleTypeProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ListStyleTypeProperty.java
index 767fd36..4396ac8 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ListStyleTypeProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ListStyleTypeProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -22,7 +22,7 @@
 		super(CSS.LIST_STYLE_TYPE);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isListStyleType(lu)) {
 			return lu.getStringValue();
 		} else {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PseudoElement.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PseudoElement.java
index 7dc0b72..78f001b 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PseudoElement.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/PseudoElement.java
@@ -10,10 +10,13 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.dom.Element;
 
 /**
  * Represents a :before or :after pseudo-element.
+ * 
+ * XXX REMOVE THIS HACK!!!
  */
 public class PseudoElement extends Element {
 
@@ -28,9 +31,9 @@
 	 * @param name
 	 *            Name of this pseudo-element, e.g. PseudoElement.BEFORE.
 	 */
-	public PseudoElement(final Element parent, final String name) {
+	public PseudoElement(final IElement parent, final String name) {
 		super(name);
-		setParent(parent);
+		setParent((Element) parent);
 	}
 
 	/**
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Rule.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Rule.java
index 6afdd08..6e02007 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Rule.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Rule.java
@@ -19,12 +19,12 @@
 import java.util.List;
 import java.util.StringTokenizer;
 
-import org.eclipse.vex.core.internal.dom.BaseNodeVisitorWithResult;
-import org.eclipse.vex.core.internal.dom.Comment;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Parent;
+import org.eclipse.vex.core.dom.BaseNodeVisitorWithResult;
+import org.eclipse.vex.core.dom.IComment;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IParent;
 import org.w3c.css.sac.AttributeCondition;
 import org.w3c.css.sac.CombinatorCondition;
 import org.w3c.css.sac.Condition;
@@ -101,7 +101,7 @@
 	 * @param node
 	 *            Node to check.
 	 */
-	public boolean matches(final Node node) {
+	public boolean matches(final INode node) {
 		return matches(selector, node);
 	}
 
@@ -110,7 +110,7 @@
 	/**
 	 * Returns true if the given element matches the given selector.
 	 */
-	private static boolean matches(final Selector selector, final Node node) {
+	private static boolean matches(final Selector selector, final INode node) {
 
 		if (node == null) {
 			// This can happen when, e.g., with the rule "foo > *".
@@ -133,7 +133,7 @@
 				if (node instanceof PseudoElement) {
 					final AttributeCondition ac = (AttributeCondition) cs.getCondition();
 					return ac.getValue().equals(getLocalNameOfElement(node)) && matches(cs.getSimpleSelector(), node.getParent());
-				} else if (node instanceof Comment) {
+				} else if (node instanceof IComment) {
 					final AttributeCondition ac = (AttributeCondition) cs.getCondition();
 					return COMMENT_RULE_NAME.equals(ac.getValue()) && matches(cs.getSimpleSelector(), node.getParent());
 				} else {
@@ -150,7 +150,7 @@
 			return true;
 
 		case Selector.SAC_ROOT_NODE_SELECTOR:
-			return node.getParent() instanceof Document;
+			return node.getParent() instanceof IDocument;
 
 		case Selector.SAC_NEGATIVE_SELECTOR:
 			break; // not yet supported
@@ -192,7 +192,7 @@
 
 		case Selector.SAC_CHILD_SELECTOR:
 			final DescendantSelector ds2 = (DescendantSelector) selector;
-			final Parent parent = node.getParent();
+			final IParent parent = node.getParent();
 			return matches(ds2.getSimpleSelector(), node) && matches(ds2.getAncestorSelector(), parent);
 
 		case Selector.SAC_DIRECT_ADJACENT_SELECTOR:
@@ -202,9 +202,9 @@
 			if (node != null && node.getParent() != null && matches(ss.getSiblingSelector(), node)) {
 
 				// find next sibling
-				final Iterator<Node> i = node.getParent().children().iterator();
-				Node e = null;
-				Node f = null;
+				final Iterator<INode> i = node.getParent().children().iterator();
+				INode e = null;
+				INode f = null;
 				while (i.hasNext() && e != node) {
 					f = e;
 					e = i.next();
@@ -223,10 +223,10 @@
 		return false;
 	}
 
-	private static String getLocalNameOfElement(final Node node) {
+	private static String getLocalNameOfElement(final INode node) {
 		return node.accept(new BaseNodeVisitorWithResult<String>("") {
 			@Override
-			public String visit(final Element element) {
+			public String visit(final IElement element) {
 				return element.getLocalName();
 			}
 		});
@@ -235,8 +235,8 @@
 	/**
 	 * Returns true if some ancestor of the given element matches the given selector.
 	 */
-	private static boolean matchesAncestor(final Selector selector, final Node node) {
-		for (final Node ancestor : node.ancestors()) {
+	private static boolean matchesAncestor(final Selector selector, final INode node) {
+		for (final INode ancestor : node.ancestors()) {
 			if (matches(selector, ancestor)) {
 				return true;
 			}
@@ -244,7 +244,7 @@
 		return false;
 	}
 
-	private static boolean matchesCondition(final Condition condition, final Node node) {
+	private static boolean matchesCondition(final Condition condition, final INode node) {
 
 		AttributeCondition attributeCondition;
 		String attributeName;
@@ -297,10 +297,10 @@
 		return false;
 	}
 
-	private static String getAttributeValue(final Node node, final String localName) {
+	private static String getAttributeValue(final INode node, final String localName) {
 		return node.accept(new BaseNodeVisitorWithResult<String>() {
 			@Override
-			public String visit(final Element element) {
+			public String visit(final IElement element) {
 				return element.getAttributeValue(localName);
 			}
 		});
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java
index 2f9dda4..c154c98 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java
@@ -27,10 +27,10 @@
 import java.util.Map;
 import java.util.WeakHashMap;
 
+import org.eclipse.vex.core.dom.BaseNodeVisitor;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.FontSpec;
-import org.eclipse.vex.core.internal.dom.BaseNodeVisitor;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -87,7 +87,7 @@
 	 * 
 	 * This must be transient to prevent it from being serialized, as WeakHashMaps are not serializable.
 	 */
-	private transient Map<Node, WeakReference<Styles>> styleMap;
+	private transient Map<INode, WeakReference<Styles>> styleMap;
 
 	/**
 	 * Class constructor.
@@ -105,7 +105,7 @@
 	 * @param element
 	 *            IVEXElement for which styles are to be flushed.
 	 */
-	public void flushStyles(final Element element) {
+	public void flushStyles(final IElement element) {
 		getStyleMap().remove(element);
 	}
 
@@ -116,7 +116,7 @@
 	 * @param element
 	 *            Parent element of the pseudo-element.
 	 */
-	public Element getAfterElement(final Element element) {
+	public PseudoElement getAfterElement(final IElement element) {
 		final PseudoElement pe = new PseudoElement(element, PseudoElement.AFTER);
 		final Styles styles = getStyles(pe);
 		if (styles == null) {
@@ -133,7 +133,7 @@
 	 * @param element
 	 *            Parent element of the pseudo-element.
 	 */
-	public Element getBeforeElement(final Element element) {
+	public PseudoElement getBeforeElement(final IElement element) {
 		final PseudoElement pe = new PseudoElement(element, PseudoElement.BEFORE);
 		final Styles styles = getStyles(pe);
 		if (styles == null) {
@@ -149,7 +149,7 @@
 	 * @param node
 	 *            Node for which to calculate the styles.
 	 */
-	public Styles getStyles(final Node node) {
+	public Styles getStyles(final INode node) {
 
 		Styles styles;
 		final WeakReference<Styles> ref = getStyleMap().get(node);
@@ -180,7 +180,7 @@
 		return styles;
 	}
 
-	private Styles calculateStyles(final Node node) {
+	private Styles calculateStyles(final INode node) {
 
 		final Styles styles = new Styles();
 		Styles parentStyles = null;
@@ -212,7 +212,7 @@
 					final LexicalUnit currentLexicalUnit = lexicalUnit;
 					node.accept(new BaseNodeVisitor() {
 						@Override
-						public void visit(final Element element) {
+						public void visit(final IElement element) {
 							final String attributeValue = element.getParentElement().getAttributeValue(currentLexicalUnit.getStringValue());
 							if (attributeValue != null) {
 								content.add(attributeValue);
@@ -268,7 +268,7 @@
 	/**
 	 * Returns all the declarations that apply to the given element.
 	 */
-	private Map<String, LexicalUnit> getApplicableDeclarations(final Node node) {
+	private Map<String, LexicalUnit> getApplicableDeclarations(final INode node) {
 		final List<PropertyDecl> rawDeclarationsForElement = findAllDeclarationsFor(node);
 
 		// Sort in cascade order. We can then just stuff them into a
@@ -289,7 +289,7 @@
 		return values;
 	}
 
-	private List<PropertyDecl> findAllDeclarationsFor(final Node node) {
+	private List<PropertyDecl> findAllDeclarationsFor(final INode node) {
 		final List<PropertyDecl> rawDeclarations = new ArrayList<PropertyDecl>();
 		for (final Rule rule : rules) {
 			if (rule.matches(node)) {
@@ -302,9 +302,9 @@
 		return rawDeclarations;
 	}
 
-	private Map<Node, WeakReference<Styles>> getStyleMap() {
+	private Map<INode, WeakReference<Styles>> getStyleMap() {
 		if (styleMap == null) {
-			styleMap = new WeakHashMap<Node, WeakReference<Styles>>();
+			styleMap = new WeakHashMap<INode, WeakReference<Styles>>();
 		}
 		return styleMap;
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextAlignProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextAlignProperty.java
index 2c65e84..db7c136 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextAlignProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextAlignProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -25,7 +25,7 @@
 		super(CSS.TEXT_ALIGN);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (TextAlignProperty.isTextAlign(lu)) {
 			return lu.getStringValue();
 		} else {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextDecorationProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextDecorationProperty.java
index b0327bf..aa4a943 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextDecorationProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/TextDecorationProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -25,7 +25,7 @@
 		super(CSS.TEXT_DECORATION);
 	}
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isTextDecoration(lu)) {
 			return lu.getStringValue();
 		} else {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/WhiteSpaceProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/WhiteSpaceProperty.java
index ab27df6..ee04366 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/WhiteSpaceProperty.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/WhiteSpaceProperty.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.css;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.w3c.css.sac.LexicalUnit;
 
 /**
@@ -29,7 +29,7 @@
      *
      */
 
-	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final Node node) {
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
 		if (isWhiteSpace(lu)) {
 			return lu.getStringValue();
 		} else {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/AncestorsIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/AncestorsIterator.java
index 09d16da..c62b724 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/AncestorsIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/AncestorsIterator.java
@@ -13,14 +13,17 @@
 import java.util.Iterator;

 import java.util.NoSuchElementException;

 

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.IParent;

+

 /**

  * @author Florian Thienel

  */

-public class AncestorsIterator implements Iterator<Node> {

+public class AncestorsIterator implements Iterator<IParent> {

 

-	private Node current;

+	private INode current;

 

-	public AncestorsIterator(final Node startNode) {

+	public AncestorsIterator(final INode startNode) {

 		current = startNode;

 	}

 

@@ -28,12 +31,12 @@
 		return current.getParent() != null;

 	}

 

-	public Node next() {

+	public IParent next() {

 		if (!hasNext()) {

 			throw new NoSuchElementException();

 		}

 		current = current.getParent();

-		return current;

+		return (IParent) current;

 	}

 

 	public void remove() {

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Attribute.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Attribute.java
index 4c26a5b..5366054 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Attribute.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Attribute.java
@@ -11,6 +11,8 @@
 package org.eclipse.vex.core.internal.dom;

 

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.IAttribute;

+import org.eclipse.vex.core.dom.IElement;

 

 /**

  * An immutable representation of an attribute within the start tag of an element. An attribute consists of a qualified

@@ -18,46 +20,25 @@
  * 

  * @author Florian Thienel

  */

-public class Attribute implements Comparable<Attribute> {

+public class Attribute implements IAttribute {

 

-	private final Element parent;

+	private final IElement parent;

 

 	private final QualifiedName name;

 

 	private final String value;

 

-	/**

-	 * Create an attribute within the namespace of the parent element, i.e. only the local name without a qualifier is

-	 * given.

-	 * 

-	 * @param parent

-	 *            the element containing the attribute

-	 * @param localName

-	 *            the local name of the attribute

-	 * @param value

-	 *            the value of the attribute

-	 */

-	public Attribute(final Element parent, final String localName, final String value) {

+	public Attribute(final IElement parent, final String localName, final String value) {

 		this(parent, new QualifiedName(null, localName), value);

 	}

 

-	/**

-	 * Create an attribute within an arbitrary namespace.

-	 * 

-	 * @param parent

-	 *            the element containing the attribute

-	 * @param name

-	 *            the qualified name of the attribute

-	 * @param value

-	 *            the value of the attribute

-	 */

-	public Attribute(final Element parent, final QualifiedName name, final String value) {

+	public Attribute(final IElement parent, final QualifiedName name, final String value) {

 		this.parent = parent;

 		this.name = name;

 		this.value = value;

 	}

 

-	public Element getParent() {

+	public IElement getParent() {

 		return parent;

 	}

 

@@ -73,10 +54,6 @@
 		return name;

 	}

 

-	/**

-	 * @return prefix:localName, or localName if prefix is null or this attribute is in the same namespace as the parent

-	 *         element.

-	 */

 	public String getPrefixedName() {

 		final String attributeQualifier = name.getQualifier();

 		if (parent == null || attributeQualifier == null) {

@@ -90,14 +67,7 @@
 		return (prefix == null ? "" : prefix + ":") + getLocalName();

 	}

 

-	/**

-	 * Compares two attributes by their qualified name.

-	 * 

-	 * @param otherAttribute

-	 *            the other attribute

-	 * @see Comparable

-	 */

-	public int compareTo(final Attribute otherAttribute) {

-		return name.toString().compareTo(otherAttribute.name.toString());

+	public int compareTo(final IAttribute otherAttribute) {

+		return name.toString().compareTo(otherAttribute.getQualifiedName().toString());

 	}

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Axis.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Axis.java
index 64eb2f3..8749d12 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Axis.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Axis.java
@@ -16,42 +16,23 @@
 import java.util.NoSuchElementException;

 

 import org.eclipse.core.runtime.Assert;

+import org.eclipse.vex.core.IFilter;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IAxis;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.INodeVisitor;

 import org.eclipse.vex.core.internal.core.AfterNIterator;

 import org.eclipse.vex.core.internal.core.FilterIterator;

 import org.eclipse.vex.core.internal.core.FirstNIterator;

-import org.eclipse.vex.core.internal.core.IFilter;

 

 /**

- * An Axis represents an iterable sequence of nodes. It is the main concept to navigate in the DOM, inspired by the

- * XPath axes. Besides implementing the Iterable interface, Axis provides a fluent interface to limit the sequence by

- * several criteria:

- * <ul>

- * <li>only nodes within a range in the content</li>

- * <li>omit text nodes</li>

- * <li>only nodes within a range of indices</li>

- * <li>only nodes which match a given chain of filters</li>

- * </ul>

- * 

- * Example:

- * 

- * <pre>

- * Iterator&lt;Node&gt; elementsInRange = parent.children().in(new ContentRange(1, 24)).matching(new IFilter&lt;Node&gt;() {

- * 	public boolean matches(Node node) {

- * 		return node instanceof Element;

- * 	}

- * }).iterator();

- * </pre>

- * 

- * The Iterable interface makes it very convenient to use the axis in a foreach loop.

- * 

  * @author Florian Thienel

- * @see <a href="http://www.w3.org/TR/xpath/#axes">http://www.w3.org/TR/xpath/#axes</a>

  */

-public abstract class Axis implements Iterable<Node> {

+public abstract class Axis<T extends INode> implements IAxis<T> {

 

 	private static final int UNDEFINED = -1;

 

-	private final Node sourceNode;

+	private final INode sourceNode;

 

 	private ContentRange contentRange = ContentRange.ALL;

 	private boolean includeText = true;

@@ -59,196 +40,103 @@
 	private int endIndex = UNDEFINED;

 	private final List<IteratorFactory> chain = new ArrayList<IteratorFactory>();

 

-	/**

-	 * @param sourceNode

-	 *            the source node of this axis

-	 */

-	public Axis(final Node sourceNode) {

+	public Axis(final INode sourceNode) {

 		this.sourceNode = sourceNode;

 	}

 

-	/**

-	 * @return the source node of this axis

-	 */

-	public Node getSourceNode() {

+	public INode getSourceNode() {

 		return sourceNode;

 	}

 

-	/**

-	 * Creates the root iterator which provides the original sequence of nodes of this axis. The root iterator must take

-	 * care of the content range and the inclusion of Text nodes. The other criteria (index range, filters) are applied

-	 * to the sequence by this axis.

-	 * 

-	 * @param contentRange

-	 *            the defined content range, by default the range of the source node

-	 * @param includeText

-	 *            true if Text nodes should be included in the original sequence

-	 */

-	protected abstract Iterator<Node> createRootIterator(final ContentRange contentRange, final boolean includeText);

-

-	public Iterator<Node> iterator() {

-		Iterator<Node> result = rootIterator();

+	@SuppressWarnings("unchecked")

+	public Iterator<T> iterator() {

+		Iterator<? extends T> result = rootIterator();

 

 		if (startIndex != UNDEFINED && endIndex != UNDEFINED) {

-			result = new AfterNIterator<Node>(result, startIndex);

-			result = new FirstNIterator<Node>(result, endIndex - startIndex + 1);

+			result = new AfterNIterator<T>(result, startIndex);

+			result = new FirstNIterator<T>(result, endIndex - startIndex + 1);

 		} else if (startIndex != UNDEFINED) {

-			result = new AfterNIterator<Node>(result, startIndex);

+			result = new AfterNIterator<T>(result, startIndex);

 		} else if (endIndex != UNDEFINED) {

-			result = new FirstNIterator<Node>(result, endIndex + 1);

+			result = new FirstNIterator<T>(result, endIndex + 1);

 		}

 

 		for (final IteratorFactory iteratorFactory : chain) {

-			result = iteratorFactory.iterator(result);

+			result = (Iterator<? extends T>) iteratorFactory.iterator(result);

 		}

 

-		return result;

+		return (Iterator<T>) result;

 	}

 

-	private Iterator<Node> rootIterator() {

+	private Iterator<? extends T> rootIterator() {

 		return createRootIterator(contentRange, includeText);

 	}

 

-	/**

-	 * Limit the nodes of this axis to the given content range. Cannot be combined with 'before' or 'after'. Can be

-	 * applied only once.

-	 * 

-	 * @param range

-	 *            the content range

-	 * @return a reference to this axis

-	 * @see Axis#before

-	 * @see Axis#after

-	 */

-	public Axis in(final ContentRange range) {

+	protected abstract Iterator<? extends T> createRootIterator(final ContentRange contentRange, final boolean includeText);

+

+	public Axis<? extends T> in(final ContentRange range) {

 		Assert.isTrue(ContentRange.ALL.equals(contentRange), "Can only use one of 'before', 'after' or 'in' in the same expression.");

 		contentRange = range;

 		return this;

 	}

 

-	/**

-	 * Limit the nodes of this axis to nodes before the given offset. Cannot be combined with 'in' or 'after'. Can be

-	 * applied only once.

-	 * 

-	 * @param beforeOffset

-	 *            the offset

-	 * @return a reference to this axis

-	 * @see Axis#in

-	 * @see Axis#after

-	 */

-	public Axis before(final int beforeOffset) {

+	public Axis<? extends T> before(final int beforeOffset) {

 		Assert.isTrue(ContentRange.ALL.equals(contentRange), "Can only use one of 'before', 'after' or 'in' in the same expression.");

 		contentRange = new ContentRange(contentRange.getStartOffset(), beforeOffset);

 		return this;

 	}

 

-	/**

-	 * Limit the nodes of this axis to nodes after the given offset. Cannot be combined with 'in' or 'before'. Can be

-	 * applied only once.

-	 * 

-	 * @param afterOffset

-	 *            the offset

-	 * @return a reference to this axis

-	 * @see Axis#in

-	 * @see Axis#before

-	 */

-	public Axis after(final int afterOffset) {

+	public Axis<? extends T> after(final int afterOffset) {

 		Assert.isTrue(ContentRange.ALL.equals(contentRange), "Can only use one of 'before', 'after' or 'in' in the same expression.");

 		contentRange = new ContentRange(afterOffset, contentRange.getEndOffset());

 		return this;

 	}

 

-	/**

-	 * Do not include Text nodes in this axis.

-	 * 

-	 * @return a reference to this axis

-	 */

-	public Axis withoutText() {

+	public Axis<? extends T> withoutText() {

 		includeText = false;

 		return this;

 	}

 

-	/**

-	 * Limit the nodes of this axis to nodes matching the given filter. Can be applied multiple times to chain multiple

-	 * filters.

-	 * 

-	 * @param filter

-	 *            the filter

-	 * @return a reference to this axis

-	 */

-	public Axis matching(final IFilter<Node> filter) {

+	public Axis<? extends T> matching(final IFilter<INode> filter) {

 		chain.add(new IteratorFactory() {

-			public Iterator<Node> iterator(final Iterator<Node> source) {

-				return new FilterIterator<Node>(source, filter);

+			public Iterator<? extends INode> iterator(final Iterator<? extends INode> source) {

+				return new FilterIterator<INode>(source, filter);

 			}

 		});

 		return this;

 	}

 

-	/**

-	 * Start the sequence of this axis at the given index. Can be applied only once.

-	 * 

-	 * @param startIndex

-	 *            the start index

-	 * @return a reference to this axis

-	 * @see Axis#to

-	 */

-	public Axis from(final int startIndex) {

+	public Axis<? extends T> from(final int startIndex) {

 		Assert.isTrue(this.startIndex == UNDEFINED, "Can set start index only once.");

 		this.startIndex = startIndex;

 		return this;

 	}

 

-	/**

-	 * End the sequence of this axis at the given index. Can be applied only once.

-	 * 

-	 * @param endIndex

-	 *            the end index

-	 * @return a reference to this axis

-	 * @see Axis#from

-	 */

-	public Axis to(final int endIndex) {

+	public Axis<? extends T> to(final int endIndex) {

 		Assert.isTrue(this.endIndex == UNDEFINED, "Can set end index only once.");

 		this.endIndex = endIndex;

 		return this;

 	}

 

-	/**

-	 * @return true if this sequence of this axis with all given criteria applied is empty

-	 */

 	public boolean isEmpty() {

 		return !iterator().hasNext();

 	}

 

-	/**

-	 * Create a list with all nodes of this axis that satisfy all given criteria. Be aware that this method goes through

-	 * the whole sequence to collect all matching nodes.

-	 * 

-	 * @return all nodes to which the given criteria apply as list

-	 */

-	public List<Node> asList() {

-		final ArrayList<Node> result = new ArrayList<Node>();

-		for (final Node node : this) {

+	public List<T> asList() {

+		final ArrayList<T> result = new ArrayList<T>();

+		for (final T node : this) {

 			result.add(node);

 		}

 		return result;

 	}

 

-	/**

-	 * @return the first node of this axis that satisfies all given critera

-	 */

-	public Node first() {

+	public T first() {

 		return iterator().next();

 	}

 

-	/**

-	 * Find the last node of this axis which satisfies all given criteria. Be aware that this method goes through the

-	 * whole sequence to find the last matching node.

-	 * 

-	 * @return the last node of this axis that satisfies all given criteria

-	 */

-	public Node last() {

-		Node result = null;

-		final Iterator<Node> iterator = iterator();

+	public T last() {

+		T result = null;

+		final Iterator<T> iterator = iterator();

 		while (iterator.hasNext()) {

 			result = iterator.next();

 		}

@@ -258,13 +146,8 @@
 		return result;

 	}

 

-	/**

-	 * @param index

-	 *            the index

-	 * @return the node with the given index in the resulting sequence of nodes

-	 */

-	public Node get(final int index) {

-		final Iterator<Node> iterator = iterator();

+	public T get(final int index) {

+		final Iterator<T> iterator = iterator();

 		int i = 0;

 		while (i++ < index) {

 			iterator.next();

@@ -272,27 +155,15 @@
 		return iterator.next();

 	}

 

-	/**

-	 * Visit all nodes of this axis that satisfy all given criteria.

-	 * 

-	 * @param visitor

-	 *            the visitor

-	 */

 	public void accept(final INodeVisitor visitor) {

-		for (final Node node : this) {

+		for (final INode node : this) {

 			node.accept(visitor);

 		}

 	}

 

-	/**

-	 * Count all nodes of this axis that satisfy all given criteria. Be aware that this method goes through the whole

-	 * sequence to count all matching nodes.

-	 * 

-	 * @return the number of nodes of this axis that satisfy all given criteria

-	 */

 	public int count() {

 		int result = 0;

-		final Iterator<Node> iterator = iterator();

+		final Iterator<T> iterator = iterator();

 		while (iterator.hasNext()) {

 			result++;

 			iterator.next();

@@ -301,6 +172,6 @@
 	}

 

 	private static interface IteratorFactory {

-		Iterator<Node> iterator(Iterator<Node> source);

+		Iterator<? extends INode> iterator(Iterator<? extends INode> source);

 	}

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Comment.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Comment.java
index cf196d9..1db2ab8 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Comment.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Comment.java
@@ -10,26 +10,28 @@
  *******************************************************************************/

 package org.eclipse.vex.core.internal.dom;

 

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.INodeVisitor;

+import org.eclipse.vex.core.dom.INodeVisitorWithResult;

+

 /**

  * A representation of an XML comment in the DOM. Comments have textual content, a start and an end tag.

  * 

  * @author Florian Thienel

  */

-public class Comment extends Node {

+public class Comment extends Node implements IComment {

 

-	@Override

 	public void accept(final INodeVisitor visitor) {

 		visitor.visit(this);

 	}

 

-	@Override

 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {

 		return visitor.visit(this);

 	}

 

-	@Override

-	public boolean isKindOf(final Node node) {

-		if (!(node instanceof Comment)) {

+	public boolean isKindOf(final INode node) {

+		if (!(node instanceof IComment)) {

 			return false;

 		}

 		return true;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyOfElement.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyOfElement.java
index 37a1e9d..694fda7 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyOfElement.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyOfElement.java
@@ -10,6 +10,10 @@
  *******************************************************************************/

 package org.eclipse.vex.core.internal.dom;

 

+import org.eclipse.vex.core.dom.BaseNodeVisitor;

+import org.eclipse.vex.core.dom.IAttribute;

+import org.eclipse.vex.core.dom.IElement;

+

 /**

  * This visitor copies the properties of a source element into the visited elements:

  * <ul>

@@ -21,19 +25,19 @@
  */

 public class CopyOfElement extends BaseNodeVisitor {

 

-	private final Element source;

+	private final IElement source;

 

 	/**

 	 * @param source

 	 *            the source element

 	 */

-	public CopyOfElement(final Element source) {

+	public CopyOfElement(final IElement source) {

 		this.source = source;

 	}

 

 	@Override

-	public void visit(final Element element) {

-		for (final Attribute attribute : source.getAttributes()) {

+	public void visit(final IElement element) {

+		for (final IAttribute attribute : source.getAttributes()) {

 			element.setAttribute(attribute.getQualifiedName(), attribute.getValue());

 		}

 

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyVisitor.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyVisitor.java
index 32e27b7..614b896 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyVisitor.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CopyVisitor.java
@@ -10,6 +10,13 @@
  *******************************************************************************/

 package org.eclipse.vex.core.internal.dom;

 

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IDocumentFragment;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.dom.INodeVisitorWithResult;

+import org.eclipse.vex.core.dom.IText;

+

 /**

  * This visitor creates a simple copy of the visited node. I.e. only the node itself, not its content neither its

  * children are copied. The copy is provided through the getCopy() method.

@@ -18,26 +25,26 @@
  */

 public class CopyVisitor implements INodeVisitorWithResult<Node> {

 

-	public Document visit(final Document document) {

+	public Document visit(final IDocument document) {

 		throw new UnsupportedOperationException("Document cannot be copied");

 	}

 

-	public DocumentFragment visit(final DocumentFragment fragment) {

+	public DocumentFragment visit(final IDocumentFragment fragment) {

 		throw new UnsupportedOperationException("DocumentFragment cannot be copied");

 	}

 

-	public Element visit(final Element element) {

+	public Element visit(final IElement element) {

 		final Element copyElement = new Element(element.getQualifiedName());

 		copyElement.accept(new CopyOfElement(element));

 		return copyElement;

 	}

 

-	public Text visit(final Text text) {

+	public Text visit(final IText text) {

 		// ignore Text nodes because they are created dynamically in Element.getChildNodes()

 		return null;

 	}

 

-	public Comment visit(final Comment comment) {

+	public Comment visit(final IComment comment) {

 		return new Comment();

 	}

 

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopy.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopy.java
index 5875aa3..9b26a57 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopy.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopy.java
@@ -14,6 +14,11 @@
 import java.util.Collections;

 import java.util.List;

 

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IContent;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.IParent;

+

 /**

  * This class creates a deep copy of a single Node or the child nodes of a Parent within a given Range. The copy is made

  * instantly when the constructor of DeepCopy is called.

@@ -24,7 +29,7 @@
  */

 public class DeepCopy {

 

-	private final Content content;

+	private final IContent content;

 	private final List<Node> nodes;

 

 	/**

@@ -33,7 +38,7 @@
 	 * @param node

 	 *            the node to copy

 	 */

-	public DeepCopy(final Node node) {

+	public DeepCopy(final INode node) {

 		final int delta;

 		if (node.isAssociated()) {

 			final ContentRange range = node.getRange();

@@ -56,7 +61,7 @@
 	 * @param range

 	 *            the range to copy

 	 */

-	public DeepCopy(final Parent parent, final ContentRange range) {

+	public DeepCopy(final IParent parent, final ContentRange range) {

 		final int delta;

 		if (parent.isAssociated()) {

 			delta = -range.getStartOffset();

@@ -70,9 +75,9 @@
 		copyNodes(parent.children().in(range), delta);

 	}

 

-	private void copyNodes(final Iterable<Node> sourceNodes, final int delta) {

+	private void copyNodes(final Iterable<? extends INode> sourceNodes, final int delta) {

 		final DeepCopyVisitor deepCopyVisitor = new DeepCopyVisitor(nodes, content, delta);

-		for (final Node sourceNode : sourceNodes) {

+		for (final INode sourceNode : sourceNodes) {

 			sourceNode.accept(deepCopyVisitor);

 		}

 	}

@@ -87,7 +92,7 @@
 	/**

 	 * @return the copied content.

 	 */

-	public Content getContent() {

+	public IContent getContent() {

 		return content;

 	}

 

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopyVisitor.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopyVisitor.java
index 9071993..8de0eca 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopyVisitor.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DeepCopyVisitor.java
@@ -2,6 +2,17 @@
 

 import java.util.List;

 

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.IContent;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IDocumentFragment;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.INodeVisitor;

+import org.eclipse.vex.core.dom.IParent;

+import org.eclipse.vex.core.dom.IText;

+

 /**

  * This visitor creates a deep copy of the visited nodes. Deep copy means a full copy of each visited node and its

  * children down to the leaf level. All copied nodes are associated with a given content. The copied nodes on the root

@@ -14,7 +25,7 @@
 	private final CopyVisitor copyVisitor = new CopyVisitor();

 

 	private final List<Node> rootNodes;

-	private final Content content;

+	private final IContent content;

 	private final int delta;

 

 	private Parent currentParent = null;

@@ -28,40 +39,40 @@
 	 *            the shift for the content association, relative to the beginning of the first node in the source

 	 *            content

 	 */

-	public DeepCopyVisitor(final List<Node> rootNodes, final Content content, final int delta) {

+	public DeepCopyVisitor(final List<Node> rootNodes, final IContent content, final int delta) {

 		this.rootNodes = rootNodes;

 		this.content = content;

 		this.delta = delta;

 	}

 

-	public void visit(final Document document) {

+	public void visit(final IDocument document) {

 		throw new UnsupportedOperationException("Document cannot be deep copied");

 	}

 

-	public void visit(final DocumentFragment fragment) {

+	public void visit(final IDocumentFragment fragment) {

 		copyChildren(fragment, null);

 	}

 

-	public void visit(final Element element) {

-		final Element copy = copy(element);

+	public void visit(final IElement element) {

+		final Element copy = (Element) copy(element);

 		addToParent(copy);

 		associate(element, copy);

 

 		copyChildren(element, copy);

 	}

 

-	public void visit(final Text text) {

+	public void visit(final IText text) {

 		// ignore Text nodes because they are created dynamically in Element.getChildNodes()

 	}

 

-	public void visit(final Comment comment) {

-		final Comment copy = copy(comment);

+	public void visit(final IComment comment) {

+		final Comment copy = (Comment) copy(comment);

 		addToParent(copy);

 		associate(comment, copy);

 	}

 

 	@SuppressWarnings("unchecked")

-	private <T extends Node> T copy(final T node) {

+	private <T extends INode> T copy(final T node) {

 		return (T) node.accept(copyVisitor);

 	}

 

@@ -73,16 +84,16 @@
 		}

 	}

 

-	private void associate(final Node source, final Node copy) {

+	private void associate(final INode source, final Node copy) {

 		if (source.isAssociated()) {

 			final ContentRange range = source.getRange();

 			copy.associate(content, range.moveBy(delta));

 		}

 	}

 

-	private void copyChildren(final Parent source, final Parent copy) {

+	private void copyChildren(final IParent source, final Parent copy) {

 		final Parent lastParent = currentParent;

-		for (final Node child : source.children()) {

+		for (final INode child : source.children()) {

 			currentParent = copy;

 			child.accept(this);

 		}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
index 158e4d7..63a6603 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
@@ -18,22 +18,39 @@
 
 import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.BaseNodeVisitorWithResult;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.DocumentEvent;
+import org.eclipse.vex.core.dom.DocumentValidationException;
+import org.eclipse.vex.core.dom.IComment;
+import org.eclipse.vex.core.dom.IContent;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IDocumentFragment;
+import org.eclipse.vex.core.dom.IDocumentListener;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.INodeVisitor;
+import org.eclipse.vex.core.dom.INodeVisitorWithResult;
+import org.eclipse.vex.core.dom.IParent;
+import org.eclipse.vex.core.dom.IPosition;
+import org.eclipse.vex.core.dom.IText;
+import org.eclipse.vex.core.dom.IValidator;
 import org.eclipse.vex.core.internal.core.ListenerList;
 
 /**
  * A representation of an XML document in the DOM.
  */
-public class Document extends Parent {
+public class Document extends Parent implements IDocument {
 
 	private final Element rootElement;
-	private final ListenerList<DocumentListener, DocumentEvent> listeners = new ListenerList<DocumentListener, DocumentEvent>(DocumentListener.class);
+	private final ListenerList<IDocumentListener, DocumentEvent> listeners = new ListenerList<IDocumentListener, DocumentEvent>(IDocumentListener.class);
 
 	private String publicID;
 	protected String systemID;
 	private String documentURI;
 
 	private String encoding;
-	private Validator validator;
+	private IValidator validator;
 
 	/**
 	 * Create a new document with the given root element. This constructor creates a Content object and associates both
@@ -65,7 +82,7 @@
 	 *            root element of the document
 	 * 
 	 */
-	public Document(final Content content, final Element rootElement) {
+	public Document(final IContent content, final Element rootElement) {
 		Assert.isTrue(content == rootElement.getContent(), "The given root element must already be associated with the given content.");
 		content.insertTagMarker(0);
 		content.insertTagMarker(content.length());
@@ -89,12 +106,10 @@
 		return getContent().length() - 1;
 	}
 
-	@Override
 	public void accept(final INodeVisitor visitor) {
 		visitor.visit(this);
 	}
 
-	@Override
 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {
 		return visitor.visit(this);
 	}
@@ -104,8 +119,7 @@
 		return getDocumentURI();
 	}
 
-	@Override
-	public boolean isKindOf(final Node node) {
+	public boolean isKindOf(final INode node) {
 		return false;
 	}
 
@@ -145,11 +159,11 @@
 		this.systemID = systemID;
 	}
 
-	public Validator getValidator() {
+	public IValidator getValidator() {
 		return validator;
 	}
 
-	public void setValidator(final Validator validator) {
+	public void setValidator(final IValidator validator) {
 		this.validator = validator;
 	}
 
@@ -157,34 +171,15 @@
 		return rootElement;
 	}
 
-	/**
-	 * @return the length of the textual content of this document plus 1 for each opening or closing XML tag (element
-	 *         tags, comment tags, PI tags and entity references).
-	 */
 	public int getLength() {
 		return getContent().length();
 	}
 
-	/**
-	 * Create a Position for the given offset. A position is automatically updated if it "moves" due to content
-	 * modifications.
-	 * 
-	 * <p>
-	 * All created positions are referenced by this document. <b>Make sure to remove positions you don't need
-	 * anymore.</b>
-	 * 
-	 * @see Position
-	 * @see Document#removePosition(Position)
-	 * @return the Position for the given offset
-	 */
-	public Position createPosition(final int offset) {
+	public IPosition createPosition(final int offset) {
 		return getContent().createPosition(offset);
 	}
 
-	/**
-	 * Remove the given Position. A removed position is not updated anymore.
-	 */
-	public void removePosition(final Position position) {
+	public void removePosition(final IPosition position) {
 		getContent().removePosition(position);
 	}
 
@@ -192,17 +187,17 @@
 	 * L1 Operations
 	 */
 
-	private boolean canInsertAt(final Node insertionNode, final int offset, final QualifiedName... nodeNames) {
+	private boolean canInsertAt(final INode insertionNode, final int offset, final QualifiedName... nodeNames) {
 		return canInsertAt(insertionNode, offset, Arrays.asList(nodeNames));
 	}
 
-	private boolean canInsertAt(final Node insertionNode, final int offset, final List<QualifiedName> nodeNames) {
+	private boolean canInsertAt(final INode insertionNode, final int offset, final List<QualifiedName> nodeNames) {
 		if (insertionNode == null) {
 			return false;
 		}
 		return insertionNode.accept(new BaseNodeVisitorWithResult<Boolean>(false) {
 			@Override
-			public Boolean visit(final Element element) {
+			public Boolean visit(final IElement element) {
 				if (validator == null) {
 					return true;
 				}
@@ -215,68 +210,55 @@
 			}
 
 			@Override
-			public Boolean visit(final Comment comment) {
+			public Boolean visit(final IComment comment) {
 				return true;
 			}
 
 			@Override
-			public Boolean visit(final Text text) {
+			public Boolean visit(final IText text) {
 				return true;
 			}
 		});
 	}
 
-	/**
-	 * @return true if text can be inserted at the given offset
-	 */
 	public boolean canInsertText(final int offset) {
-		return canInsertAt(getNodeForInsertionAt(offset), offset, Validator.PCDATA);
+		return canInsertAt(getNodeForInsertionAt(offset), offset, IValidator.PCDATA);
 	}
 
-	/**
-	 * Insert the given text at the given offset.
-	 * 
-	 * @param offset
-	 *            the offset at which the text should be inserted
-	 * @param text
-	 *            The text to insert. Control characters are automatically converted to \s (except for \n).
-	 * @throws DocumentValidationException
-	 *             if text is not allowed at the given offset
-	 */
 	public void insertText(final int offset, final String text) throws DocumentValidationException {
 		Assert.isTrue(offset > getStartOffset() && offset <= getEndOffset(), MessageFormat.format("Offset must be in [{0}, {1}]", getStartOffset() + 1, getEndOffset()));
 
 		final String adjustedText = convertControlCharactersToSpaces(text);
-		final Node insertionNode = getNodeForInsertionAt(offset);
+		final INode insertionNode = getNodeForInsertionAt(offset);
 		insertionNode.accept(new INodeVisitor() {
-			public void visit(final Document document) {
+			public void visit(final IDocument document) {
 				Assert.isTrue(false, "Cannot insert text directly into Document.");
 			}
 
-			public void visit(final DocumentFragment fragment) {
+			public void visit(final IDocumentFragment fragment) {
 				Assert.isTrue(false, "DocumentFragment is never a child of Document.");
 			}
 
-			public void visit(final Element element) {
-				if (!canInsertAt(element, offset, Validator.PCDATA)) {
+			public void visit(final IElement element) {
+				if (!canInsertAt(element, offset, IValidator.PCDATA)) {
 					throw new DocumentValidationException(MessageFormat.format("Cannot insert text ''{0}'' at offset {1}.", text, offset));
 				}
 
-				fireBeforeContentInserted(new DocumentEvent(Document.this, element, offset, adjustedText.length(), null));
+				fireBeforeContentInserted(new DocumentEvent(Document.this, element, new ContentRange(offset, offset + adjustedText.length() - 1)));
 				getContent().insertText(offset, adjustedText);
-				fireContentInserted(new DocumentEvent(Document.this, element, offset, adjustedText.length(), null));
+				fireContentInserted(new DocumentEvent(Document.this, element, new ContentRange(offset, offset + adjustedText.length() - 1)));
 			}
 
-			public void visit(final Text text) {
-				fireBeforeContentInserted(new DocumentEvent(Document.this, text.getParent(), offset, adjustedText.length(), null));
+			public void visit(final IText text) {
+				fireBeforeContentInserted(new DocumentEvent(Document.this, text.getParent(), new ContentRange(offset, offset + adjustedText.length() - 1)));
 				getContent().insertText(offset, adjustedText);
-				fireContentInserted(new DocumentEvent(Document.this, text.getParent(), offset, adjustedText.length(), null));
+				fireContentInserted(new DocumentEvent(Document.this, text.getParent(), new ContentRange(offset, offset + adjustedText.length() - 1)));
 			}
 
-			public void visit(final Comment comment) {
-				fireBeforeContentInserted(new DocumentEvent(Document.this, comment.getParent(), offset, adjustedText.length(), null));
+			public void visit(final IComment comment) {
+				fireBeforeContentInserted(new DocumentEvent(Document.this, comment.getParent(), new ContentRange(offset, offset + adjustedText.length() - 1)));
 				getContent().insertText(offset, adjustedText);
-				fireContentInserted(new DocumentEvent(Document.this, comment.getParent(), offset, adjustedText.length(), null));
+				fireContentInserted(new DocumentEvent(Document.this, comment.getParent(), new ContentRange(offset, offset + adjustedText.length() - 1)));
 			}
 		});
 	}
@@ -291,38 +273,25 @@
 		return new String(characters);
 	}
 
-	/**
-	 * @return true if a comment can be inserted a the given offset
-	 */
 	public boolean canInsertComment(final int offset) {
 		if (!(offset > getStartOffset() && offset <= getEndOffset())) {
 			return false;
 		}
-		final Node node = getNodeForInsertionAt(offset);
-		if (node instanceof Comment) {
+		final INode node = getNodeForInsertionAt(offset);
+		if (node instanceof IComment) {
 			return false;
 		}
 		return true;
 	}
 
-	/**
-	 * Insert a new comment at the given offset.
-	 * 
-	 * @see Comment
-	 * @param offset
-	 *            the offset at which the comment should be inserted
-	 * @return the new comment
-	 * @throws DocumentValidationException
-	 *             if a comment is not allowed a the given offset (e.g. within an existing comment)
-	 */
-	public Comment insertComment(final int offset) throws DocumentValidationException {
+	public IComment insertComment(final int offset) throws DocumentValidationException {
 		if (!canInsertComment(offset)) {
 			throw new DocumentValidationException(MessageFormat.format("Cannot insert a comment at offset {0}.", offset));
 		}
 
 		final Parent parent = getParentForInsertionAt(offset);
 
-		fireBeforeContentInserted(new DocumentEvent(this, parent, offset, 2, null));
+		fireBeforeContentInserted(new DocumentEvent(this, parent, new ContentRange(offset, offset + 1)));
 
 		final Comment comment = new Comment();
 		getContent().insertTagMarker(offset);
@@ -331,31 +300,15 @@
 
 		parent.insertChildAt(offset, comment);
 
-		fireContentInserted(new DocumentEvent(this, parent, offset, 2, null));
+		fireContentInserted(new DocumentEvent(this, parent, comment.getRange()));
 
 		return comment;
 	}
 
-	/**
-	 * @return true if a new element with the given qualified name can be inserted at the given offset
-	 */
 	public boolean canInsertElement(final int offset, final QualifiedName elementName) {
 		return canInsertAt(getElementForInsertionAt(offset), offset, elementName);
 	}
 
-	/**
-	 * Insert a new element with the given qualified name a the given offset.
-	 * 
-	 * @see Element
-	 * @see QualifiedName
-	 * @param offset
-	 *            the offset at which the element should be inserted
-	 * @param elementName
-	 *            the qualified name of the new element
-	 * @return the new element
-	 * @throws DocumentValidationException
-	 *             if an element with the given qualified name is not allowed a the given offset
-	 */
 	public Element insertElement(final int offset, final QualifiedName elementName) throws DocumentValidationException {
 		Assert.isTrue(offset > rootElement.getStartOffset() && offset <= rootElement.getEndOffset(),
 				MessageFormat.format("Offset must be in [{0}, {1}]", rootElement.getStartOffset() + 1, rootElement.getEndOffset()));
@@ -365,7 +318,7 @@
 			throw new DocumentValidationException(MessageFormat.format("Cannot insert element {0} at offset {1}.", elementName, offset));
 		}
 
-		fireBeforeContentInserted(new DocumentEvent(this, parent, offset, 2, null));
+		fireBeforeContentInserted(new DocumentEvent(this, parent, new ContentRange(offset, offset + 1)));
 
 		final Element element = new Element(elementName);
 		getContent().insertTagMarker(offset);
@@ -374,30 +327,16 @@
 
 		parent.insertChildAt(offset, element);
 
-		fireContentInserted(new DocumentEvent(this, parent, offset, 2, null));
+		fireContentInserted(new DocumentEvent(this, parent, element.getRange()));
 
 		return element;
 	}
 
-	/**
-	 * @return true if the given DocumentFragment can be inserted at the given offset
-	 */
-	public boolean canInsertFragment(final int offset, final DocumentFragment fragment) {
+	public boolean canInsertFragment(final int offset, final IDocumentFragment fragment) {
 		return canInsertAt(getElementForInsertionAt(offset), offset, fragment.getNodeNames());
 	}
 
-	/**
-	 * Insert the given DocumentFragment at the given offset.
-	 * 
-	 * @see DocumentFragment
-	 * @param offset
-	 *            the offset at which the fragment should be inserted
-	 * @param fragment
-	 *            the fragment to insert
-	 * @throws DocumentValidationException
-	 *             if the given fragment may not be inserted at the given offset
-	 */
-	public void insertFragment(final int offset, final DocumentFragment fragment) throws DocumentValidationException {
+	public void insertFragment(final int offset, final IDocumentFragment fragment) throws DocumentValidationException {
 		Assert.isTrue(isInsertionPointIn(this, offset), "Cannot insert fragment outside of the document range.");
 
 		final Element parent = getElementForInsertionAt(offset);
@@ -405,7 +344,7 @@
 			throw new DocumentValidationException(MessageFormat.format("Cannot insert document fragment at offset {0}.", offset));
 		}
 
-		fireBeforeContentInserted(new DocumentEvent(this, parent, offset, 2, null));
+		fireBeforeContentInserted(new DocumentEvent(this, parent, new ContentRange(offset, offset + 1)));
 
 		getContent().insertContent(offset, fragment.getContent());
 
@@ -418,42 +357,34 @@
 			nextOffset = newNode.getEndOffset() + 1;
 		}
 
-		fireContentInserted(new DocumentEvent(this, parent, offset, fragment.getContent().length(), null));
+		fireContentInserted(new DocumentEvent(this, parent, new ContentRange(offset, offset + fragment.getContent().length() - 1)));
 	}
 
 	private void associateDeeply(final Node node, final int offset) {
 		if (node instanceof Parent) {
 			final Parent parent = (Parent) node;
-			for (final Node child : parent.children()) {
-				associateDeeply(child, offset);
+			for (final INode child : parent.children()) {
+				associateDeeply((Node) child, offset);
 			}
 		}
 		node.associate(getContent(), node.getRange().moveBy(offset));
 	}
 
-	/**
-	 * Delete everything in the given range. The range must be balanced i.e. it must start in the same node as it ends.
-	 * 
-	 * @param range
-	 *            the range to delete
-	 * @throws DocumentValidationException
-	 *             if the deletion would lead to an invalid document
-	 */
 	public void delete(final ContentRange range) throws DocumentValidationException {
-		final Parent surroundingParent = getParentAt(range.getStartOffset());
-		final Parent parentAtEndOffset = getParentAt(range.getEndOffset());
+		final IParent surroundingParent = getParentAt(range.getStartOffset());
+		final IParent parentAtEndOffset = getParentAt(range.getEndOffset());
 		Assert.isTrue(surroundingParent == parentAtEndOffset, MessageFormat.format("Range {0} for deletion is unbalanced: {1} -> {2}", range, surroundingParent, parentAtEndOffset));
 
 		final Parent parentForDeletion;
 		if (range.equals(surroundingParent.getRange())) {
-			parentForDeletion = surroundingParent.getParent();
+			parentForDeletion = (Parent) surroundingParent.getParent();
 		} else {
-			parentForDeletion = surroundingParent;
+			parentForDeletion = (Parent) surroundingParent;
 		}
 
 		final boolean deletionIsValid = parentForDeletion.accept(new BaseNodeVisitorWithResult<Boolean>(true) {
 			@Override
-			public Boolean visit(final Document document) {
+			public Boolean visit(final IDocument document) {
 				if (range.intersects(document.getRootElement().getRange())) {
 					return false;
 				}
@@ -461,8 +392,8 @@
 			}
 
 			@Override
-			public Boolean visit(final Element element) {
-				final Validator validator = getValidator();
+			public Boolean visit(final IElement element) {
+				final IValidator validator = getValidator();
 				if (validator == null) {
 					return true;
 				}
@@ -475,25 +406,22 @@
 			throw new DocumentValidationException(MessageFormat.format("Cannot delete {0}", range));
 		}
 
-		fireBeforeContentDeleted(new DocumentEvent(this, parentForDeletion, range.getStartOffset(), range.length(), null));
+		fireBeforeContentDeleted(new DocumentEvent(this, parentForDeletion, range));
 
-		for (final Node child : parentForDeletion.children().in(range)) {
-			parentForDeletion.removeChild(child);
-			child.dissociate();
+		for (final INode child : parentForDeletion.children().in(range)) {
+			parentForDeletion.removeChild((Node) child);
+			((Node) child).dissociate();
 		}
 
 		getContent().remove(range);
 
-		fireContentDeleted(new DocumentEvent(this, parentForDeletion, range.getStartOffset(), range.length(), null));
+		fireContentDeleted(new DocumentEvent(this, parentForDeletion, range));
 	}
 
 	/*
 	 * Miscellaneous
 	 */
 
-	/**
-	 * @return the character at the given offset. If there is an XML tag at the given offset \0 is returned.
-	 */
 	public char getCharacterAt(final int offset) {
 		final String text = getContent().getText(new ContentRange(offset, offset));
 		if (text.length() == 0) {
@@ -507,25 +435,16 @@
 		return text.charAt(0);
 	}
 
-	/**
-	 * Find the nearest common node of the given offsets going from each offset to the root element.
-	 * 
-	 * @param offset1
-	 *            the first offset
-	 * @param offset2
-	 *            the second offset
-	 * @return the nearest common node for both offsets
-	 */
-	public Node findCommonNode(final int offset1, final int offset2) {
+	public INode findCommonNode(final int offset1, final int offset2) {
 		Assert.isTrue(containsOffset(offset1) && containsOffset(offset2));
 		return findCommonNodeIn(this, offset1, offset2);
 	}
 
-	private static Node findCommonNodeIn(final Parent parent, final int offset1, final int offset2) {
-		for (final Node child : parent.children().withoutText()) {
+	private static INode findCommonNodeIn(final IParent parent, final int offset1, final int offset2) {
+		for (final INode child : parent.children().withoutText()) {
 			if (isCommonNodeFor(child, offset1, offset2)) {
-				if (child instanceof Parent) {
-					return findCommonNodeIn((Parent) child, offset1, offset2);
+				if (child instanceof IParent) {
+					return findCommonNodeIn((IParent) child, offset1, offset2);
 				}
 				return child;
 			}
@@ -533,23 +452,17 @@
 		return parent;
 	}
 
-	private static boolean isCommonNodeFor(final Node node, final int offset1, final int offset2) {
+	private static boolean isCommonNodeFor(final INode node, final int offset1, final int offset2) {
 		return isInsertionPointIn(node, offset1) && isInsertionPointIn(node, offset2);
 	}
 
-	/**
-	 * @return true if the given node would contain an insertion at the given offset
-	 */
-	public static boolean isInsertionPointIn(final Node node, final int offset) {
+	public static boolean isInsertionPointIn(final INode node, final int offset) {
 		return node.getRange().resizeBy(1, 0).contains(offset);
 	}
 
-	/**
-	 * @return the node in which an insertion at the given offset will end
-	 */
-	public Node getNodeForInsertionAt(final int offset) {
-		final Node node = getChildAt(offset);
-		if (node instanceof Text) {
+	public INode getNodeForInsertionAt(final int offset) {
+		final INode node = getChildAt(offset);
+		if (node instanceof IText) {
 			return node.getParent();
 		}
 		if (offset == node.getStartOffset()) {
@@ -559,20 +472,17 @@
 	}
 
 	private Parent getParentForInsertionAt(final int offset) {
-		final Node node = getChildAt(offset);
+		final INode node = getChildAt(offset);
 		if (!(node instanceof Parent)) {
-			return node.getParent();
+			return (Parent) node.getParent();
 		}
 		if (offset == node.getStartOffset()) {
-			return node.getParent();
+			return (Parent) node.getParent();
 		}
 		// this cast is save because if we got here node is a Parent
 		return (Parent) node;
 	}
 
-	/**
-	 * @return the element in which an insertion at the given offset will end
-	 */
 	public Element getElementForInsertionAt(final int offset) {
 		final Element parent = getParentElement(getChildAt(offset));
 		if (parent == null) {
@@ -584,7 +494,7 @@
 		return parent;
 	}
 
-	private static Element getParentElement(final Node node) {
+	private static Element getParentElement(final INode node) {
 		if (node == null) {
 			return null;
 		}
@@ -594,53 +504,37 @@
 		return getParentElement(node.getParent());
 	}
 
-	private Parent getParentAt(final int offset) {
-		final Node child = getChildAt(offset);
-		if (child instanceof Parent) {
-			return (Parent) child;
+	private IParent getParentAt(final int offset) {
+		final INode child = getChildAt(offset);
+		if (child instanceof IParent) {
+			return (IParent) child;
 		}
 		return child.getParent();
 	}
 
-	/**
-	 * @return true if there is an XML tag at the given offset (element tags, comment tags, PI tags and entity
-	 *         references)
-	 */
 	public boolean isTagAt(final int offset) {
 		return getContent().isTagMarker(offset);
 	}
 
-	/**
-	 * Create a new DocumentFragment with a deep copy of the given range in this document. The range must be balanced
-	 * i.e. it must start in the same node as it ends.
-	 * 
-	 * @see DocumentFragment
-	 * @param range
-	 *            the range to copy into the fragment
-	 * @return a new fragment with a deep copy of the given range
-	 */
 	public DocumentFragment getFragment(final ContentRange range) {
-		final Parent parent = getParentOfRange(range);
+		final IParent parent = getParentOfRange(range);
 		final DeepCopy deepCopy = new DeepCopy(parent, range);
 		return new DocumentFragment(deepCopy.getContent(), deepCopy.getNodes());
 	}
 
-	private Parent getParentOfRange(final ContentRange range) {
+	private IParent getParentOfRange(final ContentRange range) {
 		Assert.isTrue(getRange().contains(range));
 
-		final Node startNode = getChildAt(range.getStartOffset());
-		final Node endNode = getChildAt(range.getEndOffset());
-		final Parent parent = startNode.getParent();
+		final INode startNode = getChildAt(range.getStartOffset());
+		final INode endNode = getChildAt(range.getEndOffset());
+		final IParent parent = startNode.getParent();
 		Assert.isTrue(parent == endNode.getParent(), MessageFormat.format("The fragment in {0} is unbalanced.", range));
 		Assert.isNotNull(parent, MessageFormat.format("No balanced parent found for {0}", range));
 
 		return parent;
 	}
 
-	/**
-	 * @return all nodes in the given range in this document
-	 */
-	public List<Node> getNodes(final ContentRange range) {
+	public List<? extends INode> getNodes(final ContentRange range) {
 		return getParentOfRange(range).children().in(range).asList();
 	}
 
@@ -648,11 +542,11 @@
 	 * Events
 	 */
 
-	public void addDocumentListener(final DocumentListener listener) {
+	public void addDocumentListener(final IDocumentListener listener) {
 		listeners.add(listener);
 	}
 
-	public void removeDocumentListener(final DocumentListener listener) {
+	public void removeDocumentListener(final IDocumentListener listener) {
 		listeners.remove(listener);
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentEvent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentEvent.java
deleted file mode 100644
index eaa7118..0000000
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentEvent.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2013 John Krasnay and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * 
- * Contributors:
- *     John Krasnay - initial API and implementation
- *     Florian Thienel - support for attribute changes
- *******************************************************************************/
-package org.eclipse.vex.core.internal.dom;
-
-import java.util.EventObject;
-
-import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.vex.core.internal.undo.IUndoableEdit;
-
-/**
- * Encapsulation of the details of a document change
- */
-public class DocumentEvent extends EventObject {
-
-	private static final long serialVersionUID = -9028980559838712720L;
-
-	private final Document document;
-	private final Parent parent;
-	private int offset;
-	private int length;
-	private QualifiedName attributeName;
-	private String oldAttributeValue;
-	private String newAttributeValue;
-	private final IUndoableEdit undoableEdit;
-
-	/**
-	 * Class constructor.
-	 * 
-	 * @param document
-	 *            Document that changed.
-	 * @param parent
-	 *            Parent containing the change.
-	 * @param offset
-	 *            offset at which the change occurred.
-	 * @param length
-	 *            length of the change.
-	 * @param undoableEdit
-	 *            IUndoableEdit that can be used to undo the change.
-	 */
-	public DocumentEvent(final Document document, final Parent parent, final int offset, final int length, final IUndoableEdit undoableEdit) {
-		super(document);
-		this.document = document;
-		this.parent = parent;
-		this.offset = offset;
-		this.length = length;
-		this.undoableEdit = undoableEdit;
-	}
-
-	/**
-	 * Class constructor used when firing an attributeChanged event.
-	 * 
-	 * @param document
-	 *            Document that changed.
-	 * @param parent
-	 *            Parent containing the attribute that changed
-	 * @param attributeName
-	 *            name of the attribute that changed
-	 * @param oldAttributeValue
-	 *            value of the attribute before the change.
-	 * @param newAttributeValue
-	 *            value of the attribute after the change.
-	 * @param undoableEdit
-	 *            IUndoableEdit that can be used to undo the change.
-	 */
-	public DocumentEvent(final Document document, final Parent parent, final QualifiedName attributeName, final String oldAttributeValue, final String newAttributeValue,
-			final IUndoableEdit undoableEdit) {
-		super(document);
-		this.document = document;
-		this.parent = parent;
-		this.attributeName = attributeName;
-		this.oldAttributeValue = oldAttributeValue;
-		this.newAttributeValue = newAttributeValue;
-		this.undoableEdit = undoableEdit;
-	}
-
-	/**
-	 * @return the length of the change
-	 */
-	public int getLength() {
-		return length;
-	}
-
-	/**
-	 * @return the offset at which the change occurred
-	 */
-	public int getOffset() {
-		return offset;
-	}
-
-	/**
-	 * @return the Parent containing the change
-	 */
-	public Parent getParent() {
-		return parent;
-	}
-
-	/**
-	 * @return the value of the attribute before the change. If null, indicates that the attribute was removed
-	 */
-	public String getNewAttributeValue() {
-		return newAttributeValue;
-	}
-
-	/**
-	 * @return the value of the attribute after the change. If null, indicates the attribute did not exist before the
-	 *         change
-	 */
-	public String getOldAttributeValue() {
-		return oldAttributeValue;
-	}
-
-	/**
-	 * @return the qualified name of the attribute that was changed
-	 */
-	public QualifiedName getAttributeName() {
-		return attributeName;
-	}
-
-	/**
-	 * @return the document for which this event was generated
-	 */
-	public Document getDocument() {
-		return document;
-	}
-
-	/**
-	 * @return the undoable edit that can be used to undo the action. May be null, in which case the action cannot be
-	 *         undone.
-	 */
-	public IUndoableEdit getUndoableEdit() {
-		return undoableEdit;
-	}
-}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java
index bd14a4c..649a9c6 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentFragment.java
@@ -16,21 +16,15 @@
 
 import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.IContent;
+import org.eclipse.vex.core.dom.IDocumentFragment;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.INodeVisitor;
+import org.eclipse.vex.core.dom.INodeVisitorWithResult;
 
-/**
- * Represents a wellformed fragment of an XML document.
- */
-public class DocumentFragment extends Parent {
+public class DocumentFragment extends Parent implements IDocumentFragment {
 
-	/**
-	 * Create a new fragment with based on the given content and nodes.
-	 * 
-	 * @param content
-	 *            the Content holding the fragment's content
-	 * @param nodes
-	 *            the nodes that make up the structure of this fragment
-	 */
-	public DocumentFragment(final Content content, final List<Node> nodes) {
+	public DocumentFragment(final IContent content, final List<Node> nodes) {
 		Assert.isTrue(content.length() > 0);
 		associate(content, content.getRange());
 		for (final Node node : nodes) {
@@ -38,51 +32,32 @@
 		}
 	}
 
-	/**
-	 * @return the length of the textual content of this fragment plus 1 for each opening or closing XML tag (element
-	 *         tags, comment tags, PI tags and entity references)
-	 */
 	public int getLength() {
 		return getContent().length();
 	}
 
-	/**
-	 * @return a list with the qualified names off all nodes on the root level of this fragment
-	 */
 	public List<QualifiedName> getNodeNames() {
 		return Node.getNodeNames(children());
 	}
 
-	/**
-	 * @return all nodes on the root level of this fragment
-	 */
-	public List<Node> getNodes() {
+	public List<? extends INode> getNodes() {
 		return children().asList();
 	}
 
-	/**
-	 * The base URI of a fragment is always null because a fragment has no persistent representation.
-	 * 
-	 * @see Node#getBaseURI()
-	 * @return null
-	 */
 	@Override
 	public String getBaseURI() {
 		return null;
 	}
 
-	@Override
 	public void accept(final INodeVisitor visitor) {
 		visitor.visit(this);
 	}
 
-	@Override
 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {
 		return visitor.visit(this);
 	}
 
-	@Override
-	public boolean isKindOf(final Node node) {
+	public boolean isKindOf(final INode node) {
 		return false;
 	}
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Element.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Element.java
index 6d840d3..8da5e15 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Element.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Element.java
@@ -17,18 +17,23 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.DocumentEvent;
+import org.eclipse.vex.core.dom.DocumentValidationException;
+import org.eclipse.vex.core.dom.Filters;
+import org.eclipse.vex.core.dom.IAttribute;
+import org.eclipse.vex.core.dom.IAxis;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.INodeVisitor;
+import org.eclipse.vex.core.dom.INodeVisitorWithResult;
 import org.eclipse.vex.core.internal.core.QualifiedNameComparator;
 
-/**
- * A representation of an XML element in the DOM. Elements have attributes, namespace declarations and children, as well
- * as a start and an end tag. The textual content of an element is represented by its child Text nodes.
- */
-public class Element extends Parent {
+public class Element extends Parent implements IElement {
 
 	/*
 	 * The xml:base attribute re-defines the base URI for a part of an XML document, according to the XML Base
@@ -43,23 +48,10 @@
 	private final Map<QualifiedName, Attribute> attributes = new HashMap<QualifiedName, Attribute>();
 	private final Map<String, String> namespaceDeclarations = new HashMap<String, String>();
 
-	/**
-	 * Create an element with the given name in the default namespace (only the local name without the qualifier is
-	 * given).
-	 * 
-	 * @param localName
-	 *            the local name of the element
-	 */
 	public Element(final String localName) {
 		this(new QualifiedName(null, localName));
 	}
 
-	/**
-	 * Create an element with the given qualified name.
-	 * 
-	 * @param qualifiedName
-	 *            the qualified name of the element
-	 */
 	public Element(final QualifiedName qualifiedName) {
 		name = qualifiedName;
 	}
@@ -70,44 +62,28 @@
 
 	@Override
 	public String getBaseURI() {
-		final Attribute baseAttribute = getAttribute(XML_BASE_ATTRIBUTE);
+		final IAttribute baseAttribute = getAttribute(XML_BASE_ATTRIBUTE);
 		if (baseAttribute != null) {
 			return baseAttribute.getValue();
 		}
 		return super.getBaseURI();
 	}
 
-	/**
-	 * Set the base URI of this element. The xml:base attribute re-defines the base URI for a part of an XML document,
-	 * according to the XML Base Recommendation.
-	 * 
-	 * @see http://www.w3.org/TR/xmlbase/
-	 */
 	public void setBaseURI(final String baseURI) {
 		setAttribute(XML_BASE_ATTRIBUTE, baseURI);
 	}
 
-	/**
-	 * This element is the same kind as the given node if the node is also an element and both have the same qualified
-	 * name.
-	 * 
-	 * @see Node#isKindOf(Node)
-	 * @return true if this element and the given node are of the same kind
-	 */
-	@Override
-	public boolean isKindOf(final Node other) {
-		if (!(other instanceof Element)) {
+	public boolean isKindOf(final INode other) {
+		if (!(other instanceof IElement)) {
 			return false;
 		}
-		return getQualifiedName().equals(((Element) other).getQualifiedName());
+		return getQualifiedName().equals(((IElement) other).getQualifiedName());
 	}
 
-	@Override
 	public void accept(final INodeVisitor visitor) {
 		visitor.visit(this);
 	}
 
-	@Override
 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {
 		return visitor.visit(this);
 	}
@@ -124,17 +100,10 @@
 		return name.getLocalName();
 	}
 
-	/**
-	 * @return the declared namespace prefix for this element
-	 */
 	public String getPrefix() {
 		return getNamespacePrefix(name.getQualifier());
 	}
 
-	/**
-	 * @return the declared namespace prefix and the local name of this element separated by a colon (e.g.
-	 *         "prefix:localName")
-	 */
 	public String getPrefixedName() {
 		final String prefix = getPrefix();
 		if (prefix == null) {
@@ -143,13 +112,6 @@
 		return prefix + ":" + getLocalName();
 	}
 
-	/**
-	 * Qualify the given local name with the namespace qualifier of this element.
-	 * 
-	 * @param localName
-	 *            the local name to be qualified
-	 * @return the qualified variant of the given local name
-	 */
 	public QualifiedName qualify(final String localName) {
 		return new QualifiedName(name.getQualifier(), localName);
 	}
@@ -158,17 +120,11 @@
 	 * Attributes
 	 */
 
-	/**
-	 * @return the attribute with the given local name, or null if the attribute is not set
-	 */
-	public Attribute getAttribute(final String localName) {
+	public IAttribute getAttribute(final String localName) {
 		return getAttribute(qualify(localName));
 	}
 
-	/**
-	 * @return the attribute with the given qualified name, or null if the attribute is not set
-	 */
-	public Attribute getAttribute(final QualifiedName name) {
+	public IAttribute getAttribute(final QualifiedName name) {
 		return attributes.get(name);
 	}
 
@@ -176,39 +132,20 @@
 		return getAttributeValue(qualify(localName));
 	}
 
-	/**
-	 * @return the value of the attribute with the given qualified name, or null if the attribute is not set
-	 */
 	public String getAttributeValue(final QualifiedName name) {
-		final Attribute attribute = getAttribute(name);
+		final IAttribute attribute = getAttribute(name);
 		if (attribute == null || "".equals(attribute.getValue().trim())) {
 			return null;
 		}
 		return attribute.getValue();
 	}
 
-	/**
-	 * Remove the attribute with the given local name.
-	 * 
-	 * @param localName
-	 *            the local name of the attribute to be removed
-	 * @throws DocumentValidationException
-	 *             if the removal of the attribute would make the document invalid
-	 */
 	public void removeAttribute(final String localName) throws DocumentValidationException {
 		removeAttribute(qualify(localName));
 	}
 
-	/**
-	 * Remove the attribute with the given qualified name.
-	 * 
-	 * @param name
-	 *            the qualified name of the attribute to be removed
-	 * @throws DocumentValidationException
-	 *             if the removal of the attribute would make the document invalid
-	 */
 	public void removeAttribute(final QualifiedName name) throws DocumentValidationException {
-		final Attribute attribute = this.getAttribute(name);
+		final IAttribute attribute = this.getAttribute(name);
 		if (attribute == null) {
 			return;
 		}
@@ -223,35 +160,15 @@
 			return;
 		}
 
-		document.fireAttributeChanged(new DocumentEvent(document, this, name, oldValue, newValue, null));
+		document.fireAttributeChanged(new DocumentEvent(document, this, name, oldValue, newValue));
 	}
 
-	/**
-	 * Set the attribute with the given local name to the given value.
-	 * 
-	 * @param localName
-	 *            the local name of the attribute
-	 * @param value
-	 *            the new attribute value
-	 * @throws DocumentValidationException
-	 *             if the new attribute value would make the document invalid
-	 */
 	public void setAttribute(final String localName, final String value) throws DocumentValidationException {
 		setAttribute(qualify(localName), value);
 	}
 
-	/**
-	 * Set the attribute with the given qualified name to the given value.
-	 * 
-	 * @param name
-	 *            the qualified name of the attribute
-	 * @param value
-	 *            the new attribute value
-	 * @throws DocumentValidationException
-	 *             if the new attribute value would make the document invalid
-	 */
 	public void setAttribute(final QualifiedName name, final String value) throws DocumentValidationException {
-		final Attribute oldAttribute = attributes.get(name);
+		final IAttribute oldAttribute = attributes.get(name);
 		final String oldValue = oldAttribute != null ? oldAttribute.getValue() : null;
 
 		if (value == null && oldValue == null) {
@@ -272,26 +189,20 @@
 					return;
 				}
 
-				document.fireAttributeChanged(new DocumentEvent(document, this, name, oldValue, value, null));
+				document.fireAttributeChanged(new DocumentEvent(document, this, name, oldValue, value));
 			}
 		}
 	}
 
-	/**
-	 * @return all attributes currently set on this element
-	 */
-	public Collection<Attribute> getAttributes() {
-		final ArrayList<Attribute> result = new ArrayList<Attribute>(attributes.values());
+	public Collection<IAttribute> getAttributes() {
+		final ArrayList<IAttribute> result = new ArrayList<IAttribute>(attributes.values());
 		Collections.sort(result);
 		return Collections.unmodifiableCollection(result);
 	}
 
-	/**
-	 * @return the qualified names of all attributes currently set on this element
-	 */
-	public List<QualifiedName> getAttributeNames() {
+	public Collection<QualifiedName> getAttributeNames() {
 		final ArrayList<QualifiedName> result = new ArrayList<QualifiedName>();
-		for (final Attribute attribute : attributes.values()) {
+		for (final IAttribute attribute : attributes.values()) {
 			result.add(attribute.getQualifiedName());
 		}
 		Collections.sort(result, new QualifiedNameComparator());
@@ -302,11 +213,8 @@
 	 * Element Structure
 	 */
 
-	/**
-	 * @return the parent element of this element
-	 */
 	public Element getParentElement() {
-		for (final Node ancestor : ancestors()) {
+		for (final INode ancestor : ancestors()) {
 			if (ancestor instanceof Element) {
 				return (Element) ancestor;
 			}
@@ -314,60 +222,34 @@
 		return null;
 	}
 
-	/**
-	 * @return the child elements of this element
-	 */
-	public List<Element> getChildElements() {
-		final List<Element> elements = new ArrayList<Element>();
-		for (final Node node : children().withoutText()) {
-			node.accept(new BaseNodeVisitor() {
-				@Override
-				public void visit(final Element element) {
-					elements.add(element);
-				}
-			});
-		}
-		return elements;
+	@SuppressWarnings("unchecked")
+	public IAxis<Element> childElements() {
+		return (IAxis<Element>) children().withoutText().matching(Filters.elements());
 	}
 
 	/*
 	 * Namespaces
 	 */
 
-	/**
-	 * @return the namespace URI of the given namespace prefix, or null if no namespace with the given prefix is
-	 *         declared
-	 */
 	public String getNamespaceURI(final String namespacePrefix) {
 		if (namespaceDeclarations.containsKey(namespacePrefix)) {
 			return namespaceDeclarations.get(namespacePrefix);
 		}
-		final Element parent = getParentElement();
+		final IElement parent = getParentElement();
 		if (parent != null) {
 			return parent.getNamespaceURI(namespacePrefix);
 		}
 		return null;
 	}
 
-	/**
-	 * @return the default namespace URI or null, if no default namespace is declared
-	 */
 	public String getDefaultNamespaceURI() {
 		return getNamespaceURI(null);
 	}
 
-	/**
-	 * @return the URI of the default namespace declared on this element, or null if no default namespace is declared on
-	 *         this element
-	 */
 	public String getDeclaredDefaultNamespaceURI() {
 		return namespaceDeclarations.get(null);
 	}
 
-	/**
-	 * @return the declared namespace prefix for the given namespace URI, or null if the namespace with the given URI is
-	 *         not declared in the document
-	 */
 	public String getNamespacePrefix(final String namespaceURI) {
 		if (namespaceURI == null) {
 			return null;
@@ -383,7 +265,7 @@
 				return entry.getKey();
 			}
 		}
-		final Element parent = getParentElement();
+		final IElement parent = getParentElement();
 		if (parent != null) {
 			final String parentPrefix = parent.getNamespacePrefix(namespaceURI);
 			if (!namespaceDeclarations.containsKey(parentPrefix)) {
@@ -393,9 +275,6 @@
 		return null;
 	}
 
-	/**
-	 * @return the prefixes of the namespaces that are declared on this element
-	 */
 	public Collection<String> getDeclaredNamespacePrefixes() {
 		final ArrayList<String> result = new ArrayList<String>();
 		for (final String prefix : namespaceDeclarations.keySet()) {
@@ -407,27 +286,16 @@
 		return result;
 	}
 
-	/**
-	 * @return the prefixes of the declared namespaces
-	 */
 	public Collection<String> getNamespacePrefixes() {
 		final HashSet<String> result = new HashSet<String>();
 		result.addAll(getDeclaredNamespacePrefixes());
-		final Element parent = getParentElement();
+		final IElement parent = getParentElement();
 		if (parent != null) {
 			result.addAll(parent.getNamespacePrefixes());
 		}
 		return result;
 	}
 
-	/**
-	 * Declare a namespace with the given prefix and URI on this element.
-	 * 
-	 * @param namespacePrefix
-	 *            the prefix of the namespace to be declared
-	 * @param namespaceURI
-	 *            the URI of the namespace to be declared
-	 */
 	public void declareNamespace(final String namespacePrefix, final String namespaceURI) {
 		if (namespaceURI == null || "".equals(namespaceURI.trim())) {
 			return;
@@ -442,15 +310,9 @@
 			return;
 		}
 
-		document.fireNamespaceChanged(new DocumentEvent(document, this, getStartOffset(), 0, null));
+		document.fireNamespaceChanged(new DocumentEvent(document, this, new ContentRange(getStartOffset(), getStartOffset())));
 	}
 
-	/**
-	 * Remove the namespace declaration with the given prefix from this element.
-	 * 
-	 * @param namespacePrefix
-	 *            the prefix of the namespace to be removed
-	 */
 	public void removeNamespace(final String namespacePrefix) {
 		final String oldNamespaceURI = namespaceDeclarations.remove(namespacePrefix);
 		final Document document = getDocument();
@@ -462,22 +324,13 @@
 			return; // we have actually removed nothing, so we should not tell anybody about it
 		}
 
-		document.fireNamespaceChanged(new DocumentEvent(document, this, getStartOffset(), 0, null));
+		document.fireNamespaceChanged(new DocumentEvent(document, this, new ContentRange(getStartOffset(), getStartOffset())));
 	}
 
-	/**
-	 * Declare the default namespace with the given URI on this element.
-	 * 
-	 * @param namespaceURI
-	 *            the URI of the default namespace
-	 */
 	public void declareDefaultNamespace(final String namespaceURI) {
 		declareNamespace(null, namespaceURI);
 	}
 
-	/**
-	 * Remove the declaration of the default namespace from this element.
-	 */
 	public void removeDefaultNamespace() {
 		removeNamespace(null);
 	}
@@ -493,7 +346,7 @@
 		sb.append("<");
 		sb.append(getPrefixedName().toString());
 
-		for (final Attribute attribute : getAttributes()) {
+		for (final IAttribute attribute : getAttributes()) {
 			sb.append(" ");
 			sb.append(attribute.getPrefixedName());
 			sb.append("=\"");
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/GapContent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/GapContent.java
index aa18683..a39929f 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/GapContent.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/GapContent.java
@@ -16,6 +16,9 @@
 import java.util.TreeSet;
 
 import org.eclipse.core.runtime.Assert;
+import org.eclipse.vex.core.dom.IContent;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.IPosition;
 
 /**
  * Implementation of the <code>Content</code> interface that manages changes efficiently. Implements a buffer that keeps
@@ -23,7 +26,7 @@
  * chars to be moved so long as the insertion is smaller than the gap. Deletions that end of the gap are also very
  * efficent. Furthermore, changes near the gap require relatively few characters to be moved.
  */
-public class GapContent implements Content {
+public class GapContent implements IContent {
 
 	private static final int GROWTH_SLOWDOWN_SIZE = 100000;
 	private static final int GROWTH_RATE_FAST = 2;
@@ -50,7 +53,7 @@
 		gapEnd = initialCapacity;
 	}
 
-	public Position createPosition(final int offset) {
+	public IPosition createPosition(final int offset) {
 
 		assertOffset(offset, 0, length());
 
@@ -65,7 +68,7 @@
 		return newPosition;
 	}
 
-	public void removePosition(final Position position) {
+	public void removePosition(final IPosition position) {
 		if (positions.contains(position)) {
 			/*
 			 * This cast is save: if the position can be removed, this instance must have created it, hence it is a
@@ -211,17 +214,17 @@
 		stringBuilder.append(content, range.getStartOffset(), range.length());
 	}
 
-	public void insertContent(final int offset, final Content content) {
+	public void insertContent(final int offset, final IContent content) {
 		assertOffset(offset, 0, length());
 
 		copyContent(content, this, content.getRange(), offset);
 	}
 
-	public Content getContent() {
+	public IContent getContent() {
 		return getContent(getRange());
 	}
 
-	public Content getContent(final ContentRange range) {
+	public IContent getContent(final ContentRange range) {
 		Assert.isTrue(getRange().contains(range));
 
 		final GapContent result = new GapContent(range.length());
@@ -229,7 +232,7 @@
 		return result;
 	}
 
-	private static void copyContent(final Content source, final Content destination, final ContentRange sourceRange, final int destinationStartOffset) {
+	private static void copyContent(final IContent source, final IContent destination, final ContentRange sourceRange, final int destinationStartOffset) {
 		for (int i = 0; i < sourceRange.length(); i++) {
 			final int sourceOffset = sourceRange.getStartOffset() + i;
 			final int destinationOffset = destinationStartOffset + i;
@@ -284,7 +287,7 @@
 	/*
 	 * Implementation of the Position interface.
 	 */
-	private static class GapContentPosition implements Position, Comparable<Position> {
+	private static class GapContentPosition implements IPosition, Comparable<IPosition> {
 
 		private int offset;
 
@@ -345,7 +348,7 @@
 			return Integer.toString(offset);
 		}
 
-		public int compareTo(final Position other) {
+		public int compareTo(final IPosition other) {
 			return offset - other.getOffset();
 		}
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/MergeNodesWithTextIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/MergeNodesWithTextIterator.java
index e214fd0..34f5aa7 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/MergeNodesWithTextIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/MergeNodesWithTextIterator.java
@@ -14,22 +14,25 @@
 import java.util.NoSuchElementException;

 

 import org.eclipse.core.runtime.Assert;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IContent;

+import org.eclipse.vex.core.dom.INode;

 

 /**

  * @author Florian Thienel

  */

-public class MergeNodesWithTextIterator implements Iterator<Node> {

+public class MergeNodesWithTextIterator implements Iterator<INode> {

 

 	private final Parent parent;

-	private final Iterator<Node> nodes;

-	private final Content content;

+	private final Iterator<? extends INode> nodes;

+	private final IContent content;

 	private final ContentRange contentRange;

 

 	private int textCursor;

-	private Node currentChild;

+	private INode currentChild;

 	private ContentRange nextTextGap;

 

-	public MergeNodesWithTextIterator(final Parent parent, final Iterable<Node> nodes, final Content content, final ContentRange contentRange) {

+	public MergeNodesWithTextIterator(final Parent parent, final Iterable<? extends INode> nodes, final IContent content, final ContentRange contentRange) {

 		this.parent = parent;

 		this.nodes = nodes.iterator();

 		this.content = content;

@@ -100,7 +103,7 @@
 		return textCursor < nextTextGap.getStartOffset();

 	}

 

-	public Node next() {

+	public INode next() {

 		if (!hasNext()) {

 			throw new NoSuchElementException();

 		}

@@ -125,13 +128,13 @@
 		return nextChild();

 	}

 

-	private Node nextChild() {

-		final Node child = currentChild;

+	private INode nextChild() {

+		final INode child = currentChild;

 		nextStep();

 		return child;

 	}

 

-	private Node nextText(final int textStart, final int textEnd) {

+	private Text nextText(final int textStart, final int textEnd) {

 		return new Text(parent, content, new ContentRange(textStart, textEnd));

 	}

 

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Node.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Node.java
index 9900a31..f4fae9e 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Node.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Node.java
@@ -17,48 +17,43 @@
 
 import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.BaseNodeVisitor;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.IAxis;
+import org.eclipse.vex.core.dom.IContent;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IParent;
+import org.eclipse.vex.core.dom.IPosition;
+import org.eclipse.vex.core.dom.IText;
+import org.eclipse.vex.core.dom.IValidator;
 
 /**
  * A representation of one node in the XML structure. A node is associated to a range of the textual content.
  * <p>
  * This is the base class for all representatives of the XML structure in the document object model (DOM).
  */
-public abstract class Node {
+public abstract class Node implements INode {
 
 	private Parent parent;
-	private Content content;
-	private Position startPosition = Position.NULL;
-	private Position endPosition = Position.NULL;
+	private IContent content;
+	private IPosition startPosition = IPosition.NULL;
+	private IPosition endPosition = IPosition.NULL;
 
-	/**
-	 * @see Parent
-	 * @return the parent of this node, maybe null if this node has no parent
-	 */
 	public Parent getParent() {
 		return parent;
 	}
 
-	/**
-	 * @see Parent
-	 * @param parent
-	 *            the parent of this node, maybe null if this node should not have a parent
-	 */
 	public void setParent(final Parent parent) {
 		this.parent = parent;
 	}
 
-	/**
-	 * The ancestors axis contains all subsequent parents of this node.
-	 * 
-	 * @return the ancestors axis of this node
-	 * @see Axis
-	 */
-	public Axis ancestors() {
-		return new Axis(this) {
+	public IAxis<IParent> ancestors() {
+		return new Axis<IParent>(this) {
 			@Override
-			protected Iterator<Node> createRootIterator(final ContentRange contentRange, final boolean includeText) {
-				return new NodesInContentRangeIterator(new Iterable<Node>() {
-					public Iterator<Node> iterator() {
+			protected Iterator<IParent> createRootIterator(final ContentRange contentRange, final boolean includeText) {
+				return NodesInContentRangeIterator.iterator(new Iterable<IParent>() {
+					public Iterator<IParent> iterator() {
 						return new AncestorsIterator(Node.this);
 					}
 				}, contentRange);
@@ -66,15 +61,7 @@
 		};
 	}
 
-	/**
-	 * Associate this node to a range within the given content.
-	 * 
-	 * @param content
-	 *            Content object holding the node's content
-	 * @param range
-	 *            the range of this node's content
-	 */
-	public void associate(final Content content, final ContentRange range) {
+	public void associate(final IContent content, final ContentRange range) {
 		if (isAssociated()) {
 			dissociate();
 		}
@@ -84,56 +71,34 @@
 		endPosition = content.createPosition(range.getEndOffset());
 	}
 
-	/**
-	 * Dissociates this node from its associated content range.
-	 */
 	public void dissociate() {
 		Assert.isTrue(isAssociated(), "This node must be associated to a ContentRange before it can be dissociated.");
 
 		content.removePosition(startPosition);
 		content.removePosition(endPosition);
-		startPosition = Position.NULL;
-		endPosition = Position.NULL;
+		startPosition = IPosition.NULL;
+		endPosition = IPosition.NULL;
 		content = null;
 	}
 
-	/**
-	 * @return if this node is associated to content
-	 */
 	public boolean isAssociated() {
 		return content != null;
 	}
 
-	/**
-	 * @return the content to which this node is associated or null if this node is not associated to any content yet
-	 */
-	public Content getContent() {
+	public IContent getContent() {
 		return content;
 	}
 
-	/**
-	 * The start offset of this node, which eventually also includes the position of a tag marker.
-	 * 
-	 * @return the start offset of this node within the textual content
-	 */
 	public int getStartOffset() {
 		Assert.isTrue(isAssociated(), "Node must be associated to a ContentRange to have a start offset.");
 		return startPosition.getOffset();
 	}
 
-	/**
-	 * The end offset of this node, which eventually also includes the position of a tag marker.
-	 * 
-	 * @return the end offset of this node within the textual content
-	 */
 	public int getEndOffset() {
 		Assert.isTrue(isAssociated(), "Node must be associated to a ContentRange to have an end offset.");
 		return endPosition.getOffset();
 	}
 
-	/**
-	 * @return the range in the content to which this node is associated, eventually including tag markers
-	 */
 	public ContentRange getRange() {
 		if (!isAssociated()) {
 			return ContentRange.NULL;
@@ -141,12 +106,6 @@
 		return new ContentRange(getStartOffset(), getEndOffset());
 	}
 
-	/**
-	 * Indicate whether this node has no content beside its tag markers. If this node is not associated with textual
-	 * content, this method returns false.
-	 * 
-	 * @return true if this node has no content beside its tag markers
-	 */
 	public boolean isEmpty() {
 		if (!isAssociated()) {
 			return false;
@@ -154,14 +113,6 @@
 		return getEndOffset() - getStartOffset() == 1;
 	}
 
-	/**
-	 * Indicate whether the given offset is within the boundaries of this node. If this node is not associated with
-	 * textual content, this method returns false.
-	 * 
-	 * @param offset
-	 *            the offset
-	 * @return true if the given offset is withing [startOffset; endOffset], or false if not associated
-	 */
 	public boolean containsOffset(final int offset) {
 		if (!isAssociated()) {
 			return false;
@@ -169,14 +120,6 @@
 		return getRange().contains(offset);
 	}
 
-	/**
-	 * Indicate whether this node is fully within the given range. If this node is not associated with textual content,
-	 * this method returns false.
-	 * 
-	 * @param range
-	 *            the range
-	 * @return true if this node is fully within the given range
-	 */
 	public boolean isInRange(final ContentRange range) {
 		if (!isAssociated()) {
 			return false;
@@ -184,33 +127,20 @@
 		return range.contains(getRange());
 	}
 
-	/**
-	 * @return the textual content of this node, not including any tag markers
-	 */
 	public String getText() {
 		return getText(getRange());
 	}
 
-	/**
-	 * The textual content in the given range, not including any element markers.
-	 * 
-	 * @param range
-	 *            the range of the textual content
-	 * @return the textual content in the given range
-	 */
 	public String getText(final ContentRange range) {
 		Assert.isTrue(isAssociated(), "Node must be associated to a Content region to have textual content.");
 		return content.getText(range.intersection(getRange()));
 	}
 
-	/**
-	 * @return the document to which this node belongs, or null if this node does not belong to any document
-	 */
 	public Document getDocument() {
 		if (this instanceof Document) {
 			return (Document) this;
 		}
-		for (final Node ancestor : ancestors()) {
+		for (final INode ancestor : ancestors()) {
 			if (ancestor instanceof Document) {
 				return (Document) ancestor;
 			}
@@ -218,17 +148,6 @@
 		return null;
 	}
 
-	/**
-	 * Indicate whether this and the given node are of the same kind (e.g. elements with the same qualified name).
-	 * 
-	 * @return true if this and the given node are of the same kind
-	 */
-	public abstract boolean isKindOf(final Node node);
-
-	/**
-	 * @see Element#setBaseURI(String)
-	 * @return the base URI of this node
-	 */
 	public String getBaseURI() {
 		if (getParent() != null) {
 			return getParent().getBaseURI();
@@ -239,39 +158,18 @@
 		return null;
 	}
 
-	/**
-	 * Accept the given visitor.
-	 * 
-	 * @see INodeVisitor
-	 * @param visitor
-	 *            the visitor
-	 */
-	public abstract void accept(final INodeVisitor visitor);
-
-	/**
-	 * Accept the given visitor.
-	 * 
-	 * @see INodeVisitorWithResult
-	 * @param visitor
-	 *            the visitor
-	 */
-	public abstract <T> T accept(final INodeVisitorWithResult<T> visitor);
-
-	/**
-	 * @return the qualified names of the given nodes
-	 */
-	public static List<QualifiedName> getNodeNames(final Iterable<Node> nodes) {
+	public static List<QualifiedName> getNodeNames(final Iterable<? extends INode> nodes) {
 		final List<QualifiedName> names = new ArrayList<QualifiedName>();
 
-		for (final Node node : nodes) {
+		for (final INode node : nodes) {
 			node.accept(new BaseNodeVisitor() {
 				@Override
-				public void visit(final Text text) {
-					names.add(Validator.PCDATA);
+				public void visit(final IText text) {
+					names.add(IValidator.PCDATA);
 				}
 
 				@Override
-				public void visit(final Element element) {
+				public void visit(final IElement element) {
 					names.add(element.getQualifiedName());
 				}
 			});
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/NodesInContentRangeIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/NodesInContentRangeIterator.java
index fb38902..e6da4a6 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/NodesInContentRangeIterator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/NodesInContentRangeIterator.java
@@ -10,17 +10,26 @@
  *******************************************************************************/

 package org.eclipse.vex.core.internal.dom;

 

+import java.util.Iterator;

+

+import org.eclipse.vex.core.IFilter;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.INode;

 import org.eclipse.vex.core.internal.core.FilterIterator;

-import org.eclipse.vex.core.internal.core.IFilter;

 

 /**

  * @author Florian Thienel

  */

-public class NodesInContentRangeIterator extends FilterIterator<Node> {

+public class NodesInContentRangeIterator extends FilterIterator<INode> {

 

-	public NodesInContentRangeIterator(final Iterable<Node> nodes, final ContentRange contentRange) {

-		super(nodes.iterator(), new IFilter<Node>() {

-			public boolean matches(final Node node) {

+	@SuppressWarnings("unchecked")

+	public static <T extends INode> Iterator<T> iterator(final Iterable<T> nodes, final ContentRange contentRange) {

+		return (Iterator<T>) new NodesInContentRangeIterator(nodes, contentRange);

+	}

+

+	private NodesInContentRangeIterator(final Iterable<? extends INode> nodes, final ContentRange contentRange) {

+		super(nodes.iterator(), new IFilter<INode>() {

+			public boolean matches(final INode node) {

 				return !node.isAssociated() || contentRange.contains(node.getRange());

 			}

 		});

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Parent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Parent.java
index 3883494..73a222c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Parent.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Parent.java
@@ -16,6 +16,10 @@
 import java.util.List;

 

 import org.eclipse.core.runtime.Assert;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.IAxis;

+import org.eclipse.vex.core.dom.INode;

+import org.eclipse.vex.core.dom.IParent;

 

 /**

  * A Parent node is a Node which can contain other nodes as children. This class defines the tree-like structure of the

@@ -24,7 +28,7 @@
  * 

  * @author Florian Thienel

  */

-public abstract class Parent extends Node {

+public abstract class Parent extends Node implements IParent {

 

 	private final List<Node> children = new ArrayList<Node>();

 

@@ -58,7 +62,7 @@
 		final ContentRange insertionRange = getRange().resizeBy(1, 0);

 		Assert.isTrue(insertionRange.contains(offset), MessageFormat.format("The offset must be within {0}.", insertionRange));

 		int i = 0;

-		for (final Node child : children()) {

+		for (final INode child : children()) {

 			if (offset <= child.getStartOffset()) {

 				return i;

 			}

@@ -79,12 +83,12 @@
 	 *            the offset

 	 * @return the node at the given offset

 	 */

-	public Node getChildAt(final int offset) {

+	public INode getChildAt(final int offset) {

 		Assert.isTrue(containsOffset(offset), MessageFormat.format("Offset must be within {0}.", getRange()));

-		for (final Node child : children()) {

+		for (final INode child : children()) {

 			if (child.containsOffset(offset)) {

-				if (child instanceof Parent) {

-					return ((Parent) child).getChildAt(offset);

+				if (child instanceof IParent) {

+					return ((IParent) child).getChildAt(offset);

 				} else {

 					return child;

 				}

@@ -102,7 +106,7 @@
 	 * @param child

 	 *            the child node to insert

 	 */

-	public void insertChildBefore(final Node beforeNode, final Node child) {

+	public void insertChildBefore(final INode beforeNode, final Node child) {

 		final int index = children.indexOf(beforeNode);

 		Assert.isTrue(index > -1, MessageFormat.format("{0} must be a child of this parent.", beforeNode));

 		insertChildAtIndex(index, child);

@@ -121,16 +125,16 @@
 

 	/**

 	 * @return the children axis of this parent.

-	 * @see Axis

+	 * @see IAxis

 	 */

-	public Axis children() {

-		return new Axis(this) {

+	public IAxis<INode> children() {

+		return new Axis<INode>(this) {

 			@Override

-			public Iterator<Node> createRootIterator(final ContentRange contentRange, final boolean includeText) {

+			public Iterator<? extends INode> createRootIterator(final ContentRange contentRange, final boolean includeText) {

 				if (includeText) {

 					return new MergeNodesWithTextIterator(Parent.this, children, getContent(), contentRange);

 				}

-				return new NodesInContentRangeIterator(children, contentRange);

+				return NodesInContentRangeIterator.iterator(children, contentRange);

 			}

 		};

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Text.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Text.java
index 5cf79ad..127ccd5 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Text.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Text.java
@@ -11,13 +11,14 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.dom;
 
-/**
- * A representation of textual content of an XML document within the DOM. Text objects are not used in the internal
- * document structure; they are dynamically created as needed by the <code>Element.getChildNodes()</code> method.
- * 
- * @see Element#getChildNodes()
- */
-public class Text extends Node {
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.IContent;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.INodeVisitor;
+import org.eclipse.vex.core.dom.INodeVisitorWithResult;
+import org.eclipse.vex.core.dom.IText;
+
+public class Text extends Node implements IText {
 
 	/**
 	 * Create a new Text node for the given range in the given content. This constructor automatically associates the
@@ -32,23 +33,20 @@
 	 * @param endOffset
 	 *            character offset of the end of the run
 	 */
-	public Text(final Parent parent, final Content content, final ContentRange range) {
+	public Text(final Parent parent, final IContent content, final ContentRange range) {
 		setParent(parent);
 		associate(content, range);
 	}
 
-	@Override
 	public void accept(final INodeVisitor visitor) {
 		visitor.visit(this);
 	}
 
-	@Override
 	public <T> T accept(final INodeVisitorWithResult<T> visitor) {
 		return visitor.visit(this);
 	}
 
-	@Override
-	public boolean isKindOf(final Node node) {
+	public boolean isKindOf(final INode node) {
 		return false;
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/package.html b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/package.html
deleted file mode 100644
index 2eca216..0000000
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/package.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version='1.0'?>
-<html>
-
-  <head>
-
-    <title>net.sf.vex.dom</title>
-
-  </head>
-
-  <body>
-
-    <p>Classes implementing an object model for XML documents. The 
-    classes in this package are designed to be similar to those in the 
-    JDOM library. However, this package is unique in that content is 
-    represented by one single string of characters for the entire 
-    document. Implementing the model in this way simplifies the editor 
-    implementation.</p>
-
-  </body>
-
-</html>
-
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java
index 622d58f..022299c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentBuilder.java
@@ -17,15 +17,14 @@
 
 import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.DocumentValidationException;
+import org.eclipse.vex.core.dom.IContent;
+import org.eclipse.vex.core.dom.IDocument;
 import org.eclipse.vex.core.internal.dom.Comment;
-import org.eclipse.vex.core.internal.dom.Content;
-import org.eclipse.vex.core.internal.dom.ContentRange;
 import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentContentModel;
-import org.eclipse.vex.core.internal.dom.DocumentValidationException;
 import org.eclipse.vex.core.internal.dom.Element;
 import org.eclipse.vex.core.internal.dom.GapContent;
-import org.eclipse.vex.core.internal.dom.IWhitespacePolicy;
 import org.eclipse.vex.core.internal.dom.Node;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
@@ -61,7 +60,7 @@
 	private boolean trimLeading = false;
 
 	// Content object to hold document content
-	private final Content content = new GapContent(100);
+	private final IContent content = new GapContent(100);
 
 	// Stack of StackElement objects
 	private final LinkedList<StackEntry> stack = new LinkedList<StackEntry>();
@@ -78,7 +77,7 @@
 	private final String baseUri;
 	private String dtdPublicID;
 	private String dtdSystemID;
-	private Document document;
+	private IDocument document;
 	private Locator locator;
 
 	public DocumentBuilder(final String baseUri, final DocumentContentModel documentContentModel) {
@@ -89,7 +88,7 @@
 	/**
 	 * Returns the newly built <code>Document</code> object.
 	 */
-	public Document getDocument() {
+	public IDocument getDocument() {
 		return document;
 	}
 
@@ -124,11 +123,11 @@
 		document.setSystemID(dtdSystemID);
 
 		for (final Node node : nodesBeforeRoot) {
-			document.insertChildBefore(document.getRootElement(), node);
+			((Document) document).insertChildBefore(document.getRootElement(), node);
 		}
 
 		for (final Node node : nodesAfterRoot) {
-			document.addChild(node);
+			((Document) document).addChild(node);
 		}
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentContentModel.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentContentModel.java
similarity index 95%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentContentModel.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentContentModel.java
index 8f7584b..7fd5d7c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentContentModel.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentContentModel.java
@@ -8,13 +8,14 @@
  * Contributors:

  * 		Florian Thienel - initial API and implementation

  *******************************************************************************/

-package org.eclipse.vex.core.internal.dom;

+package org.eclipse.vex.core.internal.io;

 

 import java.io.IOException;

 import java.net.MalformedURLException;

 import java.net.URL;

 import java.text.MessageFormat;

 

+import org.eclipse.vex.core.dom.IElement;

 import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;

 import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;

 import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;

@@ -38,11 +39,11 @@
 	public DocumentContentModel() {

 	}

 

-	public DocumentContentModel(final String baseUri, final String publicId, final String systemId, final Element rootElement) {

+	public DocumentContentModel(final String baseUri, final String publicId, final String systemId, final IElement rootElement) {

 		initialize(baseUri, publicId, systemId, rootElement);

 	}

 

-	public void initialize(final String baseUri, final String publicId, final String systemId, final Element rootElement) {

+	public void initialize(final String baseUri, final String publicId, final String systemId, final IElement rootElement) {

 		this.baseUri = baseUri;

 		this.publicId = publicId;

 		this.systemId = systemId;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentReader.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentReader.java
index a862b86..8d96909 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentReader.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentReader.java
@@ -22,8 +22,7 @@
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParserFactory;
 
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentContentModel;
+import org.eclipse.vex.core.dom.IDocument;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.EntityResolver;
 import org.xml.sax.InputSource;
@@ -77,7 +76,7 @@
 	 * @param url
 	 *            URL from which to load the document.
 	 */
-	public Document read(final URL url) throws IOException, ParserConfigurationException, SAXException {
+	public IDocument read(final URL url) throws IOException, ParserConfigurationException, SAXException {
 		return read(new InputSource(url.toString()));
 	}
 
@@ -87,7 +86,7 @@
 	 * @param s
 	 *            String containing the document to be read.
 	 */
-	public Document read(final String s) throws IOException, ParserConfigurationException, SAXException {
+	public IDocument read(final String s) throws IOException, ParserConfigurationException, SAXException {
 		final Reader reader = new CharArrayReader(s.toCharArray());
 		return this.read(new InputSource(reader));
 	}
@@ -98,7 +97,7 @@
 	 * @param is
 	 *            SAX InputSource from which to load the document.
 	 */
-	public Document read(final InputSource is) throws IOException, ParserConfigurationException, SAXException {
+	public IDocument read(final InputSource is) throws IOException, ParserConfigurationException, SAXException {
 		final SAXParserFactory factory = SAXParserFactory.newInstance();
 		factory.setValidating(false);
 		factory.setNamespaceAware(true);
@@ -129,7 +128,7 @@
 		xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", lexicalHandler);
 		xmlReader.setEntityResolver(combinedEntityResolver);
 		xmlReader.parse(is);
-		final Document result = builder.getDocument();
+		final IDocument result = builder.getDocument();
 		if (result != null) {
 			result.setDocumentURI(is.getSystemId());
 		}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentWriter.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentWriter.java
index 17b4960..2031f5a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentWriter.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/DocumentWriter.java
@@ -16,18 +16,16 @@
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.util.Arrays;
-import java.util.List;
 
-import org.eclipse.vex.core.internal.dom.Attribute;
-import org.eclipse.vex.core.internal.dom.BaseNodeVisitor;
-import org.eclipse.vex.core.internal.dom.Comment;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentFragment;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.IWhitespacePolicy;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Text;
-import org.eclipse.vex.core.internal.dom.Validator;
+import org.eclipse.vex.core.dom.BaseNodeVisitor;
+import org.eclipse.vex.core.dom.IAttribute;
+import org.eclipse.vex.core.dom.IComment;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IDocumentFragment;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IText;
+import org.eclipse.vex.core.dom.IValidator;
 import org.eclipse.vex.core.internal.validator.AttributeDefinition;
 
 /**
@@ -140,7 +138,7 @@
 		this.wrapColumn = wrapColumn;
 	}
 
-	public void write(final Document document, final OutputStream out) throws IOException {
+	public void write(final IDocument document, final OutputStream out) throws IOException {
 		final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
 		printWriter.println("<?xml version='1.0' encoding='UTF-8'?>");
 
@@ -148,7 +146,7 @@
 		printWriter.flush();
 	}
 
-	public void write(final DocumentFragment fragment, final OutputStream out) throws IOException {
+	public void write(final IDocumentFragment fragment, final OutputStream out) throws IOException {
 		final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
 		printWriter.println("<?xml version='1.0' encoding='UTF-8'?>");
 
@@ -158,10 +156,10 @@
 
 	// ====================================================== PRIVATE
 
-	private void writeNode(final Node node, final PrintWriter out, final String indent) {
+	private void writeNode(final INode node, final PrintWriter out, final String indent) {
 		node.accept(new BaseNodeVisitor() {
 			@Override
-			public void visit(final Document document) {
+			public void visit(final IDocument document) {
 				if (document.getSystemID() != null) {
 					final StringBuilder buffer = new StringBuilder();
 					buffer.append("<!DOCTYPE ");
@@ -180,22 +178,22 @@
 					out.println(buffer.toString());
 				}
 
-				for (final Node child : document.children()) {
+				for (final INode child : document.children()) {
 					writeNode(child, out, indent);
 				}
 			}
 
 			@Override
-			public void visit(final DocumentFragment fragment) {
+			public void visit(final IDocumentFragment fragment) {
 				out.print("<vex_fragment>");
-				for (final Node child : fragment.children()) {
+				for (final INode child : fragment.children()) {
 					writeNodeNoWrap(child, out);
 				}
 				out.println("</vex_fragment>");
 			}
 
 			@Override
-			public void visit(final Element element) {
+			public void visit(final IElement element) {
 				if (whitespacePolicy.isPre(element)) {
 					out.print(indent);
 					writeNodeNoWrap(node, out);
@@ -204,9 +202,8 @@
 				}
 
 				boolean hasBlockChild = false;
-				final List<Element> children = element.getChildElements();
-				for (int i = 0; i < children.size(); i++) {
-					if (whitespacePolicy.isBlock(children.get(i))) {
+				for (final INode child : element.childElements()) {
+					if (whitespacePolicy.isBlock(child)) {
 						hasBlockChild = true;
 						break;
 					}
@@ -236,7 +233,7 @@
 					out.println(">");
 
 					final String childIndent = indent + DocumentWriter.this.indent;
-					for (final Node child : element.children()) {
+					for (final INode child : element.children()) {
 						writeNode(child, out, childIndent);
 					}
 					out.print(indent);
@@ -255,7 +252,7 @@
 			}
 
 			@Override
-			public void visit(final Comment comment) {
+			public void visit(final IComment comment) {
 				out.print(indent);
 				out.println("<!-- ");
 
@@ -274,7 +271,7 @@
 			}
 
 			@Override
-			public void visit(final Text text) {
+			public void visit(final IText text) {
 				final TextWrapper wrapper = new TextWrapper();
 				wrapper.add(escape(node.getText()));
 
@@ -288,17 +285,17 @@
 		});
 	}
 
-	private void writeNodeNoWrap(final Node node, final PrintWriter out) {
+	private void writeNodeNoWrap(final INode node, final PrintWriter out) {
 		node.accept(new BaseNodeVisitor() {
 			@Override
-			public void visit(final Element element) {
+			public void visit(final IElement element) {
 				out.print("<");
 				out.print(element.getPrefixedName());
 				out.print(getNamespaceDeclarationsString(element));
 				out.print(getAttributeString(element));
 				out.print(">");
 
-				for (final Node child : element.children()) {
+				for (final INode child : element.children()) {
 					writeNodeNoWrap(child, out);
 				}
 
@@ -308,20 +305,20 @@
 			}
 
 			@Override
-			public void visit(final Comment comment) {
+			public void visit(final IComment comment) {
 				out.print("<!-- ");
 				out.print(escape(node.getText()));
 				out.print(" -->");
 			}
 
 			@Override
-			public void visit(final Text text) {
+			public void visit(final IText text) {
 				out.print(escape(node.getText()));
 			}
 		});
 	}
 
-	private static String getNamespaceDeclarationsString(final Element element) {
+	private static String getNamespaceDeclarationsString(final IElement element) {
 		final StringBuilder result = new StringBuilder();
 		final String declaredNamespaceURI = element.getDeclaredDefaultNamespaceURI();
 		if (declaredNamespaceURI != null) {
@@ -333,10 +330,10 @@
 		return result.toString();
 	}
 
-	private static void addNode(final Node node, final TextWrapper wrapper) {
+	private static void addNode(final INode node, final TextWrapper wrapper) {
 		node.accept(new BaseNodeVisitor() {
 			@Override
-			public void visit(final Element element) {
+			public void visit(final IElement element) {
 				final boolean elementHasChildren = element.hasChildren();
 
 				final StringBuilder buffer = new StringBuilder();
@@ -351,7 +348,7 @@
 				}
 				wrapper.addNoSplit(buffer.toString());
 
-				for (final Node child : element.children()) {
+				for (final INode child : element.children()) {
 					addNode(child, wrapper);
 				}
 
@@ -361,25 +358,25 @@
 			}
 
 			@Override
-			public void visit(final Comment comment) {
+			public void visit(final IComment comment) {
 				wrapper.addNoSplit("<!-- ");
 				wrapper.add(escape(node.getText()));
 				wrapper.addNoSplit(" -->");
 			}
 
 			@Override
-			public void visit(final Text text) {
+			public void visit(final IText text) {
 				wrapper.add(escape(node.getText()));
 			}
 		});
 	}
 
-	private static String getAttributeString(final Element element) {
-		final Document document = element.getDocument();
-		final Validator validator = document != null ? document.getValidator() : null;
+	private static String getAttributeString(final IElement element) {
+		final IDocument document = element.getDocument();
+		final IValidator validator = document != null ? document.getValidator() : null;
 
 		final StringBuffer result = new StringBuffer();
-		for (final Attribute attribute : element.getAttributes()) {
+		for (final IAttribute attribute : element.getAttributes()) {
 			if (!isAttributeDefaultValueSet(validator, attribute)) {
 				result.append(" ");
 				result.append(attribute.getPrefixedName());
@@ -391,7 +388,7 @@
 		return result.toString();
 	}
 
-	private static boolean isAttributeDefaultValueSet(final Validator validator, final Attribute attribute) {
+	private static boolean isAttributeDefaultValueSet(final IValidator validator, final IAttribute attribute) {
 		if (validator != null) {
 			final AttributeDefinition attributeDefinition = validator.getAttributeDefinition(attribute);
 			if (attributeDefinition != null) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/IWhitespacePolicy.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/IWhitespacePolicy.java
similarity index 84%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/IWhitespacePolicy.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/IWhitespacePolicy.java
index 47ae73f..0c42fd6 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/IWhitespacePolicy.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/IWhitespacePolicy.java
@@ -9,7 +9,10 @@
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - a NULL object
  *******************************************************************************/
-package org.eclipse.vex.core.internal.dom;
+package org.eclipse.vex.core.internal.io;
+
+import org.eclipse.vex.core.dom.INode;
+
 
 /**
  * Determines whitespace policy for document elements. For example, a CSS stylesheet implements a whitespace policy via
@@ -21,11 +24,11 @@
 	 * A NULL object of this type. No blocks and no pre elements.
 	 */
 	IWhitespacePolicy NULL = new IWhitespacePolicy() {
-		public boolean isBlock(final Node node) {
+		public boolean isBlock(final INode node) {
 			return false;
 		}
 
-		public boolean isPre(final Node node) {
+		public boolean isPre(final INode node) {
 			return false;
 		}
 	};
@@ -36,7 +39,7 @@
 	 * @param element
 	 *            Element to test.
 	 */
-	boolean isBlock(Node node);
+	boolean isBlock(INode node);
 
 	/**
 	 * Returns true if the given element is pre-formatted, that is, all of its contained whitespace should be preserved.
@@ -44,5 +47,5 @@
 	 * @param element
 	 *            Element to test.
 	 */
-	boolean isPre(Node node);
+	boolean isPre(INode node);
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/IWhitespacePolicyFactory.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/IWhitespacePolicyFactory.java
similarity index 96%
rename from org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/IWhitespacePolicyFactory.java
rename to org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/IWhitespacePolicyFactory.java
index 4a28684..6eca185 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/IWhitespacePolicyFactory.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/io/IWhitespacePolicyFactory.java
@@ -9,7 +9,7 @@
  *     John Krasnay - initial API and implementation
  *     Florian Thienel - a NULL object
  *******************************************************************************/
-package org.eclipse.vex.core.internal.dom;
+package org.eclipse.vex.core.internal.io;
 
 /**
  * Factory for returning a WhitespacePolicy object given a document type public ID. This is required by DocumentBuilder,
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBlockBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBlockBox.java
index d57f6c7..979ec97 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBlockBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBlockBox.java
@@ -16,6 +16,15 @@
 import java.util.List;
 import java.util.Set;
 
+import org.eclipse.vex.core.dom.BaseNodeVisitorWithResult;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.IComment;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IParent;
+import org.eclipse.vex.core.dom.IPosition;
+import org.eclipse.vex.core.dom.IText;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Color;
 import org.eclipse.vex.core.internal.core.ColorResource;
@@ -25,15 +34,6 @@
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.BaseNodeVisitorWithResult;
-import org.eclipse.vex.core.internal.dom.Comment;
-import org.eclipse.vex.core.internal.dom.ContentRange;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Parent;
-import org.eclipse.vex.core.internal.dom.Position;
-import org.eclipse.vex.core.internal.dom.Text;
 
 /**
  * Base class of block boxes that can contain other block boxes. This class implements the layout method and various
@@ -55,7 +55,7 @@
 	/**
 	 * Element with which we are associated. For anonymous boxes, this is null.
 	 */
-	private final Node node;
+	private final INode node;
 
 	/*
 	 * We cache the top and bottom margins, since they may be affected by our children.
@@ -66,12 +66,12 @@
 	/**
 	 * Start position of an anonymous box. For non-anonymous boxes, this is null.
 	 */
-	private Position startPosition;
+	private IPosition startPosition;
 
 	/**
 	 * End position of an anonymous box. For non-anonymous boxes, this is null.
 	 */
-	private Position endPosition;
+	private IPosition endPosition;
 
 	/**
 	 * Class constructor for non-anonymous boxes.
@@ -83,7 +83,7 @@
 	 * @param node
 	 *            Node associated with this box. anonymous box.
 	 */
-	public AbstractBlockBox(final LayoutContext context, final BlockBox parent, final Node node) {
+	public AbstractBlockBox(final LayoutContext context, final BlockBox parent, final INode node) {
 		this.parent = parent;
 		this.node = node;
 
@@ -112,7 +112,7 @@
 		marginTop = 0;
 		marginBottom = 0;
 
-		final Document doc = context.getDocument();
+		final IDocument doc = context.getDocument();
 		startPosition = doc.createPosition(startOffset);
 		endPosition = doc.createPosition(endOffset);
 	}
@@ -120,14 +120,14 @@
 	/**
 	 * Walks the box tree and returns the nearest enclosing element.
 	 */
-	protected Parent findContainingParent() {
+	protected IParent findContainingParent() {
 		BlockBox box = this;
-		Node node = box.getNode();
-		while (!(node instanceof Parent)) {
+		INode node = box.getNode();
+		while (!(node instanceof IParent)) {
 			box = box.getParent();
 			node = box.getNode();
 		}
-		return (Parent) node;
+		return (IParent) node;
 	}
 
 	/**
@@ -202,13 +202,13 @@
 	}
 
 	@Override
-	public Node getNode() {
+	public INode getNode() {
 		return node;
 	}
 
 	@Override
 	public int getEndOffset() {
-		final Node element = getNode();
+		final INode element = getNode();
 		if (element != null) {
 			return element.getEndOffset();
 		} else if (getEndPosition() != null) {
@@ -228,7 +228,7 @@
 	 */
 	protected int getEstimatedHeight(final LayoutContext context) {
 
-		final Node node = findContainingParent();
+		final INode node = findContainingParent();
 		final Styles styles = context.getStyleSheet().getStyles(node);
 		final int charCount = getEndOffset() - getStartOffset();
 
@@ -390,7 +390,7 @@
 
 	@Override
 	public int getStartOffset() {
-		final Node node = getNode();
+		final INode node = getNode();
 		if (node != null) {
 			return node.getStartOffset() + 1;
 		} else if (getStartPosition() != null) {
@@ -519,8 +519,8 @@
 	 */
 	protected void paintSelectionFrame(final LayoutContext context, final int x, final int y, final boolean selected) {
 
-		final Node node = getNode();
-		final Parent parent = node == null ? null : node.getParent();
+		final INode node = getNode();
+		final IParent parent = node == null ? null : node.getParent();
 
 		final boolean paintFrame = context.isNodeSelected(node) && !context.isNodeSelected(parent);
 
@@ -561,15 +561,15 @@
 		}
 	}
 
-	protected String getSelectionFrameName(final Node node) {
+	protected String getSelectionFrameName(final INode node) {
 		return node.accept(new BaseNodeVisitorWithResult<String>() {
 			@Override
-			public String visit(final Element element) {
+			public String visit(final IElement element) {
 				return element.getPrefixedName();
 			}
 
 			@Override
-			public String visit(final Comment comment) {
+			public String visit(final IComment comment) {
 				return "Comment";
 			}
 		});
@@ -666,14 +666,14 @@
 			pendingInlines.addAll(beforeInlines);
 		}
 
-		final Document document = context.getDocument();
-		final Node node = document.findCommonNode(startOffset, endOffset);
+		final IDocument document = context.getDocument();
+		final INode node = document.findCommonNode(startOffset, endOffset);
 
 		if (startOffset == endOffset) {
 			final int relOffset = startOffset - node.getStartOffset();
 			pendingInlines.add(new PlaceholderBox(context, node, relOffset));
-		} else if (node instanceof Parent) {
-			final BlockInlineIterator iter = new BlockInlineIterator(context, (Parent) node, startOffset, endOffset);
+		} else if (node instanceof IParent) {
+			final BlockInlineIterator iter = new BlockInlineIterator(context, (IParent) node, startOffset, endOffset);
 			while (true) {
 				Object next = iter.next();
 				if (next == null) {
@@ -694,10 +694,10 @@
 					if (isTableChild(context, next)) {
 						// Consume continguous table children and create an
 						// anonymous table.
-						final int tableStartOffset = ((Element) next).getStartOffset();
+						final int tableStartOffset = ((IElement) next).getStartOffset();
 						int tableEndOffset = -1; // dummy to hide warning
 						while (isTableChild(context, next)) {
-							tableEndOffset = ((Element) next).getEndOffset() + 1;
+							tableEndOffset = ((IElement) next).getEndOffset() + 1;
 							next = iter.next();
 						}
 
@@ -709,7 +709,7 @@
 							iter.push(next);
 						}
 					} else { // next is a block box element
-						final Node blockNode = (Node) next;
+						final INode blockNode = (INode) next;
 						blockBoxes.add(context.getBoxFactory().createBox(context, blockNode, this, width));
 					}
 				}
@@ -736,12 +736,12 @@
 	private static class BlockInlineIterator {
 
 		private final LayoutContext context;
-		private final Parent parent;
+		private final IParent parent;
 		private int startOffset;
 		private final int endOffset;
 		private final LinkedList<Object> pushStack = new LinkedList<Object>();
 
-		public BlockInlineIterator(final LayoutContext context, final Parent parent, final int startOffset, final int endOffset) {
+		public BlockInlineIterator(final LayoutContext context, final IParent parent, final int startOffset, final int endOffset) {
 			this.context = context;
 			this.parent = parent;
 			this.startOffset = startOffset;
@@ -757,7 +757,7 @@
 			} else if (startOffset == endOffset) {
 				return null;
 			} else {
-				final Node blockNode = findNextBlockNode(context, parent, startOffset, endOffset);
+				final INode blockNode = findNextBlockNode(context, parent, startOffset, endOffset);
 				if (blockNode == null) {
 					if (startOffset < endOffset) {
 						final ContentRange result = new ContentRange(startOffset, endOffset);
@@ -871,18 +871,18 @@
 	 * @param endOffset
 	 *            The offset at which to end the search.
 	 */
-	private static Node findNextBlockNode(final LayoutContext context, final Parent parent, final int startOffset, final int endOffset) {
-		for (final Node child : parent.children().in(new ContentRange(startOffset, endOffset)).withoutText()) {
-			final Node nextBlockNode = child.accept(new BaseNodeVisitorWithResult<Node>() {
+	private static INode findNextBlockNode(final LayoutContext context, final IParent parent, final int startOffset, final int endOffset) {
+		for (final INode child : parent.children().in(new ContentRange(startOffset, endOffset)).withoutText()) {
+			final INode nextBlockNode = child.accept(new BaseNodeVisitorWithResult<INode>() {
 				@Override
-				public Node visit(final Element element) {
+				public INode visit(final IElement element) {
 					// found?
 					if (!isInline(context, element, parent)) {
 						return element;
 					}
 
 					// recursion
-					final Node fromChild = findNextBlockNode(context, element, startOffset, endOffset);
+					final INode fromChild = findNextBlockNode(context, element, startOffset, endOffset);
 					if (fromChild != null) {
 						return fromChild;
 					}
@@ -891,7 +891,7 @@
 				}
 
 				@Override
-				public Node visit(final Comment comment) {
+				public INode visit(final IComment comment) {
 					if (!isInline(context, comment, parent)) {
 						return comment;
 					}
@@ -906,13 +906,13 @@
 		return null;
 	}
 
-	private static boolean isInline(final LayoutContext context, final Node child, final Node parent) {
+	private static boolean isInline(final LayoutContext context, final INode child, final INode parent) {
 		final String style = displayStyleOf(child, context);
 		final String parentStyle = displayStyleOf(parent, context);
 
 		return child.accept(new BaseNodeVisitorWithResult<Boolean>(false) {
 			@Override
-			public Boolean visit(final Element element) {
+			public Boolean visit(final IElement element) {
 				if (style.equals(CSS.INLINE)) {
 					return true;
 				}
@@ -956,10 +956,10 @@
 			}
 
 			@Override
-			public Boolean visit(final Comment comment) {
+			public Boolean visit(final IComment comment) {
 				final boolean parentIsInline = parent.accept(new BaseNodeVisitorWithResult<Boolean>(false) {
 					@Override
-					public Boolean visit(final Element element) {
+					public Boolean visit(final IElement element) {
 						return parentStyle.equals(CSS.INLINE);
 					};
 				});
@@ -967,33 +967,33 @@
 			}
 
 			@Override
-			public Boolean visit(final Text text) {
+			public Boolean visit(final IText text) {
 				return true;
 			}
 		});
 	}
 
-	private static String displayStyleOf(final Node node, final LayoutContext context) {
+	private static String displayStyleOf(final INode node, final LayoutContext context) {
 		return context.getStyleSheet().getStyles(node).getDisplay();
 	}
 
 	/**
 	 * Return the end position of an anonymous box. The default implementation returns null.
 	 */
-	private Position getEndPosition() {
+	private IPosition getEndPosition() {
 		return endPosition;
 	}
 
 	/**
 	 * Return the start position of an anonymous box. The default implementation returns null.
 	 */
-	private Position getStartPosition() {
+	private IPosition getStartPosition() {
 		return startPosition;
 	}
 
 	private boolean isTableChild(final LayoutContext context, final Object rangeOrElement) {
-		if (rangeOrElement != null && rangeOrElement instanceof Element) {
-			return LayoutUtils.isTableChild(context.getStyleSheet(), (Element) rangeOrElement);
+		if (rangeOrElement != null && rangeOrElement instanceof IElement) {
+			return LayoutUtils.isTableChild(context.getStyleSheet(), (IElement) rangeOrElement);
 		} else {
 			return false;
 		}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBox.java
index 604656c..3efda6a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractBox.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Color;
 import org.eclipse.vex.core.internal.core.ColorResource;
@@ -18,7 +19,6 @@
 import org.eclipse.vex.core.internal.core.Rectangle;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * Base implementation of the <code>Box</code> interface, implementing some common methods.
@@ -70,7 +70,7 @@
 	 * 
 	 * @see org.eclipse.vex.core.internal.layout.Box#getNode()
 	 */
-	public Node getNode() {
+	public INode getNode() {
 		return null;
 	}
 
@@ -106,7 +106,7 @@
 	 * is associated with this box returns all zeros.
 	 */
 	public Insets getInsets(final LayoutContext context, final int containerWidth) {
-		final Node node = getNode();
+		final INode node = getNode();
 		if (node == null) {
 			return Insets.ZERO_INSETS;
 		} else {
@@ -274,7 +274,7 @@
 	 *            If true, the background is filled and the borders are drawn; otherwise, just the background is filled.
 	 *            This is handy when removing the borders when drawing the selection frame.
 	 */
-	protected void drawBox(final LayoutContext context, final Node node, final int x, final int y, final int containerWidth, final boolean drawBorders) {
+	protected void drawBox(final LayoutContext context, final INode node, final int x, final int y, final int containerWidth, final boolean drawBorders) {
 
 		if (node == null) {
 			return;
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockElementBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockElementBox.java
index 620f2a4..8f3a672 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockElementBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockElementBox.java
@@ -15,16 +15,17 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IParent;
 import org.eclipse.vex.core.internal.VEXCorePlugin;
 import org.eclipse.vex.core.internal.core.Drawable;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.core.Rectangle;
 import org.eclipse.vex.core.internal.css.CSS;
+import org.eclipse.vex.core.internal.css.PseudoElement;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Parent;
 
 /**
  * A block box corresponding to a DOM Element. Block boxes lay their children out stacked top to bottom. Block boxes
@@ -53,7 +54,7 @@
 	 * @param node
 	 *            Node to which this box corresponds.
 	 */
-	public BlockElementBox(final LayoutContext context, final BlockBox parent, final Node node) {
+	public BlockElementBox(final LayoutContext context, final BlockBox parent, final INode node) {
 		super(context, parent, node);
 	}
 
@@ -123,7 +124,7 @@
 			start = System.currentTimeMillis();
 		}
 
-		final Node node = getNode();
+		final INode node = getNode();
 		final int width = getWidth();
 
 		final List<Box> childList = new ArrayList<Box>();
@@ -131,13 +132,13 @@
 		final StyleSheet styleSheet = context.getStyleSheet();
 
 		// element and styles for generated boxes
-		Element genElement;
+		PseudoElement genElement;
 		Styles genStyles;
 
 		// :before content
 		List<InlineBox> beforeInlines = null;
-		if (node instanceof Element) { // TODO replace PseudoElement with a more flexible mechanism
-			genElement = context.getStyleSheet().getBeforeElement((Element) node);
+		if (node instanceof IElement) { // TODO replace PseudoElement with a more flexible mechanism
+			genElement = context.getStyleSheet().getBeforeElement((IElement) node);
 			if (genElement != null) {
 				genStyles = styleSheet.getStyles(genElement);
 				if (genStyles.getDisplay().equals(CSS.INLINE)) {
@@ -164,8 +165,8 @@
 		// :after content
 		Box afterBlock = null;
 		List<InlineBox> afterInlines = null;
-		if (node instanceof Element) {
-			genElement = context.getStyleSheet().getAfterElement((Element) node);
+		if (node instanceof IElement) {
+			genElement = context.getStyleSheet().getAfterElement((IElement) node);
 			if (genElement != null) {
 				genStyles = context.getStyleSheet().getStyles(genElement);
 				if (genStyles.getDisplay().equals(CSS.INLINE)) {
@@ -229,7 +230,7 @@
 	/**
 	 * Returns a Drawable that draws a circle-style list item bullet.
 	 */
-	private static InlineBox createCircleBullet(final Node node, final Styles styles) {
+	private static InlineBox createCircleBullet(final INode node, final Styles styles) {
 		final int size = Math.round(0.5f * styles.getFontSize());
 		final int lift = Math.round(0.1f * styles.getFontSize());
 		final Drawable drawable = new Drawable() {
@@ -249,7 +250,7 @@
 	/**
 	 * Returns a Drawable that draws a disc-style list item bullet.
 	 */
-	private static InlineBox createDiscBullet(final Node node, final Styles styles) {
+	private static InlineBox createDiscBullet(final INode node, final Styles styles) {
 		final int size = Math.round(0.5f * styles.getFontSize());
 		final int lift = Math.round(0.1f * styles.getFontSize());
 		final Drawable drawable = new Drawable() {
@@ -267,7 +268,7 @@
 	/**
 	 * Returns a Drawable that draws a square-style list item bullet.
 	 */
-	private static InlineBox createSquareBullet(final Node node, final Styles styles) {
+	private static InlineBox createSquareBullet(final INode node, final Styles styles) {
 		final int size = Math.round(0.5f * styles.getFontSize());
 		final int lift = Math.round(0.1f * styles.getFontSize());
 		final Drawable drawable = new Drawable() {
@@ -303,15 +304,15 @@
 	 * amongst its siblings starting with 1.
 	 */
 	private int getItemNumber() {
-		final Node node = getNode();
-		final Parent parent = node.getParent();
+		final INode node = getNode();
+		final IParent parent = node.getParent();
 
 		if (parent == null) {
 			return 1;
 		}
 
 		int item = 1;
-		for (final Node child : parent.children()) {
+		for (final INode child : parent.children()) {
 			if (child == node) {
 				return item;
 			}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockPseudoElementBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockPseudoElementBox.java
index 69be385..20009eb 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockPseudoElementBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BlockPseudoElementBox.java
@@ -13,23 +13,25 @@
 
 import java.util.List;
 
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.internal.css.PseudoElement;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * Implements a Block
+ * 
+ * XXX REMOVE THIS HACK!!!
  */
 public class BlockPseudoElementBox extends AbstractBox implements BlockBox {
 
-	private final Element pseudoElement;
+	private final PseudoElement pseudoElement;
 	private final BlockBox parent;
 	private final ParagraphBox para;
 
 	private final int marginTop;
 	private final int marginBottom;
 
-	public BlockPseudoElementBox(final LayoutContext context, final Element pseudoElement, final BlockBox parent, final int width) {
+	public BlockPseudoElementBox(final LayoutContext context, final PseudoElement pseudoElement, final BlockBox parent, final int width) {
 
 		this.pseudoElement = pseudoElement;
 		this.parent = parent;
@@ -66,7 +68,7 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getNode()
 	 */
 	@Override
-	public Node getNode() {
+	public INode getNode() {
 		return pseudoElement;
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Box.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Box.java
index 1c06434..eaf2ce5 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Box.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/Box.java
@@ -10,9 +10,9 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Insets;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * Represents a rectangular area in the layout. The height and width of the box are measured from the inner edges of the
@@ -48,7 +48,7 @@
 	 * Returns the Element with which this box is associated, or null if there is no such box. The box may directly
 	 * represent the Element, or simply use it for formatting information.
 	 */
-	public Node getNode();
+	public INode getNode();
 
 	/**
 	 * Returns the offset of the end of the content that the box covers.
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BoxFactory.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BoxFactory.java
index 0a6feff..e20c951 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BoxFactory.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/BoxFactory.java
@@ -12,7 +12,7 @@
 
 import java.io.Serializable;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 
 /**
  * Interface to an object that creates boxes from elements. Implementations of this interface must be serializable.
@@ -31,6 +31,6 @@
 	 * @param containerWidth
 	 *            Width of the box to be created.
 	 */
-	public Box createBox(LayoutContext context, Node node, BlockBox parent, int containerWidth);
+	public Box createBox(LayoutContext context, INode node, BlockBox parent, int containerWidth);
 
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CommentBlockBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CommentBlockBox.java
index c939e2f..b30d824 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CommentBlockBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CommentBlockBox.java
@@ -13,8 +13,8 @@
 import java.util.ArrayList;

 import java.util.List;

 

+import org.eclipse.vex.core.dom.INode;

 import org.eclipse.vex.core.internal.VEXCorePlugin;

-import org.eclipse.vex.core.internal.dom.Node;

 

 /**

  * @author Florian Thienel

@@ -24,7 +24,7 @@
 	private static final String AFTER_TEXT = "-->";

 	private static final String BEFORE_TEXT = "<!--";

 

-	public CommentBlockBox(final LayoutContext context, final BlockBox parent, final Node node) {

+	public CommentBlockBox(final LayoutContext context, final BlockBox parent, final INode node) {

 		super(context, parent, node);

 	}

 

@@ -40,7 +40,7 @@
 			start = System.currentTimeMillis();

 		}

 

-		final Node node = getNode();

+		final INode node = getNode();

 		final int width = getWidth();

 

 		final List<Box> result = new ArrayList<Box>();

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CssBoxFactory.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CssBoxFactory.java
index 15ff461..9a983ba 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CssBoxFactory.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CssBoxFactory.java
@@ -10,10 +10,10 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.dom.IComment;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Comment;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * Implementation of the BoxFactory interface that returns boxes that represent CSS semantics.
@@ -22,9 +22,9 @@
 
 	private static final long serialVersionUID = -6882526795866485074L;
 
-	public Box createBox(final LayoutContext context, final Node node, final BlockBox parentBox, final int containerWidth) {
+	public Box createBox(final LayoutContext context, final INode node, final BlockBox parentBox, final int containerWidth) {
 		final Styles styles = context.getStyleSheet().getStyles(node);
-		if (node instanceof Comment) {
+		if (node instanceof IComment) {
 			return new CommentBlockBox(context, parentBox, node);
 		} else if (styles.getDisplay().equals(CSS.TABLE)) {
 			return new TableBox(context, parentBox, node);
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DocumentTextBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DocumentTextBox.java
index a47c603..9284f34 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DocumentTextBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DocumentTextBox.java
@@ -13,12 +13,12 @@
 import java.text.MessageFormat;
 
 import org.eclipse.core.runtime.Assert;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.ColorResource;
 import org.eclipse.vex.core.internal.core.FontResource;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.ContentRange;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * A TextBox that gets its text from the document. Represents text which is editable within the VexWidget.
@@ -40,7 +40,7 @@
 	 * @param endOffset
 	 *            end offset of the text
 	 */
-	public DocumentTextBox(final LayoutContext context, final Node node, final int startOffset, final int endOffset) {
+	public DocumentTextBox(final LayoutContext context, final INode node, final int startOffset, final int endOffset) {
 		super(node);
 		Assert.isTrue(startOffset <= endOffset, MessageFormat.format("DocumentTextBox for {2}: startOffset {0} > endOffset {1}", startOffset, endOffset, node));
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DrawableBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DrawableBox.java
index 9113f7b..36e7551 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DrawableBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/DrawableBox.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.ColorResource;
 import org.eclipse.vex.core.internal.core.Drawable;
 import org.eclipse.vex.core.internal.core.FontMetrics;
@@ -17,7 +18,6 @@
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.core.Rectangle;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * An inline box that draws a Drawable object. The drawable is drawn relative to the text baseline, therefore it should
@@ -30,7 +30,7 @@
 	public static final byte END_MARKER = 2;
 
 	private final Drawable drawable;
-	private final Node node;
+	private final INode node;
 	private final byte marker;
 
 	/**
@@ -41,7 +41,7 @@
 	 * @param node
 	 *            Node whose styles determine the color of the drawable.
 	 */
-	public DrawableBox(final Drawable drawable, final Node node) {
+	public DrawableBox(final Drawable drawable, final INode node) {
 		this(drawable, node, NO_MARKER);
 	}
 
@@ -56,7 +56,7 @@
 	 * @param marker
 	 *            which marker should be drawn. Must be one of NO_MARKER, START_MARKER, or END_MARKER.
 	 */
-	public DrawableBox(final Drawable drawable, final Node node, final byte marker) {
+	public DrawableBox(final Drawable drawable, final INode node, final byte marker) {
 		this.drawable = drawable;
 		this.node = node;
 		this.marker = marker;
@@ -76,7 +76,7 @@
 	 * Returns the node that controls the styling for this text box.
 	 */
 	@Override
-	public Node getNode() {
+	public INode getNode() {
 		return node;
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrRangeCallback.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrRangeCallback.java
index 9b3a581..24ce745 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrRangeCallback.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ElementOrRangeCallback.java
@@ -10,11 +10,11 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Parent;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.IParent;
 
 public interface ElementOrRangeCallback {
-	public void onElement(Element child, String displayStyle);
+	public void onElement(IElement child, String displayStyle);
 
-	public void onRange(Parent parent, int startOffset, int endOffset);
+	public void onRange(IParent parent, int startOffset, int endOffset);
 }
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ImageBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ImageBox.java
index 897c8d9..c671497 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ImageBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ImageBox.java
@@ -2,16 +2,16 @@
 

 import java.net.URL;

 

+import org.eclipse.vex.core.dom.INode;

 import org.eclipse.vex.core.internal.core.Image;

 import org.eclipse.vex.core.internal.core.Point;

 import org.eclipse.vex.core.internal.css.Styles;

-import org.eclipse.vex.core.internal.dom.Node;

 

 public class ImageBox extends AbstractInlineBox {

 

 	private final Image image;

 

-	public static ImageBox create(final Node node, final LayoutContext context, final int maxWidth) {

+	public static ImageBox create(final INode node, final LayoutContext context, final int maxWidth) {

 		if (node == null) {

 			return null;

 		}

@@ -51,7 +51,7 @@
 		return Math.round(1f * scaled / current * opposite);

 	}

 

-	public static ImageBox createWithHeight(final Node node, final LayoutContext context, final int maxHeight) {

+	public static ImageBox createWithHeight(final INode node, final LayoutContext context, final int maxHeight) {

 		if (node == null) {

 			return null;

 		}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineElementBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineElementBox.java
index 8869dc3..b8746ad 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineElementBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineElementBox.java
@@ -14,19 +14,20 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.vex.core.dom.BaseNodeVisitor;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.IComment;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IText;
 import org.eclipse.vex.core.internal.core.Drawable;
 import org.eclipse.vex.core.internal.core.FontMetrics;
 import org.eclipse.vex.core.internal.core.FontResource;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.core.Rectangle;
 import org.eclipse.vex.core.internal.css.CSS;
+import org.eclipse.vex.core.internal.css.PseudoElement;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.BaseNodeVisitor;
-import org.eclipse.vex.core.internal.dom.Comment;
-import org.eclipse.vex.core.internal.dom.ContentRange;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Text;
 
 /**
  * An inline box that represents an inline element. This box is responsible for creating and laying out its child boxes.
@@ -35,7 +36,7 @@
 
 	private static final String COMMENT_AFTER_TEXT = "-->";
 	private static final String COMMENT_BEFORE_TEXT = "<!--";
-	private final Node node;
+	private final INode node;
 	private final InlineBox[] children;
 	private InlineBox firstContentChild = null;
 	private InlineBox lastContentChild = null;
@@ -54,7 +55,7 @@
 	 * @param endOffset
 	 *            End offset of the range being rendered, which may be arbitrarily after or inside the element.
 	 */
-	private InlineElementBox(final LayoutContext context, final Node node, final int startOffset, final int endOffset) {
+	private InlineElementBox(final LayoutContext context, final INode node, final int startOffset, final int endOffset) {
 
 		this.node = node;
 
@@ -71,8 +72,7 @@
 			}
 
 			// :before content
-			final Element beforeElement;
-			beforeElement = context.getStyleSheet().getBeforeElement((Element) node);
+			final PseudoElement beforeElement = context.getStyleSheet().getBeforeElement((IElement) node);
 			if (beforeElement != null) {
 				childList.addAll(LayoutUtils.createGeneratedInlines(context, beforeElement));
 			}
@@ -100,7 +100,7 @@
 			childList.add(createRightMarker(node, styles));
 
 			// :after content
-			final Element afterElement = context.getStyleSheet().getAfterElement((Element) node);
+			final PseudoElement afterElement = context.getStyleSheet().getAfterElement((IElement) node);
 			if (afterElement != null) {
 				childList.addAll(LayoutUtils.createGeneratedInlines(context, afterElement));
 			}
@@ -127,7 +127,7 @@
 	 * @param children
 	 *            Child boxes.
 	 */
-	private InlineElementBox(final LayoutContext context, final Node node, final InlineBox[] children) {
+	private InlineElementBox(final LayoutContext context, final INode node, final InlineBox[] children) {
 		this.node = node;
 		this.children = children;
 		layout(context);
@@ -160,7 +160,7 @@
 	 * Returns the element associated with this box.
 	 */
 	@Override
-	public Node getNode() {
+	public INode getNode() {
 		return node;
 	}
 
@@ -266,16 +266,16 @@
 	 *            The end of the range to convert to inline boxes.
 	 * @return
 	 */
-	static InlineBoxes createInlineBoxes(final LayoutContext context, final Node node, final ContentRange range) {
+	static InlineBoxes createInlineBoxes(final LayoutContext context, final INode node, final ContentRange range) {
 		final InlineBoxes result = new InlineBoxes();
 
 		node.accept(new BaseNodeVisitor() {
 			@Override
-			public void visit(final Element element) {
-				for (final Node childNode : element.children().in(range)) {
+			public void visit(final IElement element) {
+				for (final INode childNode : element.children().in(range)) {
 					childNode.accept(new BaseNodeVisitor() {
 						@Override
-						public void visit(final Element element) {
+						public void visit(final IElement element) {
 							final InlineBox placeholder = new PlaceholderBox(context, node, element.getStartOffset() - node.getStartOffset());
 							result.boxes.add(placeholder);
 							if (result.firstContentBox == null) {
@@ -286,7 +286,7 @@
 						}
 
 						@Override
-						public void visit(final Comment comment) {
+						public void visit(final IComment comment) {
 							final PlaceholderBox placeholder = new PlaceholderBox(context, node, comment.getStartOffset() - node.getStartOffset());
 							result.boxes.add(placeholder);
 							if (result.firstContentBox == null) {
@@ -304,7 +304,7 @@
 						};
 
 						@Override
-						public void visit(final Text text) {
+						public void visit(final IText text) {
 							final ContentRange boxRange = range.intersection(text.getRange());
 							final InlineBox child = new DocumentTextBox(context, node, boxRange.getStartOffset(), boxRange.getEndOffset());
 							addChildInlineBox(result, child);
@@ -329,7 +329,7 @@
 
 	// ========================================================== PRIVATE
 
-	private static InlineBox createLeftMarker(final Node node, final Styles styles) {
+	private static InlineBox createLeftMarker(final INode node, final Styles styles) {
 		final int size = Math.round(0.5f * styles.getFontSize());
 		final int lift = Math.round(0.1f * styles.getFontSize());
 		final Drawable drawable = new Drawable() {
@@ -349,7 +349,7 @@
 		return new DrawableBox(drawable, node, DrawableBox.START_MARKER);
 	}
 
-	private static InlineBox createRightMarker(final Node node, final Styles styles) {
+	private static InlineBox createRightMarker(final INode node, final Styles styles) {
 		final int size = Math.round(0.5f * styles.getFontSize());
 		final int lift = Math.round(0.1f * styles.getFontSize());
 		final Drawable drawable = new Drawable() {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutContext.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutContext.java
index 3914de8..778cdfc 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutContext.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutContext.java
@@ -16,11 +16,11 @@
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.VEXCorePlugin;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.StyleSheet;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * Encapsulation of all the resources needed to create a box tree. Most operations on a box tree, such as creating the
@@ -29,7 +29,7 @@
 public class LayoutContext {
 
 	private BoxFactory boxFactory;
-	private Document document;
+	private IDocument document;
 	private Graphics graphics;
 	private StyleSheet styleSheet;
 	private int selectionStart;
@@ -52,7 +52,7 @@
 	/**
 	 * Returns the document being layed out.
 	 */
-	public Document getDocument() {
+	public IDocument getDocument() {
 		return document;
 	}
 
@@ -84,7 +84,7 @@
 	 * @param node
 	 *            Node to test. May be null, in which case this method returns false.
 	 */
-	public boolean isNodeSelected(final Node node) {
+	public boolean isNodeSelected(final INode node) {
 		return node != null && node.getStartOffset() >= getSelectionStart() && node.getEndOffset() + 1 <= getSelectionEnd();
 	}
 
@@ -105,7 +105,7 @@
 	/**
 	 * Sets the document being layed out.
 	 */
-	public void setDocument(final Document document) {
+	public void setDocument(final IDocument document) {
 		this.document = document;
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java
index 34f3bcf..2385cf2 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java
@@ -16,13 +16,13 @@
 import java.util.List;
 import java.util.Set;
 
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IParent;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.ContentRange;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Parent;
 
 /**
  * Tools for layout and rendering of CSS-styled boxes
@@ -37,7 +37,7 @@
 	 * @param pseudoElement
 	 *            Element representing the generated content.
 	 */
-	public static List<InlineBox> createGeneratedInlines(final LayoutContext context, final Element pseudoElement) {
+	public static List<InlineBox> createGeneratedInlines(final LayoutContext context, final IElement pseudoElement) {
 		final String text = getGeneratedContent(context, pseudoElement);
 		final List<InlineBox> list = new ArrayList<InlineBox>();
 		if (text.length() > 0) {
@@ -55,8 +55,8 @@
 	 *            Offset to test.
 	 */
 	public static boolean elementOrRangeContains(final Object elementOrRange, final int offset) {
-		if (elementOrRange instanceof Element) {
-			return ((Element) elementOrRange).containsOffset(offset);
+		if (elementOrRange instanceof IElement) {
+			return ((IElement) elementOrRange).containsOffset(offset);
 		} else {
 			return ((ContentRange) elementOrRange).contains(offset);
 		}
@@ -70,7 +70,7 @@
 	 * @param pseudoElement
 	 *            PseudoElement for which the generated content is to be returned.
 	 */
-	private static String getGeneratedContent(final LayoutContext context, final Element pseudoElement) {
+	private static String getGeneratedContent(final LayoutContext context, final IElement pseudoElement) {
 		final Styles styles = context.getStyleSheet().getStyles(pseudoElement);
 		final List<String> content = styles.getContent();
 		final StringBuffer sb = new StringBuffer();
@@ -99,26 +99,25 @@
 	 *            DisplayStyleCallback through which the caller is notified of matching elements and non-matching
 	 *            ranges.
 	 */
-	public static void iterateChildrenByDisplayStyle(final StyleSheet styleSheet, final Set<String> displayStyles, final Parent parent, final int startOffset, final int endOffset,
+	public static void iterateChildrenByDisplayStyle(final StyleSheet styleSheet, final Set<String> displayStyles, final IParent parent, final int startOffset, final int endOffset,
 			final ElementOrRangeCallback callback) {
 
-		final List<Node> nonMatching = new ArrayList<Node>();
+		final List<INode> nonMatching = new ArrayList<INode>();
 
-		for (final Node node : parent.children()) {
+		for (final INode node : parent.children()) {
 			if (node.getEndOffset() <= startOffset) {
 				continue;
 			} else if (node.getStartOffset() >= endOffset) {
 				break;
 			} else {
-
-				if (node instanceof Element) {
-					final Element childElement = (Element) node;
+				if (node instanceof IElement) {
+					final IElement childElement = (IElement) node;
 					final String display = styleSheet.getStyles(childElement).getDisplay();
 					if (displayStyles.contains(display)) {
 						if (!nonMatching.isEmpty()) {
-							final Node firstNode = nonMatching.get(0);
-							final Node lastNode = nonMatching.get(nonMatching.size() - 1);
-							if (lastNode instanceof Element) {
+							final INode firstNode = nonMatching.get(0);
+							final INode lastNode = nonMatching.get(nonMatching.size() - 1);
+							if (lastNode instanceof IElement) {
 								callback.onRange(parent, firstNode.getStartOffset(), lastNode.getEndOffset() + 1);
 							} else {
 								callback.onRange(parent, firstNode.getStartOffset(), lastNode.getEndOffset());
@@ -136,9 +135,9 @@
 		}
 
 		if (!nonMatching.isEmpty()) {
-			final Node firstNode = nonMatching.get(0);
-			final Node lastNode = nonMatching.get(nonMatching.size() - 1);
-			if (lastNode instanceof Element) {
+			final INode firstNode = nonMatching.get(0);
+			final INode lastNode = nonMatching.get(nonMatching.size() - 1);
+			if (lastNode instanceof IElement) {
 				callback.onRange(parent, firstNode.getStartOffset(), lastNode.getEndOffset() + 1);
 			} else {
 				callback.onRange(parent, firstNode.getStartOffset(), lastNode.getEndOffset());
@@ -161,7 +160,7 @@
 	 *            DisplayStyleCallback through which the caller is notified of matching elements and non-matching
 	 *            ranges.
 	 */
-	public static void iterateChildrenByDisplayStyle(final StyleSheet styleSheet, final Set<String> displayStyles, final Element table, final ElementOrRangeCallback callback) {
+	public static void iterateChildrenByDisplayStyle(final StyleSheet styleSheet, final Set<String> displayStyles, final IElement table, final ElementOrRangeCallback callback) {
 		iterateChildrenByDisplayStyle(styleSheet, displayStyles, table, table.getStartOffset() + 1, table.getEndOffset(), callback);
 	}
 
@@ -173,15 +172,15 @@
 	 * @param element
 	 *            Element to test.
 	 */
-	public static boolean isTableChild(final StyleSheet styleSheet, final Element element) {
+	public static boolean isTableChild(final StyleSheet styleSheet, final IElement element) {
 		final String display = styleSheet.getStyles(element).getDisplay();
 		return TABLE_CHILD_STYLES.contains(display);
 	}
 
-	public static void iterateTableRows(final StyleSheet styleSheet, final Parent element, final int startOffset, final int endOffset, final ElementOrRangeCallback callback) {
+	public static void iterateTableRows(final StyleSheet styleSheet, final IParent element, final int startOffset, final int endOffset, final ElementOrRangeCallback callback) {
 
 		iterateChildrenByDisplayStyle(styleSheet, NON_ROW_STYLES, element, startOffset, endOffset, new ElementOrRangeCallback() {
-			public void onElement(final Element child, final String displayStyle) {
+			public void onElement(final IElement child, final String displayStyle) {
 				if (displayStyle.equals(CSS.TABLE_ROW_GROUP) || displayStyle.equals(CSS.TABLE_HEADER_GROUP) || displayStyle.equals(CSS.TABLE_FOOTER_GROUP)) {
 
 					// iterate rows in group
@@ -191,7 +190,7 @@
 				}
 			}
 
-			public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				// iterate over rows in range
 				iterateChildrenByDisplayStyle(styleSheet, ROW_STYLES, element, startOffset, endOffset, callback);
 			}
@@ -199,11 +198,11 @@
 
 	}
 
-	public static void iterateTableCells(final StyleSheet styleSheet, final Parent element, final int startOffset, final int endOffset, final ElementOrRangeCallback callback) {
+	public static void iterateTableCells(final StyleSheet styleSheet, final IParent element, final int startOffset, final int endOffset, final ElementOrRangeCallback callback) {
 		iterateChildrenByDisplayStyle(styleSheet, CELL_STYLES, element, startOffset, endOffset, callback);
 	}
 
-	public static void iterateTableCells(final StyleSheet styleSheet, final Parent row, final ElementOrRangeCallback callback) {
+	public static void iterateTableCells(final StyleSheet styleSheet, final IParent row, final ElementOrRangeCallback callback) {
 		iterateChildrenByDisplayStyle(styleSheet, CELL_STYLES, row, row.getStartOffset(), row.getEndOffset(), callback);
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LineBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LineBox.java
index c361922..012c848 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LineBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LineBox.java
@@ -10,14 +10,14 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 
 /**
  * Represents a line of text and inline images.
  */
 public class LineBox extends CompositeInlineBox {
 
-	private final Node node;
+	private final INode node;
 	private final InlineBox[] children;
 	private InlineBox firstContentChild = null;
 	private InlineBox lastContentChild = null;
@@ -31,7 +31,7 @@
 	 * @param children
 	 *            InlineBoxes that make up this line.
 	 */
-	public LineBox(final LayoutContext context, final Node node, final InlineBox[] children) {
+	public LineBox(final LayoutContext context, final INode node, final InlineBox[] children) {
 
 		this.node = node;
 		this.children = children;
@@ -73,7 +73,7 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getNode()
 	 */
 	@Override
-	public Node getNode() {
+	public INode getNode() {
 		return node;
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ParagraphBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ParagraphBox.java
index 83c4e70..27e4ae7 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ParagraphBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/ParagraphBox.java
@@ -14,10 +14,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * A box that wraps inline content into a paragraph.
@@ -58,7 +58,7 @@
 	 * @param width
 	 *            width to which the paragraph is to be wrapped
 	 */
-	public static ParagraphBox create(final LayoutContext context, final Node node, final List<InlineBox> inlines, final int width) {
+	public static ParagraphBox create(final LayoutContext context, final INode node, final List<InlineBox> inlines, final int width) {
 		final InlineBox[] array = inlines.toArray(new InlineBox[inlines.size()]);
 		return create(context, node, array, width);
 	}
@@ -75,7 +75,7 @@
 	 * @param width
 	 *            width to which the paragraph is to be wrapped.
 	 */
-	public static ParagraphBox create(final LayoutContext context, final Node node, final InlineBox[] inlines, final int width) {
+	public static ParagraphBox create(final LayoutContext context, final INode node, final InlineBox[] inlines, final int width) {
 
 		// lines is the list of LineBoxes we are creating
 		final List<Box> lines = new ArrayList<Box>();
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/PlaceholderBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/PlaceholderBox.java
index 7561ee3..083a33e 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/PlaceholderBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/PlaceholderBox.java
@@ -10,19 +10,19 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.FontMetrics;
 import org.eclipse.vex.core.internal.core.FontResource;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * A zero-width box that represents a single offset in the document.
  */
 public class PlaceholderBox extends AbstractInlineBox {
 
-	private final Node node;
+	private final INode node;
 	private final int relOffset;
 	private final int textTop;
 	private final int baseline;
@@ -38,7 +38,7 @@
 	 * @param relOffset
 	 *            Offset of the placeholder, relative to the start of the element.
 	 */
-	public PlaceholderBox(final LayoutContext context, final Node node, final int relOffset) {
+	public PlaceholderBox(final LayoutContext context, final INode node, final int relOffset) {
 
 		this.node = node;
 		this.relOffset = relOffset;
@@ -88,7 +88,7 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getNode()
 	 */
 	@Override
-	public Node getNode() {
+	public INode getNode() {
 		return node;
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/RootBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/RootBox.java
index ae6fd76..90c4efb 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/RootBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/RootBox.java
@@ -10,19 +10,19 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.VEXCorePlugin;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Insets;
 import org.eclipse.vex.core.internal.core.Rectangle;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * A wrapper for the top level <code>BlockElementBox</code> that applies its margins.
  */
 public class RootBox extends AbstractBox implements BlockBox {
 
-	private final Document document;
+	private final IDocument document;
 	private final BlockElementBox childBox;
 	private final Box[] children = new Box[1];
 
@@ -36,7 +36,7 @@
 	 * @param width
 	 *            width of this box
 	 */
-	public RootBox(final LayoutContext context, final Document document, final int width) {
+	public RootBox(final LayoutContext context, final IDocument document, final int width) {
 		this.document = document;
 		setWidth(width);
 
@@ -68,7 +68,7 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getNode()
 	 */
 	@Override
-	public Node getNode() {
+	public INode getNode() {
 		return document;
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/StaticTextBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/StaticTextBox.java
index b3d784f..214a99d 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/StaticTextBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/StaticTextBox.java
@@ -10,11 +10,11 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.ColorResource;
 import org.eclipse.vex.core.internal.core.FontResource;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * A TextBox representing a static string. Represents text which is not editable within the VexWidget, such as
@@ -39,7 +39,7 @@
 	 * @param text
 	 *            Static text to display
 	 */
-	public StaticTextBox(final LayoutContext context, final Node node, final String text) {
+	public StaticTextBox(final LayoutContext context, final INode node, final String text) {
 		this(context, node, text, NO_MARKER);
 		if (text.length() == 0) {
 			throw new IllegalArgumentException("StaticTextBox cannot have an empty text string.");
@@ -61,7 +61,7 @@
 	 *            START_MARKER or END_MARKER, depending on whether the text represents the start sentinel or the end
 	 *            sentinel of the element
 	 */
-	public StaticTextBox(final LayoutContext context, final Node node, final String text, final byte marker) {
+	public StaticTextBox(final LayoutContext context, final INode node, final String text, final byte marker) {
 		super(node);
 		this.text = text;
 		this.marker = marker;
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBodyBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBodyBox.java
index 9669d2a..ca3cba7 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBodyBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBodyBox.java
@@ -16,11 +16,11 @@
 import java.util.List;
 import java.util.Set;
 
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.IParent;
 import org.eclipse.vex.core.internal.core.Insets;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Parent;
 
 /**
  * An anonymous box that contains the table row groups for a table. This box is generated by a TableBox and assumes the
@@ -43,11 +43,11 @@
 		final List<Box> children = new ArrayList<Box>();
 
 		iterateChildrenByDisplayStyle(context.getStyleSheet(), childDisplayStyles, new ElementOrRangeCallback() {
-			public void onElement(final Element child, final String displayStyle) {
+			public void onElement(final IElement child, final String displayStyle) {
 				children.add(new TableRowGroupBox(context, TableBodyBox.this, child));
 			}
 
-			public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				children.add(new TableRowGroupBox(context, TableBodyBox.this, startOffset, endOffset));
 			}
 		});
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBox.java
index 52f9d95..9350fe4 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableBox.java
@@ -16,13 +16,13 @@
 import java.util.List;
 import java.util.Set;
 
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IParent;
 import org.eclipse.vex.core.internal.core.Insets;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Parent;
 
 /**
  * Box that lays out a table.
@@ -35,7 +35,7 @@
 	 * @param node
 	 *            Element represented by this box.
 	 */
-	public TableBox(final LayoutContext context, final BlockBox parent, final Node node) {
+	public TableBox(final LayoutContext context, final BlockBox parent, final INode node) {
 		super(context, parent, node);
 	}
 
@@ -55,11 +55,11 @@
 		final List<Box> children = new ArrayList<Box>();
 
 		iterateChildrenByDisplayStyle(context.getStyleSheet(), captionOrColumnStyles, new ElementOrRangeCallback() {
-			public void onElement(final Element child, final String displayStyle) {
+			public void onElement(final IElement child, final String displayStyle) {
 				children.add(new BlockElementBox(context, TableBox.this, child));
 			}
 
-			public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				children.add(new TableBodyBox(context, TableBox.this, startOffset, endOffset));
 			}
 		});
@@ -143,11 +143,11 @@
 			count = 0;
 		}
 
-		public void onElement(final Element child, final String displayStyle) {
+		public void onElement(final IElement child, final String displayStyle) {
 			count++;
 		}
 
-		public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+		public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 			count++;
 		}
 
@@ -159,20 +159,20 @@
 	 */
 	private int computeColumnCount(final LayoutContext context) {
 
-		final Parent tableElement = findContainingParent();
+		final IParent tableElement = findContainingParent();
 		final int[] columnCounts = new int[1]; // work around Java's insistence
 												// on final
 		columnCounts[0] = 0;
 		final StyleSheet styleSheet = context.getStyleSheet();
 		final CountingCallback callback = new CountingCallback();
 		LayoutUtils.iterateTableRows(styleSheet, tableElement, getStartOffset(), getEndOffset(), new ElementOrRangeCallback() {
-			public void onElement(final Element child, final String displayStyle) {
+			public void onElement(final IElement child, final String displayStyle) {
 				LayoutUtils.iterateTableCells(styleSheet, child, callback);
 				columnCounts[0] = Math.max(columnCounts[0], callback.getCount());
 				callback.reset();
 			}
 
-			public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				LayoutUtils.iterateTableCells(styleSheet, parent, startOffset, endOffset, callback);
 				columnCounts[0] = Math.max(columnCounts[0], callback.getCount());
 				callback.reset();
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableCellBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableCellBox.java
index 48c765d..13361c3 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableCellBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableCellBox.java
@@ -13,8 +13,8 @@
 
 import java.util.List;
 
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Element;
 
 /**
  * Represents an element with display:table-cell, or a generated, anonymous table cell.
@@ -31,7 +31,7 @@
 	 * @param element
 	 *            Element with which this box is associated.
 	 */
-	public TableCellBox(final LayoutContext context, final BlockBox parent, final Element element, final int width) {
+	public TableCellBox(final LayoutContext context, final BlockBox parent, final IElement element, final int width) {
 		super(context, parent, element);
 		final Styles styles = context.getStyleSheet().getStyles(element);
 		setWidth(width - styles.getBorderLeftWidth() - styles.getPaddingLeft().get(parent.getWidth()) - styles.getPaddingRight().get(parent.getWidth()) - styles.getBorderRightWidth());
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowBox.java
index 6659ac8..2aa90eb 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowBox.java
@@ -14,17 +14,17 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.IParent;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Insets;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Parent;
 
 /**
  * Box representing a row in a table.
  */
 public class TableRowBox extends AbstractBlockBox {
 
-	public TableRowBox(final LayoutContext context, final TableRowGroupBox parent, final Element element) {
+	public TableRowBox(final LayoutContext context, final TableRowGroupBox parent, final IElement element) {
 		super(context, parent, element);
 	}
 
@@ -37,17 +37,17 @@
 
 		final List<Box> children = new ArrayList<Box>();
 
-		final Parent parent = findContainingParent();
+		final IParent parent = findContainingParent();
 		final int[] widths = getTableBox().getColumnWidths();
 
 		LayoutUtils.iterateTableCells(context.getStyleSheet(), parent, getStartOffset(), getEndOffset(), new ElementOrRangeCallback() {
 			private int column = 0;
 
-			public void onElement(final Element child, final String displayStyle) {
+			public void onElement(final IElement child, final String displayStyle) {
 				children.add(new TableCellBox(context, TableRowBox.this, child, widths[column++]));
 			}
 
-			public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				children.add(new TableCellBox(context, TableRowBox.this, startOffset, endOffset, widths[column++]));
 			}
 		});
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowGroupBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowGroupBox.java
index dbb079f..65c9988 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowGroupBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TableRowGroupBox.java
@@ -16,12 +16,12 @@
 import java.util.List;
 import java.util.Set;
 
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IParent;
 import org.eclipse.vex.core.internal.core.Insets;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Parent;
 
 /**
  * Container for TableRowBox objects. May correspond to an element with display:table-row-group,
@@ -39,7 +39,7 @@
 	 * @param node
 	 *            Node that generated this box.
 	 */
-	public TableRowGroupBox(final LayoutContext context, final BlockBox parent, final Node node) {
+	public TableRowGroupBox(final LayoutContext context, final BlockBox parent, final INode node) {
 		super(context, parent, node);
 	}
 
@@ -71,11 +71,11 @@
 		final List<Box> children = new ArrayList<Box>();
 
 		iterateChildrenByDisplayStyle(context.getStyleSheet(), childDisplayStyles, new ElementOrRangeCallback() {
-			public void onElement(final Element child, final String displayStyle) {
+			public void onElement(final IElement child, final String displayStyle) {
 				children.add(new TableRowBox(context, TableRowGroupBox.this, child));
 			}
 
-			public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				children.add(new TableRowBox(context, TableRowGroupBox.this, startOffset, endOffset));
 			}
 		});
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextBox.java
index 4738dc4..6a6ef44 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/TextBox.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.ColorResource;
 import org.eclipse.vex.core.internal.core.FontMetrics;
@@ -17,7 +18,6 @@
 import org.eclipse.vex.core.internal.core.FontSpec;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.Node;
 
 /**
  * An inline box containing text. The <code>getText</code> and <code>splitAt</code> methods are abstract and must be
@@ -25,7 +25,7 @@
  */
 public abstract class TextBox extends AbstractInlineBox implements InlineBox {
 
-	private final Node node;
+	private final INode node;
 	private int baseline;
 
 	public static final char NEWLINE_CHAR = 0xa;
@@ -37,7 +37,7 @@
 	 * @param node
 	 *            Node containing the text. This is used for styling information.
 	 */
-	public TextBox(final Node node) {
+	public TextBox(final INode node) {
 		this.node = node;
 	}
 
@@ -95,7 +95,7 @@
 	 * Returns the node that controls the styling for this text box.
 	 */
 	@Override
-	public Node getNode() {
+	public INode getNode() {
 		return node;
 	}
 
@@ -137,7 +137,7 @@
 		final Graphics g = context.getGraphics();
 
 		boolean inSelectedBlock = false;
-		Node e = getNode();
+		INode e = getNode();
 		while (e != null) {
 			final Styles styles = context.getStyleSheet().getStyles(e);
 			if (styles.isBlock()) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeAttributeEdit.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeAttributeEdit.java
index ff29762..34d04b8 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeAttributeEdit.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeAttributeEdit.java
@@ -1,17 +1,17 @@
 package org.eclipse.vex.core.internal.undo;

 

 import org.eclipse.core.runtime.QualifiedName;

-import org.eclipse.vex.core.internal.dom.DocumentValidationException;

-import org.eclipse.vex.core.internal.dom.Element;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IElement;

 

 public class ChangeAttributeEdit implements IUndoableEdit {

 

-	private final Element element;

+	private final IElement element;

 	private final QualifiedName attributeName;

 	private final String oldValue;

 	private final String newValue;

 

-	public ChangeAttributeEdit(final Element element, final QualifiedName attributeName, final String oldValue, final String newValue) {

+	public ChangeAttributeEdit(final IElement element, final QualifiedName attributeName, final String oldValue, final String newValue) {

 		this.element = element;

 		this.attributeName = attributeName;

 		this.oldValue = oldValue;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeNamespaceEdit.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeNamespaceEdit.java
index 422eef7..84fb92e 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeNamespaceEdit.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeNamespaceEdit.java
@@ -1,16 +1,16 @@
 package org.eclipse.vex.core.internal.undo;

 

-import org.eclipse.vex.core.internal.dom.DocumentValidationException;

-import org.eclipse.vex.core.internal.dom.Element;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IElement;

 

 public class ChangeNamespaceEdit implements IUndoableEdit {

 

-	private final Element element;

+	private final IElement element;

 	private final String prefix;

 	private final String oldUri;

 	private final String newUri;

 

-	public ChangeNamespaceEdit(final Element element, final String prefix, final String oldUri, final String newUri) {

+	public ChangeNamespaceEdit(final IElement element, final String prefix, final String oldUri, final String newUri) {

 		this.element = element;

 		this.prefix = prefix;

 		this.oldUri = oldUri;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/DeleteEdit.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/DeleteEdit.java
index d82dc6c..1c0bf3f 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/DeleteEdit.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/DeleteEdit.java
@@ -1,17 +1,17 @@
 package org.eclipse.vex.core.internal.undo;

 

-import org.eclipse.vex.core.internal.dom.Document;

-import org.eclipse.vex.core.internal.dom.DocumentFragment;

-import org.eclipse.vex.core.internal.dom.DocumentValidationException;

-import org.eclipse.vex.core.internal.dom.ContentRange;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IDocumentFragment;

 

 public class DeleteEdit implements IUndoableEdit {

 

-	private final Document document;

+	private final IDocument document;

 	private final ContentRange range;

-	private DocumentFragment fragment = null;

+	private IDocumentFragment fragment = null;

 

-	public DeleteEdit(final Document document, final ContentRange range) {

+	public DeleteEdit(final IDocument document, final ContentRange range) {

 		this.document = document;

 		this.range = range;

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertCommentEdit.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertCommentEdit.java
index 5ff5951..c55d35a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertCommentEdit.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertCommentEdit.java
@@ -1,16 +1,16 @@
 package org.eclipse.vex.core.internal.undo;

 

-import org.eclipse.vex.core.internal.dom.Comment;

-import org.eclipse.vex.core.internal.dom.Document;

-import org.eclipse.vex.core.internal.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.IDocument;

 

 public class InsertCommentEdit implements IUndoableEdit {

 

-	private final Document document;

+	private final IDocument document;

 	private final int offset;

-	private Comment comment;

+	private IComment comment;

 

-	public InsertCommentEdit(final Document document, final int offset) {

+	public InsertCommentEdit(final IDocument document, final int offset) {

 		this.document = document;

 		this.offset = offset;

 		comment = null;

@@ -37,7 +37,7 @@
 		}

 	}

 

-	public Comment getComment() {

+	public IComment getComment() {

 		return comment;

 	}

 

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertElementEdit.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertElementEdit.java
index 2a7e5f3..536a046 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertElementEdit.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertElementEdit.java
@@ -1,18 +1,18 @@
 package org.eclipse.vex.core.internal.undo;

 

 import org.eclipse.core.runtime.QualifiedName;

-import org.eclipse.vex.core.internal.dom.Document;

-import org.eclipse.vex.core.internal.dom.DocumentValidationException;

-import org.eclipse.vex.core.internal.dom.Element;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IElement;

 

 public class InsertElementEdit implements IUndoableEdit {

 

-	private final Document document;

+	private final IDocument document;

 	private final int offset;

 	private final QualifiedName elementName;

-	private Element element;

+	private IElement element;

 

-	public InsertElementEdit(final Document document, final int offset, final QualifiedName elementName) {

+	public InsertElementEdit(final IDocument document, final int offset, final QualifiedName elementName) {

 		this.document = document;

 		this.offset = offset;

 		this.elementName = elementName;

@@ -40,7 +40,7 @@
 		}

 	}

 

-	public Element getElement() {

+	public IElement getElement() {

 		return element;

 	}

 

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertFragmentEdit.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertFragmentEdit.java
index f34a735..dd2f43a 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertFragmentEdit.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertFragmentEdit.java
@@ -1,16 +1,16 @@
 package org.eclipse.vex.core.internal.undo;

 

-import org.eclipse.vex.core.internal.dom.Document;

-import org.eclipse.vex.core.internal.dom.DocumentFragment;

-import org.eclipse.vex.core.internal.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IDocumentFragment;

 

 public class InsertFragmentEdit implements IUndoableEdit {

 

-	private final Document document;

+	private final IDocument document;

 	private final int offset;

-	private final DocumentFragment fragment;

+	private final IDocumentFragment fragment;

 

-	public InsertFragmentEdit(final Document document, final int offset, final DocumentFragment fragment) {

+	public InsertFragmentEdit(final IDocument document, final int offset, final IDocumentFragment fragment) {

 		this.document = document;

 		this.offset = offset;

 		this.fragment = fragment;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertTextEdit.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertTextEdit.java
index 3c73b43..af773df 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertTextEdit.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/InsertTextEdit.java
@@ -1,16 +1,16 @@
 package org.eclipse.vex.core.internal.undo;

 

-import org.eclipse.vex.core.internal.dom.ContentRange;

-import org.eclipse.vex.core.internal.dom.Document;

-import org.eclipse.vex.core.internal.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.ContentRange;

+import org.eclipse.vex.core.dom.DocumentValidationException;

+import org.eclipse.vex.core.dom.IDocument;

 

 public class InsertTextEdit implements IUndoableEdit {

 

-	private final Document document;

+	private final IDocument document;

 	private final int offset;

 	private String text;

 

-	public InsertTextEdit(final Document document, final int offset, final String text) {

+	public InsertTextEdit(final IDocument document, final int offset, final String text) {

 		this.document = document;

 		this.offset = offset;

 		this.text = text;

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/validator/WTPVEXValidator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/validator/WTPVEXValidator.java
index 5c077d6..01eaba5 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/validator/WTPVEXValidator.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/validator/WTPVEXValidator.java
@@ -24,10 +24,10 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.vex.core.internal.dom.Attribute;
-import org.eclipse.vex.core.internal.dom.DocumentContentModel;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Validator;
+import org.eclipse.vex.core.dom.IAttribute;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.IValidator;
+import org.eclipse.vex.core.internal.io.DocumentContentModel;
 import org.eclipse.vex.core.internal.validator.AttributeDefinition.Type;
 import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
 import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
@@ -44,7 +44,7 @@
 import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMValidator.ElementPathRecordingResult;
 import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMValidator.StringElementContentComparator;
 
-public class WTPVEXValidator implements Validator {
+public class WTPVEXValidator implements IValidator {
 
 	private static final ElementContentComparator ELEMENT_CONTENT_COMPARATOR = new StringElementContentComparator() {
 		@Override
@@ -124,7 +124,7 @@
 		return dtd;
 	}
 
-	public AttributeDefinition getAttributeDefinition(final Attribute attribute) {
+	public AttributeDefinition getAttributeDefinition(final IAttribute attribute) {
 		final String attributeName = attribute.getLocalName();
 		final CMElementDeclaration cmElement = getElementDeclaration(attribute.getParent());
 		/*
@@ -150,7 +150,7 @@
 		return new AttributeDefinition(attributeName, Type.CDATA, /* default value */"", /* values */new String[0], /* required */false, /* fixed */true);
 	}
 
-	public List<AttributeDefinition> getAttributeDefinitions(final Element element) {
+	public List<AttributeDefinition> getAttributeDefinitions(final IElement element) {
 		final CMElementDeclaration cmElement = getElementDeclaration(element);
 		/*
 		 * #342320: If we do not find the element, it is acutally not valid. But we are benevolent here since we do not
@@ -170,7 +170,7 @@
 		return attributeList;
 	}
 
-	private CMElementDeclaration getElementDeclaration(final Element element) {
+	private CMElementDeclaration getElementDeclaration(final IElement element) {
 		if (element == null) {
 			return null;
 		}
@@ -204,7 +204,7 @@
 		return vexAttr;
 	}
 
-	public Set<QualifiedName> getValidItems(final Element element) {
+	public Set<QualifiedName> getValidItems(final IElement element) {
 		return getValidItems(getElementDeclaration(element));
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/CssWhitespacePolicy.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/CssWhitespacePolicy.java
index a95f919..a3a2437 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/CssWhitespacePolicy.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/CssWhitespacePolicy.java
@@ -10,10 +10,10 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.widget;
 
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.StyleSheet;
-import org.eclipse.vex.core.internal.dom.IWhitespacePolicy;
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.internal.io.IWhitespacePolicy;
 
 /**
  * Implementation of WhitespacePolicy using a CSS stylesheet.
@@ -30,11 +30,11 @@
 		this.styleSheet = styleSheet;
 	}
 
-	public boolean isBlock(final Node node) {
+	public boolean isBlock(final INode node) {
 		return styleSheet.getStyles(node).isBlock();
 	}
 
-	public boolean isPre(final Node node) {
+	public boolean isPre(final INode node) {
 		return CSS.PRE.equals(styleSheet.getStyles(node).getWhiteSpace());
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/IVexWidget.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/IVexWidget.java
index dca76b8..66101c2 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/IVexWidget.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/IVexWidget.java
@@ -14,15 +14,15 @@
 import java.net.URL;
 
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.DocumentValidationException;
+import org.eclipse.vex.core.dom.IComment;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IDocumentFragment;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.ElementName;
 import org.eclipse.vex.core.internal.css.StyleSheet;
-import org.eclipse.vex.core.internal.dom.Comment;
-import org.eclipse.vex.core.internal.dom.ContentRange;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentFragment;
-import org.eclipse.vex.core.internal.dom.DocumentValidationException;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.eclipse.vex.core.internal.layout.Box;
 import org.eclipse.vex.core.internal.layout.BoxFactory;
 import org.eclipse.vex.core.internal.undo.CannotRedoException;
@@ -174,17 +174,17 @@
 	/**
 	 * Returns the element at the current caret offset.
 	 */
-	public Element getCurrentElement();
+	public IElement getCurrentElement();
 
 	/**
 	 * Returns the node a the current caret offset.
 	 */
-	public Node getCurrentNode();
+	public INode getCurrentNode();
 
 	/**
 	 * Returns the document associated with this component.
 	 */
-	public Document getDocument();
+	public IDocument getDocument();
 
 	/**
 	 * Returns the width to which the document was layed out.
@@ -199,7 +199,7 @@
 	/**
 	 * Returns the currently selected document fragment, or null if there is no current selection.
 	 */
-	public DocumentFragment getSelectedFragment();
+	public IDocumentFragment getSelectedFragment();
 
 	/**
 	 * Returns the currently selected string, or an empty string if there is no current selection.
@@ -249,7 +249,7 @@
 	 * @param frag
 	 *            DocumentFragment to insert.
 	 */
-	public void insertFragment(DocumentFragment frag) throws DocumentValidationException;
+	public void insertFragment(IDocumentFragment frag) throws DocumentValidationException;
 
 	/**
 	 * Inserts the given element at the current caret position. Any selected content becomes the new contents of the
@@ -259,7 +259,7 @@
 	 *            Qualified name of the element to insert.
 	 * @return the newly inserted element
 	 */
-	public Element insertElement(QualifiedName elementName) throws DocumentValidationException;
+	public IElement insertElement(QualifiedName elementName) throws DocumentValidationException;
 
 	/**
 	 * Inserts the given text at the current caret position. Any selected content is first deleted.
@@ -274,7 +274,7 @@
 	 * 
 	 * @return the new comment
 	 */
-	public Comment insertComment() throws DocumentValidationException;
+	public IComment insertComment() throws DocumentValidationException;
 
 	/**
 	 * Returns the value of the debugging flag.
@@ -477,7 +477,7 @@
 	 * @param styleSheet
 	 *            StyleSheet to use for formatting
 	 */
-	public void setDocument(Document document, StyleSheet styleSheet);
+	public void setDocument(IDocument document, StyleSheet styleSheet);
 
 	/**
 	 * Sets the width to which the document should be layed out. The actual resulting width may be different due to
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/VexWidgetImpl.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/VexWidgetImpl.java
index d34b8c0..b15bdf9 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/VexWidgetImpl.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/VexWidgetImpl.java
@@ -26,6 +26,19 @@
 
 import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.dom.BaseNodeVisitorWithResult;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.DocumentEvent;
+import org.eclipse.vex.core.dom.DocumentValidationException;
+import org.eclipse.vex.core.dom.IComment;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IDocumentFragment;
+import org.eclipse.vex.core.dom.IDocumentListener;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IPosition;
+import org.eclipse.vex.core.dom.IText;
+import org.eclipse.vex.core.dom.IValidator;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Color;
 import org.eclipse.vex.core.internal.core.ElementName;
@@ -36,19 +49,8 @@
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
 import org.eclipse.vex.core.internal.css.Styles;
-import org.eclipse.vex.core.internal.dom.BaseNodeVisitorWithResult;
-import org.eclipse.vex.core.internal.dom.Comment;
-import org.eclipse.vex.core.internal.dom.ContentRange;
 import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentEvent;
-import org.eclipse.vex.core.internal.dom.DocumentFragment;
-import org.eclipse.vex.core.internal.dom.DocumentListener;
-import org.eclipse.vex.core.internal.dom.DocumentValidationException;
-import org.eclipse.vex.core.internal.dom.Element;
 import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Position;
-import org.eclipse.vex.core.internal.dom.Text;
-import org.eclipse.vex.core.internal.dom.Validator;
 import org.eclipse.vex.core.internal.layout.BlockBox;
 import org.eclipse.vex.core.internal.layout.Box;
 import org.eclipse.vex.core.internal.layout.BoxFactory;
@@ -97,7 +99,7 @@
 	private int layoutWidth = 500; // something reasonable to handle a document
 	// being set before the widget is sized
 
-	private Document document;
+	private IDocument document;
 	private StyleSheet styleSheet;
 	private BoxFactory boxFactory = new CssBoxFactory();
 
@@ -119,7 +121,7 @@
 	private int selectionStart;
 	private int selectionEnd;
 
-	private Node currentNode;
+	private INode currentNode;
 
 	private boolean caretVisible = true;
 	private Caret caret;
@@ -130,7 +132,7 @@
 
 	private boolean antiAliased = false;
 
-	private final DocumentListener documentListener = new DocumentListener() {
+	private final IDocumentListener documentListener = new IDocumentListener() {
 
 		public void attributeChanged(final DocumentEvent e) {
 			invalidateElementBox(e.getParent());
@@ -140,7 +142,7 @@
 			 * 
 			 * This cast is save because this event is only fired due to the attribute changes of elements.
 			 */
-			getStyleSheet().flushStyles((Element) e.getParent());
+			getStyleSheet().flushStyles((IElement) e.getParent());
 
 			if (beginWorkCount == 0) {
 				VexWidgetImpl.this.relayout();
@@ -211,17 +213,17 @@
 	 * @param frag
 	 *            DocumentFragment to be inserted.
 	 */
-	public boolean canInsertFragment(final DocumentFragment frag) {
+	public boolean canInsertFragment(final IDocumentFragment frag) {
 		if (readOnly) {
 			return false;
 		}
 
-		final Document doc = getDocument();
+		final IDocument doc = getDocument();
 		if (doc == null) {
 			return false;
 		}
 
-		final Validator validator = doc.getValidator();
+		final IValidator validator = doc.getValidator();
 		if (validator == null) {
 			return true;
 		}
@@ -233,7 +235,7 @@
 			endOffset = getSelectionEnd();
 		}
 
-		final Element parent = getDocument().getElementForInsertionAt(startOffset);
+		final IElement parent = getDocument().getElementForInsertionAt(startOffset);
 		final List<QualifiedName> seq1 = Node.getNodeNames(parent.children().before(startOffset));
 		final List<QualifiedName> seq2 = frag.getNodeNames();
 		final List<QualifiedName> seq3 = Node.getNodeNames(parent.children().after(endOffset));
@@ -249,12 +251,12 @@
 			return false;
 		}
 
-		final Document doc = getDocument();
+		final IDocument doc = getDocument();
 		if (doc == null) {
 			return false;
 		}
 
-		final Validator validator = document.getValidator();
+		final IValidator validator = document.getValidator();
 		if (validator == null) {
 			return true;
 		}
@@ -266,9 +268,9 @@
 			endOffset = getSelectionEnd();
 		}
 
-		final Element parent = getDocument().getElementForInsertionAt(startOffset);
+		final IElement parent = getDocument().getElementForInsertionAt(startOffset);
 		final List<QualifiedName> seq1 = Node.getNodeNames(parent.children().before(startOffset));
-		final List<QualifiedName> seq2 = Collections.singletonList(Validator.PCDATA);
+		final List<QualifiedName> seq2 = Collections.singletonList(IValidator.PCDATA);
 		final List<QualifiedName> seq3 = Node.getNodeNames(parent.children().after(endOffset));
 
 		return validator.isValidSequence(parent.getQualifiedName(), seq1, seq2, seq3, true);
@@ -301,18 +303,18 @@
 			return false;
 		}
 
-		final Document doc = getDocument();
+		final IDocument doc = getDocument();
 		if (doc == null) {
 			return false;
 		}
 
-		final Validator validator = doc.getValidator();
+		final IValidator validator = doc.getValidator();
 		if (validator == null) {
 			return false;
 		}
 
-		final Element element = doc.getElementForInsertionAt(getCaretOffset());
-		final Element parent = element.getParentElement();
+		final IElement element = doc.getElementForInsertionAt(getCaretOffset());
+		final IElement parent = element.getParentElement();
 		if (parent == null) {
 			// can't unwrap the root
 			return false;
@@ -342,7 +344,7 @@
 			deleteSelection();
 		} else {
 			final int offset = getCaretOffset();
-			final Document doc = getDocument();
+			final IDocument doc = getDocument();
 			final int n = doc.getLength() - 1;
 			if (offset == n) {
 				// nop
@@ -376,7 +378,7 @@
 			deleteSelection();
 		} else {
 			int offset = getCaretOffset();
-			final Document doc = getDocument();
+			final IDocument doc = getDocument();
 			if (offset == 1) {
 				// nop
 			} else if (isBetweenMatchingElements(offset)) {
@@ -443,7 +445,7 @@
 	}
 
 	public void doWork(final boolean savePosition, final Runnable runnable) {
-		Position position = null;
+		IPosition position = null;
 
 		if (savePosition) {
 			position = getDocument().createPosition(getCaretOffset());
@@ -565,30 +567,30 @@
 		return getCaretOffset();
 	}
 
-	public Element getCurrentElement() {
-		return currentNode.accept(new BaseNodeVisitorWithResult<Element>(null) {
+	public IElement getCurrentElement() {
+		return currentNode.accept(new BaseNodeVisitorWithResult<IElement>(null) {
 			@Override
-			public Element visit(final Element element) {
+			public IElement visit(final IElement element) {
 				return element;
 			}
 
 			@Override
-			public Element visit(final Comment comment) {
+			public IElement visit(final IComment comment) {
 				return comment.getParent().accept(this);
 			}
 
 			@Override
-			public Element visit(final Text text) {
+			public IElement visit(final IText text) {
 				return text.getParent().accept(this);
 			}
 		});
 	}
 
-	public Node getCurrentNode() {
+	public INode getCurrentNode() {
 		return currentNode;
 	}
 
-	public Document getDocument() {
+	public IDocument getDocument() {
 		return document;
 	}
 
@@ -604,12 +606,12 @@
 			return new ElementName[0];
 		}
 
-		final Document doc = getDocument();
+		final IDocument doc = getDocument();
 		if (doc == null) {
 			return new ElementName[0];
 		}
 
-		final Validator validator = doc.getValidator();
+		final IValidator validator = doc.getValidator();
 		if (validator == null) {
 			return new ElementName[0];
 		}
@@ -617,7 +619,7 @@
 		final int startOffset = getStartOffset();
 		final int endOffset = getEndOffset();
 
-		final Element parent = doc.getElementForInsertionAt(startOffset);
+		final IElement parent = doc.getElementForInsertionAt(startOffset);
 		if (parent == null) {
 			return new ElementName[0];
 		}
@@ -625,7 +627,7 @@
 		final List<QualifiedName> nodesBefore = Node.getNodeNames(parent.children().before(startOffset));
 		final List<QualifiedName> nodesAfter = Node.getNodeNames(parent.children().after(endOffset));
 		final List<QualifiedName> selectedNodes = Node.getNodeNames(parent.children().in(new ContentRange(startOffset, endOffset)));
-		final List<QualifiedName> candidates = createCandidatesList(validator, parent, Validator.PCDATA);
+		final List<QualifiedName> candidates = createCandidatesList(validator, parent, IValidator.PCDATA);
 
 		filterInvalidSequences(validator, parent, nodesBefore, nodesAfter, candidates);
 
@@ -644,7 +646,7 @@
 		return result;
 	}
 
-	private static List<QualifiedName> createCandidatesList(final Validator validator, final Element parent, final QualifiedName... exceptions) {
+	private static List<QualifiedName> createCandidatesList(final IValidator validator, final IElement parent, final QualifiedName... exceptions) {
 		final Set<QualifiedName> validItems = validator.getValidItems(parent);
 		final List<QualifiedName> exceptionItems = Arrays.asList(exceptions);
 		final List<QualifiedName> result = new ArrayList<QualifiedName>();
@@ -656,7 +658,7 @@
 		return result;
 	}
 
-	private static void filterInvalidSequences(final Validator validator, final Element parent, final List<QualifiedName> nodesBefore, final List<QualifiedName> nodesAfter,
+	private static void filterInvalidSequences(final IValidator validator, final IElement parent, final List<QualifiedName> nodesBefore, final List<QualifiedName> nodesAfter,
 			final List<QualifiedName> candidates) {
 		final int sequenceLength = nodesBefore.size() + 1 + nodesAfter.size();
 		for (final Iterator<QualifiedName> iterator = candidates.iterator(); iterator.hasNext();) {
@@ -671,7 +673,7 @@
 		}
 	}
 
-	private static void filterInvalidSelectionParents(final Validator validator, final List<QualifiedName> selectedNodes, final List<QualifiedName> candidates) {
+	private static void filterInvalidSelectionParents(final IValidator validator, final List<QualifiedName> selectedNodes, final List<QualifiedName> candidates) {
 		for (final Iterator<QualifiedName> iter = candidates.iterator(); iter.hasNext();) {
 			final QualifiedName candidate = iter.next();
 			if (!validator.isValidSequence(candidate, selectedNodes, true)) {
@@ -693,24 +695,24 @@
 			return new ElementName[0];
 		}
 
-		final Document doc = getDocument();
+		final IDocument doc = getDocument();
 		if (doc == null) {
 			return new ElementName[0];
 		}
 
-		final Validator validator = doc.getValidator();
+		final IValidator validator = doc.getValidator();
 		if (validator == null) {
 			return new ElementName[0];
 		}
 
-		final Element element = doc.getElementForInsertionAt(getCaretOffset());
-		final Element parent = element.getParentElement();
+		final IElement element = doc.getElementForInsertionAt(getCaretOffset());
+		final IElement parent = element.getParentElement();
 		if (parent == null) {
 			// can't morph the root
 			return new ElementName[0];
 		}
 
-		final List<QualifiedName> candidates = createCandidatesList(validator, parent, Validator.PCDATA, element.getQualifiedName());
+		final List<QualifiedName> candidates = createCandidatesList(validator, parent, IValidator.PCDATA, element.getQualifiedName());
 
 		// root out those that can't contain the current content
 		final List<QualifiedName> content = Node.getNodeNames(element.children());
@@ -746,7 +748,7 @@
 		return new ContentRange(getSelectionStart(), getSelectionEnd() - 1);
 	}
 
-	public DocumentFragment getSelectedFragment() {
+	public IDocumentFragment getSelectedFragment() {
 		if (hasSelection()) {
 			return document.getFragment(getSelectedRange());
 		} else {
@@ -782,17 +784,17 @@
 		return getSelectionStart() != getSelectionEnd();
 	}
 
-	public Element insertElement(final QualifiedName elementName) throws DocumentValidationException, ReadOnlyException {
+	public IElement insertElement(final QualifiedName elementName) throws DocumentValidationException, ReadOnlyException {
 		if (readOnly) {
 			throw new ReadOnlyException(MessageFormat.format("Cannot insert element {0}, because the editor is read-only.", elementName));
 		}
 
 		boolean success = false;
-		final Element result;
+		final IElement result;
 		try {
 			beginWork();
 
-			DocumentFragment selectedFragment = null;
+			IDocumentFragment selectedFragment = null;
 			if (hasSelection()) {
 				selectedFragment = getSelectedFragment();
 				deleteSelection();
@@ -812,7 +814,7 @@
 		}
 	}
 
-	public void insertFragment(final DocumentFragment fragment) throws DocumentValidationException {
+	public void insertFragment(final IDocumentFragment fragment) throws DocumentValidationException {
 		if (readOnly) {
 			throw new ReadOnlyException("Cannot insert fragment, because the editor is read-only");
 		}
@@ -870,7 +872,7 @@
 		this.moveBy(+1);
 	}
 
-	public Comment insertComment() throws DocumentValidationException, ReadOnlyException {
+	public IComment insertComment() throws DocumentValidationException, ReadOnlyException {
 		if (readOnly) {
 			throw new ReadOnlyException("Cannot insert comment, because the editor is read-only.");
 		}
@@ -885,7 +887,7 @@
 			beginWork();
 
 			final InsertCommentEdit edit = applyEdit(new InsertCommentEdit(document, getCaretOffset()), getCaretOffset());
-			final Comment result = edit.getComment();
+			final IComment result = edit.getComment();
 			this.moveTo(getCaretOffset() + 1);
 			scrollCaretVisible();
 			success = true;
@@ -900,9 +902,9 @@
 			throw new ReadOnlyException(MessageFormat.format("Cannot morph to element {0}, because the editor is read-only.", elementName));
 		}
 
-		final Document doc = getDocument();
+		final IDocument doc = getDocument();
 		final int offset = getCaretOffset();
-		final Element currentElement = doc.getElementForInsertionAt(offset);
+		final IElement currentElement = doc.getElementForInsertionAt(offset);
 
 		if (currentElement == doc.getRootElement()) {
 			throw new DocumentValidationException("Cannot morph the root element.");
@@ -913,7 +915,7 @@
 			beginWork();
 			this.moveTo(currentElement.getStartOffset() + 1, false);
 			this.moveTo(currentElement.getEndOffset(), true);
-			final DocumentFragment frag = getSelectedFragment();
+			final IDocumentFragment frag = getSelectedFragment();
 			deleteSelection();
 			this.moveBy(-1, false);
 			this.moveBy(2, true);
@@ -956,7 +958,7 @@
 			moveCaretTo(offset);
 		}
 
-		final Node oldNode = currentNode;
+		final INode oldNode = currentNode;
 		currentNode = document.getNodeForInsertionAt(caretOffset);
 
 		if (beginWorkCount == 0) {
@@ -967,7 +969,7 @@
 		final LayoutContext context = createLayoutContext(g);
 		caret = rootBox.getCaret(context, caretOffset);
 
-		Node node = currentNode;
+		INode node = currentNode;
 		if (node != oldNode) {
 			caretColor = Color.BLACK;
 			while (node != null) {
@@ -1002,7 +1004,7 @@
 		// expand or shrink the selection to make sure the selection is balanced
 		final int balancedStart = Math.min(mark, offset);
 		final int balancedEnd = Math.max(mark, offset);
-		final Node balancedNode = document.findCommonNode(balancedStart, balancedEnd);
+		final INode balancedNode = document.findCommonNode(balancedStart, balancedEnd);
 		if (movingForward && movingTowardMark) {
 			selectionStart = balanceForward(balancedStart, balancedNode);
 			selectionEnd = balanceForward(balancedEnd, balancedNode);
@@ -1022,9 +1024,9 @@
 		}
 	}
 
-	private int balanceForward(final int offset, final Node balancedNode) {
+	private int balanceForward(final int offset, final INode balancedNode) {
 		int balancedOffset = offset;
-		Node node = document.getNodeForInsertionAt(balancedOffset);
+		INode node = document.getNodeForInsertionAt(balancedOffset);
 		while (node != balancedNode) {
 			balancedOffset = node.getEndOffset() + 1;
 			node = document.getNodeForInsertionAt(balancedOffset);
@@ -1032,9 +1034,9 @@
 		return balancedOffset;
 	}
 
-	private int balanceBackward(final int offset, final Node balancedNode) {
+	private int balanceBackward(final int offset, final INode balancedNode) {
 		int balancedOffset = offset;
-		Node node = document.getNodeForInsertionAt(balancedOffset);
+		INode node = document.getNodeForInsertionAt(balancedOffset);
 		while (node != balancedNode) {
 			balancedOffset = node.getStartOffset();
 			node = document.getNodeForInsertionAt(balancedOffset);
@@ -1076,7 +1078,7 @@
 	}
 
 	public void moveToNextWord(final boolean select) {
-		final Document doc = getDocument();
+		final IDocument doc = getDocument();
 		final int n = doc.getLength() - 1;
 		int offset = getCaretOffset();
 		while (offset < n && !Character.isLetterOrDigit(doc.getCharacterAt(offset))) {
@@ -1109,7 +1111,7 @@
 	}
 
 	public void moveToPreviousWord(final boolean select) {
-		final Document doc = getDocument();
+		final IDocument doc = getDocument();
 		int offset = getCaretOffset();
 		while (offset > 1 && !Character.isLetterOrDigit(doc.getCharacterAt(offset - 1))) {
 			offset--;
@@ -1190,7 +1192,7 @@
 	}
 
 	public void savePosition(final Runnable runnable) {
-		final Position pos = getDocument().createPosition(getCaretOffset());
+		final IPosition pos = getDocument().createPosition(getCaretOffset());
 		try {
 			runnable.run();
 		} finally {
@@ -1204,7 +1206,7 @@
 	}
 
 	public void selectWord() {
-		final Document doc = getDocument();
+		final IDocument doc = getDocument();
 		int startOffset = getCaretOffset();
 		int endOffset = getCaretOffset();
 		while (startOffset > 1 && Character.isLetterOrDigit(doc.getCharacterAt(startOffset - 1))) {
@@ -1236,7 +1238,7 @@
 			throw new ReadOnlyException(MessageFormat.format("Cannot set attribute {0}, because the editor is read-only.", attributeName));
 		}
 
-		final Element element = getCurrentElement();
+		final IElement element = getCurrentElement();
 		if (element == null) {
 			// TODO throw IllegalStateException("Not in element");
 			return;
@@ -1256,7 +1258,7 @@
 			throw new ReadOnlyException(MessageFormat.format("Cannot remove attribute {0}, because the editor is read-only.", attributeName));
 		}
 
-		final Element element = getCurrentElement();
+		final IElement element = getCurrentElement();
 		if (element == null) {
 			return;
 		}
@@ -1287,9 +1289,9 @@
 		this.readOnly = readOnly;
 	}
 
-	public void setDocument(final Document document, final StyleSheet styleSheet) {
+	public void setDocument(final IDocument document, final StyleSheet styleSheet) {
 		if (this.document != null) {
-			final Document doc = document;
+			final IDocument doc = document;
 			doc.removeDocumentListener(documentListener);
 		}
 
@@ -1350,8 +1352,8 @@
 
 		final long start = System.currentTimeMillis();
 
-		final Document doc = getDocument();
-		Element element = doc.getElementForInsertionAt(getCaretOffset());
+		final IDocument doc = getDocument();
+		IElement element = doc.getElementForInsertionAt(getCaretOffset());
 		Styles styles = getStyleSheet().getStyles(element);
 		while (!styles.isBlock()) {
 			element = element.getParentElement();
@@ -1365,7 +1367,7 @@
 				applyEdit(new InsertTextEdit(document, getCaretOffset(), "\n"), getCaretOffset());
 				this.moveBy(1);
 			} else {
-				DocumentFragment frag = null;
+				IDocumentFragment frag = null;
 				int offset = getCaretOffset();
 				final boolean atEnd = offset == element.getEndOffset();
 				if (!atEnd) {
@@ -1434,7 +1436,7 @@
 			throw new ReadOnlyException(MessageFormat.format("Cannot declare namespace {0}, because the editor is read-only.", namespacePrefix));
 		}
 
-		final Element element = getCurrentElement();
+		final IElement element = getCurrentElement();
 		if (element == null) {
 			// TODO throw IllegalStateException("Not in element");
 			return;
@@ -1448,7 +1450,7 @@
 			throw new ReadOnlyException(MessageFormat.format("Cannot remove namespace {0}, because the editor is read-only.", namespacePrefix));
 		}
 
-		final Element element = getCurrentElement();
+		final IElement element = getCurrentElement();
 		if (element == null) {
 			// TODO throw IllegalStateException("Not in element");
 			return;
@@ -1462,7 +1464,7 @@
 			throw new ReadOnlyException("Cannot declare default namespace, because the editor is read-only.");
 		}
 
-		final Element element = getCurrentElement();
+		final IElement element = getCurrentElement();
 		if (element == null) {
 			// TODO throw IllegalStateException("Not in element");
 			return;
@@ -1476,7 +1478,7 @@
 			throw new ReadOnlyException("Cannot remove default namespace, because the editor is read-only.");
 		}
 
-		final Element element = getCurrentElement();
+		final IElement element = getCurrentElement();
 		if (element == null) {
 			// TODO throw IllegalStateException("Not in element");
 			return;
@@ -1574,7 +1576,7 @@
 	 * @param node
 	 *            Node for which to search.
 	 */
-	private void invalidateElementBox(final Node node) {
+	private void invalidateElementBox(final INode node) {
 
 		final BlockBox elementBox = (BlockBox) this.findInnermostBox(new IBoxFilter() {
 			public boolean matches(final Box box) {
@@ -1597,8 +1599,8 @@
 		if (offset <= 1 || offset >= getDocument().getLength() - 1) {
 			return false;
 		}
-		final Element e1 = getDocument().getElementForInsertionAt(offset - 1);
-		final Element e2 = getDocument().getElementForInsertionAt(offset + 1);
+		final IElement e1 = getDocument().getElementForInsertionAt(offset - 1);
+		final IElement e2 = getDocument().getElementForInsertionAt(offset + 1);
 		return e1 != e2 && e1 != null && e2 != null && e1.getParent() == e2.getParent() && e1.isKindOf(e2);
 	}
 
@@ -1653,11 +1655,11 @@
 
 			// get the second element
 			moveTo(offset + 1);
-			final Element secondElement = getCurrentElement();
+			final IElement secondElement = getCurrentElement();
 
 			// preserve the second element's content
 			final boolean shouldMoveContent = !secondElement.isEmpty();
-			final DocumentFragment preservedContent;
+			final IDocumentFragment preservedContent;
 			if (shouldMoveContent) {
 				moveTo(secondElement.getEndOffset(), true);
 				preservedContent = getSelectedFragment();
diff --git a/org.eclipse.vex.docbook/src/org/eclipse/vex/docbook/DocBookOutlineProvider.java b/org.eclipse.vex.docbook/src/org/eclipse/vex/docbook/DocBookOutlineProvider.java
index 9498071..0d4cb14 100644
--- a/org.eclipse.vex.docbook/src/org/eclipse/vex/docbook/DocBookOutlineProvider.java
+++ b/org.eclipse.vex.docbook/src/org/eclipse/vex/docbook/DocBookOutlineProvider.java
@@ -20,8 +20,9 @@
 import org.eclipse.jface.viewers.ITreeContentProvider;
 import org.eclipse.jface.viewers.LabelProvider;
 import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.dom.Filters;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.ui.internal.editor.VexEditor;
 import org.eclipse.vex.ui.internal.outline.IOutlineProvider;
 
@@ -41,8 +42,8 @@
 		return labelProvider;
 	}
 
-	public Element getOutlineElement(final Element child) {
-		Element element = child;
+	public IElement getOutlineElement(final IElement child) {
+		IElement element = child;
 		while (element.getParentElement() != null && !isTitledElement(element)) {
 			element = element.getParentElement();
 		}
@@ -59,11 +60,11 @@
 		}
 
 		public Object[] getChildren(final Object parentElement) {
-			return getOutlineChildren((Element) parentElement);
+			return getOutlineChildren((IElement) parentElement);
 		}
 
 		public Object getParent(final Object element) {
-			final Element parent = ((Element) element).getParentElement();
+			final IElement parent = ((IElement) element).getParentElement();
 			if (parent == null) {
 				return element;
 			} else {
@@ -72,11 +73,11 @@
 		}
 
 		public boolean hasChildren(final Object element) {
-			return getOutlineChildren((Element) element).length > 0;
+			return getOutlineChildren((IElement) element).length > 0;
 		}
 
 		public Object[] getElements(final Object inputElement) {
-			final Document document = (Document) inputElement;
+			final IDocument document = (IDocument) inputElement;
 			return new Object[] { document.getRootElement() };
 		}
 
@@ -89,25 +90,25 @@
 	 * @param element
 	 * @return
 	 */
-	private Element[] getOutlineChildren(final Element element) {
-		final List<Element> children = new ArrayList<Element>();
-		for (final Element child : element.getChildElements()) {
+	private IElement[] getOutlineChildren(final IElement element) {
+		final List<IElement> children = new ArrayList<IElement>();
+		for (final IElement child : element.childElements()) {
 			if (titledElements.contains(child.getLocalName())) {
 				children.add(child);
 			}
 		}
-		return children.toArray(new Element[children.size()]);
+		return children.toArray(new IElement[children.size()]);
 	}
 
 	private final ILabelProvider labelProvider = new LabelProvider() {
 		@Override
 		public String getText(final Object o) {
-			final Element e = (Element) o;
-			Element titleChild = findChild(e, "title");
+			final IElement e = (IElement) o;
+			IElement titleChild = findChild(e, "title");
 			if (titleChild != null) {
 				return titleChild.getText();
 			} else {
-				final Element infoChild = findChild(e, e.getLocalName() + "info");
+				final IElement infoChild = findChild(e, e.getLocalName() + "info");
 				if (infoChild != null) {
 					titleChild = findChild(infoChild, "title");
 					if (titleChild != null) {
@@ -129,13 +130,9 @@
 	 * @param element
 	 * @return
 	 */
-	private boolean isTitledElement(final Element e) {
-
-		if (titledElements.contains(e.getLocalName()) || e.getParent() == null) {
-			final List<Element> children = e.getChildElements();
-			if (children.size() > 0 && children.get(0).getLocalName().equals("title") || children.size() > 1 && children.get(1).getLocalName().equals("title")) {
-				return true;
-			}
+	private boolean isTitledElement(final IElement element) {
+		if (titledElements.contains(element.getLocalName()) || element.getParent() == null) {
+			return !element.childElements().to(1).matching(Filters.elementsNamed("title")).isEmpty();
 		}
 		return false;
 	}
@@ -144,11 +141,9 @@
 	 * Finds the first child of the given element with the given name. Returns null if none found. We should move this
 	 * to XPath when we gain that facility.
 	 */
-	private Element findChild(final Element parent, final String childName) {
-		for (final Element child : parent.getChildElements()) {
-			if (child.getLocalName().equals(childName)) {
-				return child;
-			}
+	private IElement findChild(final IElement parent, final String childName) {
+		for (final IElement child : parent.childElements().matching(Filters.elementsNamed(childName))) {
+			return child;
 		}
 		return null;
 	}
diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/namespace/tests/EditNamespacesControllerTest.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/namespace/tests/EditNamespacesControllerTest.java
index 9384e83..87dad7a 100644
--- a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/namespace/tests/EditNamespacesControllerTest.java
+++ b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/namespace/tests/EditNamespacesControllerTest.java
@@ -21,6 +21,7 @@
 import java.util.List;

 

 import org.eclipse.core.runtime.QualifiedName;

+import org.eclipse.vex.core.dom.IElement;

 import org.eclipse.vex.core.internal.dom.Element;

 import org.eclipse.vex.core.internal.widget.MockHostComponent;

 import org.eclipse.vex.core.internal.widget.VexWidgetImpl;

@@ -49,10 +50,10 @@
 		assertContainsNamespaceDefinition(new EditableNamespaceDefinition("ns2", "http://namespace/uri/2"), namespaces);

 	}

 

-	private EditNamespacesController createController(final Element element) {

+	private EditNamespacesController createController(final IElement element) {

 		final VexWidgetImpl widget = new VexWidgetImpl(new MockHostComponent()) {

 			@Override

-			public Element getCurrentElement() {

+			public IElement getCurrentElement() {

 				return element;

 			}

 		};

diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/swt/tests/DocumentFragmentTransferTest.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/swt/tests/DocumentFragmentTransferTest.java
index 1341f74..ce38fe6 100644
--- a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/swt/tests/DocumentFragmentTransferTest.java
+++ b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/swt/tests/DocumentFragmentTransferTest.java
@@ -16,17 +16,18 @@
 import java.io.ByteArrayOutputStream;

 

 import org.eclipse.core.runtime.QualifiedName;

-import org.eclipse.vex.core.internal.dom.Comment;

+import org.eclipse.vex.core.dom.IComment;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IDocumentFragment;

+import org.eclipse.vex.core.dom.IElement;

 import org.eclipse.vex.core.internal.dom.Document;

-import org.eclipse.vex.core.internal.dom.DocumentFragment;

-import org.eclipse.vex.core.internal.dom.Element;

 import org.eclipse.vex.ui.internal.swt.DocumentFragmentTransfer;

 import org.junit.Before;

 import org.junit.Test;

 

 public class DocumentFragmentTransferTest {

 

-	private Document document;

+	private IDocument document;

 

 	@Before

 	public void setUp() throws Exception {

@@ -43,7 +44,7 @@
 	@Test

 	public void shouldTransferElementAndText() throws Exception {

 		document.insertText(document.getRootElement().getEndOffset(), "Hello");

-		final Element child = addChild();

+		final IElement child = addChild();

 		document.insertText(child.getEndOffset(), "New");

 		document.insertText(document.getRootElement().getEndOffset(), "World");

 

@@ -52,7 +53,7 @@
 

 	@Test

 	public void shouldTransferElementWithNamespace() throws Exception {

-		final Element child = addChild();

+		final IElement child = addChild();

 		child.declareNamespace("ns1", "http://namespaceUri/1");

 

 		assertRoundTripWorks(getExpectedFragment());

@@ -60,7 +61,7 @@
 

 	@Test

 	public void shouldTransferElementWithDefaultNamespace() throws Exception {

-		final Element child = addChild(new QualifiedName("http://namespaceUri/default", "child"));

+		final IElement child = addChild(new QualifiedName("http://namespaceUri/default", "child"));

 		child.declareDefaultNamespace("http://namespaceUri/default");

 

 		assertRoundTripWorks(getExpectedFragment());

@@ -68,28 +69,28 @@
 

 	@Test

 	public void shouldTransferComment() throws Exception {

-		final Comment comment = document.insertComment(document.getRootElement().getEndOffset());

+		final IComment comment = document.insertComment(document.getRootElement().getEndOffset());

 		document.insertText(comment.getEndOffset(), "Hello World");

 		assertRoundTripWorks(getExpectedFragment());

 	}

 

-	private Element addChild() {

+	private IElement addChild() {

 		return addChild(new QualifiedName(null, "child"));

 	}

 

-	private Element addChild(final QualifiedName elementName) {

+	private IElement addChild(final QualifiedName elementName) {

 		return document.insertElement(document.getRootElement().getEndOffset(), elementName);

 	}

 

-	private DocumentFragment getExpectedFragment() {

+	private IDocumentFragment getExpectedFragment() {

 		return document.getFragment(document.getRootElement().getRange().resizeBy(1, -1));

 	}

 

-	private static void assertRoundTripWorks(final DocumentFragment expectedFragment) throws Exception {

+	private static void assertRoundTripWorks(final IDocumentFragment expectedFragment) throws Exception {

 		final ByteArrayOutputStream buffer = new ByteArrayOutputStream();

 		final DocumentFragmentTransfer transfer = new DocumentFragmentTransfer();

 		transfer.writeFragmentToStream(expectedFragment, buffer);

-		final DocumentFragment actualFragment = transfer.readFragmentFromStream(new ByteArrayInputStream(buffer.toByteArray()));

+		final IDocumentFragment actualFragment = transfer.readFragmentFromStream(new ByteArrayInputStream(buffer.toByteArray()));

 		assertContentEqual(expectedFragment, actualFragment);

 	}

 

diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DoctypeFactory.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DoctypeFactory.java
index 43d0f2e..238c29c 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DoctypeFactory.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DoctypeFactory.java
@@ -16,7 +16,7 @@
 import java.net.URISyntaxException;
 import java.net.URL;
 
-import org.eclipse.vex.core.internal.dom.DocumentContentModel;
+import org.eclipse.vex.core.internal.io.DocumentContentModel;
 import org.eclipse.vex.core.internal.validator.WTPVEXValidator;
 
 /**
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DoctypePropertyPage.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DoctypePropertyPage.java
index 229aec7..464fe97 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DoctypePropertyPage.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DoctypePropertyPage.java
@@ -35,7 +35,7 @@
 import org.eclipse.swt.widgets.TableItem;
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.dialogs.PropertyPage;
-import org.eclipse.vex.core.internal.dom.Validator;
+import org.eclipse.vex.core.dom.IValidator;
 import org.eclipse.vex.ui.internal.VexPlugin;
 
 /**
@@ -194,7 +194,7 @@
 	}
 
 	private void populateRootElements() {
-		final Validator validator = (Validator) pluginProject.getParsedResource(((IFile) getElement()).getLocationURI());
+		final IValidator validator = (IValidator) pluginProject.getParsedResource(((IFile) getElement()).getLocationURI());
 		if (validator != null) {
 			final List<String> list = Arrays.asList(doctype.getRootElements());
 			final Set<String> selectedRootElements = new TreeSet<String>(list);
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DocumentType.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DocumentType.java
index 08fd4cb..7055185 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DocumentType.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DocumentType.java
@@ -11,7 +11,7 @@
  *******************************************************************************/
 package org.eclipse.vex.ui.internal.config;
 
-import org.eclipse.vex.core.internal.dom.Validator;
+import org.eclipse.vex.core.dom.IValidator;
 
 /**
  * A registered document type.
@@ -83,8 +83,8 @@
 		this.systemId = systemId;
 	}
 
-	public Validator getValidator() {
-		return (Validator) getConfig().getParsedResource(getResourceUri());
+	public IValidator getValidator() {
+		return (IValidator) getConfig().getParsedResource(getResourceUri());
 	}
 
 	@Override
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/DocumentTypeSelectionPage.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/DocumentTypeSelectionPage.java
index f6d2065..608fe94 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/DocumentTypeSelectionPage.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/DocumentTypeSelectionPage.java
@@ -25,7 +25,7 @@
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Label;
-import org.eclipse.vex.core.internal.dom.Validator;
+import org.eclipse.vex.core.dom.IValidator;
 import org.eclipse.vex.ui.internal.VexPlugin;
 import org.eclipse.vex.ui.internal.config.DocumentType;
 
@@ -180,7 +180,7 @@
 	}
 
 	private static String[] getPossibleRootElements(final DocumentType documentType) {
-		final Validator validator = documentType.getValidator();
+		final IValidator validator = documentType.getValidator();
 		if (validator == null) {
 			return new String[0];
 		}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexActionBarContributor.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexActionBarContributor.java
index ee6f1eb..96e5d9c 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexActionBarContributor.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexActionBarContributor.java
@@ -25,7 +25,7 @@
 import org.eclipse.ui.texteditor.FindReplaceAction;
 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
 import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
-import org.eclipse.vex.core.internal.dom.DocumentValidationException;
+import org.eclipse.vex.core.dom.DocumentValidationException;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 import org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorActionBarContributor;
 
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexDocumentContentModel.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexDocumentContentModel.java
index 786c82e..e33f63b 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexDocumentContentModel.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexDocumentContentModel.java
@@ -11,9 +11,9 @@
 package org.eclipse.vex.ui.internal.editor;

 

 import org.eclipse.swt.widgets.Shell;

-import org.eclipse.vex.core.internal.dom.DocumentContentModel;

-import org.eclipse.vex.core.internal.dom.Element;

-import org.eclipse.vex.core.internal.dom.IWhitespacePolicy;

+import org.eclipse.vex.core.dom.IElement;

+import org.eclipse.vex.core.internal.io.DocumentContentModel;

+import org.eclipse.vex.core.internal.io.IWhitespacePolicy;

 import org.eclipse.vex.core.internal.widget.CssWhitespacePolicy;

 import org.eclipse.vex.ui.internal.VexPlugin;

 import org.eclipse.vex.ui.internal.config.DocumentType;

@@ -37,7 +37,7 @@
 	}

 

 	@Override

-	public void initialize(final String baseUri, final String publicId, final String systemId, final Element rootElement) {

+	public void initialize(final String baseUri, final String publicId, final String systemId, final IElement rootElement) {

 		super.initialize(baseUri, publicId, systemId, rootElement);

 		final String mainDocumentTypeIdentifier = getMainDocumentTypeIdentifier();

 		documentType = getRegisteredDocumentType();

diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexEditor.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexEditor.java
index 1c304f2..1b7380d 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexEditor.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/VexEditor.java
@@ -68,12 +68,12 @@
 import org.eclipse.ui.views.properties.IPropertySource;
 import org.eclipse.ui.views.properties.IPropertySourceProvider;
 import org.eclipse.ui.views.properties.PropertySheetPage;
+import org.eclipse.vex.core.dom.DocumentEvent;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IDocumentListener;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.IValidator;
 import org.eclipse.vex.core.internal.core.ListenerList;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentEvent;
-import org.eclipse.vex.core.internal.dom.DocumentListener;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Validator;
 import org.eclipse.vex.core.internal.io.DocumentReader;
 import org.eclipse.vex.core.internal.io.DocumentWriter;
 import org.eclipse.vex.core.internal.validator.WTPVEXValidator;
@@ -113,7 +113,7 @@
 
 	private boolean loaded;
 	private DocumentType doctype;
-	private Document document;
+	private IDocument document;
 	private Style style;
 
 	private VexWidget vexWidget;
@@ -354,7 +354,7 @@
 			doctype = documentContentModel.getDocumentType();
 			style = documentContentModel.getStyle();
 
-			final Validator validator = new WTPVEXValidator(documentContentModel);
+			final IValidator validator = new WTPVEXValidator(documentContentModel);
 			if (validator != null) {
 				document.setValidator(validator);
 				if (debugging) {
@@ -718,7 +718,7 @@
 		}
 	};
 
-	private final DocumentListener documentListener = new DocumentListener() {
+	private final IDocumentListener documentListener = new IDocumentListener() {
 
 		public void attributeChanged(final DocumentEvent e) {
 			setDirty();
@@ -779,7 +779,7 @@
 
 	private String getLocationPath() {
 		final List<String> path = new ArrayList<String>();
-		Element element = vexWidget.getCurrentElement();
+		IElement element = vexWidget.getCurrentElement();
 		while (element != null) {
 			path.add(element.getPrefixedName());
 			element = element.getParentElement();
@@ -806,14 +806,14 @@
 			final PropertySheetPage page = new PropertySheetPage();
 			page.setPropertySourceProvider(new IPropertySourceProvider() {
 				public IPropertySource getPropertySource(final Object object) {
-					if (object instanceof Element) {
+					if (object instanceof IElement) {
 						final IStructuredSelection selection = (IStructuredSelection) vexWidget.getSelection();
 						final boolean multipleElementsSelected = selection != null && selection.size() > 1;
-						final Validator validator = vexWidget.getDocument().getValidator();
-						return new ElementPropertySource((Element) object, validator, multipleElementsSelected);
+						final IValidator validator = vexWidget.getDocument().getValidator();
+						return new ElementPropertySource((IElement) object, validator, multipleElementsSelected);
 					}
-					if (object instanceof Document) {
-						return new DocumentPropertySource((Document) object);
+					if (object instanceof IDocument) {
+						return new DocumentPropertySource((IDocument) object);
 					}
 					return null;
 				}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractAddColumnHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractAddColumnHandler.java
index cc02652..f64e71a 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractAddColumnHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractAddColumnHandler.java
@@ -17,8 +17,8 @@
 import org.eclipse.core.commands.AbstractHandler;
 import org.eclipse.core.commands.ExecutionEvent;
 import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.dom.CopyOfElement;
-import org.eclipse.vex.core.internal.dom.Element;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 
 /**
@@ -51,18 +51,18 @@
 			return;
 		}
 
-		final List<Element> cellsToDup = new ArrayList<Element>();
+		final List<IElement> cellsToDup = new ArrayList<IElement>();
 		VexHandlerUtil.iterateTableCells(widget, new TableCellCallbackAdapter() {
 			@Override
 			public void onCell(final Object row, final Object cell, final int rowIndex, final int cellIndex) {
-				if (cellIndex == indexToDup && cell instanceof Element) {
-					cellsToDup.add((Element) cell);
+				if (cellIndex == indexToDup && cell instanceof IElement) {
+					cellsToDup.add((IElement) cell);
 				}
 			}
 		});
 
 		int finalOffset = -1;
-		for (final Element element : cellsToDup) {
+		for (final IElement element : cellsToDup) {
 			if (finalOffset == -1) {
 				finalOffset = element.getStartOffset() + 1;
 			}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractAddRowHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractAddRowHandler.java
index f6d84a2..012e4a8 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractAddRowHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractAddRowHandler.java
@@ -15,8 +15,8 @@
 import java.util.List;
 
 import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.dom.CopyOfElement;
-import org.eclipse.vex.core.internal.dom.Element;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 
 /**
@@ -92,15 +92,15 @@
 		widget.moveTo(insertOffset);
 
 		for (final RowCells rowCells : rowCellsToInsert) {
-			if (rowCells.row instanceof Element) {
-				final Element rowElement = (Element) rowCells.row;
+			if (rowCells.row instanceof IElement) {
+				final IElement rowElement = (IElement) rowCells.row;
 				widget.insertElement(rowElement.getQualifiedName()).accept(new CopyOfElement(rowElement));
 			}
 
 			//cells that are to be inserted.
 			for (final Object cell : rowCells.cells) {
-				if (cell instanceof Element) {
-					final Element cellElement = (Element) cell;
+				if (cell instanceof IElement) {
+					final IElement cellElement = (IElement) cell;
 					widget.insertElement(cellElement.getQualifiedName()).accept(new CopyOfElement(cellElement));
 					widget.moveBy(+1);
 				} else {
@@ -108,7 +108,7 @@
 				}
 			}
 
-			if (rowCells.row instanceof Element) {
+			if (rowCells.row instanceof IElement) {
 				widget.moveBy(+1);
 			}
 		}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractMoveColumnHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractMoveColumnHandler.java
index 859b6ef..1efb279 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractMoveColumnHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractMoveColumnHandler.java
@@ -16,7 +16,7 @@
 import org.eclipse.core.commands.AbstractHandler;
 import org.eclipse.core.commands.ExecutionEvent;
 import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.vex.core.internal.dom.ContentRange;
+import org.eclipse.vex.core.dom.ContentRange;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 
 /**
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractMoveRowHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractMoveRowHandler.java
index 9d327f3..42e5202 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractMoveRowHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractMoveRowHandler.java
@@ -11,7 +11,7 @@
 package org.eclipse.vex.ui.internal.handlers;
 
 import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.vex.core.internal.dom.ContentRange;
+import org.eclipse.vex.core.dom.ContentRange;
 import org.eclipse.vex.ui.internal.handlers.VexHandlerUtil.SelectedRows;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractRemoveTableCellsHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractRemoveTableCellsHandler.java
index 2dcd47d..334cfe9 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractRemoveTableCellsHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractRemoveTableCellsHandler.java
@@ -13,7 +13,7 @@
 import java.util.List;
 
 import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.vex.core.internal.dom.ContentRange;
+import org.eclipse.vex.core.dom.ContentRange;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 
 /**
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractVexWidgetHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractVexWidgetHandler.java
index d838c02..5842046 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractVexWidgetHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/AbstractVexWidgetHandler.java
@@ -19,7 +19,7 @@
 import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.menus.UIElement;
 import org.eclipse.ui.services.IServiceScopes;
-import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.ui.internal.editor.Messages;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 
@@ -60,7 +60,7 @@
 			return;
 		}
 
-		final Element currentElement = widget.getCurrentElement();
+		final IElement currentElement = widget.getCurrentElement();
 		final String name;
 		if (currentElement != null) {
 			name = currentElement.getPrefixedName();
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/DuplicateSelectionHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/DuplicateSelectionHandler.java
index 3dd95bc..cb49d93 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/DuplicateSelectionHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/DuplicateSelectionHandler.java
@@ -11,7 +11,7 @@
 package org.eclipse.vex.ui.internal.handlers;
 
 import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 
 /**
@@ -24,7 +24,7 @@
 		widget.doWork(new Runnable() {
 			public void run() {
 				if (!widget.hasSelection()) {
-					final Node node = widget.getCurrentNode();
+					final INode node = widget.getCurrentNode();
 
 					// Can't duplicate the document
 					if (node.getParent() == null) {
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/MoveSelectionUpHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/MoveSelectionUpHandler.java
index e466d84..2c94d1c 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/MoveSelectionUpHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/MoveSelectionUpHandler.java
@@ -11,8 +11,8 @@
 package org.eclipse.vex.ui.internal.handlers;
 
 import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.vex.core.internal.dom.ContentRange;
-import org.eclipse.vex.core.internal.dom.Node;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.layout.BlockBox;
 import org.eclipse.vex.core.internal.layout.Box;
 import org.eclipse.vex.core.internal.widget.IBoxFilter;
@@ -52,7 +52,7 @@
 			// box.getStartPosition() + 1, but this would be a VERY large
 			// change.)
 			System.out.println("Box is " + box);
-			final Node node = box.getNode();
+			final INode node = box.getNode();
 			if (node != null) {
 				widget.moveTo(node.getEndOffset() + 1);
 				widget.moveTo(node.getStartOffset(), true);
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/RemoveTagHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/RemoveTagHandler.java
index 5efc7c4..0b4cea4 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/RemoveTagHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/RemoveTagHandler.java
@@ -15,8 +15,8 @@
 import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.ui.commands.IElementUpdater;
 import org.eclipse.ui.menus.UIElement;
-import org.eclipse.vex.core.internal.dom.DocumentFragment;
-import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.dom.IDocumentFragment;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 
 /**
@@ -41,10 +41,10 @@
 	public void execute(final VexWidget widget) throws ExecutionException {
 		widget.doWork(new Runnable() {
 			public void run() {
-				final Element element = widget.getDocument().getElementForInsertionAt(widget.getCaretOffset());
+				final IElement element = widget.getDocument().getElementForInsertionAt(widget.getCaretOffset());
 				widget.moveTo(element.getStartOffset() + 1, false);
 				widget.moveTo(element.getEndOffset(), true);
-				final DocumentFragment frag = widget.getSelectedFragment();
+				final IDocumentFragment frag = widget.getSelectedFragment();
 				widget.deleteSelection();
 				widget.moveBy(-1, false);
 				widget.moveBy(2, true);
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitBlockElementHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitBlockElementHandler.java
index e0be8ab..825eced 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitBlockElementHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitBlockElementHandler.java
@@ -15,14 +15,14 @@
 import java.util.List;
 
 import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IDocumentFragment;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.VEXCorePlugin;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.Styles;
 import org.eclipse.vex.core.internal.dom.CopyOfElement;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentFragment;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.eclipse.vex.core.internal.widget.IVexWidget;
 import org.eclipse.vex.ui.internal.swt.VexWidget;
 
@@ -36,14 +36,14 @@
 
 	@Override
 	public void execute(final VexWidget widget) throws ExecutionException {
-		Element element = widget.getCurrentElement();
+		IElement element = widget.getCurrentElement();
 		if (element == null) {
 			return; // we are not in an element, so we bail out here
 		}
 		Styles styles = widget.getStyleSheet().getStyles(element);
 		while (!styles.isBlock()) {
 			element = element.getParentElement();
-			if (element == null || element.getParent() instanceof Document) {
+			if (element == null || element.getParent() instanceof IDocument) {
 				return; // we reached the root element which cannot be split 
 			}
 			styles = widget.getStyleSheet().getStyles(element);
@@ -59,7 +59,7 @@
 	 * @param node
 	 *            Node to be split.
 	 */
-	protected void splitElement(final IVexWidget vexWidget, final Node node) {
+	protected void splitElement(final IVexWidget vexWidget, final INode node) {
 
 		vexWidget.doWork(new Runnable() {
 			public void run() {
@@ -80,13 +80,13 @@
 					// and put them in a list of fragments to be reconstructed
 					// when
 					// we clone the element.
-					final List<Element> children = new ArrayList<Element>();
-					final List<DocumentFragment> frags = new ArrayList<DocumentFragment>();
-					Element child = vexWidget.getCurrentElement();
+					final List<IElement> children = new ArrayList<IElement>();
+					final List<IDocumentFragment> fragments = new ArrayList<IDocumentFragment>();
+					IElement child = vexWidget.getCurrentElement();
 					while (true) {
 						children.add(child);
 						vexWidget.moveTo(child.getEndOffset(), true);
-						frags.add(vexWidget.getSelectedFragment());
+						fragments.add(vexWidget.getSelectedFragment());
 						vexWidget.deleteSelection();
 						vexWidget.moveTo(child.getEndOffset() + 1);
 						if (child == node) {
@@ -97,12 +97,12 @@
 
 					for (int i = children.size() - 1; i >= 0; i--) {
 						child = children.get(i);
-						final DocumentFragment frag = frags.get(i);
-						final Element newChild = vexWidget.insertElement(child.getQualifiedName());
+						final IDocumentFragment fragment = fragments.get(i);
+						final IElement newChild = vexWidget.insertElement(child.getQualifiedName());
 						newChild.accept(new CopyOfElement(child));
 						final int offset = vexWidget.getCaretOffset();
-						if (frag != null) {
-							vexWidget.insertFragment(frag);
+						if (fragment != null) {
+							vexWidget.insertFragment(fragment);
 						}
 						vexWidget.moveTo(offset);
 					}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitItemHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitItemHandler.java
index fdbedfd..4dd5455 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitItemHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitItemHandler.java
@@ -11,9 +11,9 @@
 package org.eclipse.vex.ui.internal.handlers;
 
 import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.StyleSheet;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.eclipse.vex.core.internal.layout.Box;
 import org.eclipse.vex.core.internal.layout.TableRowBox;
 import org.eclipse.vex.core.internal.widget.IBoxFilter;
@@ -38,7 +38,7 @@
 				if (box instanceof TableRowBox) {
 					return true;
 				} else {
-					final Node node = box.getNode();
+					final INode node = box.getNode();
 					return node != null && ss.getStyles(node).getDisplay().equals(CSS.LIST_ITEM);
 				}
 			}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/VexHandlerUtil.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/VexHandlerUtil.java
index 079a9d5..20a3060 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/VexHandlerUtil.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/VexHandlerUtil.java
@@ -19,14 +19,14 @@
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
+import org.eclipse.vex.core.dom.IParent;
 import org.eclipse.vex.core.internal.css.CSS;
 import org.eclipse.vex.core.internal.css.StyleSheet;
-import org.eclipse.vex.core.internal.dom.ContentRange;
 import org.eclipse.vex.core.internal.dom.CopyOfElement;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
-import org.eclipse.vex.core.internal.dom.Parent;
 import org.eclipse.vex.core.internal.layout.BlockBox;
 import org.eclipse.vex.core.internal.layout.Box;
 import org.eclipse.vex.core.internal.layout.ElementOrRangeCallback;
@@ -116,8 +116,8 @@
 							firstCellIsAnonymous = true;
 						}
 					} else {
-						final Element element = (Element) cells[i].getNode();
-						final Element newElement = vexWidget.insertElement(element.getQualifiedName());
+						final IElement element = (IElement) cells[i].getNode();
+						final IElement newElement = vexWidget.insertElement(element.getQualifiedName());
 						newElement.accept(new CopyOfElement(element));
 						vexWidget.moveBy(+1);
 					}
@@ -150,8 +150,8 @@
 
 				if (!tr.isAnonymous()) {
 					vexWidget.moveBy(+1); // Move past sentinel in current row
-					final Element element = (Element) tr.getNode();
-					final Element newElement = vexWidget.insertElement(element.getQualifiedName());
+					final IElement element = (IElement) tr.getNode();
+					final IElement newElement = vexWidget.insertElement(element.getQualifiedName());
 					newElement.accept(new CopyOfElement(element));
 				}
 
@@ -180,7 +180,7 @@
 	 */
 	public static int getCurrentColumnIndex(final IVexWidget vexWidget) {
 
-		final Element row = getCurrentTableRow(vexWidget);
+		final IElement row = getCurrentTableRow(vexWidget);
 
 		if (row == null) {
 			return -1;
@@ -191,14 +191,14 @@
 		LayoutUtils.iterateTableCells(vexWidget.getStyleSheet(), row, new ElementOrRangeCallback() {
 			private int i = 0;
 
-			public void onElement(final Element child, final String displayStyle) {
+			public void onElement(final IElement child, final String displayStyle) {
 				if (offset > child.getStartOffset() && offset <= child.getEndOffset()) {
 					column[0] = i;
 				}
 				i++;
 			}
 
-			public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				i++;
 			}
 		});
@@ -212,9 +212,9 @@
 	 * @param vexWidget
 	 *            IVexWidget to use.
 	 */
-	public static Element getCurrentTableRow(final IVexWidget vexWidget) {
+	public static IElement getCurrentTableRow(final IVexWidget vexWidget) {
 		final StyleSheet styleSheet = vexWidget.getStyleSheet();
-		Element element = vexWidget.getCurrentElement();
+		IElement element = vexWidget.getCurrentElement();
 
 		while (element != null) {
 			if (styleSheet.getStyles(element).getDisplay().equals(CSS.TABLE_ROW)) {
@@ -253,8 +253,8 @@
 		}
 
 		int previousSiblingStart = -1;
-		final Element parent = vexWidget.getDocument().getElementForInsertionAt(startOffset);
-		for (final Node child : parent.children()) {
+		final IElement parent = vexWidget.getDocument().getElementForInsertionAt(startOffset);
+		for (final INode child : parent.children()) {
 			if (startOffset == child.getStartOffset()) {
 				break;
 			}
@@ -343,19 +343,19 @@
 
 			final private int[] rowIndex = { 0 };
 
-			public void onElement(final Element row, final String displayStyle) {
+			public void onElement(final IElement row, final String displayStyle) {
 
 				callback.startRow(row, rowIndex[0]);
 
 				LayoutUtils.iterateTableCells(ss, row, new ElementOrRangeCallback() {
 					private int cellIndex = 0;
 
-					public void onElement(final Element cell, final String displayStyle) {
+					public void onElement(final IElement cell, final String displayStyle) {
 						callback.onCell(row, cell, rowIndex[0], cellIndex);
 						cellIndex++;
 					}
 
-					public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+					public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 						callback.onCell(row, new ContentRange(startOffset, endOffset), rowIndex[0], cellIndex);
 						cellIndex++;
 					}
@@ -366,7 +366,7 @@
 				rowIndex[0]++;
 			}
 
-			public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 
 				final ContentRange row = new ContentRange(startOffset, endOffset);
 				callback.startRow(row, rowIndex[0]);
@@ -374,12 +374,12 @@
 				LayoutUtils.iterateTableCells(ss, parent, startOffset, endOffset, new ElementOrRangeCallback() {
 					private int cellIndex = 0;
 
-					public void onElement(final Element cell, final String displayStyle) {
+					public void onElement(final IElement cell, final String displayStyle) {
 						callback.onCell(row, cell, rowIndex[0], cellIndex);
 						cellIndex++;
 					}
 
-					public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+					public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 						callback.onCell(row, new ContentRange(startOffset, endOffset), rowIndex[0], cellIndex);
 						cellIndex++;
 					}
@@ -456,13 +456,13 @@
 	public static void iterateTableRows(final IVexWidget vexWidget, final ElementOrRangeCallback callback) {
 
 		final StyleSheet ss = vexWidget.getStyleSheet();
-		final Document doc = vexWidget.getDocument();
+		final IDocument doc = vexWidget.getDocument();
 		final int offset = vexWidget.getCaretOffset();
 
 		// This may or may not be a table
 		// In any case, it's the element that contains the top-level table
 		// children
-		Element table = doc.getElementForInsertionAt(offset);
+		IElement table = doc.getElementForInsertionAt(offset);
 
 		while (table != null && !LayoutUtils.isTableChild(ss, table)) {
 			table = table.getParentElement();
@@ -476,17 +476,17 @@
 			return;
 		}
 
-		final List<Element> tableChildren = new ArrayList<Element>();
+		final List<IElement> tableChildren = new ArrayList<IElement>();
 		final boolean[] found = new boolean[] { false };
 		LayoutUtils.iterateChildrenByDisplayStyle(ss, LayoutUtils.TABLE_CHILD_STYLES, table, new ElementOrRangeCallback() {
-			public void onElement(final Element child, final String displayStyle) {
+			public void onElement(final IElement child, final String displayStyle) {
 				if (offset >= child.getStartOffset() && offset <= child.getEndOffset()) {
 					found[0] = true;
 				}
 				tableChildren.add(child);
 			}
 
-			public void onRange(final Parent parent, final int startOffset, final int endOffset) {
+			public void onRange(final IParent parent, final int startOffset, final int endOffset) {
 				if (!found[0]) {
 					tableChildren.clear();
 				}
@@ -510,8 +510,8 @@
 	 *            Element or IntRange to be inspected.
 	 */
 	public static ContentRange getInnerRange(final Object elementOrRange) {
-		if (elementOrRange instanceof Element) {
-			final Element element = (Element) elementOrRange;
+		if (elementOrRange instanceof IElement) {
+			final IElement element = (IElement) elementOrRange;
 			return new ContentRange(element.getStartOffset() + 1, element.getEndOffset());
 		} else {
 			return (ContentRange) elementOrRange;
@@ -526,8 +526,8 @@
 	 *            Element or IntRange to be inspected.
 	 */
 	public static ContentRange getOuterRange(final Object elementOrRange) {
-		if (elementOrRange instanceof Element) {
-			final Element element = (Element) elementOrRange;
+		if (elementOrRange instanceof IElement) {
+			final IElement element = (IElement) elementOrRange;
 			return new ContentRange(element.getStartOffset(), element.getEndOffset() + 1);
 		} else {
 			return (ContentRange) elementOrRange;
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/namespace/EditNamespacesController.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/namespace/EditNamespacesController.java
index c4d9962..edf26f0 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/namespace/EditNamespacesController.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/namespace/EditNamespacesController.java
@@ -15,7 +15,7 @@
 import java.util.List;

 

 import org.eclipse.core.runtime.Assert;

-import org.eclipse.vex.core.internal.dom.Element;

+import org.eclipse.vex.core.dom.IElement;

 import org.eclipse.vex.core.internal.widget.IVexWidget;

 

 /**

@@ -24,7 +24,7 @@
 public class EditNamespacesController {

 

 	private final IVexWidget widget;

-	private final Element element;

+	private final IElement element;

 

 	private String defaultNamespaceURI;

 

@@ -38,7 +38,7 @@
 		namespaceDefinitions = getNamespaceDefinitions(element);

 	}

 

-	private static String getDefaultNamespaceURI(final Element element) {

+	private static String getDefaultNamespaceURI(final IElement element) {

 		final String result = element.getDeclaredDefaultNamespaceURI();

 		if (result == null) {

 			return "";

@@ -46,7 +46,7 @@
 		return result;

 	}

 

-	private static List<EditableNamespaceDefinition> getNamespaceDefinitions(final Element element) {

+	private static List<EditableNamespaceDefinition> getNamespaceDefinitions(final IElement element) {

 		final ArrayList<EditableNamespaceDefinition> result = new ArrayList<EditableNamespaceDefinition>();

 		for (final String prefix : element.getDeclaredNamespacePrefixes()) {

 			result.add(new EditableNamespaceDefinition(prefix, element.getNamespaceURI(prefix)));

diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/DefaultOutlineProvider.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/DefaultOutlineProvider.java
index f3ae7a1..3ec4890 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/DefaultOutlineProvider.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/DefaultOutlineProvider.java
@@ -18,10 +18,10 @@
 import org.eclipse.jface.viewers.ITreeContentProvider;
 import org.eclipse.jface.viewers.LabelProvider;
 import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.css.StyleSheet;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.IWhitespacePolicy;
+import org.eclipse.vex.core.internal.io.IWhitespacePolicy;
 import org.eclipse.vex.core.internal.widget.CssWhitespacePolicy;
 import org.eclipse.vex.ui.internal.editor.VexEditor;
 
@@ -37,7 +37,7 @@
 		labelProvider = new LabelProvider() {
 			@Override
 			public String getText(final Object o) {
-				final Element e = (Element) o;
+				final IElement e = (IElement) o;
 				String s = e.getText();
 				if (s.length() > 30) {
 					s = s.substring(0, 30) + "..."; //$NON-NLS-1$
@@ -56,8 +56,8 @@
 		return labelProvider;
 	}
 
-	public Element getOutlineElement(final Element child) {
-		Element element = child;
+	public IElement getOutlineElement(final IElement child) {
+		IElement element = child;
 		while (element != null) {
 
 			// block element?
@@ -66,7 +66,7 @@
 			}
 
 			// root?
-			final Element parent = element.getParentElement();
+			final IElement parent = element.getParentElement();
 			if (parent == null) {
 				return element;
 			}
@@ -84,9 +84,8 @@
 	private class ContentProvider implements ITreeContentProvider {
 
 		public Object[] getChildren(final Object parentElement) {
-			final List<Element> blockChildren = new ArrayList<Element>();
-			final List<Element> children = ((Element) parentElement).getChildElements();
-			for (final Element child : children) {
+			final List<IElement> blockChildren = new ArrayList<IElement>();
+			for (final IElement child : ((IElement) parentElement).childElements()) {
 				if (whitespacePolicy.isBlock(child)) {
 					blockChildren.add(child);
 				}
@@ -95,15 +94,15 @@
 		}
 
 		public Object getParent(final Object element) {
-			return ((Element) element).getParent();
+			return ((IElement) element).getParent();
 		}
 
 		public boolean hasChildren(final Object o) {
-			return hasBlockChild((Element) o);
+			return hasBlockChild((IElement) o);
 		}
 
 		public Object[] getElements(final Object inputElement) {
-			return new Object[] { ((Document) inputElement).getRootElement() };
+			return new Object[] { ((IDocument) inputElement).getRootElement() };
 			// return this.getChildren(inputElement);
 		}
 
@@ -117,8 +116,8 @@
 
 		// ====================================================== PRIVATE
 
-		private boolean hasBlockChild(final Element element) {
-			for (final Element child : element.getChildElements()) {
+		private boolean hasBlockChild(final IElement element) {
+			for (final IElement child : element.childElements()) {
 				if (whitespacePolicy.isBlock(child)) {
 					return true;
 				}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/DocumentOutlinePage.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/DocumentOutlinePage.java
index 2685f24..73280dc 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/DocumentOutlinePage.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/DocumentOutlinePage.java
@@ -31,7 +31,7 @@
 import org.eclipse.ui.part.IPageSite;
 import org.eclipse.ui.part.Page;
 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
-import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.ui.internal.VexPlugin;
 import org.eclipse.vex.ui.internal.config.DocumentType;
 import org.eclipse.vex.ui.internal.editor.IVexEditorListener;
@@ -209,9 +209,9 @@
 			if (event.getSource() instanceof VexWidget) {
 				final VexWidget vexWidget = (VexWidget) event.getSource();
 				if (vexWidget.isFocusControl() && getTreeViewer() != null) {
-					final Element element = vexWidget.getCurrentElement();
+					final IElement element = vexWidget.getCurrentElement();
 					if (element != null) {
-						final Element outlineElement = outlineProvider.getOutlineElement(element);
+						final IElement outlineElement = outlineProvider.getOutlineElement(element);
 						getTreeViewer().refresh(outlineElement);
 						getTreeViewer().setSelection(new StructuredSelection(outlineElement), true);
 					} else {
@@ -225,7 +225,7 @@
 					final TreeItem[] selected = treeViewer.getTree().getSelection();
 					if (selected.length > 0) {
 
-						final Element element = (Element) selected[0].getData();
+						final IElement element = (IElement) selected[0].getData();
 						final VexWidget vexWidget = vexEditor.getVexWidget();
 
 						// Moving to the end of the element first is a cheap
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/IOutlineProvider.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/IOutlineProvider.java
index a27f15f..807f4c9 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/IOutlineProvider.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/outline/IOutlineProvider.java
@@ -12,7 +12,7 @@
 
 import org.eclipse.jface.viewers.IBaseLabelProvider;
 import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.ui.internal.editor.VexEditor;
 
 /**
@@ -45,7 +45,7 @@
 	 * returned directly.
 	 * 
 	 * @param child
-	 *            Element for which to find the outline element.
+	 *            element for which to find the outline element.
 	 */
-	public Element getOutlineElement(Element child);
+	public IElement getOutlineElement(IElement child);
 }
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/property/DocumentPropertySource.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/property/DocumentPropertySource.java
index e51c875..41a463d 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/property/DocumentPropertySource.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/property/DocumentPropertySource.java
@@ -13,7 +13,7 @@
 import org.eclipse.ui.views.properties.IPropertyDescriptor;

 import org.eclipse.ui.views.properties.IPropertySource2;

 import org.eclipse.ui.views.properties.PropertyDescriptor;

-import org.eclipse.vex.core.internal.dom.Document;

+import org.eclipse.vex.core.dom.IDocument;

 

 /**

  * @author Florian Thienel

@@ -25,9 +25,9 @@
 	private static final String DOCUMENT_URI = "documentUri";

 	private static final String ENCODING = "encoding";

 

-	private final Document document;

+	private final IDocument document;

 

-	public DocumentPropertySource(final Document document) {

+	public DocumentPropertySource(final IDocument document) {

 		this.document = document;

 	}

 

diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/property/ElementPropertySource.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/property/ElementPropertySource.java
index 1119157..825710c 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/property/ElementPropertySource.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/property/ElementPropertySource.java
@@ -20,11 +20,11 @@
 import org.eclipse.ui.views.properties.IPropertySource2;
 import org.eclipse.ui.views.properties.PropertyDescriptor;
 import org.eclipse.ui.views.properties.TextPropertyDescriptor;
-import org.eclipse.vex.core.internal.dom.Attribute;
-import org.eclipse.vex.core.internal.dom.DocumentValidationException;
-import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.dom.DocumentValidationException;
+import org.eclipse.vex.core.dom.IAttribute;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.IValidator;
 import org.eclipse.vex.core.internal.dom.Namespace;
-import org.eclipse.vex.core.internal.dom.Validator;
 import org.eclipse.vex.core.internal.validator.AttributeDefinition;
 import org.eclipse.vex.ui.internal.editor.Messages;
 
@@ -40,11 +40,11 @@
 	private static final String ATTRIBUTES_CATEGORY = "Attributes";
 	private static final String NAMESPACES_CATEGORY = "Namespaces";
 
-	private final Element element;
-	private final Validator validator;
+	private final IElement element;
+	private final IValidator validator;
 	private final boolean multipleElementsSelected;
 
-	public ElementPropertySource(final Element element, final Validator validator, final boolean multipleElementsSelected) {
+	public ElementPropertySource(final IElement element, final IValidator validator, final boolean multipleElementsSelected) {
 		this.element = element;
 		this.validator = validator;
 		this.multipleElementsSelected = multipleElementsSelected;
@@ -123,7 +123,7 @@
 				return Messages.getString("ElementPropertySource.multiple"); //$NON-NLS-1$
 			}
 
-			final Attribute attribute = element.getAttribute(attributeDefinition.getName());
+			final IAttribute attribute = element.getAttribute(attributeDefinition.getName());
 			final String value;
 			if (attribute != null) {
 				value = attribute.getValue();
@@ -171,7 +171,7 @@
 
 		if (id instanceof AttributeDefinition) {
 			final AttributeDefinition attributeDefinition = (AttributeDefinition) id;
-			final Attribute attribute = element.getAttribute(attributeDefinition.getName());
+			final IAttribute attribute = element.getAttribute(attributeDefinition.getName());
 			if (attribute == null) {
 				return false;
 			}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/ContentAssist.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/ContentAssist.java
index 4163867..fa55e3d 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/ContentAssist.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/ContentAssist.java
@@ -53,8 +53,8 @@
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Text;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.core.ElementName;
-import org.eclipse.vex.core.internal.dom.Element;
 import org.eclipse.vex.ui.internal.Icon;
 import org.eclipse.vex.ui.internal.VexPlugin;
 import org.eclipse.vex.ui.internal.editor.Messages;
@@ -354,7 +354,7 @@
 		final ElementName[] names = widget.getValidMorphElements();
 		final AbstractVexAction[] actions = new AbstractVexAction[names.length];
 		final int caretOffset = widget.getCaretOffset();
-		final Element element = widget.getDocument().getElementForInsertionAt(caretOffset);
+		final IElement element = widget.getDocument().getElementForInsertionAt(caretOffset);
 		final String sourceName = element.getPrefixedName();
 		for (int i = 0; i < names.length; i++) {
 			final QualifiedName qualifiedName = names[i].getQualifiedName();
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/DocumentFragmentTransfer.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/DocumentFragmentTransfer.java
index 90a90f4..4cad1c8 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/DocumentFragmentTransfer.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/DocumentFragmentTransfer.java
@@ -21,8 +21,8 @@
 
 import org.eclipse.swt.dnd.ByteArrayTransfer;
 import org.eclipse.swt.dnd.TransferData;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentFragment;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IDocumentFragment;
 import org.eclipse.vex.core.internal.io.DocumentReader;
 import org.eclipse.vex.core.internal.io.DocumentWriter;
 import org.xml.sax.InputSource;
@@ -64,7 +64,7 @@
 
 	@Override
 	public void javaToNative(final Object object, final TransferData transferData) {
-		if (object == null || !(object instanceof DocumentFragment)) {
+		if (object == null || !(object instanceof IDocumentFragment)) {
 			return;
 		}
 
@@ -72,7 +72,7 @@
 			return;
 		}
 
-		final DocumentFragment fragment = (DocumentFragment) object;
+		final IDocumentFragment fragment = (IDocumentFragment) object;
 		final ByteArrayOutputStream out = new ByteArrayOutputStream();
 		try {
 			writeFragmentToStream(fragment, out);
@@ -81,7 +81,7 @@
 		super.javaToNative(out.toByteArray(), transferData);
 	}
 
-	public void writeFragmentToStream(final DocumentFragment fragment, final OutputStream out) throws IOException {
+	public void writeFragmentToStream(final IDocumentFragment fragment, final OutputStream out) throws IOException {
 		new DocumentWriter().write(fragment, out);
 	}
 
@@ -106,9 +106,9 @@
 		return null;
 	}
 
-	public DocumentFragment readFragmentFromStream(final InputStream in) throws IOException {
+	public IDocumentFragment readFragmentFromStream(final InputStream in) throws IOException {
 		try {
-			final Document document = new DocumentReader().read(new InputSource(in));
+			final IDocument document = new DocumentReader().read(new InputSource(in));
 			return document.getFragment(document.getRootElement().getRange().resizeBy(1, -1));
 		} catch (final ParserConfigurationException e) {
 			// TODO shoult never happen - log this exception?
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/VexWidget.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/VexWidget.java
index 016f8aa..d30a0b7 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/VexWidget.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/swt/VexWidget.java
@@ -51,6 +51,13 @@
 import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.vex.core.dom.ContentRange;
+import org.eclipse.vex.core.dom.DocumentValidationException;
+import org.eclipse.vex.core.dom.IComment;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IDocumentFragment;
+import org.eclipse.vex.core.dom.IElement;
+import org.eclipse.vex.core.dom.INode;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Color;
 import org.eclipse.vex.core.internal.core.ColorResource;
@@ -59,13 +66,6 @@
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.core.Rectangle;
 import org.eclipse.vex.core.internal.css.StyleSheet;
-import org.eclipse.vex.core.internal.dom.Comment;
-import org.eclipse.vex.core.internal.dom.ContentRange;
-import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentFragment;
-import org.eclipse.vex.core.internal.dom.DocumentValidationException;
-import org.eclipse.vex.core.internal.dom.Element;
-import org.eclipse.vex.core.internal.dom.Node;
 import org.eclipse.vex.core.internal.layout.Box;
 import org.eclipse.vex.core.internal.layout.BoxFactory;
 import org.eclipse.vex.core.internal.widget.HostComponent;
@@ -227,15 +227,15 @@
 		return impl.getCaretOffset();
 	}
 
-	public Element getCurrentElement() {
+	public IElement getCurrentElement() {
 		return impl.getCurrentElement();
 	}
 
-	public Node getCurrentNode() {
+	public INode getCurrentNode() {
 		return impl.getCurrentNode();
 	}
 
-	public Document getDocument() {
+	public IDocument getDocument() {
 		return impl.getDocument();
 	}
 
@@ -247,7 +247,7 @@
 		return impl.getSelectedRange();
 	}
 
-	public DocumentFragment getSelectedFragment() {
+	public IDocumentFragment getSelectedFragment() {
 		return impl.getSelectedFragment();
 	}
 
@@ -279,11 +279,11 @@
 		impl.insertChar(c);
 	}
 
-	public void insertFragment(final DocumentFragment frag) throws DocumentValidationException {
-		impl.insertFragment(frag);
+	public void insertFragment(final IDocumentFragment fragment) throws DocumentValidationException {
+		impl.insertFragment(fragment);
 	}
 
-	public Element insertElement(final QualifiedName elementName) throws DocumentValidationException {
+	public IElement insertElement(final QualifiedName elementName) throws DocumentValidationException {
 		return impl.insertElement(elementName);
 	}
 
@@ -291,7 +291,7 @@
 		impl.insertText(text);
 	}
 
-	public Comment insertComment() throws DocumentValidationException {
+	public IComment insertComment() throws DocumentValidationException {
 		return impl.insertComment();
 	}
 
@@ -357,9 +357,9 @@
 		}
 
 		final Clipboard clipboard = new Clipboard(getDisplay());
-		final DocumentFragment frag = (DocumentFragment) clipboard.getContents(DocumentFragmentTransfer.getInstance());
-		if (frag != null) {
-			insertFragment(frag);
+		final IDocumentFragment fragment = (IDocumentFragment) clipboard.getContents(DocumentFragmentTransfer.getInstance());
+		if (fragment != null) {
+			insertFragment(fragment);
 		} else {
 			pasteText();
 		}
@@ -417,7 +417,7 @@
 		impl.setReadOnly(readOnly);
 	}
 
-	public void setDocument(final Document doc, final StyleSheet styleSheet) {
+	public void setDocument(final IDocument doc, final StyleSheet styleSheet) {
 		impl.setDocument(doc, styleSheet);
 	}
 
@@ -543,7 +543,7 @@
 		public void fireSelectionChanged() {
 
 			if (hasSelection()) {
-				final List<Node> nodes = getDocument().getNodes(getSelectedRange());
+				final List<? extends INode> nodes = getDocument().getNodes(getSelectedRange());
 				selection = new StructuredSelection(nodes);
 			} else {
 				selection = new StructuredSelection(getCurrentNode());
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/wizards/NewDocumentWizard.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/wizards/NewDocumentWizard.java
index 92b9f05..eb21989 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/wizards/NewDocumentWizard.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/wizards/NewDocumentWizard.java
@@ -31,9 +31,10 @@
 import org.eclipse.ui.internal.registry.EditorRegistry;
 import org.eclipse.ui.internal.registry.FileEditorMapping;
 import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
+import org.eclipse.vex.core.dom.IDocument;
+import org.eclipse.vex.core.dom.IElement;
 import org.eclipse.vex.core.internal.dom.Document;
-import org.eclipse.vex.core.internal.dom.DocumentContentModel;
-import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.internal.io.DocumentContentModel;
 import org.eclipse.vex.core.internal.io.DocumentWriter;
 import org.eclipse.vex.core.internal.validator.WTPVEXValidator;
 import org.eclipse.vex.core.internal.widget.CssWhitespacePolicy;
@@ -71,7 +72,7 @@
 	@Override
 	public boolean performFinish() {
 		try {
-			final Document doc = createDocument(typePage.getDocumentType(), typePage.getRootElementName());
+			final IDocument doc = createDocument(typePage.getDocumentType(), typePage.getRootElementName());
 
 			final Style style = VexPlugin.getDefault().getPreferences().getPreferredStyle(typePage.getDocumentType().getPublicId());
 			if (style == null) {
@@ -115,7 +116,7 @@
 		}
 	}
 
-	private static Document createDocument(final DocumentType documentType, final String rootElementName) {
+	private static IDocument createDocument(final DocumentType documentType, final String rootElementName) {
 		if (isDTD(documentType)) {
 			return createDocumentWithDTD(documentType, rootElementName);
 		}
@@ -127,18 +128,18 @@
 		return systemId != null && systemId.toLowerCase().endsWith(".dtd");
 	}
 
-	private static Document createDocumentWithDTD(final DocumentType documentType, final String rootElementName) {
-		final Document result = new Document(new QualifiedName(null, rootElementName));
+	private static IDocument createDocumentWithDTD(final DocumentType documentType, final String rootElementName) {
+		final IDocument result = new Document(new QualifiedName(null, rootElementName));
 		result.setPublicID(documentType.getPublicId());
 		result.setSystemID(documentType.getSystemId());
 		return result;
 	}
 
-	private static Document createDocumentWithSchema(final DocumentType documentType, final String rootElementName) {
+	private static IDocument createDocumentWithSchema(final DocumentType documentType, final String rootElementName) {
 		final String defaultNamespaceUri = documentType.getPublicId();
 		final Document document = new Document(new QualifiedName(defaultNamespaceUri, rootElementName));
 
-		final Element root = document.getRootElement();
+		final IElement root = document.getRootElement();
 		root.declareDefaultNamespace(defaultNamespaceUri);
 
 		final WTPVEXValidator validator = new WTPVEXValidator(new DocumentContentModel(null, null, null, root));
diff --git a/org.eclipse.vex.xhtml/META-INF/MANIFEST.MF b/org.eclipse.vex.xhtml/META-INF/MANIFEST.MF
index 6b3b865..1d2dca3 100644
--- a/org.eclipse.vex.xhtml/META-INF/MANIFEST.MF
+++ b/org.eclipse.vex.xhtml/META-INF/MANIFEST.MF
@@ -6,9 +6,8 @@
 Bundle-Vendor: %providerName
 Require-Bundle: org.eclipse.vex.ui;bundle-version="[1.0.0,2.0.0)",
  org.eclipse.vex.core;bundle-version="[1.0.0,2.0.0)",
- org.eclipse.jface;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.emf.common;bundle-version="[2.4.1,3.0.0)",
- org.eclipse.emf.ecore;bundle-version="[2.4.1,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.4.0,5.0.0)",
+ org.eclipse.jface;bundle-version="[3.4.0,5.0.0)",
  org.eclipse.wst.standard.schemas;bundle-version="[1.0.0,2.0.0)"
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Bundle-ClassPath: .
diff --git a/org.eclipse.vex.xhtml/src/org/eclipse/vex/xhtml/XhtmlOutlineProvider.java b/org.eclipse.vex.xhtml/src/org/eclipse/vex/xhtml/XhtmlOutlineProvider.java
index 5a16d26..7b5aad1 100644
--- a/org.eclipse.vex.xhtml/src/org/eclipse/vex/xhtml/XhtmlOutlineProvider.java
+++ b/org.eclipse.vex.xhtml/src/org/eclipse/vex/xhtml/XhtmlOutlineProvider.java
@@ -18,8 +18,9 @@
 import org.eclipse.jface.viewers.ITreeContentProvider;

 import org.eclipse.jface.viewers.LabelProvider;

 import org.eclipse.jface.viewers.Viewer;

-import org.eclipse.vex.core.internal.dom.Document;

-import org.eclipse.vex.core.internal.dom.Element;

+import org.eclipse.vex.core.dom.Filters;

+import org.eclipse.vex.core.dom.IDocument;

+import org.eclipse.vex.core.dom.IElement;

 import org.eclipse.vex.ui.internal.editor.VexEditor;

 import org.eclipse.vex.ui.internal.outline.IOutlineProvider;

 

@@ -39,8 +40,8 @@
 		return labelProvider;

 	}

 

-	public Element getOutlineElement(final Element child) {

-		Element element = child;

+	public IElement getOutlineElement(final IElement child) {

+		IElement element = child;

 		while (element.getParentElement() != null) {

 

 			// TODO: compare to all structural element names

@@ -66,11 +67,11 @@
 		}

 

 		public Object[] getChildren(final Object parentElement) {

-			return getOutlineChildren((Element) parentElement);

+			return getOutlineChildren((IElement) parentElement);

 		}

 

 		public Object getParent(final Object element) {

-			final Element parent = ((Element) element).getParentElement();

+			final IElement parent = ((IElement) element).getParentElement();

 			if (parent == null) {

 				return element;

 			} else {

@@ -79,11 +80,11 @@
 		}

 

 		public boolean hasChildren(final Object element) {

-			return getOutlineChildren((Element) element).length > 0;

+			return getOutlineChildren((IElement) element).length > 0;

 		}

 

 		public Object[] getElements(final Object inputElement) {

-			final Document document = (Document) inputElement;

+			final IDocument document = (IDocument) inputElement;

 			return new Object[] { document.getRootElement() };

 		}

 

@@ -96,23 +97,23 @@
 	 * @param element

 	 * @return

 	 */

-	private Element[] getOutlineChildren(final Element element) {

-		final List children = new ArrayList();

+	private IElement[] getOutlineChildren(final IElement element) {

+		final List<IElement> children = new ArrayList<IElement>();

 		if (element.getParent() == null) {

-			final Element body = findChild(element, "body");

+			final IElement body = findChild(element, "body");

 			if (body != null) {

-				final List<Element> childElements = body.getChildElements();

+				final List<? extends IElement> childElements = body.childElements().asList();

 

 				// First, find the lowest numbered h tag available

 				String lowH = "h6";

-				for (final Element child : childElements) {

+				for (final IElement child : childElements) {

 					if (isHTag(child) && child.getLocalName().compareTo(lowH) < 0) {

 						lowH = child.getLocalName();

 					}

 				}

 

 				// Now, get all body children at that level

-				for (final Element child : childElements) {

+				for (final IElement child : childElements) {

 					if (child.getLocalName().equals(lowH)) {

 						children.add(child);

 					}

@@ -123,9 +124,8 @@
 			// between this element and the next element at the same level

 			final int level = Integer.parseInt(element.getLocalName().substring(1));

 			final String childName = "h" + (level + 1);

-			final List<Element> childElements = element.getParentElement().getChildElements();

 			boolean foundSelf = false;

-			for (final Element child : childElements) {

+			for (final IElement child : element.getParentElement().childElements()) {

 				if (child == element) {

 					foundSelf = true;

 				} else if (!foundSelf) {

@@ -138,19 +138,19 @@
 				}

 			}

 		}

-		return (Element[]) children.toArray(new Element[children.size()]);

+		return children.toArray(new IElement[children.size()]);

 	}

 

 	private final ILabelProvider labelProvider = new LabelProvider() {

 		@Override

 		public String getText(final Object o) {

 			String text;

-			final Element element = (Element) o;

+			final IElement element = (IElement) o;

 			if (element.getParent() == null) {

 				text = "html";

-				final Element head = findChild(element, "head");

+				final IElement head = findChild(element, "head");

 				if (head != null) {

-					final Element title = findChild(head, "title");

+					final IElement title = findChild(head, "title");

 					if (title != null) {

 						text = title.getText();

 					}

@@ -162,16 +162,14 @@
 		}

 	};

 

-	private Element findChild(final Element parent, final String childName) {

-		for (final Element child : parent.getChildElements()) {

-			if (child.getLocalName().equals(childName)) {

-				return child;

-			}

+	private IElement findChild(final IElement parent, final String childName) {

+		for (final IElement child : parent.childElements().matching(Filters.elementsNamed(childName))) {

+			return child;

 		}

 		return null;

 	}

 

-	private boolean isHTag(final Element element) {

+	private boolean isHTag(final IElement element) {

 		final String name = element.getLocalName();

 		return name.equals("h1") || name.equals("h2") || name.equals("h3") || name.equals("h4") || name.equals("h5") || name.equals("h6");

 	}