bug 257806: read comments within the root element
Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentReaderTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentReaderTest.java
index 4fc9658..ac2f657 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentReaderTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentReaderTest.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.vex.core.internal.dom;
+import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -18,6 +19,7 @@
import java.io.IOException;
import java.net.URL;
+import java.util.List;
import org.eclipse.vex.core.tests.TestResources;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
@@ -121,4 +123,22 @@
assertEquals(2, documentContentModelPosition[0]);
assertEquals(1, entityResolverPosition[0]);
}
+
+ @Test
+ public void readDocumentWithComments() throws Exception {
+ final DocumentReader reader = new DocumentReader();
+ final Document document = reader.read(TestResources.get("documentWithComments.xml"));
+ final Element rootElement = document.getRootElement();
+ final List<Node> rootChildNodes = rootElement.getChildNodes();
+ assertEquals(4, rootChildNodes.size());
+
+ final CommentElement comment1 = (CommentElement) rootChildNodes.get(0);
+ assertEquals("A comment within the root element.", comment1.getText());
+
+ final CommentElement comment2 = (CommentElement) ((Element) rootChildNodes.get(1)).getChildNodes().get(1);
+ assertEquals("A comment within text.", comment2.getText());
+
+ final CommentElement comment3 = (CommentElement) rootChildNodes.get(2);
+ assertEquals("Another comment between two child elements.", comment3.getText());
+ }
}
diff --git a/org.eclipse.vex.core.tests/testResources/documentWithComments.xml b/org.eclipse.vex.core.tests/testResources/documentWithComments.xml
new file mode 100644
index 0000000..13183f4
--- /dev/null
+++ b/org.eclipse.vex.core.tests/testResources/documentWithComments.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE section PUBLIC "-//Eclipse Foundation//DTD Vex Test//EN" "test1.dtd">
+<!-- A comment before the root element. -->
+<section>
+ <!-- A comment within the root element. -->
+ <title>Testdocument with DTD <!-- A comment within text. -->(Public Identifier)</title>
+ <!-- Another comment between two child elements. -->
+ <para>This is a Testdocument using a DTD which is referenced by a public identifier.</para>
+</section>
+<!-- A final comment after the root element. -->
\ No newline at end of file
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CommentElement.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CommentElement.java
new file mode 100644
index 0000000..6da3fb6
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/CommentElement.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.dom;
+
+import org.eclipse.core.runtime.QualifiedName;
+
+/**
+ * Represents a comment
+ */
+public class CommentElement extends Element {
+
+ public static final QualifiedName COMMENT_ELEMENT_NAME = new QualifiedName(null, "!COMMENT");
+
+ public CommentElement() {
+ super(COMMENT_ELEMENT_NAME);
+ }
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentBuilder.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentBuilder.java
index b368fa4..e48918f 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentBuilder.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/DocumentBuilder.java
@@ -11,6 +11,7 @@
*******************************************************************************/
package org.eclipse.vex.core.internal.dom;
+import java.util.Arrays;
import java.util.LinkedList;
import org.eclipse.core.runtime.Assert;
@@ -80,13 +81,21 @@
// ============================================= ContentHandler methods
public void characters(final char[] ch, final int start, final int length) throws SAXException {
+ appendPendingCharsFiltered(ch, start, length);
+ }
+
+ private void appendPendingCharsFiltered(final char[] ch, final int start, final int length) {
// Convert control characters to spaces, since we use nulls for element delimiters
- final char[] chars = new char[length];
- System.arraycopy(ch, start, chars, 0, length);
- for (int i = 0; i < chars.length; i++)
- if (Character.isISOControl(chars[i]) && chars[i] != '\n' && chars[i] != '\r' && chars[i] != '\t')
- chars[i] = ' ';
- pendingChars.append(chars);
+ for (int i = start; i < start + length; i++) {
+ if (isControlCharacter(ch[i]))
+ pendingChars.append(' ');
+ else
+ pendingChars.append(ch[i]);
+ }
+ }
+
+ private static boolean isControlCharacter(final char ch) {
+ return Character.isISOControl(ch) && ch != '\n' && ch != '\r' && ch != '\t';
}
public void endDocument() {
@@ -176,7 +185,7 @@
documentContentModel.initialize(baseUri, dtdPublicID, dtdSystemID, rootElement);
policy = documentContentModel.getWhitespacePolicy();
}
-
+
appendChars(isBlock(element));
stack.add(new StackEntry(element, content.getLength(), isPre(element)));
@@ -206,6 +215,28 @@
// ============================================== LexicalHandler methods
public void comment(final char[] ch, final int start, final int length) {
+ System.out.println("Comment: " + Arrays.toString(ch) + " start: " + start + " length: " + length);
+ System.out.println("Element Stack: " + stack);
+
+ if (stack.isEmpty()) // TODO support comments outside of the root element
+ return;
+
+ final CommentElement element = new CommentElement();
+ final Element parent = stack.getLast().element;
+ parent.addChild(element);
+
+ appendChars(true); // comments are handled as block elements
+ final int startOffset = content.getLength();
+ content.insertElementMarker(content.getLength());
+
+ trimLeading = true; // comments are handled as block elements
+ appendPendingCharsFiltered(ch, start, length);
+ appendChars(true); // comments are handled as block elements
+
+ content.insertElementMarker(content.getLength());
+ element.setContent(content, startOffset, content.getLength() - 1);
+
+ trimLeading = true; // comments are handled as block elements
}
public void endCDATA() {