Merge branch 'master' into master_juno
diff --git a/org.eclipse.vex.core.tests/plugin.xml b/org.eclipse.vex.core.tests/plugin.xml
index a23c416..17a8faa 100644
--- a/org.eclipse.vex.core.tests/plugin.xml
+++ b/org.eclipse.vex.core.tests/plugin.xml
@@ -13,10 +13,18 @@
                name="http://www.eclipse.org/vex/test/content"

                uri="testResources/content.xsd">

          </uri>

+         <system

+               systemId="http://www.eclipse.org/vex/test/content.xsd"

+               uri="testResources/content.xsd">

+         </system>

          <public

                publicId="-//Eclipse Foundation//DTD Vex Test//EN"

                uri="testResources/test1.dtd">

          </public>

+       <uri

+             name="urn:org:eclipse:vex:styles:test:test.css"

+             uri="testResources/test.css">

+       </uri>

       </catalogContribution>

    </extension>

 

diff --git a/org.eclipse.vex.core.tests/pom.xml b/org.eclipse.vex.core.tests/pom.xml
index 4dfaf79..6ddf768 100644
--- a/org.eclipse.vex.core.tests/pom.xml
+++ b/org.eclipse.vex.core.tests/pom.xml
@@ -19,11 +19,6 @@
 				<groupId>org.eclipse.tycho</groupId>
 				<artifactId>tycho-surefire-plugin</artifactId>
 				<version>${tycho-version}</version>
-				<configuration>
-					<useUIHarness>true</useUIHarness>
-					<testSuite>org.eclipse.vex.core.tests</testSuite>
-					<testClass>org.eclipse.vex.core.tests.VEXCoreTestSuite</testClass>
-				</configuration>
 			</plugin>
 		</plugins>
 	</build>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java
index 28c737c..7405245 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java
@@ -1,82 +1,84 @@
-/*******************************************************************************

- * Copyright (c) 2011, 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

- * 		Carsten Hiesserich - additional tests

- *******************************************************************************/

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

-

-import static org.junit.Assert.assertEquals;

-import static org.junit.Assert.assertTrue;

-

-import java.util.List;

-

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

-import org.eclipse.vex.core.provisional.dom.IElement;

-import org.junit.Test;

-

-/**

- * @author Florian Thienel

- */

-public class BatikBehaviorTest {

-

-	@Test

-	public void pseudoElements() throws Exception {

-		final StyleSheetReader reader = new StyleSheetReader();

-		final StyleSheet styleSheet = reader.read("plan:before { display: block; font-size: 123px; }");

-		final List<Rule> rules = styleSheet.getRules();

-		assertEquals(1, rules.size());

-		final Rule rule = rules.get(0);

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

-		// The rule should match the parent of the pseudo element. See StyleSheet#getApplicableDeclarations

-		assertTrue(rule.matches(element));

-		final IElement before = styleSheet.getPseudoElement(element, "before", false);

-		final Styles beforeStyles = styleSheet.getStyles(before);

-		assertEquals("block", beforeStyles.get("display"));

-		assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);

-	}

-

-	@Test

-	public void pseudoElements_shouldInheritFromParent() throws Exception {

-		final StyleSheetReader reader = new StyleSheetReader();

-		final StyleSheet styleSheet = reader.read("plan {font-size: 123px;} plan:before { content: 'test' }");

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

-		final IElement before = styleSheet.getPseudoElement(element, "before", false);

-		final Styles beforeStyles = styleSheet.getStyles(before);

-		assertEquals("test", beforeStyles.getContent(element).get(0));

-		assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);

-	}

-

-	@Test

-	public void testNamespace() throws Exception {

-		final StyleSheetReader reader = new StyleSheetReader();

-		final StyleSheet styleSheet = reader.read("vex|plan {font-size: 123px;} vex|plan:before { content: 'test' }");

-		final Element element = new Element("vex|plan");

-		final Styles styles = styleSheet.getStyles(element);

-		assertEquals(123.0f, styles.getFontSize(), 0.0f);

-		final IElement before = styleSheet.getPseudoElement(element, "before", false);

-		final Styles beforeStyles = styleSheet.getStyles(before);

-		assertEquals("test", beforeStyles.getContent(element).get(0));

-		assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);

-	}

-

-	@Test

-	public void testNamespaceWithChildSelector() throws Exception {

-		final StyleSheetReader reader = new StyleSheetReader();

-		final StyleSheet styleSheet = reader.read("vex|parent {font-size: 123px;} vex|parent > child { content: 'child' } child {content: 'nochild'}");

-		final Element element = new Element("vex|parent");

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

-		final Element nochild = new Element("child");

-		child.setParent(element);

-		final Styles styles = styleSheet.getStyles(child);

-		assertEquals(1, styles.getContent(element).size());

-		assertEquals("child", styles.getContent(element).get(0));

-		final Styles nochildStyles = styleSheet.getStyles(nochild);

-		assertEquals("nochild", nochildStyles.getContent(element).get(0));

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2011, 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
+ * 		Carsten Hiesserich - additional tests
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.css;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.internal.dom.Namespace;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.junit.Test;
+
+/**
+ * @author Florian Thienel
+ */
+public class BatikBehaviorTest {
+
+	@Test
+	public void pseudoElements() throws Exception {
+		final StyleSheetReader reader = new StyleSheetReader();
+		final StyleSheet styleSheet = reader.read("plan:before { display: block; font-size: 123px; }");
+		final List<Rule> rules = styleSheet.getRules();
+		assertEquals(1, rules.size());
+		final Rule rule = rules.get(0);
+		final Element element = new Element("plan");
+		// The rule should match the parent of the pseudo element. See StyleSheet#getApplicableDeclarations
+		assertTrue(rule.matches(element));
+		final IElement before = styleSheet.getPseudoElement(element, "before", false);
+		final Styles beforeStyles = styleSheet.getStyles(before);
+		assertEquals("block", beforeStyles.get("display"));
+		assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);
+	}
+
+	@Test
+	public void pseudoElements_shouldInheritFromParent() throws Exception {
+		final StyleSheetReader reader = new StyleSheetReader();
+		final StyleSheet styleSheet = reader.read("plan {font-size: 123px;} plan:before { content: 'test' }");
+		final Element element = new Element("plan");
+		final IElement before = styleSheet.getPseudoElement(element, "before", false);
+		final Styles beforeStyles = styleSheet.getStyles(before);
+		assertEquals("test", beforeStyles.getContent(element).get(0));
+		assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);
+	}
+
+	@Test
+	public void testNamespace() throws Exception {
+		final StyleSheetReader reader = new StyleSheetReader();
+		final StyleSheet styleSheet = reader.read("vex|plan {font-size: 123px;} vex|plan:before { content: 'test' }");
+		final Element element = new Element(new QualifiedName(Namespace.VEX_NAMESPACE_URI, "plan"));
+		final Styles styles = styleSheet.getStyles(element);
+		assertEquals(123.0f, styles.getFontSize(), 0.0f);
+		final IElement before = styleSheet.getPseudoElement(element, "before", false);
+		final Styles beforeStyles = styleSheet.getStyles(before);
+		assertEquals("test", beforeStyles.getContent(element).get(0));
+		assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);
+	}
+
+	@Test
+	public void testNamespaceWithChildSelector() throws Exception {
+		final StyleSheetReader reader = new StyleSheetReader();
+		final StyleSheet styleSheet = reader.read("vex|parent {font-size: 123px;} vex|parent > child { content: 'child' } child {content: 'nochild'}");
+		final Element element = new Element(new QualifiedName(Namespace.VEX_NAMESPACE_URI, "parent"));
+		final Element child = new Element("child");
+		final Element nochild = new Element("child");
+		child.setParent(element);
+		final Styles styles = styleSheet.getStyles(child);
+		assertEquals(1, styles.getContent(element).size());
+		assertEquals("child", styles.getContent(element).get(0));
+		final Styles nochildStyles = styleSheet.getStyles(nochild);
+		assertEquals("nochild", nochildStyles.getContent(element).get(0));
+	}
+}
\ No newline at end of file
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 a0e2cc3..3389232 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
@@ -12,6 +12,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import java.net.URL;
 
@@ -582,4 +583,10 @@
 		element.setAttribute("attribute", "After");
 		assertEquals("After", styles.getContent(element).get(0));
 	}
+
+	@Test
+	public void testCatalogImport() throws Exception {
+		final StyleSheet ss = parseStyleSheetResource("testCatalog.css");
+		assertTrue(ss.getRules().size() > 0);
+	}
 }
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/testCatalog.css b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/testCatalog.css
new file mode 100644
index 0000000..d9fc687
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/testCatalog.css
@@ -0,0 +1,2 @@
+/* Stylesheet for unit testing */
+@import url(urn:org:eclipse:vex:styles:test:test.css)
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AttributeTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AttributeTest.java
new file mode 100644
index 0000000..bbfe332
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/AttributeTest.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Carsten Hiesserich 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:
+ *     Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.dom;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.provisional.dom.IDocument;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.junit.Test;
+
+public class AttributeTest {
+
+	@Test
+	public void testWithoutNamespace() throws Exception {
+		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"));
+
+		a.setAttribute("attr1", "attr1Val");
+		assertEquals("Expected attribute count", 1, a.getAttributes().size());
+		assertEquals("attr1Val", a.getAttribute("attr1").getValue());
+		assertEquals("attr1Val", a.getAttributeValue("attr1"));
+		a.removeAttribute("attr1");
+		assertEquals("Expected attribute count", 0, a.getAttributes().size());
+
+		ns.setAttribute("attr2", "attr2Val");
+		assertEquals("Expected attribute count", 1, ns.getAttributes().size());
+		assertEquals("attr2Val", ns.getAttribute("attr2").getValue());
+		assertEquals("attr2Val", ns.getAttributeValue("attr2"));
+		ns.removeAttribute("attr2");
+		assertEquals("Expected attribute count", 0, ns.getAttributes().size());
+	}
+
+	@Test
+	public void testWithNamespace() throws Exception {
+		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"));
+
+		a.setAttribute(new QualifiedName("http://namespace/attr", "attr1"), "attr1Val");
+		assertEquals("Expected attribute count", 1, a.getAttributes().size());
+		assertEquals("attr1Val", a.getAttribute(new QualifiedName("http://namespace/attr", "attr1")).getValue());
+		assertEquals("attr1Val", a.getAttributeValue(new QualifiedName("http://namespace/attr", "attr1")));
+		a.removeAttribute(new QualifiedName("http://namespace/attr", "attr1"));
+		assertEquals("Expected attribute count", 0, a.getAttributes().size());
+
+		ns.setAttribute(new QualifiedName("http://namespace/attr", "attr2"), "attr2Val");
+		assertEquals("Expected attribute count", 1, ns.getAttributes().size());
+		assertEquals("attr2Val", ns.getAttribute(new QualifiedName("http://namespace/attr", "attr2")).getValue());
+		assertEquals("attr2Val", ns.getAttributeValue(new QualifiedName("http://namespace/attr", "attr2")));
+		ns.removeAttribute(new QualifiedName("http://namespace/attr", "attr2"));
+		assertEquals("Expected attribute count", 0, ns.getAttributes().size());
+	}
+}
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 195b73a..26a09ff 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
@@ -63,6 +63,7 @@
 		final RootBox parentBox = new RootBox(context, doc, 500);
 
 		final BlockElementBox box = new BlockElementBox(context, parentBox, doc.getRootElement());
+		box.setWidth(parentBox.getWidth());
 
 		final List<Box> childrenList = box.createChildren(context);
 		final Box[] children = childrenList.toArray(new Box[childrenList.size()]);
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTests.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTest.java
similarity index 98%
rename from org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTests.java
rename to org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTest.java
index 9d6dcba..c2d0282 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTests.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/L1DeletionTest.java
@@ -21,7 +21,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class L1DeletionTests {
+public class L1DeletionTest {
 
 	private IDocument document;
 	private IElement child;
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 2c7e02b..e88bff0 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
@@ -4,7 +4,7 @@
  * 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

  * 		Carsten Hiesserich - test for handling of attribute namespaces in FindUndeclaredNamespacesVisitor

@@ -226,7 +226,7 @@
 		element.setAttribute(new QualifiedName("http://namespace/uri/2", "attribute3"), "value3");

 

 		assertEquals("attribute1", element.getAttribute("attribute1").getPrefixedName());

-		assertEquals("attribute2", element.getAttribute(new QualifiedName("http://namespace/uri/1", "attribute2")).getPrefixedName());

+		assertEquals("ns1:attribute2", element.getAttribute(new QualifiedName("http://namespace/uri/1", "attribute2")).getPrefixedName());

 		assertEquals("ns2:attribute3", element.getAttribute(new QualifiedName("http://namespace/uri/2", "attribute3")).getPrefixedName());

 	}

 

@@ -280,25 +280,26 @@
 		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 IElement rootElement = document.getRootElement();

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

+		assertFalse(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")));

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

 

 		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")));

+		assertTrue(firstNestedElement.getAttributeNames().contains(new QualifiedName(null, "attr4")));

 

 		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")));

+		assertTrue(secondNestedElement.getAttributeNames().contains(new QualifiedName(null, "attr6")));

 	}

 

 	@Test

 	public void readWriteCycle() throws Exception {

+		// Caution: Vex sorts attributes on writing, so the order of attributes may change

 		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> ";

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

 		final IDocument document = readDocumentFromString(inputContent);

 

 		final DocumentWriter documentWriter = new DocumentWriter();

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 678b831..c894112 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
@@ -4,7 +4,7 @@
  * 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

  *		Carsten Hiesserich - extended insert / remove tests for nodes with text (bug 408731)

@@ -453,6 +453,48 @@
 	}

 

 	@Test

+	public void shouldReturnChildAtOffset() throws Exception {

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

+		final TestChild child1 = addTestChild();

+		content.insertText(child1.getEndOffset(), "Child1");

+

+		assertSame(child1, parent.getChildAt(9));

+	}

+

+	@Test

+	public void shouldReturnTextAtOffsetBetweenChildren() throws Exception {

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

+		final TestChild child1 = addTestChild();

+		content.insertText(child1.getEndOffset(), "Child1");

+		content.insertText(parent.getEndOffset(), " Gap ");

+		final TestChild child2 = addTestChild();

+		content.insertText(child2.getEndOffset(), "Child2");

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

+

+		final INode text = parent.children().get(2);

+

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

+	}

+

+	@Test

+	public void shouldReturnTextAtOffsetBeforeFirstChild() throws Exception {

+		setUpChildNodes();

+

+		final INode text = parent.children().get(0);

+

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

+	}

+

+	@Test

+	public void shouldReturnTextAtOffsetAfterLastChild() throws Exception {

+		setUpChildNodes();

+

+		final INode text = parent.children().get(3);

+

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

+	}

+

+	@Test

 	public void shouldReturnTextWithinBoundaries() throws Exception {

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

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

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java
index e643210..52e3aa7 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/io/DocumentContentModelTest.java
@@ -16,8 +16,6 @@
 import static org.junit.Assert.assertNull;

 import static org.junit.Assert.assertTrue;

 

-import java.net.URL;

-

 import org.eclipse.core.runtime.QualifiedName;

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

 import org.eclipse.vex.core.provisional.dom.DocumentContentModel;

@@ -99,17 +97,24 @@
 	}

 

 	@Test

-	public void resolveSchemaIdentifier() throws Exception {

-		final URL resolvedUrl = model.resolveSchemaIdentifier(TestResources.TEST_DTD);

+	public void resolveSchemaBySchemaLocation() throws Exception {

+		final String resolvedUrl = model.resolveResourceURI(null, "http://www.eclipse.org/vex/test/content.xsd");

 		assertNotNull(resolvedUrl);

-		assertTrue(resolvedUrl.toString().contains(VEXCoreTestPlugin.PLUGIN_ID));

+		assertTrue(resolvedUrl.contains(VEXCoreTestPlugin.PLUGIN_ID) && resolvedUrl.endsWith("testResources/content.xsd"));

+	}

+

+	@Test

+	public void resolveSchemaByNamespace() throws Exception {

+		final String resolvedUrl = model.resolveResourceURI(null, "http://www.eclipse.org/vex/test/content");

+		assertNotNull(resolvedUrl);

+		assertTrue(resolvedUrl.contains(VEXCoreTestPlugin.PLUGIN_ID) && resolvedUrl.endsWith("testResources/content.xsd"));

 	}

 

 	@Test

 	public void onlySystemId() throws Exception {

 		model.initialize(null, null, TestResources.get("test1.dtd").toString(), null);

 		assertTrue(model.isDtdAssigned());

-		assertNotNull(model.getDTD());

+		assertNotNull(model.getContentModelDocument());

 	}

 

 	@Test

@@ -117,8 +122,26 @@
 		final String baseUri = TestResources.get("test.css").toString();

 		model.initialize(baseUri, null, "test1.dtd", null);

 		assertTrue(model.isDtdAssigned());

-		final CMDocument dtd = model.getDTD();

+		final CMDocument dtd = model.getContentModelDocument();

 		assertNotNull(dtd);

 		assertEquals(11, dtd.getElements().getLength());

 	}

+

+	@Test

+	public void onlyNamespace() throws Exception {

+		model.initialize(null, null, null, new Element(new QualifiedName("http://www.eclipse.org/vex/test/content", "rootElement")));

+		assertFalse(model.isDtdAssigned());

+		final CMDocument schema = model.getContentModelDocument();

+		assertNotNull(schema);

+		assertEquals(1, schema.getElements().getLength());

+	}

+

+	@Test

+	public void testExplicitNamespace() throws Exception {

+		model.setSchemaId(null, "http://www.eclipse.org/vex/test/content");

+		assertFalse(model.isDtdAssigned());

+		final CMDocument schema = model.getContentModelDocument();

+		assertNotNull(schema);

+		assertEquals(1, schema.getElements().getLength());

+	}

 }

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 dab2031..ca6aa00 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,14 @@
 import java.io.IOException;

 import java.net.URL;

 import java.util.Iterator;

+import java.util.List;

 

+import org.eclipse.core.runtime.QualifiedName;

 import org.eclipse.vex.core.IFilter;

 import org.eclipse.vex.core.internal.dom.DummyValidator;

 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;

 import org.eclipse.vex.core.provisional.dom.DocumentContentModel;

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

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

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

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

@@ -234,4 +237,20 @@
 

 		assertEquals("whitespace text nodes", 0, nodesWithEmptyTextNodes.count());

 	}

+

+	@Test

+	public void readDocumentWithAttributes() throws Exception {

+		final DocumentReader reader = new DocumentReader();

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

+		final List<? extends IElement> elements = document.getRootElement().childElements().asList();

+		final IElement chapter = elements.get(1);

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

+		assertEquals("Expected attributes in chapter element", 2, chapter.getAttributes().size());

+		final IAttribute attr1 = chapter.getAttribute(new QualifiedName(null, "attribute"));

+		assertNotNull("Attribute without namespace not found", attr1);

+		assertEquals("Value of attribute without namespace", "ns-null", attr1.getValue());

+		final IAttribute attr2 = chapter.getAttribute(new QualifiedName("http://www.eclipse.org/vex/test/content", "attribute"));

+		assertNotNull("Attribute with namespace not found", attr2);

+		assertEquals("Value of attribute without namespace", "ns-content", attr2.getValue());

+	}

 }

diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FormattingPortionIteratorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FormattingPortionIteratorTest.java
new file mode 100644
index 0000000..52cf070
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/FormattingPortionIteratorTest.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * 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.internal.layout;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.internal.css.IWhitespacePolicy;
+import org.eclipse.vex.core.internal.dom.Document;
+import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.provisional.dom.ContentRange;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.INode;
+import org.eclipse.vex.core.provisional.dom.IParent;
+import org.junit.Test;
+
+/**
+ * @author Florian Thienel
+ */
+public class FormattingPortionIteratorTest {
+
+	private Document document;
+	private IParent parent;
+	private Element blockElement;
+
+	@Test
+	public void givenRangeWithBlockElement_whenBlockElementStartsAtRangeStart_shouldReturnBlockElement() throws Exception {
+		givenRangeWithBlockElement();
+
+		final FormattingPortionIterator iterator = createIterator(blockElement.getStartOffset(), parent.getEndOffset());
+
+		assertSame(blockElement, iterator.next());
+	}
+
+	@Test
+	public void givenRangeWithBlockElement_whenBlockElementStartsAfterRangeStart_shouldReturnRangeBeforeBlockElement() throws Exception {
+		givenRangeWithBlockElement();
+
+		final FormattingPortionIterator iterator = createIterator(blockElement.getStartOffset() - 2, parent.getEndOffset());
+
+		assertEquals(new ContentRange(blockElement.getStartOffset() - 2, blockElement.getStartOffset()), iterator.next());
+	}
+
+	@Test
+	public void givenRangeWithBlockElement_whenContentExistsAfterBlockElement_shouldReturnRangeAfterBlockElement() throws Exception {
+		givenRangeWithBlockElement();
+
+		final FormattingPortionIterator iterator = createIterator(blockElement.getStartOffset(), parent.getEndOffset());
+
+		iterator.next();
+		assertEquals(new ContentRange(blockElement.getEndOffset() + 1, parent.getEndOffset()), iterator.next());
+	}
+
+	@Test
+	public void givenRangeWithBlockElement_whenNoMoreContentExists_shouldReturnNull() throws Exception {
+		givenRangeWithBlockElement();
+
+		final FormattingPortionIterator iterator = createIterator(blockElement.getEndOffset(), parent.getEndOffset());
+
+		iterator.next();
+		assertNull(iterator.next());
+	}
+
+	@Test
+	public void givenRangeWithBlockElement_whenContentRangeIsPushed_shouldReturnContentRange() throws Exception {
+		givenRangeWithBlockElement();
+
+		final FormattingPortionIterator iterator = createIterator(parent.getStartOffset(), parent.getEndOffset());
+
+		final ContentRange contentRange = (ContentRange) iterator.next();
+		iterator.push(contentRange);
+
+		assertSame(contentRange, iterator.next());
+	}
+
+	@Test
+	public void givenRangeWithBlockElement_whenBlockElementIsPushed_shouldReturnBlockElement() throws Exception {
+		givenRangeWithBlockElement();
+
+		final FormattingPortionIterator iterator = createIterator(blockElement.getStartOffset(), parent.getEndOffset());
+
+		final IElement element = (IElement) iterator.next();
+		iterator.push(element);
+
+		assertSame(element, iterator.next());
+	}
+
+	@Test
+	public void givenRangeWithBlockElement_whenEndingWithinBlockElement_shouldNotReturnBlockElement() throws Exception {
+		givenRangeWithBlockElement();
+
+		final FormattingPortionIterator iterator = createIterator(parent.getStartOffset(), blockElement.getStartOffset() + 2);
+
+		iterator.next();
+		assertNull(iterator.next());
+	}
+
+	@Test
+	public void givenRangeWithSeveralBlockElements_shouldReturnAllBlockElementsAndRanges() throws Exception {
+		givenRangeWithBlockElements(10);
+
+		final FormattingPortionIterator iterator = createIterator(parent.getStartOffset(), parent.getEndOffset());
+
+		int count = 0;
+		while (iterator.next() != null) {
+			count++;
+		}
+		assertEquals(12, count);
+	}
+
+	private void givenRangeWithBlockElement() {
+		givenRangeWithBlockElements(1);
+	}
+
+	private void givenRangeWithBlockElements(final int count) {
+		document = new Document(new QualifiedName(null, "parent"));
+		parent = document.getRootElement();
+		document.insertText(parent.getEndOffset(), "Hello");
+		for (int i = 0; i < count; i++) {
+			blockElement = document.insertElement(parent.getEndOffset(), new QualifiedName(null, "element"));
+			document.insertText(blockElement.getEndOffset(), "Block " + i);
+		}
+		document.insertText(parent.getEndOffset(), "World");
+	}
+
+	private FormattingPortionIterator createIterator(final int startOffset, final int endOffset) {
+		return new FormattingPortionIterator(new IWhitespacePolicy() {
+			@Override
+			public boolean isBlock(final INode node) {
+				return node instanceof IElement;
+			}
+
+			@Override
+			public boolean isPre(final INode node) {
+				return false;
+			}
+		}, parent, startOffset, endOffset);
+	}
+}
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/LayoutTest.java
similarity index 86%
rename from org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTestSuite.java
rename to org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTest.java
index 6d6f6be..25ea549 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/LayoutTest.java
@@ -30,7 +30,6 @@
 import org.eclipse.vex.core.internal.css.IStyleSheetProvider;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
-import org.eclipse.vex.core.internal.dom.DummyValidator;
 import org.eclipse.vex.core.internal.io.DocumentReader;
 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;
 import org.eclipse.vex.core.provisional.dom.ContentRange;
@@ -54,6 +53,8 @@
  * <ul>
  * <li>insertTextAction="someText" - Insert the given text at the end of the element.</li>
  * <li>removeTextAction="5" - Remove given length text from the start of the element.</li>
+ * <li>removeElementAction="1" - Remove the element that defined this box.</li>
+ * <li>shouldBeRemoved="1" - This box is expected to be removed;
  * <li>InvalidateAction="1" - Invalidates the element (only valid in BlockBox instances)</li>
  * </ul>
  * The expected layout state of an box may be checked with the attribute <code>layoutState="LAYOUT_XXX"</code> (
@@ -62,17 +63,18 @@
  * 
  */
 @RunWith(AllTests.class)
-public class LayoutTestSuite extends TestCase {
+public class LayoutTest extends TestCase {
 
 	public String id;
 	public String documentContent;
 	public int layoutWidth = 100;
 	public boolean performActions = false;
+	public boolean invalidateParentBlock;
 	public BoxSpec result;
 	public String css;
 
 	public static Test suite() throws ParserConfigurationException, FactoryConfigurationError, IOException, SAXException {
-		final TestSuite suite = new TestSuite(LayoutTestSuite.class.getName());
+		final TestSuite suite = new TestSuite(LayoutTest.class.getName());
 		suite.addTest(loadSuite("block-inline.xml"));
 		suite.addTest(loadSuite("before-after.xml"));
 		suite.addTest(loadSuite("linebreaks.xml"));
@@ -87,17 +89,17 @@
 		final TestCaseBuilder builder = new TestCaseBuilder();
 		xmlReader.setContentHandler(builder);
 		// xmlReader.setEntityResolver(builder);
-		final URL url = LayoutTestSuite.class.getResource(filename);
+		final URL url = LayoutTest.class.getResource(filename);
 		xmlReader.parse(new InputSource(url.toString()));
 
 		final TestSuite suite = new TestSuite(filename);
-		for (final LayoutTestSuite test : builder.testCases) {
+		for (final LayoutTest test : builder.testCases) {
 			suite.addTest(test);
 		}
 		return suite;
 	}
 
-	public LayoutTestSuite() {
+	public LayoutTest() {
 		super("testLayout");
 	}
 
@@ -107,7 +109,7 @@
 	}
 
 	public void testLayout() throws Exception {
-		final URL url = LayoutTestSuite.class.getResource(css);
+		final URL url = LayoutTest.class.getResource(css);
 		final StyleSheet styleSheet = new StyleSheetReader().read(url);
 
 		final FakeGraphics g = new FakeGraphics();
@@ -119,7 +121,7 @@
 		context.setWhitespacePolicy(new CssWhitespacePolicy(styleSheet));
 
 		final DocumentReader reader = new DocumentReader();
-		reader.setValidator(new DummyValidator());
+		reader.setValidator(new LayoutTestValidator());
 		reader.setStyleSheetProvider(new IStyleSheetProvider() {
 			public StyleSheet getStyleSheet(final DocumentContentModel documentContentModel) {
 				return styleSheet;
@@ -127,6 +129,7 @@
 		});
 		reader.setWhitespacePolicyFactory(CssWhitespacePolicy.FACTORY);
 		final IDocument document = reader.read(documentContent);
+		document.setValidator(reader.getValidator());
 		context.setDocument(document);
 
 		final RootBox rootBox = new RootBox(context, document, layoutWidth);
@@ -143,7 +146,8 @@
 		}
 	}
 
-	private static void performActions(final BoxSpec boxSpec, final Box box, final IDocument doc) {
+	private void performActions(final BoxSpec boxSpec, final Box box, final IDocument doc) {
+
 		if (boxSpec.insertTextAction != null) {
 			doc.insertText(box.getNode().getEndOffset(), boxSpec.insertTextAction);
 		}
@@ -158,12 +162,36 @@
 			doc.getContent().remove(new ContentRange(startOffset + 1, startOffset + boxSpec.removeTextAction));
 		}
 
+		if (boxSpec.removeElementAction) {
+			if (box.getNode() == null) {
+				fail(String.format("Error in test configuration. Can not remove element for box'%s'", boxSpec.toString()));
+			}
+			System.out.println("Removing element " + box.getNode());
+			final int startOffset = box.getNode().getStartOffset();
+			final int endOffset = box.getNode().getEndOffset();
+			doc.delete(new ContentRange(startOffset, endOffset));
+			invalidateParentBlock = true;
+			return;
+		}
+
 		if (boxSpec.invalidateAction && box instanceof BlockBox) {
 			((BlockBox) box).invalidate(true);
 		}
 
+		final List<BoxSpec> toRemove = new ArrayList<BoxSpec>();
 		for (int i = 0; i < boxSpec.children.size(); i++) {
-			performActions(boxSpec.children.get(i), box.getChildren()[i], doc);
+			final BoxSpec childSpec = boxSpec.children.get(i);
+			performActions(childSpec, box.getChildren()[i], doc);
+			if (childSpec.removeElementAction || childSpec.shouldBeRemoved) {
+				toRemove.add(childSpec);
+			}
+		}
+
+		boxSpec.children.removeAll(toRemove);
+
+		if (invalidateParentBlock && box instanceof BlockBox && box.getNode() != null) {
+			((BlockBox) box).invalidate(true);
+			invalidateParentBlock = false;
 		}
 	}
 
@@ -248,9 +276,9 @@
 
 	private static class TestCaseBuilder extends DefaultHandler {
 
-		private List<LayoutTestSuite> testCases;
+		private List<LayoutTest> testCases;
 		private String css;
-		private LayoutTestSuite testCase;
+		private LayoutTest testCase;
 		private BoxSpec boxSpec;
 		private Stack<BoxSpec> boxSpecs;
 		private boolean inDoc;
@@ -285,7 +313,7 @@
 		public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
 
 			if (qName.equals("testcases")) {
-				testCases = new ArrayList<LayoutTestSuite>();
+				testCases = new ArrayList<LayoutTest>();
 				css = attributes.getValue("css");
 				if (css == null) {
 					css = "test.css";
@@ -293,7 +321,7 @@
 				testCase = null;
 				boxSpecs = new Stack<BoxSpec>();
 			} else if (qName.equals("test")) {
-				testCase = new LayoutTestSuite();
+				testCase = new LayoutTest();
 				testCase.id = attributes.getValue("id");
 				testCase.css = css;
 				final String layoutWidth = attributes.getValue("layoutWidth");
@@ -319,7 +347,9 @@
 				} catch (final NumberFormatException e) {
 					boxSpec.removeTextAction = 0;
 				}
+				boxSpec.removeElementAction = attributes.getValue("removeElementAction") != null;
 				boxSpec.invalidateAction = attributes.getValue("invalidateAction") != null;
+				boxSpec.shouldBeRemoved = attributes.getValue("shouldBeRemoved") != null;
 				String layoutStateAttr = attributes.getValue("layoutState");
 				if (layoutStateAttr != null) {
 					layoutStateAttr = layoutStateAttr.trim().toLowerCase();
@@ -353,6 +383,8 @@
 		public byte layoutState = -1;
 		public String insertTextAction;
 		public int removeTextAction;
+		public boolean removeElementAction;
+		public boolean shouldBeRemoved;
 		public boolean invalidateAction = false;
 	}
 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTestValidator.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTestValidator.java
new file mode 100644
index 0000000..b760b7b
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/LayoutTestValidator.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Carsten Hiesserich 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:
+ * 		Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.layout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.internal.dom.DummyValidator;
+
+/**
+ * A dummy validator tzo be used with layout tests
+ */
+public class LayoutTestValidator extends DummyValidator {
+
+	final static List<String> nodesForInsertion = new ArrayList<String>();
+	static {
+		nodesForInsertion.add("p");
+	};
+
+	@Override
+	public boolean isValidSequence(final QualifiedName element, final List<QualifiedName> sequence1, final List<QualifiedName> sequence2, final List<QualifiedName> sequence3, final boolean partial) {
+		// Allow insertions in <p> element
+		if (nodesForInsertion.contains(element.getLocalName())) {
+			return true;
+		}
+
+		return false;
+	}
+}
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 659a01f..9efbe3d 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
@@ -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,6 +7,7 @@
  *
  * Contributors:
  *     John Krasnay - initial API and implementation
+ *     Carsten Hiesserich - adapted tests to optimized split methods
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
@@ -25,6 +26,7 @@
 import org.eclipse.vex.core.provisional.dom.ContentRange;
 import org.eclipse.vex.core.provisional.dom.IDocument;
 import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.INode;
 import org.junit.Test;
 
 /**
@@ -57,48 +59,62 @@
 
 		final Styles styles = context.getStyleSheet().getStyles(root);
 
-		final int width = g.getCharWidth();
-
 		// 0 6 13 21
 		// / / / /
 		// baggy orange trousers
 
 		doc.insertText(2, "baggy orange trousers");
-		final DocumentTextBox box = new DocumentTextBox(context, root, 2, 23);
-		assertEquals(box.getText().length() * width, box.getWidth());
+		final DocumentTextBox box = new DocumentTextBox(context, root, root.getStartOffset() + 1, root.getEndOffset() - 1);
 		assertEquals(styles.getLineHeight(), box.getHeight());
-		assertSplit(box, 22, false, "baggy orange ", "trousers");
-		assertSplit(box, 21, false, "baggy orange ", "trousers");
-		assertSplit(box, 20, false, "baggy orange ", "trousers");
-		assertSplit(box, 13, false, "baggy orange ", "trousers");
-		assertSplit(box, 12, false, "baggy ", "orange trousers");
-		assertSplit(box, 6, false, "baggy ", "orange trousers");
-		assertSplit(box, 5, false, null, "baggy orange trousers");
-		assertSplit(box, 1, false, null, "baggy orange trousers");
-		assertSplit(box, 0, false, null, "baggy orange trousers");
-		assertSplit(box, -1, false, null, "baggy orange trousers");
 
-		assertSplit(box, 22, true, "baggy orange ", "trousers");
-		assertSplit(box, 21, true, "baggy orange ", "trousers");
-		assertSplit(box, 20, true, "baggy orange ", "trousers");
-		assertSplit(box, 13, true, "baggy orange ", "trousers");
-		assertSplit(box, 12, true, "baggy ", "orange trousers");
-		assertSplit(box, 6, true, "baggy ", "orange trousers");
-		assertSplit(box, 5, true, "baggy ", "orange trousers");
-		assertSplit(box, 4, true, "bagg", "y orange trousers");
-		assertSplit(box, 3, true, "bag", "gy orange trousers");
-		assertSplit(box, 2, true, "ba", "ggy orange trousers");
-		assertSplit(box, 1, true, "b", "aggy orange trousers");
-		assertSplit(box, 0, true, "b", "aggy orange trousers");
-		assertSplit(box, -1, true, "b", "aggy orange trousers");
+		assertSplit(root, 22, false, "baggy orange ", "trousers");
+		assertSplit(root, 21, false, "baggy orange ", "trousers");
+		assertSplit(root, 20, false, "baggy orange ", "trousers");
+		assertSplit(root, 13, false, "baggy orange ", "trousers");
+		assertSplit(root, 12, false, "baggy ", "orange trousers");
+		assertSplit(root, 6, false, "baggy ", "orange trousers");
+		assertSplit(root, 5, false, null, "baggy orange trousers");
+		assertSplit(root, 1, false, null, "baggy orange trousers");
+		assertSplit(root, 0, false, null, "baggy orange trousers");
+		assertSplit(root, -1, false, null, "baggy orange trousers");
+
+		assertSplit(root, 22, true, "baggy orange ", "trousers");
+		assertSplit(root, 21, true, "baggy orange ", "trousers");
+		assertSplit(root, 20, true, "baggy orange ", "trousers");
+		assertSplit(root, 13, true, "baggy orange ", "trousers");
+		assertSplit(root, 12, true, "baggy ", "orange trousers");
+		assertSplit(root, 6, true, "baggy ", "orange trousers");
+		assertSplit(root, 5, true, "baggy ", "orange trousers");
+		assertSplit(root, 4, true, "bagg", "y orange trousers");
+		assertSplit(root, 3, true, "bag", "gy orange trousers");
+		assertSplit(root, 2, true, "ba", "ggy orange trousers");
+		assertSplit(root, 1, true, "b", "aggy orange trousers");
+		assertSplit(root, 0, true, "b", "aggy orange trousers");
+		assertSplit(root, -1, true, "b", "aggy orange trousers");
 
 		doc.delete(new ContentRange(3, 22));
 	}
 
-	private void assertSplit(final DocumentTextBox box, final int splitPos, final boolean force, final String left, final String right) {
+	@Test
+	public void testMultipleSplit() throws Exception {
+		final IDocument doc = new Document(new QualifiedName(null, "root"));
+		doc.insertText(2, "12345 67890 ");
+		final IElement root = doc.getRootElement();
+		final DocumentTextBox box = new DocumentTextBox(context, root, root.getStartOffset() + 1, root.getEndOffset() - 1);
+		final InlineBox.Pair pair = box.split(context, 150, false);
+		assertEquals("12345 ", ((DocumentTextBox) pair.getLeft()).getText());
+		final InlineBox.Pair pair2 = pair.getRight().split(context, 100, false);
+		assertNull(pair2.getLeft());
+		assertEquals("67890 ", ((DocumentTextBox) pair2.getRight()).getText());
+		assertEquals("Last right box should have a width", 36, pair2.getRight().getWidth());
+	}
+
+	private void assertSplit(final INode node, final int splitPos, final boolean force, final String left, final String right) {
+
+		final DocumentTextBox box = new DocumentTextBox(context, node, node.getStartOffset() + 1, node.getEndOffset() - 1);
 
 		final Styles styles = context.getStyleSheet().getStyles(box.getNode());
-
+		final int textLength = box.getText().length();
 		final int width = g.getCharWidth();
 
 		final InlineBox.Pair pair = box.split(context, splitPos * width, force);
@@ -106,9 +122,9 @@
 		final DocumentTextBox leftBox = (DocumentTextBox) pair.getLeft();
 		final DocumentTextBox rightBox = (DocumentTextBox) pair.getRight();
 
-		final int leftOffset = 2;
+		final int leftOffset = box.getNode().getStartOffset() + 1;
 		final int midOffset = leftOffset + (left == null ? 0 : left.length());
-		final int rightOffset = leftOffset + box.getText().length();
+		final int rightOffset = leftOffset + textLength;
 
 		if (left == null) {
 			assertNull(leftBox);
@@ -126,10 +142,10 @@
 		} else {
 			assertNotNull(rightBox);
 			assertEquals(right, rightBox.getText());
-			assertEquals(right.length() * width, rightBox.getWidth());
+			//assertEquals(right.length() * width, rightBox.getWidth());
 			assertEquals(styles.getLineHeight(), rightBox.getHeight());
 			assertEquals(midOffset, rightBox.getStartOffset());
-			assertEquals(rightOffset, rightBox.getEndOffset());
+			assertEquals(rightOffset - 1, rightBox.getEndOffset());
 		}
 
 	}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestStaticTextBox.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestStaticTextBox.java
index 5215646..6e34941 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestStaticTextBox.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/TestStaticTextBox.java
@@ -23,6 +23,7 @@
 import org.eclipse.vex.core.internal.css.StyleSheetReader;
 import org.eclipse.vex.core.internal.css.Styles;
 import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.core.provisional.dom.INode;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -54,47 +55,58 @@
 
 	@Test
 	public void testSplit() throws Exception {
-		final int width = g.getCharWidth();
 
-		final StaticTextBox box = new StaticTextBox(context, root, "baggy orange trousers");
-		assertEquals(box.getText().length() * width, box.getWidth());
+		final StaticTextBox box = new StaticTextBox(context, root, "test");
 		assertEquals(styles.getLineHeight(), box.getHeight());
-		assertSplit(box, 22, false, "baggy orange ", "trousers");
-		assertSplit(box, 21, false, "baggy orange ", "trousers");
-		assertSplit(box, 20, false, "baggy orange ", "trousers");
-		assertSplit(box, 13, false, "baggy orange ", "trousers");
-		assertSplit(box, 12, false, "baggy ", "orange trousers");
-		assertSplit(box, 6, false, "baggy ", "orange trousers");
-		assertSplit(box, 5, false, null, "baggy orange trousers");
-		assertSplit(box, 1, false, null, "baggy orange trousers");
-		assertSplit(box, 0, false, null, "baggy orange trousers");
-		assertSplit(box, -1, false, null, "baggy orange trousers");
 
-		assertSplit(box, 22, true, "baggy orange ", "trousers");
-		assertSplit(box, 21, true, "baggy orange ", "trousers");
-		assertSplit(box, 20, true, "baggy orange ", "trousers");
-		assertSplit(box, 13, true, "baggy orange ", "trousers");
-		assertSplit(box, 12, true, "baggy ", "orange trousers");
-		assertSplit(box, 6, true, "baggy ", "orange trousers");
-		assertSplit(box, 5, true, "baggy ", "orange trousers");
-		assertSplit(box, 4, true, "bagg", "y orange trousers");
-		assertSplit(box, 3, true, "bag", "gy orange trousers");
-		assertSplit(box, 2, true, "ba", "ggy orange trousers");
-		assertSplit(box, 1, true, "b", "aggy orange trousers");
-		assertSplit(box, 0, true, "b", "aggy orange trousers");
-		assertSplit(box, -1, true, "b", "aggy orange trousers");
+		assertSplit(root, 22, false, "baggy orange ", "trousers");
+		assertSplit(root, 21, false, "baggy orange ", "trousers");
+		assertSplit(root, 20, false, "baggy orange ", "trousers");
+		assertSplit(root, 13, false, "baggy orange ", "trousers");
+		assertSplit(root, 12, false, "baggy ", "orange trousers");
+		assertSplit(root, 6, false, "baggy ", "orange trousers");
+		assertSplit(root, 5, false, null, "baggy orange trousers");
+		assertSplit(root, 1, false, null, "baggy orange trousers");
+		assertSplit(root, 0, false, null, "baggy orange trousers");
+		assertSplit(root, -1, false, null, "baggy orange trousers");
+
+		assertSplit(root, 22, true, "baggy orange ", "trousers");
+		assertSplit(root, 21, true, "baggy orange ", "trousers");
+		assertSplit(root, 20, true, "baggy orange ", "trousers");
+		assertSplit(root, 13, true, "baggy orange ", "trousers");
+		assertSplit(root, 12, true, "baggy ", "orange trousers");
+		assertSplit(root, 6, true, "baggy ", "orange trousers");
+		assertSplit(root, 5, true, "baggy ", "orange trousers");
+		assertSplit(root, 4, true, "bagg", "y orange trousers");
+		assertSplit(root, 3, true, "bag", "gy orange trousers");
+		assertSplit(root, 2, true, "ba", "ggy orange trousers");
+		assertSplit(root, 1, true, "b", "aggy orange trousers");
+		assertSplit(root, 0, true, "b", "aggy orange trousers");
+		assertSplit(root, -1, true, "b", "aggy orange trousers");
 	}
 
+	@Test
 	public void testSpaceSplit() throws Exception {
-		final StaticTextBox box = new StaticTextBox(context, root, "red  green");
-		assertSplit(box, 11, false, "red  ", "green");
-		assertSplit(box, 10, false, "red  ", "green");
-		assertSplit(box, 9, false, "red  ", "green");
-		assertSplit(box, 5, false, "red  ", "green");
-
+		assertSplit(root, 11, false, "red  ", "green");
+		assertSplit(root, 10, false, "red  ", "green");
+		assertSplit(root, 9, false, "red  ", "green");
+		assertSplit(root, 5, false, "red  ", "green");
 	}
 
-	private void assertSplit(final StaticTextBox box, final int splitPos, final boolean force, final String left, final String right) {
+	@Test
+	public void testMultipleSplit() throws Exception {
+		final StaticTextBox box = new StaticTextBox(context, root, "12345 67890 ");
+		final InlineBox.Pair pair = box.split(context, 150, false);
+		assertEquals("12345 ", ((StaticTextBox) pair.getLeft()).getText());
+		final InlineBox.Pair pair2 = pair.getRight().split(context, 100, false);
+		assertNull(pair2.getLeft());
+		assertEquals("67890 ", ((StaticTextBox) pair2.getRight()).getText());
+		assertEquals("Last right box should have a width", 36, pair2.getRight().getWidth());
+	}
+
+	private void assertSplit(final INode node, final int splitPos, final boolean force, final String left, final String right) {
+
+		final StaticTextBox box = new StaticTextBox(context, node, left != null ? left + right : right);
 
 		final Styles styles = context.getStyleSheet().getStyles(box.getNode());
 		final int width = g.getCharWidth();
@@ -118,7 +130,6 @@
 		} else {
 			assertNotNull(rightBox);
 			assertEquals(right, rightBox.getText());
-			assertEquals(right.length() * width, rightBox.getWidth());
 			assertEquals(styles.getLineHeight(), rightBox.getHeight());
 		}
 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/before-after.css b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/before-after.css
index 78e02cd..74b3077 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/before-after.css
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/before-after.css
@@ -21,6 +21,15 @@
 }
 
 
+iib2 {
+  display: inline;
+}
+
+iib2:before {
+  display: inline;
+  content: 'BEFORE1 BEFORE2 ';
+}
+
 iba {
   display: inline;
 }
@@ -78,3 +87,12 @@
   content: 'BEFORE';
 }
 
+bbb2 {
+  display: block;
+}
+
+bbb2:before {
+  display: block;
+  content: 'BEFORE1 BEFORE2 ';
+}
+
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/before-after.xml b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/before-after.xml
index 19670db..f48a7a6 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/before-after.xml
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/before-after.xml
@@ -114,6 +114,74 @@
 		</result>
 	</test>
 
+	<test id="Block with Split In Before" layoutWidth="42">
+		<doc><![CDATA[ <root><bbb2>wuzzle</bbb2></root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+
+						<box class="BlockElementBox" element="bbb2">
+
+							<box class="BlockPseudoElementBox">
+								<box class="ParagraphBox">
+									<box class="LineBox">
+										<box class="StaticTextBox" text="BEFORE1 " />
+									</box>
+									<box class="LineBox">
+										<box class="StaticTextBox" text="BEFORE2 " />
+									</box>
+								</box>
+							</box>
+
+							<box class="ParagraphBox">
+								<box class="LineBox">
+									<box class="DocumentTextBox" text="wuzzle" />
+									<box class="PlaceholderBox" />
+								</box>
+							</box>
+
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
+
+	<test id="Inline with Split In Before" layoutWidth="66">
+		<doc><![CDATA[ <root>abc<iib2>wuzzle</iib2></root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+						<box class="ParagraphBox">
+							<box class="LineBox">
+								<box class="DocumentTextBox" text="abc" />
+								<box class="PlaceholderBox" />
+								<box class="InlineElementBox" element="iib2">
+									<box class="StaticTextBox" text="BEFORE1 " />
+								</box>
+							</box>
+							<box class="LineBox">
+								<box class="InlineElementBox" element="iib2">
+									<box class="StaticTextBox" text="BEFORE2 " />
+								</box>
+							</box>
+							<box class="LineBox">
+								<box class="InlineElementBox" element="iib2">
+									<box class="DrawableBox" />
+									<box class="DocumentTextBox" text="wuzzle" />
+									<box class="PlaceholderBox" />
+									<box class="DrawableBox" />
+								</box>
+								<box class="PlaceholderBox" />
+							</box>
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
 
 	<!-- <test id="Inline with Block Before" layoutWidth="100"> <doc><![CDATA[ 
 		<root><ibb>wuzzle</ibb></root> ]]></doc> <result> <box class="RootBox"> <box 
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/block-inline.css b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/block-inline.css
index ba32596..1b68fee 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/block-inline.css
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/block-inline.css
@@ -9,6 +9,11 @@
   display: inline;
 }
 
+nomarker {
+  display: inline;
+  _vex-inline-marker: none;
+}
+
 p {
   display: block;
 }
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/block-inline.xml b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/block-inline.xml
index d9aaccd..9d9b06d 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/block-inline.xml
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/layout/block-inline.xml
@@ -258,7 +258,64 @@
 		</result>
 	</test>
 
+	<test id="Inline With Surrounding Text Split 3" layoutWidth="24">
+		<doc><![CDATA[ <root>hat <b>cat sat</b> bat</root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+						<box class="ParagraphBox">
+							<box class="LineBox">
+								<box class="DocumentTextBox" text="hat " />
+							</box>
+							<box class="LineBox">
+								<box class="PlaceholderBox" />
+								<box class="InlineElementBox">
+									<box class="DrawableBox" />
+									<box class="DocumentTextBox" text="cat " />
+								</box>
+							</box>
+							<box class="LineBox">
+								<box class="InlineElementBox">
+									<box class="DocumentTextBox" text="sat" />
+									<box class="PlaceholderBox" />
+									<box class="DrawableBox" />
+								</box>
+								<box class="DocumentTextBox" text=" " />
+							</box>
+							<box class="LineBox">
+								<box class="DocumentTextBox" text="bat" />
+								<box class="PlaceholderBox" />
+							</box>
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
 
+	<test id="Inline w/o marker" layoutWidth="100">
+		<doc><![CDATA[ <root><nomarker>cat sat</nomarker></root> ]]></doc>
+		<result>
+			<box class="RootBox">
+				<box class="BlockElementBox">
+					<box class="BlockElementBox" element="root">
+						<box class="ParagraphBox">
+							<box class="LineBox">
+								<box class="PlaceholderBox" />
+								<box class="InlineElementBox">
+									<box class="DocumentTextBox" text="cat " />
+									<box class="DocumentTextBox" text="sat" />
+									<box class="PlaceholderBox" />
+								</box>
+								<box class="PlaceholderBox" />
+							</box>
+						</box>
+					</box>
+				</box>
+			</box>
+		</result>
+	</test>
 
 	<test id="Block Child w/ Inline Before" layoutWidth="75">
 		<doc><![CDATA[ <root>Paris <p>Garters</p></root> ]]></doc>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java
index 76d60b1..df646ed 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/validator/DTDValidatorTest.java
@@ -166,17 +166,6 @@
 		assertInvalidSequence("document", "preface", "index");
 	}
 
-	@Test
-	public void testValidateDocumentWithDTDAndNamespaces() throws Exception {
-		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");
-		doc.insertElement(6, new QualifiedName(null, "para"));
-
-		validator.getAttributeDefinitions(doc.getRootElement());
-	}
-
 	private void assertFullyValidSequence(final String element, final String... sequence) {
 		// fully includes partially
 		assertValidSequence(true, element, true, true, sequence);
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
deleted file mode 100644
index ccfe43d..0000000
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestSuite.java
+++ /dev/null
@@ -1,83 +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 - bug 306639 - remove serializability from StyleSheet
- *                       and dependend classes
- *     Carsten Hiesserich - bug 408501 - keep whitespace when copying fragments
- *     						into pre elements
- *******************************************************************************/
-package org.eclipse.vex.core.tests;
-
-import org.eclipse.vex.core.internal.core.AfterNIteratorTest;
-import org.eclipse.vex.core.internal.core.FilterIteratorTest;
-import org.eclipse.vex.core.internal.core.FirstNIteratorTest;
-import org.eclipse.vex.core.internal.core.XmlTest;
-import org.eclipse.vex.core.internal.css.BatikBehaviorTest;
-import org.eclipse.vex.core.internal.css.CssTest;
-import org.eclipse.vex.core.internal.css.CssWhitespacePolicyTest;
-import org.eclipse.vex.core.internal.css.PropertyTest;
-import org.eclipse.vex.core.internal.css.RuleTest;
-import org.eclipse.vex.core.internal.dom.AxisTest;
-import org.eclipse.vex.core.internal.dom.BasicNodeTest;
-import org.eclipse.vex.core.internal.dom.BlockElementBoxTest;
-import org.eclipse.vex.core.internal.dom.ContentRangeTest;
-import org.eclipse.vex.core.internal.dom.CopyVisitorTest;
-import org.eclipse.vex.core.internal.dom.DeepCopyTest;
-import org.eclipse.vex.core.internal.dom.DocumentEventTest;
-import org.eclipse.vex.core.internal.dom.DocumentFragmentTest;
-import org.eclipse.vex.core.internal.dom.DocumentTest;
-import org.eclipse.vex.core.internal.dom.GapContentTest;
-import org.eclipse.vex.core.internal.dom.L1CommentHandlingTest;
-import org.eclipse.vex.core.internal.dom.L1DeletionTests;
-import org.eclipse.vex.core.internal.dom.L1ElementHandlingTest;
-import org.eclipse.vex.core.internal.dom.L1FragmentHandlingTest;
-import org.eclipse.vex.core.internal.dom.L1ProcessingInstructionHandlingTest;
-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.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;
-import org.eclipse.vex.core.internal.io.SpaceNormalizerTest;
-import org.eclipse.vex.core.internal.io.TextWrapperTest;
-import org.eclipse.vex.core.internal.io.XMLFragmentTest;
-import org.eclipse.vex.core.internal.layout.ImageBoxTest;
-import org.eclipse.vex.core.internal.layout.LayoutTestSuite;
-import org.eclipse.vex.core.internal.layout.TableLayoutTest;
-import org.eclipse.vex.core.internal.layout.TestBlockElementBox;
-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.DTDValidatorTest;
-import org.eclipse.vex.core.internal.validator.SchemaValidatorTest;
-import org.eclipse.vex.core.internal.widget.L2CommentEditingTest;
-import org.eclipse.vex.core.internal.widget.L2ProcessingInstructionEditingTest;
-import org.eclipse.vex.core.internal.widget.L2SelectionTest;
-import org.eclipse.vex.core.internal.widget.L2SimpleEditingTest;
-import org.eclipse.vex.core.internal.widget.L2StyleSheetTest;
-import org.eclipse.vex.core.internal.widget.L2XmlInsertionTest;
-import org.eclipse.vex.core.internal.widget.VexWidgetTest;
-import org.eclipse.vex.core.internal.widget.swt.DocumentFragmentTransferTest;
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-@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, CssWhitespacePolicyTest.class, BatikBehaviorTest.class, ContentRangeTest.class, BasicNodeTest.class,
-		ParentTest.class, DocumentTest.class, L1TextHandlingTest.class, L1CommentHandlingTest.class, L1ProcessingInstructionHandlingTest.class, L1ElementHandlingTest.class,
-		L1FragmentHandlingTest.class, L1DeletionTests.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, ListenerListTest.class, DocumentFragmentTransferTest.class,
-		XMLFragmentTest.class, VexWidgetTest.class, L2SimpleEditingTest.class, L2SelectionTest.class, L2CommentEditingTest.class, L2ProcessingInstructionEditingTest.class, L2XmlInsertionTest.class,
-		DocumentEventTest.class, L2StyleSheetTest.class, XmlTest.class
-
-})
-public class VEXCoreTestSuite {
-}
diff --git a/org.eclipse.vex.core.tests/testResources/document.xml b/org.eclipse.vex.core.tests/testResources/document.xml
index 5eeb284..e7086a3 100644
--- a/org.eclipse.vex.core.tests/testResources/document.xml
+++ b/org.eclipse.vex.core.tests/testResources/document.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>

 <chapter xmlns="http://www.eclipse.org/vex/test/structure" xmlns:c="http://www.eclipse.org/vex/test/content">

 	<title>Title</title>

-	<chapter>

+	<chapter attribute="ns-null" c:attribute="ns-content">

 		<title>1.1</title>

 		<c:p>The <c:i>first</c:i> <c:b>paragraph</c:b>.</c:p>

 	</chapter>

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java
index beb8584..83f064c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java
@@ -133,6 +133,7 @@
 	// we can't use a dash '-vex' here, because of a bug in the batik css parser
 	// see https://issues.apache.org/bugzilla/show_bug.cgi?id=47800
 	public static final String OUTLINE_CONTENT = "_vex-outline-content";
+	public static final String INLINE_MARKER = "_vex-inline-marker";
 
 	// suffixes to BORDER_XXX
 	public static final String COLOR_SUFFIX = "-color";
@@ -235,8 +236,9 @@
 	public static final String XX_SMALL = "xx-small";
 
 	// Common element names
-	public static final String XML_PROCESSING_INSTRUCTION = "vex|processing-instruction";
-	public static final String XML_COMMENT = "vex|comment";
+	public static final String XML_PROCESSING_INSTRUCTION = "processing-instruction";
+	public static final String XML_COMMENT = "comment";
+	public static final String VEX_NAMESPACE_PREFIX = "vex";
 
 	// Pseudo elements
 	public static final String PSEUDO_TARGET = "target";
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/InlineMarkerProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/InlineMarkerProperty.java
new file mode 100644
index 0000000..29275e7
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/InlineMarkerProperty.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Carsten Hiesserich 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:
+ *     Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.css;
+
+import org.eclipse.vex.core.provisional.dom.INode;
+import org.w3c.css.sac.LexicalUnit;
+
+/**
+ * The -vex-inline-marker CSS property. This property decides the type of inline markers<br />
+ * The value <code>none</code> will hide the inline markers around the element.<br />
+ * The defualt is <code>normal</code> to display the default markers.
+ */
+public class InlineMarkerProperty extends AbstractProperty {
+
+	/**
+	 * Class constructor.
+	 */
+	public InlineMarkerProperty() {
+		super(CSS.INLINE_MARKER);
+	}
+
+	public Object calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
+		if (isInlineMarker(lu)) {
+			return lu.getStringValue();
+		}
+
+		return CSS.NORMAL;
+	}
+
+	/**
+	 * Returns true if the given lexical unit represents a valid _vex-inline-marker.
+	 * 
+	 * @param lu
+	 *            LexicalUnit to check.
+	 */
+	public static boolean isInlineMarker(final LexicalUnit lu) {
+		if (lu == null) {
+			return false;
+		} else if (lu.getLexicalUnitType() == LexicalUnit.SAC_IDENT) {
+			final String s = lu.getStringValue();
+			return s.equals(CSS.NORMAL) || s.equals(CSS.NONE);
+		} else {
+			return false;
+		}
+	}
+}
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 bc736e3..fdaaa9a 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
@@ -20,6 +20,7 @@
 import java.util.List;
 import java.util.StringTokenizer;
 
+import org.eclipse.vex.core.internal.dom.Namespace;
 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;
 import org.eclipse.vex.core.provisional.dom.IComment;
 import org.eclipse.vex.core.provisional.dom.IDocument;
@@ -156,6 +157,13 @@
 		case Selector.SAC_ELEMENT_NODE_SELECTOR:
 			final String elementName = getLocalNameOfElement(node);
 			final String selectorName = ((ElementSelector) selector).getLocalName();
+
+			// If the Selector has a namespace URI, it has to match the namespace URI of the node
+			final String selectorNamespaceURI = ((ElementSelector) selector).getNamespaceURI();
+			if (selectorNamespaceURI != null && !selectorNamespaceURI.equals(getNamespaceURIOfElement(node))) {
+				return false;
+			}
+
 			if (selectorName == null) {
 				// We land here if we have a wildcard selector (*) or
 				// a pseudocondition w/o an element name (:before)
@@ -244,6 +252,25 @@
 		});
 	}
 
+	private static String getNamespaceURIOfElement(final INode node) {
+		return node.accept(new BaseNodeVisitorWithResult<String>("") {
+			@Override
+			public String visit(final IElement element) {
+				return element.getQualifiedName().getQualifier();
+			}
+
+			@Override
+			public String visit(final IComment comment) {
+				return Namespace.VEX_NAMESPACE_URI;
+			}
+
+			@Override
+			public String visit(final IProcessingInstruction pi) {
+				return Namespace.VEX_NAMESPACE_URI;
+			}
+		});
+	}
+
 	/**
 	 * Returns true if some ancestor of the given element matches the given selector.
 	 */
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 0a6707a..9aa8714 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
@@ -82,7 +82,7 @@
 			new BorderWidthProperty(CSS.BORDER_LEFT_WIDTH, CSS.BORDER_LEFT_STYLE, IProperty.Axis.HORIZONTAL),
 			new BorderWidthProperty(CSS.BORDER_RIGHT_WIDTH, CSS.BORDER_RIGHT_STYLE, IProperty.Axis.HORIZONTAL),
 			new BorderWidthProperty(CSS.BORDER_TOP_WIDTH, CSS.BORDER_TOP_STYLE, IProperty.Axis.VERTICAL), new BorderSpacingProperty(), new LengthProperty(CSS.HEIGHT, IProperty.Axis.VERTICAL),
-			new LengthProperty(CSS.WIDTH, IProperty.Axis.HORIZONTAL), new BackgroundImageProperty(), new OutlineContentProperty() };
+			new LengthProperty(CSS.WIDTH, IProperty.Axis.HORIZONTAL), new BackgroundImageProperty(), new OutlineContentProperty(), new InlineMarkerProperty() };
 
 	/**
 	 * The rules that comprise the stylesheet.
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheetReader.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheetReader.java
index bd72c57..dce4b62 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheetReader.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheetReader.java
@@ -44,7 +44,7 @@
 	private static final URIResolver URI_RESOLVER = URIResolverPlugin.createResolver();
 
 	public static Parser createParser() {
-		return new org.apache.batik.css.parser.Parser() {
+		final Parser parser = new org.apache.batik.css.parser.Parser() {
 
 			/**
 			 * The batik implementation uses hardcoded values. This Override allows custom PseudoElements.
@@ -106,6 +106,9 @@
 			}
 
 		};
+
+		parser.setSelectorFactory(new VexSelectorFactory());
+		return parser;
 	}
 
 	/**
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java
index 1cc7da2..5f8e14d 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java
@@ -229,6 +229,13 @@
 	}
 
 	/**
+	 * Returns the value of the <code>_vex-inline-marker</code> property.
+	 */
+	public String getInlineMarker() {
+		return (String) values.get(CSS.INLINE_MARKER);
+	}
+
+	/**
 	 * Returns the value of the <code>lineHeight</code> property.
 	 */
 	public int getLineHeight() {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/VexSelectorFactory.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/VexSelectorFactory.java
new file mode 100644
index 0000000..e092e7e
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/VexSelectorFactory.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Carsten Hiesserich 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:
+ *     Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.css;
+
+import org.apache.batik.css.parser.DefaultElementSelector;
+import org.apache.batik.css.parser.DefaultSelectorFactory;
+import org.eclipse.vex.core.internal.dom.Namespace;
+import org.w3c.css.sac.CSSException;
+import org.w3c.css.sac.ElementSelector;
+
+/**
+ * Together with {@link org.eclipse.vex.core.internal.css.CssScanner CssScanner} this class provides a pseudo support
+ * for CSS namespaces.<br>
+ * There is no support for <code>@namespace</code> rules, the allowed namespaces and prefixes are hardcoded.
+ */
+public class VexSelectorFactory extends DefaultSelectorFactory {
+	/**
+	 * <b>SAC</b>: Implements {@link org.w3c.css.sac.SelectorFactory#createElementSelector(String,String)}.
+	 */
+	@Override
+	public ElementSelector createElementSelector(String namespaceURI, String tagName) throws CSSException {
+		final int seperatorIndex = tagName != null ? tagName.indexOf("|") : -1;
+		if (seperatorIndex > -1) {
+			final String namespacePrefix = tagName.substring(0, seperatorIndex);
+			if (namespacePrefix.equals(CSS.VEX_NAMESPACE_PREFIX)) {
+				namespaceURI = Namespace.VEX_NAMESPACE_URI;
+				tagName = tagName.substring(seperatorIndex + 1);
+			}
+		}
+		return new DefaultElementSelector(namespaceURI, tagName);
+	}
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/vex-core-styles.css b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/vex-core-styles.css
index 4e8119f..f3c7ca2 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/vex-core-styles.css
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/vex-core-styles.css
@@ -16,6 +16,7 @@
 vex|processing-instruction {
 	display: inherit;
 	color: blue;
+	_vex-inline-marker: none;
 }
 
 vex|processing-instruction:before {
@@ -33,6 +34,7 @@
 vex|comment {
 	display: inherit;
 	color: green;
+	_vex-inline-marker: none;
 }
 
 vex|comment:before {
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 e07de80..508c81a 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
@@ -59,10 +59,6 @@
 		if (parent == null || attributeQualifier == null) {

 			return getLocalName();

 		}

-		final String elementQualifier = parent.getQualifiedName().getQualifier();

-		if (attributeQualifier.equals(elementQualifier)) {

-			return getLocalName();

-		}

 		final String prefix = parent.getNamespacePrefix(attributeQualifier);

 		return (prefix == null ? "" : prefix + ":") + getLocalName();

 	}

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 cfa54de..1ddbc69 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
@@ -114,7 +114,7 @@
 	 */
 
 	public IAttribute getAttribute(final String localName) {
-		return getAttribute(qualify(localName));
+		return getAttribute(new QualifiedName(null, localName));
 	}
 
 	public IAttribute getAttribute(final QualifiedName name) {
@@ -122,7 +122,7 @@
 	}
 
 	public String getAttributeValue(final String localName) {
-		return getAttributeValue(qualify(localName));
+		return getAttributeValue(new QualifiedName(null, localName));
 	}
 
 	public String getAttributeValue(final QualifiedName name) {
@@ -142,7 +142,7 @@
 	}
 
 	public void removeAttribute(final String localName) throws DocumentValidationException {
-		removeAttribute(qualify(localName));
+		removeAttribute(new QualifiedName(null, localName));
 	}
 
 	public void removeAttribute(final QualifiedName name) throws DocumentValidationException {
@@ -173,7 +173,7 @@
 	}
 
 	public void setAttribute(final String localName, final String value) throws DocumentValidationException {
-		setAttribute(qualify(localName), value);
+		setAttribute(new QualifiedName(null, localName), value);
 	}
 
 	public void setAttribute(final QualifiedName name, final String value) throws DocumentValidationException {
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 159500e..fd1d179 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
@@ -9,9 +9,11 @@
  *     John Krasnay - initial API and implementation
  *     Igor Jacy Lino Campista - Java 5 warnings fixed (bug 311325)
  *     Florian Thienel - refactoring to full fledged DOM
+ *     Carsten Hiesserich - some optimization in getText methods
  *******************************************************************************/
 package org.eclipse.vex.core.internal.dom;
 
+import java.util.Iterator;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -37,7 +39,7 @@
 	private char[] content;
 	private int gapStart;
 	private int gapEnd;
-	private TreeSet<GapContentPosition> positions = new TreeSet<GapContentPosition>();
+	private final TreeSet<GapContentPosition> positions = new TreeSet<GapContentPosition>();
 
 	/**
 	 * Create a GapContent with the given initial capacity.
@@ -113,14 +115,9 @@
 	}
 
 	private void movePositions(final int startOffset, final int delta) {
-		final TreeSet<GapContentPosition> newPositions = new TreeSet<GapContentPosition>();
-		for (final GapContentPosition position : positions) {
-			if (position.getOffset() >= startOffset) {
-				position.setOffset(position.getOffset() + delta);
-			}
-			newPositions.add(position);
+		for (final GapContentPosition position : positions.tailSet(new GapContentPosition(startOffset))) {
+			position.setOffset(position.getOffset() + delta);
 		}
-		positions = newPositions;
 	}
 
 	public void insertTagMarker(final int offset) {
@@ -155,18 +152,17 @@
 		moveGap(range.getEndOffset() + 1);
 		gapStart -= range.length();
 
-		final TreeSet<GapContentPosition> newPositions = new TreeSet<GapContentPosition>();
-		for (final GapContentPosition position : positions) {
-			if (position.getOffset() > range.getEndOffset()) {
-				position.setOffset(position.getOffset() - range.length());
-				newPositions.add(position);
-			} else if (position.getOffset() >= range.getStartOffset()) {
+		final SortedSet<GapContentPosition> tail = positions.tailSet(new GapContentPosition(range.getStartOffset()));
+		for (final Iterator<GapContentPosition> iterator = tail.iterator(); iterator.hasNext();) {
+			final GapContentPosition position = iterator.next();
+
+			if (position.getOffset() <= range.getEndOffset()) {
 				position.invalidate();
+				iterator.remove();
 			} else {
-				newPositions.add(position);
+				position.setOffset(position.getOffset() - range.length());
 			}
 		}
-		positions = newPositions;
 	}
 
 	public String getText() {
@@ -177,7 +173,8 @@
 		Assert.isTrue(getRange().contains(range));
 
 		final int delta = gapEnd - gapStart;
-		final StringBuilder result = new StringBuilder();
+		// Use range length as initial capacity. This might be a bit too much, but that's better than having to resize the StringBuilder.
+		final StringBuilder result = new StringBuilder(range.length());
 		if (range.getEndOffset() < gapStart) {
 			appendPlainText(result, range);
 		} else if (range.getStartOffset() >= gapStart) {
@@ -190,7 +187,8 @@
 	}
 
 	private void appendPlainText(final StringBuilder stringBuilder, final ContentRange range) {
-		for (int i = range.getStartOffset(); range.contains(i); i++) {
+		final int endOffset = range.getEndOffset();
+		for (int i = range.getStartOffset(); i <= endOffset; i++) {
 			final char c = content[i];
 			if (!isTagMarker(c)) {
 				stringBuilder.append(c);
@@ -206,16 +204,16 @@
 		Assert.isTrue(getRange().contains(range));
 
 		final int delta = gapEnd - gapStart;
-		final StringBuilder result = new StringBuilder();
 		if (range.getEndOffset() < gapStart) {
-			appendRawText(result, range);
+			return new String(content, range.getStartOffset(), range.length());
 		} else if (range.getStartOffset() >= gapStart) {
-			appendRawText(result, range.moveBy(delta));
+			return new String(content, range.getStartOffset() + delta, range.length());
 		} else {
+			final StringBuilder result = new StringBuilder(range.length());
 			appendRawText(result, new ContentRange(range.getStartOffset(), gapStart - 1));
 			appendRawText(result, new ContentRange(gapEnd, range.getEndOffset() + delta));
+			return result.toString();
 		}
-		return result.toString();
 	}
 
 	private void appendRawText(final StringBuilder stringBuilder, final ContentRange range) {
@@ -295,7 +293,7 @@
 	/*
 	 * Implementation of the Position interface.
 	 */
-	private static class GapContentPosition implements IPosition, Comparable<IPosition> {
+	private static class GapContentPosition implements IPosition {
 
 		private int offset;
 
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 4d3cc88..66a3355 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
@@ -16,6 +16,7 @@
 import java.util.List;
 
 import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.AssertionFailedException;
 import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitor;
 import org.eclipse.vex.core.provisional.dom.ContentRange;
@@ -90,12 +91,16 @@
 	}
 
 	public int getStartOffset() {
-		Assert.isTrue(isAssociated(), "Node must be associated to a ContentRange to have a start offset.");
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have a start offset.");
+		}
 		return startPosition.getOffset();
 	}
 
 	public int getEndOffset() {
-		Assert.isTrue(isAssociated(), "Node must be associated to a ContentRange to have an end offset.");
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a ContentRange to have a start offset.");
+		}
 		return endPosition.getOffset();
 	}
 
@@ -132,7 +137,9 @@
 	}
 
 	public String getText(final ContentRange range) {
-		Assert.isTrue(isAssociated(), "Node must be associated to a Content region to have textual content.");
+		if (!isAssociated()) {
+			throw new AssertionFailedException("Node must be associated to a Content region to have textual content.");
+		}
 		return content.getText(range.intersection(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 8c1529c..bb19d77 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
@@ -4,7 +4,7 @@
  * 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

  * 		Carsten Hiesserich - fixed insertion of elements to nodes with text (bug 408731)

@@ -17,6 +17,7 @@
 import java.util.List;

 

 import org.eclipse.core.runtime.Assert;

+import org.eclipse.core.runtime.AssertionFailedException;

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

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

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

@@ -63,15 +64,31 @@
 		final ContentRange insertionRange = getRange().resizeBy(1, 0);

 		Assert.isTrue(insertionRange.contains(offset), MessageFormat.format("The offset must be within {0}.", insertionRange));

 

-		// We have to return an index in the children List, so Axis withoutText must be used!

-		int i = 0;

-		for (final INode child : children().withoutText()) {

-			if (offset <= child.getStartOffset()) {

-				return i;

-			}

-			i++;

+		if (children.isEmpty()) {

+			return 0;

 		}

-		return children.size();

+

+		int minIndex = -1;

+		int maxIndex = children.size();

+

+		while (minIndex <= maxIndex) {

+			final int pivotIndex = (maxIndex + minIndex) / 2;

+			final INode pivot = children.get(pivotIndex);

+

+			if (pivot.containsOffset(offset)) {

+				return pivotIndex;

+			} else if (maxIndex - minIndex == 1) {

+				return maxIndex;

+			}

+

+			if (pivot.getStartOffset() > offset) {

+				maxIndex = Math.min(pivotIndex, maxIndex);

+			} else if (pivot.getEndOffset() < offset) {

+				minIndex = Math.max(pivotIndex, minIndex);

+			}

+		}

+

+		throw new AssertionError("No child found at offset " + offset);

 	}

 

 	private void insertChildAtIndex(final int index, final Node child) {

@@ -87,17 +104,66 @@
 	 * @return the node at the given offset

 	 */

 	public INode getChildAt(final int offset) {

-		Assert.isTrue(containsOffset(offset), MessageFormat.format("Offset must be within {0}.", getRange()));

-		for (final INode child : children()) {

-			if (child.containsOffset(offset)) {

-				if (child instanceof IParent) {

-					return ((IParent) child).getChildAt(offset);

-				} else {

-					return child;

-				}

+		if (!containsOffset(offset)) {

+			throw new AssertionFailedException(MessageFormat.format("Offset must be within {0}.", getRange()));

+		}

+

+		if (offset == getStartOffset() || offset == getEndOffset()) {

+			return this;

+		}

+

+		if (children.isEmpty()) {

+			return new Text(this, getContent(), getRange().resizeBy(1, -1));

+		}

+

+		int minIndex = -1;

+		int maxIndex = children.size();

+

+		while (minIndex <= maxIndex) {

+			final int pivotIndex = (maxIndex + minIndex) / 2;

+			final INode pivot = children.get(pivotIndex);

+

+			if (pivot.containsOffset(offset)) {

+				return getChildIn(pivot, offset);

+			} else if (maxIndex - minIndex == 1) {

+				return createTextBetween(minIndex, maxIndex);

+			}

+

+			if (pivot.getStartOffset() > offset) {

+				maxIndex = Math.min(pivotIndex, maxIndex);

+			} else if (pivot.getEndOffset() < offset) {

+				minIndex = Math.max(pivotIndex, minIndex);

 			}

 		}

-		return this;

+

+		throw new AssertionError("No child found at offset " + offset);

+	}

+

+	private INode getChildIn(final INode child, final int offset) {

+		if (child instanceof IParent) {

+			return ((IParent) child).getChildAt(offset);

+		}

+		return child;

+	}

+

+	private Text createTextBetween(final int childIndex1, final int childIndex2) {

+		Assert.isTrue(childIndex1 < childIndex2);

+

+		final int startOffset;

+		if (childIndex1 < 0) {

+			startOffset = getStartOffset() + 1;

+		} else {

+			startOffset = children.get(childIndex1).getEndOffset() + 1;

+		}

+

+		final int endOffset;

+		if (childIndex2 >= children.size()) {

+			endOffset = getEndOffset() - 1;

+		} else {

+			endOffset = children.get(childIndex2).getStartOffset() - 1;

+		}

+

+		return new Text(this, getContent(), new ContentRange(startOffset, endOffset));

 	}

 

 	/**

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 056c86d..5cb845f 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
@@ -255,7 +255,8 @@
 			if ("".equals(attrs.getLocalName(i))) {
 				attributeName = new QualifiedName(null, attrs.getQName(i));
 			} else if ("".equals(attrs.getURI(i))) {
-				attributeName = new QualifiedName(elementName.getQualifier(), attrs.getLocalName(i));
+				// Attributes do not inherit the elements namespace (http://www.w3.org/TR/REC-xml-names/#defaulting)
+				attributeName = new QualifiedName(null, attrs.getLocalName(i));
 			} else {
 				attributeName = new QualifiedName(attrs.getURI(i), attrs.getLocalName(i));
 			}
@@ -272,7 +273,7 @@
 			if (dtdPublicID != null && dtdSystemID != null || previousDocTypeID == null) {
 				// The content model is initialized only if the input document defines a DocType
 				// or if it has not been initialized already.
-				// This way, a user selected is reapplied when the document is reloaded.
+				// This way, a user selected doctype is reapplied when the document is reloaded.
 				documentContentModel.initialize(baseUri, dtdPublicID, dtdSystemID, rootElement);
 			}
 			final StyleSheet styleSheet = styleSheetProvider.getStyleSheet(documentContentModel);
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 1eb7b4a..b896ddb 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
@@ -13,7 +13,6 @@
 package org.eclipse.vex.core.internal.layout;
 
 import java.util.ArrayList;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
@@ -23,7 +22,6 @@
 import org.eclipse.vex.core.internal.core.FontMetrics;
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.core.Insets;
-import org.eclipse.vex.core.internal.css.IWhitespacePolicy;
 import org.eclipse.vex.core.internal.css.StyleSheet;
 import org.eclipse.vex.core.internal.css.Styles;
 import org.eclipse.vex.core.internal.widget.IBoxFilter;
@@ -706,15 +704,15 @@
 			final int relOffset = startOffset - node.getStartOffset();
 			pendingInlines.add(new PlaceholderBox(context, node, relOffset));
 		} else if (node instanceof IParent) {
-			final BlockInlineIterator iter = new BlockInlineIterator(context, (IParent) node, startOffset, endOffset);
+			final FormattingPortionIterator iter = new FormattingPortionIterator(context.getWhitespacePolicy(), (IParent) node, startOffset, endOffset);
 			while (true) {
-				Object next = iter.next();
-				if (next == null) {
+				Object formattingPortion = iter.next();
+				if (formattingPortion == null) {
 					break;
 				}
 
-				if (next instanceof ContentRange) {
-					final ContentRange range = (ContentRange) next;
+				if (formattingPortion instanceof ContentRange) {
+					final ContentRange range = (ContentRange) formattingPortion;
 					final InlineElementBox.InlineBoxes inlineBoxes = InlineElementBox.createInlineBoxes(context, node, range);
 					pendingInlines.addAll(inlineBoxes.boxes);
 					pendingInlines.add(new PlaceholderBox(context, node, range.getEndOffset() - node.getStartOffset()));
@@ -724,25 +722,25 @@
 						pendingInlines.clear();
 					}
 
-					if (isTableChild(context, next)) {
+					if (isTableChild(context, formattingPortion)) {
 						// Consume continguous table children and create an
 						// anonymous table.
-						final int tableStartOffset = ((IElement) next).getStartOffset();
+						final int tableStartOffset = ((IElement) formattingPortion).getStartOffset();
 						int tableEndOffset = -1; // dummy to hide warning
-						while (isTableChild(context, next)) {
-							tableEndOffset = ((IElement) next).getEndOffset() + 1;
-							next = iter.next();
+						while (isTableChild(context, formattingPortion)) {
+							tableEndOffset = ((IElement) formattingPortion).getEndOffset() + 1;
+							formattingPortion = iter.next();
 						}
 
 						// add anonymous table
 						blockBoxes.add(new TableBox(context, this, tableStartOffset, tableEndOffset));
-						if (next == null) {
+						if (formattingPortion == null) {
 							break;
 						} else {
-							iter.push(next);
+							iter.push(formattingPortion);
 						}
 					} else { // next is a block box element
-						final INode blockNode = (INode) next;
+						final INode blockNode = (INode) formattingPortion;
 						blockBoxes.add(context.getBoxFactory().createBox(context, blockNode, this, width));
 					}
 				}
@@ -766,57 +764,6 @@
 		return blockBoxes;
 	}
 
-	private static class BlockInlineIterator {
-
-		private final LayoutContext context;
-		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 IParent parent, final int startOffset, final int endOffset) {
-			this.context = context;
-			this.parent = parent;
-			this.startOffset = startOffset;
-			this.endOffset = endOffset;
-		}
-
-		/**
-		 * Returns the next block element or inline range, or null if we're at the end.
-		 */
-		public Object next() {
-			if (!pushStack.isEmpty()) {
-				return pushStack.removeLast();
-			} else if (startOffset >= endOffset) {
-				return null;
-			} else {
-				final INode blockNode = findNextBlockNode(context, parent, startOffset, endOffset);
-				if (blockNode == null) {
-					if (startOffset < endOffset) {
-						final ContentRange result = new ContentRange(startOffset, endOffset);
-						startOffset = endOffset;
-						return result;
-					} else {
-						return null;
-					}
-				} else if (blockNode.getStartOffset() > startOffset) {
-					pushStack.addLast(blockNode);
-					final ContentRange result = new ContentRange(startOffset, blockNode.getStartOffset());
-					startOffset = blockNode.getEndOffset() + 1;
-					return result;
-				} else {
-					startOffset = blockNode.getEndOffset() + 1;
-					return blockNode;
-				}
-			}
-		}
-
-		public void push(final Object pushed) {
-			pushStack.addLast(pushed);
-		}
-
-	}
-
 	protected boolean hasChildren() {
 		return getChildren() != null && getChildren().length > 0;
 	}
@@ -893,62 +840,6 @@
 	// ========================================================= PRIVATE
 
 	/**
-	 * Searches for the next block-formatted child.
-	 * 
-	 * @param context
-	 *            LayoutContext to use.
-	 * @param parent
-	 *            Element within which to search.
-	 * @param startOffset
-	 *            The offset at which to start the search.
-	 * @param endOffset
-	 *            The offset at which to end the search.
-	 */
-	private static INode findNextBlockNode(final LayoutContext context, final IParent parent, final int startOffset, final int endOffset) {
-		final IWhitespacePolicy policy = context.getWhitespacePolicy();
-		for (final INode child : parent.children().in(new ContentRange(startOffset, endOffset)).withoutText()) {
-			final INode nextBlockNode = child.accept(new BaseNodeVisitorWithResult<INode>() {
-				@Override
-				public INode visit(final IElement element) {
-					// found?
-					if (policy.isBlock(element)) {
-						return element;
-					}
-
-					// recursion
-					final INode fromChild = findNextBlockNode(context, element, startOffset, endOffset);
-					if (fromChild != null) {
-						return fromChild;
-					}
-
-					return null;
-				}
-
-				@Override
-				public INode visit(final IComment comment) {
-					if (policy.isBlock(comment)) {
-						return comment;
-					}
-					return null;
-				}
-
-				@Override
-				public INode visit(final IProcessingInstruction pi) {
-					if (policy.isBlock(pi)) {
-						return pi;
-					}
-					return null;
-				}
-			});
-			if (nextBlockNode != null) {
-				return nextBlockNode;
-			}
-		}
-
-		return null;
-	}
-
-	/**
 	 * Return the end position of an anonymous box. The default implementation returns null.
 	 */
 	private IPosition getEndPosition() {
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 c4716e7..f854bcd 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.core.runtime.Assert;
 import org.eclipse.vex.core.internal.core.Caret;
 import org.eclipse.vex.core.internal.core.Color;
 import org.eclipse.vex.core.internal.core.ColorResource;
@@ -141,6 +142,7 @@
 	 * @see org.eclipse.vex.core.internal.layout.Box#getWidth()
 	 */
 	public int getWidth() {
+		Assert.isTrue(width > -1); // Make sure width has been calculated
 		return width;
 	}
 
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractInlineBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractInlineBox.java
index 7d2e909..0265f9d 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractInlineBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/AbstractInlineBox.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2010 Florian Thienel and others.

+ * Copyright (c) 2010, 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

@@ -7,6 +7,7 @@
  * 

  * Contributors:

  * 		Florian Thienel - initial API and implementation

+ * 		Carsten Hiesserich - added isSplitable() method

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

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

 

@@ -18,4 +19,13 @@
 	public void alignOnBaseline(final int baseline) {

 		setY(baseline - getBaseline());

 	}

+

+	public boolean isSplitable() {

+		return false;

+	}

+

+	public Pair split(final LayoutContext context, final int maxWidth, final boolean force) {

+		throw new UnsupportedOperationException("split method not supported");

+	}

+

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CompositeInlineBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CompositeInlineBox.java
index 63cb2c1..c0334a0 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CompositeInlineBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/CompositeInlineBox.java
@@ -102,10 +102,16 @@
 		return new TextCaret(x, y, height);
 	}
 
+	@Override
+	public boolean isSplitable() {
+		return true;
+	}
+
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.InlineBox#split(org.eclipse.vex.core.internal.layout.LayoutContext,
 	 *      int, boolean)
 	 */
+	@Override
 	public Pair split(final LayoutContext context, final int maxWidth, final boolean force) {
 
 		// list of children that have yet to be added to the left side
@@ -120,26 +126,48 @@
 
 		int remaining = maxWidth;
 		boolean eol = false;
+		InlineBox currentBox = null;
 
-		while (!rights.isEmpty() && remaining >= 0) {
-			final InlineBox inline = (InlineBox) rights.removeFirst();
-			final InlineBox.Pair pair = inline.split(context, remaining, force && lefts.isEmpty());
-
-			if (pair.getLeft() != null) {
-				lefts.addAll(pending);
-				pending.clear();
-				lefts.add(pair.getLeft());
-				remaining -= pair.getLeft().getWidth();
+		while ((!rights.isEmpty() || currentBox != null) && remaining >= 0) {
+			final InlineBox inline;
+			if (currentBox != null) {
+				inline = currentBox;
+				currentBox = null;
+			} else {
+				inline = (InlineBox) rights.removeFirst();
 			}
 
-			if (pair.getRight() != null) {
-				pending.add(pair.getRight());
-				remaining -= pair.getRight().getWidth();
-			}
+			if (inline.isSplitable()) {
+				final InlineBox.Pair pair = inline.split(context, remaining, force && lefts.isEmpty());
 
-			if (pair.getLeft() != null && pair.getLeft().isEOL()) {
-				eol = true;
-				break;
+				if (pair.getLeft() != null) {
+					lefts.addAll(pending);
+					pending.clear();
+					lefts.add(pair.getLeft());
+					remaining -= pair.getLeft().getWidth();
+				}
+
+				if (pair.getRight() != null) {
+					if (pair.getLeft() == null) {
+						// pair.left is null, so the right either fits completely or not at all
+						remaining = pair.getRemaining();
+						pending.add(pair.getRight());
+					} else if (remaining >= 0 && !pair.getLeft().isEOL()) {
+						// we have no valid right width, so try to further split the right element
+						currentBox = pair.getRight();
+					} else {
+						pending.add(pair.getRight());
+					}
+				}
+
+				if (pair.getLeft() != null && pair.getLeft().isEOL()) {
+					eol = true;
+					break;
+				}
+			} else {
+				// If the box is not splitable, it has a valid width
+				remaining -= inline.getWidth();
+				pending.add(inline);
 			}
 
 		}
@@ -152,7 +180,7 @@
 
 		final InlineBox[] leftKids = lefts.toArray(new InlineBox[lefts.size()]);
 		final InlineBox[] rightKids = rights.toArray(new InlineBox[rights.size()]);
-		return this.split(context, leftKids, rightKids);
+		return this.split(context, leftKids, rightKids, remaining);
 	}
 
 	/**
@@ -164,9 +192,11 @@
 	 *            Child boxes to be given to the left box.
 	 * @param rights
 	 *            Child boxes to be given to the right box.
+	 * @param remaining
+	 *            The remaining width after the split.
 	 * @return
 	 */
-	protected abstract Pair split(LayoutContext context, InlineBox[] lefts, InlineBox[] rights);
+	public abstract Pair split(LayoutContext context, InlineBox[] lefts, InlineBox[] rights, int remaining);
 
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.Box#viewToModel(org.eclipse.vex.core.internal.layout.LayoutContext,
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 bddd2a1..93890ca 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
@@ -1,18 +1,19 @@
 /*******************************************************************************
- * 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
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
  * Contributors:
  *     John Krasnay - initial API and implementation
+ *     Carsten Hiesserich - performance optimization for split methods
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
 import java.text.MessageFormat;
 
-import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.AssertionFailedException;
 import org.eclipse.vex.core.internal.core.ColorResource;
 import org.eclipse.vex.core.internal.core.FontResource;
 import org.eclipse.vex.core.internal.core.Graphics;
@@ -25,7 +26,7 @@
  */
 public class DocumentTextBox extends TextBox {
 
-	private final int startRelative;
+	private int startRelative;
 	private final int endRelative;
 
 	/**
@@ -42,14 +43,42 @@
 	 */
 	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));
+		if (startOffset > endOffset) {
+			// Do not use Assert.isTrue. This Contructor is called very often and the use of Assert.isTrue would evaluate the Message.format every time.
+			throw new AssertionFailedException(MessageFormat.format("assertion failed: DocumentTextBox for {2}: startOffset {0} > endOffset {1}", startOffset, endOffset, node)); //$NON-NLS-1$
+		}
 
-		startRelative = startOffset - node.getStartOffset();
-		endRelative = endOffset - node.getStartOffset();
-		calculateSize(context);
+		final int nodeStart = node.getStartOffset();
+		startRelative = startOffset - nodeStart;
+		endRelative = endOffset - nodeStart;
 
-		Assert.isTrue(getText().length() >= endOffset - startOffset,
-				MessageFormat.format("DocumentTextBox for {2}: text shorter than range: {0} < {1}", getText().length(), endOffset - startOffset, node));
+		// The box constructed here will be splitted, so there's no need to calculate the width here.
+		calculateHeight(context);
+		setWidth(-1);
+
+		if (startOffset <= nodeStart || endOffset >= node.getEndOffset()) {
+			// Do not use Assert.isTrue. This Contructor is called very often and the use of Assert.isTrue would evaluate the Message.format every time.
+			throw new AssertionFailedException(MessageFormat.format("assertion failed: Range of DocumentTextBox for {0} exceeds content of parent node", node)); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Class constructor used by the splitAt method.
+	 * 
+	 * @param other
+	 *            Instance of DocumentTextBox that should be splitted.
+	 * @param endOffset
+	 *            The endOffset of the new box.
+	 * @param width
+	 *            The calculated layout width of the new box.
+	 */
+	private DocumentTextBox(final DocumentTextBox other, final int endOffset, final int width) {
+		super(other.getNode());
+		startRelative = other.startRelative;
+		endRelative = endOffset - getNode().getStartOffset();
+		setWidth(width);
+		setHeight(other.getHeight());
+		setBaseline(other.getBaseline());
 	}
 
 	/**
@@ -81,7 +110,14 @@
 	 */
 	@Override
 	public String getText() {
-		return getNode().getText(new ContentRange(getStartOffset(), getEndOffset()));
+		// The content range of this box can not include tag markers, so we can use IContent#getRawText here. This
+		// method is dramatically faster than IContent#getText
+		return getNode().getContent().getRawText(new ContentRange(getStartOffset(), getEndOffset()));
+	}
+
+	@Override
+	public boolean isEOL() {
+		return getNode().getContent().charAt(getEndOffset()) == NEWLINE_CHAR;
 	}
 
 	/**
@@ -164,28 +200,36 @@
 	 * @see org.eclipse.vex.core.internal.layout.TextBox#splitAt(int)
 	 */
 	@Override
-	public Pair splitAt(final LayoutContext context, final int offset) {
+	protected Pair splitAt(final LayoutContext context, final int offset, final int leftWidth, final int maxWidth) {
 
 		if (offset < 0 || offset > endRelative - startRelative + 1) {
 			throw new IllegalStateException();
 		}
 
 		final int split = getStartOffset() + offset;
+		int remaining = maxWidth;
 
 		DocumentTextBox left;
 		if (offset == 0) {
 			left = null;
 		} else {
-			left = new DocumentTextBox(context, getNode(), getStartOffset(), split - 1);
+			left = new DocumentTextBox(this, split - 1, leftWidth);
+			remaining -= leftWidth;
 		}
 
 		InlineBox right;
 		if (split > getEndOffset()) {
 			right = null;
 		} else {
-			right = new DocumentTextBox(context, getNode(), split, getEndOffset());
+			// Instead of creating a new box, we reuse this one
+			startRelative = split - getNode().getStartOffset();
+			if (left == null) {
+				calculateSize(context);
+				remaining -= getWidth();
+			}
+			right = this;
 		}
-		return new Pair(left, right);
+		return new Pair(left, right, remaining);
 	}
 
 	/**
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 fa5558a..5ec9ae6 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
@@ -85,14 +85,6 @@
 	}
 
 	/**
-	 * @see org.eclipse.vex.core.internal.layout.InlineBox#split(org.eclipse.vex.core.internal.layout.LayoutContext,
-	 *      int, boolean)
-	 */
-	public Pair split(final LayoutContext context, final int maxWidth, final boolean force) {
-		return new Pair(null, this);
-	}
-
-	/**
 	 * Draw the drawable. The foreground color of the context's Graphics is set before calling the drawable's draw
 	 * method.
 	 */
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/FormattingPortionIterator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/FormattingPortionIterator.java
new file mode 100644
index 0000000..d2a228b
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/FormattingPortionIterator.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * 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.internal.layout;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import org.eclipse.vex.core.internal.css.IWhitespacePolicy;
+import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;
+import org.eclipse.vex.core.provisional.dom.ContentRange;
+import org.eclipse.vex.core.provisional.dom.IComment;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.INode;
+import org.eclipse.vex.core.provisional.dom.IParent;
+import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
+
+/**
+ * @author Florian Thienel
+ */
+public class FormattingPortionIterator {
+
+	private final IWhitespacePolicy policy;
+	private int startOffset;
+	private final int endOffset;
+	private final LinkedList<Iterator<? extends INode>> iteratorStack = new LinkedList<Iterator<? extends INode>>();
+	private final LinkedList<Object> pushStack = new LinkedList<Object>();
+
+	public FormattingPortionIterator(final IWhitespacePolicy policy, final IParent parent, final int startOffset, final int endOffset) {
+		this.policy = policy;
+		this.startOffset = startOffset;
+		this.endOffset = endOffset;
+		pushIteratorFor(parent);
+	}
+
+	/**
+	 * Returns the next block element or inline range, or null if we're at the end.
+	 */
+	public Object next() {
+		if (!pushStack.isEmpty()) {
+			return pushStack.removeLast();
+		} else if (startOffset >= endOffset) {
+			return null;
+		} else {
+			final INode blockNode = findNextBlockNode(policy);
+			if (blockNode == null) {
+				if (startOffset < endOffset) {
+					final ContentRange result = new ContentRange(startOffset, endOffset);
+					startOffset = endOffset;
+					return result;
+				} else {
+					return null;
+				}
+			} else if (blockNode.getStartOffset() > startOffset) {
+				pushStack.addLast(blockNode);
+				final ContentRange result = new ContentRange(startOffset, blockNode.getStartOffset());
+				startOffset = blockNode.getEndOffset() + 1;
+				return result;
+			} else {
+				startOffset = blockNode.getEndOffset() + 1;
+				return blockNode;
+			}
+		}
+	}
+
+	public void push(final Object pushed) {
+		pushStack.addLast(pushed);
+	}
+
+	private void pushIteratorFor(final IParent parent) {
+		pushIterator(parent.children().in(new ContentRange(startOffset, endOffset)).withoutText().iterator());
+	}
+
+	private void pushIterator(final Iterator<? extends INode> iterator) {
+		iteratorStack.addFirst(iterator);
+	}
+
+	private Iterator<? extends INode> peekIterator() {
+		return iteratorStack.getFirst();
+	}
+
+	private void popIterator() {
+		if (hasIterator()) {
+			iteratorStack.removeFirst();
+		}
+	}
+
+	private boolean hasIterator() {
+		return !iteratorStack.isEmpty();
+	}
+
+	private INode findNextBlockNode(final IWhitespacePolicy policy) {
+		for (final Iterator<? extends INode> iterator = peekIterator(); iterator.hasNext();) {
+			final INode nextBlockNode = iterator.next().accept(new BaseNodeVisitorWithResult<INode>() {
+				@Override
+				public INode visit(final IElement element) {
+					// found?
+					if (policy.isBlock(element)) {
+						return element;
+					}
+
+					// recursion
+					pushIteratorFor(element);
+					final INode fromChild = findNextBlockNode(policy);
+					if (fromChild != null) {
+						return fromChild;
+					}
+
+					return null;
+				}
+
+				@Override
+				public INode visit(final IComment comment) {
+					if (policy.isBlock(comment)) {
+						return comment;
+					}
+					return null;
+				}
+
+				@Override
+				public INode visit(final IProcessingInstruction pi) {
+					if (policy.isBlock(pi)) {
+						return pi;
+					}
+					return null;
+				}
+			});
+			if (nextBlockNode != null) {
+				return nextBlockNode;
+			}
+		}
+
+		popIterator();
+		if (hasIterator()) {
+			return findNextBlockNode(policy);
+		}
+
+		return null;
+	}
+}
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 0636bd4..7c9dcfd 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
@@ -98,7 +98,4 @@
 		return false;

 	}

 

-	public Pair split(final LayoutContext context, final int maxWidth, final boolean force) {

-		return new Pair(null, this);

-	}

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineBox.java
index fea8dcd..4531578 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/InlineBox.java
@@ -1,12 +1,13 @@
 /*******************************************************************************
- * 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
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
  * Contributors:
  *     John Krasnay - initial API and implementation
+ *     Carsten Hiesserich - added remainingWidth to Pair
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
@@ -21,6 +22,7 @@
 	public class Pair {
 		private final InlineBox left;
 		private final InlineBox right;
+		private final int remainingWidth;
 
 		/**
 		 * Class constructor.
@@ -29,10 +31,13 @@
 		 *            box to the left of the split
 		 * @param right
 		 *            box to the right of the split
+		 * @param remaining
+		 *            the remaining layout width after this split
 		 */
-		public Pair(final InlineBox left, final InlineBox right) {
+		public Pair(final InlineBox left, final InlineBox right, final int remaining) {
 			this.left = left;
 			this.right = right;
+			remainingWidth = remaining;
 		}
 
 		/**
@@ -48,6 +53,13 @@
 		public InlineBox getRight() {
 			return right;
 		}
+
+		/**
+		 * Return the remaining with after the split
+		 */
+		public int getRemaining() {
+			return remainingWidth;
+		}
 	}
 
 	/**
@@ -66,6 +78,11 @@
 	public boolean isEOL();
 
 	/**
+	 * @return <code>true</code> if this box can be splitted.
+	 */
+	public boolean isSplitable();
+
+	/**
 	 * Splits this inline box into two. If <code>force</code> is false, this method should find a natural split point
 	 * (e.g. after a space) and return two boxes representing a split at that point. The width of the last box must not
 	 * exceed <code>maxWidth</code>. If no such natural split exists, null should be returned as the left box and
@@ -89,6 +106,7 @@
 	 *            Maximum width of the left part of the box.
 	 * @param force
 	 *            if true, force a suboptimal split
+	 * @return A new {@link Pair} of inline boxes, or null if this box is not splitable
 	 */
 	public Pair split(LayoutContext context, int maxWidth, boolean force);
 }
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 d6ecd4a..61e1211 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
@@ -21,7 +21,6 @@
 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.StyleSheet;
 import org.eclipse.vex.core.internal.css.Styles;
 import org.eclipse.vex.core.provisional.dom.BaseNodeVisitor;
 import org.eclipse.vex.core.provisional.dom.ContentRange;
@@ -37,14 +36,15 @@
 public class InlineElementBox extends CompositeInlineBox {
 
 	private final INode node;
-	private final InlineBox[] children;
+	private InlineBox[] children;
 	private InlineBox firstContentChild = null;
 	private InlineBox lastContentChild = null;
 	private int baseline;
 	private int halfLeading;
 
 	/**
-	 * Class constructor, called by the createInlineBoxes static factory method.
+	 * Class constructor, called by the createInlineBoxes static factory method. The Box created here is only temporary,
+	 * it will be replaced by the split method.
 	 * 
 	 * @param context
 	 *            LayoutContext to use.
@@ -71,13 +71,17 @@
 				childList.add(new SpaceBox(space, 1));
 			}
 
+			final boolean showLeftMarker = styles.getInlineMarker().equals(CSS.NORMAL);
+
 			// :before content
 			final IElement beforeElement = context.getStyleSheet().getPseudoElement(node, CSS.PSEUDO_BEFORE, true);
 			if (beforeElement != null) {
-				childList.addAll(LayoutUtils.createGeneratedInlines(context, beforeElement));
+				childList.addAll(LayoutUtils.createGeneratedInlines(context, beforeElement, showLeftMarker ? StaticTextBox.NO_MARKER : StaticTextBox.START_MARKER));
 			}
 			// left marker
-			childList.add(createLeftMarker(node, styles));
+			if (showLeftMarker) {
+				childList.add(createLeftMarker(node, styles));
+			}
 		}
 
 		// background image
@@ -105,13 +109,17 @@
 		if (endOffset > node.getEndOffset()) {
 			childList.add(new PlaceholderBox(context, node, node.getEndOffset() - node.getStartOffset()));
 
+			final boolean showRightMarker = styles.getInlineMarker().equals(CSS.NORMAL);
+
 			// trailing marker
-			childList.add(createRightMarker(node, styles));
+			if (showRightMarker) {
+				childList.add(createRightMarker(node, styles));
+			}
 
 			// :after content
 			final IElement afterElement = context.getStyleSheet().getPseudoElement(node, CSS.PSEUDO_AFTER, true);
 			if (afterElement != null) {
-				childList.addAll(LayoutUtils.createGeneratedInlines(context, afterElement));
+				childList.addAll(LayoutUtils.createGeneratedInlines(context, afterElement, showRightMarker ? StaticTextBox.NO_MARKER : StaticTextBox.END_MARKER));
 			}
 
 			// space for the right margin/border/padding
@@ -123,7 +131,6 @@
 		}
 
 		children = childList.toArray(new InlineBox[childList.size()]);
-		layout(context);
 	}
 
 	/**
@@ -210,7 +217,7 @@
 	}
 
 	@Override
-	public Pair split(final LayoutContext context, final InlineBox[] lefts, final InlineBox[] rights) {
+	public Pair split(final LayoutContext context, final InlineBox[] lefts, final InlineBox[] rights, final int remaining) {
 
 		InlineElementBox left = null;
 		InlineElementBox right = null;
@@ -220,10 +227,23 @@
 		}
 
 		if (rights.length > 0) {
-			right = new InlineElementBox(context, getNode(), rights);
+			// We reuse this element instead of creating a new one
+			children = rights;
+			for (final InlineBox child : children) {
+				if (child.hasContent()) {
+					// The lastContentChild is already set in this instance an did not change
+					firstContentChild = child;
+					break;
+				}
+			}
+			if (left == null && remaining >= 0) {
+				// There is no left box, and the right box fits without further splitting, so we have to calculate the size here
+				layout(context);
+			}
+			right = this;
 		}
 
-		return new Pair(left, right);
+		return new Pair(left, right, remaining);
 	}
 
 	@Override
@@ -292,12 +312,16 @@
 
 						@Override
 						public void visit(final IComment comment) {
-							createBoxWithBeforeAndAfterContent(comment);
+							addPlaceholderBox(result, new PlaceholderBox(context, node, comment.getStartOffset() - node.getStartOffset()));
+							final InlineBox child = new InlineElementBox(context, comment, range.getStartOffset(), range.getEndOffset());
+							addChildInlineBox(result, child);
 						};
 
 						@Override
 						public void visit(final IProcessingInstruction pi) {
-							createBoxWithBeforeAndAfterContent(pi);
+							addPlaceholderBox(result, new PlaceholderBox(context, node, pi.getStartOffset() - node.getStartOffset()));
+							final InlineBox child = new InlineElementBox(context, pi, range.getStartOffset(), range.getEndOffset());
+							addChildInlineBox(result, child);
 						};
 
 						@Override
@@ -306,34 +330,21 @@
 							final InlineBox child = new DocumentTextBox(context, node, boxRange.getStartOffset(), boxRange.getEndOffset());
 							addChildInlineBox(result, child);
 						}
-
-						private void createBoxWithBeforeAndAfterContent(final INode node) {
-							addPlaceholderBox(result, new PlaceholderBox(context, node, node.getStartOffset() - node.getStartOffset()));
-							final List<Box> boxes = new ArrayList<Box>();
-							final StyleSheet styleSheet = context.getStyleSheet();
-
-							// :before content
-							final IElement before = styleSheet.getPseudoElement(node, CSS.PSEUDO_BEFORE, true);
-							if (before != null) {
-								boxes.addAll(LayoutUtils.createGeneratedInlines(context, before, StaticTextBox.START_MARKER));
-							}
-
-							if (node.getEndOffset() - node.getStartOffset() > 1) {
-								boxes.add(new DocumentTextBox(context, node, node.getStartOffset() + 1, node.getEndOffset() - 1));
-							}
-							boxes.add(new PlaceholderBox(context, node, node.getEndOffset() - node.getStartOffset()));
-
-							// :after content
-							final IElement after = styleSheet.getPseudoElement(node, CSS.PSEUDO_AFTER, true);
-							if (after != null) {
-								boxes.addAll(LayoutUtils.createGeneratedInlines(context, after, StaticTextBox.END_MARKER));
-							}
-							final InlineBox child = new InlineElementBox(context, node, boxes.toArray(new InlineBox[boxes.size()]));
-							addChildInlineBox(result, child);
-						}
 					});
 				}
 			}
+
+			@Override
+			public void visit(final IComment comment) {
+				final InlineBox child = new DocumentTextBox(context, comment, comment.getStartOffset() + 1, comment.getEndOffset() - 1);
+				addChildInlineBox(result, child);
+			}
+
+			@Override
+			public void visit(final IProcessingInstruction pi) {
+				final InlineBox child = new DocumentTextBox(context, pi, pi.getStartOffset() + 1, pi.getEndOffset() - 1);
+				addChildInlineBox(result, child);
+			}
 		});
 
 		return result;
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 0fbef92..8b90944 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
@@ -18,7 +18,7 @@
 public class LineBox extends CompositeInlineBox {
 
 	private final INode node;
-	private final InlineBox[] children;
+	private InlineBox[] children;
 	private InlineBox firstContentChild = null;
 	private InlineBox lastContentChild = null;
 	private int baseline;
@@ -32,29 +32,26 @@
 	 *            InlineBoxes that make up this line.
 	 */
 	public LineBox(final LayoutContext context, final INode node, final InlineBox[] children) {
-
 		this.node = node;
 		this.children = children;
+	}
 
-		int height = 0;
-		int x = 0;
-		baseline = 0;
-		for (final InlineBox child : children) {
-			child.setX(x);
-			child.setY(0); // TODO: do proper vertical alignment
-			baseline = Math.max(baseline, child.getBaseline());
-			x += child.getWidth();
-			height = Math.max(height, child.getHeight());
-			if (child.hasContent()) {
-				if (firstContentChild == null) {
-					firstContentChild = child;
-				}
-				lastContentChild = child;
-			}
-		}
-
-		setHeight(height);
-		setWidth(x);
+	/**
+	 * Class constructor used by the split method.
+	 * 
+	 * @param other
+	 *            Instance of LineBox that should be splitted.
+	 * @param context
+	 *            LayoutContext used for the layout.
+	 * @param node
+	 *            Node to which this box applies.
+	 * @param children
+	 *            Child boxes.
+	 */
+	private LineBox(final LineBox other, final LayoutContext context, final InlineBox[] children) {
+		node = other.node;
+		this.children = children;
+		layout(context);
 	}
 
 	/**
@@ -106,20 +103,27 @@
 	 *      org.eclipse.vex.core.internal.layout.InlineBox[], org.eclipse.vex.core.internal.layout.InlineBox[])
 	 */
 	@Override
-	public Pair split(final LayoutContext context, final InlineBox[] lefts, final InlineBox[] rights) {
+	public Pair split(final LayoutContext context, final InlineBox[] lefts, final InlineBox[] rights, final int remaining) {
 
 		LineBox left = null;
 		LineBox right = null;
 
 		if (lefts.length > 0) {
-			left = new LineBox(context, getNode(), lefts);
+			left = new LineBox(this, context, lefts);
 		}
 
 		if (rights.length > 0) {
-			right = new LineBox(context, getNode(), rights);
+			// We reuse this element instead of creating a new one
+			children = rights;
+
+			if (left == null && remaining >= 0) {
+				// There is no left box, and the right box fits without further splitting, so we have to calculate the size here
+				layout(context);
+			}
+			right = this;
 		}
 
-		return new Pair(left, right);
+		return new Pair(left, right, remaining);
 	}
 
 	/**
@@ -137,4 +141,26 @@
 
 	// ========================================================== PRIVATE
 
+	private void layout(final LayoutContext context) {
+		int height = 0;
+		int x = 0;
+		baseline = 0;
+		for (final InlineBox child : children) {
+			child.setX(x);
+			child.setY(0); // TODO: do proper vertical alignment
+			baseline = Math.max(baseline, child.getBaseline());
+			x += child.getWidth();
+			height = Math.max(height, child.getHeight());
+			if (child.hasContent()) {
+				if (firstContentChild == null) {
+					firstContentChild = child;
+				}
+				lastContentChild = child;
+			}
+		}
+
+		setHeight(height);
+		setWidth(x);
+	}
+
 }
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 e66d698..eecb0d0 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
@@ -84,28 +84,25 @@
 
 		while (right != null) {
 			final InlineBox.Pair pair = right.split(context, width, true);
-			//FIXME icampist this indicates some design problem, since later on, LineBoxes are expected
-			//either we cast here to LineBox or we make an if later on.
 			lines.add(pair.getLeft());
 			right = pair.getRight();
 		}
 
 		final Styles styles = context.getStyleSheet().getStyles(node);
 		final String textAlign = styles.getTextAlign();
+		final boolean alignRight = textAlign.equals(CSS.RIGHT);
+		final boolean alignCenter = textAlign.equals(CSS.CENTER);
 
 		// y-offset of the next line
 		int y = 0;
 
 		int actualWidth = 0;
 
-		//children for the ParagraphBox constructor that accepts only LineBoxes
-		final List<LineBox> lineBoxesChildren = new ArrayList<LineBox>();
-
 		for (final Box lineBox : lines) {
 			int x;
-			if (textAlign.equals(CSS.RIGHT)) {
+			if (alignRight) {
 				x = width - lineBox.getWidth();
-			} else if (textAlign.equals(CSS.CENTER)) {
+			} else if (alignCenter) {
 				x = (width - lineBox.getWidth()) / 2;
 			} else {
 				x = 0;
@@ -116,36 +113,12 @@
 
 			y += lineBox.getHeight();
 			actualWidth = Math.max(actualWidth, lineBox.getWidth());
-
-			//strange, but we need to check the case because it's not explicit anywhere
-			if (lineBox instanceof LineBox) {
-				lineBoxesChildren.add((LineBox) lineBox);
-			}
 		}
 
-		final ParagraphBox para = new ParagraphBox(lineBoxesChildren.toArray(new LineBox[lineBoxesChildren.size()]));
+		final ParagraphBox para = new ParagraphBox(lines.toArray(new LineBox[lines.size()]));
 		para.setWidth(actualWidth);
 		para.setHeight(y);
 
-		// BlockElementBox uses a scaling factor to estimate box height based
-		// on font size, layout width, and character count, as follows.
-		//
-		// estHeight = factor * fontSize * fontSize * charCount / width
-		//
-		// This bit reports the actual factor that would correctly estimate
-		// the height of a BlockElementBox containing only this paragraph.
-		//
-		// factor = estHeight * width / (fontSize * fontSize * charCount)
-		//
-		/*
-		 * Box firstContentBox = null; for (int i = 0; i < inlines.length; i++) { Box box = inlines[i]; if
-		 * (box.hasContent()) { firstContentBox = box; break; } }
-		 * 
-		 * if (firstContentBox != null) { float fontSize = styles.getFontSize(); int charCount =
-		 * lastContentBox.getEndOffset() - firstContentBox.getStartOffset(); float factor = para.getHeight()
-		 * para.getWidth() / (fontSize fontSize charCount); System.out.println("Actual factor is " + factor); }
-		 */
-
 		return para;
 	}
 
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 38afaac..0e7f54c 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
@@ -69,14 +69,6 @@
 	}
 
 	/**
-	 * @see org.eclipse.vex.core.internal.layout.InlineBox#split(org.eclipse.vex.core.internal.layout.LayoutContext,
-	 *      int, boolean)
-	 */
-	public Pair split(final LayoutContext context, final int maxWidth, final boolean force) {
-		return new Pair(null, this);
-	}
-
-	/**
 	 * @see org.eclipse.vex.core.internal.layout.Box#getCaret(org.eclipse.vex.core.internal.layout.LayoutContext, int)
 	 */
 	@Override
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SpaceBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SpaceBox.java
index 0f90c12..3ded483 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SpaceBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/SpaceBox.java
@@ -40,14 +40,6 @@
 	}
 
 	/**
-	 * @see org.eclipse.vex.core.internal.layout.InlineBox#split(org.eclipse.vex.core.internal.layout.LayoutContext,
-	 *      int, boolean)
-	 */
-	public Pair split(final LayoutContext context, final int maxWidth, final boolean force) {
-		return new Pair(null, this);
-	}
-
-	/**
 	 * @see java.lang.Object#toString()
 	 */
 	@Override
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 b86ed20..8654b51 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,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.vex.core.internal.core.ColorResource;
 import org.eclipse.vex.core.internal.core.FontResource;
 import org.eclipse.vex.core.internal.core.Graphics;
@@ -28,6 +29,8 @@
 
 	private final String text;
 	private final byte marker;
+	private int startRelative;
+	private final int endRelative;
 
 	/**
 	 * Class constructor.
@@ -64,8 +67,35 @@
 	public StaticTextBox(final LayoutContext context, final INode node, final String text, final byte marker) {
 		super(node);
 		this.text = text;
+		startRelative = 0;
+		endRelative = text.length();
 		this.marker = marker;
-		calculateSize(context);
+		calculateHeight(context);
+		setWidth(-1);
+	}
+
+	/**
+	 * Class constructor used by the splitAt method.
+	 * 
+	 * @param other
+	 *            Instance of DocumentTextBox that should be splitted.
+	 * @param endOffset
+	 *            The endOffset of the text in the new box.
+	 * @param width
+	 *            The calculated layout width of the new box.
+	 */
+	private StaticTextBox(final StaticTextBox other, final int endOffset, final int width) {
+		super(other.getNode());
+		text = other.text; // Text is shared in all instances
+		startRelative = other.startRelative;
+		endRelative = startRelative + endOffset;
+		if (endRelative <= startRelative) {
+			Assert.isTrue(startRelative < endRelative, "StaticTextBox start is greater than end");
+		}
+		marker = other.marker;
+		setWidth(width);
+		setHeight(other.getHeight());
+		setBaseline(other.getBaseline());
 	}
 
 	/**
@@ -73,7 +103,12 @@
 	 */
 	@Override
 	public String getText() {
-		return text;
+		return text.substring(startRelative, endRelative);
+	}
+
+	@Override
+	public boolean isEOL() {
+		return text.length() > 0 && text.charAt(endRelative - 1) == NEWLINE_CHAR;
 	}
 
 	/**
@@ -123,22 +158,31 @@
 	 * @see org.eclipse.vex.core.internal.layout.TextBox#splitAt(int)
 	 */
 	@Override
-	public Pair splitAt(final LayoutContext context, final int offset) {
+	protected Pair splitAt(final LayoutContext context, final int offset, final int leftWidth, final int maxWidth) {
+
+		int remaining = maxWidth;
 
 		StaticTextBox left;
 		if (offset == 0) {
 			left = null;
 		} else {
-			left = new StaticTextBox(context, getNode(), getText().substring(0, offset), marker);
+			left = new StaticTextBox(this, offset, leftWidth);
+			remaining -= leftWidth;
 		}
 
 		StaticTextBox right;
-		if (offset == getText().length()) {
+		if (offset + startRelative >= endRelative) {
 			right = null;
 		} else {
-			right = new StaticTextBox(context, getNode(), getText().substring(offset), marker);
+			// Instead of creating a new box, we reuse this one
+			startRelative += offset;
+			if (left == null) {
+				calculateSize(context);
+				remaining -= getWidth();
+			}
+			right = this;
 		}
-		return new Pair(left, right);
+		return new Pair(left, right, remaining);
 	}
 
 }
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 0983682..f975164 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
@@ -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,6 +7,7 @@
  *
  * Contributors:
  *     John Krasnay - initial API and implementation
+ *     Carsten Hiesserich - performance optimization for split methods
  *******************************************************************************/
 package org.eclipse.vex.core.internal.layout;
 
@@ -46,7 +47,8 @@
 	 * initialized.
 	 * 
 	 * @param context
-	 *            LayoutContext used to calculate size.
+	 *            LayoutContext used to calculate size. The correct font has to be set in the context's graphics before
+	 *            calling this method.
 	 */
 	protected void calculateSize(final LayoutContext context) {
 		String s = getText();
@@ -56,13 +58,41 @@
 
 		final Graphics g = context.getGraphics();
 		final Styles styles = context.getStyleSheet().getStyles(getNode());
+
+		final FontMetrics fm = g.getFontMetrics();
+		if (s.length() > 1000) {
+			// g.stringWidth() fails randomly with long strings on windows. Such a long text will be splitted anyway,
+			// so it is safe to return a very long fixed width here instead.
+			setWidth(99999);
+		} else {
+			setWidth(g.stringWidth(s));
+		}
+		setHeight(styles.getLineHeight());
+		final int halfLeading = (getHeight() - (fm.getAscent() + fm.getDescent())) / 2;
+		setBaseline(halfLeading + fm.getAscent());
+	}
+
+	/**
+	 * Causes the box to recalculate its height and baseline. Subclasses should call this from their constructors after
+	 * they are initialized.
+	 * 
+	 * @param context
+	 *            LayoutContext used to calculate size.
+	 */
+	protected void calculateHeight(final LayoutContext context) {
+		String s = getText();
+		if (s.endsWith(NEWLINE_STRING)) {
+			s = s.substring(0, s.length() - 1);
+		}
+
+		final Graphics g = context.getGraphics();
+		final Styles styles = context.getStyleSheet().getStyles(getNode());
 		final FontResource font = g.createFont(styles.getFont());
 		final FontResource oldFont = g.setFont(font);
 		final FontMetrics fm = g.getFontMetrics();
-		setWidth(g.stringWidth(s));
 		setHeight(styles.getLineHeight());
 		final int halfLeading = (getHeight() - (fm.getAscent() + fm.getDescent())) / 2;
-		baseline = halfLeading + fm.getAscent();
+		setBaseline(halfLeading + fm.getAscent());
 		g.setFont(oldFont);
 		font.dispose();
 	}
@@ -75,6 +105,13 @@
 	}
 
 	/**
+	 * @see org.eclipse.vex.core.internal.layout.InlineBox#getBaseline()
+	 */
+	public void setBaseline(final int baseline) {
+		this.baseline = baseline;
+	}
+
+	/**
 	 * @see org.eclipse.vex.core.internal.layout.Box#getCaret(org.eclipse.vex.core.internal.layout.LayoutContext, int)
 	 */
 	@Override
@@ -115,11 +152,6 @@
 		return Character.isWhitespace(c);
 	}
 
-	public boolean isEOL() {
-		final String s = getText();
-		return s.length() > 0 && s.charAt(s.length() - 1) == NEWLINE_CHAR;
-	}
-
 	/**
 	 * Paints a string as selected text.
 	 * 
@@ -202,31 +234,44 @@
 		g.drawLine(x, y, x + width, y);
 	}
 
+	@Override
+	public boolean isSplitable() {
+		return true;
+	}
+
 	/**
 	 * @see org.eclipse.vex.core.internal.layout.InlineBox#split(org.eclipse.vex.core.internal.layout.LayoutContext,
 	 *      int, boolean)
 	 */
+	@Override
 	public Pair split(final LayoutContext context, final int maxWidth, final boolean force) {
 
-		final char[] chars = getText().toCharArray();
+		final String text = getText();
+		final int length = text.length();
 
-		if (chars.length == 0) {
+		if (text.length() == 0) {
 			throw new IllegalStateException();
 		}
 
 		final Graphics g = context.getGraphics();
 		final Styles styles = context.getStyleSheet().getStyles(node);
+
 		final FontResource font = g.createFont(styles.getFont());
 		final FontResource oldFont = g.setFont(font);
 
 		int split = 0;
 		int next = 1;
+		int width = 0;
+		int splitWidth = 0;
 		boolean eol = false; // end of line found
-		while (next < chars.length) {
-			if (isSplitChar(chars[next - 1])) {
-				if (g.charsWidth(chars, 0, next) <= maxWidth) {
+		while (next < length) {
+			final char nextChar = text.charAt(next - 1);
+			if (isSplitChar(nextChar)) {
+				width += g.stringWidth(text.substring(split, next));
+				if (width <= maxWidth) {
 					split = next;
-					if (chars[next - 1] == NEWLINE_CHAR) {
+					splitWidth = width;
+					if (nextChar == NEWLINE_CHAR) {
 						eol = true;
 						break;
 					}
@@ -240,40 +285,53 @@
 		if (force && split == 0) {
 			// find some kind of split
 			split = 1;
-			while (split < chars.length) {
-				if (g.charsWidth(chars, 0, split + 1) > maxWidth) {
+			splitWidth = width = g.stringWidth(text.substring(0, 1));
+			while (split < length) {
+				width += g.stringWidth(text.substring(split, split + 1));
+				if (width > maxWidth) {
 					break;
 				}
 				split++;
+				splitWidth = width;
 			}
-
 		}
 
 		// include any trailing spaces in the split
 		// this also grabs any leading spaces when split==0
+		final int spaceCharWidth = context.getGraphics().stringWidth(" ");
 		if (!eol) {
-			while (split < chars.length - 1 && chars[split] == ' ') {
+			while (split < length && text.charAt(split) == ' ') {
 				split++;
+				splitWidth += spaceCharWidth;
 			}
 		}
 
+		final Pair splitPair = splitAt(context, split, splitWidth, maxWidth);
+
+		// The created font is used by the calculateSize() method, so we have to keep it till after the splitAt method call.
 		g.setFont(oldFont);
 		font.dispose();
 
-		return splitAt(context, split);
+		return splitPair;
 	}
 
 	/**
 	 * Return a pair of boxes representing a split at the given offset. If split is zero, then the returned left box
 	 * should be null. If the split is equal to the length of the text, then the right box should be null.
-	 * 
+	 *
 	 * @param context
-	 *            LayoutContext used to calculate the sizes of the resulting boxes.
+	 *            LayoutContext used to calculate size. The correct font has to be set in the context's graphics before
+	 *            calling this method.
 	 * @param offset
 	 *            location of the split, relative to the start of the text box.
+	 * @param leftWidth
+	 *            Calculated width of the left box. The width has already been calculated by the calling class, so
+	 *            there's no need to calculated it again.
+	 * @param maxWidth
+	 *            The maximal width of the current split. Used to calculate the remaining width of the returned Pair.
 	 * @return
 	 */
-	public abstract Pair splitAt(LayoutContext context, int offset);
+	protected abstract Pair splitAt(LayoutContext context, int offset, int leftWidth, int maxWidth);
 
 	/**
 	 * @see java.lang.Object#toString()
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/VerticalRange.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/VerticalRange.java
index ca7aed1..c4f8cc1 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/VerticalRange.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/VerticalRange.java
@@ -13,7 +13,7 @@
 
 import java.text.MessageFormat;
 
-import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.AssertionFailedException;
 
 /**
  * Represents a vertical range used in the layouting algorithm. Zero-length ranges (i.e. ranges where top == bottom) are
@@ -33,7 +33,9 @@
 	 *            bottom of the range, must be >= top
 	 */
 	public VerticalRange(final int top, final int bottom) {
-		Assert.isTrue(top <= bottom, MessageFormat.format("top {0} must not be above bottom {1}", top, bottom));
+		if (top > bottom) {
+			throw new AssertionFailedException(MessageFormat.format("top {0} must not be above bottom {1}", top, bottom));
+		}
 		this.top = top;
 		this.bottom = bottom;
 	}
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 5153b9a..7e374dc 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
@@ -41,7 +41,6 @@
 import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
 import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
 import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
-import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager;
 import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMValidator;
 import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMValidator.ElementContentComparator;
 import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMValidator.ElementPathRecordingResult;
@@ -64,9 +63,7 @@
 
 	private final DocumentContentModel documentContentModel;
 
-	private CMDocument dtd;
-
-	private final Map<URL, CMDocument> contentModelCache = new HashMap<URL, CMDocument>();
+	private final Map<String, CMDocument> contentModelCache = new HashMap<String, CMDocument>();
 
 	private final CMValidator validator = new CMValidator();
 
@@ -90,48 +87,29 @@
 		return documentContentModel;
 	}
 
-	private CMDocument getSchema(final String namespaceURI) {
-		if (isDTDDefined()) {
-			return getDTD();
-		}
-		if (namespaceURI == null) {
-			/*
-			 * This can be the case if the document does neither contain a doctype declaration nor a default namespace
-			 * declaration.
-			 */
-			return getSchema((URL) null);
-		}
-		final URL resolved = documentContentModel.resolveSchemaIdentifier(namespaceURI);
-		return getSchema(resolved);
-	}
-
-	private CMDocument getSchema(final URL schemaUrl) {
-		if (contentModelCache.containsKey(schemaUrl)) {
-			return contentModelCache.get(schemaUrl);
+	private CMDocument getContentModelDoc(final String schemaURI) {
+		if (contentModelCache.containsKey(schemaURI)) {
+			return contentModelCache.get(schemaURI);
 		}
 
-		final CMDocument contentModel;
-		if (schemaUrl != null) {
-			final ContentModelManager modelManager = ContentModelManager.getInstance();
-			contentModel = modelManager.createCMDocument(schemaUrl.toString(), null);
+		CMDocument contentModel;
+
+		if (schemaURI == null) {
+			contentModel = documentContentModel.getContentModelDocument();
 		} else {
+			contentModel = documentContentModel.getContentModelDocument(schemaURI);
+		}
+
+		if (contentModel == null) {
+			// Schema could not be resolved - create a dummy instance
 			contentModel = new UnknownCMDocument(null);
 		}
-		contentModelCache.put(schemaUrl, contentModel);
+
+		contentModelCache.put(schemaURI, contentModel);
+
 		return contentModel;
 	}
 
-	private boolean isDTDDefined() {
-		return documentContentModel.isDtdAssigned();
-	}
-
-	private CMDocument getDTD() {
-		if (dtd == null && documentContentModel.isDtdAssigned()) {
-			dtd = documentContentModel.getDTD();
-		}
-		return dtd;
-	}
-
 	public AttributeDefinition getAttributeDefinition(final IAttribute attribute) {
 		final String attributeName = attribute.getLocalName();
 		final CMElementDeclaration cmElement = getElementDeclaration(attribute.getParent());
@@ -190,7 +168,7 @@
 			return null;
 		}
 		final String localName = element.getLocalName();
-		final CMElementDeclaration declarationFromRoot = (CMElementDeclaration) getSchema(element.getQualifiedName().getQualifier()).getElements().getNamedItem(localName);
+		final CMElementDeclaration declarationFromRoot = (CMElementDeclaration) getContentModelDoc(element.getQualifiedName().getQualifier()).getElements().getNamedItem(localName);
 		if (declarationFromRoot != null) {
 			return declarationFromRoot;
 		}
@@ -346,7 +324,7 @@
 
 	private Set<CMElementDeclaration> getValidRootElements(final String namespaceURI) {
 		final HashSet<CMElementDeclaration> result = new HashSet<CMElementDeclaration>();
-		final Iterator<?> iter = getSchema(namespaceURI).getElements().iterator();
+		final Iterator<?> iter = getContentModelDoc(namespaceURI).getElements().iterator();
 		while (iter.hasNext()) {
 			final CMElementDeclaration element = (CMElementDeclaration) iter.next();
 			result.add(element);
@@ -368,7 +346,13 @@
 			return true;
 		}
 
-		final CMNode parent = getSchema(element.getQualifier()).getElements().getNamedItem(element.getLocalName());
+		final CMDocument document = getContentModelDoc(element.getQualifier());
+		if (document == null) {
+			System.out.println("Unable to resolve validation schema for " + element.getQualifier());
+			return true;
+		}
+		CMNode parent = null;
+		parent = document.getElements().getNamedItem(element.getLocalName());
 		if (!(parent instanceof CMElementDeclaration)) {
 			return true;
 		}
@@ -425,7 +409,7 @@
 	private Set<String> getRequiredNamespaces(final String namespaceUri, final Set<CMNode> visitedNodes) {
 		final HashSet<String> result = new HashSet<String>();
 		result.add(namespaceUri);
-		final CMDocument mainSchema = getSchema(namespaceUri);
+		final CMDocument mainSchema = getContentModelDoc(namespaceUri);
 		for (final Iterator<?> iter = mainSchema.getElements().iterator(); iter.hasNext();) {
 			final CMElementDeclaration elementDeclaration = (CMElementDeclaration) iter.next();
 			result.addAll(getRequiredNamespaces(elementDeclaration, visitedNodes));
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/ContentRange.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/ContentRange.java
index 68b8f79..e576af7 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/ContentRange.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/ContentRange.java
@@ -12,7 +12,7 @@
 

 import java.text.MessageFormat;

 

-import org.eclipse.core.runtime.Assert;

+import org.eclipse.core.runtime.AssertionFailedException;

 

 /**

  * An immutable representation of a range within <code>IContent</code>.

@@ -35,7 +35,10 @@
 	 *            the end offset of this range

 	 */

 	public ContentRange(final int startOffset, final int endOffset) {

-		Assert.isTrue(startOffset <= endOffset, MessageFormat.format("startOffset {0} must not be greater than endOffset {1}", startOffset, endOffset));

+		if (startOffset > endOffset) {

+			// Do not use Assert.isTrue. This Contructor is called very often and the use of Assert.isTrue would evaluate the Message.format every time.

+			throw new AssertionFailedException(MessageFormat.format("assertion failed: startOffset {0} must not be greater than endOffset {1}", startOffset, endOffset)); //$NON-NLS-1$

+		}

 		this.startOffset = startOffset;

 		this.endOffset = endOffset;

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/DocumentContentModel.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/DocumentContentModel.java
index e74650f..e8823aa 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/DocumentContentModel.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/DocumentContentModel.java
@@ -11,8 +11,6 @@
 package org.eclipse.vex.core.provisional.dom;

 

 import java.io.IOException;

-import java.net.MalformedURLException;

-import java.net.URL;

 import java.text.MessageFormat;

 

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

@@ -42,17 +40,45 @@
 		initialize(baseUri, publicId, systemId, rootElement);

 	}

 

+	/**

+	 * Initialize the content model.

+	 * 

+	 * @param baseUri

+	 *            The base uri of the loaded document

+	 * @param publicId

+	 *            The PublicID of the DocumentTypeDefinition (DTD)

+	 * @param systemId

+	 *            The SystemID of the DocumentTypeDefinition (DTD)

+	 * @param rootElement

+	 *            If no DTD is defined (publicId and systemId are both null) the namespace of the root element is used

+	 *            to define the document type.

+	 */

 	public void initialize(final String baseUri, final String publicId, final String systemId, final IElement rootElement) {

 		this.baseUri = baseUri;

 		this.publicId = publicId;

 		this.systemId = systemId;

-		if (rootElement != null) {

+		if (publicId == null && systemId == null && rootElement != null) {

 			schemaId = rootElement.getQualifiedName().getQualifier();

 		} else {

 			schemaId = null;

 		}

 	}

 

+	/**

+	 * Sets an explicit namespace.

+	 * 

+	 * @param baseUri

+	 *            The base uri of the loaded document

+	 * @param rootNamespace

+	 *            The default namespace to resolve the XML-Schema for validation.

+	 */

+	public void setSchemaId(final String baseUri, final String rootNamespace) {

+		this.baseUri = baseUri;

+		publicId = null;

+		systemId = null;

+		schemaId = rootNamespace;

+	}

+

 	public String getMainDocumentTypeIdentifier() {

 		if (publicId != null) {

 			return publicId;

@@ -71,29 +97,76 @@
 		return systemId;

 	}

 

+	public String getSchemaId() {

+		return schemaId;

+	}

+

 	public boolean isDtdAssigned() {

 		return publicId != null || systemId != null;

 	}

 

-	public CMDocument getDTD() {

-		final URL resolvedPublicId = resolveSchemaIdentifier(publicId);

-		if (resolvedPublicId != null) {

-			return createCMDocument(resolvedPublicId);

+	/**

+	 * Create and return the WTP CMDocument for the DTD or schema defined by this ContentModel.

+	 * 

+	 * @return The resolved CMDocument.

+	 */

+	public CMDocument getContentModelDocument() {

+		if (schemaId != null) {

+			return getContentModelDocument(schemaId);

 		}

-		return createCMDocument(resolveSystemId(systemId));

+

+		String resolvedURI = null;

+		try {

+			resolvedURI = resolveResourceURI(publicId, systemId);

+			if (resolvedURI == null) {

+				return null;

+			}

+			return createCMDocument(resolvedURI);

+		} catch (final Exception e) {

+			throw new AssertionError(MessageFormat.format("Resolution of systemId ''{0}'' resulted in a exception:{1}. {2}", systemId, resolvedURI, e.getMessage()));

+		}

 	}

 

-	private CMDocument createCMDocument(final URL resolvedDtdUrl) {

-		if (resolvedDtdUrl == null) {

+	/**

+	 * Create and return the WTP CMDocument for the XML-Schema at the given URI or namespace. The XML catalog is used to

+	 * resolve the schema URI.

+	 * 

+	 * @param schemaID

+	 *            The URI or the namespace of the XML-Schema.

+	 * @return The resolved CMDocument.

+	 */

+	public CMDocument getContentModelDocument(final String schemaId) {

+		String resolvedUri = null;

+		try {

+			resolvedUri = resolveResourceURI(null, schemaId);

+			if (resolvedUri == null) {

+				return null;

+			}

+			return createCMDocument(resolvedUri);

+		} catch (final Exception e) {

+			throw new AssertionError(MessageFormat.format("Resolution of resource URI ''{0}'' resulted in a exception:{1}. {2}", schemaId, resolvedUri, e.getMessage()));

+		}

+	}

+

+	/**

+	 * Create a new CMDocument from the DTD or XML-Schema at the given URI.

+	 * 

+	 * @param resourceURI

+	 *            The URI containing the schema or dtd.

+	 * @return

+	 */

+	private CMDocument createCMDocument(final String resourceURI) {

+		if (resourceURI == null) {

 			return null;

 		}

 		final ContentModelManager modelManager = ContentModelManager.getInstance();

-		return modelManager.createCMDocument(resolvedDtdUrl.toString(), null);

+		final CMDocument cmDocument = modelManager.createCMDocument(resourceURI, null);

+		return cmDocument;

 	}

 

 	public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {

-		final String resolved = URI_RESOLVER.resolve(baseUri, publicId, systemId);

-		System.out.println("Resolved " + publicId + " " + systemId + " -> " + resolved);

+		final String resolved = resolveResourceURI(publicId, systemId);

+

 		if (resolved == null) {

 			return null;

 		}

@@ -103,36 +176,19 @@
 		return result;

 	}

 

-	public URL resolveSchemaIdentifier(final String schemaIdentifier) {

-		if (schemaIdentifier == null) {

-			return null;

-		}

-		final String schemaLocation = URI_RESOLVER.resolve(baseUri, schemaIdentifier, null);

-		if (schemaLocation == null) {

-			/*

-			 * TODO this is a common case that should be handled somehow - a hint should be shown: the schema is not

-			 * available, the schema should be added to the catalog by the user - an inferred schema should be used, to

-			 * allow to at least display the document in the editor - this is not the right place to either check or

-			 * handle this

-			 */

-			return null;

-		}

-		try {

-			return new URL(schemaLocation);

-		} catch (final MalformedURLException e) {

-			throw new AssertionError(MessageFormat.format("Resolution of schema ''{0}'' resulted in a malformed URL: ''{1}''. {2}", schemaIdentifier, schemaLocation, e.getMessage()));

-		}

-	}

-

-	public URL resolveSystemId(final String systemId) {

-		final String schemaLocation = URI_RESOLVER.resolve(baseUri, null, systemId);

-		if (schemaLocation == null) {

-			return null;

-		}

-		try {

-			return new URL(schemaLocation);

-		} catch (final MalformedURLException e) {

-			throw new AssertionError(MessageFormat.format("Resolution of systemId ''{0}'' resulted in a malformed URL: ''{1}''. {2}", systemId, schemaLocation, e.getMessage()));

-		}

+	/**

+	 * Resolve the URI for a given Resource with the XML-Catalog.

+	 * 

+	 * @param publicId

+	 *            The public identifier (DTD) of the resource being referenced, may be null

+	 * @param systemId

+	 *            The system identifier (DTD) or the namespace (XML-Schema) of the resource being referenced, may be

+	 *            null.

+	 * @return A String containing the resolved URI.

+	 * @throws IOException

+	 */

+	public String resolveResourceURI(final String publicId, final String systemId) throws IOException {

+		final String resolved = URI_RESOLVER.resolve(baseUri, publicId, systemId);

+		return resolved;

 	}

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/IPosition.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/IPosition.java
index d8850ad..98a04b3 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/IPosition.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/provisional/dom/IPosition.java
@@ -4,7 +4,7 @@
  * 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 - NULL object
@@ -18,7 +18,7 @@
  * 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 IPosition {
+public interface IPosition extends Comparable<IPosition> {
 
 	static IPosition NULL = new IPosition() {
 		public int getOffset() {
@@ -33,6 +33,11 @@
 		public String toString() {
 			return "NULL";
 		}
+
+		@Override
+		public int compareTo(final IPosition other) {
+			return -1;
+		}
 	};
 
 	/**
diff --git a/org.eclipse.vex.docbook/plugin.properties b/org.eclipse.vex.docbook/plugin.properties
index 050fe5a..6750db3 100644
--- a/org.eclipse.vex.docbook/plugin.properties
+++ b/org.eclipse.vex.docbook/plugin.properties
@@ -13,9 +13,7 @@
 
 doctype.docbook4_5=DocBook v4.5
 doctype.docbook5_0_DTD=DocBook v5.0 (DTD)
-doctype.docbook5_0_XSD1=DocBook v5.0 (http://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd)
-doctype.docbook5_0_XSD2=DocBook v5.0 (http://docbook.org/xml/5.0/xsd/docbook.xsd)
-doctype.docbook5_0_XSD3=DocBook v5.0 (http://docbook.org/ns/docbook)
+doctype.docbook5_0_XSD2=DocBook v5.0 (XML Schema)
 
 style.docbook-plain=DocBook Plain
 contentType.name=DocBook XML Document

diff --git a/org.eclipse.vex.docbook/plugin.xml b/org.eclipse.vex.docbook/plugin.xml
index 1079b51..7dae25e 100644
--- a/org.eclipse.vex.docbook/plugin.xml
+++ b/org.eclipse.vex.docbook/plugin.xml
@@ -16,6 +16,14 @@
              uri="4.5/docbookx.dtd"
              webURL="http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
        </public>
+       <system
+             systemId="http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
+             uri="4.5/docbookx.dtd">
+       </system>
+       <system
+             systemId="http://docbook.org/xml/4.5/docbookx.dtd"
+             uri="4.5/docbookx.dtd">
+       </system>
        <uri
              name="urn:org:eclipse:vex:styles:docbook:docbook-plain.css"
              uri="styles/docbook-plain.css">
@@ -33,33 +41,41 @@
              webURL="http://www.oasis-open.org/docbook/xml/5.0/docbook.dtd">
        </public>
        <uri
-             name="http://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd"
-             uri="5.0/xsd/docbook.xsd">
-       </uri>
-       <uri
-             name="http://docbook.org/xml/5.0/xsd/docbook.xsd"
-             uri="5.0/xsd/docbook.xsd">
-       </uri>
-       <uri
              name="http://docbook.org/ns/docbook"
              uri="5.0/xsd/docbook.xsd">
        </uri>
+       <system
+             systemId="http://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd"
+             uri="5.0/xsd/docbook.xsd">
+       </system>
+       <system
+             systemId="http://docbook.org/xml/5.0/xsd/docbook.xsd"
+             uri="5.0/xsd/docbook.xsd">
+       </system>
        <uri
-             name="http://www.oasis-open.org/docbook/xml/5.0/xsd/xlink.xsd"
+             name="http://www.w3.org/1999/xlink"
              uri="5.0/xsd/xlink.xsd">
        </uri>
-       <uri
-             name="http://docbook.org/xml/5.0/xsd/xlink.xsd"
+       <system
+             systemId="http://www.oasis-open.org/docbook/xml/5.0/xsd/xlink.xsd"
              uri="5.0/xsd/xlink.xsd">
-       </uri>
+       </system>
+       <system
+             systemId="http://docbook.org/xml/5.0/xsd/xlink.xsd"
+             uri="5.0/xsd/xlink.xsd">
+       </system>
        <uri
-             name="http://www.oasis-open.org/docbook/xml/5.0/xsd/xml.xsd"
+             name="http://www.w3.org/XML/1998/namespace"
              uri="5.0/xsd/xml.xsd">
        </uri>
-       <uri
-             name="http://docbook.org/xml/5.0/xsd/xml.xsd"
+       <system
+             systemId="http://www.oasis-open.org/docbook/xml/5.0/xsd/xml.xsd"
              uri="5.0/xsd/xml.xsd">
-       </uri>
+       </system>
+       <system
+             systemId="http://docbook.org/xml/5.0/xsd/xml.xsd"
+             uri="5.0/xsd/xml.xsd">
+       </system>
     </catalogContribution>
  </extension>
  
@@ -145,54 +161,13 @@
       </doctype>
    </extension>
 
-   <extension
-         id="docbook5_0_XSD1"
-         name="%doctype.docbook5_0_XSD1"
-         point="org.eclipse.vex.ui.doctypes">
-      <doctype
-            publicId="http://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd"
-            systemId="5.0/xsd/docbook.xsd">
-            
-         <rootElement
-               name="article">
-         </rootElement>
-         <rootElement
-               name="appendix">
-         </rootElement>
-         <rootElement
-               name="book">
-         </rootElement>
-         <rootElement
-               name="chapter">
-         </rootElement>
-         <rootElement
-               name="sect1">
-         </rootElement>
-         <rootElement
-               name="sect2">
-         </rootElement>
-         <rootElement
-               name="sect3">
-         </rootElement>
-         <rootElement
-               name="sect4">
-         </rootElement>
-         <rootElement
-               name="sect5">
-         </rootElement>
-         <rootElement
-               name="section">
-         </rootElement>
-      </doctype>
-   </extension>
 
    <extension
          id="docbook5_0_XSD2"
          name="%doctype.docbook5_0_XSD2"
          point="org.eclipse.vex.ui.doctypes">
-      <doctype
-            publicId="http://docbook.org/xml/5.0/xsd/docbook.xsd"
-            systemId="5.0/xsd/docbook.xsd">
+      <schema
+            namespaceName="http://docbook.org/ns/docbook">
             
          <rootElement
                name="article">
@@ -224,49 +199,9 @@
          <rootElement
                name="section">
          </rootElement>
-      </doctype>
+      </schema>
    </extension>
 
-   <extension
-         id="docbook5_0_XSD2"
-         name="%doctype.docbook5_0_XSD3"
-         point="org.eclipse.vex.ui.doctypes">
-      <doctype
-            publicId="http://docbook.org/ns/docbook"
-            systemId="5.0/xsd/docbook.xsd">
-            
-         <rootElement
-               name="article">
-         </rootElement>
-         <rootElement
-               name="appendix">
-         </rootElement>
-         <rootElement
-               name="book">
-         </rootElement>
-         <rootElement
-               name="chapter">
-         </rootElement>
-         <rootElement
-               name="sect1">
-         </rootElement>
-         <rootElement
-               name="sect2">
-         </rootElement>
-         <rootElement
-               name="sect3">
-         </rootElement>
-         <rootElement
-               name="sect4">
-         </rootElement>
-         <rootElement
-               name="sect5">
-         </rootElement>
-         <rootElement
-               name="section">
-         </rootElement>
-      </doctype>
-   </extension>
 
    <extension
          id="docbook-plain"
@@ -274,11 +209,12 @@
          point="org.eclipse.vex.ui.styles">
       <style
             css="styles/docbook-plain.css">
+         <doctypeRef
+               publicId="docbook5_0_DTD">
+         </doctypeRef>
          <doctypeRef publicId="-//OASIS//DTD Simplified DocBook XML V1.1//EN"/>
          <doctypeRef publicId="-//OASIS//DTD DocBook XML V4.5//EN"/>
          <doctypeRef publicId="-//OASIS//DTD DocBook XML 5.0//EN"/>
-         <doctypeRef publicId="http://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd"/>
-         <doctypeRef publicId="http://docbook.org/xml/5.0/xsd/docbook.xsd"/>
          <doctypeRef publicId="http://docbook.org/ns/docbook"/>
       </style>
    </extension>
diff --git a/org.eclipse.vex.ui.tests/META-INF/MANIFEST.MF b/org.eclipse.vex.ui.tests/META-INF/MANIFEST.MF
index f666f20..6166a7a 100644
--- a/org.eclipse.vex.ui.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.vex.ui.tests/META-INF/MANIFEST.MF
@@ -14,8 +14,5 @@
  org.w3c.css.sac;bundle-version="[1.3.0,2.0.0)",
  org.junit;bundle-version="4.10.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Export-Package: org.eclipse.vex.ui.internal.config.tests;x-internal:=true,
- org.eclipse.vex.ui.internal.editor.tests;x-internal:=true,
- org.eclipse.vex.ui.tests
 Bundle-Localization: plugin
 Bundle-ClassPath: .
diff --git a/org.eclipse.vex.ui.tests/plugin.xml b/org.eclipse.vex.ui.tests/plugin.xml
index 657600e..dd04ca3 100644
--- a/org.eclipse.vex.ui.tests/plugin.xml
+++ b/org.eclipse.vex.ui.tests/plugin.xml
@@ -26,6 +26,14 @@
       </doctype>

    </extension>

    <extension

+         id="test-schema-doctype"

+         name="test schema doctype"

+         point="org.eclipse.vex.ui.doctypes">

+      <schema

+            namespaceName="http://org.eclipse.vex/namespace">

+      </schema>

+   </extension>

+   <extension

          id="test-style"

          name="test style"

          point="org.eclipse.vex.ui.styles">

@@ -36,5 +44,35 @@
          </doctypeRef>

       </style>

    </extension>

+   <extension

+         id="test-style"

+         name="test style"

+         point="org.eclipse.vex.ui.styles">

+      <style

+            css="testdata/test-schema.css">

+         <doctypeRef

+               publicId="http://org.eclipse.vex/namespace">

+         </doctypeRef>

+      </style>

+   </extension>

+   <extension

+         id="test-style-doctype-id"

+         name="test style doctype id"

+         point="org.eclipse.vex.ui.styles">

+      <style

+            css="testdata/test-doctype-id.css">

+         <doctypeRef

+               publicId="test-schema-doctype2">

+         </doctypeRef>

+      </style>

+   </extension>

+   <extension

+         id="test-schema-doctype2"

+         name="test schema doctype2"

+         point="org.eclipse.vex.ui.doctypes">

+      <schema

+            namespaceName="http://org.eclipse.vex/namespace2">

+      </schema>

+   </extension>

 

 </plugin>

diff --git a/org.eclipse.vex.ui.tests/pom.xml b/org.eclipse.vex.ui.tests/pom.xml
index 55d00cf..096360f 100644
--- a/org.eclipse.vex.ui.tests/pom.xml
+++ b/org.eclipse.vex.ui.tests/pom.xml
@@ -21,11 +21,9 @@
 				<version>${tycho-version}</version>
 				<configuration>
 					<useUIHarness>true</useUIHarness>
-					<testSuite>org.eclipse.vex.ui.tests</testSuite>
-					<testClass>org.eclipse.vex.ui.tests.VexUiTestSuite</testClass>
 				</configuration>
 			</plugin>
 		</plugins>
 	</build>
-		
+
 </project>
diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/ConfigurationRegistryTest.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/ConfigurationRegistryTest.java
index 933f56d..83d6e9b 100644
--- a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/ConfigurationRegistryTest.java
+++ b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/ConfigurationRegistryTest.java
@@ -1,15 +1,17 @@
 /*******************************************************************************

- * Copyright (c) 2010 Florian Thienel and others.

+ * 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

+ * 		Carsten Hiesserich - additional tests 

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

 package org.eclipse.vex.ui.internal.config.tests;

 

+import static org.junit.Assert.assertEquals;

 import static org.junit.Assert.assertFalse;

 import static org.junit.Assert.assertNotNull;

 import static org.junit.Assert.assertTrue;

@@ -20,10 +22,12 @@
 

 import org.eclipse.core.resources.IProject;

 import org.eclipse.vex.ui.internal.config.ConfigEvent;

+import org.eclipse.vex.ui.internal.config.ConfigLoaderJob;

 import org.eclipse.vex.ui.internal.config.ConfigSource;

 import org.eclipse.vex.ui.internal.config.ConfigurationLoader;

 import org.eclipse.vex.ui.internal.config.ConfigurationRegistry;

 import org.eclipse.vex.ui.internal.config.ConfigurationRegistryImpl;

+import org.eclipse.vex.ui.internal.config.DocumentType;

 import org.eclipse.vex.ui.internal.config.IConfigListener;

 import org.eclipse.vex.ui.internal.config.PluginProject;

 import org.junit.After;

@@ -116,6 +120,46 @@
 		assertNotNull(registry.getPluginProject(project));

 	}

 

+	@Test

+	public void testPluginDoctypeDefinition() throws Exception {

+		final ConfigurationRegistry configurationRegistry = new ConfigurationRegistryImpl(new ConfigLoaderJob());

+		configurationRegistry.loadConfigurations();

+

+		final DocumentType doctype = configurationRegistry.getDocumentType("-//Vex//DTD Test//EN", null);

+		assertNotNull(doctype);

+		assertEquals("test.dtd", doctype.getSystemId());

+	}

+

+	@Test

+	public void testPluginNamespaceDefinition() throws Exception {

+		final ConfigurationRegistry configurationRegistry = new ConfigurationRegistryImpl(new ConfigLoaderJob());

+		configurationRegistry.loadConfigurations();

+

+		final DocumentType doctype = configurationRegistry.getDocumentType("http://org.eclipse.vex/namespace", null);

+		assertNotNull(doctype);

+		assertEquals("test schema doctype", doctype.getName());

+	}

+

+	@Test

+	public void testGetDocumentTypesWithStyles() throws Exception {

+		final ConfigurationRegistry configurationRegistry = new ConfigurationRegistryImpl(new ConfigLoaderJob());

+		configurationRegistry.loadConfigurations();

+

+		final DocumentType[] doctypes = configurationRegistry.getDocumentTypesWithStyles();

+		boolean dtdFound = false;

+		boolean schemaFound = false;

+		for (final DocumentType doctype : doctypes) {

+			if ("test doctype".equals(doctype.getName())) {

+				dtdFound = true;

+			}

+			if ("test schema doctype".equals(doctype.getName())) {

+				schemaFound = true;

+			}

+		}

+		assertTrue("DoctypeWithStyles should return Doctype with DTD ", dtdFound);

+		assertTrue("DoctypeWithStyles should return Docype with namespace ", schemaFound);

+	}

+

 	private static class MockConfigurationLoader implements ConfigurationLoader {

 		private final List<ConfigSource> loadedConfigSources;

 

diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/PreferencesTest.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/PreferencesTest.java
new file mode 100644
index 0000000..de9b323
--- /dev/null
+++ b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/PreferencesTest.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Carsten Hiesserich 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:
+ * 		Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.ui.internal.config.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.URL;
+
+import org.eclipse.vex.ui.internal.VexPlugin;
+import org.eclipse.vex.ui.internal.VexPreferences;
+import org.eclipse.vex.ui.internal.config.ConfigSource;
+import org.eclipse.vex.ui.internal.config.DocumentType;
+import org.eclipse.vex.ui.internal.config.Style;
+import org.junit.Test;
+
+@SuppressWarnings("restriction")
+public class PreferencesTest {
+
+	@Test
+	public void testStylesheetPreference() throws Exception {
+		final VexPreferences preferences = VexPlugin.getDefault().getPreferences();
+		final DocumentType doctype = new DocumentType(new MockConfigSource());
+		doctype.setSimpleId("vex_test_doctype");
+		final Style style = new Style(new MockConfigSource());
+		style.setSimpleId("vex-test-style");
+		preferences.setPreferredStyleId(doctype, style.getUniqueId());
+
+		final String preferredStyleId = preferences.getPreferredStyleId(doctype);
+		assertEquals(style.getUniqueId(), preferredStyleId);
+	}
+
+	private class MockConfigSource extends ConfigSource {
+
+		public MockConfigSource() {
+			super("test_config");
+		}
+
+		@Override
+		public URL getBaseUrl() {
+			return null;
+		}
+
+	}
+}
diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/VexDocumentContentModelTest.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/VexDocumentContentModelTest.java
new file mode 100644
index 0000000..59dafed
--- /dev/null
+++ b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/internal/config/tests/VexDocumentContentModelTest.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Carsten Hiesserich 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:
+ * 		Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.ui.internal.config.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.internal.dom.Element;
+import org.eclipse.vex.ui.internal.config.Style;
+import org.eclipse.vex.ui.internal.editor.NoStyleForDoctypeException;
+import org.eclipse.vex.ui.internal.editor.VexDocumentContentModel;
+import org.junit.Before;
+import org.junit.Test;
+
+@SuppressWarnings("restriction")
+public class VexDocumentContentModelTest {
+
+	private VexDocumentContentModel model;
+
+	@Before
+	public void setUp() throws Exception {
+		model = new VexDocumentContentModel();
+	}
+
+	@Test
+	public void resolveDoctypeByPublicId() throws Exception {
+		try {
+			model.initialize(null, "-//Vex//DTD Test//EN", null, new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement")));
+		} catch (final NoStyleForDoctypeException e) {
+			// We are not interested in the StyleSheet here
+		}
+		assertTrue(model.isDtdAssigned());
+		assertNotNull(model.getDocumentType());
+		assertEquals("test doctype", model.getDocumentType().getName());
+	}
+
+	@Test
+	public void resolveDoctypeBySystemId() throws Exception {
+		try {
+			model.initialize(null, "UnknownPublicId", "test.dtd", new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement")));
+		} catch (final NoStyleForDoctypeException e) {
+			// We are not interested in the StyleSheet here
+		}
+		assertTrue(model.isDtdAssigned());
+		assertNotNull(model.getDocumentType());
+		assertEquals("test doctype", model.getDocumentType().getName());
+	}
+
+	@Test
+	public void resolveDoctypeByNamespace() throws Exception {
+		try {
+			model.initialize(null, null, null, new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement")));
+		} catch (final NoStyleForDoctypeException e) {
+			// We are not interested in the StyleSheet here
+		}
+		assertFalse(model.isDtdAssigned());
+		assertNotNull(model.getDocumentType());
+		assertEquals("test schema doctype", model.getDocumentType().getName());
+	}
+
+	@Test
+	public void resolveCSSByPublicId() throws Exception {
+		model.initialize(null, "-//Vex//DTD Test//EN", null, new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement")));
+		assertTrue(model.isDtdAssigned());
+		final Style style = model.getStyle();
+		assertNotNull(style);
+		assertTrue(style.getResourceUri().toString().endsWith("test.css"));
+	}
+
+	@Test
+	public void resolveCSSBySystemId() throws Exception {
+		model.initialize(null, null, "test.dtd", new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement")));
+		assertTrue(model.isDtdAssigned());
+		final Style style = model.getStyle();
+		assertNotNull(style);
+		assertTrue(style.getResourceUri().toString().endsWith("test.css"));
+	}
+
+	@Test
+	public void resolveCSSByPluginId() throws Exception {
+		model.initialize(null, null, null, new Element(new QualifiedName("http://org.eclipse.vex/namespace2", "rootElement")));
+		final Style style = model.getStyle();
+		assertNotNull(style);
+		assertTrue(style.getResourceUri().toString().endsWith("test-doctype-id.css"));
+	}
+
+	@Test
+	public void resolveCSSByNamespace() throws Exception {
+		model.initialize(null, null, null, new Element(new QualifiedName("http://org.eclipse.vex/namespace", "rootElement")));
+		assertFalse(model.isDtdAssigned());
+		final Style style = model.getStyle();
+		assertNotNull(style);
+		assertTrue(style.getResourceUri().toString().endsWith("test-schema.css"));
+	}
+}
diff --git a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/tests/VexUiTestSuite.java b/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/tests/VexUiTestSuite.java
deleted file mode 100644
index e2fd051..0000000
--- a/org.eclipse.vex.ui.tests/src/org/eclipse/vex/ui/tests/VexUiTestSuite.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2013 Holger Voormann 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:
- *     Holger Voormann - initial API and implementation
- *     Carsten Hiesserich - added OutlineProvider tests
- *******************************************************************************/
-package org.eclipse.vex.ui.tests;
-
-import org.eclipse.vex.ui.internal.config.tests.ConfigLoaderJobTest;
-import org.eclipse.vex.ui.internal.config.tests.ConfigurationRegistryTest;
-import org.eclipse.vex.ui.internal.editor.tests.FindReplaceTargetTest;
-import org.eclipse.vex.ui.internal.editor.tests.HandlerUtilTest;
-import org.eclipse.vex.ui.internal.namespace.tests.EditNamespacesControllerTest;
-import org.eclipse.vex.ui.internal.outline.tests.OutlineFilterTest;
-import org.eclipse.vex.ui.internal.outline.tests.OutlineProviderTest;
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-@RunWith(Suite.class)
-@Suite.SuiteClasses({ ConfigLoaderJobTest.class, ConfigurationRegistryTest.class, EditNamespacesControllerTest.class, FindReplaceTargetTest.class, OutlineProviderTest.class, OutlineFilterTest.class,
-		HandlerUtilTest.class })
-public class VexUiTestSuite {
-}
diff --git a/org.eclipse.vex.ui.tests/testdata/test-doctype-id.css b/org.eclipse.vex.ui.tests/testdata/test-doctype-id.css
new file mode 100644
index 0000000..9a83031
--- /dev/null
+++ b/org.eclipse.vex.ui.tests/testdata/test-doctype-id.css
@@ -0,0 +1,53 @@
+
+html {
+  display: block;
+}
+
+body {
+  display: block;
+}
+
+p {
+  display: block;
+}
+
+block {
+  display: block;
+}
+
+pre {
+  display: block;
+  white-space: pre;
+}
+
+
+/* Styles for positioning tests */
+root {
+  border: 3px 7px 11px 13px;
+  padding: 17px 19px 23px 29px;
+}
+
+small {
+  border-width: 1px 2px 3px 4px;
+  border-style: solid;
+  margin: 100px 200px 300px 400px;
+  padding: 10px 20px 30px 40px;
+  display: block;
+}
+
+medium {
+  border-width: 2px 4px 6px 8px;
+  border-style: solid;
+  margin: 200px 400px 600px 800px;
+  padding: 20px 40px 60px 80px;
+  display: block;
+}
+
+large {
+  border-width: 3px 6px 9px 12px;
+  border-style: solid;
+  margin: 300px 600px 900px 1200px;
+  padding: 30px 60px 90px 120px;
+  display: block;
+}
+
diff --git a/org.eclipse.vex.ui.tests/testdata/test-schema.css b/org.eclipse.vex.ui.tests/testdata/test-schema.css
new file mode 100644
index 0000000..9a83031
--- /dev/null
+++ b/org.eclipse.vex.ui.tests/testdata/test-schema.css
@@ -0,0 +1,53 @@
+
+html {
+  display: block;
+}
+
+body {
+  display: block;
+}
+
+p {
+  display: block;
+}
+
+block {
+  display: block;
+}
+
+pre {
+  display: block;
+  white-space: pre;
+}
+
+
+/* Styles for positioning tests */
+root {
+  border: 3px 7px 11px 13px;
+  padding: 17px 19px 23px 29px;
+}
+
+small {
+  border-width: 1px 2px 3px 4px;
+  border-style: solid;
+  margin: 100px 200px 300px 400px;
+  padding: 10px 20px 30px 40px;
+  display: block;
+}
+
+medium {
+  border-width: 2px 4px 6px 8px;
+  border-style: solid;
+  margin: 200px 400px 600px 800px;
+  padding: 20px 40px 60px 80px;
+  display: block;
+}
+
+large {
+  border-width: 3px 6px 9px 12px;
+  border-style: solid;
+  margin: 300px 600px 900px 1200px;
+  padding: 30px 60px 90px 120px;
+  display: block;
+}
+
diff --git a/org.eclipse.vex.ui/schema/doctype.exsd b/org.eclipse.vex.ui/schema/doctype.exsd
index 3846319..1d2aa3b 100644
--- a/org.eclipse.vex.ui/schema/doctype.exsd
+++ b/org.eclipse.vex.ui/schema/doctype.exsd
@@ -1,133 +1,149 @@
-<?xml version='1.0' encoding='UTF-8'?>

-<!-- Schema file written by PDE -->

-<schema targetNamespace="vex-editor" xmlns="http://www.w3.org/2001/XMLSchema">

-<annotation>

-      <appinfo>

-         <meta.schema plugin="vex-editor" id="doctype" name="Vex DocType"/>

-      </appinfo>

-      <documentation>

-         Registers a new document type with Vex.

-      </documentation>

-   </annotation>

-

-   <element name="extension">

-      <annotation>

-         <appinfo>

-            <meta.element />

-         </appinfo>

-      </annotation>

-      <complexType>

-         <sequence>

-            <element ref="doctype"/>

-         </sequence>

-         <attribute name="point" type="string" use="required">

-            <annotation>

-               <documentation>

-                  

-               </documentation>

-            </annotation>

-         </attribute>

-         <attribute name="id" type="string">

-            <annotation>

-               <documentation>

-                  

-               </documentation>

-            </annotation>

-         </attribute>

-         <attribute name="name" type="string">

-            <annotation>

-               <documentation>

-                  

-               </documentation>

-            </annotation>

-         </attribute>

-      </complexType>

-   </element>

-

-   <element name="doctype">

-      <annotation>

-         <appinfo>

-            <meta.element labelAttribute="publicId"/>

-         </appinfo>

-      </annotation>

-      <complexType>

-         <sequence>

-            <element ref="rootElement" minOccurs="0" maxOccurs="unbounded"/>

-         </sequence>

-         <attribute name="publicId" type="string">

-            <annotation>

-               <documentation>

-                  

-               </documentation>

-            </annotation>

-         </attribute>

-         <attribute name="systemId" type="string">

-            <annotation>

-               <documentation>

-                  

-               </documentation>

-            </annotation>

-         </attribute>

-         <attribute name="outlineProvider" type="string">

-            <annotation>

-               <documentation>

-                  

-               </documentation>

-               <appinfo>

-                  <meta.attribute kind="java" basedOn="net.sf.vex.editor.IOutlineProvider"/>

-               </appinfo>

-            </annotation>

-         </attribute>

-      </complexType>

-   </element>

-

-   <element name="rootElement">

-      <complexType>

-         <attribute name="name" type="string">

-            <annotation>

-               <documentation>

-                  

-               </documentation>

-            </annotation>

-         </attribute>

-      </complexType>

-   </element>

-

-   <annotation>

-      <appinfo>

-         <meta.section type="since"/>

-      </appinfo>

-      <documentation>

-         [Enter the first release in which this extension point appears.]

-      </documentation>

-   </annotation>

-

-   <annotation>

-      <appinfo>

-         <meta.section type="examples"/>

-      </appinfo>

-      <documentation>

-         [Enter extension point usage example here.]

-      </documentation>

-   </annotation>

-

-   <annotation>

-      <appinfo>

-         <meta.section type="apiInfo"/>

-      </appinfo>

-      <documentation>

-         [Enter API information here.]

-      </documentation>

-   </annotation>

-

-   <annotation>

-      <appinfo>

-         <meta.section type="implementation"/>

-      </appinfo>

-      <documentation>

-         [Enter information about supplied implementation of this extension point.]

-      </documentation>

-   </annotation>

-

-

-</schema>

+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="vex-editor" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appinfo>
+         <meta.schema plugin="vex-editor" id="doctype" name="Vex DocType"/>
+      </appinfo>
+      <documentation>
+         Registers a new document type with Vex.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appinfo>
+            <meta.element />
+         </appinfo>
+      </annotation>
+      <complexType>
+         <choice>
+            <element ref="doctype"/>
+            <element ref="schema"/>
+         </choice>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="doctype">
+      <annotation>
+         <appinfo>
+            <meta.element labelAttribute="publicId"/>
+         </appinfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="rootElement" minOccurs="0" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="publicId" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="systemId" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="outlineProvider" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appinfo>
+                  <meta.attribute kind="java" basedOn="net.sf.vex.editor.IOutlineProvider"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="rootElement">
+      <complexType>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="schema">
+      <complexType>
+         <sequence minOccurs="0" maxOccurs="unbounded">
+            <element ref="rootElement"/>
+         </sequence>
+         <attribute name="namespaceName" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The namespace name that is the target of the defined XML-Schema
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="apiInfo"/>
+      </appinfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="since"/>
+      </appinfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="examples"/>
+      </appinfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="implementation"/>
+      </appinfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+
+</schema>
diff --git a/org.eclipse.vex.ui/schema/style.exsd b/org.eclipse.vex.ui/schema/style.exsd
index 26a3933..5ce16ad 100644
--- a/org.eclipse.vex.ui/schema/style.exsd
+++ b/org.eclipse.vex.ui/schema/style.exsd
@@ -1,16 +1,21 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <!-- Schema file written by PDE -->
-<schema targetNamespace="vex-editor">
+<schema targetNamespace="vex-editor" xmlns="http://www.w3.org/2001/XMLSchema">
 <annotation>
-      <appInfo>
+      <appinfo>
          <meta.schema plugin="vex-editor" id="style" name="Vex Style"/>
-      </appInfo>
+      </appinfo>
       <documentation>
-         Registers a new document type with Vex.
+         Registers a new CSS Stylesheet type with Vex.
       </documentation>
    </annotation>
 
    <element name="extension">
+      <annotation>
+         <appinfo>
+            <meta.element />
+         </appinfo>
+      </annotation>
       <complexType>
          <sequence>
             <element ref="style"/>
@@ -49,9 +54,9 @@
                <documentation>
                   
                </documentation>
-               <appInfo>
+               <appinfo>
                   <meta.attribute kind="resource"/>
-               </appInfo>
+               </appinfo>
             </annotation>
          </attribute>
       </complexType>
@@ -62,7 +67,7 @@
          <attribute name="publicId" type="string">
             <annotation>
                <documentation>
-                  
+                  The PublicID (DTD) or namespace (XML-Schema) of the referenced document type.
                </documentation>
             </annotation>
          </attribute>
@@ -70,48 +75,40 @@
    </element>
 
    <annotation>
-      <appInfo>
-         <meta.section type="since"/>
-      </appInfo>
-      <documentation>
-         [Enter the first release in which this extension point appears.]
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appInfo>
-         <meta.section type="examples"/>
-      </appInfo>
-      <documentation>
-         [Enter extension point usage example here.]
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appInfo>
+      <appinfo>
          <meta.section type="apiInfo"/>
-      </appInfo>
+      </appinfo>
       <documentation>
          [Enter API information here.]
       </documentation>
    </annotation>
 
    <annotation>
-      <appInfo>
+      <appinfo>
+         <meta.section type="since"/>
+      </appinfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="examples"/>
+      </appinfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
          <meta.section type="implementation"/>
-      </appInfo>
+      </appinfo>
       <documentation>
          [Enter information about supplied implementation of this extension point.]
       </documentation>
    </annotation>
 
-   <annotation>
-      <appInfo>
-         <meta.section type="copyright"/>
-      </appInfo>
-      <documentation>
-         
-      </documentation>
-   </annotation>
 
 </schema>
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/VexPreferences.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/VexPreferences.java
index a7599d0..056b959 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/VexPreferences.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/VexPreferences.java
@@ -19,7 +19,9 @@
 import org.eclipse.vex.core.internal.css.StyleSheet;

 import org.eclipse.vex.core.provisional.dom.DocumentContentModel;

 import org.eclipse.vex.ui.internal.config.ConfigurationRegistry;

+import org.eclipse.vex.ui.internal.config.DocumentType;

 import org.eclipse.vex.ui.internal.config.Style;

+import org.eclipse.vex.ui.internal.editor.VexDocumentContentModel;

 import org.osgi.service.prefs.BackingStoreException;

 import org.osgi.service.prefs.Preferences;

 

@@ -49,9 +51,9 @@
 		this.configurationRegistry = configurationRegistry;

 	}

 

-	public void setPreferredStyleId(final String publicId, final String styleId) {

+	public void setPreferredStyleId(final DocumentType doctype, final String styleId) {

 		final Preferences preferences = InstanceScope.INSTANCE.getNode(VexPlugin.ID);

-		final String key = getStylePreferenceKey(publicId);

+		final String key = getStylePreferenceKey(doctype.getUniqueId());

 		preferences.put(key, styleId);

 		try {

 			preferences.flush();

@@ -60,9 +62,9 @@
 		}

 	}

 

-	public String getPreferredStyleId(final String publicId) {

+	public String getPreferredStyleId(final DocumentType doctype) {

 		final Preferences preferences = InstanceScope.INSTANCE.getNode(VexPlugin.ID);

-		final String preferredStyleId = preferences.get(getStylePreferenceKey(publicId), null);

+		final String preferredStyleId = preferences.get(getStylePreferenceKey(doctype.getUniqueId()), null);

 		return preferredStyleId;

 	}

 

@@ -70,8 +72,8 @@
 		return publicId + PREFERRED_STYLE_SUFFIX;

 	}

 

-	public Style getPreferredStyle(final String publicId) {

-		return configurationRegistry.getStyle(publicId, getPreferredStyleId(publicId));

+	public Style getPreferredStyle(final DocumentType doctype) {

+		return configurationRegistry.getStyle(doctype, getPreferredStyleId(doctype));

 	}

 

 	public String getIndentationPattern() {

@@ -87,7 +89,13 @@
 	}

 

 	public StyleSheet getStyleSheet(final DocumentContentModel documentContentModel) {

-		final Style style = getPreferredStyle(documentContentModel.getMainDocumentTypeIdentifier());

+		Style style = null;

+		if (documentContentModel instanceof VexDocumentContentModel) {

+			// We only support the VexDocumentContentModel

+			// If there will ever be another DocumentContentModel implememntation, it will

+			// have to define it's own method for resolving styles

+			style = getPreferredStyle(((VexDocumentContentModel) documentContentModel).getDocumentType());

+		}

 		if (style == null) {

 			return StyleSheet.NULL;

 		}

diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigLoaderJob.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigLoaderJob.java
index e80e087..a979bab 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigLoaderJob.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigLoaderJob.java
@@ -108,7 +108,7 @@
 	}
 
 	public boolean isLoading() {
-		return getState() == Job.RUNNING;
+		return getState() == Job.RUNNING || getState() == Job.WAITING;
 	}
 
 	public void load(final Runnable whenDone) {
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistry.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistry.java
index ea8b278..0b73b9f 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistry.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistry.java
@@ -4,7 +4,7 @@
  * 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

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

@@ -35,15 +35,17 @@
 	boolean isLoaded();

 

 	/**

-	 * The document type configuration for the given public identifier, or null if there is no configuration for the

-	 * given public identifier.

+	 * The document type configuration for the given identifier.<br />

+	 * This method tries to resolve by PublicId or namespace first. If this does not yield as result, a doctype with a

+	 * matching SystemId is returned.

 	 * 

-	 * @param publicId

-	 *            the public identifier

-	 * @return the document type configuration for the given public identifier, or null if there is no configuration for

-	 *         the given public identifier.

+	 * @param id

+	 *            the public/system identifier or namespace

+	 * @param systemId

+	 *            the system id, only used when resolving the public id fails. May be null.

+	 * @return the document type configuration for the identifier, or null if there is no doctype found.

 	 */

-	DocumentType getDocumentType(final String publicId);

+	DocumentType getDocumentType(final String id, final String systemId);

 

 	/**

 	 * @return all document type configurations

@@ -56,13 +58,18 @@
 	DocumentType[] getDocumentTypesWithStyles();

 

 	/**

-	 * All styles for the document type with the given public identifier.

+	 * All styles for the given document type. The returned styles are ordered by the way they are resolved:

+	 * <ul>

+	 * <li>1. document type id</li>

+	 * <li>2. Public ID (DTD) or Namespace (XML-Schema)</li>

+	 * <li>3. System ID (DTD)</li>

+	 * </ul>

 	 * 

-	 * @param publicId

-	 *            the document type's public identifier

-	 * @return all styles for the document type with the given public identifier

+	 * @param doctype

+	 *            the document type

+	 * @return all styles for the given document type

 	 */

-	Style[] getStyles(final String publicId);

+	Style[] getStyles(final DocumentType doctype);

 

 	/**

 	 * The style with the given id, or null if there is no style with this id.

@@ -74,16 +81,15 @@
 	Style getStyle(final String styleId);

 

 	/**

-	 * An arbitrary style for the document type with the given public identifier. If available, the style with the given

-	 * style id is preferred.

+	 * An arbitrary style for the given document type. If available, the style with the given style id is preferred.

 	 * 

-	 * @param publicId

-	 *            the document type's public identifier

+	 * @param pdoctype

+	 *            the document type

 	 * @param preferredStyleId

 	 *            the preferred style's id

 	 * @return a style for the given document type, or null if no style is configured for the given document type

 	 */

-	Style getStyle(final String publicId, final String preferredStyleId);

+	Style getStyle(final DocumentType doctype, final String preferredStyleId);

 

 	/**

 	 * The representation of the given plug-in project in the workspace.

diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistryImpl.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistryImpl.java
index 2317d58..971e8cd 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistryImpl.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationRegistryImpl.java
@@ -187,15 +187,22 @@
 		configListeners.fireEvent("configLoaded", e); //$NON-NLS-1$
 	}
 
-	public DocumentType getDocumentType(final String publicId) {
+	public DocumentType getDocumentType(final String id, final String systemId) {
 		final List<ConfigItem> configItems = getAllConfigItems(DocumentType.EXTENSION_POINT);
+		DocumentType systemDoctype = null;
+		// Try to resolve by PublicId or namespace first
 		for (final ConfigItem configItem : configItems) {
 			final DocumentType doctype = (DocumentType) configItem;
-			if (doctype.getPublicId().equals(publicId)) {
+			if (id.equals(doctype.getPublicId()) || id.equals(doctype.getNamespaceName())) {
 				return doctype;
 			}
+			if (systemId != null && systemId.equals(doctype.getSystemId())) {
+				// Save the doctype resolved by SystemID
+				systemDoctype = doctype;
+			}
 		}
-		return null;
+
+		return systemDoctype; // May be null
 	}
 
 	public DocumentType[] getDocumentTypes() {
@@ -210,21 +217,40 @@
 		final List<DocumentType> result = new ArrayList<DocumentType>();
 		for (final ConfigItem configItem : getAllConfigItems(DocumentType.EXTENSION_POINT)) {
 			final DocumentType doctype = (DocumentType) configItem;
-			if (getStyles(doctype.getPublicId()).length > 0) {
+			if (getStyles(doctype).length > 0) {
 				result.add(doctype);
 			}
 		}
 		return result.toArray(new DocumentType[result.size()]);
 	}
 
-	public Style[] getStyles(final String publicId) {
-		final ArrayList<Style> result = new ArrayList<Style>();
+	public Style[] getStyles(final DocumentType doctype) {
+		final ArrayList<Style> resultId = new ArrayList<Style>();
+		final ArrayList<Style> resultPublic = new ArrayList<Style>();
+		final ArrayList<Style> resultSystem = new ArrayList<Style>();
+		final ArrayList<Style> resultSchema = new ArrayList<Style>();
 		for (final ConfigItem configItem : getAllConfigItems(Style.EXTENSION_POINT)) {
 			final Style style = (Style) configItem;
-			if (style.appliesTo(publicId)) {
-				result.add(style);
+			if (style.appliesTo(doctype.getSimpleId())) {
+				resultId.add(style);
+			}
+			if (!doctype.isBlank(doctype.getPublicId()) && style.appliesTo(doctype.getPublicId())) {
+				resultPublic.add(style);
+			}
+			if (!doctype.isBlank(doctype.getSystemId()) && style.appliesTo(doctype.getSystemId())) {
+				resultSystem.add(style);
+			}
+			if (!doctype.isBlank(doctype.getNamespaceName()) && style.appliesTo(doctype.getNamespaceName())) {
+				resultSchema.add(style);
 			}
 		}
+
+		// The resolved stylesheet are returned in a defined order
+		final ArrayList<Style> result = new ArrayList<Style>();
+		result.addAll(resultId);
+		result.addAll(resultPublic);
+		result.addAll(resultSchema);
+		result.addAll(resultSystem);
 		return result.toArray(new Style[result.size()]);
 	}
 
@@ -238,8 +264,8 @@
 		return null;
 	}
 
-	public Style getStyle(final String publicId, final String preferredStyleId) {
-		final Style[] styles = getStyles(publicId);
+	public Style getStyle(final DocumentType doctype, final String preferredStyleId) {
+		final Style[] styles = getStyles(doctype);
 		if (styles.length == 0) {
 			return null;
 		}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationView.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationView.java
index 65c289f..7d3bda7 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationView.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/ConfigurationView.java
@@ -77,7 +77,7 @@
 				return VexPlugin.getDefault().getConfigurationRegistry().getDocumentTypes();
 			}
 			if (parentElement instanceof DocumentType) {
-				return VexPlugin.getDefault().getConfigurationRegistry().getStyles(((DocumentType) parentElement).getPublicId());
+				return VexPlugin.getDefault().getConfigurationRegistry().getStyles((DocumentType) parentElement);
 			}
 			return new Object[0];
 		}
@@ -87,7 +87,7 @@
 				return VexPlugin.getDefault().getConfigurationRegistry();
 			}
 			if (element instanceof Style) {
-				return VexPlugin.getDefault().getConfigurationRegistry().getDocumentType(((Style) element).getDocumentTypes().iterator().next());
+				return VexPlugin.getDefault().getConfigurationRegistry().getDocumentType(((Style) element).getDocumentTypes().iterator().next(), null);
 			}
 			return null;
 		}
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 bf7a2ff..4cbed14 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
@@ -27,9 +27,11 @@
 	private static final String[] EXTS = new String[] { "dtd" }; //$NON-NLS-1$
 
 	private static final String ELT_DOCTYPE = "doctype"; //$NON-NLS-1$
+	private static final String ELT_SCHEMA = "schema"; //$NON-NLS-1$
 	private static final String ATTR_OUTLINE_PROVIDER = "outlineProvider"; //$NON-NLS-1$
 	private static final String ATTR_SYSTEM_ID = "systemId"; //$NON-NLS-1$
 	private static final String ATTR_PUBLIC_ID = "publicId"; //$NON-NLS-1$
+	private static final String ATTR_NAMESPACE_NAME = "namespaceName"; //$NON-NLS-1$
 
 	private static final String ELT_ROOT_ELEMENT = "rootElement"; //$NON-NLS-1$
 	private static final String ATTR_NAME = "name"; //$NON-NLS-1$
@@ -54,13 +56,23 @@
 		if (configElements.length < 1) {
 			return null;
 		}
-		final IConfigElement configElement = configElements[0];
-		final String publicId = configElement.getAttribute(ATTR_PUBLIC_ID);
-		final String systemId = configElement.getAttribute(ATTR_SYSTEM_ID);
 		final DocumentType doctype = new DocumentType(config);
-		doctype.setPublicId(publicId);
-		doctype.setSystemId(systemId);
-		doctype.setResourceUri(newUri(config.resolve(publicId, systemId)));
+		final IConfigElement configElement = configElements[0];
+		if (configElement.getName() == null) {
+			System.out.println("configElement:" + configElement.getName());
+		}
+		if (configElement.getName().equals(ELT_DOCTYPE)) {
+			final String publicId = configElement.getAttribute(ATTR_PUBLIC_ID);
+			final String systemId = configElement.getAttribute(ATTR_SYSTEM_ID);
+			doctype.setPublicId(publicId);
+			doctype.setSystemId(systemId);
+			doctype.setResourceUri(newUri(config.resolve(publicId, systemId)));
+		} else {
+			final String namespaceName = configElement.getAttribute(ATTR_NAMESPACE_NAME);
+			doctype.setNamespaceName(namespaceName);
+			doctype.setResourceUri(newUri(config.resolve(null, namespaceName)));
+		}
+
 		doctype.setOutlineProvider(configElement.getAttribute(ATTR_OUTLINE_PROVIDER));
 
 		final IConfigElement[] rootElementRefs = configElement.getChildren();
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 9ec9bda..ec7df87 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
@@ -48,6 +48,30 @@
 		return systemId;
 	}
 
+	/**
+	 * Returns the namespace name of the document type.
+	 */
+	public String getNamespaceName() {
+		return namespaceName;
+	}
+
+	/**
+	 * Return the main type identifier of this document type.
+	 */
+	public String getMainId() {
+		if (!isBlank(publicId)) {
+			return publicId;
+		}
+		if (!isBlank(namespaceName)) {
+			return namespaceName;
+		}
+		if (!isBlank(systemId)) {
+			return systemId;
+		}
+
+		return "";
+	}
+
 	@Override
 	public String getExtensionPointId() {
 		return EXTENSION_POINT;
@@ -83,13 +107,24 @@
 		this.systemId = systemId;
 	}
 
+	/**
+	 * Sets the namespace name of the document type. This is used when creating new documents but ignored otherwise.
+	 * 
+	 * @param namespaceName
+	 *            new namespace name for the document type.
+	 */
+	public void setNamespaceName(final String namespaceName) {
+		this.namespaceName = namespaceName;
+	}
+
 	public IValidator getValidator() {
 		return (IValidator) getConfig().getParsedResource(getResourceUri());
 	}
 
 	@Override
 	public boolean isValid() {
-		return super.isValid() && !isBlank(publicId) && !isBlank(systemId) && getValidator() != null;
+		final boolean doctypeValid = !isBlank(publicId) && !isBlank(systemId) || !isBlank(namespaceName);
+		return super.isValid() && doctypeValid && getValidator() != null;
 	}
 
 	@Override
@@ -121,6 +156,7 @@
 
 	private String publicId;
 	private String systemId;
+	private String namespaceName;
 	private String outlineProvider;
 	private String[] rootElements = EMPTY_STRING_ARRAY;
 
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DomConfigurationElement.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DomConfigurationElement.java
index 64eb825..089cc0c 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DomConfigurationElement.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/DomConfigurationElement.java
@@ -63,7 +63,7 @@
 	}
 
 	public String getName() {
-		return element.getLocalName();
+		return element.getTagName();
 	}
 
 	public String getValue() {
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/StylePropertyPage.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/StylePropertyPage.java
index 9000db4..4d0be08 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/StylePropertyPage.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/config/StylePropertyPage.java
@@ -195,7 +195,7 @@
 		Arrays.sort(documentTypes);
 		for (final DocumentType documentType : documentTypes) {
 			if (selectedDoctypes.contains(documentType.getName())) {
-				style.addDocumentType(documentType.getPublicId());
+				style.addDocumentType(documentType.getSimpleId());
 			}
 		}
 
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/DocumentInputReader.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/DocumentInputReader.java
new file mode 100644
index 0000000..22fa524
--- /dev/null
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/editor/DocumentInputReader.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Carsten Hiesserich 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:
+ *     Carsten Hiesserich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.ui.internal.editor;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.jface.text.BadLocationException;
+
+/**
+ * This class wraps a {@link org.eclipse.jface.text.IDocument JFace Document} in an Reader. The Jface document already
+ * contains an encoded String, so we can simply return the chars here.
+ */
+public class DocumentInputReader extends Reader {
+
+	private final org.eclipse.jface.text.IDocument document;
+	private int position;
+	private final int documentLength;
+
+	public DocumentInputReader(final org.eclipse.jface.text.IDocument document) {
+		this.document = document;
+		documentLength = document.getLength();
+		position = 0;
+	}
+
+	@Override
+	public void close() throws IOException {
+		// TODO Auto-generated method stub
+
+	}
+
+	/**
+	 * Reads characters into a portion of an array. This method will block until some input is available, an I/O error
+	 * occurs, or the end of the stream is reached.
+	 * 
+	 * @param cbuf
+	 *            - Destination buffer
+	 * @param off
+	 *            - Offset at which to start storing characters
+	 * @param length
+	 *            - Maximum number of characters to read
+	 * 
+	 * @return The number of characters read, or -1 if the end of the stream has been reached
+	 */
+	@Override
+	public int read(final char[] cbuf, final int off, final int length) throws IOException {
+
+		int charsRead = 0;
+		while (charsRead < length && position < documentLength) {
+			try {
+				final char c = document.getChar(position++);
+				cbuf[off + charsRead++] = c;
+			} catch (final BadLocationException e) {
+				return -1;
+			}
+		}
+
+		if (charsRead == 0) {
+			return -1;
+		}
+
+		return charsRead;
+	}
+
+}
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 6e6176a..a53f6fd 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
@@ -89,7 +89,7 @@
 		final String[] typeNames = new String[doctypes.length];
 		for (int i = 0; i < doctypes.length; i++) {
 			typeNames[i] = doctypes[i].getName();
-			if (doctypes[i].getPublicId().equals(publicId)) {
+			if (doctypes[i].getMainId().equals(publicId)) {
 				initSelection = i;
 			}
 		}
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 648b391..3079730 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
@@ -35,18 +35,29 @@
 		this.shell = shell;

 	}

 

+	/**

+	 * This constructor is only menat to be used for unit testing.

+	 */

+	public VexDocumentContentModel() {

+		shell = null;

+	}

+

 	@Override

 	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();

-		if (documentType == null) {

+		if (documentType == null && shell != null) {

 			documentType = queryUserForDocumentType();

 			if (documentType == null) {

 				throw new NoRegisteredDoctypeException(mainDocumentTypeIdentifier, false);

 			}

 			// Reinitialize after the user selected a doctype

-			super.initialize(baseUri, documentType.getPublicId(), documentType.getSystemId(), rootElement);

+			if (documentType.getNamespaceName() != null) {

+				setSchemaId(baseUri, documentType.getNamespaceName());

+			} else {

+				super.initialize(baseUri, documentType.getPublicId(), documentType.getSystemId(), null);

+			}

 		}

 

 		// TODO verify documentType URL???

@@ -55,15 +66,21 @@
 		//			final String message = MessageFormat.format(Messages.getString("VexEditor.noUrlForDoctype"), mainDocumentTypeIdentifier);

 		//			throw new RuntimeException(message);

 		//		}

-

-		style = VexPlugin.getDefault().getPreferences().getPreferredStyle(documentType.getPublicId());

+		style = VexPlugin.getDefault().getPreferences().getPreferredStyle(getDocumentType());

 		if (style == null) {

 			throw new NoStyleForDoctypeException();

 		}

 	}

 

 	private DocumentType getRegisteredDocumentType() {

-		return VexPlugin.getDefault().getConfigurationRegistry().getDocumentType(getMainDocumentTypeIdentifier());

+		if (getMainDocumentTypeIdentifier() == null) {

+			return null;

+		}

+		final DocumentType doctype = VexPlugin.getDefault().getConfigurationRegistry().getDocumentType(getMainDocumentTypeIdentifier(), getSystemId());

+		if (doctype != null) {

+			return doctype;

+		}

+		return null;

 	}

 

 	private DocumentType queryUserForDocumentType() {

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 27464e8..22aa250 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
@@ -74,6 +74,7 @@
 import org.eclipse.ui.commands.ICommandService;
 import org.eclipse.ui.contexts.IContextService;
 import org.eclipse.ui.dialogs.SaveAsDialog;
+import org.eclipse.ui.editors.text.IStorageDocumentProvider;
 import org.eclipse.ui.ide.FileStoreEditorInput;
 import org.eclipse.ui.part.EditorPart;
 import org.eclipse.ui.part.FileEditorInput;
@@ -505,16 +506,6 @@
 	}
 
 	/**
-	 * Return a reasonable style for the given doctype.
-	 * 
-	 * @param publicId
-	 *            Public ID for which to return the style.
-	 */
-	public Style getPreferredStyle(final String publicId) {
-		return configurationRegistry.getStyle(publicId, preferences.getPreferredStyleId(publicId));
-	}
-
-	/**
 	 * Returns the DocumentType associated with this editor.
 	 */
 	public DocumentType getDocumentType() {
@@ -742,8 +733,20 @@
 				}
 			}
 
+			String encoding;
+			if (provider instanceof IStorageDocumentProvider) {
+				// Try to get the encoding from the DocumentProvider
+				encoding = ((IStorageDocumentProvider) provider).getEncoding(getEditorInput());
+			} else {
+				encoding = "UTF-8";
+			}
+
+			// A Reader is used here to avoid an in memory copy of the documents content
+			final InputSource is = new InputSource(new DocumentInputReader(jFaceDoc));
+			is.setEncoding(encoding);
+
+			// Set the systemId of the InputSource to resolve relative URIs
 			final IEditorInput input = getEditorInput();
-			final InputSource is = new InputSource(jFaceDoc.get());
 			if (input instanceof IFileEditorInput) {
 				final IFile file = ((IFileEditorInput) input).getFile();
 				is.setSystemId(file.getLocationURI().toString());
@@ -864,7 +867,7 @@
 		this.style = style;
 		if (vexWidget != null) {
 			vexWidget.setStyleSheet(style.getStyleSheet());
-			preferences.setPreferredStyleId(document.getPublicID(), style.getUniqueId());
+			preferences.setPreferredStyleId(doctype, style.getUniqueId());
 		}
 		vexEditorListeners.fireEvent("styleChanged", new VexEditorEvent(this)); //$NON-NLS-1$
 	}
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/StyleMenu.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/StyleMenu.java
index ffe13fc..098c2f6 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/StyleMenu.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/StyleMenu.java
@@ -20,6 +20,7 @@
 import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.vex.ui.internal.VexPlugin;
+import org.eclipse.vex.ui.internal.config.DocumentType;
 import org.eclipse.vex.ui.internal.config.Style;
 import org.eclipse.vex.ui.internal.editor.VexEditor;
 
@@ -37,8 +38,8 @@
 			return;
 		}
 
-		final String publicId = editor.getDocumentType().getPublicId();
-		for (final Style style : VexPlugin.getDefault().getConfigurationRegistry().getStyles(publicId)) {
+		final DocumentType doctype = editor.getDocumentType();
+		for (final Style style : VexPlugin.getDefault().getConfigurationRegistry().getStyles(doctype)) {
 			final MenuItem menuItem = new MenuItem(menu, SWT.RADIO, index);
 			menuItem.setText(style.getName());
 			menuItem.setSelection(style == editor.getStyle());
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 5b8eea8..2c9fc14 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
@@ -74,7 +74,7 @@
 		try {
 			final IDocument doc = createDocument(typePage.getDocumentType(), typePage.getRootElementName());
 
-			final Style style = VexPlugin.getDefault().getPreferences().getPreferredStyle(typePage.getDocumentType().getPublicId());
+			final Style style = VexPlugin.getDefault().getPreferences().getPreferredStyle(typePage.getDocumentType());
 			if (style == null) {
 				MessageDialog.openError(getShell(), Messages.getString("NewDocumentWizard.noStyles.title"), Messages.getString("NewDocumentWizard.noStyles.message")); //$NON-NLS-1$ //$NON-NLS-2$
 				return false;
@@ -136,7 +136,7 @@
 	}
 
 	private static IDocument createDocumentWithSchema(final DocumentType documentType, final String rootElementName) {
-		final String defaultNamespaceUri = documentType.getPublicId();
+		final String defaultNamespaceUri = documentType.getNamespaceName();
 		final Document document = new Document(new QualifiedName(defaultNamespaceUri, rootElementName));
 
 		final IElement root = document.getRootElement();
diff --git a/org.eclipse.vex.xhtml/styles/xhtml1-plain.css b/org.eclipse.vex.xhtml/styles/xhtml1-plain.css
index 43f820c..d1a71e6 100644
--- a/org.eclipse.vex.xhtml/styles/xhtml1-plain.css
+++ b/org.eclipse.vex.xhtml/styles/xhtml1-plain.css
@@ -1,4 +1,5 @@
 a {
+  display: inline;
   border-bottom: 1px solid;
   color: blue;
 }
@@ -19,7 +20,8 @@
   /* TODO */
 }
 
-b { 
+b {
+  display: inline;
   font-weight: bold;
 }
 
@@ -109,6 +111,7 @@
 }
 
 em {
+  display: inline;
   font-style: italic;
 }
 
@@ -119,7 +122,7 @@
 form {
   /* TODO */
 }
-  
+
 h1 {
   display: block;
   font-size: 2em;
@@ -184,6 +187,7 @@
 }
 
 i {
+  display: inline;
   font-style: italic;
 }
 
@@ -326,6 +330,7 @@
 }
 
 small {
+  display: inline;
   font-size: 80%;
 }
 
@@ -334,6 +339,7 @@
 }
 
 strong {
+  display: inline;
   font-weight: bold;
 }
 
@@ -402,6 +408,7 @@
 }
 
 tt {
+  display: inline;
   font: 12px "Courier New", sans-serif;
 }