CVS structure renamed. org.eclipse.wtp.* has been moved to org.eclipse.*
diff --git a/bundles/org.eclipse.wst.dtd.core/.classpath b/bundles/org.eclipse.wst.dtd.core/.classpath
new file mode 100644
index 0000000..065ac06
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.wst.dtd.core/.cvsignore b/bundles/org.eclipse.wst.dtd.core/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/bundles/org.eclipse.wst.dtd.core/.project b/bundles/org.eclipse.wst.dtd.core/.project
new file mode 100644
index 0000000..3bb71a0
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.dtd.core</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.wst.dtd.core/README.txt b/bundles/org.eclipse.wst.dtd.core/README.txt
new file mode 100644
index 0000000..5b71e3e
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/README.txt
@@ -0,0 +1 @@
+This plugin extends the core model to implement a dtd specific model.
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.dtd.core/build.properties b/bundles/org.eclipse.wst.dtd.core/build.properties
new file mode 100644
index 0000000..58016dd
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/build.properties
@@ -0,0 +1,7 @@
+bin.includes = icons/,\
+               plugin.properties,\
+               dtdmodel.jar,\
+               plugin.xml
+jars.compile.order = dtdmodel.jar
+source.dtdmodel.jar = src/
+output.dtdmodel.jar = bin/
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/DTDFile.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/DTDFile.gif
new file mode 100644
index 0000000..64ee536
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/DTDFile.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/any.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/any.gif
new file mode 100644
index 0000000..7017d91
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/any.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/attribute.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/attribute.gif
new file mode 100644
index 0000000..00bb7b4
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/attribute.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/attribute_list.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/attribute_list.gif
new file mode 100644
index 0000000..795eb5e
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/attribute_list.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/comment.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/comment.gif
new file mode 100644
index 0000000..28c2ccb
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/comment.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/element.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/element.gif
new file mode 100644
index 0000000..01f4889
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/element.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/element_ref.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/element_ref.gif
new file mode 100644
index 0000000..749acfc
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/element_ref.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/emptycontent.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/emptycontent.gif
new file mode 100644
index 0000000..bc8e66c
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/emptycontent.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/entity.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/entity.gif
new file mode 100644
index 0000000..6a91888
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/entity.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/entity_reference.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/entity_reference.gif
new file mode 100644
index 0000000..d30b26b
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/entity_reference.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_comm.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_comm.gif
new file mode 100644
index 0000000..28c2ccb
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_comm.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_el.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_el.gif
new file mode 100644
index 0000000..801c133
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_el.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_ent.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_ent.gif
new file mode 100644
index 0000000..2fb2ca7
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_ent.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_not.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_not.gif
new file mode 100644
index 0000000..5909668
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_not.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_unrec.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_unrec.gif
new file mode 100644
index 0000000..6fd82e6
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/fldr_unrec.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/genhtmform_wiz.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/genhtmform_wiz.gif
new file mode 100644
index 0000000..5f54702
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/genhtmform_wiz.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/newdtd_wiz.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/newdtd_wiz.gif
new file mode 100644
index 0000000..2c115ff
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/newdtd_wiz.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/notation.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/notation.gif
new file mode 100644
index 0000000..ce9df98
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/notation.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/one.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/one.gif
new file mode 100644
index 0000000..694c26f
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/one.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/onechoice.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/onechoice.gif
new file mode 100644
index 0000000..d13ba2e
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/onechoice.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/oneormore.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/oneormore.gif
new file mode 100644
index 0000000..8b2b357
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/oneormore.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/oneormorechoice.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/oneormorechoice.gif
new file mode 100644
index 0000000..96398c0
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/oneormorechoice.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/oneormoresequence.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/oneormoresequence.gif
new file mode 100644
index 0000000..041db27
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/oneormoresequence.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/onesequence.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/onesequence.gif
new file mode 100644
index 0000000..5f9658e
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/onesequence.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/optional.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/optional.gif
new file mode 100644
index 0000000..e7422d7
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/optional.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/optionalchoice.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/optionalchoice.gif
new file mode 100644
index 0000000..fb4f9bd
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/optionalchoice.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/optionalsequence.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/optionalsequence.gif
new file mode 100644
index 0000000..f8d5289
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/optionalsequence.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/txtext.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/txtext.gif
new file mode 100644
index 0000000..efa7a38
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/txtext.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/unrecognized_content.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/unrecognized_content.gif
new file mode 100644
index 0000000..358997d
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/unrecognized_content.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/zeroormore.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/zeroormore.gif
new file mode 100644
index 0000000..daf514d
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/zeroormore.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/zeroormorechoice.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/zeroormorechoice.gif
new file mode 100644
index 0000000..a1ac131
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/zeroormorechoice.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/zeroormoresequence.gif b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/zeroormoresequence.gif
new file mode 100644
index 0000000..8ed4cb7
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/icons/full/obj16/zeroormoresequence.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.dtd.core/plugin.properties b/bundles/org.eclipse.wst.dtd.core/plugin.properties
new file mode 100644
index 0000000..0c806f8
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/plugin.properties
@@ -0,0 +1,112 @@
+Structured_Source_DTD_Model.name=Structured Source DTD Model
+Structured_Source_DTD_Model_NL_Support.name=Structured Source DTD Model NL Support
+! Properties file for component: XML tools SSE DTD Model
+! Packaged for translation in:  xml.zip
+
+!plugin.xml
+_UI_PLUGIN_NAME=SSE DTD Model
+
+! Strings for DTDBasicTypeImpl type descriptions
+_UI_NONE_DESC=None
+
+!! NOTE TO TRANSLATOR: Do not translate following text in parentheses on following 10 lines i.e.(CDATA)
+_UI_CHARACTER_DATA_DESC=Character Data (CDATA)
+_UI_IDENTIFIER_DESC=Identifier (ID)
+_UI_ID_REFERENCE_DESC=ID Reference (IDREF)
+_UI_ID_REFERENCES_DESC=ID References (IDREFS)
+_UI_ENTITY_NAME_DESC=Entity Name (ENTITY)
+_UI_ENTITY_NAMES_DESC=Entity Names (ENTITIES)
+_UI_NAME_TOKEN_DESC=Name Token (NMTOKEN)
+_UI_NAME_TOKENS_DESC=Name Tokens (NMTOKENS)
+_UI_ENUM_NAME_TOKENS_DESC=Enumerated Name Tokens
+_UI_ENUM_NOTATION_DESC=Enumerated NOTATION
+
+!dtd/util/CreateListItems.java
+_UI_LABEL_NONE=(none)
+
+! Strings from sed/model
+
+! Attribute.java
+_UI_LABEL_ATTR_DEFAULT_VAL=Attribute Default Change Value
+_UI_LABEL_ATTR_DEFAULT_KIND=Change Attribute Default Value
+_UI_LABEL_ATTR_TYPE=Change Attribute Type
+
+! AttributeEnumList
+_UI_LABEL_ATTR_ENUM_ITEMS=Change Attribute Enumeration Value
+
+! AttributeList
+_UI_LABEL_ATTR_LIST_ADD=Add Attribute
+
+! CMGroupNode
+_UI_LABEL_CM_GRP_NODE_CONNECTOR=Change Connector
+_UI_LABEL_CM_GRP_NODE_INSERT_ELEMENT=Insert Element
+_UI_LABEL_CM_GRP_NODE_ADD_GRP=Add Group
+_UI_LABEL_CM_GRP_NODE_ADD_CHILD=Add Child Element
+
+! CMNode
+_UI_LABEL_CM_NODE_MIX_CONTENT=Mixed Content
+_UI_LABEL_CM_NODE_CHILD_CONTENT=Children Content
+_UI_LABEL_CM_NODE_SET_MIX_CONTENT=Set Mixed Content
+_UI_LABEL_CM_NODE_SET_CHILD_CONTENT=Set Children Content
+
+!! NOTE TO TRANSLATOR - USAGE: "Set <variable content> Content"
+_UI_LABEL_CM_NODE_SET=Set
+_UI_LABEL_CM_NODE_CONTENT=Content
+
+!! NOTE TO TRANSLATOR - DO NOT TRANSLATE FOLLOWING 3 LINES
+_UI_LABEL_CM_NODE_PCDATA=(#PCDATA)
+_UI_LABEL_CM_NODE_ANY=ANY
+_UI_LABEL_CM_NODE_EMPTY=EMPTY
+
+! CMRepeatableNode
+_UI_LABEL_CM_REP_NODE_CHG_OCCUR=Change Occurrence
+
+! Comment
+_UI_LABEL_COMMENT_CHG=Comment Change
+
+! DTDFile
+_UI_LABEL_DTD_FILE_ADD_ELEMENT=Add Element
+_UI_LABEL_DTD_FILE_ADD_ENTITY=Add Entity
+_UI_LABEL_DTD_FILE_ADD_COMMENT=Add Comment
+_UI_LABEL_DTD_FILE_ADD_PARM_ENTITY_REF=Add Parameter Entity Reference
+_UI_LABEL_DTD_FILE_ADD_NOTATION=Add Notation
+_UI_LABEL_DTD_FILE_ADD_ATTR_LIST=Add Attribute List
+_UI_LABEL_DTD_FILE_DELETE=Delete
+
+! DTDNode
+_UI_LABEL_DTD_NODE_NAME_CHG=Name Change
+_UI_LABEL_DTD_NODE_DELETE=Delete
+
+! Element
+_UI_LABEL_ELEMENT_ADD_ATTR=Add Attribute
+_UI_LABEL_ELEMENT_ADD_GRP=Add Group
+_UI_LABEL_ELEMENT_ADD_CHILD=Add Child Element
+
+! Entity
+_UI_LABEL_ENTITY_SET_PARM_ENTITY=Set Parameter Entity
+_UI_LABEL_ENTITY_SET_GENERAL_ENTITY=Set General Entity
+_UI_LABEL_ENTITY_SET_EXT_ENTITY=Set External Entity
+_UI_LABEL_ENTITY_SET_INT_ENTITY=Set Internal Entity
+_UI_LABEL_ENTITY_VALUE_CHG=Entity Value Change
+
+!! NOTE TO TRANSLATOR - USAGE: "NDATA Change"
+_UI_LABEL_ENTITY_NDATA_CHANGE=Change
+
+! ExternalNode
+_UI_LABEL_EXT_NODE_PUBLIC_ID_CHG=Public ID Change
+_UI_LABEL_EXT_NODE_SYSTEM_ID_CHG=System ID Change
+
+! NodeList
+_UI_LABEL_NODE_LIST_ELEMENTS=Elements
+_UI_LABEL_NODE_LIST_ENTITIES=Entities
+_UI_LABEL_NODE_LIST_NOTATIONS=Notations
+_UI_LABEL_NODE_LIST_COMMENTS=Comments
+_UI_LABEL_NODE_LIST_OTHER=Other
+_UI_LABEL_NODE_LIST_ATTRIBUTES=Attributes
+
+! ParameterEntityReference
+_UI_LABEL_PARM_ENTITY_REF_CHG_ENTITY_REF=Change Entity Reference
+_UI_LABEL_PARM_ENTITY_REF_COMMENT_CHG=Comment Change
+
+! TopLevelNode
+_UI_LABEL_TOP_LEVEL_NODE_DELETE=Delete
diff --git a/bundles/org.eclipse.wst.dtd.core/plugin.xml b/bundles/org.eclipse.wst.dtd.core/plugin.xml
new file mode 100644
index 0000000..20563fd
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/plugin.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+	id="org.eclipse.wst.dtd.core"
+	name="%Structured_Source_DTD_Model.name"
+	version="1.0.0"
+	provider-name="Eclipse.org"
+	class="org.eclipse.wst.dtd.core.DTDPlugin">
+
+	<runtime>
+		<library name="dtdmodel.jar">
+			<export name="*" />
+		</library>
+	</runtime>
+	<requires>
+		<import plugin="org.eclipse.core.runtime.compatibility" />
+		<import plugin="org.eclipse.ui.ide" />
+		<import plugin="org.eclipse.ui.views" />
+		<import plugin="org.eclipse.jface.text" />
+		<import plugin="org.eclipse.ui.workbench.texteditor" />
+		<import plugin="org.eclipse.ui.editors" />
+		<import plugin="org.eclipse.wst.sse.core" />
+		<import plugin="org.eclipse.wst.xml.core" />
+		<import plugin="org.eclipse.core.resources" />
+		<import plugin="org.eclipse.core.runtime" />
+		<import plugin="org.eclipse.wst.encoding" />
+		<import plugin="org.eclipse.ui" />
+	</requires>
+
+
+	<extension point="org.eclipse.wst.sse.core.modelHandler">
+		<modelHandler
+			class="org.eclipse.wst.dtd.core.modelhandler.ModelHandlerForDTD"
+			associatedContentTypeId="org.eclipse.wst.dtd.core.dtdsource"
+			id="org.eclipse.wst.sse.core.handler.dtd">
+		</modelHandler>
+	</extension>
+	<extension
+		point="org.eclipse.wst.sse.core.builderdelegate"
+		id="org.eclipse.wst.dtd.core.builderdelegate.todo">
+		<participant
+			class="org.eclipse.wst.dtd.core.builder.delegates.DTDTaskTagSeeker"
+			contentType="org.eclipse.wst.dtd.core.dtdsource"
+		/>
+	</extension>
+
+	<extension point="org.eclipse.team.core.fileTypes">
+		<fileTypes
+			type="text"
+			extension="dtd" />
+		<fileTypes
+			type="text"
+			extension="mod" />
+		<fileTypes
+			type="text"
+			extension="ent" />
+	</extension>
+	
+	   <extension
+         point="org.eclipse.core.runtime.contentTypes">
+         <content-type
+               file-extensions="dtd,mod,ent"
+               priority="normal"
+               name="DTD Content Type"
+               id="dtdsource"
+               base-type="org.eclipse.core.runtime.text"
+			   default-charset="UTF-8">
+			<describer class="org.eclipse.wst.dtd.core.content.ContentDescriberForDTD"/>
+		</content-type>
+   </extension>
+	
+	
+</plugin>
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Attribute.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Attribute.java
new file mode 100644
index 0000000..c037b19
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Attribute.java
@@ -0,0 +1,372 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.Hashtable;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+// base class for an Element's contentmodel
+public class Attribute extends DTDNode {
+
+	public static final String CDATA = DTDPlugin.getDTDString("_UI_CHARACTER_DATA_DESC"); //$NON-NLS-1$
+	public static final String ID = DTDPlugin.getDTDString("_UI_IDENTIFIER_DESC"); //$NON-NLS-1$
+	public static final String IDREF = DTDPlugin.getDTDString("_UI_ID_REFERENCE_DESC"); //$NON-NLS-1$
+	public static final String IDREFS = DTDPlugin.getDTDString("_UI_ID_REFERENCES_DESC"); //$NON-NLS-1$
+	public static final String ENTITY = DTDPlugin.getDTDString("_UI_ENTITY_NAME_DESC"); //$NON-NLS-1$
+	public static final String ENTITIES = DTDPlugin.getDTDString("_UI_ENTITY_NAMES_DESC"); //$NON-NLS-1$
+	public static final String NMTOKEN = DTDPlugin.getDTDString("_UI_NAME_TOKEN_DESC"); //$NON-NLS-1$
+	public static final String NMTOKENS = DTDPlugin.getDTDString("_UI_NAME_TOKENS_DESC"); //$NON-NLS-1$
+	public static final String ENUMERATED_NAME = DTDPlugin.getDTDString("_UI_ENUM_NAME_TOKENS_DESC"); //$NON-NLS-1$
+	public static final String ENUMERATED_NOTATION = DTDPlugin.getDTDString("_UI_ENUM_NOTATION_DESC"); //$NON-NLS-1$
+
+	public static final String[] types = {CDATA, ID, IDREF, IDREFS, ENTITY, ENTITIES, NMTOKEN, NMTOKENS, ENUMERATED_NAME, ENUMERATED_NOTATION};
+
+	protected static Hashtable typeHash = new Hashtable();
+
+	{
+		typeHash.put(DTDRegionTypes.CDATA_KEYWORD, CDATA);
+		typeHash.put(DTDRegionTypes.ID_KEYWORD, ID);
+		typeHash.put(DTDRegionTypes.IDREF_KEYWORD, IDREF);
+		typeHash.put(DTDRegionTypes.IDREFS_KEYWORD, IDREFS);
+		typeHash.put(DTDRegionTypes.ENTITY_KEYWORD, ENTITY);
+		typeHash.put(DTDRegionTypes.ENTITIES_KEYWORD, ENTITIES);
+		typeHash.put(DTDRegionTypes.NMTOKEN_KEYWORD, NMTOKEN);
+		typeHash.put(DTDRegionTypes.NMTOKENS_KEYWORD, NMTOKENS);
+		typeHash.put(DTDRegionTypes.NOTATION_KEYWORD, ENUMERATED_NOTATION);
+		// this one's a special case since there is no keyword for
+		// enumerated name tokens
+		typeHash.put("()", ENUMERATED_NAME); //$NON-NLS-1$
+
+		// now put the reverse in place.  This gives us a 2 way lookup
+		// for when we want to retrieve the value and when we want to set it
+		typeHash.put(CDATA, "CDATA"); //$NON-NLS-1$
+		typeHash.put(ID, "ID"); //$NON-NLS-1$
+		typeHash.put(IDREF, "IDREF"); //$NON-NLS-1$
+		typeHash.put(IDREFS, "IDREFS"); //$NON-NLS-1$
+		typeHash.put(ENTITY, "ENTITY"); //$NON-NLS-1$
+		typeHash.put(ENTITIES, "ENTITIES"); //$NON-NLS-1$
+		typeHash.put(NMTOKEN, "NMTOKEN"); //$NON-NLS-1$
+		typeHash.put(NMTOKENS, "NMTOKENS"); //$NON-NLS-1$
+		typeHash.put(ENUMERATED_NAME, ""); //$NON-NLS-1$
+		typeHash.put(ENUMERATED_NOTATION, "NOTATION"); //$NON-NLS-1$
+	}
+
+	public static final String IMPLIED = "#IMPLIED"; //$NON-NLS-1$
+	public static final String REQUIRED = "#REQUIRED"; //$NON-NLS-1$
+	public static final String FIXED = "#FIXED"; //$NON-NLS-1$
+
+	//  public static final String IMPLIED = "IMPLIED";
+
+	public Attribute(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode);
+	}
+
+	public Image getImage() {
+		return DTDPlugin.getInstance().getImage(DTDResource.ATTRIBUTEICON);
+	}
+
+	public ITextRegion getNameRegion() {
+		return getNextRegion(iterator(), DTDRegionTypes.ATTRIBUTE_NAME);
+	}
+
+	public ITextRegion getNextQuotedLiteral(RegionIterator iter) {
+		while (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			if (region.getType().equals(DTDRegionTypes.SINGLEQUOTED_LITERAL) || region.getType().equals(DTDRegionTypes.DOUBLEQUOTED_LITERAL)) {
+				return region;
+			}
+		}
+		return null;
+	}
+
+	public String getValueFromQuotedRegion(ITextRegion region) {
+		String type = region.getType();
+		if (type.equals(DTDRegionTypes.SINGLEQUOTED_LITERAL) || type.equals(DTDRegionTypes.DOUBLEQUOTED_LITERAL)) {
+			String text = getStructuredDocumentRegion().getText(region);
+			return text.substring(1, text.length() - 1);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	public void setDefaultValue(String value, boolean fixed) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_ATTR_DEFAULT_VAL")); //$NON-NLS-1$
+		setDefaultValue(this, value, fixed);
+		endRecording(this);
+	}
+
+	public void setDefaultValue(Object requestor, String value, boolean fixed) {
+		ITextRegion defaultValue = getNextQuotedLiteral(iterator());
+		String quoteChar = value.indexOf("\"") == -1 ? "\"" : "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		int startOffset = 0;
+		int endOffset = 0;
+		String newText = ""; //$NON-NLS-1$
+
+		String oldValue = getDefaultValue();
+		boolean oldKindIsFixed = getDefaultKind().equals(Attribute.FIXED);
+		if (oldValue.equals(value) && fixed == oldKindIsFixed) {
+			// nothing to do
+			return;
+		}
+
+		if (defaultValue != null) {
+			startOffset = getStructuredDocumentRegion().getStartOffset(defaultValue);
+			endOffset = getStructuredDocumentRegion().getEndOffset(defaultValue);
+		}
+
+		ITextRegion defaultKindRegion = getDefaultKindRegion();
+		if (defaultKindRegion != null) {
+			startOffset = getStructuredDocumentRegion().getStartOffset(defaultKindRegion);
+			endOffset = endOffset == 0 ? getStructuredDocumentRegion().getEndOffset(defaultKindRegion) : endOffset;
+		}
+		else {
+			if (startOffset == 0) {
+				endOffset = startOffset = getOffsetAfterType();
+				newText += " "; //$NON-NLS-1$
+			}
+			ITextRegion typeRegion = getTypeRegion();
+			if (typeRegion == null && getEnumList() == null) {
+				// tack on a default type
+				//        newText += "CDATA ";
+			}
+		}
+		if (fixed) {
+			newText += "#FIXED "; //$NON-NLS-1$
+		}
+		else {
+			if (getDefaultKind().equals("") && value.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
+				// if not fixed and value is "" then reset the default kind to implied
+				newText += "#IMPLIED"; //$NON-NLS-1$
+			}
+		}
+
+		if (!getType().equals("") && !value.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
+			newText += quoteChar + value + quoteChar;
+		}
+		replaceText(requestor, startOffset, endOffset - startOffset, newText);
+	}
+
+	public String getDefaultValue() {
+		ITextRegion defaultValue = getNextQuotedLiteral(iterator());
+		if (defaultValue != null) {
+			return getValueFromQuotedRegion(defaultValue);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	protected int getOffsetAfterType() {
+		ITextRegion typeRegion = getTypeRegion();
+
+		String type = getType();
+		boolean isEnumeration = type.equals(ENUMERATED_NAME) || type.equals(ENUMERATED_NOTATION);
+		if (isEnumeration) {
+			// now check if maybe this is an enumeration
+			if (getEnumList() != null) {
+				return getEnumList().getEndOffset();
+			}
+		}
+		if (typeRegion != null) {
+			return getStructuredDocumentRegion().getEndOffset(typeRegion);
+		}
+		else {
+			ITextRegion nameRegion = getNameRegion();
+			return getStructuredDocumentRegion().getEndOffset(nameRegion);
+			//        // create one
+			//        typeRegion = findOrCreateTypeRegion((String)typeHash.get(CDATA));
+		}
+	}
+
+	public void setDefaultKind(String kind) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_ATTR_DEFAULT_KIND")); //$NON-NLS-1$
+		setDefaultKind(this, kind);
+		endRecording(this);
+	}
+
+	public void setDefaultKind(Object requestor, String kind) {
+
+		ITextRegion defaultKindRegion = getDefaultKindRegion();
+		String oldDefaultKind = defaultKindRegion == null ? "" : getStructuredDocumentRegion().getText(defaultKindRegion); //$NON-NLS-1$
+		if (!kind.equals(oldDefaultKind)) {
+			String newText = kind;
+			int startOffset = 0;
+			int length = 0;
+			if (defaultKindRegion != null) {
+				startOffset = getStructuredDocumentRegion().getStartOffset(defaultKindRegion);
+				length = getStructuredDocumentRegion().getEndOffset(defaultKindRegion) - startOffset;
+			}
+			else {
+				startOffset = getOffsetAfterType();
+				newText = " " + newText; //$NON-NLS-1$
+			}
+
+			ITextRegion defaultValue = getNextQuotedLiteral(iterator());
+
+			if (kind.equals(Attribute.FIXED) || kind.equals("")) { //$NON-NLS-1$
+				if (defaultValue == null) {
+					// we are changing to fixed and wehave no quoted region.  put in an empty value        
+					newText += " \"\""; //$NON-NLS-1$
+				}
+			}
+			else {
+				if (defaultValue != null) {
+					length = getStructuredDocumentRegion().getEndOffset(defaultValue) - startOffset;
+				}
+			}
+			replaceText(requestor, startOffset, length, newText);
+			// do something if there is no "kind" region
+		}
+	}
+
+	public ITextRegion getDefaultKindRegion() {
+		RegionIterator iter = iterator();
+		while (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			if (region.getType() == DTDRegionTypes.IMPLIED_KEYWORD || region.getType() == DTDRegionTypes.REQUIRED_KEYWORD || region.getType() == DTDRegionTypes.FIXED_KEYWORD) {
+				return region;
+			}
+		}
+		return null;
+	}
+
+	public String getDefaultKind() {
+		ITextRegion defaultKindRegion = getDefaultKindRegion();
+		if (defaultKindRegion != null) {
+			return getStructuredDocumentRegion().getText(defaultKindRegion);
+		}
+
+		return ""; //$NON-NLS-1$
+	}
+
+	public ITextRegion getTypeRegion() {
+		RegionIterator iter = iterator();
+
+		while (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			if (region.getType() == DTDRegionTypes.CDATA_KEYWORD || region.getType() == DTDRegionTypes.ID_KEYWORD || region.getType() == DTDRegionTypes.IDREF_KEYWORD || region.getType() == DTDRegionTypes.IDREFS_KEYWORD || region.getType() == DTDRegionTypes.ENTITY_KEYWORD || region.getType() == DTDRegionTypes.ENTITIES_KEYWORD || region.getType() == DTDRegionTypes.NMTOKEN_KEYWORD || region.getType() == DTDRegionTypes.NMTOKENS_KEYWORD || region.getType() == DTDRegionTypes.NOTATION_KEYWORD || region.getType() == DTDRegionTypes.PARM_ENTITY_TYPE) {
+				return region;
+			}
+		}
+		return null;
+	}
+
+	public void setType(String type) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_ATTR_TYPE")); //$NON-NLS-1$
+		setType(this, type);
+		endRecording(this);
+	}
+
+	public void setType(Object requestor, String type) {
+		String oldType = getType();
+		if (!type.equals(oldType)) {
+			boolean wasEnumeration = oldType.equals(ENUMERATED_NAME) || oldType.equals(ENUMERATED_NOTATION);
+			boolean isEnumeration = type.equals(ENUMERATED_NAME) || type.equals(ENUMERATED_NOTATION);
+			String newText = ""; //$NON-NLS-1$
+			int startOffset = 0;
+			int endOffset = 0;
+
+			if (wasEnumeration && !isEnumeration) {
+				// get rid of the old enumlist
+				AttributeEnumList enumList = getEnumList();
+				if (enumList != null) {
+					startOffset = enumList.getStartOffset();
+					endOffset = enumList.getEndOffset();
+				}
+			}
+
+			ITextRegion region = getTypeRegion();
+			if (region != null) {
+				startOffset = getStructuredDocumentRegion().getStartOffset(region);
+				if (endOffset == 0) {
+					endOffset = getStructuredDocumentRegion().getEndOffset(region);
+				}
+			}
+			else if (startOffset == 0) {
+				ITextRegion nameRegion = getNameRegion();
+				newText += " "; //$NON-NLS-1$
+				endOffset = startOffset = getStructuredDocumentRegion().getEndOffset(nameRegion);
+			}
+
+			String newTypeWord = (String) typeHash.get(type);
+			if (newTypeWord == null) {
+				// then this must be a parm entity being used in the type
+				// use the type text directly
+				newTypeWord = type;
+			}
+
+			newText += newTypeWord;
+
+			if (isEnumeration && !wasEnumeration) {
+				// put in a new numlist
+				boolean isSpaceNeeded = !type.equals(ENUMERATED_NAME);
+				newText += isSpaceNeeded ? " " : ""; //$NON-NLS-1$ //$NON-NLS-2$
+				newText += "()"; //$NON-NLS-1$
+			}
+			replaceText(requestor, startOffset, endOffset - startOffset, newText);
+			if (newTypeWord.equals("") && !type.equals(ENUMERATED_NAME)) { //$NON-NLS-1$
+				// the set the defaultkind to ""
+				//        setDefaultKind(requestor, "");
+				setDefaultValue(requestor, "", false); //$NON-NLS-1$
+			}
+
+		}
+	}
+
+	public String getType() {
+		ITextRegion region = getTypeRegion();
+		if (region != null) {
+			String type = (String) typeHash.get(region.getType());
+			if (type == null) {
+				// just return the text of the type region since this may be an entity representing the type;
+				return getStructuredDocumentRegion().getText(region);
+			}
+			return type;
+		}
+		else if (getEnumList() != null) {
+			// enumerated name tokens don't have a type keyword.  just
+			// the existence of the left paren is enough
+			return (String) typeHash.get("()"); //$NON-NLS-1$
+		}
+
+		return ""; //$NON-NLS-1$
+	}
+
+	public void resolveRegions() {
+		removeChildNodes();
+		RegionIterator iter = iterator();
+
+		while (iter.hasNext()) {
+			ITextRegion currentRegion = iter.next();
+			if (currentRegion.getType().equals(DTDRegionTypes.LEFT_PAREN)) {
+				enumList = new AttributeEnumList(getDTDFile(), getStructuredDocumentRegion());
+			}
+			if (enumList != null) {
+				enumList.addRegion(currentRegion);
+				if (currentRegion.getType() == DTDRegionTypes.RIGHT_PAREN) {
+					return;
+				}
+			}
+		}
+
+	}
+
+	private AttributeEnumList enumList = null;
+
+	public AttributeEnumList getEnumList() {
+		return enumList;
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/AttributeEnumList.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/AttributeEnumList.java
new file mode 100644
index 0000000..f539ee1
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/AttributeEnumList.java
@@ -0,0 +1,72 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public class AttributeEnumList extends DTDNode {
+
+	public AttributeEnumList(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode);
+	}
+
+	public Image getImage() {
+		// never exposed in tree
+		return null;
+	}
+
+	private ArrayList list = new ArrayList();
+
+	// return the items that are in this enumerated list
+	public List getItems() {
+		list.clear();
+		RegionIterator iter = iterator();
+		while (iter.hasNext()) {
+			ITextRegion name = getNextRegion(iter, DTDRegionTypes.NAME);
+			if (name != null) {
+				list.add(getStructuredDocumentRegion().getText(name));
+			}
+		}
+		return list;
+	}
+
+	public void setItems(String[] items) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_ATTR_ENUM_ITEMS")); //$NON-NLS-1$
+		setItems(this, items);
+		endRecording(this);
+	}
+
+	public void setItems(Object requestor, String[] items) {
+		if (items != null) {
+			String text = "("; //$NON-NLS-1$
+			for (int i = 0; i < items.length; i++) {
+				if (i > 0) {
+					text += " | " + items[i]; //$NON-NLS-1$
+				}
+				else {
+					text += items[i];
+				}
+			}
+			text += ")"; //$NON-NLS-1$
+			replaceText(requestor, getStartOffset(), getNodeLength(), text);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/AttributeList.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/AttributeList.java
new file mode 100644
index 0000000..9b666be
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/AttributeList.java
@@ -0,0 +1,119 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.ArrayList;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public class AttributeList extends NamedTopLevelNode {
+	public AttributeList(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode, DTDRegionTypes.ATTLIST_TAG);
+	}
+
+	public Image getImage() {
+		return DTDPlugin.getInstance().getImage(DTDResource.ATTRIBUTELISTICON);
+	}
+
+	public void resolveRegions() {
+		removeChildNodes();
+		RegionIterator iter = iterator();
+
+		if (getNameRegion() != null) {
+			// we skip past the name token is our name
+			skipPastName(iter);
+		}
+
+		ArrayList children = new ArrayList();
+		Attribute attribute = null;
+		boolean trailingWhitespace = false;
+		while (iter.hasNext()) {
+			ITextRegion currentRegion = iter.next();
+			if (currentRegion.getType().equals(DTDRegionTypes.ATTRIBUTE_NAME)) {
+				attribute = new Attribute(getDTDFile(), getStructuredDocumentRegion());
+				children.add(attribute);
+				appendChild(attribute);
+				trailingWhitespace = false;
+			}
+			if (attribute != null && currentRegion.getType() != DTDRegionTypes.END_TAG) {
+				if (!trailingWhitespace) {
+					attribute.addRegion(currentRegion);
+				}
+				else {
+					if (currentRegion.getType() == DTDRegionTypes.WHITESPACE) {
+						attribute.addWhitespaceRegion(currentRegion);
+					}
+				}
+
+				// the following prevents extra whitespace from being picked
+				// up by the attribute
+				if (currentRegion.getType() == DTDRegionTypes.REQUIRED_KEYWORD || currentRegion.getType() == DTDRegionTypes.IMPLIED_KEYWORD || currentRegion.getType() == DTDRegionTypes.SINGLEQUOTED_LITERAL || currentRegion.getType() == DTDRegionTypes.DOUBLEQUOTED_LITERAL) {
+					trailingWhitespace = true;
+				}
+			}
+		}
+		int numKids = children.size();
+		for (int i = 0; i < numKids; i++) {
+			((Attribute) children.get(i)).resolveRegions();
+		} // end of for ()
+	}
+
+	public void insertIntoModel(Object requestor, Attribute reference, Attribute node, boolean isAfter) {
+		int offset = 0;
+		String newText = ""; //$NON-NLS-1$
+		String nodeText = node.getFullNodeText();
+		boolean isLastChild = false;
+		if (!isAfter) {
+			offset = reference.getStartOffset();
+		}
+		else {
+			// try and get next child
+			Attribute attr = (Attribute) reference.getNextSibling();
+			if (attr != null) {
+				offset = attr.getStartOffset();
+			}
+			else {
+				// just use the end offset
+				offset = reference.getWhitespaceEndOffset();
+			}
+		}
+		newText += nodeText;// + (isLastChild ? "\n" : "\n\t");
+		if (!node.hasTrailingWhitespace()) {
+			newText += "\n\t"; //$NON-NLS-1$
+		}
+		replaceText(requestor, offset, 0, newText);
+	}
+
+	public void addAttribute(String name) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_ATTR_LIST_ADD")); //$NON-NLS-1$
+
+		DTDNode lastAttribute = (DTDNode) getLastChild();
+		if (lastAttribute != null) {
+			replaceText(this, lastAttribute.getEndOffset(), 0, "\n\t" + name + " CDATA #IMPLIED"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		else {
+			ITextRegion nameRegion = getNameRegion();
+			if (nameRegion != null) {
+				replaceText(this, getStructuredDocumentRegion().getEndOffset(nameRegion), 0, "\n\t" + name + " CDATA #IMPLIED"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+
+		}
+
+		endRecording(this);
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMBasicNode.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMBasicNode.java
new file mode 100644
index 0000000..40d5d1e
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMBasicNode.java
@@ -0,0 +1,169 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+/* CMBasicNode combines all the different content types into one.  The idea behind this is to allow arbitrary name changes to not require a tree update.
+ */
+public class CMBasicNode extends CMRepeatableNode {
+
+	//    static final int EMPTY = 0;
+	//    static final int ANY = 1;
+	//    static final int PCDATA = 2;
+
+	public CMBasicNode(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode);
+	}
+
+	public String getType() {
+		ITextRegion pcdata = getNextRegion(iterator(), DTDRegionTypes.CONTENT_PCDATA);
+		if (pcdata != null) {
+			return PCDATA;
+		}
+
+		if (isRootElementContent()) {
+			final String name = getName();
+			if (isRootElementContent()) {
+				if (name.equals(EMPTY)) {
+					return EMPTY;
+				}
+				else if (name.equals(ANY)) {
+					return ANY;
+				}
+				else {
+					// otherwise just return it's name as the type
+					return name;
+				}
+
+			}
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	public boolean isPCData() {
+		ITextRegion pcdata = getNextRegion(iterator(), DTDRegionTypes.CONTENT_PCDATA);
+		if (pcdata != null) {
+			return true;
+		}
+		return false;
+	}
+
+	public boolean isEmptyAnyOrPCData() {
+		if (isPCData()) {
+			return true;
+		}
+
+
+		final String name = getName();
+		if (isRootElementContent()) {
+			if (name.equals(EMPTY) || name.equals(ANY)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	//    public Node insertRegion(Region token)
+	//    {
+	//      if (!tokenStream.containsToken(token) && token.getType() == Token.OCCUR_TYPE) 
+	//      {
+	//        // then add it so that our range contains it
+	//        insertIntoTokenStream(token);
+	//      }
+	//      return this;
+	//    }
+
+	public boolean isReference() {
+		return !isEmptyAnyOrPCData();
+	}
+
+	public Image getImage() {
+		final String name = getName();
+		ITextRegion pcdata = getNextRegion(iterator(), DTDRegionTypes.CONTENT_PCDATA);
+		if (pcdata != null) {
+			return DTDPlugin.getInstance().getImage(DTDResource.PCDATAICON);
+		}
+
+		if (isRootElementContent()) {
+			if (name.equals(EMPTY)) {
+				return DTDPlugin.getInstance().getImage(DTDResource.EMPTYICON);
+			}
+			else if (name.equals(ANY)) {
+				return DTDPlugin.getInstance().getImage(DTDResource.ANYICON);
+			}
+		}
+
+		// Otherwise this is just an element reference node.  Just return
+		// what CMRepeatableNode would give us
+		return super.getImage();
+	}
+
+	// returns the occurrencetoken, or the token where the occurrence token should appear after
+	public ITextRegion getOccurrenceRegion() {
+		RegionIterator iter = iterator();
+		skipPastName(iter);
+		if (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			if (region.getType() == DTDRegionTypes.OCCUR_TYPE) {
+				return region;
+			}
+		}
+		return getNameRegion();
+	}
+
+	public ITextRegion getNameRegion() {
+		RegionIterator iter = iterator();
+		while (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			if (region.getType() == DTDRegionTypes.NAME || region.getType() == DTDRegionTypes.CONTENT_PCDATA) {
+				return region;
+			}
+		}
+		return null;
+	}
+
+	public void setName(Object requestor, String name) {
+		//    beginRecording(requestor, "Name Change");
+
+		super.setName(requestor, name);
+		if (!isReference()) {
+			// if it is no longer a reference node, remove the occurrence token
+			setOccurrence(requestor, CMRepeatableNode.ONCE);
+		}
+
+		//    endRecording(requestor);
+	}
+
+	/*  public static String getName(int type)
+	 {
+	 switch (type) 
+	 {
+	 case EMPTY:
+	 return emptyString;
+	 case ANY:
+	 return anyString;
+	 case PCDATA:
+	 return pcdataString;
+	 default:
+	 break;
+	 } // end of switch ()
+	 return "";
+	 }*/
+
+}// CMBasicNode
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMGroupNode.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMGroupNode.java
new file mode 100644
index 0000000..8714159
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMGroupNode.java
@@ -0,0 +1,416 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public class CMGroupNode extends CMRepeatableNode {
+
+	public static final char CHOICE = '|';
+	public static final char SEQUENCE = ',';
+
+	//  protected ArrayList children = new ArrayList();
+
+	public CMGroupNode(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode);
+	}
+
+	public String getType() {
+		if (isRootElementContent()) {
+			if (getFirstChild() != null) {
+				CMNode node = (CMNode) getFirstChild();
+				if (node.getType().equals(PCDATA)) {
+					return MIXED;
+				}
+				else {
+					return CHILDREN;
+				}
+			}
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	protected char connector = SEQUENCE;
+
+	/**
+	 * Get the value of connector.
+	 * @return value of connector.
+	 */
+	public char getConnector() {
+		Object[] children = getChildren();
+		for (int i = 0; i < children.length - 1; i++) {
+			DTDNode childA = (DTDNode) children[i];
+			DTDNode childB = (DTDNode) children[i + 1];
+
+			// create a stream between the two siblings and walk it
+			// note that this stream includes the last region of the first sibling and the first region of the next sibling.
+			// both these should be ignored
+			RegionIterator iter = new RegionIterator(getStructuredDocumentRegion(), childA.getEndOffset(), childB.getStartOffset());
+			//      stream.setFirstRegion(childA.getLastRegion());
+			//      stream.setLastRegion(childB.getFirstRegion());
+			//      Iterator iter = stream.iterator();
+			// skip the first region which is the last region of childA
+			//do we need this now ?
+			//      iter.next();
+			ITextRegion currentRegion = null;
+			while (iter.hasNext() && currentRegion != childB.getStartRegion()) {
+				currentRegion = iter.next();
+				if (currentRegion.getType() == DTDRegionTypes.CONNECTOR) {
+					connector = getStructuredDocumentRegion().getText(currentRegion).charAt(0);
+					return connector;
+				}
+			}
+		}
+		return connector;
+	}
+
+	/**
+	 * Set the value of connector.
+	 * @param v  Value to assign to connector.
+	 */
+	public void setConnector(char v) {
+		if (connector != v) {
+			connector = v;
+			// walk through our kids and see if there is a connector between
+			// each sibling.  if not, create one and set the connector.  if there is
+			// then just change the text of the connector
+			Object[] children = getChildren();
+			if (children.length <= 1) {
+				// there won't be any connector existing between the children
+				// just notify a change in the node and return;
+				getDTDFile().notifyNodeChanged(this);
+				return;
+			}
+			beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_CM_GRP_NODE_CONNECTOR")); //$NON-NLS-1$
+			for (int i = 0; i < children.length - 1; i++) {
+				DTDNode childA = (DTDNode) children[i];
+				DTDNode childB = (DTDNode) children[i + 1];
+
+				// create a stream between the two siblings and walk it
+				// note that this stream includes the last region of the first sibling and the first region of the next sibling.
+				// both these should be ignored
+				RegionIterator iter = new RegionIterator(getStructuredDocumentRegion(), childA.getEndOffset(), childB.getStartOffset());
+				// skip the first region which is the last region of childA
+
+				// do we still need this
+				//        iter.next();
+				ITextRegion currentRegion = null;
+				boolean foundConnector = false;
+				while (iter.hasNext() && currentRegion != childB.getStartRegion()) {
+					currentRegion = iter.next();
+					if (currentRegion.getType() == DTDRegionTypes.CONNECTOR) {
+						foundConnector = true;
+						//            Region oldRegion = currentRegion.createCopy();
+						// found a connector! on to the next sibling pair
+						//            currentRegion.updateText(String.valueOf(v));
+						replaceText(this, getStructuredDocumentRegion().getStartOffset(currentRegion), 1, String.valueOf(connector));
+						//changeStructuredDocument(oldRegion, currentRegion);
+						break;
+					}
+				}
+
+				if (!foundConnector) {
+					//if we're here, that means we need to insert a new connector region after childA
+					replaceText(this, childA.getEndOffset(), 0, String.valueOf(connector));
+					//          DTDRegion connectorRegion = new DTDRegion(DTDRegionTypes.CONNECTOR, childA.getEndOffset(), 1);
+					//          insertIntoStructuredDocument(connectorRegion);
+				}
+			}
+			endRecording(this);
+		}
+	}
+
+	public void insertChildNode(String nodeText, int position) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_CM_GRP_NODE_INSERT_ELEMENT")); //$NON-NLS-1$
+		insertChildNode(this, nodeText, position);
+		endRecording(this);
+	}
+
+	public void insertChildNode(Object requestor, String nodeText, int position) {
+		Object[] children = getChildren();
+
+		int startOffset = 0;
+		boolean isLastChild = position == children.length;
+		String newText = ""; //$NON-NLS-1$
+		if (position < children.length) {
+			DTDNode reference = (DTDNode) children[position];
+			startOffset = reference.getStartOffset();
+			newText = nodeText + " " + String.valueOf(getConnector()) + " "; //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		else if (position == children.length) {
+			// add to end
+			DTDNode reference = (DTDNode) children[position - 1];
+			startOffset = reference.getEndOffset();
+			newText = " " + String.valueOf(getConnector()) + " " + nodeText; //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		replaceText(requestor, startOffset, 0, newText);
+	}
+
+	public void delete(Object requestor, DTDNode child) {
+		Object[] children = getChildren();
+
+		if (children.length == 1 && getFirstChild() == child) {
+			replaceText(requestor, child.getStartOffset(), child.getNodeLength(), null);
+			return;
+		}
+
+		for (int i = 0; i < children.length - 1; i++) {
+			DTDNode childA = (DTDNode) children[i];
+			DTDNode childB = (DTDNode) children[i + 1];
+
+			boolean childADeleted = childA == child;
+			boolean childBDeleted = childB == child;
+			if (childADeleted || childBDeleted) {
+				// we found the child
+				int startOffset = childADeleted ? childA.getStartOffset() : childA.getEndOffset();
+				int endOffset = childADeleted ? childB.getStartOffset() : childB.getEndOffset();
+				replaceText(requestor, startOffset, endOffset - startOffset, ""); //$NON-NLS-1$
+				removeChild(child);
+				break;
+			}
+		}
+	}
+
+	public void addGroup() {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_CM_GRP_NODE_ADD_GRP")); //$NON-NLS-1$
+		DTDNode lastNode = (DTDNode) getLastChild();
+		if (lastNode != null) {
+			replaceText(this, lastNode.getEndOffset(), 0, String.valueOf(getConnector()) + " ()"); //$NON-NLS-1$
+		}
+		else {
+			replaceText(this, getStartOffset() + 1, 0, "()"); //$NON-NLS-1$
+		}
+
+		endRecording(this);
+	}
+
+	public void addChild() {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_CM_GRP_NODE_ADD_CHILD")); //$NON-NLS-1$
+		DTDNode lastNode = (DTDNode) getLastChild();
+		if (lastNode != null) {
+			replaceText(this, lastNode.getEndOffset(), 0, String.valueOf(getConnector()) + " NewChild"); //$NON-NLS-1$
+		}
+		else {
+			replaceText(this, getStartOffset() + 1, 0, "NewChild"); //$NON-NLS-1$
+		}
+
+		endRecording(this);
+	}
+
+  public String getName() 
+  {
+    return ""; //$NON-NLS-1$
+  }
+
+  public Image getImage() 
+  {
+  	DTDPlugin resourcePlugin = DTDPlugin.getInstance();
+  	switch (getConnector()) 
+    {
+  		case SEQUENCE :
+        return resourcePlugin.getImage(DTDResource.ONESEQUENCEICON);
+        /*
+  			switch (getOccurrence()) {
+  				case ONCE :
+  					return resourcePlugin.getImage(DTDResource.ONESEQUENCEICON);
+  				case OPTIONAL :
+  					return resourcePlugin.getImage(DTDResource.OPTIONALSEQUENCEICON);
+  				case ONE_OR_MORE :
+  					return resourcePlugin.getImage(DTDResource.ONEORMORESEQUENCEICON);
+  				case ZERO_OR_MORE :
+  					return resourcePlugin.getImage(DTDResource.ZEROORMORESEQUENCEICON);
+  			}
+        */
+  		case CHOICE :
+        return resourcePlugin.getImage(DTDResource.ONECHOICEICON);
+        /*
+  			switch (getOccurrence()) {
+  				case ONCE :
+  					return resourcePlugin.getImage(DTDResource.ONECHOICEICON);
+  				case OPTIONAL :
+  					return resourcePlugin.getImage(DTDResource.OPTIONALCHOICEICON);
+  				case ONE_OR_MORE :
+  					return resourcePlugin.getImage(DTDResource.ONEORMORECHOICEICON);
+  				case ZERO_OR_MORE :
+  					return resourcePlugin.getImage(DTDResource.ZEROORMORECHOICEICON);
+  			}
+        */
+  	}
+  	return null;
+  }
+
+	public void insertIntoModel(Object requestor, CMNode reference, CMNode node, boolean isAfter) {
+		String nodeText = node.getNodeText();
+		List children = getChildrenList();
+
+		int index = children.indexOf(reference);
+		if (index == -1) {
+			// no reference node, add it to the end??
+			index = children.size();
+		}
+		else {
+			// got an index.  if we want to add after, increase by 1
+			index = isAfter ? index + 1 : index;
+		}
+		insertChildNode(requestor, nodeText, index);
+	}
+
+	// returns the occurrenceregion, or the last region where the occurrence region should appear after
+	public ITextRegion getOccurrenceRegion() {
+		int nesting = 0;
+
+		// we skip past the first left paren we see since that is the beginning of our own node
+		RegionIterator iter = iterator();
+		// we assume the first region is the '('
+		iter.next();
+		ITextRegion currentRegion = null;
+		while (iter.hasNext() && nesting >= 0) {
+			currentRegion = iter.next();
+			if (currentRegion.getType() == DTDRegionTypes.LEFT_PAREN) {
+				nesting++;
+			}
+			if (currentRegion.getType() == DTDRegionTypes.RIGHT_PAREN) {
+				nesting--;
+			}
+		}
+		if (nesting < 0) {
+			// This means we have passed over the right paren that marks the end of our grouping.
+			// Look for an occurrence region
+			while (iter.hasNext()) {
+				currentRegion = iter.next();
+				if (currentRegion.getType() == DTDRegionTypes.OCCUR_TYPE) {
+					return currentRegion;
+				}
+			}
+		}
+		// if we're here, this means that there is no occur region.  return the last region 
+		return iter.previous();
+	}
+
+	public void resolveRegions() {
+		int nesting = 0;
+		//    children.clear();
+		removeChildNodes();
+		// we skip past the first left paren we see since that is the beginning of our own node
+		boolean isConnectorSet = false;
+		DTDNode currentGroupNode = null;
+		CMBasicNode currentReferenceNode = null;
+		RegionIterator iter = iterator();
+		// we assume the first region is the '('
+		iter.next();
+		while (iter.hasNext() && nesting >= 0) {
+			ITextRegion currentRegion = iter.next();
+			if (nesting == 0) {
+				if (currentRegion.getType().equals(DTDRegionTypes.CONTENT_PCDATA)) {
+					currentGroupNode = currentReferenceNode = null;
+					DTDNode pcData = new CMBasicNode(getDTDFile(), getStructuredDocumentRegion());
+					pcData.addRegion(currentRegion);
+					appendChild(pcData);
+					//          children.add(pcData);
+				}
+				else if (currentRegion.getType().equals(DTDRegionTypes.NAME)) {
+					// we have hit a new reference node.  Make sure we reset the groupnode var so it doesn't collect more regions
+					currentGroupNode = null;
+					currentReferenceNode = new CMBasicNode(getDTDFile(), getStructuredDocumentRegion());
+					currentReferenceNode.addRegion(currentRegion);
+					appendChild(currentReferenceNode);
+					//          children.add(currentReferenceNode);
+				}
+				else if (currentRegion.getType().equals(DTDRegionTypes.OCCUR_TYPE)) {
+					// we could potentially flag an error here if we hit an occurrence type and currentRefNode and currentGroupNode are null
+					if (currentReferenceNode != null) {
+						//           currentReferenceNode.setOccurrence(currentRegion.getText().toCharArray()[0]);
+						currentReferenceNode.addRegion(currentRegion);
+						currentReferenceNode = null;
+					}
+				}
+				else if (currentRegion.getType().equals(DTDRegionTypes.CONNECTOR)) {
+					// note that if connector is already set and it is different from the current connector region, then we have an error!
+					//         setConnector(currentRegion.getText().toCharArray()[0]);
+				}
+				else if (currentRegion.getType().equals(DTDRegionTypes.LEFT_PAREN)) {
+					if (currentGroupNode == null) {
+						// we have hit a new group.  Make sure we reset the referencenode var so it doesn't collect any more regions
+						currentReferenceNode = null;
+						currentGroupNode = new CMGroupNode(getDTDFile(), getStructuredDocumentRegion());
+						appendChild(currentGroupNode);
+						//            children.add(currentGroupNode);
+					}
+				}
+			}
+
+			if (currentRegion.getType().equals(DTDRegionTypes.LEFT_PAREN)) {
+				nesting++;
+			}
+			if (currentRegion.getType().equals(DTDRegionTypes.RIGHT_PAREN)) {
+				nesting--;
+				if (nesting == 0 && currentGroupNode != null) {
+					currentGroupNode.addRegion(currentRegion);
+					// peek at next region to see if it is an occur region.  if
+					// so, add it to the groupnode
+					if (iter.hasNext()) {
+						ITextRegion nextRegion = iter.next();
+						if (nextRegion.getType().equals(DTDRegionTypes.OCCUR_TYPE)) {
+							currentGroupNode.addRegion(nextRegion);
+						}
+						else {
+							// Otherwise, push it back as the next item to be retrieved by a future next() call
+							iter.previous();
+						}
+					}
+					currentGroupNode = null;
+				}
+			}
+			if (currentGroupNode != null) {
+				currentGroupNode.addRegion(currentRegion);
+			}
+		}
+
+		if (nesting < 0) {
+			// This means we have passed over the right paren that marks the end of our grouping.
+			// Look for an occurrence region
+			while (iter.hasNext()) {
+				ITextRegion currentRegion = iter.next();
+				if (currentRegion.getType().equals(DTDRegionTypes.OCCUR_TYPE)) {
+					//          setOccurrence(currentRegion.getText().toCharArray()[0]);
+				}
+			} // end of while ()
+		}
+
+		//      for (org.w3c.dom.Node child = getFirstChild(); child != null; child = child.getNextSibling())
+		//      {
+		//        System.out.println("child found = " + child);
+		//      }
+
+		Object[] children = getChildren();
+		//    System.out.println("children legnth = " + children.length);
+
+		for (int i = 0; i < children.length; i++) {
+			DTDNode currentNode = (DTDNode) children[i];
+			currentNode.resolveRegions();
+		} // end of while ()
+
+	}
+
+	//    public Object[] getChildren()
+	//    {
+	//      return children.toArray();
+	//    }
+}// CMGroupNode
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMNode.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMNode.java
new file mode 100644
index 0000000..b0cb170
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMNode.java
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+
+// base class for an Element's contentmodel
+public abstract class CMNode extends DTDNode {
+
+	public CMNode(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode);
+	}
+
+	public static final String EMPTY = DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_EMPTY"); //$NON-NLS-1$
+	public static final String ANY = DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_ANY"); //$NON-NLS-1$
+	public static final String PCDATA = DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_PCDATA"); //$NON-NLS-1$
+	public static final String MIXED = DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_MIX_CONTENT"); //$NON-NLS-1$
+	public static final String CHILDREN = DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_CHILD_CONTENT"); //$NON-NLS-1$
+
+
+	boolean rootElementContent;
+
+	/**
+	 * Get the value of rootElementContent.  This tells us whether this
+	 * element content's parent is a direct decendent of the containing element
+	 * @return value of rootElementContent.
+	 */
+	public boolean isRootElementContent() {
+		return rootElementContent;
+	}
+
+	// this is only valid to ask if the content is a root element content
+	abstract public String getType();
+
+	/**
+	 * Set the value of rootElementContent.
+	 * @param v  Value to assign to rootElementContent.
+	 */
+	public void setRootElementContent(boolean v) {
+		this.rootElementContent = v;
+	}
+
+	// if this is a root element, change the content to mixed
+	// ie . (#PCDATA, child1)
+	public void setMixedContent() {
+		if (isRootElementContent()) {
+			if (!getType().equals(MIXED)) {
+				beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_SET_MIX_CONTENT")); //$NON-NLS-1$
+				if (this instanceof CMBasicNode) {
+					replaceText(this, getStartOffset(), getNodeLength(), "(#PCDATA | newChild)*"); //$NON-NLS-1$
+				}
+				else {
+					// now must convert from children content to this one.  must
+					// preserve the children
+					CMGroupNode group = (CMGroupNode) this;
+					group.setConnector(CMGroupNode.CHOICE);
+					group.setOccurrence(CMRepeatableNode.ZERO_OR_MORE);
+					CMNode firstChild = (CMNode) group.getFirstChild();
+					if (!firstChild.getType().equals(PCDATA)) {
+						group.insertChildNode("#PCDATA", 0); //$NON-NLS-1$
+					}
+				}
+				endRecording(this);
+			}
+		}
+	}
+
+	// if this is a root element, change the content to children
+	// ie . (child1)
+	public void setChildrenContent(String newChild) {
+		if (isRootElementContent()) {
+			if (!newChild.equals("")) { //$NON-NLS-1$
+				beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_SET_CHILD_CONTENT")); //$NON-NLS-1$
+				replaceText(this, getStartOffset(), getNodeLength(), "(" + newChild + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+				endRecording(this);
+				return;
+			}
+
+			if (!getType().equals(CHILDREN)) {
+				beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_SET_CHILD_CONTENT")); //$NON-NLS-1$
+				if (this instanceof CMBasicNode) {
+					replaceText(this, getStartOffset(), getNodeLength(), "(newChild)"); //$NON-NLS-1$
+				}
+				else {
+					// now must convert from mixed content to this one.  must
+					// preserve the remaining children
+					CMGroupNode group = (CMGroupNode) this;
+					CMNode firstChild = (CMNode) group.getFirstChild();
+					if (firstChild.getType().equals(PCDATA)) {
+						group.delete(firstChild);
+					}
+				}
+
+				endRecording(this);
+			}
+		}
+	}
+
+	public void setContent(String content) {
+		if (isRootElementContent()) {
+			beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_SET") + " " + content + " " + DTDPlugin.getDTDString("_UI_LABEL_CM_NODE_CONTENT")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+			replaceText(this, getStartOffset(), getNodeLength(), content);
+			endRecording(this);
+		}
+	}
+
+	//    public void delete()
+	//    {
+	//      if (isRootElementContent()) 
+	//      {
+	//        // then the superclasses delete will be fine
+	//        super.delete();
+	//        return;
+	//      }
+
+	//      CMGroupNode parent = (CMGroupNode) getParentNode();
+	//      parent.removeChildNode(this);
+	//    }
+
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMRepeatableNode.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMRepeatableNode.java
new file mode 100644
index 0000000..6e7ce36
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/CMRepeatableNode.java
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public abstract class CMRepeatableNode extends CMNode {
+
+	public static final char ONCE = '1';
+	public static final char OPTIONAL = '?';
+	public static final char ONE_OR_MORE = '+';
+	public static final char ZERO_OR_MORE = '*';
+
+
+	public CMRepeatableNode(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode);
+	}
+
+	public char getOccurrence() {
+		ITextRegion occurRegion = getOccurrenceRegion();
+		if (occurRegion != null && occurRegion.getType() == DTDRegionTypes.OCCUR_TYPE) {
+			return getStructuredDocumentRegion().getText(occurRegion).charAt(0);
+		}
+		return CMRepeatableNode.ONCE;
+	}
+
+	// returns the occurrenceregion, or the last region where the occurrence region should appear after
+	abstract public ITextRegion getOccurrenceRegion();
+
+	public void setOccurrence(char occurrence) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_CM_REP_NODE_CHG_OCCUR")); //$NON-NLS-1$
+		setOccurrence(this, occurrence);
+		endRecording(this);
+	}
+
+	public void setOccurrence(Object requestor, char occurrence) {
+		if (getOccurrence() != occurrence) {
+			ITextRegion region = getOccurrenceRegion();
+			if (region != null) {
+				if (region.getType().equals(DTDRegionTypes.OCCUR_TYPE)) {
+					if (occurrence == CMRepeatableNode.ONCE) {
+						// we need to remove the occur region from the flat model;
+						getDTDFile().getStructuredDocument().replaceText(requestor, getStructuredDocumentRegion().getStartOffset(region), 1, ""); //$NON-NLS-1$
+					}
+					else {
+						//            Region oldOccur = region.createCopy();
+						getDTDFile().getStructuredDocument().replaceText(requestor, getStructuredDocumentRegion().getStartOffset(region), 1, String.valueOf(occurrence));
+						//            changeStructuredDocument(oldOccur, region);
+					}
+				}
+				else if (occurrence != CMRepeatableNode.ONCE) {
+					//          System.out.println(getString());
+					// we need to create an occurrenceRegion
+					replaceText(requestor, getStructuredDocumentRegion().getEndOffset(region), 0, String.valueOf(occurrence));
+				}
+			}
+		}
+	}
+
+	public Image getImage() {
+    DTDPlugin resourcePlugin = DTDPlugin.getInstance();
+    return resourcePlugin.getImage(DTDResource.ELEMENTREFICON);
+	}
+  
+}// CMRepeatableNode
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Comment.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Comment.java
new file mode 100644
index 0000000..2377104
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Comment.java
@@ -0,0 +1,76 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public class Comment extends NamedTopLevelNode {
+
+	public Comment(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode, DTDRegionTypes.COMMENT_START);
+	}
+
+	public Image getImage() {
+		return DTDPlugin.getInstance().getImage(DTDResource.COMMENTICON);
+	}
+
+	public String getName() {
+		String text = getText();
+		if (text.length() <= 30) {
+			return text;
+		}
+		else {
+			return text.substring(0, 29) + "..."; //$NON-NLS-1$
+		}
+	}
+
+	public class StartEndPair {
+		public int startOffset, endOffset;
+	}
+
+	private void getStartAndEndOffsetForText(StartEndPair pair) {
+		RegionIterator iter = iterator();
+		ITextRegion commentStartTag = getStartTag(iter);
+		ITextRegion endCommentTag = getNextRegion(iter, DTDRegionTypes.COMMENT_END);
+		pair.endOffset = getStructuredDocumentRegion().getEndOffset();
+		if (commentStartTag != null) {
+			pair.startOffset = getStructuredDocumentRegion().getEndOffset(commentStartTag);
+		}
+		if (endCommentTag != null) {
+			pair.endOffset = getStructuredDocumentRegion().getStartOffset(endCommentTag);
+		}
+	}
+
+	public String getText() {
+		String text = getStructuredDocumentRegion().getText();
+		int flatNodeStart = getStructuredDocumentRegion().getStartOffset();
+		StartEndPair pair = new StartEndPair();
+		getStartAndEndOffsetForText(pair);
+		return text.substring(pair.startOffset - flatNodeStart, pair.endOffset - flatNodeStart);
+	}
+
+	public void setText(String newText) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_COMMENT_CHG")); //$NON-NLS-1$
+		int flatNodeStart = getStructuredDocumentRegion().getStartOffset();
+		StartEndPair pair = new StartEndPair();
+		getStartAndEndOffsetForText(pair);
+		replaceText(this, pair.startOffset, pair.endOffset - pair.startOffset, newText);
+		endRecording(this);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDFile.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDFile.java
new file mode 100644
index 0000000..fac8c11
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDFile.java
@@ -0,0 +1,671 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.document.DTDModelImpl;
+import org.eclipse.wst.dtd.core.event.IDTDFileListener;
+import org.eclipse.wst.dtd.core.event.NodesEvent;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.dtd.core.util.DTDExternalReferenceRemover;
+import org.eclipse.wst.dtd.core.util.DTDModelUpdater;
+import org.eclipse.wst.dtd.core.util.DTDNotationReferenceRemover;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.events.NewModelEvent;
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+
+
+public class DTDFile implements IndexedRegion {
+
+	protected ArrayList lists = new ArrayList();
+	protected DTDModelImpl dtdModel;
+	protected IStructuredDocument fStructuredDocument;
+
+	public DTDFile(DTDModelImpl dtdModel) {
+		this.dtdModel = dtdModel;
+		this.fStructuredDocument = dtdModel.getStructuredDocument();
+	}
+
+	protected NodeList elementList = new NodeList(this, DTDRegionTypes.ELEMENT_TAG);
+	protected NodeList notationList = new NodeList(this, DTDRegionTypes.NOTATION_TAG);
+	protected NodeList entityList = new NodeList(this, DTDRegionTypes.ENTITY_TAG);
+	protected NodeList commentList = new NodeList(this, DTDRegionTypes.COMMENT_START);
+	protected NodeList unrecognizedList = new NodeList(this, DTDRegionTypes.UNKNOWN_CONTENT);
+	protected NodeList attlistList = new NodeList(this, DTDRegionTypes.ATTLIST_TAG);
+
+	public NodeList getElementsAndParameterEntityReferences() {
+		return elementList;
+	}
+
+	public NodeList getNotations() {
+		return notationList;
+	}
+
+	public NodeList getEntities() {
+		return entityList;
+	}
+
+	public NodeList getComments() {
+		return commentList;
+	}
+
+	public NodeList getUnrecognized() {
+		return unrecognizedList;
+	}
+
+	protected ArrayList folderList = null;
+
+	public ArrayList getNodeLists() {
+		if (folderList == null) {
+			folderList = new ArrayList();
+			folderList.add(notationList);
+			folderList.add(entityList);
+			folderList.add(elementList);
+			folderList.add(attlistList);
+			folderList.add(commentList);
+			folderList.add(unrecognizedList);
+		}
+		return folderList;
+	}
+
+	public DTDModelImpl getDTDModel() {
+		return dtdModel;
+	}
+
+
+
+	public int getInsertOffset(DTDNode node, boolean isAfter) {
+		int offset = 0;
+		if (node != null) {
+			if (isAfter) {
+				// then get the next node and use it's start offset
+				int index = getNodes().indexOf(getNode(node.getStructuredDocumentRegion()));
+
+				DTDNode afterNode = null;
+				if (index + 1 < getNodes().size()) {
+					afterNode = (DTDNode) getNodes().get(index + 1);
+				}
+				if (afterNode != null) {
+					offset = afterNode.getStructuredDocumentRegion().getStartOffset();
+				}
+				else {
+					// add to end
+					if (getStructuredDocument().getLastStructuredDocumentRegion() != null) {
+						offset = getStructuredDocument().getLastStructuredDocumentRegion().getEndOffset();
+					}
+				}
+			}
+			else {
+				offset = node.getStructuredDocumentRegion().getStartOffset();
+			}
+		}
+		else {
+			// add to end
+			if (getStructuredDocument().getLastStructuredDocumentRegion() != null) {
+				offset = getStructuredDocument().getLastStructuredDocumentRegion().getEndOffset();
+			}
+		}
+		return offset;
+	}
+
+	public void createElement(DTDNode node, String name, boolean isAfter) {
+		getDTDModel().beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_DTD_FILE_ADD_ELEMENT")); //$NON-NLS-1$
+		DTDNode topLevelNode = null;
+		String newStream = "<!ELEMENT " + name + " EMPTY>\n"; //$NON-NLS-1$ //$NON-NLS-2$
+		int offset = getInsertOffset(node, isAfter);
+		getStructuredDocument().replaceText(this, offset, 0, newStream);
+		getDTDModel().endRecording(this);
+	}
+
+	public void createEntity(DTDNode node, String name, boolean isAfter) {
+		getDTDModel().beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_DTD_FILE_ADD_ENTITY")); //$NON-NLS-1$
+		DTDNode topLevelNode = null;
+		String newStream = "<!ENTITY " + name + " \"\">\n";  //$NON-NLS-1$//$NON-NLS-2$
+		int offset = getInsertOffset(node, isAfter);
+		getStructuredDocument().replaceText(this, offset, 0, newStream);
+		getDTDModel().endRecording(this);
+	}
+
+	public void createComment(DTDNode node, String name, boolean isAfter) {
+		getDTDModel().beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_DTD_FILE_ADD_COMMENT")); //$NON-NLS-1$
+		DTDNode topLevelNode = null;
+		String newStream = "<!-- " + name + " -->\n"; //$NON-NLS-1$ //$NON-NLS-2$
+		int offset = getInsertOffset(node, isAfter);
+		getStructuredDocument().replaceText(this, offset, 0, newStream);
+		getDTDModel().endRecording(this);
+	}
+
+	public void createParameterEntityReference(DTDNode node, String name, boolean isAfter) {
+		getDTDModel().beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_DTD_FILE_ADD_PARM_ENTITY_REF")); //$NON-NLS-1$
+		DTDNode topLevelNode = null;
+		String newStream = name + "\n"; //$NON-NLS-1$
+		int offset = getInsertOffset(node, isAfter);
+		getStructuredDocument().replaceText(this, offset, 0, newStream);
+		getDTDModel().endRecording(this);
+	}
+
+	public void createNotation(DTDNode node, String name, boolean isAfter) {
+		getDTDModel().beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_DTD_FILE_ADD_NOTATION")); //$NON-NLS-1$
+		DTDNode topLevelNode = null;
+		String newStream = "<!NOTATION " + name + " SYSTEM \"\">\n"; //$NON-NLS-1$ //$NON-NLS-2$
+		int offset = getInsertOffset(node, isAfter);
+		getStructuredDocument().replaceText(this, offset, 0, newStream);
+		getDTDModel().endRecording(this);
+	}
+
+	public void createAttributeList(DTDNode node, String name, boolean isAfter) {
+		getDTDModel().beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_DTD_FILE_ADD_ATTR_LIST")); //$NON-NLS-1$
+		DTDNode topLevelNode = null;
+		String newStream = "<!ATTLIST " + name + ">\n"; //$NON-NLS-1$ //$NON-NLS-2$
+		int offset = getInsertOffset(node, isAfter);
+		getStructuredDocument().replaceText(this, offset, 0, newStream);
+		getDTDModel().endRecording(this);
+	}
+
+	public void insertIntoModel(Object requestor, DTDNode reference, DTDNode node, boolean isAfter) {
+		String nodeText = ""; //$NON-NLS-1$
+		if (node instanceof TopLevelNode) {
+			nodeText = ((TopLevelNode) node).getFullText();
+		}
+		else {
+			nodeText = node.getNodeText();
+		}
+		int offset = getInsertOffset(reference, isAfter);
+		getStructuredDocument().replaceText(requestor, offset, 0, nodeText);
+	}
+
+	private boolean isMovingNode = false;
+
+	public void moveNode(Object requestor, DTDNode referenceNode, DTDNode nodeToMove, boolean isAfter) {
+		isMovingNode = true;
+
+		deleteNode(requestor, nodeToMove);
+		insertIntoModel(requestor, referenceNode, nodeToMove, isAfter);
+		isMovingNode = false;
+	}
+
+	public void deleteNode(DTDNode node) {
+		getDTDModel().beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_DTD_FILE_DELETE")); //$NON-NLS-1$
+		deleteNode(this, node);
+		getDTDModel().endRecording(this);
+	}
+
+	public void deleteNode(Object requestor, DTDNode node) {
+		DTDNode parent = (DTDNode) node.getParentNode();
+		if (parent != null) {
+			parent.delete(requestor, node);
+		}
+		else {
+			if (!isMovingNode) {
+				DTDModelUpdater updater = new DTDModelUpdater();
+				updater.objectAboutToBeDeleted(requestor, node);
+				if (node instanceof ParameterEntityReference) {
+					Entity referencedEntity = ((ParameterEntityReference) node).getEntityObject();
+					if (referencedEntity != null) {
+						// remove references to all elements and parm entities contained in our current model
+						DTDExternalReferenceRemover remover = new DTDExternalReferenceRemover();
+						remover.externalReferenceAboutToChange(requestor, referencedEntity);
+					}
+				}
+				else if (node instanceof Notation) {
+					Notation notation = ((Notation) node);
+					DTDNotationReferenceRemover remover = new DTDNotationReferenceRemover();
+					remover.notationAboutToBeDeleted(requestor, notation);
+				}
+			}
+
+			// no parent?  then delete up until the start of the next node
+			// if it is a top level node
+			int startOffset = node.getStartOffset();
+			int endOffset = node.getWhitespaceEndOffset();
+			if (node instanceof TopLevelNode) {
+				endOffset = getInsertOffset(node, true);
+			}
+			getStructuredDocument().replaceText(requestor, startOffset, endOffset - startOffset, ""); //$NON-NLS-1$
+		}
+	}
+
+	protected ArrayList nodeList = new ArrayList();
+
+	protected void addNode(DTDNode node) {
+		addNode(nodeList.size(), node);
+	}
+
+	protected void addNode(int index, DTDNode node) {
+		nodeList.add(index, node);
+		/*
+		 if (index < nodeList.size()) 
+		 {
+		 insertBefore(node, (DTDNode) nodeList.get(index));
+		 }
+		 else 
+		 {
+		 appendChild(node);
+		 }*/
+	}
+
+	protected void removeNodes(List nodes) {
+		getNodes().removeAll(nodes);
+		/*    for (int i = 0; i < nodes.size(); i++) 
+		 {
+		 removeChild((DTDNode)nodes.get(i));
+		 } // end of for ()*/
+	}
+
+	public ArrayList getNodes() {
+		return nodeList;
+	}
+
+	public IStructuredDocument getStructuredDocument() {
+		return fStructuredDocument;
+	}
+
+	public IndexedRegion getNodeAt(int offset) {
+		DTDNode node = getTopLevelNodeAt(offset);
+		if (node != null) {
+			return node.getDeepestNode(offset);
+		}
+		return null;
+	}
+
+	public IndexedRegion getNodeAt(int startOffset, int endOffset) {
+		DTDNode node = getTopLevelNodeAt(startOffset);
+		if (node != null) {
+			return node.getDeepestNode(startOffset, endOffset);
+		}
+		return null;
+	}
+
+	public DTDNode getTopLevelNodeAt(int offset) {
+		for (int i = 0; i < nodeList.size(); i++) {
+			DTDNode node = (DTDNode) nodeList.get(i);
+			if (node.contains(offset)) {
+				return node;
+			}
+		}
+		return null;
+	}
+
+	public DTDNode getNode(IStructuredDocumentRegion flatNode) {
+		for (int i = 0; i < nodeList.size(); i++) {
+			DTDNode node = (DTDNode) nodeList.get(i);
+			if (node.getStructuredDocumentRegion() == flatNode) {
+				return node;
+			}
+		}
+		return null;
+	}
+
+	boolean creatingNewModel = false;
+
+	public void newModel(NewModelEvent event) {
+		creatingNewModel = true;
+		nodeList.clear();
+		NodesEvent removeEvent = new NodesEvent();
+		removeEvent.getNodes().addAll(nodeList);
+		notifyNodesRemoved(removeEvent);
+		/*    removeChildNodes();*/
+
+		if (fStructuredDocument.getRegionList() != null) {
+			buildNodes(fStructuredDocument.getRegionList());
+		}
+		creatingNewModel = false;
+	}
+
+	public void buildNodes(IStructuredDocumentRegionList list) {
+		NodesEvent addedDTDNodes = new NodesEvent();
+
+		Enumeration flatNodes = list.elements();
+		TopLevelNode previousNode = null;
+		while (flatNodes.hasMoreElements()) {
+			IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) flatNodes.nextElement();
+			TopLevelNode node = (TopLevelNode) buildNode(flatNode);
+			// if we don't create a node, then we assume that the flat
+			// node was whitespace.  Tack it on to a previous toplevel
+			// node
+			if (node != null) {
+				previousNode = node;
+				addedDTDNodes.add(node);
+			}
+			else {
+				if (previousNode != null) {
+					previousNode.addWhitespaceStructuredDocumentRegion(flatNode);
+				}
+			}
+
+		}
+		if (addedDTDNodes.getNodes().size() > 0)// &&
+		//        creatingNewModel == false) 
+		{
+			// now tell people about the additions
+			notifyNodesAdded(addedDTDNodes);
+		}
+	}
+
+	public void rebuildNodes(List nodes) {
+		// remove the old nodes
+		removeNodes(nodes);
+
+		// now rebuild them
+		NodesEvent addedDTDNodes = new NodesEvent();
+		Iterator dtdNodes = nodes.iterator();
+		while (dtdNodes.hasNext()) {
+			DTDNode dtdNode = (DTDNode) dtdNodes.next();
+			//      System.out.println("rebuilding " + dtdNode.getStructuredDocumentRegion().getText());
+
+			DTDNode node = buildNode(dtdNode.getStructuredDocumentRegion());
+			if (node != null) {
+				addedDTDNodes.add(node);
+			}
+		}
+		if (addedDTDNodes.getNodes().size() > 0) {
+			// now tell people about the additions
+			notifyNodesAdded(addedDTDNodes);
+		}
+	}
+
+	public DTDNode buildNode(IStructuredDocumentRegion flatNode) {
+		//    ITextRegionList regions = flatNode.getRegions();
+		DTDNode node = null;
+		if (isElement(flatNode)) {
+			// then this is an element
+			node = new Element(this, flatNode);
+		}
+		else if (isEntity(flatNode)) {
+			node = new Entity(this, flatNode);
+		}
+		else if (isNotation(flatNode)) {
+			node = new Notation(this, flatNode);
+		}
+		else if (isAttributeList(flatNode)) {
+			node = new AttributeList(this, flatNode);
+		}
+		else if (isComment(flatNode)) {
+			node = new Comment(this, flatNode);
+		}
+		else if (isParameterEntityReference(flatNode)) {
+			node = new ParameterEntityReference(this, flatNode);
+		}
+		else if (!flatNode.getText().trim().equals("")) { //$NON-NLS-1$
+			node = new Unrecognized(this, flatNode);
+		}
+		if (node != null) {
+			insertNode(node);
+			node.resolveRegions();
+		}
+		return node;
+	}
+
+	// it is assumed that flatnode contains at least 3 regions
+	public boolean isElement(IStructuredDocumentRegion flatNode) {
+		if (flatNode.getRegions().size() >= 3) {
+			ITextRegion second = flatNode.getRegions().get(1);
+			ITextRegion third = flatNode.getRegions().get(2);
+			if (second.getType().equals(DTDRegionTypes.EXCLAMATION) && third.getType().equals(DTDRegionTypes.ELEMENT_TAG)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	// it is assumed that flatnode contains at least 3 regions
+	public boolean isEntity(IStructuredDocumentRegion flatNode) {
+		if (flatNode.getRegions().size() >= 3) {
+			ITextRegion second = flatNode.getRegions().get(1);
+			ITextRegion third = flatNode.getRegions().get(2);
+			if (second.getType().equals(DTDRegionTypes.EXCLAMATION) && third.getType().equals(DTDRegionTypes.ENTITY_TAG)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	// it is assumed that flatnode contains at least 3 regions
+	public boolean isNotation(IStructuredDocumentRegion flatNode) {
+		if (flatNode.getRegions().size() >= 3) {
+			ITextRegion second = flatNode.getRegions().get(1);
+			ITextRegion third = flatNode.getRegions().get(2);
+			if (second.getType().equals(DTDRegionTypes.EXCLAMATION) && third.getType().equals(DTDRegionTypes.NOTATION_TAG)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	// it is assumed that flatnode contains at least 3 regions
+	public boolean isAttributeList(IStructuredDocumentRegion flatNode) {
+		if (flatNode.getRegions().size() >= 3) {
+			ITextRegion second = flatNode.getRegions().get(1);
+			ITextRegion third = flatNode.getRegions().get(2);
+			if (second.getType().equals(DTDRegionTypes.EXCLAMATION) && third.getType().equals(DTDRegionTypes.ATTLIST_TAG)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	// it is assumed that flatnode contains at least 3 regions
+	public boolean isComment(IStructuredDocumentRegion flatNode) {
+		if (flatNode.getRegions().size() >= 2) {
+			ITextRegion region = flatNode.getRegions().get(1);
+			if (region.getType().equals(DTDRegionTypes.COMMENT_START)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	// it is assumed that flatnode contains at least 3 regions
+	public boolean isParameterEntityReference(IStructuredDocumentRegion flatNode) {
+		if (flatNode.getRegions().size() == 1) {
+			ITextRegion region = flatNode.getRegions().get(0);
+			if (region.getType().equals(DTDRegionTypes.ENTITY_PARM)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	public boolean isUnrecognized(IStructuredDocumentRegion flatNode) {
+		return !isElement(flatNode) && !isEntity(flatNode) && !isNotation(flatNode) && !isParameterEntityReference(flatNode) && !isAttributeList(flatNode) && !isComment(flatNode);
+	}
+
+
+	public void insertNode(DTDNode node) {
+		int startOffset = node.getStartOffset();
+		int insertIndex = -1;
+		//    System.out.println("startoffset = " + startOffset);
+		for (int i = 0; i < getNodes().size(); i++) {
+			DTDNode currentNode = (DTDNode) getNodes().get(i);
+			//      System.out.println("currentNode endOffset = " +currentNode.getEndOffset());
+
+			if (currentNode.getEndOffset() > startOffset) {
+				//        System.out.println("endoffset " + currentNode.getEndOffset() + " > " + startOffset);
+				insertIndex = i;
+				break;
+			}
+		}
+		if (insertIndex == -1) {
+			insertIndex = getNodes().size();
+		}
+
+
+		//    System.out.println("insert index = " + insertIndex);
+
+		addNode(insertIndex, node);
+	}
+
+	public void nodesReplaced(StructuredDocumentRegionsReplacedEvent event) {
+		IStructuredDocumentRegionList oldNodes = event.getOldStructuredDocumentRegions();
+		NodesEvent removedDTDNodes = new NodesEvent();
+		for (int i = 0; i < oldNodes.getLength(); i++) {
+			IStructuredDocumentRegion flatNode = oldNodes.item(i);
+
+			for (Iterator iter = getNodes().iterator(); iter.hasNext();) {
+				DTDNode node = (DTDNode) iter.next();
+				if (node.getStructuredDocumentRegion() == flatNode) {
+					removedDTDNodes.add(node);
+				}
+			}
+		}
+
+		buildNodes(event.getNewStructuredDocumentRegions());
+
+		if (removedDTDNodes.getNodes().size() > 0) {
+			notifyNodesRemoved(removedDTDNodes);
+			removeNodes(removedDTDNodes.getNodes());
+		}
+	}
+
+	public void regionsReplaced(RegionsReplacedEvent event) {
+		List nodesToRebuild = new ArrayList();
+		IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
+		DTDNode affectedNode = getNode(flatNode);
+
+		if (!isSameTopLevelType(affectedNode)) {
+			nodesToRebuild.add(affectedNode);
+			rebuildNodes(nodesToRebuild);
+		}
+		else {
+			affectedNode.resolveRegions();
+			notifyNodeChanged(affectedNode);
+			// now try and determine which ones were added
+			NodesEvent addedDTDNodes = new NodesEvent();
+			ITextRegionList newRegions = event.getNewRegions();
+			int size = newRegions.size();
+			for (int i = 0; i < size; i++) {
+				ITextRegion region = newRegions.get(i);
+				DTDNode deepestNode = affectedNode.getDeepestNode(flatNode.getStartOffset(region), flatNode.getEndOffset(region));
+				if (!addedDTDNodes.getNodes().contains(deepestNode)) {
+					addedDTDNodes.add(deepestNode);
+				}
+			}
+			if (addedDTDNodes.getNodes().size() > 0) {
+				notifyNodesAdded(addedDTDNodes);
+			}
+		}
+	}
+
+	public void regionChanged(RegionChangedEvent event) {
+		ITextRegion changedRegion = event.getRegion();
+		IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
+		DTDNode affectedNode = (DTDNode) getNodeAt(flatNode.getStartOffset(changedRegion), flatNode.getEndOffset(changedRegion));
+		if (affectedNode != null) {
+			// no need to resolve regions as it is just a change
+			//      affectedNode.resolveRegions();
+			notifyNodeChanged(affectedNode);
+		}
+	}
+
+	boolean isSameTopLevelType(DTDNode affectedNode) {
+		IStructuredDocumentRegion flatNode = affectedNode.getStructuredDocumentRegion();
+		// return true if the flatnode still matches what the affectedNode
+		// is representing
+		if (affectedNode instanceof Element && isElement(flatNode)) {
+			return true;
+		}
+		if (affectedNode instanceof Entity && isEntity(flatNode)) {
+			return true;
+		}
+		if (affectedNode instanceof Comment && isComment(flatNode)) {
+			return true;
+		}
+		if (affectedNode instanceof AttributeList && isAttributeList(flatNode)) {
+			return true;
+		}
+		if (affectedNode instanceof Notation && isNotation(flatNode)) {
+			return true;
+		}
+		if (affectedNode instanceof Unrecognized && isUnrecognized(flatNode)) {
+			return true;
+		}
+		return false;
+	}
+
+	public Image getImage() {
+		return DTDPlugin.getInstance().getImage(DTDResource.DTDFILEICON);
+	}
+
+	public String getName() {
+		org.eclipse.core.runtime.Path path = new org.eclipse.core.runtime.Path(getDTDModel().getId().toString());
+		return path.lastSegment();
+	}
+
+	protected ArrayList modelListeners = new ArrayList();
+
+	public void addDTDFileListener(IDTDFileListener listener) {
+		modelListeners.add(listener);
+	}
+
+	public void removeDTDFileListener(IDTDFileListener listener) {
+		modelListeners.remove(listener);
+	}
+
+	public void notifyNodesAdded(NodesEvent addedNodes) {
+		Iterator iter = modelListeners.iterator();
+		while (iter.hasNext()) {
+			IDTDFileListener listener = (IDTDFileListener) iter.next();
+			listener.nodesAdded(addedNodes);
+		}
+	}
+
+	protected void notifyNodesRemoved(NodesEvent event) {
+		Iterator iter = modelListeners.iterator();
+		while (iter.hasNext()) {
+			IDTDFileListener listener = (IDTDFileListener) iter.next();
+			listener.nodesRemoved(event);
+		}
+	}
+
+	public void notifyNodeChanged(DTDNode node) {
+		Iterator iter = modelListeners.iterator();
+		while (iter.hasNext()) {
+			IDTDFileListener listener = (IDTDFileListener) iter.next();
+			listener.nodeChanged(node);
+		}
+	}
+
+	/**
+	 * Sets the flatModel.
+	 * @param flatModel The flatModel to set
+	 */
+	public void setStructuredDocument(IStructuredDocument flatModel) {
+		this.fStructuredDocument = flatModel;
+	}
+
+	// Implements IndexedRegion
+
+	public boolean contains(int testPosition) {
+		return getStartOffset() <= testPosition && testPosition <= getEndOffset();
+	}
+
+	public int getEndOffset() {
+		return getStructuredDocument().getFirstStructuredDocumentRegion().getEndOffset();
+	}
+
+	public int getStartOffset() {
+		return getStructuredDocument().getFirstStructuredDocumentRegion().getStartOffset();
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDNode.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDNode.java
new file mode 100644
index 0000000..acc6faf
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDNode.java
@@ -0,0 +1,326 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.document.DTDModelImpl;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.IFactoryRegistry;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.text.TextRegionListImpl;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.document.NodeContainer;
+
+
+public abstract class DTDNode extends NodeContainer implements IndexedRegion {
+
+	// these are characteroffsets
+	protected DTDFile dtdFile;
+
+	public DTDNode(DTDFile dtdFile, IStructuredDocumentRegion flatNode) {
+		this.dtdFile = dtdFile;
+		this.flatNode = flatNode;
+	}
+
+	// flat node that contains this node
+	protected IStructuredDocumentRegion flatNode;
+
+	/**
+	 * Get the value of flatNode.
+	 * @return value of flatNode.
+	 */
+	public IStructuredDocumentRegion getStructuredDocumentRegion() {
+		return flatNode;
+	}
+
+	/**
+	 */
+	public IFactoryRegistry getFactoryRegistry() {
+		DTDModelImpl model = dtdFile.getDTDModel();
+		if (model != null) {
+			IFactoryRegistry reg = model.getFactoryRegistry();
+			if (reg != null)
+				return reg;
+		}
+		return null;
+	}
+
+	/**
+	 * Set the value of flatNode.
+	 * @param v  Value to assign to flatNode.
+	 */
+	public void setStructuredDocumentRegion(IStructuredDocumentRegion v) {
+		this.flatNode = v;
+	}
+
+	public boolean contains(int testPosition) {
+		return containsRange(testPosition, testPosition);
+	}
+
+	public boolean containsRange(int start, int end) {
+		return getStartOffset() <= start && end <= getEndOffset();
+	}
+
+	public DTDNode getDeepestNode(int offset) {
+		if (contains(offset)) {
+			// now see if a child contains this offset
+			Object[] children = getChildren();
+			for (int i = 0; i < children.length; i++) {
+				DTDNode child = (DTDNode) children[i];
+				DTDNode deepest = child.getDeepestNode(offset);
+				if (deepest != null) {
+					return deepest;
+				}
+			} // end of for ()
+			return this;
+		}
+		return null;
+	}
+
+	public DTDNode getDeepestNode(int start, int end) {
+		if (containsRange(start, end)) {
+			// now see if a child contains this offset
+			Object[] children = getChildren();
+			for (int i = 0; i < children.length; i++) {
+				DTDNode child = (DTDNode) children[i];
+				DTDNode deepest = child.getDeepestNode(start, end);
+				if (deepest != null) {
+					return deepest;
+				}
+			} // end of for ()
+			return this;
+		}
+		return null;
+	}
+
+	public int getStartOffset() {
+		return getStructuredDocumentRegion().getStartOffset(getStartRegion());
+	}
+
+	public int getEndOffset() {
+		return getStructuredDocumentRegion().getEndOffset(getEndRegion());
+	}
+
+	public int getNodeLength() {
+		return getEndOffset() - getStartOffset();
+	}
+
+	public int getFullNodeLength() {
+		return getWhitespaceEndOffset() - getStartOffset();
+	}
+
+	public boolean hasTrailingWhitespace() {
+		return whitespace.size() > 0;
+	}
+
+	public String getNodeText() {
+		StringBuffer sb = new StringBuffer();
+
+		RegionIterator iter = iterator();
+		while (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			sb.append(getStructuredDocumentRegion().getText(region));
+		}
+		return sb.toString();
+	}
+
+	public String getFullNodeText() {
+		String text = getNodeText();
+		if (whitespace.size() > 0) {
+			RegionIterator iter = new RegionIterator(whitespace);
+			while (iter.hasNext()) {
+				ITextRegion region = iter.next();
+				text += getStructuredDocumentRegion().getText(region);
+			}
+		}
+		return text;
+	}
+
+	//  private Region startRegion,endRegion;
+	public ITextRegion getStartRegion() {
+		return regions.get(0);
+		//    return startRegion;
+	}
+
+	public ITextRegion getEndRegion() {
+		return regions.get(regions.size() - 1);//endRegion;
+	}
+
+	// return the first token containing the specified token type
+	public ITextRegion getNextRegion(RegionIterator iter, String type) {
+		while (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			if (region.getType().equals(type)) {
+				return region;
+			}
+		}
+		return null;
+	}
+
+	public RegionIterator iterator() {
+		//    System.out.println("create region iter " + this.getClass() + " with start , end = " + getStartOffset() + ", " +getEndOffset());
+		return new RegionIterator(regions);
+	}
+
+	public ITextRegion getNameRegion() {
+		RegionIterator iter = iterator();
+		while (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			if (region.getType() == DTDRegionTypes.NAME) {
+				return region;
+			}
+		}
+		return null;
+	}
+
+	public String getNodeName() {
+		return getName();
+	}
+
+	public short getNodeType() {
+		return -1;
+	}
+
+	public org.w3c.dom.Node cloneNode(boolean deepest) {
+		return null;
+	}
+
+	public boolean supports(java.lang.String feature, java.lang.String version) {
+		return false;
+	}
+
+	public String getName() {
+		ITextRegion region = getNameRegion();
+		if (region != null) {
+			return getStructuredDocumentRegion().getText(region);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	public void beginRecording(Object requestor, String label) {
+		getDTDFile().getDTDModel().beginRecording(requestor, label);
+	}
+
+	public void endRecording(Object requestor) {
+		getDTDFile().getDTDModel().endRecording(requestor);
+	}
+
+	public void replaceText(Object requestor, int start, int length, String newText) {
+		getDTDFile().getStructuredDocument().replaceText(requestor, start, length, newText);
+	}
+
+	public void setName(String name) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_DTD_NODE_NAME_CHG")); //$NON-NLS-1$
+		setName(this, name);
+		endRecording(this);
+	}
+
+	public void setName(Object requestor, String name) {
+		if (!getName().equals(name)) {
+			ITextRegion nameRegion = getNameRegion();
+			if (nameRegion != null) {
+				//        nameToken.updateText(name);
+				getDTDFile().getDTDModel().getReferenceUpdater().nameAboutToChange(requestor, this, name);
+				replaceText(requestor, getStructuredDocumentRegion().getStartOffset(nameRegion), nameRegion.getLength(), name);
+			}
+		}
+	}
+
+	// skips past next name token in the iterator
+	protected void skipPastName(RegionIterator iter) {
+		while (iter.hasNext()) {
+			ITextRegion currentRegion = iter.next();
+			if (currentRegion.getType() == DTDRegionTypes.NAME) {
+				break;
+			}
+		}
+	}
+
+	public Object[] getChildren() {
+		return getChildrenList().toArray();
+	}
+
+	public List getChildrenList() {
+		org.w3c.dom.Node child = getFirstChild();
+		if (child != null) {
+			List children = new ArrayList();
+			for (; child != null; child = child.getNextSibling()) {
+				children.add(child);
+			}
+			return children;
+		}
+		else {
+			return Collections.EMPTY_LIST;
+		}
+	}
+
+	abstract public Image getImage();
+
+	public void resolveRegions() {
+	}
+
+	protected TextRegionListImpl regions = new TextRegionListImpl();
+
+	public void addRegion(ITextRegion region) {
+		/*
+		 if (startRegion == null) 
+		 {
+		 startRegion = region;
+		 }
+		 endRegion = region;*/
+		regions.add(region);
+	}
+
+	protected TextRegionListImpl whitespace = new TextRegionListImpl();
+
+	public void addWhitespaceRegion(ITextRegion region) {
+		whitespace.add(region);
+	}
+
+	// return end offset including whitespace
+	// or just the end offset if there is no whitespace
+	public int getWhitespaceEndOffset() {
+		if (whitespace.size() > 0) {
+			ITextRegion region = whitespace.get(whitespace.size() - 1);
+			return getStructuredDocumentRegion().getEndOffset(region);
+		}
+
+		return getEndOffset();
+	}
+
+	public DTDFile getDTDFile() {
+		return dtdFile;
+	}
+
+	public org.w3c.dom.Node appendChild(org.w3c.dom.Node newChild) throws org.w3c.dom.DOMException {
+		//    System.out.println("appendchild called with " + newChild);
+		return super.appendChild(newChild);
+	}
+
+	public void delete(DTDNode child) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_DTD_NODE_DELETE")); //$NON-NLS-1$
+		delete(this, child);
+		endRecording(this);
+	}
+
+	public void delete(Object requestor, DTDNode child) {
+		replaceText(requestor, child.getStartOffset(), child.getFullNodeLength(), ""); //$NON-NLS-1$
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDPlugin.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDPlugin.java
new file mode 100644
index 0000000..e5f1ec2
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDPlugin.java
@@ -0,0 +1,107 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+import org.eclipse.core.runtime.IPluginDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+public class DTDPlugin extends AbstractUIPlugin {
+	private static DTDPlugin instance;
+	private ResourceBundle resourceBundle;
+
+	public DTDPlugin(IPluginDescriptor descriptor) {
+		super(descriptor);
+		instance = this;
+		try {
+			resourceBundle = descriptor.getResourceBundle();
+		}
+		catch (java.util.MissingResourceException exception) {
+			//B2BUtilPlugin.getPlugin().getMsgLogger().write(B2BUtilPlugin.getGUIString("_WARN_PLUGIN_PROPERTIES_MISSING") + descriptor.getLabel());
+			resourceBundle = null;
+		}
+	}
+
+	public void startup() {
+		instance = this;
+	}
+
+	public synchronized static DTDPlugin getInstance() {
+		return instance;
+	}
+
+	public static DTDPlugin getPlugin() {
+		return instance;
+	}
+
+	public static Image getDTDImage(String iconName) {
+		return getInstance().getImage(iconName);
+	}
+
+	public static ImageDescriptor getDTDImageDescriptor(String iconName) {
+		String thisID = getInstance().getBundle().getSymbolicName();
+		return AbstractUIPlugin.imageDescriptorFromPlugin(thisID, iconName);
+	}
+
+	public static String getDTDString(String key) {
+		// In case it is invoked from a command line
+		if (getInstance() == null) {
+			return ""; //$NON-NLS-1$
+		}
+
+		return getInstance().getString(key);
+	}
+
+	public Image getImage(String iconName) {
+		ImageRegistry imageRegistry = getImageRegistry();
+		Image image = imageRegistry.get(iconName);
+		
+		if (image == null) {
+			String thisID = getInstance().getBundle().getSymbolicName();
+			imageRegistry.put(iconName, imageDescriptorFromPlugin(thisID, iconName));
+			image = imageRegistry.get(iconName);
+		}
+		
+		return image;
+	}
+
+	/**
+	 * This gets the string resource.
+	 */
+	public String getString(String key) {
+		return getResourceBundle().getString(key);
+	}
+
+	/**
+	 * This gets the string resource and does one substitution.
+	 */
+	public String getString(String key, Object s1) {
+		return MessageFormat.format(getString(key), new Object[]{s1});
+	}
+
+	/**
+	 * This gets the string resource and does two substitutions.
+	 */
+	public String getString(String key, Object s1, Object s2) {
+		return MessageFormat.format(getString(key), new Object[]{s1, s2});
+	}
+
+	public ResourceBundle getResourceBundle() {
+		return resourceBundle;
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDResource.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDResource.java
new file mode 100644
index 0000000..2947cd3
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/DTDResource.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+
+public interface DTDResource {
+	//Enumeration Constants
+	public static final String ANYICON = "icons/full/obj16/any.gif"; //$NON-NLS-1$
+	public static final String ATTRIBUTEICON = "icons/full/obj16/attribute.gif"; //$NON-NLS-1$
+	public static final String ATTRIBUTELISTICON = "icons/full/obj16/attribute_list.gif"; //$NON-NLS-1$
+	public static final String COMMENTICON = "icons/full/obj16/comment.gif"; //$NON-NLS-1$
+	public static final String ELEMENTICON = "icons/full/obj16/element.gif"; //$NON-NLS-1$
+	public static final String ELEMENTREFICON = "icons/full/obj16/element_ref.gif"; //$NON-NLS-1$
+	public static final String EMPTYICON = "icons/full/obj16/emptycontent.gif"; //$NON-NLS-1$
+	public static final String ENTITYICON = "icons/full/obj16/entity.gif"; //$NON-NLS-1$
+	public static final String ENTITYREFERENCEICON = "icons/full/obj16/entity_reference.gif"; //$NON-NLS-1$
+	public static final String NOTATIONICON = "icons/full/obj16/notation.gif"; //$NON-NLS-1$
+	public static final String PCDATAICON = "icons/full/obj16/txtext.gif"; //$NON-NLS-1$
+	public static final String UNRECOGNIZEDICON = "icons/full/obj16/unrecognized_content.gif"; //$NON-NLS-1$
+
+	public static final String FLDR_EL = "icons/full/obj16/fldr_el.gif"; //$NON-NLS-1$
+	public static final String FLDR_ENT = "icons/full/obj16/fldr_ent.gif"; //$NON-NLS-1$
+	public static final String FLDR_NOT = "icons/full/obj16/fldr_not.gif"; //$NON-NLS-1$
+	public static final String FLDR_COMM = "icons/full/obj16/fldr_comm.gif"; //$NON-NLS-1$
+	public static final String FLDR_UNREC = "icons/full/obj16/fldr_unrec.gif"; //$NON-NLS-1$
+	
+	public static final String ONEICON = "icons/full/obj16/one.gif"; //$NON-NLS-1$
+	public static final String OPTIONALICON = "icons/full/obj16/optional.gif"; //$NON-NLS-1$
+	public static final String ONEORMOREICON = "icons/full/obj16/oneormore.gif"; //$NON-NLS-1$
+	public static final String ZEROORMOREICON = "icons/full/obj16/zeroormore.gif"; //$NON-NLS-1$
+
+	public static final String ONESEQUENCEICON = "icons/full/obj16/onesequence.gif"; //$NON-NLS-1$
+	public static final String OPTIONALSEQUENCEICON = "icons/full/obj16/optionalsequence.gif"; //$NON-NLS-1$
+	public static final String ONEORMORESEQUENCEICON = "icons/full/obj16/oneormoresequence.gif"; //$NON-NLS-1$
+	public static final String ZEROORMORESEQUENCEICON = "icons/full/obj16/zeroormoresequence.gif"; //$NON-NLS-1$
+
+	public static final String ONECHOICEICON = "icons/full/obj16/onechoice.gif"; //$NON-NLS-1$
+	public static final String OPTIONALCHOICEICON = "icons/full/obj16/optionalchoice.gif"; //$NON-NLS-1$
+	public static final String ONEORMORECHOICEICON = "icons/full/obj16/oneormorechoice.gif"; //$NON-NLS-1$
+	public static final String ZEROORMORECHOICEICON = "icons/full/obj16/zeroormorechoice.gif"; //$NON-NLS-1$
+
+	public static final String DTDFILEICON = "icons/full/obj16/DTDFile.gif"; //$NON-NLS-1$
+
+	public static final String NEWDTD = "icons/full/obj16/newdtd_wiz.gif"; //$NON-NLS-1$
+	public static final String NEWHTMLFORM = "icons/full/obj16/genhtmform_wiz.gif"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Element.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Element.java
new file mode 100644
index 0000000..e0693c3
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Element.java
@@ -0,0 +1,201 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.w3c.dom.Node;
+
+
+public class Element extends NamedTopLevelNode {
+
+	public Element(DTDFile dtdFile, IStructuredDocumentRegion flatNode) {
+		super(dtdFile, flatNode, DTDRegionTypes.ELEMENT_TAG);
+	}
+
+	public short getNodeType() {
+		return Node.ELEMENT_NODE;
+	}
+
+	public Node cloneNode(boolean deep) {
+		return new Element(dtdFile, flatNode);
+	}
+
+	protected CMNode contentModel;
+
+	public void setContentModel(CMNode contentModel) {
+		this.contentModel = contentModel;
+	}
+
+	public void addAttribute(String name) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_ELEMENT_ADD_ATTR")); //$NON-NLS-1$
+		List attLists = getAttributeLists();
+		if (attLists.size() == 0) {
+			getDTDFile().createAttributeList(this, getName(), true);
+			attLists = getAttributeLists();
+		}
+		if (attLists.size() > 0) {
+			AttributeList attList = (AttributeList) attLists.get(attLists.size() - 1);
+			attList.addAttribute(name);
+		}
+		endRecording(this);
+	}
+
+	List attListList = new ArrayList();
+
+	public List getAttributeLists() {
+		attListList.clear();
+		String elementName = getName();
+		Iterator iter = dtdFile.getNodes().iterator();
+		while (iter.hasNext()) {
+			DTDNode node = (DTDNode) iter.next();
+			if (node instanceof AttributeList && node.getName().equals(elementName)) {
+				attListList.add(node);
+			}
+		}
+		return attListList;
+	}
+
+	List attributes = new ArrayList();
+
+	public List getElementAttributes() {
+		attributes.clear();
+		Iterator attLists = getAttributeLists().iterator();
+		while (attLists.hasNext()) {
+			AttributeList attList = (AttributeList) attLists.next();
+
+			Object[] children = attList.getChildren();
+			for (int i = 0; i < children.length; i++) {
+				attributes.add(children[i]);
+			}
+		}
+		return attributes;
+	}
+
+
+
+	public CMNode getContentModel() {
+		//    Object[] children = getChildren()
+		return (CMNode) getFirstChild();//contentModel;
+	}
+
+	public Image getImage() {
+		return DTDPlugin.getInstance().getImage(DTDResource.ELEMENTICON);
+	}
+
+	public void resolveRegions() {
+		//    System.out.println("element node stream = " + tokenStream.getString());
+		contentModel = null;
+		removeChildNodes();
+		RegionIterator iter = iterator();
+
+		if (getNameRegion() != null) {
+			// we skip past the name token is our name
+			skipPastName(iter);
+		}
+
+		CMBasicNode basicNode = null;
+		while (iter.hasNext()) {
+			ITextRegion currentRegion = iter.next();
+
+			if (contentModel == null) {
+				if (currentRegion.getType().equals(DTDRegionTypes.NAME)) {
+					contentModel = basicNode = new CMBasicNode(getDTDFile(), getStructuredDocumentRegion());
+				}
+				else if (currentRegion.getType().equals(DTDRegionTypes.CONTENT_PCDATA)) {
+					contentModel = basicNode = new CMBasicNode(getDTDFile(), getStructuredDocumentRegion());
+				}
+				else if (currentRegion.getType().equals(DTDRegionTypes.LEFT_PAREN)) {
+					contentModel = new CMGroupNode(getDTDFile(), getStructuredDocumentRegion());
+				}
+			}
+
+			if (contentModel != null) {
+				if (!currentRegion.getType().equals(DTDRegionTypes.END_TAG)) {
+					// content model gets all regions except for the '>'
+					contentModel.addRegion(currentRegion);
+				}
+				else {
+					// if it is equal to the end tag, then don't add anymore regions
+					// for the content model
+					break;
+				}
+
+			}
+
+		}
+		if (contentModel != null) {
+			appendChild(contentModel);
+			// this is the root element content so set it true
+			contentModel.setRootElementContent(true);
+			// now tell the content model to resolve it's regions
+			contentModel.resolveRegions();
+
+		}
+	}
+
+	protected void addContent(Object requestor, String content) {
+		ITextRegion whitespace = getWhitespaceAfterName();
+		int startOffset = 0;
+		int length = 0;
+		if (whitespace != null) {
+			startOffset = getStructuredDocumentRegion().getStartOffset(whitespace);
+			length = whitespace.getLength() >= 2 ? 1 : 0;
+		}
+		else {
+			ITextRegion nameRegion = getNameRegion();
+			if (nameRegion != null) {
+				startOffset = getStructuredDocumentRegion().getEndOffset(nameRegion);
+			}
+			else {
+				ITextRegion elementTag = getNextRegion(iterator(), DTDRegionTypes.ELEMENT_TAG);
+				startOffset = getStructuredDocumentRegion().getEndOffset(elementTag);
+			}
+		}
+		replaceText(requestor, startOffset, length, content);
+	}
+
+	public void addGroup() {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_ELEMENT_ADD_GRP")); //$NON-NLS-1$
+		addContent(this, " ()"); //$NON-NLS-1$
+		endRecording(this);
+	}
+
+	public void addChild() {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_ELEMENT_ADD_CHILD")); //$NON-NLS-1$
+		addContent(this, " EMPTY"); //$NON-NLS-1$
+		endRecording(this);
+	}
+
+	public void replaceContentModel(Object requestor, CMNode node) {
+		int offset = 0;
+		int length = 0;
+		String nodeText = node.getNodeText();
+		CMNode contentModel = getContentModel();
+		if (contentModel != null) {
+			offset = contentModel.getStartOffset();
+			length = contentModel.getWhitespaceEndOffset() - offset;
+			replaceText(requestor, offset, length, nodeText);
+		}
+		else {
+			addContent(requestor, nodeText);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Entity.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Entity.java
new file mode 100644
index 0000000..40b9c08
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Entity.java
@@ -0,0 +1,316 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+// external node contains code to help set and get public ids
+public class Entity extends ExternalNode {
+
+	public Entity(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode, DTDRegionTypes.ENTITY_TAG);
+	}
+
+	public ITextRegion getPercentRegion() {
+		return getNextRegion(iterator(), DTDRegionTypes.PERCENT);
+	}
+
+	/**
+	 * Get the value of isParameterEntity.
+	 * @return value of isParameterEntity.
+	 */
+	public boolean isParameterEntity() {
+		return getPercentRegion() != null;
+	}
+
+	private static String setParameterEntity = DTDPlugin.getDTDString("_UI_LABEL_ENTITY_SET_PARM_ENTITY"); //$NON-NLS-1$
+	private static String setGeneralEntity = DTDPlugin.getDTDString("_UI_LABEL_ENTITY_SET_GENERAL_ENTITY"); //$NON-NLS-1$
+
+	/**
+	 * Set the value of isParameterEntity.
+	 * @param v  Value to assign to isParameterEntity.
+	 */
+	public void setParameterEntity(boolean v) {
+		if (isParameterEntity() != v) {
+			beginRecording(this, v ? setParameterEntity : setGeneralEntity);
+			if (v) {
+				RegionIterator iter = iterator();
+				ITextRegion startTag = getNextRegion(iter, DTDRegionTypes.ENTITY_TAG);
+				int startOffset = 0, length = 0;
+
+				if (iter.hasNext()) {
+					ITextRegion region = iter.next();
+					startOffset = getStructuredDocumentRegion().getStartOffset(region);
+					if (region.getType() == DTDRegionTypes.WHITESPACE && region.getLength() > 1) {
+						length = 1;
+					}
+				}
+				else {
+					startOffset = getStructuredDocumentRegion().getEndOffset(startTag);
+				}
+				replaceText(this, startOffset, length, " %"); //$NON-NLS-1$
+				// now get rid of any NData since it is only allowed if the 
+				// entity is a general entity and not a parameter entity
+				removeNData(this);
+			}
+			else {
+				// get rid of percent region
+				ITextRegion percentRegion = getPercentRegion();
+				replaceText(this, getStructuredDocumentRegion().getStartOffset(percentRegion), percentRegion.getLength(), ""); //$NON-NLS-1$
+			}
+
+			endRecording(this);
+		}
+	}
+
+	private void removeNData(Object requestor) {
+		ITextRegion ndataRegion = null;
+
+		// see if we have an NDATA keyword
+		ndataRegion = getNextRegion(iterator(), DTDRegionTypes.NDATA_KEYWORD);
+		int startOffset = 0, endOffset = 0;
+		if (ndataRegion != null) {
+			startOffset = getStructuredDocumentRegion().getStartOffset(ndataRegion);
+			endOffset = getStructuredDocumentRegion().getEndOffset(ndataRegion);
+		}
+		ITextRegion value = getNextRegion(iterator(), DTDRegionTypes.NDATA_VALUE);
+		if (value != null) {
+			if (startOffset == 0) {
+				startOffset = getStructuredDocumentRegion().getStartOffset(value);
+			}
+			endOffset = getStructuredDocumentRegion().getEndOffset(value);
+		}
+		replaceText(requestor, startOffset, endOffset - startOffset, ""); //$NON-NLS-1$
+	}
+
+	/**
+	 * Get the value of externalEntity.
+	 * @return value of externalEntity.
+	 */
+	public boolean isExternalEntity() {
+		return getPublicKeywordRegion(iterator()) != null || getSystemKeywordRegion(iterator()) != null;
+	}
+
+	private static String setExternalEntity = DTDPlugin.getDTDString("_UI_LABEL_ENTITY_SET_EXT_ENTITY"); //$NON-NLS-1$
+	private static String setInternalEntity = DTDPlugin.getDTDString("_UI_LABEL_ENTITY_SET_INT_ENTITY"); //$NON-NLS-1$
+
+	/**
+	 * Set the value of externalEntity.
+	 * @param v  Value to assign to externalEntity.
+	 */
+	public void setExternalEntity(boolean isExternalEntity) {
+		if (isExternalEntity() != isExternalEntity) {
+			//      externalEntity = v;
+			beginRecording(this, isExternalEntity ? setExternalEntity : setInternalEntity);
+			if (isExternalEntity) {
+				// we need to get rid of the value literal
+				ITextRegion quote = getNextRegion(iterator(), DTDRegionTypes.SINGLEQUOTED_LITERAL);
+				if (quote == null) {
+					quote = getNextRegion(iterator(), DTDRegionTypes.DOUBLEQUOTED_LITERAL);
+				}
+				if (quote != null) {
+					replaceText(this, getStructuredDocumentRegion().getStartOffset(quote), quote.getLength(), ""); //$NON-NLS-1$
+				}
+				setSystemID(""); //$NON-NLS-1$
+			}
+			else {
+				// we need to get rid of text between end of name region and the last double quoted literal
+				RegionIterator iter = iterator();
+				ITextRegion keyword = getSystemKeywordRegion(iter);
+				int startOffset = 0;
+				int length = 0;
+				if (keyword == null) {
+					// reset the iterator
+					iter = iterator();
+					keyword = getPublicKeywordRegion(iter);
+				}
+				if (keyword != null) {
+					startOffset = getStructuredDocumentRegion().getStartOffset(keyword);
+					// start with a length just equal to the keyword for now
+					length = keyword.getLength();
+				}
+				else {
+					// reset the iterator since we didn't find the keyword
+					iter = iterator();
+					// just go from after the name
+					startOffset = getStructuredDocumentRegion().getEndOffset(getNameRegion());
+				}
+
+				// now that we have the start, look for the end
+				ITextRegion lastRegion = null;
+
+				if (lastRegion == null) {
+					// then look for last quoted literal
+					while (iter.hasNext()) {
+						ITextRegion literal = getNextQuotedLiteral(iter);
+						if (literal != null) {
+							lastRegion = literal;
+						}
+					}
+				}
+
+				if (lastRegion != null) {
+					length = getStructuredDocumentRegion().getEndOffset(lastRegion) - startOffset;
+				}
+				replaceText(this, startOffset, length, "\"\""); //$NON-NLS-1$
+				removeNData(this);
+			}
+			endRecording(this);
+		}
+	}
+
+
+	/**
+	 * Get the value of notationName.
+	 * @return value of notationName.
+	 */
+	public String getNotationName() {
+		ITextRegion ndataRegion = getNextRegion(iterator(), DTDRegionTypes.NDATA_VALUE);
+		if (ndataRegion != null) {
+			return getStructuredDocumentRegion().getText(ndataRegion);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	/**
+	 * Set the value of notationName.
+	 * @param newNotation  Value to assign to notationName.
+	 */
+	public void setNotationName(String newNotation) {
+		beginRecording(this, "NDATA " + DTDPlugin.getDTDString("_UI_LABEL_ENTITY_NDATA_CHANGE")); //$NON-NLS-1$ //$NON-NLS-2$
+		setNotationName(this, newNotation);
+		endRecording(this);
+	}
+
+	public void setNotationName(Object requestor, String newNotation) {
+		if (!getNotationName().equals(newNotation)) {
+			if (!newNotation.equals("")) { //$NON-NLS-1$
+				// 
+				ITextRegion ndataRegion = getNextRegion(iterator(), DTDRegionTypes.NDATA_VALUE);
+				if (ndataRegion != null) {
+					replaceText(requestor, getStructuredDocumentRegion().getStartOffset(ndataRegion), ndataRegion.getLength(), newNotation);
+				}
+				else {
+					// time to create one
+					int startOffset = 0;
+					String string = ""; //$NON-NLS-1$
+					RegionIterator iter = iterator();
+					ITextRegion ndataKeyword = getNextRegion(iter, DTDRegionTypes.NDATA_KEYWORD);
+					if (ndataKeyword == null) {
+						// we'll need to create one after the last quoted literal
+						// Reset iterator
+						string += " NDATA "; //$NON-NLS-1$
+						iter = iterator();
+						ITextRegion lastQuotedLiteral = null;
+						while (iter.hasNext()) {
+							ITextRegion literal = getNextQuotedLiteral(iter);
+							if (literal != null) {
+								lastQuotedLiteral = literal;
+							}
+						}
+						if (lastQuotedLiteral != null) {
+							startOffset = getStructuredDocumentRegion().getEndOffset(lastQuotedLiteral);
+						}
+						else {
+							// created after the system or public keyword
+							ITextRegion keyword = getPublicKeywordRegion(iterator());
+							if (keyword == null) {
+								keyword = getSystemKeywordRegion(iterator());
+							}
+							// we shouldn't be null here since we check if we were external already
+							startOffset = getStructuredDocumentRegion().getEndOffset(keyword);
+						}
+
+					}
+					else {
+						startOffset = getStructuredDocumentRegion().getEndOffset(ndataKeyword);
+					}
+					replaceText(requestor, startOffset, 0, string + newNotation);
+				}
+			}
+			else {
+				// need to remove the ndata stuff
+				removeNData(requestor);
+			}
+		}
+	}
+
+	/**
+	 * Get the value of value.
+	 * @return value of value.
+	 */
+	public String getValue() {
+		if (!isExternalEntity()) {
+			ITextRegion valueRegion = getNextQuotedLiteral(iterator());
+			if (valueRegion != null) {
+				return getValueFromQuotedRegion(valueRegion);
+			}
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	/**
+	 * Set the value of value.
+	 * @param v  Value to assign to value.
+	 */
+	public void setValue(String v) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_ENTITY_VALUE_CHG")); //$NON-NLS-1$
+		setValue(this, v);
+		endRecording(this);
+	}
+
+	/**
+	 * Set the value of value.
+	 * @param v  Value to assign to value.
+	 */
+	public void setValue(Object requestor, String v) {
+		if (!isExternalEntity()) {
+			if (!getValue().equals(v)) {
+				// then it makes sense to change the value
+				ITextRegion valueRegion = getNextQuotedLiteral(iterator());
+				String quoteChar = v.indexOf("\"") == -1 ? "\"" : "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				if (valueRegion != null) {
+					replaceText(requestor, getStructuredDocumentRegion().getStartOffset(valueRegion), valueRegion.getLength(), quoteChar + v + quoteChar);
+				}
+				else {
+					int startOffset = 0, length = 0;
+					RegionIterator iter = iterator();
+					ITextRegion region = getNextRegion(iter, DTDRegionTypes.NAME);
+					if (region == null) {
+						// create it after the percent if there is one
+						region = getPercentRegion();
+					}
+					if (region == null) {
+						// if still null, then create it after the element tag
+						region = getStartTag(iterator());
+					}
+
+					if (region != null) {
+						startOffset = getStructuredDocumentRegion().getEndOffset(region);
+						replaceText(requestor, startOffset, 0, quoteChar + v + quoteChar);
+					}
+				}
+			}
+		}
+	}
+
+	public Image getImage() {
+		return DTDPlugin.getInstance().getImage(DTDResource.ENTITYICON);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/ExternalNode.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/ExternalNode.java
new file mode 100644
index 0000000..ae0b462
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/ExternalNode.java
@@ -0,0 +1,239 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+// base class for nodes that can contain external content
+public abstract class ExternalNode extends NamedTopLevelNode {
+
+	public ExternalNode(DTDFile file, IStructuredDocumentRegion flatNode, String tagType) {
+		super(file, flatNode, tagType);
+	}
+
+	String publicID;
+
+	public ITextRegion getPublicKeywordRegion(RegionIterator iter) {
+		return getNextRegion(iter, DTDRegionTypes.PUBLIC_KEYWORD);
+	}
+
+	public ITextRegion getSystemKeywordRegion(RegionIterator iter) {
+		return getNextRegion(iter, DTDRegionTypes.SYSTEM_KEYWORD);
+	}
+
+	public ITextRegion getNextQuotedLiteral(RegionIterator iter) {
+		while (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			if (region.getType().equals(DTDRegionTypes.SINGLEQUOTED_LITERAL) || region.getType().equals(DTDRegionTypes.DOUBLEQUOTED_LITERAL)) {
+				return region;
+			}
+		}
+		return null;
+	}
+
+	public ITextRegion getPublicValueRegion() {
+		RegionIterator iter = iterator();
+
+		ITextRegion publicKeyword = getPublicKeywordRegion(iter);
+
+		if (publicKeyword != null && iter.hasNext()) {
+			ITextRegion quotedLiteral = getNextQuotedLiteral(iter);
+			if (quotedLiteral != null) {
+				return quotedLiteral;
+			}
+		}
+		return null;
+	}
+
+	public ITextRegion getSystemValueRegion() {
+		RegionIterator iter = iterator();
+
+		ITextRegion systemKeyword = getSystemKeywordRegion(iter);
+		if (systemKeyword != null && iter.hasNext()) {
+			ITextRegion quotedLiteral = getNextQuotedLiteral(iter);
+			if (quotedLiteral != null) {
+				return quotedLiteral;
+			}
+		}
+		else {
+			// try and see if there is a second quoted literal after a public keyword
+			iter = iterator();
+			ITextRegion publicKeyword = getPublicKeywordRegion(iter);
+
+			if (publicKeyword != null && iter.hasNext()) {
+				ITextRegion quotedLiteral = getNextQuotedLiteral(iter);
+				if (quotedLiteral != null && iter.hasNext()) {
+					// now get the second quoted literal
+					quotedLiteral = getNextQuotedLiteral(iter);
+					if (quotedLiteral != null) {
+						// got it!
+						return quotedLiteral;
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Get the value of publicID.
+	 * @return value of publicID.
+	 */
+	public String getPublicID() {
+		ITextRegion publicValue = getPublicValueRegion();
+		if (publicValue != null) {
+			return getValueFromQuotedRegion(publicValue);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	public String getValueFromQuotedRegion(ITextRegion region) {
+		String type = region.getType();
+		if (type.equals(DTDRegionTypes.SINGLEQUOTED_LITERAL) || type.equals(DTDRegionTypes.DOUBLEQUOTED_LITERAL)) {
+			String text = getStructuredDocumentRegion().getText(region);
+			return text.substring(1, text.length() - 1);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+
+	/**
+	 * Set the value of publicID.
+	 * @param v  Value to assign to publicID.
+	 */
+	public void setPublicID(String v) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_EXT_NODE_PUBLIC_ID_CHG")); //$NON-NLS-1$
+		setPublicID(this, v);
+		endRecording(this);
+	}
+
+	/**
+	 * Set the value of publicID.
+	 * @param v  Value to assign to publicID.
+	 */
+	public void setPublicID(Object requestor, String v) {
+		if (!v.equals(publicID)) {
+			publicID = v;
+			ITextRegion publicValue = getPublicValueRegion();
+			ITextRegion publicKeyword = getPublicKeywordRegion(iterator());
+			ITextRegion systemKeyword = getSystemKeywordRegion(iterator());
+			ITextRegion systemValue = getSystemValueRegion();
+
+			if (v.equals("")) { //$NON-NLS-1$
+				if (publicKeyword != null) {
+					// time to get rid of the public keyword and value
+					// and replace it with the system one
+					int startOffset = getStructuredDocumentRegion().getStartOffset(publicKeyword);
+					String newString = "SYSTEM"; //$NON-NLS-1$
+					if (systemValue == null) {
+						newString += " \"\""; //$NON-NLS-1$
+					}
+					replaceText(requestor, startOffset, getStructuredDocumentRegion().getEndOffset(publicValue) - startOffset, newString);
+				}
+			}
+			else {
+				// here were setting a non empty value
+				String quoteChar = v.indexOf("\"") == -1 ? "\"" : "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				if (publicValue != null) {
+					replaceText(requestor, getStructuredDocumentRegion().getStartOffset(publicValue), publicValue.getLength(), quoteChar + publicID + quoteChar);
+				}
+				else {
+					// time to create stuff
+					if (publicKeyword != null) {
+						// then just put our new value after the keyword
+						replaceText(requestor, getStructuredDocumentRegion().getEndOffset(publicKeyword), 0, " " + quoteChar + v + quoteChar); //$NON-NLS-1$
+					}
+					else {
+						// we need the public keyword as well
+						if (systemKeyword != null) {
+							replaceText(requestor, getStructuredDocumentRegion().getStartOffset(systemKeyword), systemKeyword.getLength(), "PUBLIC " + quoteChar + v + quoteChar); //$NON-NLS-1$
+						}
+						else {
+							ITextRegion nameRegion = getNameRegion();
+							replaceText(requestor, getStructuredDocumentRegion().getEndOffset(nameRegion), 0, " PUBLIC " + quoteChar + v + quoteChar); //$NON-NLS-1$
+						}
+					}
+				}
+			}
+		}
+	}
+
+	String systemID;
+
+	/**
+	 * Get the value of systemID.
+	 * @return value of systemID.
+	 */
+	public String getSystemID() {
+		ITextRegion systemValue = getSystemValueRegion();
+		if (systemValue != null) {
+			return getValueFromQuotedRegion(systemValue);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+
+	/**
+	 * Set the value of systemID.
+	 * @param v  Value to assign to systemID.
+	 */
+	public void setSystemID(String v) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_EXT_NODE_SYSTEM_ID_CHG")); //$NON-NLS-1$
+		setSystemID(this, v);
+		endRecording(this);
+	}
+
+	/**
+	 * Set the value of systemID.
+	 * @param v  Value to assign to systemID.
+	 */
+	public void setSystemID(Object requestor, String v) {
+		if (!v.equals(systemID) || (getPublicKeywordRegion(iterator()) == null && getSystemKeywordRegion(iterator()) == null)) {
+			systemID = v;
+			String quoteChar = v.indexOf("\"") == -1 ? "\"" : "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			ITextRegion systemValue = getSystemValueRegion();
+			if (systemValue != null) {
+				replaceText(requestor, getStructuredDocumentRegion().getStartOffset(systemValue), systemValue.getLength(), quoteChar + systemID + quoteChar);
+			}
+			else {
+				ITextRegion systemKeyword = getSystemKeywordRegion(iterator());
+
+				// time to create stuff
+				if (systemKeyword != null) {
+					// then just put our new value after the keyword
+					replaceText(requestor, getStructuredDocumentRegion().getEndOffset(systemKeyword), 0, " " + quoteChar + v + quoteChar); //$NON-NLS-1$
+				}
+				else {
+					// see if we have a public keyword
+					ITextRegion publicKeyword = getPublicKeywordRegion(iterator());
+					if (publicKeyword == null) {
+						ITextRegion nameRegion = getNameRegion();
+
+						replaceText(requestor, getStructuredDocumentRegion().getEndOffset(nameRegion), 0, " SYSTEM " + quoteChar + v + quoteChar); //$NON-NLS-1$
+					}
+					else {
+						// put it after the public value region
+						ITextRegion publicValueRegion = getPublicValueRegion();
+						replaceText(requestor, getStructuredDocumentRegion().getEndOffset(publicValueRegion), 0, " " + quoteChar + v + quoteChar); //$NON-NLS-1$
+					}
+
+				}
+			}
+
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Logger.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Logger.java
new file mode 100644
index 0000000..b693fdd
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Logger.java
@@ -0,0 +1,123 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if desired,
+ * the console. This class should only be used by classes in this plugin. Other
+ * plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+	private static Plugin fPlugin = DTDPlugin.getInstance();
+	private static final String fPluginId = fPlugin.getDescriptor().getUniqueIdentifier();
+
+	private static final String TRACEFILTER_LOCATION = "/debug/tracefilter"; //$NON-NLS-1$
+
+	public static final int OK = IStatus.OK; // 0
+	public static final int INFO = IStatus.INFO; // 1
+	public static final int WARNING = IStatus.WARNING; // 2
+	public static final int ERROR = IStatus.ERROR; // 4
+
+	public static final int OK_DEBUG = 200 + OK;
+	public static final int INFO_DEBUG = 200 + INFO;
+	public static final int WARNING_DEBUG = 200 + WARNING;
+	public static final int ERROR_DEBUG = 200 + ERROR;
+
+	/**
+	 * Adds message to log.
+	 * @param level severity level of the message (OK, INFO, WARNING, ERROR, OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG)
+	 * @param message text to add to the log
+	 * @param exception exception thrown
+	 */
+	protected static void _log(int level, String message, Throwable exception) {
+		if (level == OK_DEBUG || level == INFO_DEBUG || level == WARNING_DEBUG || level == ERROR_DEBUG) {
+			if (!fPlugin.isDebugging())
+				return;
+		}
+
+		int severity = IStatus.OK;
+		switch (level) {
+			case INFO_DEBUG :
+			case INFO :
+				severity = IStatus.INFO;
+				break;
+			case WARNING_DEBUG :
+			case WARNING :
+				severity = IStatus.WARNING;
+				break;
+			case ERROR_DEBUG :
+			case ERROR :
+				severity = IStatus.ERROR;
+		}
+		Status statusObj = new Status(severity, fPluginId, severity, message, exception);
+		fPlugin.getLog().log(statusObj);
+	}
+
+	/**
+	 * Prints message to log if category matches /debug/tracefilter option.
+	 * @param message text to print
+	 * @param category category of the message, to be compared with /debug/tracefilter
+	 */
+	protected static void _trace(String category, String message, Throwable exception) {
+		if (!fPlugin.isDebugging())
+			return;
+
+		String traceFilter = Platform.getDebugOption(fPluginId + TRACEFILTER_LOCATION);
+		if (traceFilter != null) {
+			StringTokenizer tokenizer = new StringTokenizer(traceFilter, ","); //$NON-NLS-1$
+			while (tokenizer.hasMoreTokens()) {
+				String cat = tokenizer.nextToken().trim();
+				if (category.equals(cat)) {
+					Status statusObj = new Status(IStatus.OK, fPluginId, IStatus.OK, message, exception);
+					fPlugin.getLog().log(statusObj);
+					return;
+				}
+			}
+		}
+	}
+
+	public static void log(int level, String message) {
+		_log(level, message, null);
+	}
+
+	public static void log(int level, String message, Throwable exception) {
+		_log(level, message, exception);
+	}
+
+	public static void logException(String message, Throwable exception) {
+		_log(ERROR, message, exception);
+	}
+
+	public static void logException(Throwable exception) {
+		_log(ERROR, exception.getMessage(), exception);
+	}
+
+	public static void traceException(String category, String message, Throwable exception) {
+		_trace(category, message, exception);
+	}
+
+	public static void traceException(String category, Throwable exception) {
+		_trace(category, exception.getMessage(), exception);
+	}
+
+	public static void trace(String category, String message) {
+		_trace(category, message, null);
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/NamedTopLevelNode.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/NamedTopLevelNode.java
new file mode 100644
index 0000000..11dacb2
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/NamedTopLevelNode.java
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+// interface for nodes that can exist at the top level in a dtdfile
+// eg. entity, notation, element, comment, attlist, or unrecognized stuff (ie <junk dkfjdl>
+public abstract class NamedTopLevelNode extends TopLevelNode {
+
+	public NamedTopLevelNode(DTDFile dtdFile, IStructuredDocumentRegion flatNode, String type) {
+		super(dtdFile, flatNode);
+		tagStartType = type;
+	}
+
+	private String tagStartType;
+
+	public ITextRegion getStartTag(RegionIterator iter) {
+		return getNextRegion(iter, tagStartType);
+	}
+
+	public ITextRegion getWhitespaceAfterName() {
+		ITextRegion nameRegion = getNameRegion();
+		RegionIterator iter = iterator();
+		// skip past the element tag region
+		ITextRegion elementTagRegion = getNextRegion(iter, tagStartType);
+		boolean foundName = false;
+		while (iter.hasNext()) {
+			ITextRegion region = iter.next();
+			if (!foundName && nameRegion != null && region == nameRegion) {
+				foundName = true;
+			}
+
+			if (region.getType().equals(DTDRegionTypes.WHITESPACE)) {
+				// there is no name region or we have already passed it
+				if (nameRegion == null || foundName) {
+					return region;
+				}
+			}
+		}
+		return null;
+	}
+
+	public void setName(Object requestor, String name) {
+		ITextRegion nameRegion = getNameRegion();
+		if (nameRegion != null) {
+			super.setName(requestor, name);
+		}
+		else {
+			RegionIterator iter = iterator();
+			ITextRegion elementTagRegion = getNextRegion(iter, tagStartType);
+			int replaceLength = 0;
+			if (iter.hasNext()) {
+				ITextRegion region = iter.next();
+				if (region.getType().equals(DTDRegionTypes.WHITESPACE)) {
+					if (region.getLength() >= 2) {
+						// there are 2 spaces between 'ELEMENT' and the content
+						// Change replace length to 1 so that the new name and
+						// the content are separated by a single space
+						replaceLength = 1;
+					}
+				}
+			}
+
+			//      beginRecording(requestor, "Name Change");
+			String newText = " " + name; //$NON-NLS-1$
+			replaceText(requestor, getStructuredDocumentRegion().getEndOffset(elementTagRegion), replaceLength, newText);
+			//      endRecording(requestor);
+		}
+	}
+
+	public ITextRegion getNameRegion() {
+		// name region is located after the whitespace (which is after
+		// the elementtag
+		RegionIterator iter = iterator();
+		ITextRegion startTag = getNextRegion(iter, tagStartType);
+
+		if (!iter.hasNext()) {
+			return null;
+		}
+
+		ITextRegion region = iter.next();
+		if (!region.getType().equals(DTDRegionTypes.WHITESPACE)) {
+			return null;
+		}
+
+		if (!iter.hasNext()) {
+			return null;
+		}
+
+		region = iter.next();
+		if (region.getType().equals(DTDRegionTypes.NAME)) {
+			return region;
+		}
+
+		// we normally stop here, but for entities, we have to see if we are at a '%'.  if so, we skip that and find the name after the whitespace again
+		if (tagStartType == DTDRegionTypes.ENTITY_TAG && region.getType().equals(DTDRegionTypes.PERCENT) && iter.hasNext()) {
+			region = iter.next();
+
+			if (!region.getType().equals(DTDRegionTypes.WHITESPACE)) {
+				return null;
+			}
+
+			if (!iter.hasNext()) {
+				return null;
+			}
+
+			region = iter.next();
+			if (region.getType().equals(DTDRegionTypes.NAME)) {
+				return region;
+			}
+		}
+
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/NodeList.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/NodeList.java
new file mode 100644
index 0000000..ed6715b
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/NodeList.java
@@ -0,0 +1,105 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+
+
+public class NodeList {
+
+	protected String listType;
+	protected DTDFile dtdFile;
+
+	public NodeList(DTDFile dtdFile, String tokenType) {
+		listType = tokenType;
+		this.dtdFile = dtdFile;
+	}
+
+	public String getListType() {
+		return listType;
+	}
+
+	public String getName() {
+		if (listType == DTDRegionTypes.ELEMENT_TAG) {
+			return DTDPlugin.getDTDString("_UI_LABEL_NODE_LIST_ELEMENTS"); //$NON-NLS-1$
+		}
+		else if (listType == DTDRegionTypes.ENTITY_TAG) {
+			return DTDPlugin.getDTDString("_UI_LABEL_NODE_LIST_ENTITIES"); //$NON-NLS-1$
+		}
+		else if (listType == DTDRegionTypes.NOTATION_TAG) {
+			return DTDPlugin.getDTDString("_UI_LABEL_NODE_LIST_NOTATIONS"); //$NON-NLS-1$
+		}
+		else if (listType == DTDRegionTypes.COMMENT_START) {
+			return DTDPlugin.getDTDString("_UI_LABEL_NODE_LIST_COMMENTS"); //$NON-NLS-1$
+		}
+		else if (listType == DTDRegionTypes.ATTLIST_TAG) {
+			return DTDPlugin.getDTDString("_UI_LABEL_NODE_LIST_ATTRIBUTES"); //$NON-NLS-1$
+		}
+		else if (listType == DTDRegionTypes.UNKNOWN_CONTENT) {
+			return DTDPlugin.getDTDString("_UI_LABEL_NODE_LIST_OTHER"); //$NON-NLS-1$
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	ArrayList listNodes = new ArrayList();
+
+	public ArrayList getNodes() {
+		listNodes.clear();
+		Iterator iter = dtdFile.getNodes().iterator();
+		while (iter.hasNext()) {
+			DTDNode node = (DTDNode) iter.next();
+			if (listType == DTDRegionTypes.ELEMENT_TAG && (node instanceof Element || node instanceof ParameterEntityReference)) {
+				listNodes.add(node);
+			}
+			else if (listType == DTDRegionTypes.ATTLIST_TAG && node instanceof AttributeList) {
+				listNodes.add(node);
+			}
+			else if (listType == DTDRegionTypes.ENTITY_TAG && node instanceof Entity) {
+				listNodes.add(node);
+			}
+			else if (listType == DTDRegionTypes.NOTATION_TAG && node instanceof Notation) {
+				listNodes.add(node);
+			}
+			else if (listType == DTDRegionTypes.COMMENT_START && node instanceof Comment) {
+				listNodes.add(node);
+			}
+			else if (listType == DTDRegionTypes.UNKNOWN_CONTENT && node instanceof Unrecognized) {
+				listNodes.add(node);
+			}
+		}
+		return listNodes;
+	}
+
+	public Image getImage() {
+		if (listType == DTDRegionTypes.ELEMENT_TAG) {
+			return DTDPlugin.getInstance().getImage(DTDResource.FLDR_EL);
+		}
+		else if (listType == DTDRegionTypes.ENTITY_TAG) {
+			return DTDPlugin.getInstance().getImage(DTDResource.FLDR_ENT);
+		}
+		else if (listType == DTDRegionTypes.NOTATION_TAG) {
+			return DTDPlugin.getInstance().getImage(DTDResource.FLDR_NOT);
+		}
+		else if (listType == DTDRegionTypes.COMMENT_START) {
+			return DTDPlugin.getInstance().getImage(DTDResource.FLDR_COMM);
+		}
+		else if (listType == DTDRegionTypes.UNKNOWN_CONTENT) {
+			return DTDPlugin.getInstance().getImage(DTDResource.FLDR_UNREC);
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Notation.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Notation.java
new file mode 100644
index 0000000..6ec36e0
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Notation.java
@@ -0,0 +1,29 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+
+
+public class Notation extends ExternalNode {
+
+	public Notation(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode, DTDRegionTypes.NOTATION_TAG);
+	}
+
+	public Image getImage() {
+		return DTDPlugin.getInstance().getImage(DTDResource.NOTATIONICON);
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/ParameterEntityReference.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/ParameterEntityReference.java
new file mode 100644
index 0000000..32ffe6e
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/ParameterEntityReference.java
@@ -0,0 +1,113 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public class ParameterEntityReference extends NamedTopLevelNode {
+
+	public ParameterEntityReference(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode, DTDRegionTypes.COMMENT_START);
+	}
+
+	public Image getImage() {
+		return DTDPlugin.getInstance().getImage(DTDResource.ENTITYREFERENCEICON);
+	}
+
+	public String getName() {
+		return getStructuredDocumentRegion().getText();
+	}
+
+	public void setReferencedEntity(String name) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_PARM_ENTITY_REF_CHG_ENTITY_REF")); //$NON-NLS-1$
+		setReferencedEntity(this, name);
+		endRecording(this);
+	}
+
+	public void setReferencedEntity(Object requestor, String name) {
+		replaceText(requestor, getStructuredDocumentRegion().getStartOffset(), getStructuredDocumentRegion().getLength(), "%" + name + ";"); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	public String getReferencedEntity() {
+		String text = getName();
+		return getName().substring(1, text.length() - 1);
+	}
+
+	private Entity cachedEntity = null;
+
+	public Entity getEntityObject() {
+		if (cachedEntity != null && !cachedEntity.getName().equals(getReferencedEntity())) {
+			// if we have a cached entity, but the name doesnt match, 
+			// null it now, so we perform a lookup
+			cachedEntity = null;
+		}
+
+		if (cachedEntity == null) {
+			List nodes = getDTDFile().getNodes();
+			for (int i = 0; i < nodes.size(); i++) {
+				DTDNode node = (DTDNode) nodes.get(i);
+				if (node instanceof Entity) {
+					Entity entity = (Entity) node;
+					if (entity.isParameterEntity() && entity.getName().equals(getReferencedEntity())) {
+						cachedEntity = entity;
+					}
+				}
+			}
+		}
+		return cachedEntity;
+	}
+
+
+
+	public class StartEndPair {
+		public int startOffset, endOffset;
+	}
+
+	private void getStartAndEndOffsetForText(StartEndPair pair) {
+		RegionIterator iter = iterator();
+		ITextRegion commentStartTag = getStartTag(iter);
+		ITextRegion endCommentTag = getNextRegion(iter, DTDRegionTypes.COMMENT_END);
+		pair.endOffset = getStructuredDocumentRegion().getEndOffset();
+		if (commentStartTag != null) {
+			pair.startOffset = getStructuredDocumentRegion().getEndOffset(commentStartTag);
+		}
+		if (endCommentTag != null) {
+			pair.endOffset = getStructuredDocumentRegion().getEndOffset(endCommentTag);
+		}
+	}
+
+	public String getText() {
+		String text = getStructuredDocumentRegion().getText();
+		int flatNodeStart = getStructuredDocumentRegion().getStartOffset();
+		StartEndPair pair = new StartEndPair();
+		getStartAndEndOffsetForText(pair);
+		return text.substring(pair.startOffset - flatNodeStart, pair.endOffset - flatNodeStart);
+	}
+
+	public void setText(String newText) {
+		beginRecording(this, DTDPlugin.getDTDString("_UI_LABEL_PARM_ENTITY_REF_COMMENT_CHG")); //$NON-NLS-1$
+		int flatNodeStart = getStructuredDocumentRegion().getStartOffset();
+		StartEndPair pair = new StartEndPair();
+		getStartAndEndOffsetForText(pair);
+		replaceText(this, pair.startOffset, pair.endOffset - pair.startOffset, newText);
+		endRecording(this);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/TopLevelNode.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/TopLevelNode.java
new file mode 100644
index 0000000..ba9fb38
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/TopLevelNode.java
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+// interface for nodes that can exist at the top level in a dtdfile
+// eg. entity, notation, element, comment, attlist, or unrecognized stuff (ie <junk dkfjdl>
+public abstract class TopLevelNode extends DTDNode {
+
+	private ArrayList flatNodes = new ArrayList();
+
+	public TopLevelNode(DTDFile dtdFile, IStructuredDocumentRegion flatNode) {
+		super(dtdFile, flatNode);
+		flatNodes.add(flatNode);
+	}
+
+	public ITextRegion getStartRegion() {
+		if (flatNode.getRegions().size() > 0) {
+			return flatNode.getRegions().get(0);
+		}
+		return null;
+	}
+
+	public ITextRegion getEndRegion() {
+		int size = flatNode.getRegions().size();
+		if (size > 0) {
+			return flatNode.getRegions().get(size - 1);
+		}
+		return null;
+	}
+
+	public RegionIterator iterator() {
+		//    System.out.println("create region iter " + this.getClass() + " with start , end = " + getStartOffset() + ", " +getEndOffset());
+		return new RegionIterator(flatNode, getStartOffset(), getEndOffset());
+	}
+
+	public void addWhitespaceStructuredDocumentRegion(IStructuredDocumentRegion node) {
+		flatNodes.add(node);
+	}
+
+	// includes what gettext gives us plus any whitespace 
+	// trailing it
+	public String getFullText() {
+		StringBuffer sb = new StringBuffer();
+		Iterator iter = flatNodes.iterator();
+		while (iter.hasNext()) {
+			IStructuredDocumentRegion fNode = (IStructuredDocumentRegion) iter.next();
+			sb.append(fNode.getText());
+		}
+		return sb.toString();
+	}
+
+	// specialize this so we delete the objects flat node range
+	// AND any whitespace
+	public void delete() {
+		beginRecording(getDTDFile(), DTDPlugin.getDTDString("_UI_LABEL_TOP_LEVEL_NODE_DELETE")); //$NON-NLS-1$
+		IStructuredDocumentRegion first = (IStructuredDocumentRegion) flatNodes.get(0);
+		IStructuredDocumentRegion last = (IStructuredDocumentRegion) flatNodes.get(flatNodes.size() - 1);
+		int startOffset = first.getStartOffset();
+		int endOffset = last.getEndOffset();
+
+		replaceText(getDTDFile(), startOffset, endOffset - startOffset, ""); //$NON-NLS-1$
+		endRecording(getDTDFile());
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Unrecognized.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Unrecognized.java
new file mode 100644
index 0000000..22a0cf2
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/Unrecognized.java
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+
+public class Unrecognized extends TopLevelNode {
+
+	public Unrecognized(DTDFile file, IStructuredDocumentRegion flatNode) {
+		super(file, flatNode);
+	}
+
+	public Image getImage() {
+		return DTDPlugin.getInstance().getImage(DTDResource.UNRECOGNIZEDICON);
+	}
+
+	public String getName() {
+		String text = getStructuredDocumentRegion().getText();
+		if (text.length() <= 30) {
+			return text;
+		}
+		else {
+			return text.substring(0, 29) + "..."; //$NON-NLS-1$
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/builder/delegates/DTDTaskTagSeeker.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/builder/delegates/DTDTaskTagSeeker.java
new file mode 100644
index 0000000..af20517
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/builder/delegates/DTDTaskTagSeeker.java
@@ -0,0 +1,25 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.builder.delegates;
+
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.builder.participants.TaskTagSeeker;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public class DTDTaskTagSeeker extends TaskTagSeeker {
+	protected boolean isCommentRegion(IStructuredDocumentRegion region, ITextRegion textRegion) {
+		return textRegion.getType().equals(DTDRegionTypes.COMMENT_CONTENT);
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/builder/participants/DTDTaskTagParticipant.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/builder/participants/DTDTaskTagParticipant.java
new file mode 100644
index 0000000..18acac8
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/builder/participants/DTDTaskTagParticipant.java
@@ -0,0 +1,25 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.builder.participants;
+
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+import org.eclipse.wst.sse.core.builder.participants.TaskTagParticipant;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public class DTDTaskTagParticipant extends TaskTagParticipant {
+	protected boolean isCommentRegion(IStructuredDocumentRegion region, ITextRegion textRegion) {
+		return textRegion.getType().equals(DTDRegionTypes.COMMENT_CONTENT);
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/content/ContentDescriberForDTD.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/content/ContentDescriberForDTD.java
new file mode 100644
index 0000000..c9a6338
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/content/ContentDescriberForDTD.java
@@ -0,0 +1,29 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.content;
+
+import org.eclipse.core.runtime.content.ITextContentDescriber;
+import org.eclipse.wst.encoding.AbstractContentDescriber;
+import org.eclipse.wst.encoding.IResourceCharsetDetector;
+import org.eclipse.wst.xml.core.contenttype.XMLResourceEncodingDetector;
+
+
+
+public class ContentDescriberForDTD extends AbstractContentDescriber implements ITextContentDescriber {
+	
+	// same rules as for XML
+	protected IResourceCharsetDetector getDetector() {
+		return new XMLResourceEncodingDetector();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/document/DTDModel.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/document/DTDModel.java
new file mode 100644
index 0000000..1ff3a47
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/document/DTDModel.java
@@ -0,0 +1,23 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.document;
+
+/**
+ * @author kboo
+ *
+ * To change the template for this generated type comment go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+public interface DTDModel {
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/document/DTDModelImpl.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/document/DTDModelImpl.java
new file mode 100644
index 0000000..1f2f13a
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/document/DTDModelImpl.java
@@ -0,0 +1,259 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.document;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.dtd.core.DTDFile;
+import org.eclipse.wst.dtd.core.DTDNode;
+import org.eclipse.wst.dtd.core.Entity;
+import org.eclipse.wst.dtd.core.NodeList;
+import org.eclipse.wst.dtd.core.event.IDTDFileListener;
+import org.eclipse.wst.dtd.core.event.NodesEvent;
+import org.eclipse.wst.dtd.core.util.DTDReferenceUpdater;
+import org.eclipse.wst.dtd.core.util.LabelValuePair;
+import org.eclipse.wst.sse.core.AbstractStructuredModel;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.events.NewModelEvent;
+import org.eclipse.wst.sse.core.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+
+
+public final class DTDModelImpl extends AbstractStructuredModel implements IStructuredDocumentListener, DTDModel {
+
+	private DTDFile document;
+
+	// entity reference names found in the conditional IGNORE sections
+	private Vector ignoredEntityRefs;
+
+	public DTDModelImpl() {
+		super();
+		document = new DTDFile(this);
+		document.addDTDFileListener(new IDTDFileListener() {
+			public void nodesAdded(NodesEvent event) {
+				checkIfExternalReferencesChanged(event);
+			}
+
+			public void nodesRemoved(NodesEvent event) {
+				checkIfExternalReferencesChanged(event);
+			}
+
+			public void nodeChanged(DTDNode node) {
+				if (node instanceof Entity) {
+					Entity entity = (Entity) node;
+					if (entity.isParameterEntity() && entity.isExternalEntity()) {
+						// just say they have changed for now
+						setReferencedModelsChanged();
+					}
+				}
+			}
+		});
+	}
+
+	// Returns entity reference names that are in
+	// the conditional IGNORE sections.
+	public Vector getIgnoredEntityRefs() {
+		if (ignoredEntityRefs == null)
+			ignoredEntityRefs = new Vector();
+		return ignoredEntityRefs;
+	}
+
+	private void checkIfExternalReferencesChanged(NodesEvent event) {
+		Iterator iter = event.getNodes().iterator();
+		while (iter.hasNext()) {
+			DTDNode node = (DTDNode) iter.next();
+			if (node instanceof Entity) {
+				Entity entity = (Entity) node;
+				if (entity.isParameterEntity() && entity.isExternalEntity()) {
+					// just say they have changed for now
+					setReferencedModelsChanged();
+				}
+			}
+		}
+	}
+
+
+	public DTDFile getDTDFile() {
+		return document;
+	}
+
+	public IndexedRegion getIndexedRegion(int offset) {
+		if (this.document == null)
+			return null;
+		//    System.out.println("getNode at " + offset + " returning = " + this.document.getNodeAt(offset));
+
+		return this.document.getNodeAt(offset);
+	}
+
+	public void newModel(NewModelEvent flatModelEvent) {
+		document.newModel(flatModelEvent);
+		//    System.out.println("\nnewmodel");
+		outputStructuredDocument(flatModelEvent);
+	}
+
+	public void noChange(NoChangeEvent flatModelEvent) {
+		//    System.out.println("\nnochange");
+		outputStructuredDocument(flatModelEvent);
+
+	}
+
+	public void nodesReplaced(StructuredDocumentRegionsReplacedEvent flatModelEvent) {
+		//    System.out.println("\nnodesreplaced");
+		document.nodesReplaced(flatModelEvent);
+		outputStructuredDocument(flatModelEvent);
+
+	}
+
+	public void regionChanged(RegionChangedEvent flatModelEvent) {
+		//    System.out.println("\nregion changed");
+		document.regionChanged(flatModelEvent);
+		//      System.out.println("= " + flatModelEvent.getStructuredDocumentRegion().getText());
+		//      System.out.println("region changed " + flatModelEvent.getRegion().hashCode() + " = " + flatModelEvent.getRegion());
+
+		outputStructuredDocument(flatModelEvent);
+	}
+
+	public void regionsReplaced(RegionsReplacedEvent flatModelEvent) {
+		//    System.out.println("\nregion replaced");
+		document.regionsReplaced(flatModelEvent);
+		outputStructuredDocument(flatModelEvent);
+	}
+
+	public void outputStructuredDocument(StructuredDocumentEvent flatModelEvent) {
+		//      System.out.println("structuredDocument source = '" + flatModelEvent.getStructuredDocument().getText() + "'");
+		//      System.out.println("new String = '" + flatModelEvent.getOriginalChanges() +"'");
+		//      System.out.println("deleted String = '" + flatModelEvent.getDeletedText() +"'");
+		//      Enumeration e = flatModelEvent.getStructuredDocument().getNodes().elements();
+		//      int i = 0;
+		//      for (; e.hasMoreElements(); i++) 
+		//      {
+		//        BasicStructuredDocumentRegion node = (BasicStructuredDocumentRegion) e.nextElement();
+		//        outputStructuredDocumentRegion(node);
+		//        System.out.println("  " + i +". " + node.hashCode() + " '" +node.getText() + "'");
+		//        }
+	}
+
+	public void outputStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		//      int size = flatNode.getNumberOfRegions();
+		//      for (int i = 0; i < size; i++) 
+		//      {
+		//        Region region = (Region) flatNode.getRegions().get(i);
+		//        System.out.println(i + ". " + region.getType());
+
+		//      } // end of for ()
+
+	}
+
+
+	/**
+	 */
+	public void setStructuredDocument(IStructuredDocument newStructuredDocument) {
+		IStructuredDocument oldStructuredDocument = super.getStructuredDocument();
+		if (newStructuredDocument == oldStructuredDocument)
+			return; // noting to do
+
+		if (oldStructuredDocument != null)
+			oldStructuredDocument.removeModelChangingListener(this);
+		super.setStructuredDocument(newStructuredDocument);
+		if (newStructuredDocument != null)
+			newStructuredDocument.addModelChangingListener(this);
+		document.setStructuredDocument(newStructuredDocument);
+	}
+
+	private boolean refreshRequired = false;
+
+	public void setRefreshRequired(boolean value) {
+		refreshRequired = value;
+	}
+
+	public boolean isRefreshRequired() {
+		return refreshRequired;
+	}
+
+	public void setReferencedModelsChanged() {
+		refreshRequired = true;
+	}
+
+	public boolean isReferencedModelsChanged() {
+		return refreshRequired;
+	}
+
+	//
+	// The following function helps determine the list of things that
+	// can be used in a parameter entity reference content
+	// Optional parameter is to allow the currently used DTDEntity to 
+	// be included in the combobox.
+	//
+	public LabelValuePair[] createParmEntityContentItems(Entity entity) {
+		NodeList entities = getDTDFile().getEntities();
+
+		Vector items = new Vector();
+
+		if (entity != null) {
+			String name = "%" + entity.getName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+			items.addElement(new LabelValuePair(name, name));
+		}
+
+		for (Iterator i = entities.getNodes().iterator(); i.hasNext();) {
+			Entity entityAt = (Entity) i.next();
+			if (entityAt.isParameterEntity() && entityAt.isExternalEntity()) {
+				String name = "%" + entityAt.getName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+				items.addElement(new LabelValuePair(name, name));
+			}
+		}
+		LabelValuePair[] comboArray = new LabelValuePair[items.size()];
+		items.copyInto(comboArray);
+		return comboArray;
+	}
+
+	private List errorMessages = new ArrayList();
+
+	public static boolean deleteFile(String fileName) {
+		boolean result = false;
+
+		// create the temp File object
+		File file = new File(fileName);
+		if (file.exists())
+			result = file.delete();
+		return result;
+	}
+
+	public void beginRecording(Object requester, String label) {
+		super.beginRecording(requester, label);
+		// clear reference updater cache
+		getReferenceUpdater().clearCache();
+	}
+
+	public void endRecording(Object requester) {
+		super.endRecording(requester);
+		// clear reference updater cache
+		getReferenceUpdater().clearCache();
+	}
+
+	protected DTDReferenceUpdater refUpdater = new DTDReferenceUpdater();
+
+	public DTDReferenceUpdater getReferenceUpdater() {
+		return refUpdater;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/encoding/DTDDocumentCharsetDetector.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/encoding/DTDDocumentCharsetDetector.java
new file mode 100644
index 0000000..748a7fd
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/encoding/DTDDocumentCharsetDetector.java
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.encoding;
+
+import java.io.IOException;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.encoding.AbstractResourceEncodingDetector;
+import org.eclipse.wst.sse.core.document.DocumentReader;
+import org.eclipse.wst.sse.core.document.IDocumentCharsetDetector;
+import org.eclipse.wst.xml.core.encoding.XMLDocumentCharsetDetector;
+
+/**
+ * @author kboo
+ * 
+ * To change the template for this generated type comment go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+public final class DTDDocumentCharsetDetector extends AbstractResourceEncodingDetector implements IDocumentCharsetDetector {
+
+	public String getSpecDefaultEncoding() {
+		// by default, UTF-8 as per XML spec
+		final String enc = "UTF-8"; //$NON-NLS-1$
+		return enc;
+	}
+
+	public void set(IDocument document) {
+		set(new DocumentReader(document, 0));
+
+
+	}
+
+	/**
+	 *
+	 */
+
+	protected void parseInput() throws IOException {
+		IDocumentCharsetDetector documentEncodingDetector = new XMLDocumentCharsetDetector();
+		documentEncodingDetector.set(fReader);
+		fEncodingMemento = documentEncodingDetector.getEncodingMemento();
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/encoding/DTDDocumentLoader.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/encoding/DTDDocumentLoader.java
new file mode 100644
index 0000000..921643c
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/encoding/DTDDocumentLoader.java
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.encoding;
+
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.dtd.core.internal.text.DTDStructuredDocumentReParser;
+import org.eclipse.wst.dtd.core.parser.DTDRegionParser;
+import org.eclipse.wst.dtd.core.text.rules.StructuredTextPartitionerForDTD;
+import org.eclipse.wst.sse.core.document.AbstractDocumentLoader;
+import org.eclipse.wst.sse.core.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
+import org.eclipse.wst.sse.core.parser.RegionParser;
+
+
+public final class DTDDocumentLoader extends AbstractDocumentLoader {
+
+	public DTDDocumentLoader() {
+		super();
+	}
+
+	public IDocumentPartitioner getDefaultDocumentPartitioner() {
+		return new StructuredTextPartitionerForDTD();
+	}
+
+	protected String getSpecDefaultEncoding() {
+		String enc = "UTF-8"; //$NON-NLS-1$
+		return enc;
+	}
+
+	public IDocumentCharsetDetector getDocumentEncodingDetector() {
+		if (fDocumentEncodingDetector == null) {
+			fDocumentEncodingDetector = new DTDDocumentCharsetDetector();
+		}
+		return fDocumentEncodingDetector;
+	}
+
+	public RegionParser getParser() {
+		return new DTDRegionParser();
+	}
+
+	public IEncodedDocument newEncodedDocument() {
+		BasicStructuredDocument flatModel = new BasicStructuredDocument(getParser());
+		DTDStructuredDocumentReParser reParser = new DTDStructuredDocumentReParser();
+		reParser.setStructuredDocument(flatModel);
+		flatModel.setReParser(reParser);
+		return flatModel;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/event/IDTDFileListener.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/event/IDTDFileListener.java
new file mode 100644
index 0000000..1594d0d
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/event/IDTDFileListener.java
@@ -0,0 +1,23 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.event;
+
+import org.eclipse.wst.dtd.core.DTDNode;
+
+public interface IDTDFileListener {
+	public void nodesAdded(NodesEvent event);
+
+	public void nodesRemoved(NodesEvent event);
+
+	public void nodeChanged(DTDNode node);
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/event/NodesEvent.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/event/NodesEvent.java
new file mode 100644
index 0000000..433aca1
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/event/NodesEvent.java
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.event;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.dtd.core.DTDNode;
+
+
+public final class NodesEvent {
+	private ArrayList changedNodes = new ArrayList();
+
+	public void add(DTDNode changedNode) {
+		changedNodes.add(changedNode);
+	}
+
+	public List getNodes() {
+		return changedNodes;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/text/DTDStructuredDocumentReParser.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/text/DTDStructuredDocumentReParser.java
new file mode 100644
index 0000000..29431d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/text/DTDStructuredDocumentReParser.java
@@ -0,0 +1,30 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.internal.text;
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.text.StructuredDocumentReParser;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+
+public class DTDStructuredDocumentReParser extends StructuredDocumentReParser {
+	protected StructuredDocumentEvent reparse(IStructuredDocumentRegion dirtyStart, IStructuredDocumentRegion dirtyEnd) {
+		return super.reparse(dirtyStart, dirtyEnd);
+	}
+
+	public StructuredDocumentEvent checkForCrossStructuredDocumentRegionBoundryCases() {
+		IStructuredDocumentRegion startNode = fStructuredDocument.getRegionAtCharacterOffset(fStart);
+		IStructuredDocumentRegion endNode = fStructuredDocument.getRegionAtCharacterOffset(fStart + fLengthToReplace - 1);
+		return reparse(startNode.getStart(), endNode.getEnd());
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/text/DTDStructuredDocumentRegionFactory.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/text/DTDStructuredDocumentRegionFactory.java
new file mode 100644
index 0000000..aacdf91
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/text/DTDStructuredDocumentRegionFactory.java
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.internal.text;
+
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+
+public class DTDStructuredDocumentRegionFactory {
+	public static final int DTD_GENERIC = 5;
+
+	public static IStructuredDocumentRegion createStructuredDocumentRegion(int type) {
+		IStructuredDocumentRegion instance = null;
+		switch (type) {
+			case DTD_GENERIC :
+				instance = new BasicStructuredDocumentRegion();
+				break;
+			default :
+				break;
+		}
+		return instance;
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/text/RegionIterator.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/text/RegionIterator.java
new file mode 100644
index 0000000..1f7b906
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/internal/text/RegionIterator.java
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.internal.text;
+
+import java.util.NoSuchElementException;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+
+public class RegionIterator {
+	public RegionIterator(IStructuredDocumentRegion node) {
+		this(node, node.getStart(), node.getEnd());
+	}
+
+	public RegionIterator(ITextRegionList regions) {
+		this.regions = regions;
+		startRegion = regions.get(0);
+		endRegion = regions.get(regions.size() - 1);
+		currentIndex = 0;
+		//    this(node, node.getStart(), node.getEnd());
+	}
+
+	public RegionIterator(IStructuredDocumentRegion node, int startOffset, int endOffset) {
+		regions = node.getRegions();
+		startRegion = node.getRegionAtCharacterOffset(startOffset);
+		endRegion = node.getRegionAtCharacterOffset(endOffset - 1);
+
+		for (int i = 0; i < regions.size(); i++) {
+			ITextRegion region = regions.get(i);
+			if (startRegion == region) {
+				currentIndex = i;
+				break;
+			}
+		}
+	}
+
+	private IStructuredDocumentRegion flatNode;
+	private ITextRegionList regions;
+	private ITextRegion startRegion, endRegion;
+	private int startOffset, endOffset;
+
+	private int currentIndex;
+
+	public ITextRegion next() {
+		if (hasNext()) {
+			return regions.get(currentIndex++);
+		}
+		throw new NoSuchElementException();
+	}
+
+	public ITextRegion previous() {
+		if (hasPrevious()) {
+			return regions.get(--currentIndex);
+		}
+		throw new NoSuchElementException();
+	}
+
+	public boolean hasNext() {
+		if (currentIndex < regions.size()) {
+			return currentIndex <= regions.indexOf(endRegion);
+		}
+		return false;
+	}
+
+	public boolean hasPrevious() {
+		if (currentIndex >= 0) {
+			return currentIndex >= regions.indexOf(startRegion);
+		}
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/modelhandler/DTDModelDumper.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/modelhandler/DTDModelDumper.java
new file mode 100644
index 0000000..f3f47bf
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/modelhandler/DTDModelDumper.java
@@ -0,0 +1,34 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.modelhandler;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.ModelDumper;
+
+public final class DTDModelDumper implements ModelDumper {
+
+	/* (non-Javadoc)
+	 */
+	public void dump(IStructuredModel model, OutputStream outputStream, EncodingRule encodingRule, IFile iFile) throws UnsupportedEncodingException, IOException, CoreException {
+		// TODO Auto-generated method stub
+		System.out.println("Implement DTDModelDumper.dump()"); //$NON-NLS-1$
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/modelhandler/DTDModelLoader.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/modelhandler/DTDModelLoader.java
new file mode 100644
index 0000000..d41f44b
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/modelhandler/DTDModelLoader.java
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.modelhandler;
+
+import org.eclipse.wst.dtd.core.document.DTDModelImpl;
+import org.eclipse.wst.dtd.core.encoding.DTDDocumentLoader;
+import org.eclipse.wst.sse.core.AbstractModelLoader;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.ModelLoader;
+import org.eclipse.wst.sse.core.document.IDocumentLoader;
+
+
+
+public final class DTDModelLoader extends AbstractModelLoader {
+	public DTDModelLoader() {
+		super();
+	}
+
+	public IStructuredModel newModel() {
+		IStructuredModel model = new DTDModelImpl();
+		// now done in create
+		//model.setStructuredDocument(createNewStructuredDocument());
+		//model.setFactoryRegistry(defaultFactoryRegistry());
+		return model;
+	}
+
+	public ModelLoader newInstance() {
+		return new DTDModelLoader();
+	}
+
+	public IDocumentLoader getDocumentLoader() {
+		if (documentLoaderInstance == null) {
+			documentLoaderInstance = new DTDDocumentLoader();
+		}
+		return documentLoaderInstance;
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/modelhandler/ModelHandlerForDTD.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/modelhandler/ModelHandlerForDTD.java
new file mode 100644
index 0000000..d593376
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/modelhandler/ModelHandlerForDTD.java
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.modelhandler;
+
+import org.eclipse.wst.dtd.core.encoding.DTDDocumentCharsetDetector;
+import org.eclipse.wst.dtd.core.encoding.DTDDocumentLoader;
+import org.eclipse.wst.sse.core.ModelLoader;
+import org.eclipse.wst.sse.core.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.modelhandler.AbstractModelHandler;
+import org.eclipse.wst.sse.core.modelhandler.IModelHandler;
+
+
+public final class ModelHandlerForDTD extends AbstractModelHandler implements IModelHandler {
+	private static String AssociatedContentTypeId = "org.eclipse.wst.dtd.core.dtdsource"; //$NON-NLS-1$
+	private static String ModelHandlerID = "org.eclipse.wst.sse.core.handler.dtd"; //$NON-NLS-1$
+
+	public ModelHandlerForDTD() {
+		super();
+		setId(ModelHandlerID);
+		setAssociatedContentTypeId(AssociatedContentTypeId);
+	}
+
+	public ModelLoader getModelLoader() {
+		return new DTDModelLoader();
+	}
+
+	public IDocumentLoader getDocumentLoader() {
+		return new DTDDocumentLoader();
+	}
+
+	public IDocumentCharsetDetector getEncodingDetector() {
+		return new DTDDocumentCharsetDetector();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegion.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegion.java
new file mode 100644
index 0000000..41354c7
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegion.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.parser;
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.parser.ContextRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+
+public class DTDRegion extends ContextRegion {
+	//TODO private String text;
+	//TODO protected IStructuredDocumentRegion parent;
+
+	public DTDRegion(String newContext, int newStart, int newLength) {
+		super(newContext, newStart, newLength, newLength);
+	}
+
+	/* TODO
+	 public int getEndOffset() 
+	 {
+	 return parent.getStartOffset() + getEnd();
+	 }
+
+	 public int getStartOffset() 
+	 {
+	 return parent.getStartOffset() + getStart();
+	 }
+
+	 public int getTextEndOffset() 
+	 {
+	 return parent.getStartOffset() + getTextEnd();
+	 }
+	 
+	 public void setParent(IStructuredDocumentRegion parent)
+	 {
+	 this.parent = parent;
+	 }
+	 
+	 public IStructuredDocumentRegion getParent()
+	 {
+	 return parent;
+	 }
+	 */
+
+	public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion flatnode, String changes, int requestStart, int requestLength) {
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegionFactory.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegionFactory.java
new file mode 100644
index 0000000..28e1995
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegionFactory.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.parser;
+
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+public class DTDRegionFactory implements DTDRegionTypes {
+	public static ITextRegion createRegion(String tokenKind, int start, int length) {
+		ITextRegion region = null;
+		if (tokenKind != null) {
+			region = new DTDRegion(tokenKind, start, length);
+		}
+		return region;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegionParser.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegionParser.java
new file mode 100644
index 0000000..7078776
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegionParser.java
@@ -0,0 +1,269 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.parser;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Vector;
+
+import org.eclipse.wst.dtd.core.internal.text.DTDStructuredDocumentRegionFactory;
+import org.eclipse.wst.dtd.core.parser.tokenizer.DTDTokenizer;
+import org.eclipse.wst.dtd.core.parser.tokenizer.Token;
+import org.eclipse.wst.sse.core.parser.RegionParser;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public class DTDRegionParser implements RegionParser {
+	private Vector cachedRegions = null;
+	private DTDTokenizer tokenizer = null;
+	private IStructuredDocumentRegion cachedNode = null; // top of node chain
+
+	public RegionParser newInstance() {
+		return new DTDRegionParser();
+	}
+
+	private IStructuredDocumentRegion addNewNodes(IStructuredDocumentRegion lastNode, Vector regions) {
+		IStructuredDocumentRegion leadingSpaceNode = null;
+		IStructuredDocumentRegion contentNode = null;
+		IStructuredDocumentRegion trailingSpaceNode = null;
+		LinkedList nodeSeeds = new LinkedList();
+		int nRegions = regions.size();
+		int leadingSpaceEnd = -1;
+		int trailingSpaceBegin = nRegions;
+
+		// find leading space
+		nodeSeeds.clear();
+		for (int i = 0; i < nRegions; i++) {
+			ITextRegion region = (ITextRegion) regions.get(i);
+			String type = region.getType();
+			if (isBlankRegion(type)) {
+				leadingSpaceEnd = i;
+				nodeSeeds.addLast(region);
+			}
+			else {
+				break;
+			}
+		}
+		if (!nodeSeeds.isEmpty()) {
+			leadingSpaceNode = createNode(nodeSeeds);
+			if (lastNode != null) {
+				lastNode.setNext(leadingSpaceNode);
+				leadingSpaceNode.setPrevious(lastNode);
+			}
+			lastNode = leadingSpaceNode;
+		}
+
+		// find trailing space
+		if (leadingSpaceEnd < nRegions - 1) {
+			nodeSeeds.clear();
+			for (int i = nRegions - 1; 0 <= i; i--) {
+				ITextRegion region = (ITextRegion) regions.get(i);
+				String type = ((ITextRegion) regions.get(i)).getType();
+				if (isBlankRegion(type)) {
+					trailingSpaceBegin = i;
+					nodeSeeds.addFirst(region);
+				}
+				else {
+					break;
+				}
+			}
+			if (!nodeSeeds.isEmpty()) {
+				trailingSpaceNode = createNode(nodeSeeds);
+			}
+
+			nodeSeeds.clear();
+			for (int i = leadingSpaceEnd + 1; i < trailingSpaceBegin; i++) {
+				nodeSeeds.addLast(regions.get(i));
+			}
+			if (!nodeSeeds.isEmpty()) {
+				contentNode = createNode(nodeSeeds);
+				if (lastNode != null) {
+					lastNode.setNext(contentNode);
+					contentNode.setPrevious(lastNode);
+				}
+				lastNode = contentNode;
+			}
+			if (trailingSpaceNode != null) {
+				lastNode.setNext(trailingSpaceNode);
+				trailingSpaceNode.setPrevious(lastNode);
+				lastNode = trailingSpaceNode;
+			}
+		}
+
+		return lastNode;
+	}
+
+	private IStructuredDocumentRegion createNode(LinkedList regions) {
+		if (regions.size() == 0) {
+			return null;
+		}
+
+		IStructuredDocumentRegion node = DTDStructuredDocumentRegionFactory.createStructuredDocumentRegion(DTDStructuredDocumentRegionFactory.DTD_GENERIC);
+		int start = ((ITextRegion) regions.getFirst()).getStart();
+		int length = ((ITextRegion) regions.getLast()).getEnd() - start;
+		node.setStart(start);
+		node.setLength(length);
+		for (ListIterator i = regions.listIterator(0); i.hasNext();) {
+			ITextRegion region = (ITextRegion) i.next();
+			node.addRegion(region);
+			region.adjustStart(-start);
+		}
+		node.setEnded(true);
+
+		return node;
+	}
+
+	private IStructuredDocumentRegion createNodeChain(List regions) {
+		IStructuredDocumentRegion headNode = null;
+		IStructuredDocumentRegion lastNode = null;
+		Vector nodeSeeds = new Vector();
+
+		for (Iterator e = regions.iterator(); e.hasNext();) {
+			ITextRegion region = (ITextRegion) e.next();
+			String type = region.getType();
+			// If the following regions appear, 
+			// a previous node is closed in front of it.
+			if (!nodeSeeds.isEmpty() && isBeginningRegion(type)) {
+				lastNode = addNewNodes(lastNode, nodeSeeds);
+				nodeSeeds.clear();
+			}
+			nodeSeeds.addElement(region);
+
+			// The following regions close the current node.
+			if (!nodeSeeds.isEmpty() && isEndingRegion(type)) {
+				lastNode = addNewNodes(lastNode, nodeSeeds);
+				nodeSeeds.clear();
+			}
+
+			if (headNode == null && lastNode != null) {
+				headNode = findFirstNode(lastNode);
+			}
+		}
+
+		// close current node forcibly.
+		if (!nodeSeeds.isEmpty()) {
+			lastNode = addNewNodes(lastNode, nodeSeeds);
+			if (headNode == null && lastNode != null) {
+				headNode = findFirstNode(lastNode);
+			}
+		}
+		return headNode;
+	}
+
+	private IStructuredDocumentRegion findFirstNode(IStructuredDocumentRegion node) {
+		IStructuredDocumentRegion firstNode = node;
+		IStructuredDocumentRegion prevNode = null;
+		while ((prevNode = firstNode.getPrevious()) != null) {
+			firstNode = prevNode;
+		}
+		return firstNode;
+	}
+
+	public IStructuredDocumentRegion getDocumentRegions() {
+		if (cachedNode != null) {
+			return cachedNode;
+		}
+
+		List regions = getRegions();
+		IStructuredDocumentRegion headNode = createNodeChain(regions);
+		cachedNode = headNode;
+
+		return headNode;
+	}
+
+	public List getRegions() {
+		if (cachedRegions != null) {
+			return cachedRegions;
+		}
+
+		Vector regions = new Vector();
+		Token currentToken = null;
+		do {
+			try {
+				currentToken = (Token) tokenizer.yylex();
+				if (currentToken != null) {
+					ITextRegion region = DTDRegionFactory.createRegion(currentToken.getType(), currentToken.getStartOffset(), currentToken.getLength());
+					regions.add(region);
+				}
+			}
+			catch (java.io.FileNotFoundException e) {
+				System.out.println("File not found"); //$NON-NLS-1$
+			}
+			catch (java.io.IOException e) {
+				System.out.println("Error opening file"); //$NON-NLS-1$
+			}
+		}
+		while (currentToken != null);
+
+		cachedRegions = regions;
+		return regions;
+	}
+
+	public void reset(Reader reader) {
+		if (tokenizer == null) {
+			try {
+				tokenizer = new DTDTokenizer(reader);
+			}
+			catch (ArrayIndexOutOfBoundsException e) {
+				System.out.println("Usage : java DTDTokenizer <inputfile>"); //$NON-NLS-1$
+			}
+		}
+		else {
+			try {
+				tokenizer.yyreset(reader);
+			}
+			catch (java.io.IOException e) {
+				System.out.println("Error opening file"); //$NON-NLS-1$
+			}
+		}
+
+		cachedNode = null;
+		cachedRegions = null;
+	}
+
+	/**
+	 * An additional offset for use with any position-dependant parsing rules
+	 */
+	public void reset(Reader reader, int offset) {
+		reset(reader);
+	}
+
+	public void reset(String input) {
+		reset(new StringReader(input));
+	}
+
+	public void reset(String input, int offset) {
+		reset(input);
+	}
+
+	private DTDTokenizer getTokenizer() {
+		return tokenizer;
+	}
+
+	private boolean isBeginningRegion(String type) {
+		return (type == DTDRegionTypes.START_TAG) || (type == DTDRegionTypes.ENTITY_PARM);
+	}
+
+	private boolean isBlankRegion(String type) {
+		return (type == DTDRegionTypes.WHITESPACE);
+	}
+
+	private boolean isEndingRegion(String type) {
+		return (type == DTDRegionTypes.END_TAG) || (type == DTDRegionTypes.ENTITY_PARM) || (type == DTDRegionTypes.COMMENT_END);
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegionTypes.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegionTypes.java
new file mode 100644
index 0000000..32bbd92
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/DTDRegionTypes.java
@@ -0,0 +1,76 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.parser;
+
+public interface DTDRegionTypes {
+	public static final String regionPrefix = "org.eclipse.wst.dtd.core.parser.DTDRegionTypes."; //$NON-NLS-1$
+
+	public static final String NAME = regionPrefix + "NAME"; //$NON-NLS-1$
+	public static final String START_TAG = regionPrefix + "START_TAG"; //$NON-NLS-1$
+	public static final String END_TAG = regionPrefix + "END_TAG"; //$NON-NLS-1$
+	public static final String LEFT_PAREN = regionPrefix + "LEFT_PAREN"; //$NON-NLS-1$
+	public static final String RIGHT_PAREN = regionPrefix + "RIGHT_PAREN"; //$NON-NLS-1$
+	public static final String WHITESPACE = regionPrefix + "WHITESPACE"; //$NON-NLS-1$
+	public static final String CONNECTOR = regionPrefix + "CONNECTOR"; //$NON-NLS-1$
+
+	public static final String OCCUR_TYPE = regionPrefix + "OCCUR_TYPE"; //$NON-NLS-1$
+	public static final String EXCLAMATION = regionPrefix + "EXCLAMATION"; //$NON-NLS-1$
+	public static final String PERCENT = regionPrefix + "PERCENT"; //$NON-NLS-1$
+	public static final String SEMICOLON = regionPrefix + "SEMICOLON"; //$NON-NLS-1$
+	public static final String COMMENT_START = regionPrefix + "COMMENT"; //$NON-NLS-1$
+	public static final String COMMENT_CONTENT = regionPrefix + "COMMENT_CONTENT"; //$NON-NLS-1$
+	public static final String COMMENT_END = regionPrefix + "COMMENT_END"; //$NON-NLS-1$
+
+	public static final String NOTATION_TAG = regionPrefix + "NOTATION_TAG"; //$NON-NLS-1$
+	public static final String NOTATION_CONTENT = regionPrefix + "NOTATION_CONTENT"; //$NON-NLS-1$
+
+	public static final String ENTITY_TAG = regionPrefix + "ENTITY_TAG"; //$NON-NLS-1$
+	public static final String ENTITY_PARM = regionPrefix + "ENTITY_PARM"; //$NON-NLS-1$
+	public static final String ENTITY_CONTENT = regionPrefix + "ENTITY_CONTENT"; //$NON-NLS-1$
+	public static final String NDATA_VALUE = regionPrefix + "NDATA_VALUE"; //$NON-NLS-1$
+
+	public static final String ELEMENT_TAG = regionPrefix + "ELEMENT_TAG"; //$NON-NLS-1$
+	public static final String ELEMENT_CONTENT = regionPrefix + "ELEMENT_CONTENT"; //$NON-NLS-1$
+	public static final String CONTENT_EMPTY = regionPrefix + "CONTENT_EMPTY"; //$NON-NLS-1$
+	public static final String CONTENT_ANY = regionPrefix + "CONTENT_ANY"; //$NON-NLS-1$
+	public static final String CONTENT_PCDATA = regionPrefix + "CONTENT_PCDATA"; //$NON-NLS-1$
+
+	public static final String ATTLIST_TAG = regionPrefix + "ATTLIST_TAG"; //$NON-NLS-1$
+
+	public static final String SYSTEM_KEYWORD = regionPrefix + "SYSTEM_KEYWORD"; //$NON-NLS-1$
+	public static final String PUBLIC_KEYWORD = regionPrefix + "PUBLIC_KEYWORD"; //$NON-NLS-1$
+	public static final String NDATA_KEYWORD = regionPrefix + "NDATA_KEYWORD"; //$NON-NLS-1$
+	public static final String SINGLEQUOTED_LITERAL = regionPrefix + "SINGLEQUOTED_LITERAL"; //$NON-NLS-1$
+	public static final String DOUBLEQUOTED_LITERAL = regionPrefix + "DOUBLEQUOTED_LITERAL"; //$NON-NLS-1$
+	public static final String UNKNOWN_CONTENT = regionPrefix + "UNKNOWN_CONTENT"; //$NON-NLS-1$
+
+	public static final String ATTRIBUTE_NAME = regionPrefix + "ATTRIBUTE_NAME"; //$NON-NLS-1$
+
+	// attribute type keywords  
+	public static final String CDATA_KEYWORD = regionPrefix + "CDATA_KEYWORD"; //$NON-NLS-1$
+	public static final String ID_KEYWORD = regionPrefix + "ID_KEYWORD"; //$NON-NLS-1$
+	public static final String IDREF_KEYWORD = regionPrefix + "IDREF_KEYWORD"; //$NON-NLS-1$
+	public static final String IDREFS_KEYWORD = regionPrefix + "IDREFS_KEYWORD"; //$NON-NLS-1$
+	public static final String ENTITY_KEYWORD = regionPrefix + "ENTITY_KEYWORD"; //$NON-NLS-1$
+	public static final String ENTITIES_KEYWORD = regionPrefix + "ENTITIES_KEYWORD"; //$NON-NLS-1$
+	public static final String NMTOKEN_KEYWORD = regionPrefix + "NMTOKEN_KEYWORD"; //$NON-NLS-1$
+	public static final String NMTOKENS_KEYWORD = regionPrefix + "NMTOKENS_KEYWORD"; //$NON-NLS-1$
+	public static final String NOTATION_KEYWORD = regionPrefix + "NOTATION_KEYWORD"; //$NON-NLS-1$
+	public static final String ENUM_CHOICE = regionPrefix + "ENUM_CHOICE"; //$NON-NLS-1$
+	public static final String PARM_ENTITY_TYPE = regionPrefix + "PARM_ENTITY_TYPE"; //$NON-NLS-1$
+
+	// attribute defaults keywords
+	public static final String REQUIRED_KEYWORD = regionPrefix + "REQUIRED_KEYWORD"; //$NON-NLS-1$
+	public static final String IMPLIED_KEYWORD = regionPrefix + "IMPLIED_KEYWORD"; //$NON-NLS-1$
+	public static final String FIXED_KEYWORD = regionPrefix + "FIXED_KEYWORD"; //$NON-NLS-1$
+}// DTDRegionTypes
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/tokenizer/DTDTokenizer.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/tokenizer/DTDTokenizer.java
new file mode 100644
index 0000000..bcd7b99
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/tokenizer/DTDTokenizer.java
@@ -0,0 +1,1275 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.parser.tokenizer;
+
+import java.io.IOException;
+
+import org.eclipse.wst.dtd.core.parser.DTDRegionTypes;
+
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.3.5
+ * on 05/04/02 11:38 AM from the specification file
+ */
+public class DTDTokenizer {
+
+	/** This character denotes the end of file */
+	final public static int YYEOF = -1;
+
+	/** initial size of the lookahead buffer */
+	final private static int YY_BUFFERSIZE = 16384;
+	final private static String yy_NL = System.getProperty("line.separator");
+
+	/** lexical states */
+	final public static int ATTRIBUTE_ENUMERATION = 13;
+	final public static int NOTATION_NAME = 6;
+	final public static int ELEMENT_CHILD = 1;
+	final public static int ENTITY_CONTENT = 4;
+	final public static int COMMENT_CONTENT = 8;
+	final public static int ATTLIST_NAME = 9;
+	final public static int EXTERNALID_CONTENT = 7;
+	final public static int ELEMENT_CONTENT = 1;
+	final public static int ELEMENT_MIXED = 1;
+	final public static int ELEMENT_MIXED_OR_CHILD = 1;
+	final public static int ATTRIBUTE_CONTENT = 11;
+	final public static int ENTITY_NAME = 3;
+	final public static int ATTRIBUTE_DEFAULT = 12;
+	final public static int ELEMENT_NAME = 2;
+	final public static int YYINITIAL = 0;
+	final public static int NDATA_CONTENT = 5;
+	final public static int ATTLIST_CONTENT = 10;
+	final public static int NODE = 1;
+
+	/** 
+	 * Translates characters to character classes
+	 */
+	final private static String yycmap_packed = "\10\0\1\0\1\5\1\3\1\0\1\0\1\2\22\0\1\5\1\6" + "\1\1\1\37\1\0\1\23\1\0\1\46\1\42\1\43\1\4\1\7" + "\1\45\1\12\1\0\1\0\12\0\1\0\1\10\1\11\1\0\1\13" + "\1\4\1\0\1\25\1\31\1\32\1\33\1\14\1\35\2\0\1\21" + "\1\0\1\36\1\15\1\16\1\17\1\24\1\27\1\40\1\34\1\26" + "\1\20\1\30\2\0\1\41\1\22\1\0\1\0\1\0\2\0\1\0" + "\1\0\32\0\1\0\1\44\uff83\0";
+
+	/** 
+	 * Translates characters to character classes
+	 */
+	final private static char[] yycmap = yy_unpack_cmap(yycmap_packed);
+
+	/** 
+	 * Translates a state to a row index in the transition table
+	 */
+	final private static int yy_rowMap[] = {0, 39, 78, 117, 156, 195, 234, 273, 312, 351, 390, 429, 468, 507, 546, 585, 624, 39, 39, 39, 663, 702, 741, 780, 819, 39, 39, 858, 897, 39, 39, 936, 936, 975, 1014, 1053, 1092, 1131, 1170, 1209, 1248, 1287, 1326, 1365, 1404, 1443, 39, 1482, 1521, 1560, 1599, 1638, 39, 1677, 1716, 1755, 1794, 1833, 1872, 39, 39, 1911, 1950, 1989, 2028, 2067, 2106, 39, 39, 39, 2145, 2184, 2223, 2262, 2301, 2340, 2379, 897, 2418, 975, 2457, 2496, 2535, 2574, 975, 2613, 2652, 2691, 2730, 1560, 2769, 2808, 2847, 2886, 2925, 2964, 3003, 3042, 3081, 3120, 1950, 3159, 3198, 3237, 3276, 3315, 1950, 39, 3354, 3393, 3432, 39, 3471, 3510, 3549, 39, 3588, 3627, 39, 3666, 3705, 3744, 39, 39, 3783, 3822, 3861, 3900, 3939, 3978, 4017, 4056, 39, 4095, 4134, 4173, 39, 4212, 4251, 4290, 4329, 4368, 4407, 4446, 4485, 4524, 4563, 4602, 4641, 4680, 4719, 4758, 4797, 4836, 4875, 4914, 4953, 4992, 5031, 5070, 5109, 5148, 5187, 5226, 5265, 5304, 5343, 975, 5382, 5421, 5460, 5499,
+				5538, 5577, 1560, 5616, 5655, 5694, 5733, 5772, 5811, 5850, 546, 5889, 5928, 5967, 6006, 975, 975, 975, 6045, 1560, 6084, 6123, 1560, 6162, 6201, 6240, 1950, 546, 6279, 546, 819, 6318, 6357, 6396, 6435, 6474, 6513, 546, 6552, 1560, 1560, 1560, 1950, 6591, 39, 1950};
+
+	/** 
+	 * The packed transition table of the DFA (part 0)
+	 */
+	final private static String yy_packed0 = "\2\17\2\20\1\17\1\20\1\21\1\17\1\22\1\23" + "\1\17\1\24\1\25\2\17\1\26\3\17\1\27\1\17" + "\1\30\21\17\47\0\2\31\2\20\1\32\1\20\1\0" + "\1\32\1\31\1\33\1\31\1\33\23\31\1\34\2\31" + "\1\35\1\36\2\37\1\31\2\40\2\20\1\0\1\20" + "\3\40\1\33\1\40\1\33\7\40\1\41\16\40\4\0" + "\1\40\1\42\1\43\2\20\1\42\1\20\3\42\1\33" + "\1\42\1\33\12\42\1\44\1\45\16\42\1\46\2\47" + "\2\20\1\47\1\20\3\47\1\33\1\47\1\33\33\47" + "\2\50\2\20\1\0\1\20\2\0\1\50\1\33\1\50" + "\1\33\26\50\4\0\1\50\1\42\1\43\2\20\1\42" + "\1\20\3\42\1\33\1\42\1\33\3\42\1\51\6\42" + "\1\52\1\53\16\42\1\46\2\54\2\55\1\54\1\55" + "\4\54\1\56\1\57\33\54\2\60\2\20\1\42\1\20" + "\2\42\1\60\1\33\1\60\1\33\26\60\4\42\1\60" + "\2\61\2\20\1\42\1\20\2\42\1\61\1\33\1\61" + "\1\33\26\61\4\42\1\61\1\62\1\63\1\64\1\65" + "\1\62\1\66\3\62\1\33\1\62\1\33\1\67\2\62" + "\1\70\1\62\1\71\10\62\1\72\4\62\1\73\2\62" + "\1\74\2\75\1\62\1\76\1\77\1\100\2\20\1\77" + "\1\20\3\77\1\33\1\77\1\33\23\77\1\101\6\77"
+				+ "\1\102\2\103\2\20\1\103\1\20\3\103\1\33\1\103" + "\1\33\26\103\1\104\1\105\1\106\2\103\2\17\2\0" + "\1\17\2\0\1\17\2\0\1\17\1\0\7\17\1\0" + "\23\17\2\0\2\20\1\0\1\20\53\0\1\107\34\0" + "\2\17\2\0\1\17\2\0\1\17\2\0\1\17\1\0" + "\1\17\1\110\1\17\1\111\3\17\1\0\25\17\2\0" + "\1\17\2\0\1\17\2\0\1\17\1\0\7\17\1\0" + "\1\112\22\17\2\113\2\0\1\113\2\0\1\113\2\0" + "\1\113\1\0\7\113\1\0\23\113\2\17\2\0\1\17" + "\2\0\1\17\2\0\1\17\1\0\4\17\1\114\2\17" + "\1\0\23\17\2\31\6\0\1\31\1\0\1\31\1\0" + "\26\31\4\0\3\31\6\0\1\31\1\0\1\31\1\0" + "\13\31\1\115\12\31\4\0\1\31\2\0\2\116\1\0" + "\1\116\31\0\1\117\7\0\2\40\4\0\3\40\1\0" + "\1\40\1\0\26\40\4\0\1\40\2\42\2\0\1\42" + "\1\0\3\42\1\0\1\42\1\0\33\42\1\43\1\120" + "\2\121\1\43\1\121\3\43\1\121\1\43\1\121\33\43" + "\2\42\2\0\1\42\1\0\3\42\1\0\1\42\1\0" + "\6\42\1\122\26\42\2\0\1\42\1\0\3\42\1\0" + "\1\42\1\0\14\42\1\123\16\42\2\46\2\124\1\46" + "\1\124\3\46\1\124\1\46\1\124\32\46\1\125\2\47"
+				+ "\2\0\1\47\1\0\3\47\1\0\1\47\1\0\33\47" + "\2\50\6\0\1\50\1\0\1\50\1\0\26\50\4\0" + "\1\50\2\42\2\0\1\42\1\0\3\42\1\0\1\42" + "\1\0\17\42\1\126\15\42\2\0\1\42\1\0\3\42" + "\1\0\1\42\1\0\6\42\1\127\26\42\2\0\1\42" + "\1\0\3\42\1\0\1\42\1\0\14\42\1\130\16\42" + "\12\54\2\0\35\54\2\55\1\54\1\55\4\54\2\0" + "\33\54\12\0\1\131\34\0\2\60\2\0\1\42\1\0" + "\2\42\1\60\1\0\1\60\1\0\26\60\4\42\1\60" + "\2\61\2\0\1\42\1\0\2\42\1\61\1\0\1\61" + "\1\0\26\61\4\42\1\61\2\62\2\0\1\62\1\0" + "\3\62\1\0\1\62\1\0\26\62\3\0\2\62\1\63" + "\1\132\2\133\1\63\1\133\3\63\1\133\1\63\1\133" + "\26\63\3\133\2\63\3\0\1\65\50\0\1\66\41\0" + "\2\62\2\0\1\62\1\0\3\62\1\0\1\62\1\0" + "\3\62\1\134\22\62\3\0\4\62\2\0\1\62\1\0" + "\3\62\1\0\1\62\1\0\2\62\1\135\5\62\1\136" + "\15\62\3\0\4\62\2\0\1\62\1\0\3\62\1\0" + "\1\62\1\0\17\62\1\137\6\62\3\0\4\62\2\0" + "\1\62\1\0\3\62\1\0\1\62\1\0\17\62\1\140" + "\6\62\3\0\4\62\2\0\1\62\1\0\3\62\1\0" + "\1\62\1\0\5\62\1\141\12\62\1\142\1\143\4\62"
+				+ "\3\0\2\62\2\76\2\144\1\76\1\144\3\76\1\144" + "\1\76\1\144\26\76\3\144\1\76\1\132\2\77\2\0" + "\1\77\1\0\3\77\1\0\1\77\1\0\33\77\1\100" + "\1\145\2\146\1\100\1\146\3\100\1\146\1\100\1\146" + "\33\100\2\77\2\0\1\77\1\0\3\77\1\0\1\77" + "\1\0\5\77\1\147\12\77\1\150\1\151\11\77\2\102" + "\2\152\1\102\1\152\3\102\1\152\1\102\1\152\32\102" + "\1\153\2\103\2\0\1\103\1\0\3\103\1\0\1\103" + "\1\0\26\103\3\0\2\103\12\0\1\154\34\0\2\17" + "\2\0\1\17\2\0\1\17\2\0\1\17\1\0\1\155" + "\6\17\1\0\25\17\2\0\1\17\2\0\1\17\2\0" + "\1\17\1\0\4\17\1\156\2\17\1\0\25\17\2\0" + "\1\17\2\0\1\17\2\0\1\17\1\0\4\17\1\157" + "\2\17\1\0\23\17\2\113\2\0\1\113\2\0\1\113" + "\1\160\1\0\1\113\1\0\7\113\1\0\23\113\2\17" + "\2\0\1\17\2\0\1\17\2\0\1\17\1\0\4\17" + "\1\161\2\17\1\0\23\17\2\31\6\0\1\31\1\0" + "\1\31\1\0\16\31\1\162\7\31\4\0\1\31\27\0" + "\1\163\17\0\1\121\1\164\45\121\2\42\2\0\1\42" + "\1\0\3\42\1\0\1\42\1\0\12\42\1\165\22\42" + "\2\0\1\42\1\0\3\42\1\0\1\42\1\0\15\42"
+				+ "\1\166\15\42\46\124\1\167\2\42\2\0\1\42\1\0" + "\3\42\1\0\1\42\1\0\11\42\1\170\23\42\2\0" + "\1\42\1\0\3\42\1\0\1\42\1\0\12\42\1\171" + "\22\42\2\0\1\42\1\0\3\42\1\0\1\42\1\0" + "\15\42\1\172\15\42\13\0\1\173\33\0\1\133\1\174" + "\45\133\2\62\2\0\1\62\1\0\3\62\1\0\1\62" + "\1\0\4\62\1\175\21\62\3\0\4\62\2\0\1\62" + "\1\0\3\62\1\0\1\62\1\0\4\62\1\176\21\62" + "\3\0\4\62\2\0\1\62\1\0\3\62\1\0\1\62" + "\1\0\4\62\1\177\21\62\3\0\4\62\2\0\1\62" + "\1\0\3\62\1\0\1\62\1\0\20\62\1\200\5\62" + "\3\0\4\62\2\0\1\62\1\0\3\62\1\0\1\62" + "\1\0\11\62\1\201\14\62\3\0\4\62\2\0\1\62" + "\1\0\3\62\1\0\1\62\1\0\2\62\1\202\23\62" + "\3\0\4\62\2\0\1\62\1\0\3\62\1\0\1\62" + "\1\0\1\203\25\62\3\0\4\62\2\0\1\62\1\0" + "\3\62\1\0\1\62\1\0\5\62\1\204\20\62\3\0" + "\2\62\46\144\1\174\1\146\1\205\45\146\2\77\2\0" + "\1\77\1\0\3\77\1\0\1\77\1\0\2\77\1\206" + "\32\77\2\0\1\77\1\0\3\77\1\0\1\77\1\0" + "\1\207\34\77\2\0\1\77\1\0\3\77\1\0\1\77" + "\1\0\5\77\1\210\25\77\46\152\1\211\2\17\2\0"
+				+ "\1\17\2\0\1\17\2\0\1\17\1\0\2\17\1\212" + "\4\17\1\0\25\17\2\0\1\17\2\0\1\17\2\0" + "\1\17\1\0\5\17\1\213\1\17\1\0\25\17\2\0" + "\1\17\2\0\1\17\2\0\1\17\1\0\7\17\1\0" + "\1\17\1\214\23\17\2\0\1\17\2\0\1\17\2\0" + "\1\17\1\0\1\17\1\215\5\17\1\0\23\17\2\31" + "\6\0\1\31\1\0\1\31\1\0\17\31\1\216\6\31" + "\4\0\1\31\32\0\1\217\14\0\2\42\2\0\1\42" + "\1\0\3\42\1\0\1\42\1\0\4\42\1\220\30\42" + "\2\0\1\42\1\0\3\42\1\0\1\42\1\0\1\42" + "\1\221\33\42\2\0\1\42\1\0\3\42\1\0\1\42" + "\1\0\4\42\1\222\30\42\2\0\1\42\1\0\3\42" + "\1\0\1\42\1\0\4\42\1\223\30\42\2\0\1\42" + "\1\0\3\42\1\0\1\42\1\0\1\42\1\224\31\42" + "\2\62\2\0\1\62\1\0\3\62\1\0\1\62\1\0" + "\5\62\1\225\20\62\3\0\4\62\2\0\1\62\1\0" + "\3\62\1\0\1\62\1\0\10\62\1\226\15\62\3\0" + "\4\62\2\0\1\62\1\0\3\62\1\0\1\62\1\0" + "\11\62\1\227\14\62\3\0\4\62\2\0\1\62\1\0" + "\3\62\1\0\1\62\1\0\1\230\25\62\3\0\4\62" + "\2\0\1\62\1\0\3\62\1\0\1\62\1\0\4\62" + "\1\231\21\62\3\0\4\62\2\0\1\62\1\0\3\62"
+				+ "\1\0\1\62\1\0\13\62\1\232\12\62\3\0\4\62" + "\2\0\1\62\1\0\3\62\1\0\1\62\1\0\24\62" + "\1\233\1\62\3\0\4\62\2\0\1\62\1\0\3\62" + "\1\0\1\62\1\0\25\62\1\234\3\0\2\62\2\77" + "\2\0\1\77\1\0\3\77\1\0\1\77\1\0\13\77" + "\1\235\21\77\2\0\1\77\1\0\3\77\1\0\1\77" + "\1\0\24\77\1\236\10\77\2\0\1\77\1\0\3\77" + "\1\0\1\77\1\0\25\77\1\237\5\77\2\17\2\0" + "\1\17\2\0\1\17\2\0\1\17\1\0\1\240\6\17" + "\1\0\25\17\2\0\1\17\2\0\1\17\2\0\1\17" + "\1\0\4\17\1\241\2\17\1\0\25\17\2\0\1\17" + "\2\0\1\17\2\0\1\17\1\0\4\17\1\242\2\17" + "\1\0\25\17\2\0\1\17\2\0\1\17\2\0\1\17" + "\1\0\5\17\1\243\1\17\1\0\23\17\2\31\6\0" + "\1\31\1\0\1\31\1\0\11\31\1\244\14\31\4\0" + "\1\31\33\0\1\245\13\0\2\42\2\0\1\42\1\0" + "\3\42\1\0\1\42\1\0\1\246\34\42\2\0\1\42" + "\1\0\3\42\1\0\1\42\1\0\5\42\1\247\27\42" + "\2\0\1\42\1\0\3\42\1\0\1\42\1\0\11\42" + "\1\250\23\42\2\0\1\42\1\0\3\42\1\0\1\42" + "\1\0\1\251\34\42\2\0\1\42\1\0\3\42\1\0" + "\1\42\1\0\5\42\1\252\25\42\2\62\2\0\1\62"
+				+ "\1\0\3\62\1\0\1\62\1\0\4\62\1\253\21\62" + "\3\0\4\62\2\0\1\62\1\0\3\62\1\0\1\62" + "\1\0\22\62\1\254\3\62\3\0\4\62\2\0\1\62" + "\1\0\3\62\1\0\1\62\1\0\4\62\1\255\21\62" + "\3\0\4\62\2\0\1\62\1\0\3\62\1\0\1\62" + "\1\0\21\62\1\256\4\62\3\0\4\62\2\0\1\62" + "\1\0\3\62\1\0\1\62\1\0\11\62\1\257\14\62" + "\3\0\4\62\2\0\1\62\1\0\3\62\1\0\1\62" + "\1\0\1\62\1\260\24\62\3\0\4\62\2\0\1\62" + "\1\0\3\62\1\0\1\62\1\0\14\62\1\261\11\62" + "\3\0\4\62\2\0\1\62\1\0\3\62\1\0\1\62" + "\1\0\1\262\25\62\3\0\2\62\2\77\2\0\1\77" + "\1\0\3\77\1\0\1\77\1\0\1\77\1\263\33\77" + "\2\0\1\77\1\0\3\77\1\0\1\77\1\0\14\77" + "\1\264\20\77\2\0\1\77\1\0\3\77\1\0\1\77" + "\1\0\1\265\32\77\2\17\2\0\1\17\2\0\1\17" + "\2\0\1\17\1\0\3\17\1\266\3\17\1\0\25\17" + "\2\0\1\17\2\0\1\17\2\0\1\17\1\0\6\17" + "\1\267\1\0\25\17\2\0\1\17\2\0\1\17\2\0" + "\1\17\1\0\5\17\1\270\1\17\1\0\25\17\2\0" + "\1\17\2\0\1\17\2\0\1\17\1\0\7\17\1\0" + "\2\17\1\271\20\17\2\31\6\0\1\31\1\0\1\31"
+				+ "\1\0\4\31\1\272\21\31\4\0\1\31\25\0\1\273" + "\21\0\2\42\2\0\1\42\1\0\3\42\1\0\1\42" + "\1\0\2\42\1\274\32\42\2\0\1\42\1\0\3\42" + "\1\0\1\42\1\0\16\42\1\274\16\42\2\0\1\42" + "\1\0\3\42\1\0\1\42\1\0\2\42\1\275\32\42" + "\2\0\1\42\1\0\3\42\1\0\1\42\1\0\16\42" + "\1\276\14\42\2\62\2\0\1\62\1\0\3\62\1\0" + "\1\62\1\0\5\62\1\277\1\300\17\62\3\0\4\62" + "\2\0\1\62\1\0\3\62\1\0\1\62\1\0\1\301" + "\25\62\3\0\4\62\2\0\1\62\1\0\3\62\1\0" + "\1\62\1\0\5\62\1\302\20\62\3\0\4\62\2\0" + "\1\62\1\0\3\62\1\0\1\62\1\0\12\62\1\303" + "\13\62\3\0\4\62\2\0\1\62\1\0\3\62\1\0" + "\1\62\1\0\5\62\1\234\20\62\3\0\4\62\2\0" + "\1\62\1\0\3\62\1\0\1\62\1\0\5\62\1\304" + "\20\62\3\0\4\62\2\0\1\62\1\0\3\62\1\0" + "\1\62\1\0\17\62\1\132\6\62\3\0\2\62\2\77" + "\2\0\1\77\1\0\3\77\1\0\1\77\1\0\5\77" + "\1\305\27\77\2\0\1\77\1\0\3\77\1\0\1\77" + "\1\0\5\77\1\306\27\77\2\0\1\77\1\0\3\77" + "\1\0\1\77\1\0\17\77\1\307\13\77\2\17\2\0" + "\1\17\2\0\1\17\2\0\1\17\1\0\4\17\1\310"
+				+ "\2\17\1\0\25\17\2\0\1\17\2\0\1\17\2\0" + "\1\17\1\0\7\17\1\0\1\311\24\17\2\0\1\17" + "\2\0\1\17\2\0\1\17\1\0\4\17\1\312\2\17" + "\1\0\23\17\2\31\6\0\1\31\1\0\1\31\1\0" + "\11\31\1\313\14\31\4\0\1\31\20\0\1\314\26\0" + "\2\62\2\0\1\62\1\0\3\62\1\0\1\62\1\0" + "\1\315\25\62\3\0\4\62\2\0\1\62\1\0\3\62" + "\1\0\1\62\1\0\3\62\1\316\22\62\3\0\4\62" + "\2\0\1\62\1\0\3\62\1\0\1\62\1\0\10\62" + "\1\317\15\62\3\0\4\62\2\0\1\62\1\0\3\62" + "\1\0\1\62\1\0\20\62\1\234\5\62\3\0\2\62" + "\2\77\2\0\1\77\1\0\3\77\1\0\1\77\1\0" + "\1\320\34\77\2\0\1\77\1\0\3\77\1\0\1\77" + "\1\0\20\77\1\321\12\77\2\17\2\0\1\17\2\0" + "\1\17\2\0\1\17\1\0\3\17\1\322\3\17\1\0" + "\23\17\25\0\1\323\21\0\2\62\2\0\1\62\1\0" + "\3\62\1\0\1\62\1\0\12\62\1\324\13\62\3\0" + "\4\62\2\0\1\62\1\0\3\62\1\0\1\62\1\0" + "\12\62\1\325\13\62\3\0\4\62\2\0\1\62\1\0" + "\3\62\1\0\1\62\1\0\3\62\1\326\22\62\3\0" + "\2\62\2\77\2\0\1\77\1\0\3\77\1\0\1\77" + "\1\0\17\77\1\327\15\77\2\0\1\77\1\0\3\77"
+				+ "\1\0\1\77\1\0\1\330\32\77\2\0\2\323\1\0" + "\1\323\35\0\1\331\3\0\2\77\2\0\1\77\1\0" + "\3\77\1\0\1\77\1\0\17\77\1\332\13\77";
+
+	/** 
+	 * The transition table of the DFA
+	 */
+	final private static int yytrans[] = yy_unpack();
+
+
+	/* error codes */
+	final private static int YY_UNKNOWN_ERROR = 0;
+	final private static int YY_ILLEGAL_STATE = 1;
+	final private static int YY_NO_MATCH = 2;
+	final private static int YY_PUSHBACK_2BIG = 3;
+
+	/* error messages for the codes above */
+	final private static String YY_ERROR_MSG[] = {"Unkown internal scanner error", "Internal error: unknown state", "Error: could not match input", "Error: pushback value was too large"};
+
+	/**
+	 * YY_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+	 */
+	private final static byte YY_ATTRIBUTE[] = {0, 8, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 1, 1, 1, 1, 1, 9, 9, 1, 1, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 9, 9, 1, 1, 1, 1, 1, 1, 9, 9, 9, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 9, 1, 1, 1, 9, 1, 1, 0, 9, 1, 1, 9, 1, 1, 1, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 9, 1};
+
+	/** the input device */
+	private java.io.Reader yy_reader;
+
+	/** the current state of the DFA */
+	private int yy_state;
+
+	/** the current lexical state */
+	private int yy_lexical_state = YYINITIAL;
+
+	/** this buffer contains the current text to be matched and is
+	 the source of the yytext() string */
+	private char yy_buffer[] = new char[YY_BUFFERSIZE];
+
+	/** the textposition at the last accepting state */
+	private int yy_markedPos;
+
+	/** the textposition at the last state to be included in yytext */
+	private int yy_pushbackPos;
+
+	/** the current text position in the buffer */
+	private int yy_currentPos;
+
+	/** startRead marks the beginning of the yytext() string in the buffer */
+	private int yy_startRead;
+
+	/** endRead marks the last character in the buffer, that has been read
+	 from input */
+	private int yy_endRead;
+
+	/** number of newlines encountered up to the start of the matched text */
+	private int yyline;
+
+	/** the number of characters up to the start of the matched text */
+	private int yychar;
+
+	/**
+	 * the number of characters from the last newline up to the start of the 
+	 * matched text
+	 */
+	private int yycolumn;
+
+	/** 
+	 * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+	 */
+	private boolean yy_atBOL = true;
+
+	/** yy_atEOF == true <=> the scanner is at the EOF */
+	private boolean yy_atEOF;
+
+	/* user code: */
+	private int node_count = 0;
+	private String currentString;
+
+	private Token createToken(String type) {
+		return new Token(type, yytext(), yyline, yychar + startOffset, yylength());
+	}
+
+	private int startOffset = 0;
+
+	public void setStartOffset(int startOffset) {
+		this.startOffset = startOffset;
+	}
+
+	public void setLine(int line) {
+		this.yyline = line;
+	}
+
+
+	/**
+	 * Creates a new scanner
+	 * There is also a java.io.InputStream version of this constructor.
+	 *
+	 * @param   in  the java.io.Reader to read input from.
+	 */
+	public DTDTokenizer(java.io.Reader in) {
+		this.yy_reader = in;
+	}
+
+	/**
+	 * Creates a new scanner.
+	 * There is also java.io.Reader version of this constructor.
+	 *
+	 * @param   in  the java.io.Inputstream to read input from.
+	 */
+	public DTDTokenizer(java.io.InputStream in) {
+		this(new java.io.InputStreamReader(in));
+	}
+
+	/** 
+	 * Unpacks the split, compressed DFA transition table.
+	 *
+	 * @return the unpacked transition table
+	 */
+	private static int[] yy_unpack() {
+		int[] trans = new int[6630];
+		int offset = 0;
+		offset = yy_unpack(yy_packed0, offset, trans);
+		return trans;
+	}
+
+	/** 
+	 * Unpacks the compressed DFA transition table.
+	 *
+	 * @param packed   the packed transition table
+	 * @return         the index of the last entry
+	 */
+	private static int yy_unpack(String packed, int offset, int[] trans) {
+		int i = 0; /* index in packed string  */
+		int j = offset; /* index in unpacked array */
+		int l = packed.length();
+		while (i < l) {
+			int count = packed.charAt(i++);
+			int value = packed.charAt(i++);
+			value--;
+			do
+				trans[j++] = value;
+			while (--count > 0);
+		}
+		return j;
+	}
+
+	/** 
+	 * Unpacks the compressed character translation table.
+	 *
+	 * @param packed   the packed character translation table
+	 * @return         the unpacked character translation table
+	 */
+	private static char[] yy_unpack_cmap(String packed) {
+		char[] map = new char[0x10000];
+		int i = 0; /* index in packed string  */
+		int j = 0; /* index in unpacked array */
+		while (i < 130) {
+			int count = packed.charAt(i++);
+			char value = packed.charAt(i++);
+			do
+				map[j++] = value;
+			while (--count > 0);
+		}
+		return map;
+	}
+
+
+	/**
+	 * Refills the input buffer.
+	 *
+	 * @return      <code>false</code>, iff there was new input.
+	 * 
+	 * @exception   IOException  if any I/O-Error occurs
+	 */
+	private boolean yy_refill() throws java.io.IOException {
+
+		/* first: make room (if you can) */
+		if (yy_startRead > 0) {
+			System.arraycopy(yy_buffer, yy_startRead, yy_buffer, 0, yy_endRead - yy_startRead);
+
+			/* translate stored positions */
+			yy_endRead -= yy_startRead;
+			yy_currentPos -= yy_startRead;
+			yy_markedPos -= yy_startRead;
+			yy_pushbackPos -= yy_startRead;
+			yy_startRead = 0;
+		}
+
+		/* is the buffer big enough? */
+		if (yy_currentPos >= yy_buffer.length) {
+			/* if not: blow it up */
+			char newBuffer[] = new char[yy_currentPos * 2];
+			System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+			yy_buffer = newBuffer;
+		}
+
+		/* finally: fill the buffer with new input */
+		int numRead = yy_reader.read(yy_buffer, yy_endRead, yy_buffer.length - yy_endRead);
+
+		if (numRead < 0) {
+			return true;
+		}
+		else {
+			yy_endRead += numRead;
+			return false;
+		}
+	}
+
+
+	/**
+	 * Closes the input stream.
+	 */
+	final public void yyclose() throws java.io.IOException {
+		yy_atEOF = true; /* indicate end of file */
+		yy_endRead = yy_startRead; /* invalidate buffer    */
+
+		if (yy_reader != null)
+			yy_reader.close();
+	}
+
+
+	/**
+	 * Closes the current stream, and resets the
+	 * scanner to read from a new input stream.
+	 *
+	 * All internal variables are reset, the old input stream 
+	 * <b>cannot</b> be reused (internal buffer is discarded and lost).
+	 * Lexical state is set to <tt>YY_INITIAL</tt>.
+	 *
+	 * @param reader   the new input stream 
+	 */
+	final public void yyreset(java.io.Reader reader) throws java.io.IOException {
+		yyclose();
+		yy_reader = reader;
+		yy_atBOL = true;
+		yy_atEOF = false;
+		yy_endRead = yy_startRead = 0;
+		yy_currentPos = yy_markedPos = yy_pushbackPos = 0;
+		yyline = yychar = yycolumn = 0;
+		yy_lexical_state = YYINITIAL;
+	}
+
+
+	/**
+	 * Returns the current lexical state.
+	 */
+	final public int yystate() {
+		return yy_lexical_state;
+	}
+
+
+	/**
+	 * Enters a new lexical state
+	 *
+	 * @param newState the new lexical state
+	 */
+	final public void yybegin(int newState) {
+		yy_lexical_state = newState;
+	}
+
+
+	/**
+	 * Returns the text matched by the current regular expression.
+	 */
+	final public String yytext() {
+		return new String(yy_buffer, yy_startRead, yy_markedPos - yy_startRead);
+	}
+
+
+	/**
+	 * Returns the character at position <tt>pos</tt> from the 
+	 * matched text. 
+	 * 
+	 * It is equivalent to yytext().charAt(pos), but faster
+	 *
+	 * @param pos the position of the character to fetch. 
+	 *            A value from 0 to yylength()-1.
+	 *
+	 * @return the character at position pos
+	 */
+	final public char yycharat(int pos) {
+		return yy_buffer[yy_startRead + pos];
+	}
+
+
+	/**
+	 * Returns the length of the matched text region.
+	 */
+	final public int yylength() {
+		return yy_markedPos - yy_startRead;
+	}
+
+
+	/**
+	 * Reports an error that occured while scanning.
+	 *
+	 * In a wellformed scanner (no or only correct usage of 
+	 * yypushback(int) and a match-all fallback rule) this method 
+	 * will only be called with things that "Can't Possibly Happen".
+	 * If this method is called, something is seriously wrong
+	 * (e.g. a JFlex bug producing a faulty scanner etc.).
+	 *
+	 * Usual syntax/scanner level error handling should be done
+	 * in error fallback rules.
+	 *
+	 * @param   errorCode  the code of the errormessage to display
+	 */
+	private void yy_ScanError(int errorCode) {
+		String message;
+		try {
+			message = YY_ERROR_MSG[errorCode];
+		}
+		catch (ArrayIndexOutOfBoundsException e) {
+			message = YY_ERROR_MSG[YY_UNKNOWN_ERROR];
+		}
+
+		throw new Error(message);
+	}
+
+
+	/**
+	 * Pushes the specified amount of characters back into the input stream.
+	 *
+	 * They will be read again by then next call of the scanning method
+	 *
+	 * @param number  the number of characters to be read again.
+	 *                This number must not be greater than yylength()!
+	 */
+	private void yypushback(int number) {
+		if (number > yylength())
+			yy_ScanError(YY_PUSHBACK_2BIG);
+
+		yy_markedPos -= number;
+	}
+
+
+	/**
+	 * Resumes scanning until the next regular expression is matched,
+	 * the end of input is encountered or an I/O-Error occurs.
+	 *
+	 * @return      the next token
+	 * @exception   IOException  if any I/O-Error occurs
+	 */
+	public Yytoken yylex() throws java.io.IOException {
+		int yy_input;
+		int yy_action;
+
+		// cached fields:
+		int yy_currentPos_l;
+		int yy_startRead_l;
+		int yy_markedPos_l;
+		int yy_endRead_l = yy_endRead;
+		char[] yy_buffer_l = yy_buffer;
+		char[] yycmap_l = yycmap;
+
+		int[] yytrans_l = yytrans;
+		int[] yy_rowMap_l = yy_rowMap;
+		byte[] yy_attr_l = YY_ATTRIBUTE;
+
+		while (true) {
+			yy_markedPos_l = yy_markedPos;
+
+			yychar += yy_markedPos_l - yy_startRead;
+
+			boolean yy_r = false;
+			for (yy_currentPos_l = yy_startRead; yy_currentPos_l < yy_markedPos_l; yy_currentPos_l++) {
+				switch (yy_buffer_l[yy_currentPos_l]) {
+					case '\u000B' :
+					case '\u000C' :
+					case '\u0085' :
+					case '\u2028' :
+					case '\u2029' :
+						yyline++;
+						yy_r = false;
+						break;
+					case '\r' :
+						yyline++;
+						yy_r = true;
+						break;
+					case '\n' :
+						if (yy_r)
+							yy_r = false;
+						else {
+							yyline++;
+						}
+						break;
+					default :
+						yy_r = false;
+				}
+			}
+
+			if (yy_r) {
+				// peek one character ahead if it is \n (if we have counted one line too much)
+				boolean yy_peek;
+				if (yy_markedPos_l < yy_endRead_l)
+					yy_peek = yy_buffer_l[yy_markedPos_l] == '\n';
+				else if (yy_atEOF)
+					yy_peek = false;
+				else {
+					boolean eof = yy_refill();
+					yy_markedPos_l = yy_markedPos;
+					yy_buffer_l = yy_buffer;
+					if (eof)
+						yy_peek = false;
+					else
+						yy_peek = yy_buffer_l[yy_markedPos_l] == '\n';
+				}
+				if (yy_peek)
+					yyline--;
+			}
+			yy_action = -1;
+
+			yy_startRead_l = yy_currentPos_l = yy_currentPos = yy_startRead = yy_markedPos_l;
+
+			yy_state = yy_lexical_state;
+
+
+			yy_forAction : {
+				while (true) {
+
+					if (yy_currentPos_l < yy_endRead_l)
+						yy_input = yy_buffer_l[yy_currentPos_l++];
+					else if (yy_atEOF) {
+						yy_input = YYEOF;
+						break yy_forAction;
+					}
+					else {
+						// store back cached positions
+						yy_currentPos = yy_currentPos_l;
+						yy_markedPos = yy_markedPos_l;
+						boolean eof = yy_refill();
+						// get translated positions and possibly new buffer
+						yy_currentPos_l = yy_currentPos;
+						yy_markedPos_l = yy_markedPos;
+						yy_buffer_l = yy_buffer;
+						yy_endRead_l = yy_endRead;
+						if (eof) {
+							yy_input = YYEOF;
+							break yy_forAction;
+						}
+						else {
+							yy_input = yy_buffer_l[yy_currentPos_l++];
+						}
+					}
+					int yy_next = yytrans_l[yy_rowMap_l[yy_state] + yycmap_l[yy_input]];
+					if (yy_next == -1)
+						break yy_forAction;
+					yy_state = yy_next;
+
+					int yy_attributes = yy_attr_l[yy_state];
+					if ((yy_attributes & 1) == 1) {
+						yy_action = yy_state;
+						yy_markedPos_l = yy_currentPos_l;
+						if ((yy_attributes & 8) == 8)
+							break yy_forAction;
+					}
+
+				}
+			}
+
+			// store back cached position
+			yy_markedPos = yy_markedPos_l;
+
+			switch (yy_action) {
+
+				case 26 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [197] { yypushback(yylength()); yybegin(YYINITIAL); }");
+					{
+						yypushback(yylength());
+						yybegin(YYINITIAL);
+					}
+				case 219 :
+					break;
+				case 89 :
+				case 123 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [231] { yypushback(yylength()); yybegin(ATTRIBUTE_DEFAULT); }");
+					{
+						yypushback(yylength());
+						yybegin(ATTRIBUTE_DEFAULT);
+					}
+				case 220 :
+					break;
+				case 12 :
+				case 62 :
+				case 63 :
+				case 64 :
+				case 65 :
+				case 102 :
+				case 103 :
+				case 104 :
+				case 133 :
+				case 134 :
+				case 135 :
+				case 156 :
+				case 157 :
+				case 158 :
+				case 178 :
+				case 179 :
+				case 180 :
+				case 196 :
+				case 197 :
+				case 207 :
+				case 208 :
+				case 215 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [247] { yypushback(yylength()); yybegin(ATTLIST_CONTENT); }");
+					{
+						yypushback(yylength());
+						yybegin(ATTLIST_CONTENT);
+					}
+				case 221 :
+					break;
+				case 51 :
+				case 52 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [217] { yypushback(yylength()); yybegin(ATTLIST_CONTENT); }");
+					{
+						yypushback(yylength());
+						yybegin(ATTLIST_CONTENT);
+					}
+				case 222 :
+					break;
+				case 205 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [227] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.NMTOKEN_KEYWORD); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.NMTOKEN_KEYWORD);
+					}
+				case 223 :
+					break;
+				case 194 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [224] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.IDREFS_KEYWORD); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.IDREFS_KEYWORD);
+					}
+				case 224 :
+					break;
+				case 191 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [225] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.ENTITY_KEYWORD); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.ENTITY_KEYWORD);
+					}
+				case 225 :
+					break;
+				case 107 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [174] { yybegin(COMMENT_CONTENT); return createToken(DTDRegionTypes.COMMENT_START); }");
+					{
+						yybegin(COMMENT_CONTENT);
+						return createToken(DTDRegionTypes.COMMENT_START);
+					}
+				case 226 :
+					break;
+				case 48 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [211] { yybegin(ATTRIBUTE_CONTENT); return createToken(DTDRegionTypes.ATTRIBUTE_NAME); }");
+					{
+						yybegin(ATTRIBUTE_CONTENT);
+						return createToken(DTDRegionTypes.ATTRIBUTE_NAME);
+					}
+				case 227 :
+					break;
+				case 39 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [283] { yybegin(EXTERNALID_CONTENT); return createToken(DTDRegionTypes.NAME); }");
+					{
+						yybegin(EXTERNALID_CONTENT);
+						return createToken(DTDRegionTypes.NAME);
+					}
+				case 228 :
+					break;
+				case 106 :
+				case 136 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [245] { yybegin(ATTLIST_CONTENT); return createToken(DTDRegionTypes.SINGLEQUOTED_LITERAL); }");
+					{
+						yybegin(ATTLIST_CONTENT);
+						return createToken(DTDRegionTypes.SINGLEQUOTED_LITERAL);
+					}
+				case 229 :
+					break;
+				case 100 :
+				case 132 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [246] { yybegin(ATTLIST_CONTENT); return createToken(DTDRegionTypes.DOUBLEQUOTED_LITERAL); }");
+					{
+						yybegin(ATTLIST_CONTENT);
+						return createToken(DTDRegionTypes.DOUBLEQUOTED_LITERAL);
+					}
+				case 230 :
+					break;
+				case 202 :
+				case 216 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [189] { return createToken(DTDRegionTypes.CONTENT_PCDATA); }");
+					{
+						return createToken(DTDRegionTypes.CONTENT_PCDATA);
+					}
+				case 231 :
+					break;
+				case 189 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [290] { return createToken(DTDRegionTypes.PUBLIC_KEYWORD); }");
+					{
+						return createToken(DTDRegionTypes.PUBLIC_KEYWORD);
+					}
+				case 232 :
+					break;
+				case 188 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [289] { return createToken(DTDRegionTypes.SYSTEM_KEYWORD); }");
+					{
+						return createToken(DTDRegionTypes.SYSTEM_KEYWORD);
+					}
+				case 233 :
+					break;
+				case 14 :
+				case 20 :
+				case 21 :
+				case 23 :
+				case 71 :
+				case 72 :
+				case 73 :
+				case 75 :
+				case 108 :
+				case 109 :
+				case 110 :
+				case 112 :
+				case 137 :
+				case 138 :
+				case 139 :
+				case 140 :
+				case 159 :
+				case 160 :
+				case 161 :
+				case 162 :
+				case 181 :
+				case 183 :
+				case 184 :
+				case 200 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [182] { return createToken(DTDRegionTypes.UNKNOWN_CONTENT); }");
+					{
+						return createToken(DTDRegionTypes.UNKNOWN_CONTENT);
+					}
+				case 234 :
+					break;
+				case 4 :
+				case 33 :
+				case 34 :
+				case 35 :
+				case 36 :
+				case 37 :
+				case 81 :
+				case 82 :
+				case 116 :
+				case 117 :
+				case 143 :
+				case 144 :
+				case 165 :
+				case 166 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [275] { return createToken(DTDRegionTypes.UNKNOWN_CONTENT); }");
+					{
+						return createToken(DTDRegionTypes.UNKNOWN_CONTENT);
+					}
+				case 235 :
+					break;
+				case 7 :
+				case 40 :
+				case 41 :
+				case 42 :
+				case 85 :
+				case 86 :
+				case 87 :
+				case 119 :
+				case 120 :
+				case 121 :
+				case 145 :
+				case 146 :
+				case 147 :
+				case 168 :
+				case 169 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [294] { return createToken(DTDRegionTypes.UNKNOWN_CONTENT); }");
+					{
+						return createToken(DTDRegionTypes.UNKNOWN_CONTENT);
+					}
+				case 236 :
+					break;
+				case 9 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [205] { return createToken(DTDRegionTypes.UNKNOWN_CONTENT); }");
+					{
+						return createToken(DTDRegionTypes.UNKNOWN_CONTENT);
+					}
+				case 237 :
+					break;
+				case 10 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [212] { return createToken(DTDRegionTypes.UNKNOWN_CONTENT); }");
+					{
+						return createToken(DTDRegionTypes.UNKNOWN_CONTENT);
+					}
+				case 238 :
+					break;
+				case 43 :
+				case 45 :
+				case 46 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [309] { return createToken(DTDRegionTypes.COMMENT_CONTENT); }");
+					{
+						return createToken(DTDRegionTypes.COMMENT_CONTENT);
+					}
+				case 239 :
+					break;
+				case 60 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [236] { return createToken(DTDRegionTypes.UNKNOWN_CONTENT); }");
+					{
+						return createToken(DTDRegionTypes.UNKNOWN_CONTENT);
+					}
+				case 240 :
+					break;
+				case 198 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [244] { return createToken(DTDRegionTypes.FIXED_KEYWORD); }");
+					{
+						return createToken(DTDRegionTypes.FIXED_KEYWORD);
+					}
+				case 241 :
+					break;
+				case 214 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [243] { yybegin(ATTLIST_CONTENT); return createToken(DTDRegionTypes.IMPLIED_KEYWORD); }");
+					{
+						yybegin(ATTLIST_CONTENT);
+						return createToken(DTDRegionTypes.IMPLIED_KEYWORD);
+					}
+				case 242 :
+					break;
+				case 212 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [228] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.NMTOKENS_KEYWORD); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.NMTOKENS_KEYWORD);
+					}
+				case 243 :
+					break;
+				case 211 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [226] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.ENTITIES_KEYWORD); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.ENTITIES_KEYWORD);
+					}
+				case 244 :
+					break;
+				case 209 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [176] { yybegin(NOTATION_NAME); return createToken(DTDRegionTypes.NOTATION_TAG); }");
+					{
+						yybegin(NOTATION_NAME);
+						return createToken(DTDRegionTypes.NOTATION_TAG);
+					}
+				case 245 :
+					break;
+				case 201 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [177] { yybegin(ATTLIST_NAME); return createToken(DTDRegionTypes.ATTLIST_TAG); }");
+					{
+						yybegin(ATTLIST_NAME);
+						return createToken(DTDRegionTypes.ATTLIST_TAG);
+					}
+				case 246 :
+					break;
+				case 199 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [173] { yybegin(ELEMENT_NAME); return createToken(DTDRegionTypes.ELEMENT_TAG); }");
+					{
+						yybegin(ELEMENT_NAME);
+						return createToken(DTDRegionTypes.ELEMENT_TAG);
+					}
+				case 247 :
+					break;
+				case 182 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [175] { yybegin(ENTITY_NAME); return createToken(DTDRegionTypes.ENTITY_TAG); }");
+					{
+						yybegin(ENTITY_NAME);
+						return createToken(DTDRegionTypes.ENTITY_TAG);
+					}
+				case 248 :
+					break;
+				case 167 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [293] { yybegin(NDATA_CONTENT); return createToken(DTDRegionTypes.NDATA_KEYWORD); }");
+					{
+						yybegin(NDATA_CONTENT);
+						return createToken(DTDRegionTypes.NDATA_KEYWORD);
+					}
+				case 249 :
+					break;
+				case 111 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [179] { return createToken(DTDRegionTypes.ENTITY_PARM); }");
+					{
+						return createToken(DTDRegionTypes.ENTITY_PARM);
+					}
+				case 250 :
+					break;
+				case 94 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [222] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.ID_KEYWORD); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.ID_KEYWORD);
+					}
+				case 251 :
+					break;
+				case 25 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [194] { return createToken(DTDRegionTypes.OCCUR_TYPE); }");
+					{
+						return createToken(DTDRegionTypes.OCCUR_TYPE);
+					}
+				case 252 :
+					break;
+				case 16 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [169] { return createToken(DTDRegionTypes.EXCLAMATION); }");
+					{
+						return createToken(DTDRegionTypes.EXCLAMATION);
+					}
+				case 253 :
+					break;
+				case 15 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [184] { return createToken(DTDRegionTypes.WHITESPACE); }");
+					{
+						return createToken(DTDRegionTypes.WHITESPACE);
+					}
+				case 254 :
+					break;
+				case 11 :
+				case 49 :
+				case 50 :
+				case 54 :
+				case 55 :
+				case 56 :
+				case 57 :
+				case 58 :
+				case 61 :
+				case 91 :
+				case 92 :
+				case 93 :
+				case 95 :
+				case 96 :
+				case 97 :
+				case 98 :
+				case 124 :
+				case 125 :
+				case 126 :
+				case 127 :
+				case 128 :
+				case 129 :
+				case 130 :
+				case 131 :
+				case 148 :
+				case 149 :
+				case 150 :
+				case 151 :
+				case 152 :
+				case 153 :
+				case 154 :
+				case 155 :
+				case 170 :
+				case 171 :
+				case 172 :
+				case 175 :
+				case 176 :
+				case 177 :
+				case 190 :
+				case 192 :
+				case 193 :
+				case 195 :
+				case 204 :
+				case 206 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [235] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.PARM_ENTITY_TYPE); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.PARM_ENTITY_TYPE);
+					}
+				case 255 :
+					break;
+				case 28 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [192] { return createToken(DTDRegionTypes.LEFT_PAREN); }");
+					{
+						return createToken(DTDRegionTypes.LEFT_PAREN);
+					}
+				case 256 :
+					break;
+				case 29 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [195] { return createToken(DTDRegionTypes.RIGHT_PAREN); }");
+					{
+						return createToken(DTDRegionTypes.RIGHT_PAREN);
+					}
+				case 257 :
+					break;
+				case 44 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [308] { return createToken(DTDRegionTypes.WHITESPACE); }");
+					{
+						return createToken(DTDRegionTypes.WHITESPACE);
+					}
+				case 258 :
+					break;
+				case 53 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [218] { return createToken(DTDRegionTypes.WHITESPACE); }");
+					{
+						return createToken(DTDRegionTypes.WHITESPACE);
+					}
+				case 259 :
+					break;
+				case 59 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [234] { yypushback(yylength()); yybegin(ATTRIBUTE_ENUMERATION); }");
+					{
+						yypushback(yylength());
+						yybegin(ATTRIBUTE_ENUMERATION);
+					}
+				case 260 :
+					break;
+				case 67 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [253] { return createToken(DTDRegionTypes.LEFT_PAREN); }");
+					{
+						return createToken(DTDRegionTypes.LEFT_PAREN);
+					}
+				case 261 :
+					break;
+				case 68 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [255] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.RIGHT_PAREN); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.RIGHT_PAREN);
+					}
+				case 262 :
+					break;
+				case 69 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [254] { return createToken(DTDRegionTypes.ENUM_CHOICE); }");
+					{
+						return createToken(DTDRegionTypes.ENUM_CHOICE);
+					}
+				case 263 :
+					break;
+				case 31 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [265] { yybegin(ENTITY_CONTENT); return createToken(DTDRegionTypes.NAME); }");
+					{
+						yybegin(ENTITY_CONTENT);
+						return createToken(DTDRegionTypes.NAME);
+					}
+				case 264 :
+					break;
+				case 47 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [204] { yybegin(ATTLIST_CONTENT); return createToken(DTDRegionTypes.NAME); }");
+					{
+						yybegin(ATTLIST_CONTENT);
+						return createToken(DTDRegionTypes.NAME);
+					}
+				case 265 :
+					break;
+				case 187 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [272] { yypushback(yylength()); yybegin(EXTERNALID_CONTENT); }");
+					{
+						yypushback(yylength());
+						yybegin(EXTERNALID_CONTENT);
+					}
+				case 266 :
+					break;
+				case 213 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [229] { yybegin(ATTRIBUTE_ENUMERATION); return createToken(DTDRegionTypes.NOTATION_KEYWORD); }");
+					{
+						yybegin(ATTRIBUTE_ENUMERATION);
+						return createToken(DTDRegionTypes.NOTATION_KEYWORD);
+					}
+				case 267 :
+					break;
+				case 174 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [220] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.CDATA_KEYWORD); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.CDATA_KEYWORD);
+					}
+				case 268 :
+					break;
+				case 173 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [223] { yybegin(ATTRIBUTE_DEFAULT); return createToken(DTDRegionTypes.IDREF_KEYWORD); }");
+					{
+						yybegin(ATTRIBUTE_DEFAULT);
+						return createToken(DTDRegionTypes.IDREF_KEYWORD);
+					}
+				case 269 :
+					break;
+				case 217 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [242] { yybegin(ATTLIST_CONTENT); return createToken(DTDRegionTypes.REQUIRED_KEYWORD); }");
+					{
+						yybegin(ATTLIST_CONTENT);
+						return createToken(DTDRegionTypes.REQUIRED_KEYWORD);
+					}
+				case 270 :
+					break;
+				case 122 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [307] { yybegin(YYINITIAL); return createToken(DTDRegionTypes.COMMENT_END); }");
+					{
+						yybegin(YYINITIAL);
+						return createToken(DTDRegionTypes.COMMENT_END);
+					}
+				case 271 :
+					break;
+				case 84 :
+				case 118 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [273] { return createToken(DTDRegionTypes.SINGLEQUOTED_LITERAL); }");
+					{
+						return createToken(DTDRegionTypes.SINGLEQUOTED_LITERAL);
+					}
+				case 272 :
+					break;
+				case 79 :
+				case 115 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [274] { return createToken(DTDRegionTypes.DOUBLEQUOTED_LITERAL); }");
+					{
+						return createToken(DTDRegionTypes.DOUBLEQUOTED_LITERAL);
+					}
+				case 273 :
+					break;
+				case 24 :
+				case 27 :
+				case 76 :
+				case 113 :
+				case 141 :
+				case 163 :
+				case 185 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [190] { return createToken(DTDRegionTypes.NAME); }");
+					{
+						return createToken(DTDRegionTypes.NAME);
+					}
+				case 274 :
+					break;
+				case 5 :
+				case 38 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [300] { yybegin(YYINITIAL); return createToken(DTDRegionTypes.NDATA_VALUE); }");
+					{
+						yybegin(YYINITIAL);
+						return createToken(DTDRegionTypes.NDATA_VALUE);
+					}
+				case 275 :
+					break;
+				case 13 :
+				case 66 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [256] { return createToken(DTDRegionTypes.NAME); }");
+					{
+						return createToken(DTDRegionTypes.NAME);
+					}
+				case 276 :
+					break;
+				case 18 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [167] { return createToken(DTDRegionTypes.START_TAG); }");
+					{
+						return createToken(DTDRegionTypes.START_TAG);
+					}
+				case 277 :
+					break;
+				case 17 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [171] { return createToken(DTDRegionTypes.SEMICOLON); }");
+					{
+						return createToken(DTDRegionTypes.SEMICOLON);
+					}
+				case 278 :
+					break;
+				case 30 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [193] { return createToken(DTDRegionTypes.CONNECTOR); }");
+					{
+						return createToken(DTDRegionTypes.CONNECTOR);
+					}
+				case 279 :
+					break;
+				case 22 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [170] { return createToken(DTDRegionTypes.PERCENT); }");
+					{
+						return createToken(DTDRegionTypes.PERCENT);
+					}
+				case 280 :
+					break;
+				case 19 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [168] { return createToken(DTDRegionTypes.END_TAG); }");
+					{
+						return createToken(DTDRegionTypes.END_TAG);
+					}
+				case 281 :
+					break;
+				case 32 :
+					//System.out.println("line: "+(yyline+1)+" "+"match: --"+yytext()+"--");
+					//System.out.println("action [264] { return createToken(DTDRegionTypes.PERCENT); }");
+					{
+						return createToken(DTDRegionTypes.PERCENT);
+					}
+				case 282 :
+					break;
+				default :
+					if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+						yy_atEOF = true;
+						return null;
+					}
+					else {
+						yy_ScanError(YY_NO_MATCH);
+					}
+			}
+		}
+	}
+
+	/**
+	 * Runs the scanner on input files.
+	 *
+	 * This main method is the debugging routine for the scanner.
+	 * It prints debugging information about each returned token to
+	 * System.out until the end of file is reached, or an error occured.
+	 *
+	 * @param argv   the command line, contains the filenames to run
+	 *               the scanner on.
+	 */
+	public static void main(String argv[]) {
+		if (argv.length == 0) {
+			System.out.println("Usage : java DTDTokenizer <inputfile>");
+		}
+		else {
+			for (int i = 0; i < argv.length; i++) {
+				DTDTokenizer scanner = null;
+				try {
+					scanner = new DTDTokenizer(new java.io.FileReader(argv[i]));
+					do {
+						System.out.println(scanner.yylex());
+					}
+					while (!scanner.yy_atEOF);
+
+				}
+				catch (java.io.FileNotFoundException e) {
+					System.out.println("File not found : \"" + argv[i] + "\"");
+				}
+				catch (java.io.IOException e) {
+					System.out.println("IO error scanning file \"" + argv[i] + "\"");
+					System.out.println(e);
+				}
+				catch (Exception e) {
+					System.out.println("Unexpected exception:");
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/tokenizer/Token.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/tokenizer/Token.java
new file mode 100644
index 0000000..e1b26ec
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/tokenizer/Token.java
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.parser.tokenizer;
+
+public class Token extends Yytoken {
+	public static final int NAME = 0;
+	public static final int START_TAG = 1;
+	public static final int END_TAG = 2;
+	public static final int LEFT_PAREN = 3;
+	public static final int RIGHT_PAREN = 4;
+	public static final int WHITESPACE = 5;
+	public static final int CONNECTOR = 6;
+
+	//    public static final int CONNECT_CHOICE = 5;
+	//    public static final int CONNECT_SEQUENCE = 6;
+	//    public static final int OCCUR_OPTIONAL = 7;
+	//    public static final int OCCUR_ONE_OR_MORE = 8;
+	//    public static final int OCCUR_ZERO_OR_MORE = 9;
+	public static final int OCCUR_TYPE = 7;
+	public static final int EXCLAMATION = 8;
+	public static final int COMMENT_START = 9;
+
+
+	public static final int NOTATION_TAG = 20;
+	public static final int NOTATION_CONTENT = 21;
+
+	public static final int ENTITY_TAG = 30;
+	public static final int ENTITY_PARM = 31;
+	public static final int ENTITY_CONTENT = 32;
+
+	public static final int ELEMENT_TAG = 40;
+	public static final int ELEMENT_CONTENT = 41;
+	public static final int CONTENT_EMPTY = 42;
+	public static final int CONTENT_ANY = 43;
+	public static final int CONTENT_PCDATA = 44;
+
+
+	public Token(String type) {
+		super(type);
+	}
+
+	public Token(String type, String text, int line, int charBegin, int length) {
+		super(type, text, line, charBegin, length);
+	}
+
+	public Token createCopy() {
+		Token copy = new Token(getType(), getText(), getStartLine(), getStartOffset(), getLength());
+		return copy;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/tokenizer/Yytoken.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/tokenizer/Yytoken.java
new file mode 100644
index 0000000..65afb52
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/parser/tokenizer/Yytoken.java
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.parser.tokenizer;
+
+class Yytoken {
+	public String m_type;
+	public String m_text;
+	public int m_line;
+	public int m_charBegin;
+	public int m_length;
+
+	Yytoken(String type) {
+		m_type = type;
+	}
+
+	Yytoken(String type, String text, int line, int charBegin, int length) {
+		m_type = type;
+		m_text = new String(text);
+		m_line = line;
+		m_charBegin = charBegin;
+		m_length = length;
+	}
+
+	public String getType() {
+		return m_type;
+	}
+
+	public int getStartLine() {
+		return m_line;
+	}
+
+	public int getStartOffset() {
+		return m_charBegin;
+	}
+
+	public int getEndOffset() {
+		return m_charBegin + m_length;
+	}
+
+	public int getLength() {
+		return m_length;
+	}
+
+	public String getText() {
+		return m_text;
+	}
+
+	public void setStartOffset(int startOffset) {
+		m_charBegin = startOffset;
+	}
+
+	public void updateOffset(int delta) {
+		m_charBegin += delta;
+	}
+
+	public void updateText(String newText) {
+		m_text = newText;
+		m_length = newText.length();
+	}
+
+	public void delete(int start, int length) {
+		int stringStart = start - m_charBegin;
+		String oldString = m_text;
+		m_text = oldString.substring(0, stringStart);
+		m_text += oldString.substring(stringStart + length);
+
+		m_length = m_text.length();
+		System.out.println("new string = " + m_text); //$NON-NLS-1$
+
+	}
+
+	public boolean equals(Yytoken other) {
+		return m_type == other.getType() && m_text.equals(other.getText()) && m_line == other.getStartLine() && m_charBegin == other.getStartOffset() && m_length == other.getLength();
+	}
+
+	public String toString() {
+		return "Text   : " + m_text + "\ntype : " + m_type + "\nline  : " + m_line + "\ncBeg. : " + m_charBegin + "\ncEnd. : " + getEndOffset() + "\ncLength. : " + m_length; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+	}
+}
+
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/text/rules/StructuredTextPartitionerForDTD.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/text/rules/StructuredTextPartitionerForDTD.java
new file mode 100644
index 0000000..c6ee747
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/text/rules/StructuredTextPartitionerForDTD.java
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.text.rules;
+
+import org.eclipse.wst.sse.core.text.rules.StructuredTextPartitioner;
+
+public class StructuredTextPartitionerForDTD extends StructuredTextPartitioner {
+
+	public static final String ST_DTD_DEFAULT = "org.eclipse.wst.dtd.core.default"; //$NON-NLS-1$
+
+	public StructuredTextPartitionerForDTD() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 */
+	public String getDefault() {
+		return ST_DTD_DEFAULT;
+	}
+
+	/* (non-Javadoc)
+	 */
+	protected void initLegalContentTypes() {
+		fSupportedTypes = new String[]{ST_DTD_DEFAULT, ST_UNKNOWN_PARTITION};
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDBatchNodeDelete.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDBatchNodeDelete.java
new file mode 100644
index 0000000..f0c2567
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDBatchNodeDelete.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.dtd.core.DTDFile;
+import org.eclipse.wst.dtd.core.DTDNode;
+
+
+public class DTDBatchNodeDelete {
+
+	protected List nodes = new ArrayList();
+	protected DTDFile dtdFile;
+
+	public DTDBatchNodeDelete(DTDFile dtdFile) {
+		this.dtdFile = dtdFile;
+	}
+
+	public void addNode(DTDNode node) {
+		// first check if the node is contained by anyone
+		for (int i = 0; i < nodes.size(); i++) {
+			DTDNode currentNode = (DTDNode) nodes.get(i);
+
+			if (currentNode.containsRange(node.getStartOffset(), node.getEndOffset())) {
+				// then no need to add the node to the list to be deleted
+				return;
+			}
+
+			if (node.getStartOffset() < currentNode.getStartOffset() && node.getEndOffset() <= currentNode.getStartOffset()) {
+				nodes.add(i, node);
+				return;
+			}
+		}
+		// if we get here, then add it to the end
+		nodes.add(node);
+	}
+
+	public void deleteNodes(Object requestor) {
+		for (int i = nodes.size() - 1; i >= 0; i--) {
+			DTDNode node = (DTDNode) nodes.get(i);
+			dtdFile.deleteNode(requestor, (DTDNode) nodes.get(i));
+		}
+		nodes.clear();
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDExternalReferenceRemover.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDExternalReferenceRemover.java
new file mode 100644
index 0000000..46c93ce
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDExternalReferenceRemover.java
@@ -0,0 +1,141 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.dtd.core.Attribute;
+import org.eclipse.wst.dtd.core.AttributeList;
+import org.eclipse.wst.dtd.core.CMBasicNode;
+import org.eclipse.wst.dtd.core.DTDFile;
+import org.eclipse.wst.dtd.core.DTDNode;
+import org.eclipse.wst.dtd.core.Element;
+import org.eclipse.wst.dtd.core.Entity;
+
+
+/*
+ * This class is responsible for updating the model when items
+ * are deleted or  so that items referenced by it are cleaned up
+ * note that top level nodes are queued up for deletion so that
+ * iteration over the list of nodes from the dtdfile is not messed up.
+ * Note that when an external parmeter entity changes, the client
+ * of the model (e.g. editor) must be a DTDFileListener implementing
+ * the listener's interface to keep the model's referential integrity
+ * (See DTDModelImpl for example).
+ */
+
+public class DTDExternalReferenceRemover extends DTDVisitor {
+
+	public DTDExternalReferenceRemover() {
+
+	}
+
+	protected boolean isUpdating = false;
+
+	protected boolean isParmEntity = false;
+	protected String oldRefName = ""; //$NON-NLS-1$
+	protected Object requestor;
+	protected DTDNode nodeToDelete;
+
+	protected DTDBatchNodeDelete batchDelete;
+	protected List externalElementsAndParmEntities = new ArrayList();
+
+	public synchronized void externalReferenceAboutToChange(Object requestor, Entity entity) {
+		if (isUpdating) {
+			return;
+		}
+		if (!entity.isParameterEntity() || !entity.isExternalEntity()) {
+			// if it is not an external parameter entity, ignore as well
+			return;
+		}
+
+		isUpdating = true;
+		this.requestor = requestor;
+
+		DTDFile dtdFile = entity.getDTDFile();
+		if (batchDelete == null) {
+			batchDelete = new DTDBatchNodeDelete(dtdFile);
+		}
+
+		// See the comment at the head of this file regarding
+		// external parameter entities.    
+		//externalElementsAndParmEntities = dtdFile.getDTDModel().getExternalModels().getElementContentNames(entity.getPublicID(), dtdFile.getDTDModel().resolveID(entity.getPublicID(), entity.getSystemID()));
+
+		visit(dtdFile);
+
+		batchDelete.deleteNodes(requestor);
+
+		isUpdating = false;
+	}
+
+	public boolean isMatchingName(String name) {
+		return externalElementsAndParmEntities.contains(name);
+	}
+
+	public void visitElement(Element element) {
+		String elementName = element.getName();
+		if (isParameterEntityRef(elementName)) {
+			if (isMatchingName(elementName)) {
+				element.setName(requestor, "TempName"); //$NON-NLS-1$
+			}
+		}
+		super.visitElement(element);
+	}
+
+	public void visitAttributeList(AttributeList attList) {
+		super.visitAttributeList(attList);
+		String attListName = attList.getName();
+		if (isParameterEntityRef(attListName)) {
+			if (isMatchingName(attListName)) {
+				attList.setName(requestor, "TempName"); //$NON-NLS-1$
+			}
+		}
+	}
+
+	public void visitAttribute(Attribute attr) {
+		super.visitAttribute(attr);
+		String attrName = attr.getName();
+		String attrType = attr.getType();
+
+		if (isParameterEntityRef(attrName)) {
+			if (isMatchingName(attrName)) {
+				attr.setName(requestor, "TempName"); //$NON-NLS-1$
+			}
+		}
+		if (isParameterEntityRef(attrType)) {
+			if (isMatchingName(attrType)) {
+				attr.setType(requestor, Attribute.CDATA);
+			}
+		}
+	}
+
+	public void visitReference(CMBasicNode node) {
+		super.visitReference(node);
+		String refName = node.getName();
+		if (isMatchingName(refName)) {
+			DTDNode parent = (DTDNode) node.getParentNode();
+			batchDelete.addNode(node);
+			//      parent.delete(requestor, node);
+		}
+	}
+
+	//    public void visitExternalParameterEntityReference(ParameterEntityReference parmEntityRef)
+	//    {
+	//      super.visitExternalParameterEntityReference(parmEntityRef);
+	//      if (isParmEntity && parmEntityRef.getName().equals(oldRefName)) 
+	//      {
+	//        nodesToDelete.add(parmEntityRef);
+	//      }
+	//    }
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDModelUpdater.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDModelUpdater.java
new file mode 100644
index 0000000..d6d7887
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDModelUpdater.java
@@ -0,0 +1,136 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.dtd.core.Attribute;
+import org.eclipse.wst.dtd.core.AttributeList;
+import org.eclipse.wst.dtd.core.CMBasicNode;
+import org.eclipse.wst.dtd.core.DTDFile;
+import org.eclipse.wst.dtd.core.DTDNode;
+import org.eclipse.wst.dtd.core.Element;
+import org.eclipse.wst.dtd.core.Entity;
+import org.eclipse.wst.dtd.core.ParameterEntityReference;
+
+
+// this class is responsible for updating the model when items
+// are deleted or a external parm entity changes so that 
+// items referenced by it are cleaned up
+// note that top level nodes are queued up for deletion so that
+// iteration over the list of nodes from the dtdfile is not messed up
+public class DTDModelUpdater extends DTDVisitor {
+
+	public DTDModelUpdater() {
+
+	}
+
+	protected boolean isUpdating = false;
+
+	protected boolean isParmEntity = false;
+	protected String oldRefName = ""; //$NON-NLS-1$
+	protected Object requestor;
+	protected DTDNode nodeToDelete;
+
+	protected List nodesToDelete = new ArrayList();
+
+	public synchronized void objectAboutToBeDeleted(Object requestor, DTDNode node) {
+		if (isUpdating) {
+			return;
+		}
+		if (!(node instanceof Entity || node instanceof Element)) {
+			// just ignore if it is not one of these
+			return;
+		}
+		if (node instanceof Entity && !((Entity) node).isParameterEntity()) {
+			// if it is not a parameter entity, ignore as well
+			return;
+		}
+
+
+		isUpdating = true;
+		this.requestor = requestor;
+		this.nodeToDelete = node;
+		oldRefName = node.getName();
+		isParmEntity = false;
+		nodesToDelete.clear();
+
+		if (node instanceof Entity) {
+			Entity entity = (Entity) node;
+			isParmEntity = true;
+			oldRefName = "%" + oldRefName + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+		}
+
+		DTDFile dtdFile = node.getDTDFile();
+		visit(dtdFile);
+
+		for (int i = 0; i < nodesToDelete.size(); i++) {
+			dtdFile.deleteNode(requestor, (DTDNode) nodesToDelete.get(i));
+		}
+
+		isUpdating = false;
+	}
+
+	public void visitElement(Element element) {
+		if (isParmEntity) {
+			if (element.getName().equals(oldRefName)) {
+				element.setName(requestor, "TempName"); //$NON-NLS-1$
+			}
+		}
+		super.visitElement(element);
+	}
+
+	public void visitAttributeList(AttributeList attList) {
+		super.visitAttributeList(attList);
+		if (attList.getName().equals(oldRefName)) {
+			if (isParmEntity) {
+				attList.setName(requestor, "TempName"); //$NON-NLS-1$
+			}
+			else {
+				// save up for later deletion
+				nodesToDelete.add(attList);
+			}
+		}
+	}
+
+	public void visitAttribute(Attribute attr) {
+		super.visitAttribute(attr);
+		if (isParmEntity) {
+			if (attr.getName().equals(oldRefName)) {
+				attr.setName(requestor, "TempName"); //$NON-NLS-1$
+			}
+			if (attr.getType().equals(oldRefName)) {
+				attr.setType(requestor, Attribute.CDATA);
+			}
+		}
+		// check the attr name and the attr type to see if it 
+		// needs updating
+	}
+
+	public void visitReference(CMBasicNode node) {
+		super.visitReference(node);
+
+		if (node.getName().equals(oldRefName)) {
+			DTDNode parent = (DTDNode) node.getParentNode();
+			parent.delete(requestor, node);
+		}
+	}
+
+	public void visitExternalParameterEntityReference(ParameterEntityReference parmEntityRef) {
+		super.visitExternalParameterEntityReference(parmEntityRef);
+		if (isParmEntity && parmEntityRef.getName().equals(oldRefName)) {
+			nodesToDelete.add(parmEntityRef);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDNotationReferenceRemover.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDNotationReferenceRemover.java
new file mode 100644
index 0000000..410a30d
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDNotationReferenceRemover.java
@@ -0,0 +1,93 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.util;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.dtd.core.Attribute;
+import org.eclipse.wst.dtd.core.AttributeEnumList;
+import org.eclipse.wst.dtd.core.AttributeList;
+import org.eclipse.wst.dtd.core.DTDFile;
+import org.eclipse.wst.dtd.core.DTDNode;
+import org.eclipse.wst.dtd.core.Entity;
+import org.eclipse.wst.dtd.core.Notation;
+
+
+public class DTDNotationReferenceRemover {
+
+	public DTDNotationReferenceRemover() {
+
+	}
+
+	protected Object requestor;
+	protected Notation notation;
+	protected String notationName;
+
+	public void notationAboutToBeDeleted(Object requestor, Notation notation) {
+		this.requestor = requestor;
+		this.notation = notation;
+		notationName = notation.getName();
+
+		visit(notation.getDTDFile());
+	}
+
+	public void visit(DTDFile file) {
+		List nodes = file.getNodes();
+		for (int i = 0; i < nodes.size(); i++) {
+			DTDNode currentNode = (DTDNode) nodes.get(i);
+			if (currentNode instanceof Entity) {
+				visitEntity((Entity) currentNode);
+			}
+			else if (currentNode instanceof AttributeList) {
+				visitAttributeList((AttributeList) currentNode);
+			}
+		}
+	}
+
+	public void visitEntity(Entity entity) {
+		if (entity.getNotationName().equals(notationName)) {
+			entity.setNotationName(requestor, ""); //$NON-NLS-1$
+		}
+	}
+
+	public void visitAttributeList(AttributeList attList) {
+		Attribute attr = (Attribute) attList.getFirstChild();
+		while (attr != null) {
+			visitAttribute(attr);
+			attr = (Attribute) attr.getNextSibling();
+		}
+	}
+
+	public void visitAttribute(Attribute attr) {
+		if (attr.getType().equals(Attribute.ENUMERATED_NOTATION)) {
+			AttributeEnumList enumList = attr.getEnumList();
+			List notationNames = enumList.getItems();
+			Iterator iter = notationNames.iterator();
+			boolean updateRequired = false;
+			while (iter.hasNext()) {
+				String notation = (String) iter.next();
+				if (notation.equals(notationName)) {
+					updateRequired = true;
+					iter.remove();
+				}
+			}
+			if (updateRequired) {
+				String[] newItems = new String[notationNames.size()];
+				notationNames.toArray(newItems);
+				enumList.setItems(requestor, newItems);
+			}
+		}
+	}
+
+}// DTDNotationRemover
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDReferenceUpdater.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDReferenceUpdater.java
new file mode 100644
index 0000000..9342958
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDReferenceUpdater.java
@@ -0,0 +1,197 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.dtd.core.Attribute;
+import org.eclipse.wst.dtd.core.AttributeEnumList;
+import org.eclipse.wst.dtd.core.AttributeList;
+import org.eclipse.wst.dtd.core.CMBasicNode;
+import org.eclipse.wst.dtd.core.DTDFile;
+import org.eclipse.wst.dtd.core.DTDNode;
+import org.eclipse.wst.dtd.core.Element;
+import org.eclipse.wst.dtd.core.Entity;
+import org.eclipse.wst.dtd.core.Notation;
+import org.eclipse.wst.dtd.core.ParameterEntityReference;
+
+
+// this class is responsible for updating any dtd node in
+// response to a change in the node that they reference
+public class DTDReferenceUpdater extends DTDVisitor {
+
+	public DTDReferenceUpdater() {
+
+	}
+
+	protected boolean isUpdating = false;
+
+	protected boolean isParmEntity = false;
+	protected boolean isNotation = false;
+	protected String oldRefName = "", newRefName = ""; //$NON-NLS-1$ //$NON-NLS-2$
+	protected String newName = ""; //$NON-NLS-1$
+	protected Object requestor;
+	protected DTDNode referencedNode = null;
+
+	public synchronized void nameAboutToChange(Object requestor, DTDNode referencedNode, String newName) {
+		if (isUpdating) {
+			return;
+		}
+		if (!(referencedNode instanceof Entity || referencedNode instanceof Element || referencedNode instanceof Notation)) {
+			// just ignore if it is not one of these
+			return;
+		}
+		if (referencedNode instanceof Entity && !((Entity) referencedNode).isParameterEntity()) {
+			// if it is not a parameter entity, ignore as well
+			return;
+		}
+
+		isUpdating = true;
+		this.requestor = requestor;
+		oldRefName = referencedNode.getName();
+		this.newName = newRefName = newName;
+		isParmEntity = false;
+		isNotation = referencedNode instanceof Notation;
+
+		if (referencedNode instanceof Entity) {
+			Entity entity = (Entity) referencedNode;
+			isParmEntity = true;
+			oldRefName = "%" + oldRefName + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+			newRefName = "%" + newRefName + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+		}
+
+		if (this.referencedNode != null) {
+			// check if the previous referenced node that was changed
+			// is the same as the one that is coming in.  if so, just
+			// change the previous regions
+			if (this.referencedNode == referencedNode) {
+				quickUpdate();
+				isUpdating = false;
+				return;
+			}
+		}
+
+		// clear the cache if we get here
+		this.referencedNode = referencedNode;
+		references.clear();
+		DTDFile dtdFile = referencedNode.getDTDFile();
+		visit(dtdFile);
+		isUpdating = false;
+	}
+
+	public void visitElement(Element element) {
+		if (isParmEntity) {
+			if (element.getName().equals(oldRefName)) {
+				element.setName(requestor, newRefName);
+				references.add(element);
+			}
+		}
+		super.visitElement(element);
+	}
+
+	public void visitAttributeList(AttributeList attList) {
+		if (!isNotation && attList.getName().equals(oldRefName)) {
+			attList.setName(requestor, newRefName);
+			references.add(attList);
+		}
+		super.visitAttributeList(attList);
+	}
+
+	public void visitAttribute(Attribute attr) {
+		super.visitAttribute(attr);
+		if (isParmEntity) {
+			// check the attr name and the attr type to see if it 
+			// needs updating
+			if (attr.getName().equals(oldRefName)) {
+				attr.setName(requestor, newRefName);
+				references.add(attr);
+			}
+			if (attr.getType().equals(oldRefName)) {
+				attr.setType(requestor, newRefName);
+				references.add(attr);
+			}
+		}
+		else if (isNotation && attr.getType().equals(Attribute.ENUMERATED_NOTATION)) {
+			AttributeEnumList enumList = attr.getEnumList();
+			List items = enumList.getItems();
+			boolean updateNeeded = false;
+			for (int i = 0; i < items.size(); i++) {
+				String notationName = (String) items.get(i);
+				if (notationName.equals(oldRefName)) {
+					updateNeeded = true;
+					items.set(i, newName);
+				}
+			}
+			if (updateNeeded) {
+				String[] newItems = new String[items.size()];
+
+				enumList.setItems((String[]) items.toArray(newItems));
+			}
+		}
+
+	}
+
+	public void visitReference(CMBasicNode node) {
+		super.visitReference(node);
+		if (isParameterEntityRef(oldRefName) && !isParmEntity) {
+			return;
+		}
+
+		if (node.getName().equals(oldRefName)) {
+			node.setName(requestor, newRefName);
+			references.add(node);
+		}
+	}
+
+	public void visitExternalParameterEntityReference(ParameterEntityReference parmEntityRef) {
+		super.visitExternalParameterEntityReference(parmEntityRef);
+		if (parmEntityRef.getName().equals(oldRefName)) {
+			parmEntityRef.setReferencedEntity(requestor, newName);
+			references.add(parmEntityRef);
+		}
+	}
+
+	public void clearCache() {
+		referencedNode = null;
+		references.clear();
+	}
+
+	// the references List is a cache of the DTDNodes that are changed
+	// as a result of a call to nameAboutToChange().  The idea is that
+	// if a subsequent call comes in that changes the name of the same 
+	// object for which this cache exists for, then we optimize the 
+	// path by just walking the cache
+	private List references = new ArrayList();
+
+	protected void quickUpdate() {
+		for (int i = 0; i < references.size(); i++) {
+			DTDNode node = (DTDNode) references.get(i);
+			if (node instanceof Element) {
+				visitElement((Element) node);
+			}
+			else if (node instanceof AttributeList) {
+				visitAttributeList((AttributeList) node);
+			}
+			else if (node instanceof Attribute) {
+				visitAttribute((Attribute) node);
+			}
+			else if (node instanceof CMBasicNode) {
+				visitReference((CMBasicNode) node);
+			}
+			else if (node instanceof ParameterEntityReference) {
+				visitExternalParameterEntityReference((ParameterEntityReference) node);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDSAXParser.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDSAXParser.java
new file mode 100644
index 0000000..8e9b6d7
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDSAXParser.java
@@ -0,0 +1,156 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.SAXParser;
+
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+
+/**
+ * TODO: Kihup and Nitin, reevaluate the use and implementation of this class
+ */
+
+//import org.apache.xerces.parsers.SAXParser;
+//import org.apache.xerces.xni.Augmentations;
+//import org.apache.xerces.xni.XMLLocator;
+//import org.apache.xerces.xni.XMLString;
+//import org.apache.xerces.xni.XNIException;
+public class DTDSAXParser extends SAXParser {
+
+	private List ignoredEntityRefs = new ArrayList();
+
+	//  private XMLLocator locator;
+	//
+	public List getIgnoredEntityRefs() {
+		return ignoredEntityRefs;
+	}
+
+	//
+	//  public XMLLocator getLocator()
+	//  {
+	//    return locator;
+	//  }
+	//
+	//  public void startDocument
+	//    (XMLLocator locator, 
+	//     String encoding, 
+	//     Augmentations augs) 
+	//  {
+	//    this.locator = locator;
+	//    super.startDocument(locator,encoding,augs); 
+	//  }
+	//
+	//  public void ignoredCharacters(XMLString text, Augmentations augs)
+	//    throws XNIException
+	//  {
+	//    String s = 
+	//      text.length > 0 ? new String(text.ch,text.offset,text.length) : "";
+	//    //System.out.println("ignoredCharacters: " + s);
+	//
+	//    StringTokenizer tokenizer = new StringTokenizer(s,";");
+	//    try
+	//    {
+	//      String token = null;
+	//      while (tokenizer.hasMoreTokens())
+	//      {
+	//        token = tokenizer.nextToken();
+	//        if (isEntityRef(token))
+	//          registerEntityRef(token);
+	//      }
+	//    }
+	//    catch (NoSuchElementException e)
+	//    {
+	//      e.printStackTrace();
+	//    }
+	//  }
+	//
+	private boolean isEntityRef(String token) {
+		// Looking for the pattern "nnnn%nnnnn".
+		if (token.indexOf('%') != -1)
+			return true; // candidate for entity reference
+		else
+			return false;
+	}
+
+	//
+	private void registerEntityRef(String token) {
+		int index = token.lastIndexOf('%');
+		if (index == -1)
+			return;
+
+		String refName = token.substring(index, token.length());
+		//System.out.println("entity ref name is: " + refName);
+		if (refName.indexOf(' ') != -1 || refName.indexOf('\t') != -1 || refName.indexOf('\n') != -1)
+			return;
+		else
+			// we found entity reference
+			ignoredEntityRefs.add(refName + ";"); //$NON-NLS-1$
+	}
+
+
+	/* (non-Javadoc)
+	 * @see javax.xml.parsers.SAXParser#getParser()
+	 */
+	public Parser getParser() throws SAXException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.xml.parsers.SAXParser#getProperty(java.lang.String)
+	 */
+	public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.xml.parsers.SAXParser#getXMLReader()
+	 */
+	public XMLReader getXMLReader() throws SAXException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.xml.parsers.SAXParser#isNamespaceAware()
+	 */
+	public boolean isNamespaceAware() {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.xml.parsers.SAXParser#isValidating()
+	 */
+	public boolean isValidating() {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.xml.parsers.SAXParser#setProperty(java.lang.String, java.lang.Object)
+	 */
+	public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
+		// TODO Auto-generated method stub
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDVisitor.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDVisitor.java
new file mode 100644
index 0000000..4118feb
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/DTDVisitor.java
@@ -0,0 +1,108 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.util;
+
+import java.util.List;
+
+import org.eclipse.wst.dtd.core.Attribute;
+import org.eclipse.wst.dtd.core.AttributeList;
+import org.eclipse.wst.dtd.core.CMBasicNode;
+import org.eclipse.wst.dtd.core.CMGroupNode;
+import org.eclipse.wst.dtd.core.CMNode;
+import org.eclipse.wst.dtd.core.DTDFile;
+import org.eclipse.wst.dtd.core.DTDNode;
+import org.eclipse.wst.dtd.core.Element;
+import org.eclipse.wst.dtd.core.ParameterEntityReference;
+
+
+public class DTDVisitor {
+
+	public DTDVisitor() {
+
+	}
+
+	public void visit(DTDFile file) {
+		List nodes = file.getNodes();
+		for (int i = 0; i < nodes.size(); i++) {
+			DTDNode currentNode = (DTDNode) nodes.get(i);
+			if (currentNode instanceof Element) {
+				visitElement((Element) currentNode);
+			}
+			else if (currentNode instanceof AttributeList) {
+				visitAttributeList((AttributeList) currentNode);
+			}
+			else if (currentNode instanceof ParameterEntityReference) {
+				visitExternalParameterEntityReference((ParameterEntityReference) currentNode);
+			}
+		}
+	}
+
+	public void visitElement(Element element) {
+		CMNode content = element.getContentModel();
+		visitContentNode(content);
+		visitAttributes(element.getElementAttributes());
+	}
+
+	public void visitAttributeList(AttributeList attList) {
+		// note that we don't visit attributes here because we
+		// want the element to visit them with it's consolidated list
+		// that it creates by gathering all attribute lists together
+	}
+
+	public void visitAttributes(List attributes) {
+		int size = attributes.size();
+		for (int i = 0; i < size; i++) {
+			Attribute attr = (Attribute) attributes.get(i);
+			visitAttribute(attr);
+		}
+	}
+
+	public void visitAttribute(Attribute attr) {
+	}
+
+	public void visitContentNode(CMNode content) {
+		if (content instanceof CMBasicNode) {
+			CMBasicNode basicNode = (CMBasicNode) content;
+			if (basicNode.isReference()) {
+				visitReference(basicNode);
+			}
+		}
+		else if (content instanceof CMGroupNode) {
+			visitGroupNode((CMGroupNode) content);
+		}
+	}
+
+	public void visitGroupNode(CMGroupNode group) {
+		List children = group.getChildrenList();
+		int size = children.size();
+		for (int i = 0; i < size; i++) {
+			visitContentNode((CMNode) children.get(i));
+		}
+	}
+
+	public void visitReference(CMBasicNode node) {
+	}
+
+	public void visitExternalParameterEntityReference(ParameterEntityReference parmEntityRef) {
+	}
+
+	// utility method
+	public boolean isParameterEntityRef(String reference) {
+		if (reference.length() > 0) {
+			return reference.charAt(0) == '%' && reference.charAt(reference.length() - 1) == ';';
+		}
+		return false;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/LabelValuePair.java b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/LabelValuePair.java
new file mode 100644
index 0000000..f85f6b8
--- /dev/null
+++ b/bundles/org.eclipse.wst.dtd.core/src/org/eclipse/wst/dtd/core/util/LabelValuePair.java
@@ -0,0 +1,30 @@
+/*
+* Copyright (c) 2002 IBM Corporation and others.
+* All rights reserved.   This program and the accompanying materials
+* are made available under the terms of the Common Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/cpl-v10.html
+* 
+* Contributors:
+*   IBM - Initial API and implementation
+*   Jens Lukowski/Innoopract - initial renaming/restructuring
+* 
+*/
+package org.eclipse.wst.dtd.core.util;
+
+import org.eclipse.jface.util.Assert;
+
+public class LabelValuePair {
+
+	public String fLabel;
+	public Object fValue;
+
+	/**
+	 * Creates a new name/value item
+	 */
+	public LabelValuePair(String label, Object value) {
+		Assert.isTrue(label != null);
+		fLabel = label;
+		fValue = value;
+	}
+}