Snapshot of commit d5ec1d5018ed24f1b4f32b1d09df6dbd7e2fc425

from branch master of git://git.jetbrains.org/idea/community.git
diff --git a/xml/impl/resources/com/intellij/codeInsight/completion/XmlNameCompletionConfidence.java b/xml/impl/resources/com/intellij/codeInsight/completion/XmlNameCompletionConfidence.java
new file mode 100644
index 0000000..77a54ec
--- /dev/null
+++ b/xml/impl/resources/com/intellij/codeInsight/completion/XmlNameCompletionConfidence.java
@@ -0,0 +1,25 @@
+package com.intellij.codeInsight.completion;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.ThreeState;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author peter
+ */
+public class XmlNameCompletionConfidence extends CompletionConfidence{
+  @NotNull
+  @Override
+  public ThreeState shouldFocusLookup(@NotNull CompletionParameters parameters) {
+    final ASTNode node = parameters.getPosition().getNode();
+    if (node == null) return ThreeState.UNSURE;
+
+    final IElementType elementType = node.getElementType();
+    if (elementType == XmlTokenType.XML_NAME || elementType == XmlTokenType.XML_TAG_NAME) {
+      return ThreeState.YES;
+    }
+    return ThreeState.UNSURE;
+  }
+}
diff --git a/xml/impl/resources/inspectionDescriptions/CheckDtdRefs.html b/xml/impl/resources/inspectionDescriptions/CheckDtdRefs.html
new file mode 100644
index 0000000..cb613ce
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/CheckDtdRefs.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<font face="verdana" size="-1">Checks consistency of <b>DTD</b> specific references, e.g. references to XML entity or to DTD element declaration.
+  The validation works in DTD or XML file types.<br>
+</font>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/CheckEmptyScriptTag.html b/xml/impl/resources/inspectionDescriptions/CheckEmptyScriptTag.html
new file mode 100644
index 0000000..4b748cd
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/CheckEmptyScriptTag.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+<font face="verdana" size="-1">Reports empty tags (like <b>script</b>) that do not work in some browsers.
+  The validation works in html or jsp file types.<br>
+</font>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/CheckImageSize.html b/xml/impl/resources/inspectionDescriptions/CheckImageSize.html
new file mode 100644
index 0000000..9f9bcb0
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/CheckImageSize.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection highlights <b>width</b> and <b>height</b> attribute values of <b>IMG</b> tag
+  that are different from the width and height of the original image.<br>
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/CheckTagEmptyBody.html b/xml/impl/resources/inspectionDescriptions/CheckTagEmptyBody.html
new file mode 100644
index 0000000..f4f4305
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/CheckTagEmptyBody.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<font face="verdana" size="-1">Reports <b>empty</b> tag body.
+  The validation works in XML / JSP / JSPX / HTML/ XHTML file types.<br>
+</font>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/CheckValidXmlInScriptTagBody.html b/xml/impl/resources/inspectionDescriptions/CheckValidXmlInScriptTagBody.html
new file mode 100644
index 0000000..ae12a39
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/CheckValidXmlInScriptTagBody.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection checks that the <b>script</b> tag content is valid XML.<br>
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/CheckXmlFileWithXercesValidator.html b/xml/impl/resources/inspectionDescriptions/CheckXmlFileWithXercesValidator.html
new file mode 100644
index 0000000..4d9a080
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/CheckXmlFileWithXercesValidator.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<font face="verdana" size="-1">Thoroughly checks XML files for DTD / schema compliance using Xerces validator.
+  The validation works in XML or XHTML file types.<br>
+</font>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/HtmlDeprecatedTag.html b/xml/impl/resources/inspectionDescriptions/HtmlDeprecatedTag.html
new file mode 100644
index 0000000..42f98ca
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/HtmlDeprecatedTag.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection highlights deprecated HTML tags and provides ability to replace them with CSS or with other tags for some of them.<br>
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/HtmlExtraClosingTag.html b/xml/impl/resources/inspectionDescriptions/HtmlExtraClosingTag.html
new file mode 100644
index 0000000..3a2cc85
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/HtmlExtraClosingTag.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection spots extra closing tag for the empty elements like IMG or BR.<br>
+</font>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/HtmlFormInputWithoutLabel.html b/xml/impl/resources/inspectionDescriptions/HtmlFormInputWithoutLabel.html
new file mode 100644
index 0000000..680c983
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/HtmlFormInputWithoutLabel.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection highlights form elements without required associated label and provides ability to create a new label.<br>
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/HtmlNonExistentInternetResource.html b/xml/impl/resources/inspectionDescriptions/HtmlNonExistentInternetResource.html
new file mode 100644
index 0000000..67b9ac9
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/HtmlNonExistentInternetResource.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<font face="verdana" size="-1">
+This inspection highlights links to non-existent web resources.
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/HtmlPathReference.html b/xml/impl/resources/inspectionDescriptions/HtmlPathReference.html
new file mode 100644
index 0000000..54d0ed0
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/HtmlPathReference.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Highlights unresolved file references in HTML.
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/HtmlPresentationalElement.html b/xml/impl/resources/inspectionDescriptions/HtmlPresentationalElement.html
new file mode 100644
index 0000000..3a0609a
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/HtmlPresentationalElement.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection highlights pure presentational HTML tags and provides ability to replace them with CSS or with other tags.<br>
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/HtmlUnknownAttribute.html b/xml/impl/resources/inspectionDescriptions/HtmlUnknownAttribute.html
new file mode 100644
index 0000000..6cf45ee
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/HtmlUnknownAttribute.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection highlights unknown HTML tag attributes as invalid, and lets mark such attributes as Custom to avoid highlighting them as invalid.<br>
+</font>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/HtmlUnknownTag.html b/xml/impl/resources/inspectionDescriptions/HtmlUnknownTag.html
new file mode 100644
index 0000000..afa4948
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/HtmlUnknownTag.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection highlights unknown HTML tags, and lets mark such tags as Custom to avoid highlighting them as unknown in future.<br>
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/HtmlUnknownTarget.html b/xml/impl/resources/inspectionDescriptions/HtmlUnknownTarget.html
new file mode 100644
index 0000000..506b1d6
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/HtmlUnknownTarget.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection checks unresolved file references in HTML.<br>
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/RequiredAttributes.html b/xml/impl/resources/inspectionDescriptions/RequiredAttributes.html
new file mode 100644
index 0000000..2011632
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/RequiredAttributes.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection reports XML/HTML tags with missing mandatory attributes.
+  You can specify attribute names that should not be reported. 
+</font>
+</body>
+</html>
diff --git a/xml/impl/resources/inspectionDescriptions/XmlDuplicatedId.html b/xml/impl/resources/inspectionDescriptions/XmlDuplicatedId.html
new file mode 100644
index 0000000..99c6e61
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/XmlDuplicatedId.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection checks for duplicate "id" attributes in XML.
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/XmlHighlighting.html b/xml/impl/resources/inspectionDescriptions/XmlHighlighting.html
new file mode 100644
index 0000000..e3c9068
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/XmlHighlighting.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Highlights XML validation problems in the results of batch code inspection.
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/XmlPathReference.html b/xml/impl/resources/inspectionDescriptions/XmlPathReference.html
new file mode 100644
index 0000000..94c9e12
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/XmlPathReference.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Highlights unresolved file references in XML.
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/XmlUnboundNsPrefix.html b/xml/impl/resources/inspectionDescriptions/XmlUnboundNsPrefix.html
new file mode 100644
index 0000000..2821e9f
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/XmlUnboundNsPrefix.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection checks for unbound namespace prefixes in XML
+</font>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/XmlUnusedNamespaceDeclaration.html b/xml/impl/resources/inspectionDescriptions/XmlUnusedNamespaceDeclaration.html
new file mode 100644
index 0000000..7722c64
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/XmlUnusedNamespaceDeclaration.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<span style="font-family: verdana,serif; font-size: smaller;">
+  Checks for unused namespace declarations and location hints in XML
+</span>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/inspectionDescriptions/XmlWrongRootElement.html b/xml/impl/resources/inspectionDescriptions/XmlWrongRootElement.html
new file mode 100644
index 0000000..81bf01c
--- /dev/null
+++ b/xml/impl/resources/inspectionDescriptions/XmlWrongRootElement.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<font face="verdana" size="-1">This inspection checks if root tag name is the same as in &lt;doctype&gt;.<br>
+</font>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/intentionDescriptions/AddSchemaPrefixIntention/after.xml.template b/xml/impl/resources/intentionDescriptions/AddSchemaPrefixIntention/after.xml.template
new file mode 100644
index 0000000..e46b614
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/AddSchemaPrefixIntention/after.xml.template
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<<spot>xs</spot>:schema targetNamespace="http://mySchema"
+        xmlns:<spot>xs</spot>="http://www.w3.org/2001/XMLSchema"
+        xmlns:my="http://mySchema">
+
+    <<spot>xs</spot>:element name="myElement" type="my:TYPE"/>
+    <<spot>xs</spot>:simpleType name="TYPE" id="TYPE">
+        <<spot>xs</spot>:restriction base="<spot>xs</spot>:integer">
+            <<spot>xs</spot>:minInclusive value="0" id="nonNegativeInteger.minInclusive"/>
+        </<spot>xs</spot>:restriction>
+    </<spot>xs</spot>:simpleType>
+</<spot>xs</spot>:schema>
diff --git a/xml/impl/resources/intentionDescriptions/AddSchemaPrefixIntention/before.xml.template b/xml/impl/resources/intentionDescriptions/AddSchemaPrefixIntention/before.xml.template
new file mode 100644
index 0000000..2e2b85a
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/AddSchemaPrefixIntention/before.xml.template
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema targetNamespace="http://mySchema"
+        <spot>xmlns</spot>="http://www.w3.org/2001/XMLSchema"
+        xmlns:my="http://mySchema">
+
+    <element name="myElement" type="my:TYPE"/>
+    <simpleType name="TYPE" id="TYPE">
+        <restriction base="integer">
+            <minInclusive value="0" id="nonNegativeInteger.minInclusive"/>
+        </restriction>
+    </simpleType>
+</schema>
diff --git a/xml/impl/resources/intentionDescriptions/AddSchemaPrefixIntention/description.html b/xml/impl/resources/intentionDescriptions/AddSchemaPrefixIntention/description.html
new file mode 100644
index 0000000..c0094d0
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/AddSchemaPrefixIntention/description.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<span style="font-family: verdana,serif; font-size: smaller;">Inserts namespace prefix</span>
+</body>
+</html>
diff --git a/xml/impl/resources/intentionDescriptions/AddXsiSchemaLocationForExtResourceAction/after.xml.template b/xml/impl/resources/intentionDescriptions/AddXsiSchemaLocationForExtResourceAction/after.xml.template
new file mode 100644
index 0000000..b50cd04
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/AddXsiSchemaLocationForExtResourceAction/after.xml.template
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+        <spot>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd"</spot>>
+          
+</schema>
\ No newline at end of file
diff --git a/xml/impl/resources/intentionDescriptions/AddXsiSchemaLocationForExtResourceAction/before.xml.template b/xml/impl/resources/intentionDescriptions/AddXsiSchemaLocationForExtResourceAction/before.xml.template
new file mode 100644
index 0000000..e9667d7
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/AddXsiSchemaLocationForExtResourceAction/before.xml.template
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema xmlns="<spot>http://www.w3.org/2001/XMLSchema</spot>">
+
+</schema>
\ No newline at end of file
diff --git a/xml/impl/resources/intentionDescriptions/AddXsiSchemaLocationForExtResourceAction/description.html b/xml/impl/resources/intentionDescriptions/AddXsiSchemaLocationForExtResourceAction/description.html
new file mode 100644
index 0000000..5742887
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/AddXsiSchemaLocationForExtResourceAction/description.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Adds xsi:schemaLocation attribute.
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/intentionDescriptions/ConvertSchemaPrefixToDefaultIntention/after.xml.template b/xml/impl/resources/intentionDescriptions/ConvertSchemaPrefixToDefaultIntention/after.xml.template
new file mode 100644
index 0000000..2e2b85a
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/ConvertSchemaPrefixToDefaultIntention/after.xml.template
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema targetNamespace="http://mySchema"
+        <spot>xmlns</spot>="http://www.w3.org/2001/XMLSchema"
+        xmlns:my="http://mySchema">
+
+    <element name="myElement" type="my:TYPE"/>
+    <simpleType name="TYPE" id="TYPE">
+        <restriction base="integer">
+            <minInclusive value="0" id="nonNegativeInteger.minInclusive"/>
+        </restriction>
+    </simpleType>
+</schema>
diff --git a/xml/impl/resources/intentionDescriptions/ConvertSchemaPrefixToDefaultIntention/before.xml.template b/xml/impl/resources/intentionDescriptions/ConvertSchemaPrefixToDefaultIntention/before.xml.template
new file mode 100644
index 0000000..e46b614
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/ConvertSchemaPrefixToDefaultIntention/before.xml.template
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<<spot>xs</spot>:schema targetNamespace="http://mySchema"
+        xmlns:<spot>xs</spot>="http://www.w3.org/2001/XMLSchema"
+        xmlns:my="http://mySchema">
+
+    <<spot>xs</spot>:element name="myElement" type="my:TYPE"/>
+    <<spot>xs</spot>:simpleType name="TYPE" id="TYPE">
+        <<spot>xs</spot>:restriction base="<spot>xs</spot>:integer">
+            <<spot>xs</spot>:minInclusive value="0" id="nonNegativeInteger.minInclusive"/>
+        </<spot>xs</spot>:restriction>
+    </<spot>xs</spot>:simpleType>
+</<spot>xs</spot>:schema>
diff --git a/xml/impl/resources/intentionDescriptions/ConvertSchemaPrefixToDefaultIntention/description.html b/xml/impl/resources/intentionDescriptions/ConvertSchemaPrefixToDefaultIntention/description.html
new file mode 100644
index 0000000..6bc2fed
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/ConvertSchemaPrefixToDefaultIntention/description.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<span style="font-family: verdana,serif; font-size: smaller;">Removes selected namespace prefix</span>
+</body>
+</html>
diff --git a/xml/impl/resources/intentionDescriptions/ManuallySetupExtResourceAction/after.xml.template b/xml/impl/resources/intentionDescriptions/ManuallySetupExtResourceAction/after.xml.template
new file mode 100644
index 0000000..731cb77
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/ManuallySetupExtResourceAction/after.xml.template
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation=<spot>"http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd"</spot>>
+
+</schema>
diff --git a/xml/impl/resources/intentionDescriptions/ManuallySetupExtResourceAction/before.xml.template b/xml/impl/resources/intentionDescriptions/ManuallySetupExtResourceAction/before.xml.template
new file mode 100644
index 0000000..8cf142f
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/ManuallySetupExtResourceAction/before.xml.template
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation=<spot>"http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd"</spot>>
+
+</schema>
\ No newline at end of file
diff --git a/xml/impl/resources/intentionDescriptions/ManuallySetupExtResourceAction/description.html b/xml/impl/resources/intentionDescriptions/ManuallySetupExtResourceAction/description.html
new file mode 100644
index 0000000..960e034
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/ManuallySetupExtResourceAction/description.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Allows to map given namespace to an XML schema file (DTD or XSD).
+</body>
+</html>
diff --git a/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/after.xml.template b/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/after.xml.template
new file mode 100644
index 0000000..c01695f
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/after.xml.template
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+    <tag attr="<spot>abcdef</spot>"/>
+</root>
diff --git a/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/before.xml.template b/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/before.xml.template
new file mode 100644
index 0000000..187344c
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/before.xml.template
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+    <tag attr="<spot>123456</spot>"/>
+</root>
\ No newline at end of file
diff --git a/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/description.html b/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/description.html
new file mode 100644
index 0000000..18345fe
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/description.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Allows to call Color Chooser for attributes
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/intentionDescriptions/XmlSplitTagAction/after.html.template b/xml/impl/resources/intentionDescriptions/XmlSplitTagAction/after.html.template
new file mode 100644
index 0000000..7a1a0b6
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/XmlSplitTagAction/after.html.template
@@ -0,0 +1,6 @@
+<html>
+<body>
+<p>this tag should be <spot></p>
+<p></spot>splitted at caret position</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/intentionDescriptions/XmlSplitTagAction/before.html.template b/xml/impl/resources/intentionDescriptions/XmlSplitTagAction/before.html.template
new file mode 100644
index 0000000..c24ed93
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/XmlSplitTagAction/before.html.template
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p>this tag should be <spot></spot>splitted at caret position</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/xml/impl/resources/intentionDescriptions/XmlSplitTagAction/description.html b/xml/impl/resources/intentionDescriptions/XmlSplitTagAction/description.html
new file mode 100644
index 0000000..f3afa2c
--- /dev/null
+++ b/xml/impl/resources/intentionDescriptions/XmlSplitTagAction/description.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+This intention splits current tag at caret position<br><br>
+</body>
+</html>
diff --git a/xml/impl/resources/liveTemplates/html_xml.xml b/xml/impl/resources/liveTemplates/html_xml.xml
new file mode 100644
index 0000000..4d5626d
--- /dev/null
+++ b/xml/impl/resources/liveTemplates/html_xml.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templateSet group="html/xml">
+  <template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.tag.pair" 
+      name="t" toReformat="true" toShortenFQNames="true" value="&lt;$TAG$ $ATTRS$&gt;$END$&lt;/$TAG_NAME$&gt;">
+    <variable name="TAG" expression="" defaultValue="" alwaysStopAt="true" />
+    <variable name="ATTRS" expression="" defaultValue="&quot;&quot;" alwaysStopAt="false" />
+    <variable name="TAG_NAME" expression="firstWord(TAG)" defaultValue="&quot;&quot;" alwaysStopAt="false" />
+    <context>
+      <option name="JAVA_CODE" value="false" />
+      <option name="JAVA_COMMENT" value="true" />
+      <option name="JAVA_STRING" value="false" />
+      <option name="XML" value="true" />
+      <option name="HTML" value="true" />
+      <option name="JSP" value="true" />
+      <option name="COMPLETION" value="false" />
+      <option name="OTHER" value="false" />
+    </context>
+  </template>
+  <template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.tag"
+    name="T" toReformat="true" toShortenFQNames="true" value="&lt;$TAG$&gt;$SELECTION$&lt;/$TAGNAME$&gt;&#13;&#10;">
+    <variable name="TAG" expression="" defaultValue="" alwaysStopAt="true" />
+    <variable name="SELECTION" expression="" defaultValue="" alwaysStopAt="false" />
+    <variable name="TAGNAME" expression="firstWord(TAG)" defaultValue="&quot;&quot;" alwaysStopAt="false" />
+    <context>
+      <option name="JAVA_CODE" value="false" />
+      <option name="JAVA_COMMENT" value="false" />
+      <option name="JAVA_STRING" value="false" />
+      <option name="XML" value="true" />
+      <option name="HTML" value="false" />
+      <option name="JSP" value="false" />
+      <option name="COMPLETION" value="false" />
+      <option name="OTHER" value="false" />
+    </context>
+  </template>
+  <template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.tag.in.htmlorjsp"
+    name="T2" toReformat="false" toShortenFQNames="false" value="&lt;$TAG$&gt;$SELECTION$&lt;/$TAGNAME$&gt;">
+    <variable name="TAG" expression="" defaultValue="" alwaysStopAt="true" />
+    <variable name="SELECTION" expression="" defaultValue="" alwaysStopAt="false" />
+    <variable name="TAGNAME" expression="firstWord(TAG)" defaultValue="&quot;&quot;" alwaysStopAt="false" />
+    <context>
+      <option name="JAVA_CODE" value="false" />
+      <option name="JAVA_COMMENT" value="false" />
+      <option name="JAVA_STRING" value="false" />
+      <option name="XML" value="false" />
+      <option name="HTML" value="true" />
+      <option name="JSP" value="true" />
+      <option name="COMPLETION" value="false" />
+      <option name="OTHER" value="false" />
+    </context>
+  </template>
+  <template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.cdata.in.xmlorhtmlorjsp"
+    name="CD" toReformat="false" toShortenFQNames="false" value="&lt;![CDATA[&#10;$SELECTION$&#10;]]&gt;">
+    <variable name="SELECTION" expression="" defaultValue="" alwaysStopAt="false" />
+    <context>
+      <option name="JAVA_CODE" value="false" />
+      <option name="JAVA_COMMENT" value="false" />
+      <option name="JAVA_STRING" value="false" />
+      <option name="XML" value="true" />
+      <option name="HTML" value="true" />
+      <option name="JSP" value="true" />
+      <option name="COMPLETION" value="false" />
+      <option name="OTHER" value="false" />
+    </context>
+  </template>
+</templateSet>
+
diff --git a/xml/impl/resources/liveTemplates/zen_html.xml b/xml/impl/resources/liveTemplates/zen_html.xml
new file mode 100644
index 0000000..43025dc
--- /dev/null
+++ b/xml/impl/resources/liveTemplates/zen_html.xml
@@ -0,0 +1,766 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templateSet group="Zen HTML">
+  <template description="" name="html:xs" toReformat="true" toShortenFQNames="true" value="&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;&#10;&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;$ENV_LANG$&quot;&gt;&#10;&lt;head&gt;&#10;  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=UTF-8&quot; /&gt;&#10;  &lt;title&gt;&lt;/title&gt;&#10;&lt;/head&gt;&#10;&lt;body&gt;&#10;  $END$&#10;&lt;/body&gt;&#10;&lt;/html&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;en&quot;" expression="" name="ENV_LANG"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="html:4t" toReformat="true" toShortenFQNames="true" value="&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;&#10;&lt;html lang=&quot;$ENV_LANG$&quot;&gt;&#10;&lt;head&gt;&#10;  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=UTF-8&quot;&gt;&#10;  &lt;title&gt;&lt;/title&gt;&#10;&lt;/head&gt;&#10;&lt;body&gt;&#10;  $END$&#10;&lt;/body&gt;&#10;&lt;/html&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;en&quot;" expression="" name="ENV_LANG"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="cc:ie6" toReformat="true" toShortenFQNames="true" value="&lt;!--[if lte IE 6]&gt;&#10;  $END$&#10;&lt;![endif]--&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="html:4s" toReformat="true" toShortenFQNames="true" value="&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt;&#10;&lt;html lang=&quot;$ENV_LANG$&quot;&gt;&#10;&lt;head&gt;&#10;  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=UTF-8&quot;&gt;&#10;  &lt;title&gt;&lt;/title&gt;&#10;&lt;/head&gt;&#10;&lt;body&gt;&#10;  $END$&#10;&lt;/body&gt;&#10;&lt;/html&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;en&quot;" expression="" name="ENV_LANG"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="cc:noie" toReformat="true" toShortenFQNames="true" value="&lt;!--[if !IE]&gt;&lt;!--&gt;&#10;  $END$&#10;&lt;!--&lt;![endif]--&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="html:5" toReformat="true" toShortenFQNames="true" value="&lt;!DOCTYPE HTML&gt;&#10;&lt;html lang=&quot;$ENV_LOCALE$&quot;&gt;&#10;&lt;head&gt;&#10;  &lt;meta charset=&quot;UTF-8&quot;&gt;&#10;  &lt;title&gt;&lt;/title&gt;&#10;&lt;/head&gt;&#10;&lt;body&gt;&#10;  $END$&#10;&lt;/body&gt;&#10;&lt;/html&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;en-US&quot;" expression="" name="ENV_LOCALE"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="cc:ie" toReformat="true" toShortenFQNames="true" value="&lt;!--[if IE]&gt;&#10;  $END$&#10;&lt;![endif]--&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="html:xt" toReformat="true" toShortenFQNames="true" value="&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;&#10;&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;$ENV_LANG$&quot;&gt;&#10;&lt;head&gt;&#10;  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=UTF-8&quot; /&gt;&#10;  &lt;title&gt;&lt;/title&gt;&#10;&lt;/head&gt;&#10;&lt;body&gt;&#10;  $END$&#10;&lt;/body&gt;&#10;&lt;/html&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;en&quot;" expression="" name="ENV_LANG"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="html:xxs" toReformat="true" toShortenFQNames="true" value="&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.1//EN&quot; &quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd&quot;&gt;&#10;&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;$ENV_LANG$&quot;&gt;&#10;&lt;head&gt;&#10;  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=UTF-8&quot; /&gt;&#10;  &lt;title&gt;&lt;/title&gt;&#10;&lt;/head&gt;&#10;&lt;body&gt;&#10;  $END$&#10;&lt;/body&gt;&#10;&lt;/html&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;en&quot;" expression="" name="ENV_LANG"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;a href=&quot;http://...&quot;&gt;...&lt;/a&gt;" name="a:link" toReformat="true" toShortenFQNames="true" value="&lt;a href=&quot;http://$VAR0$&quot;&gt;$END$&lt;/a&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;datetime-local&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:datetime-local" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;datetime-local&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;reset&quot; value=&quot;...&quot;&gt;" name="input:reset" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;reset&quot; value=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;colgroup&gt;...&lt;/colgroup&gt;" name="colg" toReformat="true" toShortenFQNames="true" value="&lt;colgroup&gt;$END$&lt;/colgroup&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;style type=&quot;text/css&quot;&gt;...&lt;/style&gt;" name="style" toReformat="true" toShortenFQNames="true" value="&lt;style type=&quot;text/css&quot;&gt;$END$&lt;/style&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;address&gt;...&lt;/address&gt;" name="adr" toReformat="true" toShortenFQNames="true" value="&lt;address&gt;$END$&lt;/address&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;img src=&quot;...&quot; alt=&quot;...&quot;&gt;" name="img" toReformat="true" toShortenFQNames="true" value="&lt;img src=&quot;$VAR0$&quot; alt=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;bdo dir=&quot;ltr&quot;&gt;...&lt;/bdo&gt;" name="bdo:l" toReformat="true" toShortenFQNames="true" value="&lt;bdo dir=&quot;ltr&quot;&gt;$END$&lt;/bdo&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;param name=&quot;...&quot; value=&quot;...&quot;&gt;" name="param" toReformat="true" toShortenFQNames="true" value="&lt;param name=&quot;$VAR0$&quot; value=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="colgroup+" toReformat="true" toShortenFQNames="true" value="&lt;colgroup&gt;&#10;  &lt;col&gt;&#10;&lt;/colgroup&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;form action=&quot;...&quot; method=&quot;post&quot;&gt;...&lt;/form&gt;" name="form:post" toReformat="true" toShortenFQNames="true" value="&lt;form action=&quot;$VAR0$&quot; method=&quot;post&quot;&gt;$END$&lt;/form&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;bdo dir=&quot;rtl&quot;&gt;...&lt;/bdo&gt;" name="bdo:r" toReformat="true" toShortenFQNames="true" value="&lt;bdo dir=&quot;rtl&quot;&gt;$END$&lt;/bdo&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;figure&gt;...&lt;/figure&gt;" name="fig" toReformat="true" toShortenFQNames="true" value="&lt;figure&gt;$END$&lt;/figure&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;radio&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:radio" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;radio&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;...print.css&quot; media=&quot;print&quot;&gt;" name="link:print" toReformat="true" toShortenFQNames="true" value="&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;$END$print.css&quot; media=&quot;print&quot;&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;option&gt;...&lt;/option&gt;" name="opt" toReformat="true" toShortenFQNames="true" value="&lt;option&gt;$END$&lt;/option&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;image&quot; src=&quot;...&quot; alt=&quot;...&quot;&gt;" name="input:i" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;image&quot; src=&quot;$VAR0$&quot; alt=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;hidden&quot; name=&quot;...&quot;&gt;" name="input:h" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;hidden&quot; name=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;file&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:f" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;file&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;checkbox&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:c" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;checkbox&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;button&quot; value=&quot;...&quot;&gt;" name="input:b" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;button&quot; value=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;abbr title=&quot;...&quot;&gt;...&lt;/abbr&gt;" name="abbr" toReformat="true" toShortenFQNames="true" value="&lt;abbr title=&quot;$VAR0$&quot;&gt;$END$&lt;/abbr&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;text&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:t" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;text&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;password&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:p" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;password&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;submit&quot; value=&quot;...&quot;&gt;" name="input:s" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;submit&quot; value=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;radio&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:r" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;radio&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;iframe&gt;...&lt;/iframe&gt;" name="ifr" toReformat="true" toShortenFQNames="true" value="&lt;iframe&gt;$END$&lt;/iframe&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;embed&gt;" name="emb" toReformat="true" toShortenFQNames="true" value="&lt;embed&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="optg+" toReformat="true" toShortenFQNames="true" value="&lt;optgroup&gt;&#10;  &lt;option value=&quot;$VAR0$&quot;&gt;$END$&lt;/option&gt;&#10;&lt;/optgroup&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;command&gt;" name="cmd" toReformat="true" toShortenFQNames="true" value="&lt;command&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;link rel=&quot;alternate&quot; type=&quot;application/atom+xml&quot; title=&quot;Atom&quot; href=&quot;atom.xml&quot;&gt;" name="link:atom" toReformat="true" toShortenFQNames="true" value="&lt;link rel=&quot;alternate&quot; type=&quot;application/atom+xml&quot; title=&quot;Atom&quot; href=&quot;atom.xml&quot;&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="table+" toReformat="true" toShortenFQNames="true" value="&lt;table&gt;&#10;  &lt;tr&gt;&#10;    &lt;td&gt;$END$&lt;/td&gt;&#10;  &lt;/tr&gt;&#10;&lt;/table&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;article&gt;...&lt;/article&gt;" name="art" toReformat="true" toShortenFQNames="true" value="&lt;article&gt;$END$&lt;/article&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;search&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:search" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;search&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;area shape=&quot;rect&quot; coords=&quot;...&quot; href=&quot;...&quot; alt=&quot;...&quot;&gt;" name="area:r" toReformat="true" toShortenFQNames="true" value="&lt;area shape=&quot;rect&quot; coords=&quot;$VAR0$&quot; href=&quot;$VAR1$&quot; alt=&quot;$VAR2$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR2"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;area shape=&quot;poly&quot; coords=&quot;...&quot; href=&quot;...&quot; alt=&quot;...&quot;&gt;" name="area:p" toReformat="true" toShortenFQNames="true" value="&lt;area shape=&quot;poly&quot; coords=&quot;$VAR0$&quot; href=&quot;$VAR1$&quot; alt=&quot;$VAR2$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR2"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;date&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:date" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;date&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;video src=&quot;...&quot;&gt;...&lt;/video&gt;" name="video" toReformat="true" toShortenFQNames="true" value="&lt;video src=&quot;$VAR0$&quot;&gt;$END$&lt;/video&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;button&quot; value=&quot;...&quot;&gt;" name="input:button" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;button&quot; value=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;area shape=&quot;default&quot; href=&quot;...&quot; alt=&quot;...&quot;&gt;" name="area:d" toReformat="true" toShortenFQNames="true" value="&lt;area shape=&quot;default&quot; href=&quot;$VAR0$&quot; alt=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;area shape=&quot;circle&quot; coords=&quot;...&quot; href=&quot;...&quot; alt=&quot;...&quot;&gt;" name="area:c" toReformat="true" toShortenFQNames="true" value="&lt;area shape=&quot;circle&quot; coords=&quot;$VAR0$&quot; href=&quot;$VAR1$&quot; alt=&quot;$VAR2$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR2"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;output&gt;...&lt;/output&gt;" name="out" toReformat="true" toShortenFQNames="true" value="&lt;output&gt;$END$&lt;/output&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;footer&gt;...&lt;/footer&gt;" name="ftr" toReformat="true" toShortenFQNames="true" value="&lt;footer&gt;$END$&lt;/footer&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;dialog&gt;...&lt;/dialog&gt;" name="dlg" toReformat="true" toShortenFQNames="true" value="&lt;dialog&gt;$END$&lt;/dialog&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;script type=&quot;text/javascript&quot; src=&quot;...&quot;&gt;...&lt;/script&gt;" name="script:src" toReformat="true" toShortenFQNames="true" value="&lt;script type=&quot;text/javascript&quot; src=&quot;$VAR0$&quot;&gt;$END$&lt;/script&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;form action=&quot;...&quot; method=&quot;get&quot;&gt;...&lt;/form&gt;" name="form:get" toReformat="true" toShortenFQNames="true" value="&lt;form action=&quot;$VAR0$&quot; method=&quot;get&quot;&gt;$END$&lt;/form&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=UTF-8&quot;&gt;" name="meta:utf" toReformat="true" toShortenFQNames="true" value="&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=UTF-8&quot;&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;label for=&quot;...&quot;&gt;...&lt;/label&gt;" name="label" toReformat="true" toShortenFQNames="true" value="&lt;label for=&quot;$VAR0$&quot;&gt;$END$&lt;/label&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;time&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:time" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;time&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;link rel=&quot;shortcut icon&quot; type=&quot;image/x-icon&quot; href=&quot;...favicon.ico&quot;&gt;" name="link:favicon" toReformat="true" toShortenFQNames="true" value="&lt;link rel=&quot;shortcut icon&quot; type=&quot;image/x-icon&quot; href=&quot;$END$favicon.ico&quot;&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;menu type=&quot;toolbar&quot;&gt;...&lt;/menu&gt;" name="menu:toolbar" toReformat="true" toShortenFQNames="true" value="&lt;menu type=&quot;toolbar&quot;&gt;$END$&lt;/menu&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;progress&gt;...&lt;/progress&gt;" name="prog" toReformat="true" toShortenFQNames="true" value="&lt;progress&gt;$END$&lt;/progress&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;email&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:email" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;email&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;optgroup&gt;...&lt;/optgroup&gt;" name="optg" toReformat="true" toShortenFQNames="true" value="&lt;optgroup&gt;$END$&lt;/optgroup&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;strong&gt;...&lt;/strong&gt;" name="str" toReformat="true" toShortenFQNames="true" value="&lt;strong&gt;$END$&lt;/strong&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;legend&gt;...&lt;/legend&gt;" name="leg" toReformat="true" toShortenFQNames="true" value="&lt;legend&gt;$END$&lt;/legend&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;acronym title=&quot;...&quot;&gt;...&lt;/acronym&gt;" name="acronym" toReformat="true" toShortenFQNames="true" value="&lt;acronym title=&quot;$VAR0$&quot;&gt;$END$&lt;/acronym&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="ol+" toReformat="true" toShortenFQNames="true" value="&lt;ol&gt;&#10;  &lt;li&gt;$END$&lt;/li&gt;&#10;&lt;/ol&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="tr+" toReformat="true" toShortenFQNames="true" value="&lt;tr&gt;&#10;  &lt;td&gt;$END$&lt;/td&gt;&#10;&lt;/tr&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="optgroup+" toReformat="true" toShortenFQNames="true" value="&lt;optgroup&gt;&#10;  &lt;option value=&quot;$VAR0$&quot;&gt;$END$&lt;/option&gt;&#10;&lt;/optgroup&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;base href=&quot;...&quot;&gt;" name="base" toReformat="true" toShortenFQNames="true" value="&lt;base href=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;blockquote&gt;...&lt;/blockquote&gt;" name="bq" toReformat="true" toShortenFQNames="true" value="&lt;blockquote&gt;$END$&lt;/blockquote&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;source&gt;...&lt;/source&gt;" name="src" toReformat="true" toShortenFQNames="true" value="&lt;source&gt;$END$&lt;/source&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;object&gt;...&lt;/object&gt;" name="obj" toReformat="true" toShortenFQNames="true" value="&lt;object&gt;$END$&lt;/object&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="dl+" toReformat="true" toShortenFQNames="true" value="&lt;dl&gt;&#10;  &lt;dt&gt;$VAR0$&lt;/dt&gt;&#10;  &lt;dd&gt;$END$&lt;/dd&gt;&#10;&lt;/dl&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;script type=&quot;text/javascript&quot;&gt;...&lt;/script&gt;" name="script" toReformat="true" toShortenFQNames="true" value="&lt;script type=&quot;text/javascript&quot;&gt;$END$&lt;/script&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;acronym&gt;...&lt;/acronym&gt;" name="acr" toReformat="true" toShortenFQNames="true" value="&lt;acronym&gt;$END$&lt;/acronym&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;password&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:password" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;password&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;file&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:file" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;file&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;textarea&gt;...&lt;/textarea&gt;" name="tarea" toReformat="true" toShortenFQNames="true" value="&lt;textarea&gt;$END$&lt;/textarea&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;select name=&quot;...&quot; id=&quot;...&quot;&gt;...&lt;/select&gt;" name="select" toReformat="true" toShortenFQNames="true" value="&lt;select name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;$END$&lt;/select&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;number&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:number" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;number&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;range&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:range" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;range&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;area shape=&quot;...&quot; coords=&quot;...&quot; href=&quot;...&quot; alt=&quot;...&quot;&gt;" name="area" toReformat="true" toShortenFQNames="true" value="&lt;area shape=&quot;$VAR0$&quot; coords=&quot;$VAR1$&quot; href=&quot;$VAR2$&quot; alt=&quot;$VAR3$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR2"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR3"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;image&quot; src=&quot;...&quot; alt=&quot;...&quot;&gt;" name="input:image" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;image&quot; src=&quot;$VAR0$&quot; alt=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="ul+" toReformat="true" toShortenFQNames="true" value="&lt;ul&gt;&#10;  &lt;li&gt;$END$&lt;/li&gt;&#10;&lt;/ul&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;month&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:month" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;month&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;fieldset&gt;...&lt;/fieldset&gt;" name="fset" toReformat="true" toShortenFQNames="true" value="&lt;fieldset&gt;$END$&lt;/fieldset&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=Win-1251&quot;&gt;" name="meta:win" toReformat="true" toShortenFQNames="true" value="&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=Win-1251&quot;&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;menu type=&quot;toolbar&quot;&gt;...&lt;/menu&gt;" name="menu:t" toReformat="true" toShortenFQNames="true" value="&lt;menu type=&quot;toolbar&quot;&gt;$END$&lt;/menu&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;form action=&quot;...&quot;&gt;...&lt;/form&gt;" name="form" toReformat="true" toShortenFQNames="true" value="&lt;form action=&quot;$VAR0$&quot;&gt;$END$&lt;/form&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;menu type=&quot;context&quot;&gt;...&lt;/menu&gt;" name="menu:c" toReformat="true" toShortenFQNames="true" value="&lt;menu type=&quot;context&quot;&gt;$END$&lt;/menu&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;link rel=&quot;stylesheet&quot; href=&quot;...&quot;&gt;" name="link" toReformat="true" toShortenFQNames="true" value="&lt;link rel=&quot;stylesheet&quot; href=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;...&quot;&gt;" name="input" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;link rel=&quot;alternate&quot; type=&quot;application/rss+xml&quot; title=&quot;RSS&quot; href=&quot;...rss.xml&quot;&gt;" name="link:rss" toReformat="true" toShortenFQNames="true" value="&lt;link rel=&quot;alternate&quot; type=&quot;application/rss+xml&quot; title=&quot;RSS&quot; href=&quot;$END$rss.xml&quot;&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="select+" toReformat="true" toShortenFQNames="true" value="&lt;select name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;&#10;  &lt;option value=&quot;$VAR2$&quot;&gt;$END$&lt;/option&gt;&#10;&lt;/select&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR2"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;header&gt;...&lt;/header&gt;" name="hdr" toReformat="true" toShortenFQNames="true" value="&lt;header&gt;$END$&lt;/header&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;caption&gt;...&lt;/caption&gt;" name="cap" toReformat="true" toShortenFQNames="true" value="&lt;caption&gt;$END$&lt;/caption&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;details&gt;...&lt;/details&gt;" name="det" toReformat="true" toShortenFQNames="true" value="&lt;details&gt;$END$&lt;/details&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;link rel=&quot;apple-touch-icon&quot; href=&quot;...favicon.png&quot;&gt;" name="link:touch" toReformat="true" toShortenFQNames="true" value="&lt;link rel=&quot;apple-touch-icon&quot; href=&quot;$END$favicon.png&quot;&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;iframe src=&quot;...&quot; frameborder=&quot;0&quot;&gt;...&lt;/iframe&gt;" name="iframe" toReformat="true" toShortenFQNames="true" value="&lt;iframe src=&quot;$VAR0$&quot; frameborder=&quot;0&quot;&gt;$END$&lt;/iframe&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;....css&quot; media=&quot;all&quot;&gt;" name="link:css" toReformat="true" toShortenFQNames="true" value="&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;$END$.css&quot; media=&quot;all&quot;&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;week&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:week" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;week&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;embed src=&quot;...&quot; type=&quot;...&quot;&gt;" name="embed" toReformat="true" toShortenFQNames="true" value="&lt;embed src=&quot;$VAR0$&quot; type=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;datagrid&gt;...&lt;/datagrid&gt;" name="datag" toReformat="true" toShortenFQNames="true" value="&lt;datagrid&gt;$END$&lt;/datagrid&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;datetime&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:datetime" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;datetime&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;option value=&quot;...&quot;&gt;...&lt;/option&gt;" name="option" toReformat="true" toShortenFQNames="true" value="&lt;option value=&quot;$VAR0$&quot;&gt;$END$&lt;/option&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;...&lt;/html&gt;" name="html:xml" toReformat="true" toShortenFQNames="true" value="&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;$END$&lt;/html&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;button&gt;...&lt;/button&gt;" name="btn" toReformat="true" toShortenFQNames="true" value="&lt;button&gt;$END$&lt;/button&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;url&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:url" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;url&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;menu type=&quot;context&quot;&gt;...&lt;/menu&gt;" name="menu:context" toReformat="true" toShortenFQNames="true" value="&lt;menu type=&quot;context&quot;&gt;$END$&lt;/menu&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="colg+" toReformat="true" toShortenFQNames="true" value="&lt;colgroup&gt;&#10;  &lt;col&gt;&#10;&lt;/colgroup&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;map name=&quot;...&quot;&gt;...&lt;/map&gt;" name="map" toReformat="true" toShortenFQNames="true" value="&lt;map name=&quot;$VAR0$&quot;&gt;$END$&lt;/map&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;color&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:color" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;color&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=7&quot;&gt;" name="meta:compat" toReformat="true" toShortenFQNames="true" value="&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=7&quot;&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;hidden&quot; name=&quot;...&quot;&gt;" name="input:hidden" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;hidden&quot; name=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;object data=&quot;...&quot; type=&quot;...&quot;&gt;...&lt;/object&gt;" name="object" toReformat="true" toShortenFQNames="true" value="&lt;object data=&quot;$VAR0$&quot; type=&quot;$VAR1$&quot;&gt;$END$&lt;/object&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;a href=&quot;mailto:...&quot;&gt;...&lt;/a&gt;" name="a:mail" toReformat="true" toShortenFQNames="true" value="&lt;a href=&quot;mailto:$VAR0$&quot;&gt;$END$&lt;/a&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;a href=&quot;...&quot;&gt;...&lt;/a&gt;" name="a" toReformat="true" toShortenFQNames="true" value="&lt;a href=&quot;$VAR0$&quot;&gt;$END$&lt;/a&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;datalist&gt;...&lt;/datalist&gt;" name="datal" toReformat="true" toShortenFQNames="true" value="&lt;datalist&gt;$END$&lt;/datalist&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;keygen&gt;" name="kg" toReformat="true" toShortenFQNames="true" value="&lt;keygen&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;textarea name=&quot;...&quot; id=&quot;...&quot; cols=&quot;30&quot; rows=&quot;10&quot;&gt;...&lt;/textarea&gt;" name="textarea" toReformat="true" toShortenFQNames="true" value="&lt;textarea name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot; cols=&quot;30&quot; rows=&quot;10&quot;&gt;$END$&lt;/textarea&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="map+" toReformat="true" toShortenFQNames="true" value="&lt;map name=&quot;$VAR0$&quot;&gt;&#10;  &lt;area shape=&quot;$VAR1$&quot; coords=&quot;$VAR2$&quot; href=&quot;$VAR3$&quot; alt=&quot;$VAR4$&quot;&gt;&#10;&lt;/map&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR2"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR3"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR4"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;submit&quot; value=&quot;...&quot;&gt;" name="input:submit" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;submit&quot; value=&quot;$VAR0$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;text&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:text" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;text&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;input type=&quot;checkbox&quot; name=&quot;...&quot; id=&quot;...&quot;&gt;" name="input:checkbox" toReformat="true" toShortenFQNames="true" value="&lt;input type=&quot;checkbox&quot; name=&quot;$VAR0$&quot; id=&quot;$VAR1$&quot;&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;fieldset&gt;...&lt;/fieldset&gt;" name="fst" toReformat="true" toShortenFQNames="true" value="&lt;fieldset&gt;$END$&lt;/fieldset&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;section&gt;...&lt;/section&gt;" name="sect" toReformat="true" toShortenFQNames="true" value="&lt;section&gt;$END$&lt;/section&gt;">
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;audio src=&quot;...&quot;&gt;...&lt;/audio&gt;" name="audio" toReformat="true" toShortenFQNames="true" value="&lt;audio src=&quot;$VAR0$&quot;&gt;$END$&lt;/audio&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;bdo dir=&quot;...&quot;&gt;...&lt;/bdo&gt;" name="bdo" toReformat="true" toShortenFQNames="true" value="&lt;bdo dir=&quot;$VAR0$&quot;&gt;$END$&lt;/bdo&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="HTML_TEXT" value="true"/>
+    </context>
+  </template>
+</templateSet>
diff --git a/xml/impl/resources/liveTemplates/zen_xsl.xml b/xml/impl/resources/liveTemplates/zen_xsl.xml
new file mode 100644
index 0000000..dbd599b
--- /dev/null
+++ b/xml/impl/resources/liveTemplates/zen_xsl.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templateSet group="Zen XSL">
+  <template description="&lt;xsl:template match=&quot;...&quot; mode=&quot;...&quot;&gt;...&lt;/xsl:template&gt;" name="tmatch" toReformat="true" toShortenFQNames="true" value="&lt;xsl:template match=&quot;$VAR0$&quot; mode=&quot;$VAR1$&quot;&gt;$END$&lt;/xsl:template&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:param name=&quot;...&quot; select=&quot;...&quot; /&gt;" name="par" toReformat="true" toShortenFQNames="true" value="&lt;xsl:param name=&quot;$VAR0$&quot; select=&quot;$VAR1$&quot; /&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:copy-of select=&quot;...&quot; /&gt;" name="co" toReformat="true" toShortenFQNames="true" value="&lt;xsl:copy-of select=&quot;$VAR0$&quot; /&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:attribute name=&quot;...&quot;&gt;...&lt;/xsl:attribute&gt;" name="attr" toReformat="true" toShortenFQNames="true" value="&lt;xsl:attribute name=&quot;$VAR0$&quot;&gt;$END$&lt;/xsl:attribute&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:value-of select=&quot;...&quot; /&gt;" name="val" toReformat="true" toShortenFQNames="true" value="&lt;xsl:value-of select=&quot;$VAR0$&quot; /&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:when test=&quot;...&quot;&gt;...&lt;/xsl:when&gt;" name="xsl:when" toReformat="true" toShortenFQNames="true" value="&lt;xsl:when test=&quot;$VAR0$&quot;&gt;$END$&lt;/xsl:when&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:for-each select=&quot;...&quot;&gt;...&lt;/xsl:for-each&gt;" name="each" toReformat="true" toShortenFQNames="true" value="&lt;xsl:for-each select=&quot;$VAR0$&quot;&gt;$END$&lt;/xsl:for-each&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:variable name=&quot;...&quot;&gt;...&lt;/xsl:variable&gt;" name="var" toReformat="true" toShortenFQNames="true" value="&lt;xsl:variable name=&quot;$VAR0$&quot;&gt;$END$&lt;/xsl:variable&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:when test=&quot;...&quot;&gt;...&lt;/xsl:when&gt;" name="wh" toReformat="true" toShortenFQNames="true" value="&lt;xsl:when test=&quot;$VAR0$&quot;&gt;$END$&lt;/xsl:when&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:template name=&quot;...&quot;&gt;...&lt;/xsl:template&gt;" name="tn" toReformat="true" toShortenFQNames="true" value="&lt;xsl:template name=&quot;$VAR0$&quot;&gt;$END$&lt;/xsl:template&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:apply-templates select=&quot;...&quot; mode=&quot;...&quot; /&gt;" name="ap" toReformat="true" toShortenFQNames="true" value="&lt;xsl:apply-templates select=&quot;$VAR0$&quot; mode=&quot;$VAR1$&quot; /&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:template match=&quot;...&quot; mode=&quot;...&quot;&gt;...&lt;/xsl:template&gt;" name="tm" toReformat="true" toShortenFQNames="true" value="&lt;xsl:template match=&quot;$VAR0$&quot; mode=&quot;$VAR1$&quot;&gt;$END$&lt;/xsl:template&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:call-template name=&quot;...&quot; /&gt;" name="call" toReformat="true" toShortenFQNames="true" value="&lt;xsl:call-template name=&quot;$VAR0$&quot; /&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="" name="choose+" toReformat="true" toShortenFQNames="true" value="&lt;xsl:choose&gt;&#10;  &lt;xsl:when test=&quot;$VAR0$&quot;&gt;$VAR1$&lt;/xsl:when&gt;&#10;  &lt;xsl:otherwise&gt;$END$&lt;/xsl:otherwise&gt;&#10;&lt;/xsl:choose&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:variable name=&quot;...&quot; select=&quot;...&quot; /&gt;" name="vare" toReformat="true" toShortenFQNames="true" value="&lt;xsl:variable name=&quot;$VAR0$&quot; select=&quot;$VAR1$&quot; /&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:with-param name=&quot;...&quot; select=&quot;...&quot; /&gt;" name="wp" toReformat="true" toShortenFQNames="true" value="&lt;xsl:with-param name=&quot;$VAR0$&quot; select=&quot;$VAR1$&quot; /&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR1"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:template name=&quot;...&quot;&gt;...&lt;/xsl:template&gt;" name="tname" toReformat="true" toShortenFQNames="true" value="&lt;xsl:template name=&quot;$VAR0$&quot;&gt;$END$&lt;/xsl:template&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+  <template description="&lt;xsl:if test=&quot;...&quot;&gt;...&lt;/xsl:if&gt;" name="if" toReformat="true" toShortenFQNames="true" value="&lt;xsl:if test=&quot;$VAR0$&quot;&gt;$END$&lt;/xsl:if&gt;">
+    <variable alwaysStopAt="true" defaultValue="&quot;&quot;" expression="" name="VAR0"/>
+    <context>
+      <option name="XSL_TEXT" value="true"/>
+    </context>
+  </template>
+</templateSet>
diff --git a/xml/impl/resources/standardSchemas/XMLSchema-instance.xsd b/xml/impl/resources/standardSchemas/XMLSchema-instance.xsd
new file mode 100644
index 0000000..e57428f
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/XMLSchema-instance.xsd
@@ -0,0 +1,25 @@
+<?xml version='1.0'?>
+<xs:schema targetNamespace="http://www.w3.org/2001/XMLSchema-instance"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+  <xs:annotation>
+   <xs:documentation xmlns="http://www.w3.org/1999/xhtml">
+    <h1>XML Schema instance namespace</h1>
+    <p>See <a href="http://www.w3.org/TR/xmlschema-1/">The XML Schema draft recommendation</a> for an introduction</p>
+
+
+    <hr />
+    $Date: 2004/06/09 12:44:55 $<br />
+    $Id: XMLSchema-instance.xsd,v 1.1 2004/06/09 12:44:55 max Exp $
+  </xs:documentation>
+ </xs:annotation>
+ <xs:attribute name="type">
+  <xs:annotation>
+   <xs:documentation>No definitions are provided here, as
+                     this schema is never used as such</xs:documentation>
+  </xs:annotation>
+ </xs:attribute>
+
+ <xs:attribute name="nill"/>
+ <xs:attribute name="schemaLocation"/>
+ <xs:attribute name="noNamespaceSchemaLocation"/>
+</xs:schema>
diff --git a/xml/impl/resources/standardSchemas/XMLSchema.dtd b/xml/impl/resources/standardSchemas/XMLSchema.dtd
new file mode 100644
index 0000000..d3c70b3
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/XMLSchema.dtd
@@ -0,0 +1,402 @@
+<!-- DTD for XML Schemas: Part 1: Structures
+     Public Identifier: "-//W3C//DTD XMLSCHEMA 200102//EN"
+     Official Location: http://www.w3.org/2001/XMLSchema.dtd -->
+<!-- $Id: XMLSchema.dtd,v 1.31 2001/10/24 15:50:16 ht Exp $ -->
+<!-- Note this DTD is NOT normative, or even definitive. -->           <!--d-->
+<!-- prose copy in the structures REC is the definitive version -->    <!--d-->
+<!-- (which shouldn't differ from this one except for this -->         <!--d-->
+<!-- comment and entity expansions, but just in case) -->              <!--d-->
+<!-- With the exception of cases with multiple namespace
+     prefixes for the XML Schema namespace, any XML document which is
+     not valid per this DTD given redefinitions in its internal subset of the
+     'p' and 's' parameter entities below appropriate to its namespace
+     declaration of the XML Schema namespace is almost certainly not
+     a valid schema. -->
+
+<!-- The simpleType element and its constituent parts
+     are defined in XML Schema: Part 2: Datatypes -->
+<!ENTITY % xs-datatypes PUBLIC 'datatypes' 'datatypes.dtd' >
+
+<!ENTITY % p 'xs:'> <!-- can be overriden in the internal subset of a
+                         schema document to establish a different
+                         namespace prefix -->
+<!ENTITY % s ':xs'> <!-- if %p is defined (e.g. as foo:) then you must
+                         also define %s as the suffix for the appropriate
+                         namespace declaration (e.g. :foo) -->
+<!ENTITY % nds 'xmlns%s;'>
+
+<!-- Define all the element names, with optional prefix -->
+<!ENTITY % schema "%p;schema">
+<!ENTITY % complexType "%p;complexType">
+<!ENTITY % complexContent "%p;complexContent">
+<!ENTITY % simpleContent "%p;simpleContent">
+<!ENTITY % extension "%p;extension">
+<!ENTITY % element "%p;element">
+<!ENTITY % unique "%p;unique">
+<!ENTITY % key "%p;key">
+<!ENTITY % keyref "%p;keyref">
+<!ENTITY % selector "%p;selector">
+<!ENTITY % field "%p;field">
+<!ENTITY % group "%p;group">
+<!ENTITY % all "%p;all">
+<!ENTITY % choice "%p;choice">
+<!ENTITY % sequence "%p;sequence">
+<!ENTITY % any "%p;any">
+<!ENTITY % anyAttribute "%p;anyAttribute">
+<!ENTITY % attribute "%p;attribute">
+<!ENTITY % attributeGroup "%p;attributeGroup">
+<!ENTITY % include "%p;include">
+<!ENTITY % import "%p;import">
+<!ENTITY % redefine "%p;redefine">
+<!ENTITY % notation "%p;notation">
+
+<!-- annotation elements -->
+<!ENTITY % annotation "%p;annotation">
+<!ENTITY % appinfo "%p;appinfo">
+<!ENTITY % documentation "%p;documentation">
+
+<!-- Customisation entities for the ATTLIST of each element type.
+     Define one of these if your schema takes advantage of the
+     anyAttribute='##other' in the schema for schemas -->
+
+<!ENTITY % schemaAttrs ''>
+<!ENTITY % complexTypeAttrs ''>
+<!ENTITY % complexContentAttrs ''>
+<!ENTITY % simpleContentAttrs ''>
+<!ENTITY % extensionAttrs ''>
+<!ENTITY % elementAttrs ''>
+<!ENTITY % groupAttrs ''>
+<!ENTITY % allAttrs ''>
+<!ENTITY % choiceAttrs ''>
+<!ENTITY % sequenceAttrs ''>
+<!ENTITY % anyAttrs ''>
+<!ENTITY % anyAttributeAttrs ''>
+<!ENTITY % attributeAttrs ''>
+<!ENTITY % attributeGroupAttrs ''>
+<!ENTITY % uniqueAttrs ''>
+<!ENTITY % keyAttrs ''>
+<!ENTITY % keyrefAttrs ''>
+<!ENTITY % selectorAttrs ''>
+<!ENTITY % fieldAttrs ''>
+<!ENTITY % includeAttrs ''>
+<!ENTITY % importAttrs ''>
+<!ENTITY % redefineAttrs ''>
+<!ENTITY % notationAttrs ''>
+<!ENTITY % annotationAttrs ''>
+<!ENTITY % appinfoAttrs ''>
+<!ENTITY % documentationAttrs ''>
+
+<!ENTITY % complexDerivationSet "CDATA">
+      <!-- #all or space-separated list drawn from derivationChoice -->
+<!ENTITY % blockSet "CDATA">
+      <!-- #all or space-separated list drawn from
+                      derivationChoice + 'substitution' -->
+
+<!ENTITY % mgs '%all; | %choice; | %sequence;'>
+<!ENTITY % cs '%choice; | %sequence;'>
+<!ENTITY % formValues '(qualified|unqualified)'>
+
+
+<!ENTITY % attrDecls    '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
+
+<!ENTITY % particleAndAttrs '((%mgs; | %group;)?, %attrDecls;)'>
+
+<!-- This is used in part2 -->
+<!ENTITY % restriction1 '((%mgs; | %group;)?)'>
+
+%xs-datatypes;
+
+<!-- the duplication below is to produce an unambiguous content model
+     which allows annotation everywhere -->
+<!ELEMENT %schema; ((%include; | %import; | %redefine; | %annotation;)*,
+                    ((%simpleType; | %complexType;
+                      | %element; | %attribute;
+                      | %attributeGroup; | %group;
+                      | %notation; ),
+                     (%annotation;)*)* )>
+<!ATTLIST %schema;
+   targetNamespace      %URIref;               #IMPLIED
+   version              CDATA                  #IMPLIED
+   %nds;                %URIref;               #FIXED 'http://www.w3.org/2001/XMLSchema'
+   xmlns                CDATA                  #IMPLIED
+   finalDefault         %complexDerivationSet; ''
+   blockDefault         %blockSet;             ''
+   id                   ID                     #IMPLIED
+   elementFormDefault   %formValues;           'unqualified'
+   attributeFormDefault %formValues;           'unqualified'
+   xml:lang             CDATA                  #IMPLIED
+   %schemaAttrs;>
+<!-- Note the xmlns declaration is NOT in the Schema for Schemas,
+     because at the Infoset level where schemas operate,
+     xmlns(:prefix) is NOT an attribute! -->
+<!-- The declaration of xmlns is a convenience for schema authors -->
+
+<!-- The id attribute here and below is for use in external references
+     from non-schemas using simple fragment identifiers.
+     It is NOT used for schema-to-schema reference, internal or
+     external. -->
+
+<!-- a type is a named content type specification which allows attribute
+     declarations-->
+<!-- -->
+
+<!ELEMENT %complexType; ((%annotation;)?,
+                         (%simpleContent;|%complexContent;|
+                          %particleAndAttrs;))>
+
+<!ATTLIST %complexType;
+          name      %NCName;                        #IMPLIED
+          id        ID                              #IMPLIED
+          abstract  %boolean;                       #IMPLIED
+          final     %complexDerivationSet;          #IMPLIED
+          block     %complexDerivationSet;          #IMPLIED
+          mixed (true|false) 'false'
+          %complexTypeAttrs;>
+
+<!-- particleAndAttrs is shorthand for a root type -->
+<!-- mixed is disallowed if simpleContent, overriden if complexContent
+     has one too. -->
+
+<!-- If anyAttribute appears in one or more referenced attributeGroups
+     and/or explicitly, the intersection of the permissions is used -->
+
+<!ELEMENT %complexContent; ((%annotation;)?, (%restriction;|%extension;))>
+<!ATTLIST %complexContent;
+          mixed (true|false) #IMPLIED
+          id    ID           #IMPLIED
+          %complexContentAttrs;>
+
+<!-- restriction should use the branch defined above, not the simple
+     one from part2; extension should use the full model  -->
+
+<!ELEMENT %simpleContent; ((%annotation;)?, (%restriction;|%extension;))>
+<!ATTLIST %simpleContent;
+          id    ID           #IMPLIED
+          %simpleContentAttrs;>
+
+<!-- restriction should use the simple branch from part2, not the
+     one defined above; extension should have no particle  -->
+
+<!ELEMENT %extension; ((%annotation;)?, (%particleAndAttrs;))>
+<!ATTLIST %extension;
+          base  %QName;      #REQUIRED
+          id    ID           #IMPLIED
+          %extensionAttrs;>
+
+<!-- an element is declared by either:
+ a name and a type (either nested or referenced via the type attribute)
+ or a ref to an existing element declaration -->
+
+<!ELEMENT %element; ((%annotation;)?, (%complexType;| %simpleType;)?,
+                     (%unique; | %key; | %keyref;)*)>
+<!-- simpleType or complexType only if no type|ref attribute -->
+<!-- ref not allowed at top level -->
+<!ATTLIST %element;
+            name               %NCName;               #IMPLIED
+            id                 ID                     #IMPLIED
+            ref                %QName;                #IMPLIED
+            type               %QName;                #IMPLIED
+            minOccurs          %nonNegativeInteger;   #IMPLIED
+            maxOccurs          CDATA                  #IMPLIED
+            nillable           %boolean;              #IMPLIED
+            substitutionGroup  %QName;                #IMPLIED
+            abstract           %boolean;              #IMPLIED
+            final              %complexDerivationSet; #IMPLIED
+            block              %blockSet;             #IMPLIED
+            default            CDATA                  #IMPLIED
+            fixed              CDATA                  #IMPLIED
+            form               %formValues;           #IMPLIED
+            %elementAttrs;>
+<!-- type and ref are mutually exclusive.
+     name and ref are mutually exclusive, one is required -->
+<!-- In the absence of type AND ref, type defaults to type of
+     substitutionGroup, if any, else the ur-type, i.e. unconstrained -->
+<!-- default and fixed are mutually exclusive -->
+
+<!ELEMENT %group; ((%annotation;)?,(%mgs;)?)>
+<!ATTLIST %group;
+          name        %NCName;               #IMPLIED
+          ref         %QName;                #IMPLIED
+          minOccurs   %nonNegativeInteger;   #IMPLIED
+          maxOccurs   CDATA                  #IMPLIED
+          id          ID                     #IMPLIED
+          %groupAttrs;>
+
+<!ELEMENT %all; ((%annotation;)?, (%element;)*)>
+<!ATTLIST %all;
+          minOccurs   (1)                    #IMPLIED
+          maxOccurs   (1)                    #IMPLIED
+          id          ID                     #IMPLIED
+          %allAttrs;>
+
+<!ELEMENT %choice; ((%annotation;)?, (%element;| %group;| %cs; | %any;)*)>
+<!ATTLIST %choice;
+          minOccurs   %nonNegativeInteger;   #IMPLIED
+          maxOccurs   CDATA                  #IMPLIED
+          id          ID                     #IMPLIED
+          %choiceAttrs;>
+
+<!ELEMENT %sequence; ((%annotation;)?, (%element;| %group;| %cs; | %any;)*)>
+<!ATTLIST %sequence;
+          minOccurs   %nonNegativeInteger;   #IMPLIED
+          maxOccurs   CDATA                  #IMPLIED
+          id          ID                     #IMPLIED
+          %sequenceAttrs;>
+
+<!-- an anonymous grouping in a model, or
+     a top-level named group definition, or a reference to same -->
+
+<!-- Note that if order is 'all', group is not allowed inside.
+     If order is 'all' THIS group must be alone (or referenced alone) at
+     the top level of a content model -->
+<!-- If order is 'all', minOccurs==maxOccurs==1 on element/any inside -->
+<!-- Should allow minOccurs=0 inside order='all' . . . -->
+
+<!ELEMENT %any; (%annotation;)?>
+<!ATTLIST %any;
+            namespace       CDATA                  '##any'
+            processContents (skip|lax|strict)      'strict'
+            minOccurs       %nonNegativeInteger;   '1'
+            maxOccurs       CDATA                  '1'
+            id              ID                     #IMPLIED
+            %anyAttrs;>
+
+<!-- namespace is interpreted as follows:
+                  ##any      - - any non-conflicting WFXML at all
+
+                  ##other    - - any non-conflicting WFXML from namespace other
+                                  than targetNamespace
+
+                  ##local    - - any unqualified non-conflicting WFXML/attribute
+                  one or     - - any non-conflicting WFXML from
+                  more URI        the listed namespaces
+                  references
+
+                  ##targetNamespace ##local may appear in the above list,
+                    with the obvious meaning -->
+
+<!ELEMENT %anyAttribute; (%annotation;)?>
+<!ATTLIST %anyAttribute;
+            namespace       CDATA              '##any'
+            processContents (skip|lax|strict)  'strict'
+            id              ID                 #IMPLIED
+            %anyAttributeAttrs;>
+<!-- namespace is interpreted as for 'any' above -->
+
+<!-- simpleType only if no type|ref attribute -->
+<!-- ref not allowed at top level, name iff at top level -->
+<!ELEMENT %attribute; ((%annotation;)?, (%simpleType;)?)>
+<!ATTLIST %attribute;
+          name      %NCName;      #IMPLIED
+          id        ID            #IMPLIED
+          ref       %QName;       #IMPLIED
+          type      %QName;       #IMPLIED
+          use       (prohibited|optional|required) #IMPLIED
+          default   CDATA         #IMPLIED
+          fixed     CDATA         #IMPLIED
+          form      %formValues;  #IMPLIED
+          %attributeAttrs;>
+<!-- type and ref are mutually exclusive.
+     name and ref are mutually exclusive, one is required -->
+<!-- default for use is optional when nested, none otherwise -->
+<!-- default and fixed are mutually exclusive -->
+<!-- type attr and simpleType content are mutually exclusive -->
+
+<!-- an attributeGroup is a named collection of attribute decls, or a
+     reference thereto -->
+<!ELEMENT %attributeGroup; ((%annotation;)?,
+                       (%attribute; | %attributeGroup;)*,
+                       (%anyAttribute;)?) >
+<!ATTLIST %attributeGroup;
+                 name       %NCName;       #IMPLIED
+                 id         ID             #IMPLIED
+                 ref        %QName;        #IMPLIED
+                 %attributeGroupAttrs;>
+
+<!-- ref iff no content, no name.  ref iff not top level -->
+
+<!-- better reference mechanisms -->
+<!ELEMENT %unique; ((%annotation;)?, %selector;, (%field;)+)>
+<!ATTLIST %unique;
+          name     %NCName;       #REQUIRED
+	  id       ID             #IMPLIED
+	  %uniqueAttrs;>
+
+<!ELEMENT %key;    ((%annotation;)?, %selector;, (%field;)+)>
+<!ATTLIST %key;
+          name     %NCName;       #REQUIRED
+	  id       ID             #IMPLIED
+	  %keyAttrs;>
+
+<!ELEMENT %keyref; ((%annotation;)?, %selector;, (%field;)+)>
+<!ATTLIST %keyref;
+          name     %NCName;       #REQUIRED
+	  refer    %QName;        #REQUIRED
+	  id       ID             #IMPLIED
+	  %keyrefAttrs;>
+
+<!ELEMENT %selector; ((%annotation;)?)>
+<!ATTLIST %selector;
+          xpath %XPathExpr; #REQUIRED
+          id    ID          #IMPLIED
+          %selectorAttrs;>
+<!ELEMENT %field; ((%annotation;)?)>
+<!ATTLIST %field;
+          xpath %XPathExpr; #REQUIRED
+          id    ID          #IMPLIED
+          %fieldAttrs;>
+
+<!-- Schema combination mechanisms -->
+<!ELEMENT %include; (%annotation;)?>
+<!ATTLIST %include;
+          schemaLocation %URIref; #REQUIRED
+          id             ID       #IMPLIED
+          %includeAttrs;>
+
+<!ELEMENT %import; (%annotation;)?>
+<!ATTLIST %import;
+          namespace      %URIref; #IMPLIED
+          schemaLocation %URIref; #IMPLIED
+          id             ID       #IMPLIED
+          %importAttrs;>
+
+<!ELEMENT %redefine; (%annotation; | %simpleType; | %complexType; |
+                      %attributeGroup; | %group;)*>
+<!ATTLIST %redefine;
+          schemaLocation %URIref; #REQUIRED
+          id             ID       #IMPLIED
+          %redefineAttrs;>
+
+<!ELEMENT %notation; (%annotation;)?>
+<!ATTLIST %notation;
+	  name        %NCName;    #REQUIRED
+	  id          ID          #IMPLIED
+	  public      CDATA       #REQUIRED
+	  system      %URIref;    #IMPLIED
+	  %notationAttrs;>
+
+<!-- Annotation is either application information or documentation -->
+<!-- By having these here they are available for datatypes as well
+     as all the structures elements -->
+
+<!ELEMENT %annotation; (%appinfo; | %documentation;)*>
+<!ATTLIST %annotation; %annotationAttrs;>
+
+<!-- User must define annotation elements in internal subset for this
+     to work -->
+<!ELEMENT %appinfo; ANY>   <!-- too restrictive -->
+<!ATTLIST %appinfo;
+          source     %URIref;      #IMPLIED
+          id         ID         #IMPLIED
+          %appinfoAttrs;>
+<!ELEMENT %documentation; ANY>   <!-- too restrictive -->
+<!ATTLIST %documentation;
+          source     %URIref;   #IMPLIED
+          id         ID         #IMPLIED
+          xml:lang   CDATA      #IMPLIED
+          %documentationAttrs;>
+
+<!NOTATION XMLSchemaStructures PUBLIC
+           'structures' 'http://www.w3.org/2001/XMLSchema.xsd' >
+<!NOTATION XML PUBLIC
+           'REC-xml-1998-0210' 'http://www.w3.org/TR/1998/REC-xml-19980210' >
diff --git a/xml/impl/resources/standardSchemas/XMLSchema.xsd b/xml/impl/resources/standardSchemas/XMLSchema.xsd
new file mode 100644
index 0000000..07e8e42
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/XMLSchema.xsd
@@ -0,0 +1,2468 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<xs:schema targetNamespace="http://www.w3.org/2001/XMLSchema" blockDefault="#all" elementFormDefault="qualified" version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xml:lang="EN" xmlns:hfp="http://www.w3.org/2001/XMLSchema-hasFacetAndProperty">
+ <xs:annotation>
+  <xs:documentation>
+    Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp 
+    Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp 
+  </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/2004/PER-xmlschema-1-20040318/structures.html">
+   The schema corresponding to this document is normative,
+   with respect to the syntactic constraints it expresses in the
+   XML Schema language.  The documentation (within &lt;documentation> elements)
+   below, is not normative, but rather highlights important aspects of
+   the W3C Recommendation of which this is a part</xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+   <xs:documentation>
+   The simpleType element and all of its members are defined
+      towards the end of this schema document</xs:documentation>
+ </xs:annotation>
+
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd">
+   <xs:annotation>
+     <xs:documentation>
+       Get access to the xml: attribute groups for xml:lang
+       as declared on 'schema' and 'documentation' below
+     </xs:documentation>
+   </xs:annotation>
+ </xs:import>
+
+ <xs:complexType name="openAttrs">
+   <xs:annotation>
+     <xs:documentation>
+       This type is extended by almost all schema types
+       to allow attributes from other namespaces to be
+       added to user schemas.
+     </xs:documentation>
+   </xs:annotation>
+   <xs:complexContent>
+     <xs:restriction base="xs:anyType">
+       <xs:anyAttribute namespace="##other" processContents="lax"/>
+     </xs:restriction>
+   </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="annotated">
+   <xs:annotation>
+     <xs:documentation>
+       This type is extended by all types which allow annotation
+       other than &lt;schema&gt; itself
+     </xs:documentation>
+   </xs:annotation>
+   <xs:complexContent>
+     <xs:extension base="xs:openAttrs">
+       <xs:sequence>
+         <xs:element ref="xs:annotation" minOccurs="0"/>
+       </xs:sequence>
+       <xs:attribute name="id" type="xs:ID"/>
+     </xs:extension>
+   </xs:complexContent>
+ </xs:complexType>
+
+ <xs:group name="schemaTop">
+  <xs:annotation>
+   <xs:documentation>
+   This group is for the
+   elements which occur freely at the top level of schemas.
+   All of their types are based on the "annotated" type by extension.</xs:documentation>
+  </xs:annotation>
+  <xs:choice>
+   <xs:group ref="xs:redefinable"/>
+   <xs:element ref="xs:element"/>
+   <xs:element ref="xs:attribute"/>
+   <xs:element ref="xs:notation"/>
+  </xs:choice>
+ </xs:group>
+ 
+ <xs:group name="redefinable">
+  <xs:annotation>
+   <xs:documentation>
+   This group is for the
+   elements which can self-redefine (see &lt;redefine> below).</xs:documentation>
+  </xs:annotation>
+  <xs:choice>
+   <xs:element ref="xs:simpleType"/>
+   <xs:element ref="xs:complexType"/>
+   <xs:element ref="xs:group"/>
+   <xs:element ref="xs:attributeGroup"/>
+  </xs:choice>
+ </xs:group>
+
+ <xs:simpleType name="formChoice">
+  <xs:annotation>
+   <xs:documentation>
+   A utility type, not for public use</xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:NMTOKEN">
+   <xs:enumeration value="qualified"/>
+   <xs:enumeration value="unqualified"/>
+  </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="reducedDerivationControl">
+  <xs:annotation>
+   <xs:documentation>
+   A utility type, not for public use</xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:derivationControl">
+   <xs:enumeration value="extension"/>
+   <xs:enumeration value="restriction"/>
+  </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="derivationSet">
+  <xs:annotation>
+   <xs:documentation>
+   A utility type, not for public use</xs:documentation>
+   <xs:documentation>
+   #all or (possibly empty) subset of {extension, restriction}</xs:documentation>
+  </xs:annotation>
+  <xs:union>
+   <xs:simpleType>    
+    <xs:restriction base="xs:token">
+     <xs:enumeration value="#all"/>
+    </xs:restriction>
+   </xs:simpleType>
+   <xs:simpleType>
+    <xs:list itemType="xs:reducedDerivationControl"/>
+   </xs:simpleType>
+  </xs:union>
+ </xs:simpleType>
+
+ <xs:simpleType name="typeDerivationControl">
+  <xs:annotation>
+   <xs:documentation>
+   A utility type, not for public use</xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:derivationControl">
+   <xs:enumeration value="extension"/>
+   <xs:enumeration value="restriction"/>
+   <xs:enumeration value="list"/>
+   <xs:enumeration value="union"/>
+  </xs:restriction>
+ </xs:simpleType>
+
+  <xs:simpleType name="fullDerivationSet">
+  <xs:annotation>
+   <xs:documentation>
+   A utility type, not for public use</xs:documentation>
+   <xs:documentation>
+   #all or (possibly empty) subset of {extension, restriction, list, union}</xs:documentation>
+  </xs:annotation>
+  <xs:union>
+   <xs:simpleType>    
+    <xs:restriction base="xs:token">
+     <xs:enumeration value="#all"/>
+    </xs:restriction>
+   </xs:simpleType>
+   <xs:simpleType>
+    <xs:list itemType="xs:typeDerivationControl"/>
+   </xs:simpleType>
+  </xs:union>
+ </xs:simpleType>
+
+ <xs:element name="schema" id="schema">
+  <xs:annotation>
+    <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-schema"/>
+  </xs:annotation>
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="xs:openAttrs">
+     <xs:sequence>
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+       <xs:element ref="xs:include"/>
+       <xs:element ref="xs:import"/>
+       <xs:element ref="xs:redefine"/>
+       <xs:element ref="xs:annotation"/>
+      </xs:choice>
+      <xs:sequence minOccurs="0" maxOccurs="unbounded">
+       <xs:group ref="xs:schemaTop"/>
+       <xs:element ref="xs:annotation" minOccurs="0" maxOccurs="unbounded"/>
+      </xs:sequence>
+     </xs:sequence>
+     <xs:attribute name="targetNamespace" type="xs:anyURI"/>
+     <xs:attribute name="version" type="xs:token"/>
+     <xs:attribute name="finalDefault" type="xs:fullDerivationSet" use="optional" default=""/>
+     <xs:attribute name="blockDefault" type="xs:blockSet" use="optional" default=""/>
+     <xs:attribute name="attributeFormDefault" type="xs:formChoice" use="optional" default="unqualified"/>
+     <xs:attribute name="elementFormDefault" type="xs:formChoice" use="optional" default="unqualified"/>
+     <xs:attribute name="id" type="xs:ID"/>
+     <xs:attribute ref="xml:lang"/>
+    </xs:extension>
+   </xs:complexContent>
+  </xs:complexType>
+
+  <xs:key name="element">
+   <xs:selector xpath="xs:element"/>
+   <xs:field xpath="@name"/>
+  </xs:key>
+
+  <xs:key name="attribute">
+   <xs:selector xpath="xs:attribute"/>
+   <xs:field xpath="@name"/>
+  </xs:key>
+
+  <xs:key name="type">
+   <xs:selector xpath="xs:complexType|xs:simpleType"/>
+   <xs:field xpath="@name"/>
+  </xs:key>
+ 
+  <xs:key name="group">
+   <xs:selector xpath="xs:group"/>
+   <xs:field xpath="@name"/>
+  </xs:key>
+ 
+  <xs:key name="attributeGroup">
+   <xs:selector xpath="xs:attributeGroup"/>
+   <xs:field xpath="@name"/>
+  </xs:key>
+ 
+  <xs:key name="notation">
+   <xs:selector xpath="xs:notation"/>
+   <xs:field xpath="@name"/>
+  </xs:key>
+
+  <xs:key name="identityConstraint">
+   <xs:selector xpath=".//xs:key|.//xs:unique|.//xs:keyref"/>
+   <xs:field xpath="@name"/>
+  </xs:key>
+
+ </xs:element>
+
+ <xs:simpleType name="allNNI">
+  <xs:annotation><xs:documentation>
+   for maxOccurs</xs:documentation></xs:annotation>
+  <xs:union memberTypes="xs:nonNegativeInteger">
+   <xs:simpleType>
+    <xs:restriction base="xs:NMTOKEN">
+     <xs:enumeration value="unbounded"/>
+    </xs:restriction>
+   </xs:simpleType>
+  </xs:union>
+ </xs:simpleType>
+
+ <xs:attributeGroup name="occurs">
+  <xs:annotation><xs:documentation>
+   for all particles</xs:documentation></xs:annotation>
+  <xs:attribute name="minOccurs" type="xs:nonNegativeInteger" use="optional" default="1"/>
+  <xs:attribute name="maxOccurs" type="xs:allNNI" use="optional" default="1"/>
+ </xs:attributeGroup>
+
+ <xs:attributeGroup name="defRef">
+  <xs:annotation><xs:documentation>
+   for element, group and attributeGroup,
+   which both define and reference</xs:documentation></xs:annotation>
+  <xs:attribute name="name" type="xs:NCName"/>
+  <xs:attribute name="ref" type="xs:QName"/>
+ </xs:attributeGroup>
+
+ <xs:group name="typeDefParticle">
+  <xs:annotation>
+    <xs:documentation>
+   'complexType' uses this</xs:documentation></xs:annotation>
+  <xs:choice>
+   <xs:element name="group" type="xs:groupRef"/>
+   <xs:element ref="xs:all"/>
+   <xs:element ref="xs:choice"/>
+   <xs:element ref="xs:sequence"/>
+  </xs:choice>
+ </xs:group>
+ 
+ 
+
+ <xs:group name="nestedParticle">
+  <xs:choice>
+   <xs:element name="element" type="xs:localElement"/>
+   <xs:element name="group" type="xs:groupRef"/>
+   <xs:element ref="xs:choice"/>
+   <xs:element ref="xs:sequence"/>
+   <xs:element ref="xs:any"/>
+  </xs:choice>
+ </xs:group>
+ 
+ <xs:group name="particle">
+  <xs:choice>
+   <xs:element name="element" type="xs:localElement"/>
+   <xs:element name="group" type="xs:groupRef"/>
+   <xs:element ref="xs:all"/>
+   <xs:element ref="xs:choice"/>
+   <xs:element ref="xs:sequence"/>
+   <xs:element ref="xs:any"/>
+  </xs:choice>
+ </xs:group>
+ 
+ <xs:complexType name="attribute">
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+    <xs:sequence>
+     <xs:element name="simpleType" minOccurs="0" type="xs:localSimpleType"/>
+    </xs:sequence>
+    <xs:attributeGroup ref="xs:defRef"/>
+    <xs:attribute name="type" type="xs:QName"/>
+    <xs:attribute name="use" use="optional" default="optional">
+     <xs:simpleType>
+      <xs:restriction base="xs:NMTOKEN">
+       <xs:enumeration value="prohibited"/>
+       <xs:enumeration value="optional"/>
+       <xs:enumeration value="required"/>
+      </xs:restriction>
+     </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="default" type="xs:string"/>
+    <xs:attribute name="fixed" type="xs:string"/>
+    <xs:attribute name="form" type="xs:formChoice"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:complexType name="topLevelAttribute">
+  <xs:complexContent>
+   <xs:restriction base="xs:attribute">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:element name="simpleType" minOccurs="0" type="xs:localSimpleType"/>
+    </xs:sequence>
+    <xs:attribute name="ref" use="prohibited"/>
+    <xs:attribute name="form" use="prohibited"/>
+    <xs:attribute name="use" use="prohibited"/>
+    <xs:attribute name="name" use="required" type="xs:NCName"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:group name="attrDecls">
+  <xs:sequence>
+   <xs:choice minOccurs="0" maxOccurs="unbounded">
+    <xs:element name="attribute" type="xs:attribute"/>
+    <xs:element name="attributeGroup" type="xs:attributeGroupRef"/>
+   </xs:choice>
+   <xs:element ref="xs:anyAttribute" minOccurs="0"/>
+  </xs:sequence>
+ </xs:group>
+
+ <xs:element name="anyAttribute" type="xs:wildcard" id="anyAttribute">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-anyAttribute"/>
+  </xs:annotation>
+ </xs:element>
+
+ <xs:group name="complexTypeModel">
+  <xs:choice>
+      <xs:element ref="xs:simpleContent"/>
+      <xs:element ref="xs:complexContent"/>
+      <xs:sequence>
+       <xs:annotation>
+        <xs:documentation>
+   This branch is short for
+   &lt;complexContent>
+   &lt;restriction base="xs:anyType">
+   ...
+   &lt;/restriction>
+   &lt;/complexContent></xs:documentation>
+       </xs:annotation>
+       <xs:group ref="xs:typeDefParticle" minOccurs="0"/>
+       <xs:group ref="xs:attrDecls"/>
+      </xs:sequence>
+  </xs:choice>
+ </xs:group>
+
+ <xs:complexType name="complexType" abstract="true">
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+    <xs:group ref="xs:complexTypeModel"/>
+    <xs:attribute name="name" type="xs:NCName">
+     <xs:annotation>
+      <xs:documentation>
+      Will be restricted to required or forbidden</xs:documentation>
+     </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="mixed" type="xs:boolean" use="optional" default="false">
+     <xs:annotation>
+      <xs:documentation>
+      Not allowed if simpleContent child is chosen.
+      May be overriden by setting on complexContent child.</xs:documentation>
+    </xs:annotation>
+    </xs:attribute>
+    <xs:attribute name="abstract" type="xs:boolean" use="optional" default="false"/>
+    <xs:attribute name="final" type="xs:derivationSet"/>
+    <xs:attribute name="block" type="xs:derivationSet"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:complexType name="topLevelComplexType">
+  <xs:complexContent>
+   <xs:restriction base="xs:complexType">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:group ref="xs:complexTypeModel"/>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:NCName" use="required"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:complexType name="localComplexType">
+  <xs:complexContent>
+   <xs:restriction base="xs:complexType">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:group ref="xs:complexTypeModel"/>
+    </xs:sequence>
+    <xs:attribute name="name" use="prohibited"/>
+    <xs:attribute name="abstract" use="prohibited"/>
+    <xs:attribute name="final" use="prohibited"/>
+    <xs:attribute name="block" use="prohibited"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:complexType name="restrictionType">
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+    <xs:sequence>
+     <xs:choice minOccurs="0">
+      <xs:group ref="xs:typeDefParticle"/>
+      <xs:group ref="xs:simpleRestrictionModel"/>
+     </xs:choice>
+     <xs:group ref="xs:attrDecls"/>
+    </xs:sequence>
+    <xs:attribute name="base" type="xs:QName" use="required"/>
+   </xs:extension>
+  </xs:complexContent>       
+ </xs:complexType>
+
+ <xs:complexType name="complexRestrictionType">
+  <xs:complexContent>
+   <xs:restriction base="xs:restrictionType">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:choice minOccurs="0">
+      <xs:annotation>
+       <xs:documentation>This choice is added simply to
+                   make this a valid restriction per the REC</xs:documentation>
+      </xs:annotation>
+      <xs:group ref="xs:typeDefParticle"/>
+     </xs:choice>
+     <xs:group ref="xs:attrDecls"/>
+    </xs:sequence>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>       
+ </xs:complexType>
+
+ <xs:complexType name="extensionType">
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+    <xs:sequence>
+     <xs:group ref="xs:typeDefParticle" minOccurs="0"/>
+     <xs:group ref="xs:attrDecls"/>
+    </xs:sequence>
+    <xs:attribute name="base" type="xs:QName" use="required"/>
+   </xs:extension>
+  </xs:complexContent>       
+ </xs:complexType>
+
+ <xs:element name="complexContent" id="complexContent">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-complexContent"/>
+  </xs:annotation>
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="xs:annotated">
+     <xs:choice>
+      <xs:element name="restriction" type="xs:complexRestrictionType"/>
+      <xs:element name="extension" type="xs:extensionType"/>
+     </xs:choice>     
+     <xs:attribute name="mixed" type="xs:boolean">
+      <xs:annotation>
+       <xs:documentation>
+       Overrides any setting on complexType parent.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+    </xs:extension>
+   </xs:complexContent>
+  </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="simpleRestrictionType">
+  <xs:complexContent>
+   <xs:restriction base="xs:restrictionType">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:choice minOccurs="0">
+      <xs:annotation>
+       <xs:documentation>This choice is added simply to
+                   make this a valid restriction per the REC</xs:documentation>
+      </xs:annotation>
+      <xs:group ref="xs:simpleRestrictionModel"/>
+     </xs:choice>
+     <xs:group ref="xs:attrDecls"/>
+    </xs:sequence>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="simpleExtensionType">
+  <xs:complexContent>
+   <xs:restriction base="xs:extensionType">
+    <xs:sequence>
+     <xs:annotation>
+      <xs:documentation>
+      No typeDefParticle group reference</xs:documentation>
+     </xs:annotation>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:group ref="xs:attrDecls"/>
+    </xs:sequence>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="simpleContent" id="simpleContent">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-simpleContent"/>
+  </xs:annotation>
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="xs:annotated">
+     <xs:choice>
+      <xs:element name="restriction" type="xs:simpleRestrictionType"/>
+      <xs:element name="extension" type="xs:simpleExtensionType"/>
+     </xs:choice>
+    </xs:extension>
+   </xs:complexContent>
+  </xs:complexType>
+ </xs:element>
+ 
+ <xs:element name="complexType" type="xs:topLevelComplexType" id="complexType">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-complexType"/>
+  </xs:annotation>
+ </xs:element>
+
+
+  <xs:simpleType name="blockSet">
+   <xs:annotation>
+    <xs:documentation>
+    A utility type, not for public use</xs:documentation>
+    <xs:documentation>
+    #all or (possibly empty) subset of {substitution, extension,
+    restriction}</xs:documentation>
+   </xs:annotation>
+   <xs:union>
+    <xs:simpleType>    
+     <xs:restriction base="xs:token">
+      <xs:enumeration value="#all"/>
+     </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType>
+     <xs:list>
+      <xs:simpleType>
+       <xs:restriction base="xs:derivationControl">
+        <xs:enumeration value="extension"/>
+        <xs:enumeration value="restriction"/>
+        <xs:enumeration value="substitution"/>
+       </xs:restriction>
+      </xs:simpleType>
+     </xs:list>
+    </xs:simpleType>
+   </xs:union>  
+  </xs:simpleType>
+
+ <xs:complexType name="element" abstract="true">
+  <xs:annotation>
+   <xs:documentation>
+   The element element can be used either
+   at the top level to define an element-type binding globally,
+   or within a content model to either reference a globally-defined
+   element or type or declare an element-type binding locally.
+   The ref form is not allowed at the top level.</xs:documentation>
+  </xs:annotation>
+
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+    <xs:sequence>
+     <xs:choice minOccurs="0">
+      <xs:element name="simpleType" type="xs:localSimpleType"/>
+      <xs:element name="complexType" type="xs:localComplexType"/>
+     </xs:choice>
+     <xs:group ref="xs:identityConstraint" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attributeGroup ref="xs:defRef"/>
+    <xs:attribute name="type" type="xs:QName"/>
+    <xs:attribute name="substitutionGroup" type="xs:QName"/>
+    <xs:attributeGroup ref="xs:occurs"/>
+    <xs:attribute name="default" type="xs:string"/>
+    <xs:attribute name="fixed" type="xs:string"/>
+    <xs:attribute name="nillable" type="xs:boolean" use="optional" default="false"/>
+    <xs:attribute name="abstract" type="xs:boolean" use="optional" default="false"/>
+    <xs:attribute name="final" type="xs:derivationSet"/>
+    <xs:attribute name="block" type="xs:blockSet"/>
+    <xs:attribute name="form" type="xs:formChoice"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:complexType name="topLevelElement">
+  <xs:complexContent>
+   <xs:restriction base="xs:element">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:choice minOccurs="0">
+      <xs:element name="simpleType" type="xs:localSimpleType"/>
+      <xs:element name="complexType" type="xs:localComplexType"/>
+     </xs:choice>
+     <xs:group ref="xs:identityConstraint" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="ref" use="prohibited"/>
+    <xs:attribute name="form" use="prohibited"/>
+    <xs:attribute name="minOccurs" use="prohibited"/>
+    <xs:attribute name="maxOccurs" use="prohibited"/>
+    <xs:attribute name="name" use="required" type="xs:NCName"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:complexType name="localElement">
+  <xs:complexContent>
+   <xs:restriction base="xs:element">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:choice minOccurs="0">
+      <xs:element name="simpleType" type="xs:localSimpleType"/>
+      <xs:element name="complexType" type="xs:localComplexType"/>
+     </xs:choice>
+     <xs:group ref="xs:identityConstraint" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="substitutionGroup" use="prohibited"/>
+    <xs:attribute name="final" use="prohibited"/>
+    <xs:attribute name="abstract" use="prohibited"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="element" type="xs:topLevelElement" id="element">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-element"/>
+  </xs:annotation>
+ </xs:element>
+
+ <xs:complexType name="group" abstract="true">
+  <xs:annotation>
+   <xs:documentation>
+   group type for explicit groups, named top-level groups and
+   group references</xs:documentation>
+  </xs:annotation>
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+    <xs:group ref="xs:particle" minOccurs="0" maxOccurs="unbounded"/>
+    <xs:attributeGroup ref="xs:defRef"/>
+    <xs:attributeGroup ref="xs:occurs"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:complexType name="realGroup">
+  <xs:complexContent>
+   <xs:restriction base="xs:group">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:choice minOccurs="0" maxOccurs="1">
+      <xs:element ref="xs:all"/>
+      <xs:element ref="xs:choice"/>
+      <xs:element ref="xs:sequence"/>
+     </xs:choice>
+    </xs:sequence>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="namedGroup">
+  <xs:complexContent>
+   <xs:restriction base="xs:realGroup">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:choice minOccurs="1" maxOccurs="1">
+      <xs:element name="all">
+       <xs:complexType>
+        <xs:complexContent>
+         <xs:restriction base="xs:all">
+          <xs:group ref="xs:allModel"/>
+          <xs:attribute name="minOccurs" use="prohibited"/>
+          <xs:attribute name="maxOccurs" use="prohibited"/>
+          <xs:anyAttribute namespace="##other" processContents="lax"/>
+         </xs:restriction>
+        </xs:complexContent>
+       </xs:complexType>
+      </xs:element>
+      <xs:element name="choice" type="xs:simpleExplicitGroup"/>
+      <xs:element name="sequence" type="xs:simpleExplicitGroup"/>
+     </xs:choice>
+    </xs:sequence>
+    <xs:attribute name="name" use="required" type="xs:NCName"/>
+    <xs:attribute name="ref" use="prohibited"/>
+    <xs:attribute name="minOccurs" use="prohibited"/>
+    <xs:attribute name="maxOccurs" use="prohibited"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="groupRef">
+  <xs:complexContent>
+   <xs:restriction base="xs:realGroup">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="ref" use="required" type="xs:QName"/>
+    <xs:attribute name="name" use="prohibited"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="explicitGroup">
+  <xs:annotation>
+   <xs:documentation>
+   group type for the three kinds of group</xs:documentation>
+  </xs:annotation>
+  <xs:complexContent>
+   <xs:restriction base="xs:group">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:group ref="xs:nestedParticle" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:NCName" use="prohibited"/>
+    <xs:attribute name="ref" type="xs:QName" use="prohibited"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:complexType name="simpleExplicitGroup">
+  <xs:complexContent>
+   <xs:restriction base="xs:explicitGroup">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:group ref="xs:nestedParticle" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="minOccurs" use="prohibited"/>
+    <xs:attribute name="maxOccurs" use="prohibited"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:group name="allModel">
+  <xs:sequence>
+      <xs:element ref="xs:annotation" minOccurs="0"/>
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+       <xs:annotation>
+        <xs:documentation>This choice with min/max is here to
+                          avoid a pblm with the Elt:All/Choice/Seq
+                          Particle derivation constraint</xs:documentation>
+       </xs:annotation>
+       <xs:element name="element" type="xs:narrowMaxMin"/>
+      </xs:choice>
+     </xs:sequence>
+ </xs:group>
+ 
+ 
+ <xs:complexType name="narrowMaxMin">
+  <xs:annotation>
+   <xs:documentation>restricted max/min</xs:documentation>
+  </xs:annotation>
+  <xs:complexContent>
+   <xs:restriction base="xs:localElement">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:choice minOccurs="0">
+      <xs:element name="simpleType" type="xs:localSimpleType"/>
+      <xs:element name="complexType" type="xs:localComplexType"/>
+     </xs:choice>
+     <xs:group ref="xs:identityConstraint" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="minOccurs" use="optional" default="1">
+     <xs:simpleType>
+      <xs:restriction base="xs:nonNegativeInteger">
+       <xs:enumeration value="0"/>
+       <xs:enumeration value="1"/>
+      </xs:restriction>
+     </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="maxOccurs" use="optional" default="1">
+     <xs:simpleType>
+      <xs:restriction base="xs:allNNI">
+       <xs:enumeration value="0"/>
+       <xs:enumeration value="1"/>
+      </xs:restriction>
+     </xs:simpleType>
+    </xs:attribute>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+  <xs:complexType name="all">
+   <xs:annotation>
+    <xs:documentation>
+   Only elements allowed inside</xs:documentation>
+   </xs:annotation>
+   <xs:complexContent>
+    <xs:restriction base="xs:explicitGroup">
+     <xs:group ref="xs:allModel"/>
+     <xs:attribute name="minOccurs" use="optional" default="1">
+      <xs:simpleType>
+       <xs:restriction base="xs:nonNegativeInteger">
+        <xs:enumeration value="0"/>
+        <xs:enumeration value="1"/>
+       </xs:restriction>
+      </xs:simpleType>
+     </xs:attribute>
+     <xs:attribute name="maxOccurs" use="optional" default="1">
+      <xs:simpleType>
+       <xs:restriction base="xs:allNNI">
+        <xs:enumeration value="1"/>
+       </xs:restriction>
+      </xs:simpleType>
+     </xs:attribute>
+     <xs:anyAttribute namespace="##other" processContents="lax"/>
+    </xs:restriction>
+   </xs:complexContent>
+  </xs:complexType>
+
+ <xs:element name="all" id="all" type="xs:all">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-all"/>
+  </xs:annotation>
+ </xs:element>
+
+ <xs:element name="choice" type="xs:explicitGroup" id="choice">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-choice"/>
+  </xs:annotation>
+ </xs:element>
+
+ <xs:element name="sequence" type="xs:explicitGroup" id="sequence">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-sequence"/>
+  </xs:annotation>
+ </xs:element>
+
+ <xs:element name="group" type="xs:namedGroup" id="group">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-group"/>
+  </xs:annotation>
+ </xs:element>
+
+ <xs:complexType name="wildcard">
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+    <xs:attribute name="namespace" type="xs:namespaceList" use="optional" default="##any"/>
+    <xs:attribute name="processContents" use="optional" default="strict">
+     <xs:simpleType>
+      <xs:restriction base="xs:NMTOKEN">
+       <xs:enumeration value="skip"/>
+       <xs:enumeration value="lax"/>
+       <xs:enumeration value="strict"/>
+      </xs:restriction>
+     </xs:simpleType>
+    </xs:attribute>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="any" id="any">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-any"/>
+  </xs:annotation>
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="xs:wildcard">
+     <xs:attributeGroup ref="xs:occurs"/>
+    </xs:extension>
+   </xs:complexContent>
+  </xs:complexType>
+ </xs:element>
+
+  <xs:annotation>
+   <xs:documentation>
+   simple type for the value of the 'namespace' attr of
+   'any' and 'anyAttribute'</xs:documentation>
+  </xs:annotation>
+  <xs:annotation>
+   <xs:documentation>
+   Value is
+              ##any      - - any non-conflicting WFXML/attribute at all
+
+              ##other    - - any non-conflicting WFXML/attribute from
+                              namespace other than targetNS
+
+              ##local    - - any unqualified non-conflicting WFXML/attribute 
+
+              one or     - - any non-conflicting WFXML/attribute from
+              more URI        the listed namespaces
+              references
+              (space separated)
+
+    ##targetNamespace or ##local may appear in the above list, to
+        refer to the targetNamespace of the enclosing
+        schema or an absent targetNamespace respectively</xs:documentation>
+  </xs:annotation>
+
+ <xs:simpleType name="namespaceList">
+  <xs:annotation>
+   <xs:documentation>
+   A utility type, not for public use</xs:documentation>
+  </xs:annotation>
+  <xs:union>
+   <xs:simpleType>
+    <xs:restriction base="xs:token">
+     <xs:enumeration value="##any"/>
+     <xs:enumeration value="##other"/>
+    </xs:restriction>
+   </xs:simpleType>
+   <xs:simpleType>
+    <xs:list>
+     <xs:simpleType>
+      <xs:union memberTypes="xs:anyURI">
+       <xs:simpleType>
+        <xs:restriction base="xs:token">
+         <xs:enumeration value="##targetNamespace"/>
+         <xs:enumeration value="##local"/>
+        </xs:restriction>
+       </xs:simpleType>
+      </xs:union>
+     </xs:simpleType>
+    </xs:list>
+   </xs:simpleType>
+  </xs:union>
+ </xs:simpleType>
+
+ <xs:element name="attribute" type="xs:topLevelAttribute" id="attribute">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-attribute"/>
+  </xs:annotation>
+ </xs:element>
+
+ <xs:complexType name="attributeGroup" abstract="true">
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+    <xs:group ref="xs:attrDecls"/>
+    <xs:attributeGroup ref="xs:defRef"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ 
+ <xs:complexType name="namedAttributeGroup">
+  <xs:complexContent>
+   <xs:restriction base="xs:attributeGroup">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+     <xs:group ref="xs:attrDecls"/>
+    </xs:sequence>
+    <xs:attribute name="name" use="required" type="xs:NCName"/>
+    <xs:attribute name="ref" use="prohibited"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="attributeGroupRef">
+  <xs:complexContent>
+   <xs:restriction base="xs:attributeGroup">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="ref" use="required" type="xs:QName"/>
+    <xs:attribute name="name" use="prohibited"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="attributeGroup" type="xs:namedAttributeGroup" id="attributeGroup">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-attributeGroup"/>
+  </xs:annotation>
+ </xs:element>
+
+ <xs:element name="include" id="include">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-include"/>
+  </xs:annotation>
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="xs:annotated">
+     <xs:attribute name="schemaLocation" type="xs:anyURI" use="required"/>
+    </xs:extension>
+   </xs:complexContent>
+  </xs:complexType>
+ </xs:element>
+
+ <xs:element name="redefine" id="redefine">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-redefine"/>
+  </xs:annotation>
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="xs:openAttrs">
+     <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="xs:annotation"/>
+      <xs:group ref="xs:redefinable"/>
+     </xs:choice>
+     <xs:attribute name="schemaLocation" type="xs:anyURI" use="required"/>
+     <xs:attribute name="id" type="xs:ID"/>
+    </xs:extension>
+   </xs:complexContent>
+  </xs:complexType>
+ </xs:element>
+
+ <xs:element name="import" id="import">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-import"/>
+  </xs:annotation>
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="xs:annotated">
+     <xs:attribute name="namespace" type="xs:anyURI"/>
+     <xs:attribute name="schemaLocation" type="xs:anyURI"/>
+    </xs:extension>
+   </xs:complexContent>
+  </xs:complexType>
+ </xs:element>
+
+ <xs:element name="selector" id="selector">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-selector"/>
+  </xs:annotation>
+  <xs:complexType>
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+     <xs:attribute name="xpath" use="required">
+      <xs:simpleType>
+       <xs:annotation>
+        <xs:documentation>A subset of XPath expressions for use
+in selectors</xs:documentation>
+        <xs:documentation>A utility type, not for public
+use</xs:documentation>
+       </xs:annotation>
+       <xs:restriction base="xs:token">
+        <xs:annotation>
+         <xs:documentation>The following pattern is intended to allow XPath
+                           expressions per the following EBNF:
+          Selector    ::=    Path ( '|' Path )*  
+          Path    ::=    ('.//')? Step ( '/' Step )*  
+          Step    ::=    '.' | NameTest  
+          NameTest    ::=    QName | '*' | NCName ':' '*'  
+                           child:: is also allowed
+         </xs:documentation>
+        </xs:annotation>
+        <xs:pattern value="(\.//)?(((child::)?((\i\c*:)?(\i\c*|\*)))|\.)(/(((child::)?((\i\c*:)?(\i\c*|\*)))|\.))*(\|(\.//)?(((child::)?((\i\c*:)?(\i\c*|\*)))|\.)(/(((child::)?((\i\c*:)?(\i\c*|\*)))|\.))*)*">
+        </xs:pattern>
+       </xs:restriction>
+      </xs:simpleType>
+     </xs:attribute>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="field" id="field">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-field"/>
+  </xs:annotation>
+  <xs:complexType>
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+     <xs:attribute name="xpath" use="required">
+      <xs:simpleType>
+       <xs:annotation>
+        <xs:documentation>A subset of XPath expressions for use
+in fields</xs:documentation>
+        <xs:documentation>A utility type, not for public
+use</xs:documentation>
+       </xs:annotation>
+       <xs:restriction base="xs:token">
+        <xs:annotation>
+         <xs:documentation>The following pattern is intended to allow XPath
+                           expressions per the same EBNF as for selector,
+                           with the following change:
+          Path    ::=    ('.//')? ( Step '/' )* ( Step | '@' NameTest ) 
+         </xs:documentation>
+        </xs:annotation>
+        <xs:pattern value="(\.//)?((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)/)*((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)|((attribute::|@)((\i\c*:)?(\i\c*|\*))))(\|(\.//)?((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)/)*((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)|((attribute::|@)((\i\c*:)?(\i\c*|\*)))))*">
+        </xs:pattern>
+       </xs:restriction>
+      </xs:simpleType>
+     </xs:attribute>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="keybase">
+  <xs:complexContent>
+   <xs:extension base="xs:annotated">
+    <xs:sequence>
+     <xs:element ref="xs:selector"/>
+     <xs:element ref="xs:field" minOccurs="1" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:NCName" use="required"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+
+ <xs:group name="identityConstraint">
+  <xs:annotation>
+   <xs:documentation>The three kinds of identity constraints, all with
+                     type of or derived from 'keybase'.
+   </xs:documentation>
+  </xs:annotation>
+  <xs:choice>
+   <xs:element ref="xs:unique"/>
+   <xs:element ref="xs:key"/>
+   <xs:element ref="xs:keyref"/>
+  </xs:choice>
+ </xs:group>
+
+ <xs:element name="unique" type="xs:keybase" id="unique">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-unique"/>
+  </xs:annotation>
+ </xs:element>
+ <xs:element name="key" type="xs:keybase" id="key">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-key"/>
+  </xs:annotation>
+ </xs:element>
+ <xs:element name="keyref" id="keyref">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-keyref"/>
+  </xs:annotation>
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="xs:keybase">
+     <xs:attribute name="refer" type="xs:QName" use="required"/>
+    </xs:extension>
+   </xs:complexContent>
+  </xs:complexType>
+ </xs:element>
+
+ <xs:element name="notation" id="notation">
+  <xs:annotation>
+   <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-notation"/>
+  </xs:annotation>
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="xs:annotated">
+     <xs:attribute name="name" type="xs:NCName" use="required"/>
+     <xs:attribute name="public" type="xs:public"/>
+     <xs:attribute name="system" type="xs:anyURI"/>
+    </xs:extension>
+   </xs:complexContent>
+  </xs:complexType>
+ </xs:element>
+
+ <xs:simpleType name="public">
+  <xs:annotation>
+   <xs:documentation>
+   A utility type, not for public use</xs:documentation>
+   <xs:documentation>
+   A public identifier, per ISO 8879</xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+
+ <xs:element name="appinfo" id="appinfo">
+   <xs:annotation>
+     <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-appinfo"/>
+   </xs:annotation>
+   <xs:complexType mixed="true">
+    <xs:sequence minOccurs="0" maxOccurs="unbounded">
+     <xs:any processContents="lax"/>
+    </xs:sequence>
+    <xs:attribute name="source" type="xs:anyURI"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:complexType>
+ </xs:element>
+
+ <xs:element name="documentation" id="documentation">
+   <xs:annotation>
+     <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-documentation"/>
+   </xs:annotation>
+   <xs:complexType mixed="true">
+    <xs:sequence minOccurs="0" maxOccurs="unbounded">
+     <xs:any processContents="lax"/>
+    </xs:sequence>
+    <xs:attribute name="source" type="xs:anyURI"/>
+    <xs:attribute ref="xml:lang"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:complexType>
+ </xs:element>
+
+ <xs:element name="annotation" id="annotation">
+   <xs:annotation>
+     <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-annotation"/>
+   </xs:annotation>
+   <xs:complexType>
+    <xs:complexContent>
+     <xs:extension base="xs:openAttrs">
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+       <xs:element ref="xs:appinfo"/>
+       <xs:element ref="xs:documentation"/>
+      </xs:choice>
+      <xs:attribute name="id" type="xs:ID"/>
+     </xs:extension>
+    </xs:complexContent>
+   </xs:complexType>
+ </xs:element>
+
+ <xs:annotation>
+  <xs:documentation>
+   notations for use within XML Schema schemas</xs:documentation>
+ </xs:annotation>
+
+ <xs:notation name="XMLSchemaStructures" public="structures" system="http://www.w3.org/2000/08/XMLSchema.xsd"/>
+ <xs:notation name="XML" public="REC-xml-19980210" system="http://www.w3.org/TR/1998/REC-xml-19980210"/>
+  
+ <xs:complexType name="anyType" mixed="true">
+  <xs:annotation>
+   <xs:documentation>
+   Not the real urType, but as close an approximation as we can
+   get in the XML representation</xs:documentation>
+  </xs:annotation>
+  <xs:sequence>
+   <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
+  </xs:sequence>
+  <xs:anyAttribute processContents="lax"/>
+ </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+      First the built-in primitive datatypes.  These definitions are for
+      information only, the real built-in definitions are magic.
+    </xs:documentation>
+
+    <xs:documentation>
+      For each built-in datatype in this schema (both primitive and
+      derived) can be uniquely addressed via a URI constructed
+      as follows:
+        1) the base URI is the URI of the XML Schema namespace
+        2) the fragment identifier is the name of the datatype
+
+      For example, to address the int datatype, the URI is:
+
+        http://www.w3.org/2001/XMLSchema#int
+
+      Additionally, each facet definition element can be uniquely
+      addressed via a URI constructed as follows:
+        1) the base URI is the URI of the XML Schema namespace
+        2) the fragment identifier is the name of the facet
+
+      For example, to address the maxInclusive facet, the URI is:
+
+        http://www.w3.org/2001/XMLSchema#maxInclusive
+
+      Additionally, each facet usage in a built-in datatype definition
+      can be uniquely addressed via a URI constructed as follows:
+        1) the base URI is the URI of the XML Schema namespace
+        2) the fragment identifier is the name of the datatype, followed
+           by a period (".") followed by the name of the facet
+
+      For example, to address the usage of the maxInclusive facet in
+      the definition of int, the URI is:
+
+        http://www.w3.org/2001/XMLSchema#int.maxInclusive
+
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="string" id="string">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="length"/>
+        <hfp:hasFacet name="minLength"/>
+        <hfp:hasFacet name="maxLength"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality" value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+                source="http://www.w3.org/TR/xmlschema-2/#string"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="preserve" id="string.preserve"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="boolean" id="boolean">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality" value="finite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#boolean"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse" fixed="true"
+        id="boolean.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="float" id="float">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="total"/>
+        <hfp:hasProperty name="bounded" value="true"/>
+        <hfp:hasProperty name="cardinality" value="finite"/>
+        <hfp:hasProperty name="numeric" value="true"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#float"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse" fixed="true"
+        id="float.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="double" id="double">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="total"/>
+        <hfp:hasProperty name="bounded" value="true"/>
+        <hfp:hasProperty name="cardinality" value="finite"/>
+        <hfp:hasProperty name="numeric" value="true"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#double"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="double.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="decimal" id="decimal">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="totalDigits"/>
+        <hfp:hasFacet name="fractionDigits"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="total"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="true"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#decimal"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="decimal.whiteSpace"/>
+    </xs:restriction>
+   </xs:simpleType>
+
+   <xs:simpleType name="duration" id="duration">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="partial"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#duration"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="duration.whiteSpace"/>
+    </xs:restriction>
+   </xs:simpleType>
+
+ <xs:simpleType name="dateTime" id="dateTime">
+    <xs:annotation>
+    <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="partial"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#dateTime"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="dateTime.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="time" id="time">
+    <xs:annotation>
+    <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="partial"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#time"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="time.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="date" id="date">
+   <xs:annotation>
+    <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="partial"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#date"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="date.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="gYearMonth" id="gYearMonth">
+   <xs:annotation>
+    <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="partial"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#gYearMonth"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="gYearMonth.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="gYear" id="gYear">
+    <xs:annotation>
+    <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="partial"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#gYear"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="gYear.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+ <xs:simpleType name="gMonthDay" id="gMonthDay">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="partial"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+       <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#gMonthDay"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+         <xs:whiteSpace value="collapse" fixed="true"
+                id="gMonthDay.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="gDay" id="gDay">
+    <xs:annotation>
+  <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="partial"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#gDay"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+         <xs:whiteSpace value="collapse"  fixed="true"
+                id="gDay.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+ <xs:simpleType name="gMonth" id="gMonth">
+    <xs:annotation>
+  <xs:appinfo>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="maxInclusive"/>
+        <hfp:hasFacet name="maxExclusive"/>
+        <hfp:hasFacet name="minInclusive"/>
+        <hfp:hasFacet name="minExclusive"/>
+        <hfp:hasProperty name="ordered" value="partial"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#gMonth"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+         <xs:whiteSpace value="collapse"  fixed="true"
+                id="gMonth.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+   <xs:simpleType name="hexBinary" id="hexBinary">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="length"/>
+        <hfp:hasFacet name="minLength"/>
+        <hfp:hasFacet name="maxLength"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#binary"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse" fixed="true"
+        id="hexBinary.whiteSpace"/>
+    </xs:restriction>
+   </xs:simpleType>
+
+ <xs:simpleType name="base64Binary" id="base64Binary">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="length"/>
+        <hfp:hasFacet name="minLength"/>
+        <hfp:hasFacet name="maxLength"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+                source="http://www.w3.org/TR/xmlschema-2/#base64Binary"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse" fixed="true"
+        id="base64Binary.whiteSpace"/>
+    </xs:restriction>
+   </xs:simpleType>
+
+   <xs:simpleType name="anyURI" id="anyURI">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="length"/>
+        <hfp:hasFacet name="minLength"/>
+        <hfp:hasFacet name="maxLength"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#anyURI"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="anyURI.whiteSpace"/>
+    </xs:restriction>
+   </xs:simpleType>
+
+  <xs:simpleType name="QName" id="QName">
+    <xs:annotation>
+        <xs:appinfo>
+        <hfp:hasFacet name="length"/>
+        <hfp:hasFacet name="minLength"/>
+        <hfp:hasFacet name="maxLength"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#QName"/>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="QName.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+   <xs:simpleType name="NOTATION" id="NOTATION">
+    <xs:annotation>
+        <xs:appinfo>
+        <hfp:hasFacet name="length"/>
+        <hfp:hasFacet name="minLength"/>
+        <hfp:hasFacet name="maxLength"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#NOTATION"/>
+      <xs:documentation>
+        NOTATION cannot be used directly in a schema; rather a type
+        must be derived from it by specifying at least one enumeration
+        facet whose value is the name of a NOTATION declared in the
+        schema.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:anySimpleType">
+      <xs:whiteSpace value="collapse"  fixed="true"
+        id="NOTATION.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+      Now the derived primitive types
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="normalizedString" id="normalizedString">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#normalizedString"/>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:whiteSpace value="replace"
+        id="normalizedString.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="token" id="token">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#token"/>
+    </xs:annotation>
+    <xs:restriction base="xs:normalizedString">
+      <xs:whiteSpace value="collapse" id="token.whiteSpace"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="language" id="language">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#language"/>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:pattern
+        value="[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*"
+                id="language.pattern">
+        <xs:annotation>
+          <xs:documentation
+                source="http://www.ietf.org/rfc/rfc3066.txt">
+            pattern specifies the content of section 2.12 of XML 1.0e2
+            and RFC 3066 (Revised version of RFC 1766).
+          </xs:documentation>
+        </xs:annotation>
+      </xs:pattern>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="IDREFS" id="IDREFS">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="length"/>
+        <hfp:hasFacet name="minLength"/>
+        <hfp:hasFacet name="maxLength"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#IDREFS"/>
+    </xs:annotation>
+    <xs:restriction>
+      <xs:simpleType>
+        <xs:list itemType="xs:IDREF"/>
+      </xs:simpleType>
+        <xs:minLength value="1" id="IDREFS.minLength"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="ENTITIES" id="ENTITIES">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="length"/>
+        <hfp:hasFacet name="minLength"/>
+        <hfp:hasFacet name="maxLength"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#ENTITIES"/>
+    </xs:annotation>
+    <xs:restriction>
+      <xs:simpleType>
+        <xs:list itemType="xs:ENTITY"/>
+      </xs:simpleType>
+        <xs:minLength value="1" id="ENTITIES.minLength"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="NMTOKEN" id="NMTOKEN">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#NMTOKEN"/>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:pattern value="\c+" id="NMTOKEN.pattern">
+        <xs:annotation>
+          <xs:documentation
+                source="http://www.w3.org/TR/REC-xml#NT-Nmtoken">
+            pattern matches production 7 from the XML spec
+          </xs:documentation>
+        </xs:annotation>
+      </xs:pattern>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="NMTOKENS" id="NMTOKENS">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasFacet name="length"/>
+        <hfp:hasFacet name="minLength"/>
+        <hfp:hasFacet name="maxLength"/>
+        <hfp:hasFacet name="enumeration"/>
+        <hfp:hasFacet name="whiteSpace"/>
+        <hfp:hasFacet name="pattern"/>
+        <hfp:hasProperty name="ordered" value="false"/>
+        <hfp:hasProperty name="bounded" value="false"/>
+        <hfp:hasProperty name="cardinality"
+                value="countably infinite"/>
+        <hfp:hasProperty name="numeric" value="false"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#NMTOKENS"/>
+    </xs:annotation>
+    <xs:restriction>
+      <xs:simpleType>
+        <xs:list itemType="xs:NMTOKEN"/>
+      </xs:simpleType>
+        <xs:minLength value="1" id="NMTOKENS.minLength"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Name" id="Name">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#Name"/>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:pattern value="\i\c*" id="Name.pattern">
+        <xs:annotation>
+          <xs:documentation
+                        source="http://www.w3.org/TR/REC-xml#NT-Name">
+            pattern matches production 5 from the XML spec
+          </xs:documentation>
+        </xs:annotation>
+      </xs:pattern>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="NCName" id="NCName">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#NCName"/>
+    </xs:annotation>
+    <xs:restriction base="xs:Name">
+      <xs:pattern value="[\i-[:]][\c-[:]]*" id="NCName.pattern">
+        <xs:annotation>
+          <xs:documentation
+                source="http://www.w3.org/TR/REC-xml-names/#NT-NCName">
+            pattern matches production 4 from the Namespaces in XML spec
+          </xs:documentation>
+        </xs:annotation>
+      </xs:pattern>
+    </xs:restriction>
+  </xs:simpleType>
+
+   <xs:simpleType name="ID" id="ID">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#ID"/>
+    </xs:annotation>
+    <xs:restriction base="xs:NCName"/>
+   </xs:simpleType>
+
+   <xs:simpleType name="IDREF" id="IDREF">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#IDREF"/>
+    </xs:annotation>
+    <xs:restriction base="xs:NCName"/>
+   </xs:simpleType>
+
+   <xs:simpleType name="ENTITY" id="ENTITY">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#ENTITY"/>
+    </xs:annotation>
+    <xs:restriction base="xs:NCName"/>
+   </xs:simpleType>
+
+  <xs:simpleType name="integer" id="integer">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#integer"/>
+    </xs:annotation>
+    <xs:restriction base="xs:decimal">
+      <xs:fractionDigits value="0" fixed="true" id="integer.fractionDigits"/>
+      <xs:pattern value="[\-+]?[0-9]+"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="nonPositiveInteger" id="nonPositiveInteger">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#nonPositiveInteger"/>
+    </xs:annotation>
+    <xs:restriction base="xs:integer">
+      <xs:maxInclusive value="0" id="nonPositiveInteger.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="negativeInteger" id="negativeInteger">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#negativeInteger"/>
+    </xs:annotation>
+    <xs:restriction base="xs:nonPositiveInteger">
+      <xs:maxInclusive value="-1" id="negativeInteger.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="long" id="long">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasProperty name="bounded" value="true"/>
+        <hfp:hasProperty name="cardinality" value="finite"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#long"/>
+    </xs:annotation>
+    <xs:restriction base="xs:integer">
+      <xs:minInclusive value="-9223372036854775808" id="long.minInclusive"/>
+      <xs:maxInclusive value="9223372036854775807" id="long.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="int" id="int">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#int"/>
+    </xs:annotation>
+    <xs:restriction base="xs:long">
+      <xs:minInclusive value="-2147483648" id="int.minInclusive"/>
+      <xs:maxInclusive value="2147483647" id="int.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="short" id="short">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#short"/>
+    </xs:annotation>
+    <xs:restriction base="xs:int">
+      <xs:minInclusive value="-32768" id="short.minInclusive"/>
+      <xs:maxInclusive value="32767" id="short.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="byte" id="byte">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#byte"/>
+    </xs:annotation>
+    <xs:restriction base="xs:short">
+      <xs:minInclusive value="-128" id="byte.minInclusive"/>
+      <xs:maxInclusive value="127" id="byte.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="nonNegativeInteger" id="nonNegativeInteger">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#nonNegativeInteger"/>
+    </xs:annotation>
+    <xs:restriction base="xs:integer">
+      <xs:minInclusive value="0" id="nonNegativeInteger.minInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="unsignedLong" id="unsignedLong">
+    <xs:annotation>
+      <xs:appinfo>
+        <hfp:hasProperty name="bounded" value="true"/>
+        <hfp:hasProperty name="cardinality" value="finite"/>
+      </xs:appinfo>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#unsignedLong"/>
+    </xs:annotation>
+    <xs:restriction base="xs:nonNegativeInteger">
+      <xs:maxInclusive value="18446744073709551615"
+        id="unsignedLong.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="unsignedInt" id="unsignedInt">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#unsignedInt"/>
+    </xs:annotation>
+    <xs:restriction base="xs:unsignedLong">
+      <xs:maxInclusive value="4294967295"
+        id="unsignedInt.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="unsignedShort" id="unsignedShort">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#unsignedShort"/>
+    </xs:annotation>
+    <xs:restriction base="xs:unsignedInt">
+      <xs:maxInclusive value="65535"
+        id="unsignedShort.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="unsignedByte" id="unsignedByte">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#unsignedByte"/>
+    </xs:annotation>
+    <xs:restriction base="xs:unsignedShort">
+      <xs:maxInclusive value="255" id="unsignedByte.maxInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="positiveInteger" id="positiveInteger">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#positiveInteger"/>
+    </xs:annotation>
+    <xs:restriction base="xs:nonNegativeInteger">
+      <xs:minInclusive value="1" id="positiveInteger.minInclusive"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+ <xs:simpleType name="derivationControl">
+  <xs:annotation>
+   <xs:documentation>
+   A utility type, not for public use</xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:NMTOKEN">
+   <xs:enumeration value="substitution"/>
+   <xs:enumeration value="extension"/>
+   <xs:enumeration value="restriction"/>
+   <xs:enumeration value="list"/>
+   <xs:enumeration value="union"/>
+  </xs:restriction>
+ </xs:simpleType>
+
+ <xs:group name="simpleDerivation">
+  <xs:choice>
+    <xs:element ref="xs:restriction"/>
+    <xs:element ref="xs:list"/>
+    <xs:element ref="xs:union"/>
+  </xs:choice>
+ </xs:group>
+
+ <xs:simpleType name="simpleDerivationSet">
+  <xs:annotation>
+   <xs:documentation>
+   #all or (possibly empty) subset of {restriction, union, list}
+   </xs:documentation>
+   <xs:documentation>
+   A utility type, not for public use</xs:documentation>
+  </xs:annotation>
+  <xs:union>
+   <xs:simpleType>
+    <xs:restriction base="xs:token">
+     <xs:enumeration value="#all"/>
+    </xs:restriction>
+   </xs:simpleType>
+   <xs:simpleType>
+    <xs:list>
+     <xs:simpleType>
+      <xs:restriction base="xs:derivationControl">
+       <xs:enumeration value="list"/>
+       <xs:enumeration value="union"/>
+       <xs:enumeration value="restriction"/>
+      </xs:restriction>
+     </xs:simpleType>
+    </xs:list>
+   </xs:simpleType>
+  </xs:union>
+ </xs:simpleType>
+
+  <xs:complexType name="simpleType" abstract="true">
+    <xs:complexContent>
+      <xs:extension base="xs:annotated">
+        <xs:group ref="xs:simpleDerivation"/>
+        <xs:attribute name="final" type="xs:simpleDerivationSet"/>
+        <xs:attribute name="name" type="xs:NCName">
+          <xs:annotation>
+            <xs:documentation>
+              Can be restricted to required or forbidden
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name="topLevelSimpleType">
+    <xs:complexContent>
+      <xs:restriction base="xs:simpleType">
+        <xs:sequence>
+          <xs:element ref="xs:annotation" minOccurs="0"/>
+          <xs:group ref="xs:simpleDerivation"/>
+        </xs:sequence>
+        <xs:attribute name="name" use="required"
+             type="xs:NCName">
+          <xs:annotation>
+            <xs:documentation>
+              Required at the top level
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+       <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name="localSimpleType">
+    <xs:complexContent>
+      <xs:restriction base="xs:simpleType">
+        <xs:sequence>
+          <xs:element ref="xs:annotation" minOccurs="0"/>
+          <xs:group ref="xs:simpleDerivation"/>
+        </xs:sequence>
+        <xs:attribute name="name" use="prohibited">
+          <xs:annotation>
+            <xs:documentation>
+              Forbidden when nested
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="final" use="prohibited"/>
+       <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="simpleType" type="xs:topLevelSimpleType" id="simpleType">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-simpleType"/>
+    </xs:annotation>
+  </xs:element>
+
+  <xs:group name="facets">
+   <xs:annotation>
+    <xs:documentation>
+       We should use a substitution group for facets, but
+       that's ruled out because it would allow users to
+       add their own, which we're not ready for yet.
+    </xs:documentation>
+   </xs:annotation>
+   <xs:choice>
+    <xs:element ref="xs:minExclusive"/>
+    <xs:element ref="xs:minInclusive"/>
+    <xs:element ref="xs:maxExclusive"/>
+    <xs:element ref="xs:maxInclusive"/>
+    <xs:element ref="xs:totalDigits"/>
+    <xs:element ref="xs:fractionDigits"/>
+    <xs:element ref="xs:length"/>
+    <xs:element ref="xs:minLength"/>
+    <xs:element ref="xs:maxLength"/>
+    <xs:element ref="xs:enumeration"/>
+    <xs:element ref="xs:whiteSpace"/>
+    <xs:element ref="xs:pattern"/>
+   </xs:choice>
+  </xs:group>
+
+  <xs:group name="simpleRestrictionModel">
+   <xs:sequence>
+    <xs:element name="simpleType" type="xs:localSimpleType" minOccurs="0"/>
+    <xs:group ref="xs:facets" minOccurs="0" maxOccurs="unbounded"/>
+   </xs:sequence>
+  </xs:group>
+
+  <xs:element name="restriction" id="restriction">
+   <xs:complexType>
+    <xs:annotation>
+      <xs:documentation
+                source="http://www.w3.org/TR/xmlschema-2/#element-restriction">
+          base attribute and simpleType child are mutually
+          exclusive, but one or other is required
+        </xs:documentation>
+      </xs:annotation>
+      <xs:complexContent>
+        <xs:extension base="xs:annotated">
+         <xs:group ref="xs:simpleRestrictionModel"/>
+         <xs:attribute name="base" type="xs:QName" use="optional"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="list" id="list">
+   <xs:complexType>
+    <xs:annotation>
+      <xs:documentation
+                source="http://www.w3.org/TR/xmlschema-2/#element-list">
+          itemType attribute and simpleType child are mutually
+          exclusive, but one or other is required
+        </xs:documentation>
+      </xs:annotation>
+      <xs:complexContent>
+        <xs:extension base="xs:annotated">
+          <xs:sequence>
+            <xs:element name="simpleType" type="xs:localSimpleType"
+                minOccurs="0"/>
+          </xs:sequence>
+          <xs:attribute name="itemType" type="xs:QName" use="optional"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="union" id="union">
+   <xs:complexType>
+    <xs:annotation>
+      <xs:documentation
+                source="http://www.w3.org/TR/xmlschema-2/#element-union">
+          memberTypes attribute must be non-empty or there must be
+          at least one simpleType child
+        </xs:documentation>
+      </xs:annotation>
+      <xs:complexContent>
+        <xs:extension base="xs:annotated">
+          <xs:sequence>
+            <xs:element name="simpleType" type="xs:localSimpleType"
+                minOccurs="0" maxOccurs="unbounded"/>
+          </xs:sequence>
+          <xs:attribute name="memberTypes" use="optional">
+            <xs:simpleType>
+              <xs:list itemType="xs:QName"/>
+            </xs:simpleType>
+          </xs:attribute>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:complexType name="facet">
+    <xs:complexContent>
+      <xs:extension base="xs:annotated">
+        <xs:attribute name="value" use="required"/>
+        <xs:attribute name="fixed" type="xs:boolean" use="optional"
+                      default="false"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+ <xs:complexType name="noFixedFacet">
+  <xs:complexContent>
+   <xs:restriction base="xs:facet">
+    <xs:sequence>
+     <xs:element ref="xs:annotation" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="fixed" use="prohibited"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+   </xs:restriction>
+  </xs:complexContent>
+ </xs:complexType>
+
+  <xs:element name="minExclusive" id="minExclusive" type="xs:facet">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-minExclusive"/>
+    </xs:annotation>
+  </xs:element>
+  <xs:element name="minInclusive" id="minInclusive" type="xs:facet">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-minInclusive"/>
+    </xs:annotation>
+  </xs:element>
+
+  <xs:element name="maxExclusive" id="maxExclusive" type="xs:facet">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-maxExclusive"/>
+    </xs:annotation>
+  </xs:element>
+  <xs:element name="maxInclusive" id="maxInclusive" type="xs:facet">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-maxInclusive"/>
+    </xs:annotation>
+  </xs:element>
+
+  <xs:complexType name="numFacet">
+    <xs:complexContent>
+      <xs:restriction base="xs:facet">
+       <xs:sequence>
+         <xs:element ref="xs:annotation" minOccurs="0"/>
+       </xs:sequence>
+       <xs:attribute name="value" type="xs:nonNegativeInteger" use="required"/>
+       <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="totalDigits" id="totalDigits">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-totalDigits"/>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:restriction base="xs:numFacet">
+          <xs:sequence>
+            <xs:element ref="xs:annotation" minOccurs="0"/>
+          </xs:sequence>
+          <xs:attribute name="value" type="xs:positiveInteger" use="required"/>
+         <xs:anyAttribute namespace="##other" processContents="lax"/>
+        </xs:restriction>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="fractionDigits" id="fractionDigits" type="xs:numFacet">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-fractionDigits"/>
+    </xs:annotation>
+  </xs:element>
+
+  <xs:element name="length" id="length" type="xs:numFacet">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-length"/>
+    </xs:annotation>
+  </xs:element>
+  <xs:element name="minLength" id="minLength" type="xs:numFacet">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-minLength"/>
+    </xs:annotation>
+  </xs:element>
+  <xs:element name="maxLength" id="maxLength" type="xs:numFacet">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-maxLength"/>
+    </xs:annotation>
+  </xs:element>
+
+  <xs:element name="enumeration" id="enumeration" type="xs:noFixedFacet">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-enumeration"/>
+    </xs:annotation>
+  </xs:element>
+
+  <xs:element name="whiteSpace" id="whiteSpace">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-whiteSpace"/>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:restriction base="xs:facet">
+          <xs:sequence>
+            <xs:element ref="xs:annotation" minOccurs="0"/>
+          </xs:sequence>
+          <xs:attribute name="value" use="required">
+            <xs:simpleType>
+              <xs:restriction base="xs:NMTOKEN">
+                <xs:enumeration value="preserve"/>
+                <xs:enumeration value="replace"/>
+                <xs:enumeration value="collapse"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+         <xs:anyAttribute namespace="##other" processContents="lax"/>
+        </xs:restriction>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="pattern" id="pattern">
+    <xs:annotation>
+      <xs:documentation
+        source="http://www.w3.org/TR/xmlschema-2/#element-pattern"/>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:restriction base="xs:noFixedFacet">
+          <xs:sequence>
+            <xs:element ref="xs:annotation" minOccurs="0"/>
+          </xs:sequence>
+          <xs:attribute name="value" type="xs:string" use="required"/>
+         <xs:anyAttribute namespace="##other" processContents="lax"/>
+        </xs:restriction>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+</xs:schema>
diff --git a/xml/impl/resources/standardSchemas/catalog.xsd b/xml/impl/resources/standardSchemas/catalog.xsd
new file mode 100644
index 0000000..5b932b4
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/catalog.xsd
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
+           xmlns:er='urn:oasis:names:tc:entity:xmlns:xml:catalog'
+           targetNamespace='urn:oasis:names:tc:entity:xmlns:xml:catalog'
+           elementFormDefault='qualified'>
+
+  <!-- $Id: catalog.xsd 226060 2003-04-22 14:53:32Z ndw $ -->
+
+  <xs:simpleType name='pubIdChars'>
+    <!-- A string of the characters defined as pubIdChar in production 13
+         of the Second Edition of the XML 1.0 Recommendation. Does not include
+         the whitespace characters because they're normalized by XML parsing. -->
+    <xs:restriction base='xs:string'>
+      <xs:pattern value="[a-zA-Z0-9-'()+,./:=?;!*#@$_%]*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name='publicIdentifier'>
+    <xs:restriction base='er:pubIdChars'/>
+  </xs:simpleType>
+
+  <xs:simpleType name='partialPublicIdentifier'>
+    <xs:restriction base='er:pubIdChars'/>
+  </xs:simpleType>
+
+  <xs:simpleType name='systemOrPublic'>
+    <xs:restriction base='xs:string'>
+      <xs:enumeration value='system'/>
+      <xs:enumeration value='public'/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <!-- The global attribute xml:base is not explicitly declared; -->
+  <!-- it is allowed by the anyAttribute declarations. -->
+
+  <xs:complexType name='catalog'>
+    <xs:choice minOccurs='1' maxOccurs='unbounded'>
+      <xs:element ref='er:public'/>
+      <xs:element ref='er:system'/>
+      <xs:element ref='er:uri'/>
+      <xs:element ref='er:rewriteSystem'/>
+      <xs:element ref='er:rewriteURI'/>
+      <xs:element ref='er:delegatePublic'/>
+      <xs:element ref='er:delegateSystem'/>
+      <xs:element ref='er:delegateURI'/>
+      <xs:element ref='er:nextCatalog'/>
+      <xs:element ref='er:group'/>
+      <xs:any namespace='##other' processContents='skip'/>
+    </xs:choice>
+    <xs:attribute name='id' type='xs:ID'/>
+    <xs:attribute name='prefer' type='er:systemOrPublic'/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+  </xs:complexType>
+
+  <xs:complexType name='public'>
+    <xs:complexContent>
+      <xs:restriction base="xs:anyType">
+        <xs:attribute name="publicId" type="er:publicIdentifier"
+                       use="required"/>
+        <xs:attribute name="uri" type="xs:anyURI" use="required"/>
+        <xs:attribute name='id' type='xs:ID'/>
+        <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name='system'>
+    <xs:complexContent>
+      <xs:restriction base="xs:anyType">
+        <xs:attribute name="systemId" type="xs:string"
+                       use="required"/>
+        <xs:attribute name="uri" type="xs:anyURI" use="required"/>
+        <xs:attribute name='id' type='xs:ID'/>
+        <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name='uri'>
+    <xs:complexContent>
+      <xs:restriction base="xs:anyType">
+        <xs:attribute name="name" type="xs:anyURI"
+                       use="required"/>
+        <xs:attribute name="uri" type="xs:anyURI" use="required"/>
+        <xs:attribute name='id' type='xs:ID'/>
+        <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name='rewriteSystem'>
+    <xs:complexContent>
+      <xs:restriction base="xs:anyType">
+        <xs:attribute name="systemIdStartString"
+                       type="xs:string"
+                       use="required"/>
+        <xs:attribute name="rewritePrefix" type="xs:string" use="required"/>
+        <xs:attribute name='id' type='xs:ID'/>
+        <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name='rewriteURI'>
+    <xs:complexContent>
+      <xs:restriction base="xs:anyType">
+        <xs:attribute name="uriIdStartString"
+                       type="xs:string"
+                       use="required"/>
+        <xs:attribute name="rewritePrefix" type="xs:string" use="required"/>
+        <xs:attribute name='id' type='xs:ID'/>
+        <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name='delegatePublic'>
+    <xs:complexContent>
+      <xs:restriction base="xs:anyType">
+        <xs:attribute name="publicIdStartString"
+                       type="er:partialPublicIdentifier"
+                       use="required"/>
+        <xs:attribute name="catalog" type="xs:anyURI" use="required"/>
+        <xs:attribute name='id' type='xs:ID'/>
+        <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name='delegateSystem'>
+    <xs:complexContent>
+      <xs:restriction base="xs:anyType">
+        <xs:attribute name="systemIdStartString"
+                       type="xs:string"
+                       use="required"/>
+        <xs:attribute name="catalog" type="xs:anyURI" use="required"/>
+        <xs:attribute name='id' type='xs:ID'/>
+        <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name='delegateURI'>
+    <xs:complexContent>
+      <xs:restriction base="xs:anyType">
+        <xs:attribute name="uriStartString"
+                       type="xs:string"
+                       use="required"/>
+        <xs:attribute name="catalog" type="xs:anyURI" use="required"/>
+        <xs:attribute name='id' type='xs:ID'/>
+        <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name='nextCatalog'>
+    <xs:complexContent>
+      <xs:restriction base="xs:anyType">
+        <xs:attribute name="catalog" type="xs:anyURI" use="required"/>
+        <xs:attribute name='id' type='xs:ID'/>
+        <xs:anyAttribute namespace="##other" processContents="lax"/>
+      </xs:restriction>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name='group'>
+    <xs:choice minOccurs='1' maxOccurs='unbounded'>
+      <xs:element ref='er:public'/>
+      <xs:element ref='er:system'/>
+      <xs:element ref='er:uri'/>
+      <xs:element ref='er:rewriteSystem'/>
+      <xs:element ref='er:rewriteURI'/>
+      <xs:element ref='er:delegatePublic'/>
+      <xs:element ref='er:delegateSystem'/>
+      <xs:element ref='er:delegateURI'/>
+      <xs:element ref='er:nextCatalog'/>
+      <xs:any namespace='##other' processContents='skip'/>
+    </xs:choice>
+    <xs:attribute name='prefer' type='er:systemOrPublic'/>
+    <xs:attribute name='id' type='xs:ID'/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+  </xs:complexType>
+
+  <xs:element name="catalog" type="er:catalog"/>
+  <xs:element name="public" type="er:public"/>
+  <xs:element name="system" type="er:system"/>
+  <xs:element name="uri" type="er:uri"/>
+  <xs:element name="rewriteSystem" type="er:rewriteSystem"/>
+  <xs:element name="rewriteURI" type="er:rewriteURI"/>
+  <xs:element name="delegatePublic" type="er:delegatePublic"/>
+  <xs:element name="delegateSystem" type="er:delegateSystem"/>
+  <xs:element name="delegateURI" type="er:delegateURI"/>
+  <xs:element name="nextCatalog" type="er:nextCatalog"/>
+  <xs:element name="group" type="er:group"/>
+
+</xs:schema>
diff --git a/xml/impl/resources/standardSchemas/datatypes.dtd b/xml/impl/resources/standardSchemas/datatypes.dtd
new file mode 100644
index 0000000..ed07e4e
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/datatypes.dtd
@@ -0,0 +1,203 @@
+<!--
+        DTD for XML Schemas: Part 2: Datatypes
+        $Id: datatypes.dtd,v 1.23 2001/03/16 17:36:30 ht Exp $
+        Note this DTD is NOT normative, or even definitive. - - the
+        prose copy in the datatypes REC is the definitive version
+        (which shouldn't differ from this one except for this comment
+        and entity expansions, but just in case)
+  -->
+
+<!--
+        This DTD cannot be used on its own, it is intended
+        only for incorporation in XMLSchema.dtd, q.v.
+  -->
+
+<!-- Define all the element names, with optional prefix -->
+<!ENTITY % simpleType "%p;simpleType">
+<!ENTITY % restriction "%p;restriction">
+<!ENTITY % list "%p;list">
+<!ENTITY % union "%p;union">
+<!ENTITY % maxExclusive "%p;maxExclusive">
+<!ENTITY % minExclusive "%p;minExclusive">
+<!ENTITY % maxInclusive "%p;maxInclusive">
+<!ENTITY % minInclusive "%p;minInclusive">
+<!ENTITY % totalDigits "%p;totalDigits">
+<!ENTITY % fractionDigits "%p;fractionDigits">
+<!ENTITY % length "%p;length">
+<!ENTITY % minLength "%p;minLength">
+<!ENTITY % maxLength "%p;maxLength">
+<!ENTITY % enumeration "%p;enumeration">
+<!ENTITY % whiteSpace "%p;whiteSpace">
+<!ENTITY % pattern "%p;pattern">
+
+<!--
+        Customisation entities for the ATTLIST of each element
+        type. Define one of these if your schema takes advantage
+        of the anyAttribute='##other' in the schema for schemas
+  -->
+
+<!ENTITY % simpleTypeAttrs "">
+<!ENTITY % restrictionAttrs "">
+<!ENTITY % listAttrs "">
+<!ENTITY % unionAttrs "">
+<!ENTITY % maxExclusiveAttrs "">
+<!ENTITY % minExclusiveAttrs "">
+<!ENTITY % maxInclusiveAttrs "">
+<!ENTITY % minInclusiveAttrs "">
+<!ENTITY % totalDigitsAttrs "">
+<!ENTITY % fractionDigitsAttrs "">
+<!ENTITY % lengthAttrs "">
+<!ENTITY % minLengthAttrs "">
+<!ENTITY % maxLengthAttrs "">
+<!ENTITY % enumerationAttrs "">
+<!ENTITY % whiteSpaceAttrs "">
+<!ENTITY % patternAttrs "">
+
+<!-- Define some entities for informative use as attribute
+        types -->
+<!ENTITY % URIref "CDATA">
+<!ENTITY % XPathExpr "CDATA">
+<!ENTITY % QName "NMTOKEN">
+<!ENTITY % QNames "NMTOKENS">
+<!ENTITY % NCName "NMTOKEN">
+<!ENTITY % nonNegativeInteger "NMTOKEN">
+<!ENTITY % boolean "(true|false)">
+<!ENTITY % simpleDerivationSet "CDATA">
+<!--
+        #all or space-separated list drawn from derivationChoice
+  -->
+
+<!--
+        Note that the use of 'facet' below is less restrictive
+        than is really intended:  There should in fact be no
+        more than one of each of minInclusive, minExclusive,
+        maxInclusive, maxExclusive, totalDigits, fractionDigits,
+        length, maxLength, minLength within datatype,
+        and the min- and max- variants of Inclusive and Exclusive
+        are mutually exclusive. On the other hand,  pattern and
+        enumeration may repeat.
+  -->
+<!ENTITY % minBound "(%minInclusive; | %minExclusive;)">
+<!ENTITY % maxBound "(%maxInclusive; | %maxExclusive;)">
+<!ENTITY % bounds "%minBound; | %maxBound;">
+<!ENTITY % numeric "%totalDigits; | %fractionDigits;">
+<!ENTITY % ordered "%bounds; | %numeric;">
+<!ENTITY % unordered
+   "%pattern; | %enumeration; | %whiteSpace; | %length; |
+   %maxLength; | %minLength;">
+<!ENTITY % facet "%ordered; | %unordered;">
+<!ENTITY % facetAttr
+        "value CDATA #REQUIRED
+        id ID #IMPLIED">
+<!ENTITY % fixedAttr "fixed %boolean; #IMPLIED">
+<!ENTITY % facetModel "(%annotation;)?">
+<!ELEMENT %simpleType;
+        ((%annotation;)?, (%restriction; | %list; | %union;))>
+<!ATTLIST %simpleType;
+    name      %NCName; #IMPLIED
+    final     %simpleDerivationSet; #IMPLIED
+    id        ID       #IMPLIED
+    %simpleTypeAttrs;>
+<!-- name is required at top level -->
+<!ELEMENT %restriction; ((%annotation;)?,
+                         (%restriction1; |
+                          ((%simpleType;)?,(%facet;)*)),
+                         (%attrDecls;))>
+<!ATTLIST %restriction;
+    base      %QName;                  #IMPLIED
+    id        ID       #IMPLIED
+    %restrictionAttrs;>
+<!--
+        base and simpleType child are mutually exclusive,
+        one is required.
+
+        restriction is shared between simpleType and
+        simpleContent and complexContent (in XMLSchema.xsd).
+        restriction1 is for the latter cases, when this
+        is restricting a complex type, as is attrDecls.
+  -->
+<!ELEMENT %list; ((%annotation;)?,(%simpleType;)?)>
+<!ATTLIST %list;
+    itemType      %QName;             #IMPLIED
+    id        ID       #IMPLIED
+    %listAttrs;>
+<!--
+        itemType and simpleType child are mutually exclusive,
+        one is required
+  -->
+<!ELEMENT %union; ((%annotation;)?,(%simpleType;)*)>
+<!ATTLIST %union;
+    id            ID       #IMPLIED
+    memberTypes   %QNames;            #IMPLIED
+    %unionAttrs;>
+<!--
+        At least one item in memberTypes or one simpleType
+        child is required
+  -->
+
+<!ELEMENT %maxExclusive; %facetModel;>
+<!ATTLIST %maxExclusive;
+        %facetAttr;
+        %fixedAttr;
+        %maxExclusiveAttrs;>
+<!ELEMENT %minExclusive; %facetModel;>
+<!ATTLIST %minExclusive;
+        %facetAttr;
+        %fixedAttr;
+        %minExclusiveAttrs;>
+
+<!ELEMENT %maxInclusive; %facetModel;>
+<!ATTLIST %maxInclusive;
+        %facetAttr;
+        %fixedAttr;
+        %maxInclusiveAttrs;>
+<!ELEMENT %minInclusive; %facetModel;>
+<!ATTLIST %minInclusive;
+        %facetAttr;
+        %fixedAttr;
+        %minInclusiveAttrs;>
+
+<!ELEMENT %totalDigits; %facetModel;>
+<!ATTLIST %totalDigits;
+        %facetAttr;
+        %fixedAttr;
+        %totalDigitsAttrs;>
+<!ELEMENT %fractionDigits; %facetModel;>
+<!ATTLIST %fractionDigits;
+        %facetAttr;
+        %fixedAttr;
+        %fractionDigitsAttrs;>
+
+<!ELEMENT %length; %facetModel;>
+<!ATTLIST %length;
+        %facetAttr;
+        %fixedAttr;
+        %lengthAttrs;>
+<!ELEMENT %minLength; %facetModel;>
+<!ATTLIST %minLength;
+        %facetAttr;
+        %fixedAttr;
+        %minLengthAttrs;>
+<!ELEMENT %maxLength; %facetModel;>
+<!ATTLIST %maxLength;
+        %facetAttr;
+        %fixedAttr;
+        %maxLengthAttrs;>
+
+<!-- This one can be repeated -->
+<!ELEMENT %enumeration; %facetModel;>
+<!ATTLIST %enumeration;
+        %facetAttr;
+        %enumerationAttrs;>
+
+<!ELEMENT %whiteSpace; %facetModel;>
+<!ATTLIST %whiteSpace;
+        %facetAttr;
+        %fixedAttr;
+        %whiteSpaceAttrs;>
+
+<!-- This one can be repeated -->
+<!ELEMENT %pattern; %facetModel;>
+<!ATTLIST %pattern;
+        %facetAttr;
+        %patternAttrs;>
diff --git a/xml/impl/resources/standardSchemas/html5/xhtml5.xsd b/xml/impl/resources/standardSchemas/html5/xhtml5.xsd
new file mode 100644
index 0000000..7158a7e
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/html5/xhtml5.xsd
@@ -0,0 +1,4611 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE xs:schema [
+<!ENTITY % HTMLlat1 PUBLIC
+       "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+       "../xhtml-lat1.ent">
+    %HTMLlat1;
+
+    <!ENTITY % HTMLsymbol PUBLIC
+       "-//W3C//ENTITIES Symbols for XHTML//EN"
+       "../xhtml-symbol.ent">
+    %HTMLsymbol;
+
+    <!ENTITY % HTMLspecial PUBLIC
+       "-//W3C//ENTITIES Special for XHTML//EN"
+       "../xhtml-special.ent">
+    %HTMLspecial;
+]>
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.w3.org/1999/xhtml"
+           xmlns:xhtml="http://www.w3.org/1999/xhtml">
+
+  <!-- ##################################################################### -->
+  <!--
+                            (This only affects mixed-version modules; wholly HTML5
+                             modules should simply be left out of the inclusion list.)
+  -->
+  <!--  (xml:base on elements other than <html>) -->
+  <!-- ##################################################################### -->
+
+  <xs:group name="common.elem.anything">
+    <xs:annotation>
+      <xs:documentation>Any element from any namespace</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:any processContents="skip"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:complexType name="common.inner.anything" mixed="true">
+    <xs:annotation>
+      <xs:documentation>Any content from any namespace</xs:documentation>
+    </xs:annotation>
+    <xs:group minOccurs="0" maxOccurs="unbounded" ref="common.elem.anything"/>
+  </xs:complexType>
+  <!-- ##################################################################### -->
+  <xs:group name="common.elem.metadata">
+    <xs:annotation>
+      <xs:documentation>Common Element Classes #</xs:documentation>
+    </xs:annotation>
+    <xs:choice>
+      <xs:element ref="xhtml:link"/>
+      <xs:group ref="xhtml:style.elem"/>
+      <xs:group ref="xhtml:meta.name.elem"/>
+      <xs:group ref="xhtml:meta.http-equiv.refresh.elem"/>
+      <xs:group ref="xhtml:meta.http-equiv.default-style.elem"/>
+      <xs:group ref="xhtml:meta.http-equiv.content-language.elem"/>
+      <xs:group ref="xhtml:meta.charset.elem"/>
+      <xs:group ref="xhtml:script.elem"/>
+      <xs:group ref="xhtml:command.elem"/>
+    </xs:choice>
+  </xs:group>
+  <xs:group name="common.elem.phrasing">
+    <xs:annotation>
+      <xs:documentation>Phrase Elements</xs:documentation>
+    </xs:annotation>
+    <xs:choice>
+      <xs:group ref="xhtml:a.elem.phrasing"/>
+      <xs:element ref="xhtml:em"/>
+      <xs:element ref="xhtml:strong"/>
+      <xs:element ref="xhtml:small"/>
+      <xs:element ref="xhtml:mark"/>
+      <xs:element ref="xhtml:abbr"/>
+      <xs:element ref="xhtml:dfn"/>
+      <xs:element ref="xhtml:i"/>
+      <xs:element ref="xhtml:b"/>
+      <xs:element ref="xhtml:code"/>
+      <xs:element ref="xhtml:var"/>
+      <xs:element ref="xhtml:samp"/>
+      <xs:element ref="xhtml:kbd"/>
+      <xs:element ref="xhtml:sup"/>
+      <xs:element ref="xhtml:sub"/>
+      <xs:element ref="xhtml:q"/>
+      <xs:element ref="xhtml:cite"/>
+      <xs:element ref="xhtml:span"/>
+      <xs:element ref="xhtml:bdo"/>
+      <xs:element ref="xhtml:br"/>
+      <xs:element ref="xhtml:wbr"/>
+      <xs:element ref="xhtml:s"/>
+      <xs:group ref="xhtml:ins.elem.phrasing"/>
+      <xs:group ref="xhtml:del.elem.phrasing"/>
+      <xs:element ref="xhtml:img"/>
+      <xs:element ref="xhtml:embed"/>
+      <xs:group ref="xhtml:object.elem.phrasing"/>
+      <xs:element ref="xhtml:iframe"/>
+      <xs:group ref="xhtml:map.elem.phrasing"/>
+      <xs:element ref="xhtml:area"/>
+      <xs:element ref="xhtml:ruby"/>
+      <xs:group ref="xhtml:video.elem.phrasing"/>
+      <xs:group ref="xhtml:audio.elem.phrasing"/>
+      <xs:group ref="xhtml:script.elem"/>
+      <xs:group ref="xhtml:input.elem"/>
+      <xs:element ref="xhtml:textarea"/>
+      <xs:element ref="xhtml:select"/>
+      <xs:group ref="xhtml:button.elem"/>
+      <xs:element ref="xhtml:label"/>
+      <xs:element ref="xhtml:output"/>
+      <xs:element ref="xhtml:datalist"/>
+      <xs:element ref="xhtml:keygen"/>
+      <xs:element ref="xhtml:progress"/>
+      <xs:group ref="xhtml:command.elem"/>
+      <xs:element ref="xhtml:bb"/>
+      <xs:group ref="xhtml:canvas.elem.phrasing"/>
+      <xs:element ref="xhtml:time"/>
+      <xs:element ref="xhtml:meter"/>
+    </xs:choice>
+  </xs:group>
+  <xs:group name="common.elem.flow">
+    <xs:annotation>
+      <xs:documentation>Prose Elements</xs:documentation>
+    </xs:annotation>
+    <xs:choice>
+      <xs:group ref="common.elem.phrasing"/>
+      <xs:group ref="xhtml:a.elem.flow"/>
+      <xs:element ref="xhtml:p"/>
+      <xs:element ref="xhtml:hr"/>
+      <xs:element ref="xhtml:pre"/>
+      <xs:element ref="xhtml:ul"/>
+      <xs:element ref="xhtml:ol"/>
+      <xs:element ref="xhtml:dl"/>
+      <xs:element ref="xhtml:div"/>
+      <xs:element ref="xhtml:h1"/>
+      <xs:element ref="xhtml:h2"/>
+      <xs:element ref="xhtml:h3"/>
+      <xs:element ref="xhtml:h4"/>
+      <xs:element ref="xhtml:h5"/>
+      <xs:element ref="xhtml:h6"/>
+      <xs:element ref="xhtml:hgroup"/>
+      <xs:element ref="xhtml:address"/>
+      <xs:element ref="xhtml:blockquote"/>
+      <xs:element ref="xhtml:section"/>
+      <xs:element ref="xhtml:nav"/>
+      <xs:element ref="xhtml:article"/>
+      <xs:element ref="xhtml:aside"/>
+      <xs:element ref="xhtml:header"/>
+      <xs:element ref="xhtml:footer"/>
+      <xs:element ref="xhtml:dialog"/>
+      <xs:group ref="xhtml:ins.elem.flow"/>
+      <xs:group ref="xhtml:del.elem.flow"/>
+      <xs:group ref="xhtml:object.elem.flow"/>
+      <xs:group ref="xhtml:map.elem.flow"/>
+      <xs:group ref="xhtml:video.elem.flow"/>
+      <xs:group ref="xhtml:audio.elem.flow"/>
+      <xs:element ref="xhtml:figure"/>
+      <xs:element ref="xhtml:table"/>
+      <xs:element ref="xhtml:form"/>
+      <xs:element ref="xhtml:fieldset"/>
+      <xs:element ref="xhtml:datagrid"/>
+      <xs:element ref="xhtml:menu"/>
+      <xs:group ref="xhtml:canvas.elem.flow"/>
+      <xs:element ref="xhtml:details"/>
+    </xs:choice>
+  </xs:group>
+  <!-- ##################################################################### -->
+  <xs:group name="common.inner.metadata">
+    <xs:annotation>
+      <xs:documentation>Common Content Models #</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:group minOccurs="0" maxOccurs="unbounded" ref="common.elem.metadata"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="common.inner.phrasing">
+    <xs:annotation>
+      <xs:documentation>Phrase Content</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:group minOccurs="0" maxOccurs="unbounded" ref="common.elem.phrasing"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="common.inner.flow">
+    <xs:annotation>
+      <xs:documentation>Prose Content</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:group minOccurs="0" maxOccurs="unbounded" ref="common.elem.flow"/>
+    </xs:sequence>
+  </xs:group>
+  <!-- REVISIT <style scoped> -->
+  <!-- ##################################################################### -->
+  <!-- ##################################################################### -->
+  <!-- When updating, check <bdo> definition too -->
+  <xs:attributeGroup name="common.attrs">
+    <xs:annotation>
+      <xs:documentation>Common Attributes #</xs:documentation>
+    </xs:annotation>
+    <xs:attributeGroup ref="common.attrs.basic"/>
+    <xs:attributeGroup ref="common.attrs.i18n"/>
+    <xs:attributeGroup ref="common.attrs.present"/>
+    <xs:attributeGroup ref="common.attrs.other"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="common.attrs.basic">
+    <xs:attribute name="id" type="common.data.id"/>
+    <xs:attribute ref="xml:id"/>
+    <xs:attribute name="class" type="common.data.tokens"/>
+    <xs:attribute name="title"/>
+    <xs:attribute name="role"/>
+    <xs:attribute ref="xml:base"/>
+    <xs:attribute ref="xml:space"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="common.attrs.i18n">
+    <xs:attribute name="dir">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="ltr"/>
+          <xs:enumeration value="rtl"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attributeGroup ref="common.attrs.language"/>
+  </xs:attributeGroup>
+  <!--
+    This lang definition is a hack for enviroments where
+    the HTML5 parser maps lang to xml:lang.
+    Sameness check left to Schematron
+  -->
+  <xs:attributeGroup name="common.attrs.language">
+    <xs:attribute ref="xml:lang"/>
+    <xs:attribute name="lang" type="common.data.langcode"/>
+  </xs:attributeGroup>
+  <!--
+    	common.attrs.language =
+    		(	common.attrs.lang
+    		|	common.attrs.xmllang
+    		)
+    	common.attrs.lang =
+    		attribute lang {
+    			common.data.langcode
+    		} & HTMLonly
+    	common.attrs.xmllang =
+    		attribute xml:lang {
+    			common.data.langcode
+    		} & XMLonly
+  -->
+  <xs:attributeGroup name="common.attrs.present">
+    <xs:attribute name="style" type="xs:string"/>
+    <xs:attribute name="tabindex" type="common.data.integer"/>
+    <xs:attribute name="accesskey" type="common.data.keylabellist"/>
+  </xs:attributeGroup>
+  <!-- REVISIT move style to a module and bundle tabindex with ARIA -->
+  <xs:attributeGroup name="common.attrs.other">
+    <xs:attributeGroup ref="xhtml:common.attrs.scripting"/>
+    <xs:attributeGroup ref="xhtml:common.attrs.interact"/>
+  </xs:attributeGroup>
+  <!-- ##################################################################### -->
+  <xs:simpleType name="common.data.tokens">
+    <xs:annotation>
+      <xs:documentation>Common Datatypes #</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:NMTOKENS"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.browsing-context">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.browsing-context-or-keyword">
+    <xs:restriction base="xs:NMTOKEN">
+      <xs:pattern value="_(blank|self|parent|top)|[A-Za-z]\c*"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.charset">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[uU][tT][fF]-8"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="SandboxType">
+    <xs:union>
+      <xs:simpleType>
+        <xs:restriction>
+          <xs:simpleType>
+            <xs:list>
+              <xs:simpleType>
+                <xs:restriction base="xs:token">
+                  <xs:enumeration value="allow-same-origin"/>
+                  <xs:enumeration value="allow-forms"/>
+                  <xs:enumeration value="allow-scripts"/>
+                </xs:restriction>
+              </xs:simpleType>
+            </xs:list>
+          </xs:simpleType>
+          <xs:maxLength value="3"/>
+        </xs:restriction>
+      </xs:simpleType>
+      <xs:simpleType>
+        <xs:restriction>
+          <xs:simpleType>
+            <xs:list>
+              <xs:simpleType>
+                <xs:restriction base="xs:token">
+                  <xs:enumeration value="allow-same-origin"/>
+                  <xs:enumeration value="allow-scripts"/>
+                  <xs:enumeration value="allow-forms"/>
+                </xs:restriction>
+              </xs:simpleType>
+            </xs:list>
+          </xs:simpleType>
+          <xs:maxLength value="3"/>
+        </xs:restriction>
+      </xs:simpleType>
+      <xs:simpleType>
+        <xs:restriction>
+          <xs:simpleType>
+            <xs:list>
+              <xs:simpleType>
+                <xs:restriction base="xs:token">
+                  <xs:enumeration value="allow-forms"/>
+                  <xs:enumeration value="allow-same-origin"/>
+                  <xs:enumeration value="allow-scripts"/>
+                </xs:restriction>
+              </xs:simpleType>
+            </xs:list>
+          </xs:simpleType>
+          <xs:maxLength value="3"/>
+        </xs:restriction>
+      </xs:simpleType>
+      <xs:simpleType>
+        <xs:restriction>
+          <xs:simpleType>
+            <xs:list>
+              <xs:simpleType>
+                <xs:restriction base="xs:token">
+                  <xs:enumeration value="allow-forms"/>
+                  <xs:enumeration value="allow-scripts"/>
+                  <xs:enumeration value="allow-same-origin"/>
+                </xs:restriction>
+              </xs:simpleType>
+            </xs:list>
+          </xs:simpleType>
+          <xs:maxLength value="3"/>
+        </xs:restriction>
+      </xs:simpleType>
+      <xs:simpleType>
+        <xs:restriction>
+          <xs:simpleType>
+            <xs:list>
+              <xs:simpleType>
+                <xs:restriction base="xs:token">
+                  <xs:enumeration value="allow-scripts"/>
+                  <xs:enumeration value="allow-same-origin"/>
+                  <xs:enumeration value="allow-forms"/>
+                </xs:restriction>
+              </xs:simpleType>
+            </xs:list>
+          </xs:simpleType>
+          <xs:maxLength value="3"/>
+        </xs:restriction>
+      </xs:simpleType>
+      <xs:simpleType>
+        <xs:restriction>
+          <xs:simpleType>
+            <xs:list>
+              <xs:simpleType>
+                <xs:restriction base="xs:token">
+                  <xs:enumeration value="allow-scripts"/>
+                  <xs:enumeration value="allow-forms"/>
+                  <xs:enumeration value="allow-same-origin"/>
+                </xs:restriction>
+              </xs:simpleType>
+            </xs:list>
+          </xs:simpleType>
+          <xs:maxLength value="3"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:union>
+  </xs:simpleType>
+
+  <!--
+    		xsd:string {
+    			pattern = "()|([^_].*)|(_[bB][lL][aA][nN][kK])|(_[sS][eE][lL][fF])|(_[pP][aA][rR][eE][nN][tT])|(_[tT][oO][pP])"
+    		}
+  -->
+  <xs:simpleType name="common.data.id">
+    <xs:annotation>
+      <xs:documentation>IDs and IDREFs</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:ID"/>
+  </xs:simpleType>
+  <!--
+    		xsd:string {
+    			pattern = "\S+"
+    		}
+  -->
+  <xs:simpleType name="common.data.idref">
+    <xs:restriction base="xs:ID"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.idrefs">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.name">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <!-- FIXME -->
+  <xs:simpleType name="common.data.hash-name">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <!--
+    		xsd:string {
+    			pattern = "#.+"
+    		}
+  -->
+  <xs:simpleType name="common.data.integer">
+    <xs:annotation>
+      <xs:documentation>Numerical</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="-?[0-9]+"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <!--
+    		xsd:string {
+    			pattern = "-?[0-9]+"
+    		}
+  -->
+  <xs:simpleType name="common.data.integer.positive">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="0*[1-9][0-9]*"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <!--
+    		xsd:string {
+    			pattern = "0*[1-9][0-9]*"
+    		}
+  -->
+  <xs:simpleType name="common.data.integer.non-negative">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[0-9]+"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <!--
+    		xsd:string {
+    			pattern = "[0-9]+"
+    		}
+  -->
+  <!--
+    	common.data.percent =
+    		xsd:string {
+    			pattern = "(100)|([1-9]?[0-9](\.[0-9]+)?)%"
+    		}
+  -->
+  <xs:simpleType name="common.data.float">
+    <xs:restriction base="xs:float">
+      <xs:pattern value="-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <!--
+    		xsd:string {
+    			pattern = "-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?"
+    		}
+  -->
+  <xs:simpleType name="common.data.float.positive">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="(0*[1-9][0-9]*(\.[0-9]+)?)|([0-9]+(\.0*[1-9][0-9]*)?)([eE]-?[0-9]+)?"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <!--
+    		xsd:string {
+    			pattern = "(0*[1-9][0-9]*(\.[0-9]+)?)|([0-9]+(\.0*[1-9][0-9]*)?)([eE]-?[0-9]+)?"
+    		}
+  -->
+  <xs:simpleType name="common.data.float.non-negative">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <!--
+    		xsd:string {
+    			pattern = "[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?"
+    		}
+  -->
+  <xs:simpleType name="common.data.datetime">
+    <xs:annotation>
+      <xs:documentation>Temporal</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.date-or-time">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.uri">
+    <xs:annotation>
+      <xs:documentation>IRIs</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:anyURI"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.uris">
+    <xs:list itemType="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.uri.absolute">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.sizes">
+    <xs:annotation>
+      <xs:documentation>&lt;link type='icon'&gt; sizes</xs:documentation>
+    </xs:annotation>
+    <xs:restriction>
+      <xs:simpleType>
+        <xs:list>
+          <xs:simpleType>
+            <xs:restriction base="xs:string">
+              <xs:pattern value="[1-9][0-9]*x[1-9][0-9]*"/>
+            </xs:restriction>
+          </xs:simpleType>
+        </xs:list>
+      </xs:simpleType>
+      <xs:minLength value="1"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.mimetype">
+    <xs:annotation>
+      <xs:documentation>MIME types</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.meta-charset">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.refresh">
+    <xs:annotation>
+      <xs:documentation>Refresh</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.default-style">
+    <xs:annotation>
+      <xs:documentation>Default style</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <!-- 		w:default-style -->
+  <xs:simpleType name="common.data.mediaquery">
+    <xs:annotation>
+      <xs:documentation>Media Queries</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.langcode">
+    <xs:annotation>
+      <xs:documentation>Language Codes</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:language"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.keylabellist">
+    <xs:annotation>
+      <xs:documentation>List of Key Labels</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.microdata-identifier">
+    <xs:annotation>
+      <xs:documentation>Microdata Identifier</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="common.data.zero">
+    <xs:annotation>
+      <xs:documentation>Zero</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <!-- ##################################################################### -->
+  <!-- ##################################################################### -->
+  <xs:attributeGroup name="common-form.attrs.form">
+    <xs:annotation>
+      <xs:documentation>WF2 Module Hook #</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="form" type="common.data.idref"/>
+  </xs:attributeGroup>
+  <!-- ##################################################################### -->
+  <!-- ##################################################################### -->
+
+  <xs:element name="html">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:html.inner">
+          <xs:attributeGroup ref="xhtml:html.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="html.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="manifest" type="common.data.uri"/>
+  </xs:attributeGroup>
+  <xs:complexType name="html.inner">
+    <xs:sequence>
+      <xs:element ref="xhtml:head"/>
+      <xs:element ref="xhtml:body"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="head">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:head.inner">
+          <xs:attributeGroup ref="xhtml:head.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="head.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <!--
+    		head.attrs.profile =
+    			attribute profile {
+    				common.data.uris #REVISIT should these be absolute (zero or more)
+    			}
+  -->
+  <xs:complexType name="head.inner">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="xhtml:title"/>
+      <xs:element ref="xhtml:base"/>
+      <xs:group ref="common.inner.metadata"/>
+    </xs:choice>
+  </xs:complexType>
+  <!--
+    	head.inner =
+    		(	meta.elem.encoding?
+    		,	(	title.elem
+    			&	base.elem? # REVISIT need a non-schema checker or Schematron
+    			&	common.inner.metadata
+    			)
+    		)
+  -->
+  <xs:element name="body">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:body.inner">
+          <xs:attributeGroup ref="xhtml:body.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="body.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="onafterprint" type="xs:string"/>
+    <xs:attribute name="onbeforeprint" type="xs:string"/>
+    <xs:attribute name="onbeforeunload" type="xs:string"/>
+    <xs:attribute name="onhashchange" type="xs:string"/>
+    <xs:attribute name="onmessage" type="xs:string"/>
+    <xs:attribute name="onoffline" type="xs:string"/>
+    <xs:attribute name="ononline" type="xs:string"/>
+    <xs:attribute name="onpopstate" type="xs:string"/>
+    <xs:attribute name="onredo" type="xs:string"/>
+    <xs:attribute name="onresize" type="xs:string"/>
+    <xs:attribute name="onstorage" type="xs:string"/>
+    <xs:attribute name="onundo" type="xs:string"/>
+    <xs:attribute name="onunload" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:complexType name="body.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:element name="title">
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="xhtml:title.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="title.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:element name="base">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:base.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="base.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="href" type="common.data.uri"/>
+    <xs:attribute name="target" type="common.data.browsing-context-or-keyword"/>
+  </xs:attributeGroup>
+  <xs:element name="link">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:link.attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:attributeGroup name="link.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:shared-hyperlink.attrs.href"/>
+    <xs:attributeGroup ref="xhtml:shared-hyperlink.attrs.rel"/>
+    <xs:attribute name="hreflang" type="common.data.langcode"/>
+    <xs:attribute name="media" type="common.data.mediaquery"/>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attribute name="sizes">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="style.elem">
+    <xs:annotation>
+      <xs:documentation>Global Style: &lt;style&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="style">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:style.inner">
+              <xs:attributeGroup ref="xhtml:style.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="style.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attribute name="media" type="common.data.mediaquery"/>
+  </xs:attributeGroup>
+  <xs:complexType name="style.inner">
+    <xs:complexContent>
+      <xs:extension base="common.inner.anything"/>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:group name="style.elem.scoped">
+    <xs:annotation>
+      <xs:documentation>Scoped Style: &lt;style scoped&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="style">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:style.inner">
+              <xs:attributeGroup ref="xhtml:style.scoped.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="style.scoped.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attribute name="media" type="common.data.mediaquery"/>
+    <xs:attributeGroup ref="xhtml:style.attrs.scoped"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="style.attrs.scoped">
+    <xs:attribute name="scoped" use="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="scoped"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:element name="meta">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:common.attrs"/>
+      <xs:attributeGroup ref="xhtml:meta.name.attrs"/>
+      <xs:attributeGroup ref="xhtml:meta.http-equiv.refresh.attrs"/>
+      <xs:attributeGroup ref="xhtml:meta.charset.attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:group name="meta.name.elem">
+    <xs:annotation>
+      <xs:documentation>Name-Value Metadata: &lt;meta name&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="meta"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="meta.name.attrs">
+    <xs:attributeGroup ref="xhtml:meta.name.attrs.name"/>
+    <xs:attributeGroup ref="xhtml:meta.name.attrs.content"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="meta.name.attrs.name">
+    <xs:attribute name="name" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="meta.name.attrs.content">
+    <xs:attribute name="content" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:group name="meta.http-equiv.refresh.elem">
+    <xs:annotation>
+      <xs:documentation>"refresh" pragma directive: &lt;meta http-equiv='refresh'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="meta"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="meta.http-equiv.refresh.attrs">
+    <xs:attribute name="http-equiv" type="xs:string"/>
+  </xs:attributeGroup>
+  <!--
+    not quite right per spec
+    if the definition is
+    reused in another language
+  -->
+  <xs:group name="meta.http-equiv.default-style.elem">
+    <xs:annotation>
+      <xs:documentation>"default-style" pragma directive: &lt;meta http-equiv='default-style'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="meta"/>
+    </xs:sequence>
+  </xs:group>
+  <!--
+    not quite right per spec
+    if the definition is
+    reused in another language
+  -->
+  <xs:group name="meta.http-equiv.content-language.elem">
+    <xs:annotation>
+      <xs:documentation>"content-language" pragma directive: &lt;meta http-equiv='content-language'&gt; (obsolete)</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="meta"/>
+    </xs:sequence>
+  </xs:group>
+  <!--
+    not quite right per spec
+    if the definition is
+    reused in another language
+  -->
+  <xs:group name="meta.charset.elem">
+    <xs:annotation>
+      <xs:documentation>Inline Character Encoding Statement for HTML: &lt;meta charset&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="meta"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="meta.charset.attrs">
+    <xs:attributeGroup ref="xhtml:meta.charset.attrs.charset"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="meta.charset.attrs.charset">
+    <xs:attribute name="charset" type="common.data.charset"/>
+  </xs:attributeGroup>
+
+  <!-- ##################################################################### -->
+  <xs:group name="a.elem.phrasing">
+    <xs:annotation>
+      <xs:documentation>RELAX NG Schema for HTML 5: Phrase Markup #</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+  <xs:element name="a">
+    <xs:complexType>
+      <xs:complexContent>
+            <xs:extension base="xhtml:a.inner.phrasing">
+          <xs:attributeGroup ref="xhtml:a.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="a.elem.flow">
+    <xs:sequence>
+      <xs:element name="a">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:a.inner.flow">
+              <xs:attributeGroup ref="xhtml:a.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="a.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="name" type="common.data.id"/>
+    <xs:attribute name="href" type="common.data.uri"/>
+    <xs:attribute name="target" type="common.data.browsing-context-or-keyword"/>
+    <xs:attribute name="rel" type="common.data.tokens"/>
+    <xs:attribute name="hreflang" type="common.data.langcode"/>
+    <xs:attribute name="media" type="common.data.mediaquery"/>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attribute name="ping" type="common.data.uris"/>
+  </xs:attributeGroup>
+  <xs:complexType name="a.inner.phrasing" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:complexType name="a.inner.flow" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:attributeGroup name="shared-hyperlink.attrs.href">
+    <xs:annotation>
+      <xs:documentation>Shared hyperlink attributes</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="href" use="required" type="common.data.uri"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="shared-hyperlink.attrs.rel">
+    <xs:attribute name="rel" use="required" type="common.data.tokens"/>
+  </xs:attributeGroup>
+  <xs:element name="em">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:em.inner">
+          <xs:attributeGroup ref="xhtml:em.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="em.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="em.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="strong">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:strong.inner">
+          <xs:attributeGroup ref="xhtml:strong.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="strong.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="strong.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="small">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:small.inner">
+          <xs:attributeGroup ref="xhtml:small.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="small.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="small.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="mark">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:mark.inner">
+          <xs:attributeGroup ref="xhtml:mark.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="mark.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="mark.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="abbr">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:abbr.inner">
+          <xs:attributeGroup ref="xhtml:abbr.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="abbr.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="abbr.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="dfn">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:dfn.inner">
+          <xs:attributeGroup ref="xhtml:dfn.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="dfn.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="dfn.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="i">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:i.inner">
+          <xs:attributeGroup ref="xhtml:i.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="i.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="i.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="b">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:b.inner">
+          <xs:attributeGroup ref="xhtml:b.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="b.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="b.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="code">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:code.inner">
+          <xs:attributeGroup ref="xhtml:code.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="code.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="code.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="var">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:var.inner">
+          <xs:attributeGroup ref="xhtml:var.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="var.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="var.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="samp">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:samp.inner">
+          <xs:attributeGroup ref="xhtml:samp.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="samp.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="samp.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="kbd">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:kbd.inner">
+          <xs:attributeGroup ref="xhtml:kbd.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="kbd.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="kbd.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="sup">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:sup.inner">
+          <xs:attributeGroup ref="xhtml:sup.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="sup.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="sup.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="sub">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:sub.inner">
+          <xs:attributeGroup ref="xhtml:sub.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="sub.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="sub.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="q">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:q.inner">
+          <xs:attributeGroup ref="xhtml:q.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="q.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="cite" type="common.data.uri"/>
+  </xs:attributeGroup>
+  <xs:complexType name="q.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="cite">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:cite.inner">
+          <xs:attributeGroup ref="xhtml:cite.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="cite.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="cite.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="span">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:span.inner">
+          <xs:attributeGroup ref="xhtml:span.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="span.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="span.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <!-- REVISIT allow ol and ul? -->
+  <xs:element name="bdo">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:bdo.inner">
+          <xs:attributeGroup ref="xhtml:bdo.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="bdo.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <!-- dir required in Schematron -->
+  <xs:complexType name="bdo.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="br">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:br.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="wbr">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:common.attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="s">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:common.attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:attributeGroup name="br.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+
+  <!-- ##################################################################### -->
+  <xs:element name="p">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:p.inner">
+          <xs:attributeGroup ref="xhtml:p.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="p.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="p.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <!-- REVISIT lists in span? -->
+  <xs:element name="hr">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:hr.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="hr.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <!-- ##################################################################### -->
+  <xs:element name="pre">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:pre.inner">
+          <xs:attributeGroup ref="xhtml:pre.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="pre.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="pre.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <!-- ##################################################################### -->
+  <xs:element name="ul">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:ul.inner">
+          <xs:attributeGroup ref="xhtml:ul.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="ul.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="ul.inner">
+    <xs:group minOccurs="0" maxOccurs="unbounded" ref="xhtml:li.elem"/>
+  </xs:complexType>
+  <xs:group name="li.elem">
+    <xs:annotation>
+      <xs:documentation>Unordered List Item: &lt;li&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="li">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:li.inner">
+              <xs:attributeGroup ref="xhtml:li.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="li.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="li.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:element name="ol">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:ol.inner">
+          <xs:attributeGroup ref="xhtml:ol.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="ol.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="start" type="common.data.integer"/>
+    <xs:attribute name="reversed">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="reversed"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="ol.attrs.reversed">
+    <xs:attribute name="reversed" use="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="reversed"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:complexType name="ol.inner">
+    <xs:group minOccurs="0" maxOccurs="unbounded" ref="xhtml:oli.elem"/>
+  </xs:complexType>
+  <xs:group name="oli.elem">
+    <xs:annotation>
+      <xs:documentation>Ordered List Item: &lt;li&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="li">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:oli.inner">
+              <xs:attributeGroup ref="xhtml:oli.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="oli.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="value" type="common.data.integer"/>
+  </xs:attributeGroup>
+  <xs:complexType name="oli.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <!-- ##################################################################### -->
+  <xs:element name="dl">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:dl.inner">
+          <xs:attributeGroup ref="xhtml:dl.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="dl.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="dl.inner">
+    <xs:sequence minOccurs="0" maxOccurs="unbounded">
+      <xs:element maxOccurs="unbounded" ref="xhtml:dt"/>
+      <xs:group maxOccurs="unbounded" ref="xhtml:dd.elem"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="dt">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:dt.inner">
+          <xs:attributeGroup ref="xhtml:dt.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="dt.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="dt.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:group name="dd.elem">
+    <xs:annotation>
+      <xs:documentation>Definition Description: &lt;dd&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="dd">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:dd.inner">
+              <xs:attributeGroup ref="xhtml:dd.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="dd.elem.phrasing">
+    <xs:sequence>
+      <xs:element name="dd">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:dd.inner.phrasing">
+              <xs:attributeGroup ref="xhtml:dd.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="dd.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="dd.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:complexType name="dd.inner.phrasing" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <!-- ##################################################################### -->
+  <xs:element name="div">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:div.inner">
+          <xs:attributeGroup ref="xhtml:div.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="div.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="div.inner" mixed="true">
+    <xs:sequence>
+      <xs:group minOccurs="0" maxOccurs="unbounded" ref="xhtml:style.elem.scoped"/>
+      <xs:group ref="common.inner.flow"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="legend">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:legend.inner">
+          <xs:attributeGroup ref="xhtml:legend.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="figcaption">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:figcaption.inner">
+          <xs:attributeGroup ref="xhtml:figcaption.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="legend.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="legend.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+
+  <!-- ##################################################################### -->
+  <xs:element name="h1">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:h1.inner">
+          <xs:attributeGroup ref="xhtml:h1.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="h1.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="h1.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="h2">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:h2.inner">
+          <xs:attributeGroup ref="xhtml:h2.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="h2.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="h2.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="h3">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:h3.inner">
+          <xs:attributeGroup ref="xhtml:h3.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="h3.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="h3.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="h4">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:h4.inner">
+          <xs:attributeGroup ref="xhtml:h4.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="h4.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="h4.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="h5">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:h5.inner">
+          <xs:attributeGroup ref="xhtml:h5.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="h5.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="h5.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="h6">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:h6.inner">
+          <xs:attributeGroup ref="xhtml:h6.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="h6.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="h6.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="hgroup">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:hgroup.inner">
+          <xs:attributeGroup ref="xhtml:hgroup.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="hgroup.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="hgroup.inner">
+    <xs:choice maxOccurs="unbounded">
+      <xs:element ref="xhtml:h1"/>
+      <xs:element ref="xhtml:h2"/>
+      <xs:element ref="xhtml:h3"/>
+      <xs:element ref="xhtml:h4"/>
+      <xs:element ref="xhtml:h5"/>
+      <xs:element ref="xhtml:h6"/>
+    </xs:choice>
+  </xs:complexType>
+  <!-- ##################################################################### -->
+  <xs:element name="address">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:address.inner">
+          <xs:attributeGroup ref="xhtml:address.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="address.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="address.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <!-- ##################################################################### -->
+  <xs:element name="blockquote">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:blockquote.inner">
+          <xs:attributeGroup ref="xhtml:blockquote.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="blockquote.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="cite" type="common.data.uri"/>
+  </xs:attributeGroup>
+  <xs:complexType name="blockquote.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+
+  <xs:complexType name="figcaption.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:attributeGroup name="figcaption.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+
+  <!-- ##################################################################### -->
+  <xs:element name="section">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:section.inner">
+          <xs:attributeGroup ref="xhtml:section.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="section.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="section.inner" mixed="true">
+    <xs:sequence>
+      <xs:group minOccurs="0" maxOccurs="unbounded" ref="xhtml:style.elem.scoped"/>
+      <xs:group ref="common.inner.flow"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="nav">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:nav.inner">
+          <xs:attributeGroup ref="xhtml:nav.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="nav.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="nav.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:element name="article">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:article.inner">
+          <xs:attributeGroup ref="xhtml:article.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="article.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="pubdate" type="common.data.datetime"/>
+  </xs:attributeGroup>
+  <xs:complexType name="article.inner" mixed="true">
+    <xs:sequence>
+      <xs:group minOccurs="0" maxOccurs="unbounded" ref="xhtml:style.elem"/>
+      <xs:group ref="common.inner.flow"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="aside">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:aside.inner">
+          <xs:attributeGroup ref="xhtml:aside.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="aside.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="aside.inner" mixed="true">
+    <xs:sequence>
+      <xs:group minOccurs="0" maxOccurs="unbounded" ref="xhtml:style.elem"/>
+      <xs:group ref="common.inner.flow"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="header">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:header.inner">
+          <xs:attributeGroup ref="xhtml:header.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="header.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="header.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:element name="footer">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:footer.inner">
+          <xs:attributeGroup ref="xhtml:footer.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="footer.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="footer.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:element name="dialog">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:dialog.inner">
+          <xs:attributeGroup ref="xhtml:dialog.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="dialog.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="dialog.inner">
+    <xs:sequence minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="xhtml:dt"/>
+      <xs:group ref="xhtml:dd.elem"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <!-- ##################################################################### -->
+  <xs:attributeGroup name="edit.attrs.cite">
+    <xs:annotation>
+      <xs:documentation>RELAX NG Schema for HTML 5: Revision Annotations #</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="cite" use="required" type="common.data.uri"/>
+  </xs:attributeGroup>
+  <xs:group name="ins.elem.flow">
+    <xs:annotation>
+      <xs:documentation>Inserts: &lt;ins&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="ins">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:ins.inner.flow">
+              <xs:attributeGroup ref="xhtml:ins.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="ins.elem.phrasing">
+    <xs:sequence>
+      <xs:element name="ins">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:ins.inner.phrasing">
+              <xs:attributeGroup ref="xhtml:ins.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="ins.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="cite" type="common.data.uri"/>
+    <xs:attribute name="datetime" type="common.data.datetime"/>
+  </xs:attributeGroup>
+  <xs:complexType name="ins.inner.flow" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:complexType name="ins.inner.phrasing" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:group name="del.elem.flow">
+    <xs:annotation>
+      <xs:documentation>Deletions: &lt;del&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+  <xs:element name="del">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:del.inner.flow">
+          <xs:attributeGroup ref="xhtml:del.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="del.elem.phrasing">
+    <xs:sequence>
+      <xs:element name="del">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:del.inner.phrasing">
+              <xs:attributeGroup ref="xhtml:del.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="del.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="cite" type="common.data.uri"/>
+    <xs:attribute name="datetime" type="common.data.datetime"/>
+  </xs:attributeGroup>
+  <xs:complexType name="del.inner.flow" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:complexType name="del.inner.phrasing" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+
+  <!-- ##################################################################### -->
+  <xs:element name="img">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:img.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="img.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:img.attrs.src"/>
+    <xs:attribute name="alt"/>
+    <xs:attribute name="height" type="common.data.integer.non-negative"/>
+    <xs:attribute name="width" type="common.data.integer.non-negative"/>
+    <xs:attribute name="usemap" type="common.data.hash-name"/>
+    <xs:attribute name="ismap">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="ismap"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="border" type="common.data.zero"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="img.attrs.src">
+    <xs:attribute name="src" use="required" type="common.data.uri"/>
+  </xs:attributeGroup>
+  <xs:element name="embed">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:embed.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="embed.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="src" type="common.data.uri"/>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attribute name="height" type="common.data.integer.positive"/>
+    <xs:attribute name="width" type="common.data.integer.positive"/>
+    <xs:attributeGroup ref="xhtml:embed.attrs.other"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="embed.attrs.other">
+    <xs:anyAttribute namespace="##local" processContents="skip"/>
+  </xs:attributeGroup>
+  <xs:group name="object.elem.flow">
+    <xs:annotation>
+      <xs:documentation>Generic Objects: &lt;object&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+  <xs:element name="object">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:object.inner.flow">
+          <xs:attributeGroup ref="xhtml:object.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="object.elem.phrasing">
+    <xs:sequence>
+      <xs:element name="object">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:object.inner.phrasing">
+              <xs:attributeGroup ref="xhtml:object.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="object.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="data" type="common.data.uri"/>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attribute name="height" type="common.data.integer.positive"/>
+    <xs:attribute name="width" type="common.data.integer.positive"/>
+    <xs:attribute name="usemap" type="common.data.hash-name"/>
+    <xs:attribute name="name" type="common.data.browsing-context"/>
+    <xs:attributeGroup ref="common-form.attrs.form"/>
+  </xs:attributeGroup>
+  <xs:complexType name="object.inner.flow" mixed="true">
+    <xs:sequence>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:param"/>
+      <xs:group ref="common.inner.flow"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name="object.inner.phrasing" mixed="true">
+    <xs:sequence>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:param"/>
+      <xs:group ref="common.inner.phrasing"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="param">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:param.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="param.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:param.attrs.name"/>
+    <xs:attributeGroup ref="xhtml:param.attrs.value"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="param.attrs.name">
+    <xs:attribute name="name" use="required" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="param.attrs.value">
+    <xs:attribute name="value" use="required" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:element name="iframe">
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="xhtml:iframe.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="iframe.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="src" type="common.data.uri"/>
+    <xs:attribute name="name" type="common.data.browsing-context"/>
+    <xs:attribute name="width" type="common.data.integer.positive"/>
+    <xs:attribute name="height" type="common.data.integer.positive"/>
+    <xs:attribute name="sandbox" type="SandboxType"/>
+    <xs:attribute name="seamless">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="seamless"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="srcdoc" type="xs:string"/>
+  </xs:attributeGroup>
+
+  <xs:group name="map.elem.flow">
+    <xs:annotation>
+      <xs:documentation>Map Definition: &lt;map&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="map">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:map.inner.flow">
+              <xs:attributeGroup ref="xhtml:map.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="map.elem.phrasing">
+    <xs:sequence>
+      <xs:element name="map">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:map.inner.phrasing">
+              <xs:attributeGroup ref="xhtml:map.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="map.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:map.attrs.name"/>
+  </xs:attributeGroup>
+  <!-- REVISIT make id required in Schematron -->
+  <xs:attributeGroup name="map.attrs.name">
+    <xs:attribute name="name" use="required" type="common.data.name"/>
+  </xs:attributeGroup>
+  <xs:complexType name="map.inner.flow" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:complexType name="map.inner.phrasing" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="area">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:area.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="area.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="alt"/>
+    <xs:attribute name="href" type="common.data.uri"/>
+    <xs:attribute name="target" type="common.data.browsing-context-or-keyword"/>
+    <xs:attribute name="ping" type="common.data.uris"/>
+    <xs:attribute name="rel" type="common.data.tokens"/>
+    <xs:attribute name="media" type="common.data.mediaquery"/>
+    <xs:attribute name="hreflang" type="common.data.langcode"/>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attributeGroup ref="xhtml:area.attrs.shape"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="area.attrs.shape">
+    <xs:attribute name="shape" type="xs:string"/>
+    <xs:attribute name="coords" type="xs:string"/>
+  </xs:attributeGroup>
+
+  <!-- ##################################################################### -->
+  <xs:element name="ruby">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:ruby.inner">
+          <xs:attributeGroup ref="xhtml:ruby.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="ruby.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="ruby.inner" mixed="true">
+    <xs:sequence maxOccurs="unbounded">
+      <xs:group ref="common.inner.phrasing"/>
+      <xs:choice>
+        <xs:element ref="xhtml:rt"/>
+        <xs:sequence>
+          <xs:group ref="xhtml:rp.elem.start"/>
+          <xs:element ref="xhtml:rt"/>
+          <xs:group ref="xhtml:rp.elem.end"/>
+        </xs:sequence>
+      </xs:choice>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="rt">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:rt.inner">
+          <xs:attributeGroup ref="xhtml:rt.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="rt.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="rt.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:group name="rp.elem.start">
+    <xs:annotation>
+      <xs:documentation>Ruby Parenthesis: &lt;rp&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="rp">
+        <xs:complexType>
+          <xs:simpleContent>
+            <xs:extension base="xhtml:rp.inner.start">
+              <xs:attributeGroup ref="xhtml:rp.attrs"/>
+            </xs:extension>
+          </xs:simpleContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="rp.elem.end">
+    <xs:sequence>
+      <xs:element name="rp">
+        <xs:complexType>
+          <xs:simpleContent>
+            <xs:extension base="xhtml:rp.inner.end">
+              <xs:attributeGroup ref="xhtml:rp.attrs"/>
+            </xs:extension>
+          </xs:simpleContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="rp.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:simpleType name="rp.inner.start">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="rp.inner.end">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <!-- ##################################################################### -->
+  <!-- src not included -->
+  <xs:attributeGroup name="media.attrs">
+    <xs:annotation>
+      <xs:documentation>RELAX NG Schema for HTML 5: Advanced Embedded Content #</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="autoplay">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autoplay"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autobuffer">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autobuffer"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="controls">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="controls"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="loop">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="loop"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:element name="source">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:source.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="source.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:source.attrs.src"/>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attribute name="media" type="common.data.mediaquery"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="source.attrs.src">
+    <xs:attribute name="src" use="required" type="common.data.uri"/>
+  </xs:attributeGroup>
+  <xs:complexType name="media.source" mixed="true">
+    <xs:annotation>
+      <xs:documentation>Media Source</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:source"/>
+    </xs:sequence>
+    <xs:attribute name="src" type="common.data.uri"/>
+  </xs:complexType>
+  <xs:attributeGroup name="media.attrs.src">
+    <xs:attribute name="src" use="required" type="common.data.uri"/>
+  </xs:attributeGroup>
+  <xs:group name="video.elem.flow">
+    <xs:annotation>
+      <xs:documentation>Video: &lt;video&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="video">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:video.inner.flow">
+              <xs:attributeGroup ref="xhtml:video.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="video.elem.phrasing">
+    <xs:sequence>
+      <xs:element name="video">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:video.inner.phrasing">
+              <xs:attributeGroup ref="xhtml:video.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="video.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:media.attrs"/>
+    <xs:attribute name="poster" type="common.data.uri"/>
+    <xs:attribute name="height" type="common.data.integer.positive"/>
+    <xs:attribute name="width" type="common.data.integer.positive"/>
+  </xs:attributeGroup>
+  <xs:complexType name="video.inner.flow" mixed="true">
+    <xs:complexContent>
+      <xs:extension base="xhtml:media.source">
+        <xs:group ref="common.inner.flow"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="video.inner.phrasing" mixed="true">
+    <xs:complexContent>
+      <xs:extension base="xhtml:media.source">
+        <xs:group ref="common.inner.phrasing"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:group name="audio.elem.flow">
+    <xs:annotation>
+      <xs:documentation>Audio: &lt;audio&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="audio">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:audio.inner.flow">
+              <xs:attributeGroup ref="xhtml:audio.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="audio.elem.phrasing">
+    <xs:sequence>
+      <xs:element name="audio">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:audio.inner.phrasing">
+              <xs:attributeGroup ref="xhtml:audio.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="audio.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:media.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="audio.inner.flow" mixed="true">
+    <xs:complexContent>
+      <xs:extension base="xhtml:media.source">
+        <xs:group ref="common.inner.flow"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="audio.inner.phrasing" mixed="true">
+    <xs:complexContent>
+      <xs:extension base="xhtml:media.source">
+        <xs:group ref="common.inner.phrasing"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:element name="figure">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:figure.inner">
+          <xs:attributeGroup ref="xhtml:figure.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="figure.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="figure.inner" mixed="true">
+    <xs:choice>
+      <xs:sequence>
+        <xs:element ref="xhtml:legend"/>
+        <xs:group ref="common.inner.flow"/>
+      </xs:sequence>
+      <xs:sequence>
+        <xs:group ref="common.inner.flow"/>
+        <xs:element minOccurs="0" ref="xhtml:legend"/>
+      </xs:sequence>
+      <xs:sequence>
+        <xs:element ref="xhtml:figcaption"/>
+        <xs:group ref="common.inner.flow"/>
+      </xs:sequence>
+      <xs:sequence>
+        <xs:group ref="common.inner.flow"/>
+        <xs:element minOccurs="0" ref="xhtml:figcaption"/>
+      </xs:sequence>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:element name="script">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:script.inner.embedded">
+          <xs:attributeGroup ref="xhtml:script.attrs.embedded"/>
+          <xs:attributeGroup ref="xhtml:script.attrs.imported"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <!-- ##################################################################### -->
+  <xs:group name="script.elem.embedded">
+    <xs:annotation>
+      <xs:documentation>RELAX NG Schema for HTML 5: Core Scripting #</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="script"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="script.attrs.embedded">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attribute name="language" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:group name="script.elem.imported">
+    <xs:sequence>
+      <xs:element ref="script"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="script.attrs.imported">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:script.attrs.src"/>
+    <xs:attribute name="defer">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="defer"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="async">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="async"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="type" type="common.data.mimetype"/>
+    <xs:attribute name="charset" type="common.data.charset"/>
+    <xs:attribute name="language" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="script.attrs.src">
+    <xs:attribute name="src" use="optional" type="common.data.uri"/>
+  </xs:attributeGroup>
+  <xs:complexType name="script.inner.embedded">
+    <xs:complexContent>
+      <xs:extension base="common.inner.anything"/>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:group name="script.elem">
+    <xs:choice>
+      <xs:group ref="xhtml:script.elem.embedded"/>
+      <xs:group ref="xhtml:script.elem.imported"/>
+    </xs:choice>
+  </xs:group>
+  <xs:group name="noscript.inner.head">
+    <xs:sequence>
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="xhtml:link"/>
+        <xs:group ref="xhtml:meta.http-equiv.default-style.elem"/>
+        <xs:group ref="xhtml:meta.http-equiv.refresh.elem"/>
+        <xs:group ref="xhtml:style.elem"/>
+      </xs:choice>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="noscript.inner.phrasing">
+    <xs:sequence>
+      <xs:group ref="common.inner.phrasing"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="noscript.inner.flow">
+    <xs:sequence>
+      <xs:group ref="common.inner.flow"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="noscript.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <!-- ##################################################################### -->
+  <xs:attributeGroup name="common.attrs.scripting">
+    <xs:annotation>
+      <xs:documentation>Event Handler Attribute Definitions</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="onabort" type="xs:string"/>
+    <xs:attribute name="onblur" type="xs:string"/>
+    <xs:attribute name="oncanplay" type="xs:string"/>
+    <xs:attribute name="oncanplaythrough" type="xs:string"/>
+    <xs:attribute name="onchange" type="xs:string"/>
+    <xs:attribute name="onclick" type="xs:string"/>
+    <xs:attribute name="oncontextmenu" type="xs:string"/>
+    <xs:attribute name="ondblclick" type="xs:string"/>
+    <xs:attribute name="ondrag" type="xs:string"/>
+    <xs:attribute name="ondragend" type="xs:string"/>
+    <xs:attribute name="ondragenter" type="xs:string"/>
+    <xs:attribute name="ondragleave" type="xs:string"/>
+    <xs:attribute name="ondragover" type="xs:string"/>
+    <xs:attribute name="ondragstart" type="xs:string"/>
+    <xs:attribute name="ondrop" type="xs:string"/>
+    <xs:attribute name="ondurationchange" type="xs:string"/>
+    <xs:attribute name="onemptied" type="xs:string"/>
+    <xs:attribute name="onended" type="xs:string"/>
+    <xs:attribute name="onerror" type="xs:string"/>
+    <xs:attribute name="onfocus" type="xs:string"/>
+    <xs:attribute name="onformchange" type="xs:string"/>
+    <xs:attribute name="onforminput" type="xs:string"/>
+    <xs:attribute name="oninput" type="xs:string"/>
+    <xs:attribute name="oninvalid" type="xs:string"/>
+    <xs:attribute name="onkeydown" type="xs:string"/>
+    <xs:attribute name="onkeypress" type="xs:string"/>
+    <xs:attribute name="onkeyup" type="xs:string"/>
+    <xs:attribute name="onload" type="xs:string"/>
+    <xs:attribute name="onloadeddata" type="xs:string"/>
+    <xs:attribute name="onloadedmetadata" type="xs:string"/>
+    <xs:attribute name="onloadstart" type="xs:string"/>
+    <xs:attribute name="onmousedown" type="xs:string"/>
+    <xs:attribute name="onmousemove" type="xs:string"/>
+    <xs:attribute name="onmouseout" type="xs:string"/>
+    <xs:attribute name="onmouseover" type="xs:string"/>
+    <xs:attribute name="onmouseup" type="xs:string"/>
+    <xs:attribute name="onmousewheel" type="xs:string"/>
+    <xs:attribute name="onpause" type="xs:string"/>
+    <xs:attribute name="onplay" type="xs:string"/>
+    <xs:attribute name="onplaying" type="xs:string"/>
+    <xs:attribute name="onprogress" type="xs:string"/>
+    <xs:attribute name="onratechange" type="xs:string"/>
+    <xs:attribute name="onreadystatechange" type="xs:string"/>
+    <xs:attribute name="onscroll" type="xs:string"/>
+    <xs:attribute name="onseeked" type="xs:string"/>
+    <xs:attribute name="onseeking" type="xs:string"/>
+    <xs:attribute name="onselect" type="xs:string"/>
+    <xs:attribute name="onshow" type="xs:string"/>
+    <xs:attribute name="onstalled" type="xs:string"/>
+    <xs:attribute name="onsubmit" type="xs:string"/>
+    <xs:attribute name="onsuspend" type="xs:string"/>
+    <xs:attribute name="ontimeupdate" type="xs:string"/>
+    <xs:attribute name="onvolumechange" type="xs:string"/>
+    <xs:attribute name="onwaiting" type="xs:string"/>
+  </xs:attributeGroup>
+
+  <!-- ##################################################################### -->
+  <xs:attributeGroup name="tables.attrs.alignment">
+    <xs:annotation>
+      <xs:documentation>RELAX NG Schema for HTML 5: Tables #</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="align">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="left"/>
+          <xs:enumeration value="center"/>
+          <xs:enumeration value="right"/>
+          <xs:enumeration value="justify"/>
+          <xs:enumeration value="char"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="char">
+      <xs:simpleType>
+        <xs:restriction base="xs:string">
+          <xs:pattern value="."/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="valign">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="top"/>
+          <xs:enumeration value="middle"/>
+          <xs:enumeration value="bottom"/>
+          <xs:enumeration value="baseline"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:element name="table">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:table.inner">
+          <xs:attributeGroup ref="xhtml:table.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="table.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="summary" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:complexType name="table.inner">
+    <xs:sequence>
+      <xs:element minOccurs="0" ref="xhtml:caption"/>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:colgroup"/>
+      <xs:element minOccurs="0" ref="xhtml:thead"/>
+      <xs:choice>
+        <xs:sequence>
+          <xs:element ref="xhtml:tfoot"/>
+          <xs:choice>
+            <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:tbody"/>
+            <xs:element maxOccurs="unbounded" ref="xhtml:tr"/>
+          </xs:choice>
+        </xs:sequence>
+        <xs:sequence>
+          <xs:choice>
+            <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:tbody"/>
+            <xs:element maxOccurs="unbounded" ref="xhtml:tr"/>
+          </xs:choice>
+          <xs:element minOccurs="0" ref="xhtml:tfoot"/>
+        </xs:sequence>
+      </xs:choice>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="caption">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:caption.inner">
+          <xs:attributeGroup ref="xhtml:caption.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="caption.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="caption.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <!-- ##################################################################### -->
+  <xs:element name="colgroup">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:colgroup.inner">
+          <xs:attributeGroup ref="xhtml:colgroup.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="colgroup.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="colgroup.inner">
+    <xs:sequence>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:col"/>
+    </xs:sequence>
+    <xs:attribute name="span" type="common.data.integer.positive"/>
+  </xs:complexType>
+  <xs:element name="col">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:col.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="col.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="span" type="common.data.integer.positive"/>
+  </xs:attributeGroup>
+  <xs:element name="thead">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:thead.inner">
+          <xs:attributeGroup ref="xhtml:thead.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="thead.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="thead.inner">
+    <xs:sequence>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:tr"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="tfoot">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:tfoot.inner">
+          <xs:attributeGroup ref="xhtml:tfoot.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="tfoot.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="tfoot.inner">
+    <xs:sequence>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:tr"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="tbody">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:tbody.inner">
+          <xs:attributeGroup ref="xhtml:tbody.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="tbody.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="tbody.inner">
+    <xs:sequence>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:tr"/>
+    </xs:sequence>
+  </xs:complexType>
+  <!-- ##################################################################### -->
+  <xs:element name="tr">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:tr.inner">
+          <xs:attributeGroup ref="xhtml:tr.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="tr.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="tr.inner">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="xhtml:td"/>
+      <xs:element ref="xhtml:th"/>
+    </xs:choice>
+  </xs:complexType>
+  <xs:attributeGroup name="tables.attrs.cell-structure">
+    <xs:annotation>
+      <xs:documentation>Common Table Cell Attributes</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="colspan" type="common.data.integer.positive"/>
+    <xs:attribute name="rowspan" type="common.data.integer.non-negative"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="tables.attrs.define-headers">
+    <xs:attribute name="scope">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="row"/>
+          <xs:enumeration value="col"/>
+          <xs:enumeration value="rowgroup"/>
+          <xs:enumeration value="colgroup"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:element name="td">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:td.inner">
+          <xs:attributeGroup ref="xhtml:td.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="td.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:tables.attrs.cell-structure"/>
+    <xs:attribute name="headers" type="common.data.idrefs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="td.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:element name="th">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:th.inner">
+          <xs:attributeGroup ref="xhtml:th.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="th.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:tables.attrs.cell-structure"/>
+    <xs:attribute name="scope">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="row"/>
+          <xs:enumeration value="col"/>
+          <xs:enumeration value="rowgroup"/>
+          <xs:enumeration value="colgroup"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="headers" type="common.data.idrefs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="th.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+
+  <!-- ##################################################################### -->
+  <xs:simpleType name="form.data.mimetypelist">
+    <xs:annotation>
+      <xs:documentation>RELAX NG Schema for HTML 5: Datatypes related to forms #</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="form.data.charsetlist">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <!--
+    FIXME should be a "a space- and/or comma-delimited
+    list of charset values"
+  -->
+  <xs:simpleType name="form.data.pattern">
+    <xs:annotation>
+      <xs:documentation>ECMAScript Regular Expression</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="form.data.datetime-local">
+    <xs:annotation>
+      <xs:documentation>Temporal</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="form.data.date">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="form.data.month">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="form.data.week">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="form.data.time">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="form.data.emailaddress">
+    <xs:annotation>
+      <xs:documentation>Email</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="form.data.emailaddresslist">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="form.data.color">
+    <xs:annotation>
+      <xs:documentation>Color</xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <!-- ##################################################################### -->
+  <xs:attributeGroup name="common-form.attrs">
+    <xs:annotation>
+      <xs:documentation>RELAX NG Schema for HTML 5: Web Forms 1.0 markup #</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="name" type="xs:string"/>
+    <xs:attribute name="disabled">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="disabled"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attributeGroup ref="common-form.attrs.form"/>
+  </xs:attributeGroup>
+
+  <!-- REVISIT tabindex goes in common.attrs -->
+  <xs:attributeGroup name="input.attrs.checked">
+    <xs:annotation>
+      <xs:documentation>Shared attributes for &lt;input&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="checked">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="checked"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:element name="input">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:input.text.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.password.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.checkbox.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.radio.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.button.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.submit.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.reset.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.file.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.hidden.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.image.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.datetime.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.datetime-local.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.date.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.month.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.time.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.week.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.number.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.range.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.email.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.url.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.search.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.tel.attrs"/>
+      <xs:attributeGroup ref="xhtml:input.color.attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:group name="input.text.elem">
+    <xs:annotation>
+      <xs:documentation>Text Field: &lt;input type='text'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.text.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="maxlength" type="common.data.integer.positive"/>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="size" type="common.data.integer.positive"/>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="pattern" type="xhtml:form.data.pattern"/>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="placeholder" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:group name="input.elem">
+    <xs:choice>
+      <xs:group ref="xhtml:input.text.elem"/>
+      <xs:group ref="xhtml:input.password.elem"/>
+      <xs:group ref="xhtml:input.checkbox.elem"/>
+      <xs:group ref="xhtml:input.radio.elem"/>
+      <xs:group ref="xhtml:input.button.elem"/>
+      <xs:group ref="xhtml:input.submit.elem"/>
+      <xs:group ref="xhtml:input.reset.elem"/>
+      <xs:group ref="xhtml:input.file.elem"/>
+      <xs:group ref="xhtml:input.hidden.elem"/>
+      <xs:group ref="xhtml:input.image.elem"/>
+      <xs:group ref="xhtml:input.datetime.elem"/>
+      <xs:group ref="xhtml:input.datetime-local.elem"/>
+      <xs:group ref="xhtml:input.date.elem"/>
+      <xs:group ref="xhtml:input.month.elem"/>
+      <xs:group ref="xhtml:input.time.elem"/>
+      <xs:group ref="xhtml:input.week.elem"/>
+      <xs:group ref="xhtml:input.number.elem"/>
+      <xs:group ref="xhtml:input.range.elem"/>
+      <xs:group ref="xhtml:input.email.elem"/>
+      <xs:group ref="xhtml:input.url.elem"/>
+      <xs:group ref="xhtml:input.search.elem"/>
+      <xs:group ref="xhtml:input.tel.elem"/>
+      <xs:group ref="xhtml:input.color.elem"/>
+    </xs:choice>
+  </xs:group>
+  <xs:group name="input.password.elem">
+    <xs:annotation>
+      <xs:documentation>Password Field: &lt;input type='password'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.password.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="maxlength" type="common.data.integer.positive"/>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="size" type="common.data.integer.positive"/>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="pattern" type="xhtml:form.data.pattern"/>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="placeholder" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="input.attrs.type">
+    <xs:attribute name="type">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="text"/>
+          <xs:enumeration value="password"/>
+          <xs:enumeration value="checkbox"/>
+          <xs:enumeration value="radio"/>
+          <xs:enumeration value="button"/>
+          <xs:enumeration value="submit"/>
+          <xs:enumeration value="reset"/>
+          <xs:enumeration value="file"/>
+          <xs:enumeration value="hidden"/>
+          <xs:enumeration value="image"/>
+          <xs:enumeration value="datetime"/>
+          <xs:enumeration value="datetime-local"/>
+          <xs:enumeration value="date"/>
+          <xs:enumeration value="month"/>
+          <xs:enumeration value="time"/>
+          <xs:enumeration value="week"/>
+          <xs:enumeration value="number"/>
+          <xs:enumeration value="range"/>
+          <xs:enumeration value="email"/>
+          <xs:enumeration value="url"/>
+          <xs:enumeration value="search"/>
+          <xs:enumeration value="tel"/>
+          <xs:enumeration value="color"/>
+
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="input.checkbox.elem">
+    <xs:annotation>
+      <xs:documentation>Checkbox: &lt;input type='checkbox'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.checkbox.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="checked">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="checked"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="input.radio.elem">
+    <xs:annotation>
+      <xs:documentation>Radiobutton: &lt;input type='radio'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.radio.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="checked">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="checked"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="input.button.elem">
+    <xs:annotation>
+      <xs:documentation>Scripting Hook Button: &lt;input type='button'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.button.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <!-- REVISIT should this be enabled by a scripting module only? -->
+  <xs:group name="input.submit.elem">
+    <xs:annotation>
+      <xs:documentation>Submit Button: &lt;input type='submit'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.submit.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="formaction" type="common.data.uri"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="formenctype" type="xhtml:shared-form.attrs.formenctype.data"/>
+    <xs:attribute name="formmethod" type="xhtml:shared-form.attrs.formmethod.data"/>
+    <xs:attribute name="formtarget" type="common.data.browsing-context-or-keyword"/>
+    <xs:attribute name="formnovalidate">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="formnovalidate"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="input.reset.elem">
+    <xs:annotation>
+      <xs:documentation>Reset Button: &lt;input type='reset'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.reset.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <!-- REVISIT does reset make sense outside a form? -->
+  <xs:group name="input.file.elem">
+    <xs:annotation>
+      <xs:documentation>File Upload: &lt;input type='file'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.file.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="accept" type="xhtml:form.data.mimetypelist"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="multiple">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="multiple"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="input.hidden.elem">
+    <xs:annotation>
+      <xs:documentation>Hidden String: &lt;input type='hidden'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.hidden.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="value" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:group name="input.image.elem">
+    <xs:annotation>
+      <xs:documentation>Image Submit Button: &lt;input type='image'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.image.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attributeGroup ref="xhtml:input.image.attrs.alt"/>
+    <xs:attribute name="src" type="common.data.uri"/>
+    <xs:attribute name="formaction" type="common.data.uri"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="formenctype" type="xhtml:shared-form.attrs.formenctype.data"/>
+    <xs:attribute name="formmethod" type="xhtml:shared-form.attrs.formmethod.data"/>
+    <xs:attribute name="formtarget" type="common.data.browsing-context-or-keyword"/>
+    <xs:attribute name="formnovalidate">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="formnovalidate"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="height" type="common.data.integer.positive"/>
+    <xs:attribute name="width" type="common.data.integer.positive"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="input.image.attrs.alt">
+    <xs:attribute name="alt" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:element name="textarea">
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="xhtml:textarea.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="textarea.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="maxlength" type="common.data.integer.positive"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="placeholder" type="xs:string"/>
+    <xs:attribute name="rows" type="common.data.integer.positive"/>
+    <xs:attribute name="wrap" type="xs:string"/>
+    <xs:attribute name="cols" type="common.data.integer.positive"/>
+  </xs:attributeGroup>
+  <!-- This is ugly. -->
+  <!--
+    Due to limitations with interleave, handling single/multiple selection
+    enforcement in RELAX NG seems to be possible but really awkward.
+    Tried it. Leaving it to Schematron.
+  -->
+  <xs:element name="option">
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="xhtml:option.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="option.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="disabled">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="disabled"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="selected">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="selected"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="label" type="xs:string"/>
+    <xs:attribute name="value" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:element name="optgroup">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:optgroup.inner">
+          <xs:attributeGroup ref="xhtml:optgroup.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="optgroup.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:optgroup.attrs.label"/>
+    <xs:attribute name="disabled">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="disabled"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="optgroup.attrs.label">
+    <xs:attribute name="label" use="required" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:complexType name="optgroup.inner">
+    <xs:sequence>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="xhtml:option"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="select">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:select.inner">
+          <xs:attributeGroup ref="xhtml:select.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="select.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attribute name="size" type="common.data.integer.positive"/>
+    <xs:attribute name="multiple">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="multiple"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:complexType name="select.inner">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="xhtml:optgroup"/>
+      <xs:element ref="xhtml:option"/>
+    </xs:choice>
+  </xs:complexType>
+  <xs:complexType name="button.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+
+  <xs:element name="button">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:button.inner">
+          <xs:attributeGroup ref="xhtml:button.submit.attrs"/>
+          <xs:attributeGroup ref="xhtml:button.reset.attrs"/>
+          <xs:attributeGroup ref="xhtml:button.button.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:group name="button.submit.elem">
+    <xs:annotation>
+      <xs:documentation>Complex Submit Button: &lt;button type='submit'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="button"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="button.submit.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="button.attrs.type"/>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="formaction" type="common.data.uri"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="formenctype" type="xhtml:shared-form.attrs.formenctype.data"/>
+    <xs:attribute name="formmethod" type="xhtml:shared-form.attrs.formmethod.data"/>
+    <xs:attribute name="formtarget" type="common.data.browsing-context-or-keyword"/>
+    <xs:attribute name="formnovalidate">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="formnovalidate"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="button.elem">
+    <xs:choice>
+      <xs:group ref="xhtml:button.submit.elem"/>
+      <xs:group ref="xhtml:button.reset.elem"/>
+      <xs:group ref="xhtml:button.button.elem"/>
+    </xs:choice>
+  </xs:group>
+  <xs:group name="button.reset.elem">
+    <xs:annotation>
+      <xs:documentation>Complex Reset Button: &lt;button type='reset'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="button"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="button.reset.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:button.attrs.type"/>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="button.attrs.type">
+    <xs:attribute name="type">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="submit"/>
+          <xs:enumeration value="reset"/>
+          <xs:enumeration value="button"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="button.button.elem">
+    <xs:annotation>
+      <xs:documentation>Complex Push Button: &lt;button type='button'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="button"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="button.button.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:button.attrs.type"/>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:element name="form">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:form.inner">
+          <xs:attributeGroup ref="xhtml:form.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="form.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="action" type="common.data.uri"/>
+    <xs:attribute name="method" type="xhtml:form.attrs.method.data"/>
+    <xs:attribute name="enctype" type="xhtml:form.attrs.enctype.data"/>
+    <xs:attribute name="name" type="xs:string"/>
+    <xs:attribute name="accept-charset" type="xhtml:form.data.charsetlist"/>
+    <xs:attribute name="novalidate">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="novalidate"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="target" type="common.data.browsing-context-or-keyword"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:simpleType name="form.attrs.method.data">
+    <xs:union>
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:union>
+  </xs:simpleType>
+  <xs:simpleType name="form.attrs.enctype.data">
+    <xs:union memberTypes="xs:string">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:union>
+  </xs:simpleType>
+  <xs:complexType name="form.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:element name="fieldset">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:fieldset.inner">
+          <xs:attributeGroup ref="xhtml:fieldset.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="fieldset.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="fieldset.inner" mixed="true">
+    <xs:sequence>
+      <xs:element minOccurs="0" ref="xhtml:legend"/>
+      <xs:group ref="common.inner.flow"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="label">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:label.inner">
+          <xs:attributeGroup ref="xhtml:label.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="label.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="for" type="common.data.idref"/>
+    <xs:attributeGroup ref="common-form.attrs.form"/>
+  </xs:attributeGroup>
+  <xs:complexType name="label.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:simpleType name="shared-form.attrs.formenctype.data">
+    <xs:union memberTypes="xs:string"/>
+  </xs:simpleType>
+  <xs:simpleType name="shared-form.attrs.formmethod.data">
+    <xs:union memberTypes="xs:string"/>
+  </xs:simpleType>
+  <xs:group name="input.datetime.elem">
+    <xs:annotation>
+      <xs:documentation>Global Date and Time: &lt;input type='datetime'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.datetime.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="min" type="common.data.datetime"/>
+    <xs:attribute name="max" type="common.data.datetime"/>
+    <xs:attribute name="step">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="common.data.datetime"/>
+  </xs:attributeGroup>
+  <xs:group name="input.datetime-local.elem">
+    <xs:annotation>
+      <xs:documentation>Date and Time with No Time Zone Information: &lt;input type='datetime-local'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.datetime-local.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="min" type="xhtml:form.data.datetime-local"/>
+    <xs:attribute name="max" type="xhtml:form.data.datetime-local"/>
+    <xs:attribute name="step">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="xhtml:form.data.datetime-local"/>
+  </xs:attributeGroup>
+  <xs:group name="input.date.elem">
+    <xs:annotation>
+      <xs:documentation>Date: &lt;input type='date'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.date.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="min" type="xhtml:form.data.date"/>
+    <xs:attribute name="max" type="xhtml:form.data.date"/>
+    <xs:attribute name="step">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="xhtml:form.data.date"/>
+  </xs:attributeGroup>
+  <xs:group name="input.month.elem">
+    <xs:annotation>
+      <xs:documentation>Year and Month: &lt;input type='month'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.month.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="min" type="xhtml:form.data.month"/>
+    <xs:attribute name="max" type="xhtml:form.data.month"/>
+    <xs:attribute name="step">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="xhtml:form.data.month"/>
+  </xs:attributeGroup>
+  <xs:group name="input.time.elem">
+    <xs:annotation>
+      <xs:documentation>Time without Time Zone Information: &lt;input type='time'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.time.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="min" type="xhtml:form.data.time"/>
+    <xs:attribute name="max" type="xhtml:form.data.time"/>
+    <xs:attribute name="step">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="xhtml:form.data.time"/>
+  </xs:attributeGroup>
+  <xs:group name="input.week.elem">
+    <xs:annotation>
+      <xs:documentation>Year and Week: &lt;input type='week'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.week.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="min" type="xhtml:form.data.week"/>
+    <xs:attribute name="max" type="xhtml:form.data.week"/>
+    <xs:attribute name="step">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="xhtml:form.data.week"/>
+  </xs:attributeGroup>
+  <xs:group name="input.number.elem">
+    <xs:annotation>
+      <xs:documentation>Number: &lt;input type='number'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.number.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="min" type="common.data.float"/>
+    <xs:attribute name="max" type="common.data.float"/>
+    <xs:attribute name="step">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="common.data.float"/>
+  </xs:attributeGroup>
+  <xs:group name="input.range.elem">
+    <xs:annotation>
+      <xs:documentation>Imprecise Number: &lt;input type='range'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.range.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="min" type="common.data.float"/>
+    <xs:attribute name="max" type="common.data.float"/>
+    <xs:attribute name="step">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="value" type="common.data.float"/>
+  </xs:attributeGroup>
+  <xs:group name="input.email.elem">
+    <xs:annotation>
+      <xs:documentation>Email Address: &lt;input type='email'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.email.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="maxlength" type="common.data.integer.positive"/>
+    <xs:attribute name="pattern" type="xhtml:form.data.pattern"/>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="size" type="common.data.integer.positive"/>
+    <xs:attribute name="placeholder" type="xs:string"/>
+    <xs:attribute name="value">
+      <xs:simpleType>
+        <xs:union memberTypes="xhtml:form.data.emailaddresslist xhtml:form.data.emailaddress"/>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="multiple">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="multiple"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="input.url.elem">
+    <xs:annotation>
+      <xs:documentation>IRI: &lt;input type='url'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.url.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="maxlength" type="common.data.integer.positive"/>
+    <xs:attribute name="pattern" type="xhtml:form.data.pattern"/>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="size" type="common.data.integer.positive"/>
+    <xs:attribute name="placeholder" type="xs:string"/>
+    <xs:attribute name="value">
+      <xs:simpleType>
+        <xs:union memberTypes="xs:string"/>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="input.search.elem">
+    <xs:annotation>
+      <xs:documentation>Search: &lt;input type='search'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.search.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="maxlength" type="common.data.integer.positive"/>
+    <xs:attribute name="pattern" type="xhtml:form.data.pattern"/>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="size" type="common.data.integer.positive"/>
+    <xs:attribute name="placeholder" type="xs:string"/>
+    <xs:attribute name="value" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:group name="input.tel.elem">
+    <xs:annotation>
+      <xs:documentation>Telephone Number: &lt;input type='tel'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.tel.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="maxlength" type="common.data.integer.positive"/>
+    <xs:attribute name="pattern" type="xhtml:form.data.pattern"/>
+    <xs:attribute name="readonly">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="readonly"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="required">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="required"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="size" type="common.data.integer.positive"/>
+    <xs:attribute name="placeholder" type="xs:string"/>
+    <xs:attribute name="value" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:group name="input.color.elem">
+    <xs:annotation>
+      <xs:documentation>Color: &lt;input type='color'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="input"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="input.color.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+    <xs:attributeGroup ref="xhtml:input.attrs.type"/>
+    <xs:attribute name="autocomplete">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="on"/>
+          <xs:enumeration value="off"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="list" type="common.data.idref"/>
+    <xs:attribute name="value" type="xhtml:form.data.color"/>
+  </xs:attributeGroup>
+  <xs:element name="output">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:output.inner">
+          <xs:attributeGroup ref="xhtml:output.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="output.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="name" type="xs:string"/>
+    <xs:attributeGroup ref="common-form.attrs.form"/>
+    <xs:attribute name="for" type="common.data.idrefs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="output.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="datalist">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:datalist.inner">
+          <xs:attributeGroup ref="xhtml:datalist.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:complexType name="datalist.inner" mixed="true">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="xhtml:option"/>
+      <xs:group ref="common.inner.phrasing"/>
+    </xs:choice>
+  </xs:complexType>
+  <xs:attributeGroup name="datalist.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:element name="keygen">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:keygen.attrs"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="keygen.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="challenge" type="xs:string"/>
+    <xs:attribute name="keytype" type="xs:string"/>
+    <xs:attribute name="autofocus">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="autofocus"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attributeGroup ref="xhtml:common-form.attrs"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="common.attrs.interact">
+    <xs:annotation>
+      <xs:documentation>RELAX NG Schema for HTML 5: Web Application Features #</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="contextmenu" type="common.data.idref"/>
+    <xs:attribute name="contenteditable">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="true"/>
+          <xs:enumeration value="false"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="draggable">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="true"/>
+          <xs:enumeration value="false"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="hidden">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="hidden"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="spellcheck">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="true"/>
+          <xs:enumeration value="false"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="common.attrs.contenteditable">
+    <xs:annotation>
+      <xs:documentation>Editable Content: contenteditable</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="contenteditable">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="true"/>
+          <xs:enumeration value="false"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="common.attrs.draggable">
+    <xs:annotation>
+      <xs:documentation>Draggable Element: draggable</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="draggable">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="true"/>
+          <xs:enumeration value="false"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="common.attrs.hidden">
+    <xs:annotation>
+      <xs:documentation>Hidden Element: hidden</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="hidden">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="hidden"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="common.attrs.spellcheck">
+    <xs:annotation>
+      <xs:documentation>Spellchecking and grammar checking: spellcheck</xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="spellcheck">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="true"/>
+          <xs:enumeration value="false"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:element name="progress">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:progress.inner">
+          <xs:attributeGroup ref="xhtml:progress.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="progress.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="value" type="common.data.float.non-negative"/>
+    <xs:attribute name="max" type="common.data.float.positive"/>
+  </xs:attributeGroup>
+  <xs:complexType name="progress.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <!-- Cannot enforce textContent format here -->
+  <xs:element name="datagrid">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:datagrid.inner">
+          <xs:attributeGroup ref="xhtml:datagrid.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="datagrid.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="multiple">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="multiple"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="disabled">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="disabled"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:complexType name="datagrid.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+
+  <xs:element name="command">
+    <xs:complexType>
+      <xs:attributeGroup ref="xhtml:command.command.attrs"/>
+      <xs:attributeGroup ref="xhtml:command.radio.attrs"/>
+      <xs:attributeGroup ref="xhtml:command.checkbox.attrs"/>
+
+    </xs:complexType>
+  </xs:element>
+
+  <xs:group name="command.command.elem">
+    <xs:annotation>
+      <xs:documentation>Command with an associated action: &lt;command type='command'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="command"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="command.command.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="command.attrs.type"/>
+    <xs:attributeGroup ref="xhtml:common-command.attrs"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="command.attrs.type">
+    <xs:attribute name="type">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="radio"/>
+          <xs:enumeration value="command"/>
+          <xs:enumeration value="checkbox"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:group name="command.elem">
+    <xs:choice>
+      <xs:group ref="xhtml:command.command.elem"/>
+      <xs:group ref="xhtml:command.radio.elem"/>
+      <xs:group ref="xhtml:command.checkbox.elem"/>
+    </xs:choice>
+  </xs:group>
+  <xs:group name="command.radio.elem">
+    <xs:annotation>
+      <xs:documentation>Selection of one item from a list of items: &lt;command type='radio'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="command"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="command.radio.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:command.attrs.type"/>
+    <xs:attributeGroup ref="xhtml:command.radio.attrs.radiogroup"/>
+    <xs:attribute name="checked">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="checked"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attributeGroup ref="xhtml:common-command.attrs"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="command.radio.attrs.radiogroup">
+    <xs:attribute name="radiogroup" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:group name="command.checkbox.elem">
+    <xs:annotation>
+      <xs:documentation>State or option that can be toggled: &lt;command type='checkbox'&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="command"/>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="command.checkbox.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attributeGroup ref="xhtml:command.attrs.type"/>
+    <xs:attribute name="checked">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="checked"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attributeGroup ref="xhtml:common-command.attrs"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="common-command.attrs">
+    <xs:attribute name="label" type="xs:string"/>
+    <xs:attribute name="icon" type="common.data.uri"/>
+    <xs:attribute name="disabled">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="disabled"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:element name="bb">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:bb.inner">
+          <xs:attributeGroup ref="xhtml:bb.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="bb.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="type" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="bb.attrs.type">
+    <xs:attribute name="type">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="makeapp"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:complexType name="bb.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="menu">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:menu.inner">
+          <xs:attributeGroup ref="xhtml:menu.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="menu.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="type">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="toolbar"/>
+          <xs:enumeration value="context"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="label" type="xs:string"/>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="menu.attrs.type">
+    <xs:attribute name="type">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="toolbar"/>
+          <xs:enumeration value="context"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:complexType name="menu.inner" mixed="true">
+    <xs:choice>
+      <xs:group minOccurs="0" maxOccurs="unbounded" ref="xhtml:mli.elem"/>
+      <xs:group ref="common.inner.flow"/>
+    </xs:choice>
+  </xs:complexType>
+  <!-- REVISIT allow nested menus -->
+  <xs:group name="mli.elem">
+    <xs:annotation>
+      <xs:documentation>Menu Item: &lt;li&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="li">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:mli.inner">
+              <xs:attributeGroup ref="xhtml:mli.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="mli.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+  </xs:attributeGroup>
+  <xs:complexType name="mli.inner" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:group name="canvas.elem.flow">
+    <xs:annotation>
+      <xs:documentation>Canvas for Dynamic Graphics: &lt;canvas&gt;</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="canvas">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:canvas.inner.flow">
+              <xs:attributeGroup ref="xhtml:canvas.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:group name="canvas.elem.phrasing">
+    <xs:sequence>
+      <xs:element name="canvas">
+        <xs:complexType>
+          <xs:complexContent>
+            <xs:extension base="xhtml:canvas.inner.phrasing">
+              <xs:attributeGroup ref="xhtml:canvas.attrs"/>
+            </xs:extension>
+          </xs:complexContent>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:group>
+  <xs:attributeGroup name="canvas.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="height" type="common.data.integer.non-negative"/>
+    <xs:attribute name="width" type="common.data.integer.non-negative"/>
+  </xs:attributeGroup>
+  <xs:complexType name="canvas.inner.flow" mixed="true">
+    <xs:group ref="common.inner.flow"/>
+  </xs:complexType>
+  <xs:complexType name="canvas.inner.phrasing" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <xs:element name="details">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:details.inner">
+          <xs:attributeGroup ref="xhtml:details.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="details.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="open">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="open"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:attributeGroup name="details.attrs.open">
+    <xs:attribute name="open">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="open"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+  <xs:complexType name="details.inner" mixed="true">
+    <xs:sequence>
+      <xs:element ref="xhtml:legend"/>
+      <xs:group ref="common.inner.flow"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="time">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:time.inner">
+          <xs:attributeGroup ref="xhtml:time.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="time.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="datetime" type="common.data.date-or-time"/>
+  </xs:attributeGroup>
+  <xs:complexType name="time.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+  <!-- Cannot enforce textContent format here -->
+  <xs:element name="meter">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xhtml:meter.inner">
+          <xs:attributeGroup ref="xhtml:meter.attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+  <xs:attributeGroup name="meter.attrs">
+    <xs:attributeGroup ref="common.attrs"/>
+    <xs:attribute name="value" type="common.data.float"/>
+    <xs:attribute name="min" type="common.data.float"/>
+    <xs:attribute name="low" type="common.data.float"/>
+    <xs:attribute name="high" type="common.data.float"/>
+    <xs:attribute name="max" type="common.data.float"/>
+    <xs:attribute name="optimum" type="common.data.float"/>
+  </xs:attributeGroup>
+
+  <xs:complexType name="meter.inner" mixed="true">
+    <xs:group ref="common.inner.phrasing"/>
+  </xs:complexType>
+
+  <xs:attribute name="id" type="xs:NCName"/>
+  <xs:attribute name="base" type="common.data.uri"/>
+  <xs:attribute name="space">
+    <xs:simpleType>
+      <xs:restriction base="xs:string">
+        <xs:enumeration value="preserve"/>
+      </xs:restriction>
+    </xs:simpleType>
+  </xs:attribute>
+  <xs:attribute name="lang" type="common.data.langcode"/>
+</xs:schema>
+
diff --git a/xml/impl/resources/standardSchemas/plugin-repository.dtd b/xml/impl/resources/standardSchemas/plugin-repository.dtd
new file mode 100644
index 0000000..2c551fa
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/plugin-repository.dtd
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!ELEMENT plugin-repository (category*)>
+<!ELEMENT category (category | idea-plugin)*>
+<!ATTLIST category
+    name CDATA #REQUIRED>
+<!ELEMENT idea-plugin (name | description | change-notes | version | vendor | idea-version ? | depends)+>
+<!ATTLIST idea-plugin
+    downloads CDATA #REQUIRED
+    size CDATA #REQUIRED
+    url CDATA #IMPLIED
+    date CDATA #REQUIRED>
+
+<!--
+    <name> is a unique Plugin identifier
+-->
+<!ELEMENT name (#PCDATA)>
+<!--
+    <description> is a short description of plugin and it functionality
+-->
+<!ELEMENT description (#PCDATA)>
+<!--
+    <version> specified current plugin version.
+-->
+<!ELEMENT version (#PCDATA)>
+<!--
+    <vendor> tag now could have an 'url' and 'email' attributes
+-->
+<!ELEMENT vendor (#PCDATA)>
+<!ATTLIST vendor
+    url CDATA #IMPLIED
+    email CDATA #IMPLIED>
+
+<!--
+    Plugin change notes
+ -->
+<!ELEMENT idea-version EMPTY>
+<!ATTLIST idea-version
+    min CDATA #IMPLIED
+    max CDATA #IMPLIED
+    since-build CDATA #IMPLIED>
+
+<!ELEMENT change-notes (#PCDATA)>
+
+<!ELEMENT depends (#PCDATA)>
diff --git a/xml/impl/resources/standardSchemas/plugin.dtd b/xml/impl/resources/standardSchemas/plugin.dtd
new file mode 100644
index 0000000..c1cb334
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/plugin.dtd
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!ELEMENT idea-plugin (name | id? | description | version | vendor | change-notes? | idea-version | category | resource-bundle | depends* | extensions* | application-components? | project-components? | module-components? | actions? | helpset)+>
+<!ATTLIST idea-plugin
+    url CDATA #IMPLIED
+    version CDATA #IMPLIED>
+<!--
+    <name> is a unique Plugin identifier
+-->
+<!ELEMENT name (#PCDATA)>
+<!--
+    <id> is a unique Plugin identifier, if not specified, id is considered equal to "name"
+-->
+<!ELEMENT id (#PCDATA)>
+<!--
+    <description> is a short description of plugin and it functionality
+-->
+<!ELEMENT description (#PCDATA)>
+<!--
+    <version> specified current plugin version.
+-->
+<!ELEMENT version (#PCDATA)>
+
+<!--
+    <vendor> tag now could have 'url', 'email' and 'logo' attributes;
+    'logo' should contain path to a 16 x 16 icon that will appear near the plugin name in the IDEA Welcome Screen 
+-->
+<!ELEMENT vendor (#PCDATA)>
+<!ATTLIST vendor
+    url CDATA #IMPLIED
+    email CDATA #IMPLIED
+    logo CDATA #IMPLIED>
+
+<!--
+    Plugin category (displayed in plugin manager) e.g. inspection, Misc, Fun Stuff, etc
+-->
+<!ELEMENT category (#PCDATA)>
+
+<!--
+    Fully qualified name of bundle used by this plugin e.g. com.mycompany.MyBundle
+-->
+<!ELEMENT resource-bundle (#PCDATA)>
+
+<!--
+    Possible extensions element
+-->
+<!ELEMENT errorHandler (#PCDATA)>
+<!ATTLIST errorHandler implementation CDATA #REQUIRED>
+
+<!--
+    Possible extensions element
+-->
+<!ELEMENT indexPatternProvider (#PCDATA)>
+<!ATTLIST indexPatternProvider implementation CDATA #REQUIRED>
+
+<!--
+    <idea-version> tag specified version of IDEA which
+    plugin could work with
+-->
+<!ELEMENT idea-version EMPTY>
+<!-- min / max attributes are left for compatibility -->
+
+<!ATTLIST idea-version
+    since-build CDATA #REQUIRED
+    until-build CDATA #IMPLIED
+    min CDATA #IMPLIED
+    max CDATA #IMPLIED
+    >
+
+<!-- change notes of current version -->
+<!ELEMENT change-notes (#PCDATA)>
+
+<!ELEMENT depends (#PCDATA)>
+<!ATTLIST depends
+   optional (true | false) #IMPLIED
+   config-file CDATA #IMPLIED
+   >
+
+<!-- extensions. Most relaxed constraints since content of the particular extension cannot be expressed with DTD
+  defaultExtensionNs - namespace prepended to referenced extension name to get qname,
+  xmlns same as previous, left for compatibility 
+ -->
+<!ELEMENT extensions ANY>
+<!ATTLIST extensions
+   defaultExtensionNs CDATA #REQUIRED
+   xmlns CDATA #IMPLIED
+   >
+
+<!ELEMENT application-components (component*)>
+<!ELEMENT project-components (component*)>
+<!ELEMENT module-components (component*)>
+<!ELEMENT component (implementation-class | interface-class? | option*)+>
+<!ELEMENT actions (action+ | group+)*>
+<!ELEMENT implementation-class (#PCDATA)>
+<!ELEMENT interface-class (#PCDATA)>
+<!ELEMENT option EMPTY>
+<!ATTLIST option
+    name CDATA #REQUIRED
+    value CDATA #REQUIRED>
+<!ELEMENT action (keyboard-shortcut? | mouse-shortcut? | shortcut? | add-to-group?)+>
+<!--
+    <action> tag has required 'id' attribute
+    which mean an action ID. Some existing plugins
+    have an uncompatible XML ID for this attribute.
+    :((
+ -->
+<!ATTLIST action
+    description CDATA #IMPLIED
+    class CDATA #REQUIRED
+    text CDATA #REQUIRED
+    id CDATA #REQUIRED
+    icon CDATA #IMPLIED
+    popup (true | false) #IMPLIED>
+<!ELEMENT keyboard-shortcut EMPTY>
+<!ATTLIST keyboard-shortcut
+    first-keystroke CDATA #REQUIRED
+    second-keystroke CDATA #IMPLIED
+    keymap CDATA #REQUIRED
+    use-shortcut-of CDATA #IMPLIED>
+<!ELEMENT mouse-shortcut EMPTY>
+<!ATTLIST mouse-shortcut
+    keystroke CDATA #REQUIRED
+    keymap CDATA #REQUIRED>
+<!ELEMENT shortcut EMPTY>
+<!ATTLIST shortcut
+    first-keystroke CDATA #REQUIRED
+    second-keystroke CDATA #IMPLIED
+    keymap CDATA #REQUIRED>
+<!ELEMENT group (reference* | separator* | action* | add-to-group*)+>
+<!ATTLIST group
+    id ID #IMPLIED
+    class CDATA #IMPLIED
+    text CDATA #IMPLIED
+    description CDATA #IMPLIED
+    popup (true | false) #IMPLIED
+    icon CDATA #IMPLIED>
+<!ELEMENT reference EMPTY>
+<!ATTLIST reference
+    ref CDATA #REQUIRED>
+<!ELEMENT add-to-group EMPTY>
+<!--
+    <add-to-group> tag use an 'id' attribute
+    to specify which group will be used.
+    It should be very useful if
+    we'll have a set of existing group IDs
+-->
+<!ATTLIST add-to-group
+    anchor (first | last | before | after) #REQUIRED
+    group-id CDATA #REQUIRED
+    relative-to-action CDATA #IMPLIED>
+<!ELEMENT separator EMPTY>
+
+<!-- helpset is a name of file from PLUGIN/help/ folder
+  Example: <helpset file="myhelp.jar" path="/Help.hs"/>
+ -->
+<!ELEMENT helpset EMPTY>
+<!ATTLIST helpset
+  file CDATA #REQUIRED
+  path CDATA #REQUIRED>
\ No newline at end of file
diff --git a/xml/impl/resources/standardSchemas/xhtml-lat1.ent b/xml/impl/resources/standardSchemas/xhtml-lat1.ent
new file mode 100644
index 0000000..ffee223
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-lat1.ent
@@ -0,0 +1,196 @@
+<!-- Portions (C) International Organization for Standardization 1986
+     Permission to copy in any form is granted for use with
+     conforming SGML systems and applications as defined in
+     ISO 8879, provided this notice is included in all copies.
+-->
+<!-- Character entity set. Typical invocation:
+    <!ENTITY % HTMLlat1 PUBLIC
+       "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+       "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+    %HTMLlat1;
+-->
+
+<!ENTITY nbsp   "&#160;"> <!-- no-break space = non-breaking space,
+                                  U+00A0 ISOnum -->
+<!ENTITY iexcl  "&#161;"> <!-- inverted exclamation mark, U+00A1 ISOnum -->
+<!ENTITY cent   "&#162;"> <!-- cent sign, U+00A2 ISOnum -->
+<!ENTITY pound  "&#163;"> <!-- pound sign, U+00A3 ISOnum -->
+<!ENTITY curren "&#164;"> <!-- currency sign, U+00A4 ISOnum -->
+<!ENTITY yen    "&#165;"> <!-- yen sign = yuan sign, U+00A5 ISOnum -->
+<!ENTITY brvbar "&#166;"> <!-- broken bar = broken vertical bar,
+                                  U+00A6 ISOnum -->
+<!ENTITY sect   "&#167;"> <!-- section sign, U+00A7 ISOnum -->
+<!ENTITY uml    "&#168;"> <!-- diaeresis = spacing diaeresis,
+                                  U+00A8 ISOdia -->
+<!ENTITY copy   "&#169;"> <!-- copyright sign, U+00A9 ISOnum -->
+<!ENTITY ordf   "&#170;"> <!-- feminine ordinal indicator, U+00AA ISOnum -->
+<!ENTITY laquo  "&#171;"> <!-- left-pointing double angle quotation mark
+                                  = left pointing guillemet, U+00AB ISOnum -->
+<!ENTITY not    "&#172;"> <!-- not sign = angled dash,
+                                  U+00AC ISOnum -->
+<!ENTITY shy    "&#173;"> <!-- soft hyphen = discretionary hyphen,
+                                  U+00AD ISOnum -->
+<!ENTITY reg    "&#174;"> <!-- registered sign = registered trade mark sign,
+                                  U+00AE ISOnum -->
+<!ENTITY macr   "&#175;"> <!-- macron = spacing macron = overline
+                                  = APL overbar, U+00AF ISOdia -->
+<!ENTITY deg    "&#176;"> <!-- degree sign, U+00B0 ISOnum -->
+<!ENTITY plusmn "&#177;"> <!-- plus-minus sign = plus-or-minus sign,
+                                  U+00B1 ISOnum -->
+<!ENTITY sup2   "&#178;"> <!-- superscript two = superscript digit two
+                                  = squared, U+00B2 ISOnum -->
+<!ENTITY sup3   "&#179;"> <!-- superscript three = superscript digit three
+                                  = cubed, U+00B3 ISOnum -->
+<!ENTITY acute  "&#180;"> <!-- acute accent = spacing acute,
+                                  U+00B4 ISOdia -->
+<!ENTITY micro  "&#181;"> <!-- micro sign, U+00B5 ISOnum -->
+<!ENTITY para   "&#182;"> <!-- pilcrow sign = paragraph sign,
+                                  U+00B6 ISOnum -->
+<!ENTITY middot "&#183;"> <!-- middle dot = Georgian comma
+                                  = Greek middle dot, U+00B7 ISOnum -->
+<!ENTITY cedil  "&#184;"> <!-- cedilla = spacing cedilla, U+00B8 ISOdia -->
+<!ENTITY sup1   "&#185;"> <!-- superscript one = superscript digit one,
+                                  U+00B9 ISOnum -->
+<!ENTITY ordm   "&#186;"> <!-- masculine ordinal indicator,
+                                  U+00BA ISOnum -->
+<!ENTITY raquo  "&#187;"> <!-- right-pointing double angle quotation mark
+                                  = right pointing guillemet, U+00BB ISOnum -->
+<!ENTITY frac14 "&#188;"> <!-- vulgar fraction one quarter
+                                  = fraction one quarter, U+00BC ISOnum -->
+<!ENTITY frac12 "&#189;"> <!-- vulgar fraction one half
+                                  = fraction one half, U+00BD ISOnum -->
+<!ENTITY frac34 "&#190;"> <!-- vulgar fraction three quarters
+                                  = fraction three quarters, U+00BE ISOnum -->
+<!ENTITY iquest "&#191;"> <!-- inverted question mark
+                                  = turned question mark, U+00BF ISOnum -->
+<!ENTITY Agrave "&#192;"> <!-- latin capital letter A with grave
+                                  = latin capital letter A grave,
+                                  U+00C0 ISOlat1 -->
+<!ENTITY Aacute "&#193;"> <!-- latin capital letter A with acute,
+                                  U+00C1 ISOlat1 -->
+<!ENTITY Acirc  "&#194;"> <!-- latin capital letter A with circumflex,
+                                  U+00C2 ISOlat1 -->
+<!ENTITY Atilde "&#195;"> <!-- latin capital letter A with tilde,
+                                  U+00C3 ISOlat1 -->
+<!ENTITY Auml   "&#196;"> <!-- latin capital letter A with diaeresis,
+                                  U+00C4 ISOlat1 -->
+<!ENTITY Aring  "&#197;"> <!-- latin capital letter A with ring above
+                                  = latin capital letter A ring,
+                                  U+00C5 ISOlat1 -->
+<!ENTITY AElig  "&#198;"> <!-- latin capital letter AE
+                                  = latin capital ligature AE,
+                                  U+00C6 ISOlat1 -->
+<!ENTITY Ccedil "&#199;"> <!-- latin capital letter C with cedilla,
+                                  U+00C7 ISOlat1 -->
+<!ENTITY Egrave "&#200;"> <!-- latin capital letter E with grave,
+                                  U+00C8 ISOlat1 -->
+<!ENTITY Eacute "&#201;"> <!-- latin capital letter E with acute,
+                                  U+00C9 ISOlat1 -->
+<!ENTITY Ecirc  "&#202;"> <!-- latin capital letter E with circumflex,
+                                  U+00CA ISOlat1 -->
+<!ENTITY Euml   "&#203;"> <!-- latin capital letter E with diaeresis,
+                                  U+00CB ISOlat1 -->
+<!ENTITY Igrave "&#204;"> <!-- latin capital letter I with grave,
+                                  U+00CC ISOlat1 -->
+<!ENTITY Iacute "&#205;"> <!-- latin capital letter I with acute,
+                                  U+00CD ISOlat1 -->
+<!ENTITY Icirc  "&#206;"> <!-- latin capital letter I with circumflex,
+                                  U+00CE ISOlat1 -->
+<!ENTITY Iuml   "&#207;"> <!-- latin capital letter I with diaeresis,
+                                  U+00CF ISOlat1 -->
+<!ENTITY ETH    "&#208;"> <!-- latin capital letter ETH, U+00D0 ISOlat1 -->
+<!ENTITY Ntilde "&#209;"> <!-- latin capital letter N with tilde,
+                                  U+00D1 ISOlat1 -->
+<!ENTITY Ograve "&#210;"> <!-- latin capital letter O with grave,
+                                  U+00D2 ISOlat1 -->
+<!ENTITY Oacute "&#211;"> <!-- latin capital letter O with acute,
+                                  U+00D3 ISOlat1 -->
+<!ENTITY Ocirc  "&#212;"> <!-- latin capital letter O with circumflex,
+                                  U+00D4 ISOlat1 -->
+<!ENTITY Otilde "&#213;"> <!-- latin capital letter O with tilde,
+                                  U+00D5 ISOlat1 -->
+<!ENTITY Ouml   "&#214;"> <!-- latin capital letter O with diaeresis,
+                                  U+00D6 ISOlat1 -->
+<!ENTITY times  "&#215;"> <!-- multiplication sign, U+00D7 ISOnum -->
+<!ENTITY Oslash "&#216;"> <!-- latin capital letter O with stroke
+                                  = latin capital letter O slash,
+                                  U+00D8 ISOlat1 -->
+<!ENTITY Ugrave "&#217;"> <!-- latin capital letter U with grave,
+                                  U+00D9 ISOlat1 -->
+<!ENTITY Uacute "&#218;"> <!-- latin capital letter U with acute,
+                                  U+00DA ISOlat1 -->
+<!ENTITY Ucirc  "&#219;"> <!-- latin capital letter U with circumflex,
+                                  U+00DB ISOlat1 -->
+<!ENTITY Uuml   "&#220;"> <!-- latin capital letter U with diaeresis,
+                                  U+00DC ISOlat1 -->
+<!ENTITY Yacute "&#221;"> <!-- latin capital letter Y with acute,
+                                  U+00DD ISOlat1 -->
+<!ENTITY THORN  "&#222;"> <!-- latin capital letter THORN,
+                                  U+00DE ISOlat1 -->
+<!ENTITY szlig  "&#223;"> <!-- latin small letter sharp s = ess-zed,
+                                  U+00DF ISOlat1 -->
+<!ENTITY agrave "&#224;"> <!-- latin small letter a with grave
+                                  = latin small letter a grave,
+                                  U+00E0 ISOlat1 -->
+<!ENTITY aacute "&#225;"> <!-- latin small letter a with acute,
+                                  U+00E1 ISOlat1 -->
+<!ENTITY acirc  "&#226;"> <!-- latin small letter a with circumflex,
+                                  U+00E2 ISOlat1 -->
+<!ENTITY atilde "&#227;"> <!-- latin small letter a with tilde,
+                                  U+00E3 ISOlat1 -->
+<!ENTITY auml   "&#228;"> <!-- latin small letter a with diaeresis,
+                                  U+00E4 ISOlat1 -->
+<!ENTITY aring  "&#229;"> <!-- latin small letter a with ring above
+                                  = latin small letter a ring,
+                                  U+00E5 ISOlat1 -->
+<!ENTITY aelig  "&#230;"> <!-- latin small letter ae
+                                  = latin small ligature ae, U+00E6 ISOlat1 -->
+<!ENTITY ccedil "&#231;"> <!-- latin small letter c with cedilla,
+                                  U+00E7 ISOlat1 -->
+<!ENTITY egrave "&#232;"> <!-- latin small letter e with grave,
+                                  U+00E8 ISOlat1 -->
+<!ENTITY eacute "&#233;"> <!-- latin small letter e with acute,
+                                  U+00E9 ISOlat1 -->
+<!ENTITY ecirc  "&#234;"> <!-- latin small letter e with circumflex,
+                                  U+00EA ISOlat1 -->
+<!ENTITY euml   "&#235;"> <!-- latin small letter e with diaeresis,
+                                  U+00EB ISOlat1 -->
+<!ENTITY igrave "&#236;"> <!-- latin small letter i with grave,
+                                  U+00EC ISOlat1 -->
+<!ENTITY iacute "&#237;"> <!-- latin small letter i with acute,
+                                  U+00ED ISOlat1 -->
+<!ENTITY icirc  "&#238;"> <!-- latin small letter i with circumflex,
+                                  U+00EE ISOlat1 -->
+<!ENTITY iuml   "&#239;"> <!-- latin small letter i with diaeresis,
+                                  U+00EF ISOlat1 -->
+<!ENTITY eth    "&#240;"> <!-- latin small letter eth, U+00F0 ISOlat1 -->
+<!ENTITY ntilde "&#241;"> <!-- latin small letter n with tilde,
+                                  U+00F1 ISOlat1 -->
+<!ENTITY ograve "&#242;"> <!-- latin small letter o with grave,
+                                  U+00F2 ISOlat1 -->
+<!ENTITY oacute "&#243;"> <!-- latin small letter o with acute,
+                                  U+00F3 ISOlat1 -->
+<!ENTITY ocirc  "&#244;"> <!-- latin small letter o with circumflex,
+                                  U+00F4 ISOlat1 -->
+<!ENTITY otilde "&#245;"> <!-- latin small letter o with tilde,
+                                  U+00F5 ISOlat1 -->
+<!ENTITY ouml   "&#246;"> <!-- latin small letter o with diaeresis,
+                                  U+00F6 ISOlat1 -->
+<!ENTITY divide "&#247;"> <!-- division sign, U+00F7 ISOnum -->
+<!ENTITY oslash "&#248;"> <!-- latin small letter o with stroke,
+                                  = latin small letter o slash,
+                                  U+00F8 ISOlat1 -->
+<!ENTITY ugrave "&#249;"> <!-- latin small letter u with grave,
+                                  U+00F9 ISOlat1 -->
+<!ENTITY uacute "&#250;"> <!-- latin small letter u with acute,
+                                  U+00FA ISOlat1 -->
+<!ENTITY ucirc  "&#251;"> <!-- latin small letter u with circumflex,
+                                  U+00FB ISOlat1 -->
+<!ENTITY uuml   "&#252;"> <!-- latin small letter u with diaeresis,
+                                  U+00FC ISOlat1 -->
+<!ENTITY yacute "&#253;"> <!-- latin small letter y with acute,
+                                  U+00FD ISOlat1 -->
+<!ENTITY thorn  "&#254;"> <!-- latin small letter thorn,
+                                  U+00FE ISOlat1 -->
+<!ENTITY yuml   "&#255;"> <!-- latin small letter y with diaeresis,
+                                  U+00FF ISOlat1 -->
diff --git a/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile10-flat.dtd b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile10-flat.dtd
new file mode 100644
index 0000000..5066cd1
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile10-flat.dtd
@@ -0,0 +1,3223 @@
+<!-- XHTML Mobile 1.0 DTD  ...................................................... -->
+<!-- file: xhtml-mobile10.dtd -->
+<!-- 
+     This is XHTML Mobile profile, a proper subset of XHTML.
+     
+     	@Wireless Application Protocol Forum, Ltd. 2001.
+
+	Terms and conditions of use are available from the Wireless Application Protocol Forum Ltd. 
+	Web site (http://www.wapforum.org/what/copyright.htm).
+    
+-->
+<!-- This is the driver file for version 1.0 of the XHTML Mobile DTD.
+
+     This DTD is identified by the PUBLIC and SYSTEM identifiers:
+
+     PUBLIC: "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
+     SYSTEM: "http://www.wapforum.org/DTD/xhtml-mobile10.dtd"
+-->
+<!ENTITY % XHTML.version  "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" >
+
+<!-- Use this URI to identify the default namespace:
+
+         "http://www.w3.org/1999/xhtml"
+
+     See the Qualified Names module for information
+     on the use of namespace prefixes in the DTD.
+-->
+<!ENTITY % NS.prefixed "IGNORE" >
+<!ENTITY % XHTML.prefix  "" >
+
+<!-- For example, if you are using XHTML Mobile 1.0 directly, use
+     the FPI in the DOCTYPE declaration, with the xmlns attribute
+     on the document element to identify the default namespace:
+
+         <?xml version="1.0"?>
+         <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
+             "http://www.wapforum.org/DTD/xhtml-mobile10.dtd" >
+         <html xmlns="http://www.w3.org/1999/xhtml"
+               xml:lang="en" >
+         ...
+         </html>
+-->
+
+<!-- reserved for future use with document profiles -->
+<!ENTITY % XHTML.profile  "" >
+
+<!-- Inline Style Module  ........................................ -->
+<!ENTITY % xhtml-inlstyle.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN"
+            "../xhtml11/xhtml-inlstyle-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Inline Style Module  ........................................... -->
+<!-- file: xhtml-inlstyle-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-inlstyle-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Inline Style 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-inlstyle-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Inline Style
+
+     This module declares the 'style' attribute, used to support inline
+     style markup. This module must be instantiated prior to the XHTML
+     Common Attributes module in order to be included in %Core.attrib;.
+-->
+
+<!ENTITY % style.attrib
+     "style        CDATA                    #IMPLIED"
+>
+
+
+<!ENTITY % Core.extra.attrib
+     "%style.attrib;"
+>
+
+<!-- end of xhtml-inlstyle-1.mod -->
+
+
+<!-- Document Model ........................................ -->
+<!ENTITY % xhtml-model.mod
+     PUBLIC "-//WAPFORUM//ENTITIES XHTML Mobile 1.0 Document Model 1.0//EN"
+            "xhtml-mobile10-model-1.mod" >
+
+<!-- XHTML Framework ........................................ -->
+<!ENTITY % XHTML.bidi  "IGNORE" >
+<!ENTITY % xhtml-framework.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN"
+            "../xhtml11/xhtml-framework-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Modular Framework Module  ...................................... -->
+<!-- file: xhtml-framework-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-framework-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-framework-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Modular Framework
+
+     This required module instantiates the modules needed
+     to support the XHTML modularization model, including:
+
+        +  notations
+        +  datatypes
+        +  namespace-qualified names
+        +  common attributes
+        +  document model
+        +  character entities
+
+     The Intrinsic Events module is ignored by default but
+     occurs in this module because it must be instantiated
+     prior to Attributes but after Datatypes.
+-->
+
+<!ENTITY % xhtml-arch.module "IGNORE" >
+<![%xhtml-arch.module;[
+<!ENTITY % xhtml-arch.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Base Architecture 1.0//EN"
+            "xhtml-arch-1.mod" >
+%xhtml-arch.mod;]]>
+
+<!ENTITY % xhtml-notations.module "INCLUDE" >
+<![%xhtml-notations.module;[
+<!ENTITY % xhtml-notations.mod
+     PUBLIC "-//W3C//NOTATIONS XHTML Notations 1.0//EN"
+            "xhtml-notations-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Notations Module  .............................................. -->
+<!-- file: xhtml-notations-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-notations-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//NOTATIONS XHTML Notations 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-notations-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Notations
+
+     defines the following notations, many of these imported from
+     other specifications and standards. When an existing FPI is
+     known, it is incorporated here.
+-->
+
+<!-- XML Notations ..................................... -->
+<!-- SGML and XML Notations ............................ -->
+
+<!-- W3C XML 1.0 Recommendation -->
+<!NOTATION w3c-xml
+     PUBLIC "ISO 8879//NOTATION Extensible Markup Language (XML) 1.0//EN" >
+
+<!-- XML 1.0 CDATA -->
+<!NOTATION cdata
+     PUBLIC "-//W3C//NOTATION XML 1.0: CDATA//EN" >
+
+<!-- SGML Formal Public Identifiers -->
+<!NOTATION fpi
+     PUBLIC "ISO 8879:1986//NOTATION Formal Public Identifier//EN" >
+
+<!-- XHTML Notations ................................... -->
+
+<!-- Length defined for cellpadding/cellspacing -->
+
+<!-- nn for pixels or nn% for percentage length -->
+<!NOTATION length
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: Length//EN" >
+
+<!-- space-separated list of link types -->
+<!NOTATION linkTypes
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: LinkTypes//EN" >
+
+<!-- single or comma-separated list of media descriptors -->
+<!NOTATION mediaDesc
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: MediaDesc//EN" >
+
+<!-- pixel, percentage, or relative -->
+<!NOTATION multiLength
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: MultiLength//EN" >
+
+<!-- one or more digits (NUMBER) -->
+<!NOTATION number
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: Number//EN" >
+
+<!-- integer representing length in pixels -->
+<!NOTATION pixels
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: Pixels//EN" >
+
+<!-- script expression -->
+<!NOTATION script
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: Script//EN" >
+
+<!-- textual content -->
+<!NOTATION text
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: Text//EN" >
+
+<!-- Imported Notations ................................ -->
+
+<!-- a single character from [ISO10646] -->
+<!NOTATION character
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: Character//EN" >
+
+<!-- a character encoding, as per [RFC2045] -->
+<!NOTATION charset
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: Charset//EN" >
+
+<!-- a space separated list of character encodings, as per [RFC2045] -->
+<!NOTATION charsets
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: Charsets//EN" >
+
+<!-- media type, as per [RFC2045] -->
+<!NOTATION contentType
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: ContentType//EN" >
+
+<!-- comma-separated list of media types, as per [RFC2045] -->
+<!NOTATION contentTypes
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: ContentTypes//EN" >
+
+<!-- date and time information. ISO date format -->
+<!NOTATION datetime
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: Datetime//EN" >
+
+<!-- a language code, as per [RFC3066] -->
+<!NOTATION languageCode
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: LanguageCode//EN" >
+
+<!-- a Uniform Resource Identifier, see [URI] -->
+<!NOTATION uri
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: URI//EN" >
+
+<!-- a space-separated list of Uniform Resource Identifiers, see [URI] -->
+<!NOTATION uris
+    PUBLIC "-//W3C//NOTATION XHTML Datatype: URIs//EN" >
+
+<!-- end of xhtml-notations-1.mod -->
+]]>
+
+<!ENTITY % xhtml-datatypes.module "INCLUDE" >
+<![%xhtml-datatypes.module;[
+<!ENTITY % xhtml-datatypes.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Datatypes 1.0//EN"
+            "../xhtml11/xhtml-datatypes-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Datatypes Module  .............................................. -->
+<!-- file: xhtml-datatypes-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-datatypes-1.mod,v 4.1 2001/04/06 19:23:32 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Datatypes 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-datatypes-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Datatypes
+
+     defines containers for the following datatypes, many of
+     these imported from other specifications and standards.
+-->
+
+<!-- Length defined for cellpadding/cellspacing -->
+
+<!-- nn for pixels or nn% for percentage length -->
+<!ENTITY % Length.datatype "CDATA" >
+
+<!-- space-separated list of link types -->
+<!ENTITY % LinkTypes.datatype "NMTOKENS" >
+
+<!-- single or comma-separated list of media descriptors -->
+<!ENTITY % MediaDesc.datatype "CDATA" >
+
+<!-- pixel, percentage, or relative -->
+<!ENTITY % MultiLength.datatype "CDATA" >
+
+<!-- one or more digits (NUMBER) -->
+<!ENTITY % Number.datatype "CDATA" >
+
+<!-- integer representing length in pixels -->
+<!ENTITY % Pixels.datatype "CDATA" >
+
+<!-- script expression -->
+<!ENTITY % Script.datatype "CDATA" >
+
+<!-- textual content -->
+<!ENTITY % Text.datatype "CDATA" >
+
+<!-- Imported Datatypes ................................ -->
+
+<!-- a single character from [ISO10646] -->
+<!ENTITY % Character.datatype "CDATA" >
+
+<!-- a character encoding, as per [RFC2045] -->
+<!ENTITY % Charset.datatype "CDATA" >
+
+<!-- a space separated list of character encodings, as per [RFC2045] -->
+<!ENTITY % Charsets.datatype "CDATA" >
+
+<!-- Color specification using color name or sRGB (#RRGGBB) values -->
+<!ENTITY % Color.datatype "CDATA" >
+
+<!-- media type, as per [RFC2045] -->
+<!ENTITY % ContentType.datatype "CDATA" >
+
+<!-- comma-separated list of media types, as per [RFC2045] -->
+<!ENTITY % ContentTypes.datatype "CDATA" >
+
+<!-- date and time information. ISO date format -->
+<!ENTITY % Datetime.datatype "CDATA" >
+
+<!-- formal public identifier, as per [ISO8879] -->
+<!ENTITY % FPI.datatype "CDATA" >
+
+<!-- a language code, as per [RFC3066] -->
+<!ENTITY % LanguageCode.datatype "NMTOKEN" >
+
+<!-- a Uniform Resource Identifier, see [URI] -->
+<!ENTITY % URI.datatype "CDATA" >
+
+<!-- a space-separated list of Uniform Resource Identifiers, see [URI] -->
+<!ENTITY % URIs.datatype "CDATA" >
+
+<!-- end of xhtml-datatypes-1.mod -->
+]]>
+
+<!-- placeholder for XLink support module -->
+<!ENTITY % xhtml-xlink.mod "" >
+
+
+<!ENTITY % xhtml-qname.module "INCLUDE" >
+<![%xhtml-qname.module;[
+<!ENTITY % xhtml-qname.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Qualified Names 1.0//EN"
+            "../xhtml11/xhtml-qname-1.mod" >
+<!-- ....................................................................... -->
+<!-- XHTML Qname Module  ................................................... -->
+<!-- file: xhtml-qname-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-qname-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Qualified Names 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-qname-1.mod"
+
+     Revisions:
+#2000-10-22: added qname declarations for ruby elements
+     ....................................................................... -->
+
+<!-- XHTML Qname (Qualified Name) Module
+
+     This module is contained in two parts, labeled Section 'A' and 'B':
+
+       Section A declares parameter entities to support namespace-
+       qualified names, namespace declarations, and name prefixing
+       for XHTML and extensions.
+
+       Section B declares parameter entities used to provide
+       namespace-qualified names for all XHTML element types:
+
+         %applet.qname;   the xmlns-qualified name for <applet>
+         %base.qname;     the xmlns-qualified name for <base>
+         ...
+
+     XHTML extensions would create a module similar to this one.
+     Included in the XHTML distribution is a template module
+     ('template-qname-1.mod') suitable for this purpose.
+-->
+
+<!-- Section A: XHTML XML Namespace Framework :::::::::::::::::::: -->
+
+<!-- 1. Declare a %XHTML.prefixed; conditional section keyword, used
+        to activate namespace prefixing. The default value should
+        inherit '%NS.prefixed;' from the DTD driver, so that unless
+        overridden, the default behaviour follows the overall DTD
+        prefixing scheme.
+-->
+<!ENTITY % NS.prefixed "IGNORE" >
+<!ENTITY % XHTML.prefixed "%NS.prefixed;" >
+
+<!-- 2. Declare a parameter entity (eg., %XHTML.xmlns;) containing
+        the URI reference used to identify the XHTML namespace:
+-->
+<!ENTITY % XHTML.xmlns  "http://www.w3.org/1999/xhtml" >
+
+<!-- 3. Declare parameter entities (eg., %XHTML.prefix;) containing
+        the default namespace prefix string(s) to use when prefixing
+        is enabled. This may be overridden in the DTD driver or the
+        internal subset of an document instance. If no default prefix
+        is desired, this may be declared as an empty string.
+
+     NOTE: As specified in [XMLNAMES], the namespace prefix serves
+     as a proxy for the URI reference, and is not in itself significant.
+-->
+<!ENTITY % XHTML.prefix  "" >
+
+<!-- 4. Declare parameter entities (eg., %XHTML.pfx;) containing the
+        colonized prefix(es) (eg., '%XHTML.prefix;:') used when
+        prefixing is active, an empty string when it is not.
+-->
+<![%XHTML.prefixed;[
+<!ENTITY % XHTML.pfx  "%XHTML.prefix;:" >
+]]>
+<!ENTITY % XHTML.pfx  "" >
+
+<!-- declare qualified name extensions here ............ -->
+<!ENTITY % xhtml-qname-extra.mod "" >
+
+
+<!-- 5. The parameter entity %XHTML.xmlns.extra.attrib; may be
+        redeclared to contain any non-XHTML namespace declaration
+        attributes for namespaces embedded in XHTML. The default
+        is an empty string.  XLink should be included here if used
+        in the DTD.
+-->
+<!ENTITY % XHTML.xmlns.extra.attrib "" >
+
+<!-- The remainder of Section A is only followed in XHTML, not extensions. -->
+
+<!-- Declare a parameter entity %NS.decl.attrib; containing
+     all XML Namespace declarations used in the DTD, plus the
+     xmlns declaration for XHTML, its form dependent on whether
+     prefixing is active.
+-->
+<![%XHTML.prefixed;[
+<!ENTITY % NS.decl.attrib
+     "xmlns:%XHTML.prefix;  %URI.datatype;   #FIXED '%XHTML.xmlns;'
+      %XHTML.xmlns.extra.attrib;"
+>
+]]>
+<!ENTITY % NS.decl.attrib
+     "%XHTML.xmlns.extra.attrib;"
+>
+
+<!-- This is a placeholder for future XLink support.
+-->
+<!ENTITY % XLINK.xmlns.attrib "" >
+
+<!-- Declare a parameter entity %NS.decl.attrib; containing all
+     XML namespace declaration attributes used by XHTML, including
+     a default xmlns attribute when prefixing is inactive.
+-->
+<![%XHTML.prefixed;[
+<!ENTITY % XHTML.xmlns.attrib
+     "%NS.decl.attrib;
+      %XLINK.xmlns.attrib;"
+>
+]]>
+<!ENTITY % XHTML.xmlns.attrib
+     "xmlns        %URI.datatype;           #FIXED '%XHTML.xmlns;'
+      %XLINK.xmlns.attrib;"
+>
+
+<!-- placeholder for qualified name redeclarations -->
+<!ENTITY % xhtml-qname.redecl "" >
+
+
+<!-- Section B: XHTML Qualified Names ::::::::::::::::::::::::::::: -->
+
+<!-- 6. This section declares parameter entities used to provide
+        namespace-qualified names for all XHTML element types.
+-->
+
+<!-- module:  xhtml-applet-1.mod -->
+<!ENTITY % applet.qname  "%XHTML.pfx;applet" >
+
+<!-- module:  xhtml-base-1.mod -->
+<!ENTITY % base.qname    "%XHTML.pfx;base" >
+
+<!-- module:  xhtml-bdo-1.mod -->
+<!ENTITY % bdo.qname     "%XHTML.pfx;bdo" >
+
+<!-- module:  xhtml-blkphras-1.mod -->
+<!ENTITY % address.qname "%XHTML.pfx;address" >
+<!ENTITY % blockquote.qname  "%XHTML.pfx;blockquote" >
+<!ENTITY % pre.qname     "%XHTML.pfx;pre" >
+<!ENTITY % h1.qname      "%XHTML.pfx;h1" >
+<!ENTITY % h2.qname      "%XHTML.pfx;h2" >
+<!ENTITY % h3.qname      "%XHTML.pfx;h3" >
+<!ENTITY % h4.qname      "%XHTML.pfx;h4" >
+<!ENTITY % h5.qname      "%XHTML.pfx;h5" >
+<!ENTITY % h6.qname      "%XHTML.pfx;h6" >
+
+<!-- module:  xhtml-blkpres-1.mod -->
+<!ENTITY % hr.qname      "%XHTML.pfx;hr" >
+
+<!-- module:  xhtml-blkstruct-1.mod -->
+<!ENTITY % div.qname     "%XHTML.pfx;div" >
+<!ENTITY % p.qname       "%XHTML.pfx;p" >
+
+<!-- module:  xhtml-edit-1.mod -->
+<!ENTITY % ins.qname     "%XHTML.pfx;ins" >
+<!ENTITY % del.qname     "%XHTML.pfx;del" >
+
+<!-- module:  xhtml-form-1.mod -->
+<!ENTITY % form.qname    "%XHTML.pfx;form" >
+<!ENTITY % label.qname   "%XHTML.pfx;label" >
+<!ENTITY % input.qname   "%XHTML.pfx;input" >
+<!ENTITY % select.qname  "%XHTML.pfx;select" >
+<!ENTITY % optgroup.qname  "%XHTML.pfx;optgroup" >
+<!ENTITY % option.qname  "%XHTML.pfx;option" >
+<!ENTITY % textarea.qname  "%XHTML.pfx;textarea" >
+<!ENTITY % fieldset.qname  "%XHTML.pfx;fieldset" >
+<!ENTITY % legend.qname  "%XHTML.pfx;legend" >
+<!ENTITY % button.qname  "%XHTML.pfx;button" >
+
+<!-- module:  xhtml-hypertext-1.mod -->
+<!ENTITY % a.qname       "%XHTML.pfx;a" >
+
+<!-- module:  xhtml-image-1.mod -->
+<!ENTITY % img.qname     "%XHTML.pfx;img" >
+
+<!-- module:  xhtml-inlphras-1.mod -->
+<!ENTITY % abbr.qname    "%XHTML.pfx;abbr" >
+<!ENTITY % acronym.qname "%XHTML.pfx;acronym" >
+<!ENTITY % cite.qname    "%XHTML.pfx;cite" >
+<!ENTITY % code.qname    "%XHTML.pfx;code" >
+<!ENTITY % dfn.qname     "%XHTML.pfx;dfn" >
+<!ENTITY % em.qname      "%XHTML.pfx;em" >
+<!ENTITY % kbd.qname     "%XHTML.pfx;kbd" >
+<!ENTITY % q.qname       "%XHTML.pfx;q" >
+<!ENTITY % samp.qname    "%XHTML.pfx;samp" >
+<!ENTITY % strong.qname  "%XHTML.pfx;strong" >
+<!ENTITY % var.qname     "%XHTML.pfx;var" >
+
+<!-- module:  xhtml-inlpres-1.mod -->
+<!ENTITY % b.qname       "%XHTML.pfx;b" >
+<!ENTITY % big.qname     "%XHTML.pfx;big" >
+<!ENTITY % i.qname       "%XHTML.pfx;i" >
+<!ENTITY % small.qname   "%XHTML.pfx;small" >
+<!ENTITY % sub.qname     "%XHTML.pfx;sub" >
+<!ENTITY % sup.qname     "%XHTML.pfx;sup" >
+<!ENTITY % tt.qname      "%XHTML.pfx;tt" >
+
+<!-- module:  xhtml-inlstruct-1.mod -->
+<!ENTITY % br.qname      "%XHTML.pfx;br" >
+<!ENTITY % span.qname    "%XHTML.pfx;span" >
+
+<!-- module:  xhtml-ismap-1.mod (also csismap, ssismap) -->
+<!ENTITY % map.qname     "%XHTML.pfx;map" >
+<!ENTITY % area.qname    "%XHTML.pfx;area" >
+
+<!-- module:  xhtml-link-1.mod -->
+<!ENTITY % link.qname    "%XHTML.pfx;link" >
+
+<!-- module:  xhtml-list-1.mod -->
+<!ENTITY % dl.qname      "%XHTML.pfx;dl" >
+<!ENTITY % dt.qname      "%XHTML.pfx;dt" >
+<!ENTITY % dd.qname      "%XHTML.pfx;dd" >
+<!ENTITY % ol.qname      "%XHTML.pfx;ol" >
+<!ENTITY % ul.qname      "%XHTML.pfx;ul" >
+<!ENTITY % li.qname      "%XHTML.pfx;li" >
+
+<!-- module:  xhtml-meta-1.mod -->
+<!ENTITY % meta.qname    "%XHTML.pfx;meta" >
+
+<!-- module:  xhtml-param-1.mod -->
+<!ENTITY % param.qname   "%XHTML.pfx;param" >
+
+<!-- module:  xhtml-object-1.mod -->
+<!ENTITY % object.qname  "%XHTML.pfx;object" >
+
+<!-- module:  xhtml-script-1.mod -->
+<!ENTITY % script.qname  "%XHTML.pfx;script" >
+<!ENTITY % noscript.qname  "%XHTML.pfx;noscript" >
+
+<!-- module:  xhtml-struct-1.mod -->
+<!ENTITY % html.qname    "%XHTML.pfx;html" >
+<!ENTITY % head.qname    "%XHTML.pfx;head" >
+<!ENTITY % title.qname   "%XHTML.pfx;title" >
+<!ENTITY % body.qname    "%XHTML.pfx;body" >
+
+<!-- module:  xhtml-style-1.mod -->
+<!ENTITY % style.qname   "%XHTML.pfx;style" >
+
+<!-- module:  xhtml-table-1.mod -->
+<!ENTITY % table.qname   "%XHTML.pfx;table" >
+<!ENTITY % caption.qname "%XHTML.pfx;caption" >
+<!ENTITY % thead.qname   "%XHTML.pfx;thead" >
+<!ENTITY % tfoot.qname   "%XHTML.pfx;tfoot" >
+<!ENTITY % tbody.qname   "%XHTML.pfx;tbody" >
+<!ENTITY % colgroup.qname  "%XHTML.pfx;colgroup" >
+<!ENTITY % col.qname     "%XHTML.pfx;col" >
+<!ENTITY % tr.qname      "%XHTML.pfx;tr" >
+<!ENTITY % th.qname      "%XHTML.pfx;th" >
+<!ENTITY % td.qname      "%XHTML.pfx;td" >
+
+<!-- module:  xhtml-ruby-1.mod -->
+
+<!ENTITY % ruby.qname    "%XHTML.pfx;ruby" >
+<!ENTITY % rbc.qname     "%XHTML.pfx;rbc" >
+<!ENTITY % rtc.qname     "%XHTML.pfx;rtc" >
+<!ENTITY % rb.qname      "%XHTML.pfx;rb" >
+<!ENTITY % rt.qname      "%XHTML.pfx;rt" >
+<!ENTITY % rp.qname      "%XHTML.pfx;rp" >
+
+<!-- Provisional XHTML 2.0 Qualified Names  ...................... -->
+
+<!-- module:  xhtml-image-2.mod -->
+<!ENTITY % alt.qname     "%XHTML.pfx;alt" >
+
+<!-- end of xhtml-qname-1.mod -->
+]]>
+
+<!ENTITY % xhtml-events.module "IGNORE" >
+<![%xhtml-events.module;[
+<!ENTITY % xhtml-events.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Intrinsic Events 1.0//EN"
+            "xhtml-events-1.mod" >
+%xhtml-events.mod;]]>
+
+<!ENTITY % xhtml-attribs.module "INCLUDE" >
+<![%xhtml-attribs.module;[
+<!ENTITY % xhtml-attribs.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Common Attributes 1.0//EN"
+            "../xhtml11/xhtml-attribs-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Common Attributes Module  ...................................... -->
+<!-- file: xhtml-attribs-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-attribs-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Common Attributes 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-attribs-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Common Attributes
+
+     This module declares many of the common attributes for the XHTML DTD.
+     %NS.decl.attrib; is declared in the XHTML Qname module.
+-->
+
+<!ENTITY % id.attrib
+     "id           ID                       #IMPLIED"
+>
+
+<!ENTITY % class.attrib
+     "class        NMTOKENS                 #IMPLIED"
+>
+
+<!ENTITY % title.attrib
+     "title        %Text.datatype;          #IMPLIED"
+>
+
+<!ENTITY % Core.extra.attrib "" >
+
+<!ENTITY % Core.attrib
+     "%XHTML.xmlns.attrib;
+      %id.attrib;
+      %class.attrib;
+      %title.attrib;
+      %Core.extra.attrib;"
+>
+
+<!ENTITY % lang.attrib
+     "xml:lang     %LanguageCode.datatype;  #IMPLIED"
+>
+
+<![%XHTML.bidi;[
+<!ENTITY % dir.attrib
+     "dir          ( ltr | rtl )            #IMPLIED"
+>
+
+<!ENTITY % I18n.attrib
+     "%dir.attrib;
+      %lang.attrib;"
+>
+
+]]>
+<!ENTITY % I18n.attrib
+     "%lang.attrib;"
+>
+
+<!ENTITY % Common.extra.attrib "" >
+
+<!-- intrinsic event attributes declared previously
+-->
+<!ENTITY % Events.attrib "" >
+
+<!ENTITY % Common.attrib
+     "%Core.attrib;
+      %I18n.attrib;
+      %Events.attrib;
+      %Common.extra.attrib;"
+>
+
+<!-- end of xhtml-attribs-1.mod -->
+]]>
+
+<!-- placeholder for content model redeclarations -->
+<!ENTITY % xhtml-model.redecl "" >
+
+
+<!ENTITY % xhtml-model.module "INCLUDE" >
+<![%xhtml-model.module;[
+<!-- instantiate the Document Model module declared in the DTD driver
+-->
+<!-- ....................................................................... -->
+<!-- XHTML Mobile 1.0 Document Model Module
+.................................... -->
+<!-- file: xhtml-mobile10-model-1.mod
+
+     This is XHTML Mobile, a proper subset of XHTML.
+     	@Wireless Application Protocol Forum, Ltd. 2001.
+
+	Terms and conditions of use are available from the Wireless
+	Application Protocol Forum Ltd.
+	Web site (http://www.wapforum.org/what/copyright.htm).
+
+-->
+<!-- XHTML Mobile Document Model
+
+     This module describes the groupings of elements that make up
+     common content models for XHTML elements.
+-->
+
+<!-- Optional Elements in head  .............. -->
+
+<!ENTITY % HeadOpts.mix
+
+     "( %meta.qname; | %link.qname; | %object.qname; | %style.qname;
+     )*" >
+
+<!-- Miscellaneous Elements  ................. -->
+
+<!ENTITY % Misc.class "" >
+
+<!-- Inline Elements  ........................ -->
+
+<!ENTITY % InlStruct.class "%br.qname; | %span.qname;" >
+
+<!ENTITY % InlPhras.class
+     "| %em.qname; | %strong.qname; | %dfn.qname; | %code.qname;
+      | %samp.qname; | %kbd.qname; | %var.qname; | %cite.qname;
+      | %abbr.qname; | %acronym.qname; | %q.qname;" >
+
+<!ENTITY % InlPres.class
+     "| %i.qname; | %b.qname; | %big.qname; | %small.qname; " >
+
+
+<!ENTITY % I18n.class "" >
+
+<!ENTITY % Anchor.class "| %a.qname;" >
+
+<!ENTITY % InlSpecial.class "| %img.qname; | %object.qname;" >
+
+<!ENTITY % InlForm.class
+     "| %input.qname; | %select.qname; | %textarea.qname;
+      | %label.qname;"
+>
+
+<!ENTITY % Inline.extra "" >
+
+<!ENTITY % Inline.class
+     "%InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %Anchor.class;
+      %InlSpecial.class;
+      %InlForm.class;
+      %Inline.extra;"
+>
+
+<!ENTITY % InlNoAnchor.class
+     "%InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %InlSpecial.class;
+      %InlForm.class;
+      %Inline.extra;"
+>
+
+<!ENTITY % InlNoAnchor.mix
+     "%InlNoAnchor.class;
+      %Misc.class;"
+>
+
+<!ENTITY % Inline.mix
+     "%Inline.class;
+      %Misc.class;"
+>
+
+<!-- Block Elements  ......................... -->
+
+<!ENTITY % Heading.class
+     "%h1.qname; | %h2.qname; | %h3.qname;
+      | %h4.qname; | %h5.qname; | %h6.qname;"
+>
+<!ENTITY % List.class  "%ul.qname; | %ol.qname; | %dl.qname;" >
+
+<!ENTITY % Table.class "| %table.qname;" >
+
+<!ENTITY % Form.class  "| %form.qname;" >
+
+<!ENTITY % Fieldset.class  "| %fieldset.qname;" >
+
+<!ENTITY % BlkStruct.class "%p.qname; | %div.qname;" >
+
+<!ENTITY % BlkPhras.class
+     "| %pre.qname; | %blockquote.qname; | %address.qname;"
+>
+
+<!ENTITY % BlkPres.class "| %hr.qname;" >
+
+<!ENTITY % BlkSpecial.class
+     "%Table.class;
+      %Form.class;
+      %Fieldset.class;"
+>
+
+<!ENTITY % Block.extra "" >
+
+<!ENTITY % Block.class
+     "%BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %BlkSpecial.class;
+      %Block.extra;"
+>
+
+<!ENTITY % BlkNoForm.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %Table.class;
+      %Block.extra;
+      %Misc.class;"
+>
+
+<!ENTITY % Block.mix
+     "%Heading.class;
+      | %List.class;
+      | %Block.class;
+      %Misc.class;"
+>
+
+<!-- All Content Elements  ................... -->
+
+<!-- declares all content except tables
+-->
+<!ENTITY % FlowNoTable.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %Form.class;
+      %Block.extra;
+      | %Inline.class;
+      %Misc.class;"
+>
+
+
+<!ENTITY % Flow.mix
+     "%Heading.class;
+      | %List.class;
+      | %Block.class;
+      | %Inline.class;
+      %Misc.class;"
+>
+
+<!-- end of xhtml-mobile10-model-1.mod -->
+
+]]>
+
+<!ENTITY % xhtml-charent.module "INCLUDE" >
+<![%xhtml-charent.module;[
+<!ENTITY % xhtml-charent.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Character Entities 1.0//EN"
+            "../xhtml11/xhtml-charent-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Character Entities Module  ......................................... -->
+<!-- file: xhtml-charent-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-charent-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Character Entities 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-charent-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Character Entities for XHTML
+
+     This module declares the set of character entities for XHTML,
+     including the Latin 1, Symbol and Special character collections.
+-->
+
+<!ENTITY % xhtml-lat1
+    PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+           "../xhtml11/xhtml-lat1.ent" >
+<!-- ...................................................................... -->
+<!-- XML-compatible ISO Latin 1 Character Entity Set for XHTML ............ -->
+<!-- file: xhtml-lat1.ent
+
+     Typical invocation:
+
+       <!ENTITY % xhtml-lat1
+           PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+                  "xhtml-lat1.ent" >
+       %xhtml-lat1;
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+       SYSTEM "../xhtml11/xhtml-lat1.ent"
+
+     Revision:  $Id: xhtml-lat1.ent,v 4.1 2001/04/10 09:34:14 altheim Exp $ SMI
+
+     Portions (C) International Organization for Standardization 1986:
+     Permission to copy in any form is granted for use with conforming
+     SGML systems and applications as defined in ISO 8879, provided
+     this notice is included in all copies.
+-->
+
+<!ENTITY nbsp   "&#160;" ><!-- no-break space = non-breaking space, U+00A0 ISOnum -->
+<!ENTITY iexcl  "&#161;" ><!-- inverted exclamation mark, U+00A1 ISOnum -->
+<!ENTITY cent   "&#162;" ><!-- cent sign, U+00A2 ISOnum -->
+<!ENTITY pound  "&#163;" ><!-- pound sign, U+00A3 ISOnum -->
+<!ENTITY curren "&#164;" ><!-- currency sign, U+00A4 ISOnum -->
+<!ENTITY yen    "&#165;" ><!-- yen sign = yuan sign, U+00A5 ISOnum -->
+<!ENTITY brvbar "&#166;" ><!-- broken bar = broken vertical bar, U+00A6 ISOnum -->
+<!ENTITY sect   "&#167;" ><!-- section sign, U+00A7 ISOnum -->
+<!ENTITY uml    "&#168;" ><!-- diaeresis = spacing diaeresis, U+00A8 ISOdia -->
+<!ENTITY copy   "&#169;" ><!-- copyright sign, U+00A9 ISOnum -->
+<!ENTITY ordf   "&#170;" ><!-- feminine ordinal indicator, U+00AA ISOnum -->
+<!ENTITY laquo  "&#171;" ><!-- left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum -->
+<!ENTITY not    "&#172;" ><!-- not sign, U+00AC ISOnum -->
+<!ENTITY shy    "&#173;" ><!-- soft hyphen = discretionary hyphen, U+00AD ISOnum -->
+<!ENTITY reg    "&#174;" ><!-- registered sign = registered trade mark sign, U+00AE ISOnum -->
+<!ENTITY macr   "&#175;" ><!-- macron = spacing macron = overline = APL overbar, U+00AF ISOdia -->
+<!ENTITY deg    "&#176;" ><!-- degree sign, U+00B0 ISOnum -->
+<!ENTITY plusmn "&#177;" ><!-- plus-minus sign = plus-or-minus sign, U+00B1 ISOnum -->
+<!ENTITY sup2   "&#178;" ><!-- superscript two = superscript digit two = squared, U+00B2 ISOnum -->
+<!ENTITY sup3   "&#179;" ><!-- superscript three = superscript digit three = cubed, U+00B3 ISOnum -->
+<!ENTITY acute  "&#180;" ><!-- acute accent = spacing acute, U+00B4 ISOdia -->
+<!ENTITY micro  "&#181;" ><!-- micro sign, U+00B5 ISOnum -->
+<!ENTITY para   "&#182;" ><!-- pilcrow sign = paragraph sign, U+00B6 ISOnum -->
+<!ENTITY middot "&#183;" ><!-- middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum -->
+<!ENTITY cedil  "&#184;" ><!-- cedilla = spacing cedilla, U+00B8 ISOdia -->
+<!ENTITY sup1   "&#185;" ><!-- superscript one = superscript digit one, U+00B9 ISOnum -->
+<!ENTITY ordm   "&#186;" ><!-- masculine ordinal indicator, U+00BA ISOnum -->
+<!ENTITY raquo  "&#187;" ><!-- right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum -->
+<!ENTITY frac14 "&#188;" ><!-- vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum -->
+<!ENTITY frac12 "&#189;" ><!-- vulgar fraction one half = fraction one half, U+00BD ISOnum -->
+<!ENTITY frac34 "&#190;" ><!-- vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum -->
+<!ENTITY iquest "&#191;" ><!-- inverted question mark = turned question mark, U+00BF ISOnum -->
+<!ENTITY Agrave "&#192;" ><!-- latin capital A with grave = latin capital A grave, U+00C0 ISOlat1 -->
+<!ENTITY Aacute "&#193;" ><!-- latin capital A with acute, U+00C1 ISOlat1 -->
+<!ENTITY Acirc  "&#194;" ><!-- latin capital A with circumflex, U+00C2 ISOlat1 -->
+<!ENTITY Atilde "&#195;" ><!-- latin capital A with tilde, U+00C3 ISOlat1 -->
+<!ENTITY Auml   "&#196;" ><!-- latin capital A with diaeresis, U+00C4 ISOlat1 -->
+<!ENTITY Aring  "&#197;" ><!-- latin capital A with ring above = latin capital A ring, U+00C5 ISOlat1 -->
+<!ENTITY AElig  "&#198;" ><!-- latin capital AE = latin capital ligature AE, U+00C6 ISOlat1 -->
+<!ENTITY Ccedil "&#199;" ><!-- latin capital C with cedilla, U+00C7 ISOlat1 -->
+<!ENTITY Egrave "&#200;" ><!-- latin capital E with grave, U+00C8 ISOlat1 -->
+<!ENTITY Eacute "&#201;" ><!-- latin capital E with acute, U+00C9 ISOlat1 -->
+<!ENTITY Ecirc  "&#202;" ><!-- latin capital E with circumflex, U+00CA ISOlat1 -->
+<!ENTITY Euml   "&#203;" ><!-- latin capital E with diaeresis, U+00CB ISOlat1 -->
+<!ENTITY Igrave "&#204;" ><!-- latin capital I with grave, U+00CC ISOlat1 -->
+<!ENTITY Iacute "&#205;" ><!-- latin capital I with acute, U+00CD ISOlat1 -->
+<!ENTITY Icirc  "&#206;" ><!-- latin capital I with circumflex, U+00CE ISOlat1 -->
+<!ENTITY Iuml   "&#207;" ><!-- latin capital I with diaeresis, U+00CF ISOlat1 -->
+<!ENTITY ETH    "&#208;" ><!-- latin capital ETH, U+00D0 ISOlat1 -->
+<!ENTITY Ntilde "&#209;" ><!-- latin capital N with tilde, U+00D1 ISOlat1 -->
+<!ENTITY Ograve "&#210;" ><!-- latin capital O with grave, U+00D2 ISOlat1 -->
+<!ENTITY Oacute "&#211;" ><!-- latin capital O with acute, U+00D3 ISOlat1 -->
+<!ENTITY Ocirc  "&#212;" ><!-- latin capital O with circumflex, U+00D4 ISOlat1 -->
+<!ENTITY Otilde "&#213;" ><!-- latin capital O with tilde, U+00D5 ISOlat1 -->
+<!ENTITY Ouml   "&#214;" ><!-- latin capital O with diaeresis, U+00D6 ISOlat1 -->
+<!ENTITY times  "&#215;" ><!-- multiplication sign, U+00D7 ISOnum -->
+<!ENTITY Oslash "&#216;" ><!-- latin capital O with stroke = latin capital O slash, U+00D8 ISOlat1 -->
+<!ENTITY Ugrave "&#217;" ><!-- latin capital U with grave, U+00D9 ISOlat1 -->
+<!ENTITY Uacute "&#218;" ><!-- latin capital U with acute, U+00DA ISOlat1 -->
+<!ENTITY Ucirc  "&#219;" ><!-- latin capital U with circumflex, U+00DB ISOlat1 -->
+<!ENTITY Uuml   "&#220;" ><!-- latin capital U with diaeresis, U+00DC ISOlat1 -->
+<!ENTITY Yacute "&#221;" ><!-- latin capital Y with acute, U+00DD ISOlat1 -->
+<!ENTITY THORN  "&#222;" ><!-- latin capital THORN, U+00DE ISOlat1 -->
+<!ENTITY szlig  "&#223;" ><!-- latin small sharp s = ess-zed, U+00DF ISOlat1 -->
+<!ENTITY agrave "&#224;" ><!-- latin small a with grave = latin small a grave, U+00E0 ISOlat1 -->
+<!ENTITY aacute "&#225;" ><!-- latin small a with acute, U+00E1 ISOlat1 -->
+<!ENTITY acirc  "&#226;" ><!-- latin small a with circumflex, U+00E2 ISOlat1 -->
+<!ENTITY atilde "&#227;" ><!-- latin small a with tilde, U+00E3 ISOlat1 -->
+<!ENTITY auml   "&#228;" ><!-- latin small a with diaeresis, U+00E4 ISOlat1 -->
+<!ENTITY aring  "&#229;" ><!-- latin small a with ring above = latin small a ring, U+00E5 ISOlat1 -->
+<!ENTITY aelig  "&#230;" ><!-- latin small ae = latin small ligature ae, U+00E6 ISOlat1 -->
+<!ENTITY ccedil "&#231;" ><!-- latin small c with cedilla, U+00E7 ISOlat1 -->
+<!ENTITY egrave "&#232;" ><!-- latin small e with grave, U+00E8 ISOlat1 -->
+<!ENTITY eacute "&#233;" ><!-- latin small e with acute, U+00E9 ISOlat1 -->
+<!ENTITY ecirc  "&#234;" ><!-- latin small e with circumflex, U+00EA ISOlat1 -->
+<!ENTITY euml   "&#235;" ><!-- latin small e with diaeresis, U+00EB ISOlat1 -->
+<!ENTITY igrave "&#236;" ><!-- latin small i with grave, U+00EC ISOlat1 -->
+<!ENTITY iacute "&#237;" ><!-- latin small i with acute, U+00ED ISOlat1 -->
+<!ENTITY icirc  "&#238;" ><!-- latin small i with circumflex, U+00EE ISOlat1 -->
+<!ENTITY iuml   "&#239;" ><!-- latin small i with diaeresis, U+00EF ISOlat1 -->
+<!ENTITY eth    "&#240;" ><!-- latin small eth, U+00F0 ISOlat1 -->
+<!ENTITY ntilde "&#241;" ><!-- latin small n with tilde, U+00F1 ISOlat1 -->
+<!ENTITY ograve "&#242;" ><!-- latin small o with grave, U+00F2 ISOlat1 -->
+<!ENTITY oacute "&#243;" ><!-- latin small o with acute, U+00F3 ISOlat1 -->
+<!ENTITY ocirc  "&#244;" ><!-- latin small o with circumflex, U+00F4 ISOlat1 -->
+<!ENTITY otilde "&#245;" ><!-- latin small o with tilde, U+00F5 ISOlat1 -->
+<!ENTITY ouml   "&#246;" ><!-- latin small o with diaeresis, U+00F6 ISOlat1 -->
+<!ENTITY divide "&#247;" ><!-- division sign, U+00F7 ISOnum -->
+<!ENTITY oslash "&#248;" ><!-- latin small o with stroke, = latin small o slash, U+00F8 ISOlat1 -->
+<!ENTITY ugrave "&#249;" ><!-- latin small u with grave, U+00F9 ISOlat1 -->
+<!ENTITY uacute "&#250;" ><!-- latin small u with acute, U+00FA ISOlat1 -->
+<!ENTITY ucirc  "&#251;" ><!-- latin small u with circumflex, U+00FB ISOlat1 -->
+<!ENTITY uuml   "&#252;" ><!-- latin small u with diaeresis, U+00FC ISOlat1 -->
+<!ENTITY yacute "&#253;" ><!-- latin small y with acute, U+00FD ISOlat1 -->
+<!ENTITY thorn  "&#254;" ><!-- latin small thorn with, U+00FE ISOlat1 -->
+<!ENTITY yuml   "&#255;" ><!-- latin small y with diaeresis, U+00FF ISOlat1 -->
+<!-- end of xhtml-lat1.ent -->
+
+
+<!ENTITY % xhtml-symbol
+    PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN"
+           "../xhtml11/xhtml-symbol.ent" >
+<!-- ...................................................................... -->
+<!-- ISO Math, Greek and Symbolic Character Entity Set for XHTML .......... -->
+<!-- file: xhtml-symbol.ent
+
+     Typical invocation:
+
+       <!ENTITY % xhtml-symbol
+           PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN"
+                  "xhtml-symbol.ent" >
+       %xhtml-symbol;
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN"
+       SYSTEM "../xhtml11/xhtml-symbol.ent"
+
+     Revision:  $Id: xhtml-symbol.ent,v 4.1 2001/04/10 09:34:14 altheim Exp $ SMI
+
+     Portions (C) International Organization for Standardization 1986:
+     Permission to copy in any form is granted for use with conforming
+     SGML systems and applications as defined in ISO 8879, provided
+     this notice is included in all copies.
+-->
+
+<!-- Relevant ISO entity set is given unless names are newly introduced.
+     New names (i.e., not in ISO 8879 [SGML] list) do not clash with
+     any existing ISO 8879 entity names. ISO 10646 [ISO10646] character
+     numbers are given for each character, in hex. Entity values are
+     decimal conversions of the ISO 10646 values and refer to the
+     document character set. Names are Unicode [UNICODE] names.
+-->
+
+<!-- Latin Extended-B -->
+<!ENTITY fnof     "&#402;" ><!-- latin small f with hook = function
+                              = florin, U+0192 ISOtech -->
+
+<!-- Greek -->
+<!ENTITY Alpha    "&#913;" ><!-- greek capital letter alpha, U+0391 -->
+<!ENTITY Beta     "&#914;" ><!-- greek capital letter beta, U+0392 -->
+<!ENTITY Gamma    "&#915;" ><!-- greek capital letter gamma, U+0393 ISOgrk3 -->
+<!ENTITY Delta    "&#916;" ><!-- greek capital letter delta, U+0394 ISOgrk3 -->
+<!ENTITY Epsilon  "&#917;" ><!-- greek capital letter epsilon, U+0395 -->
+<!ENTITY Zeta     "&#918;" ><!-- greek capital letter zeta, U+0396 -->
+<!ENTITY Eta      "&#919;" ><!-- greek capital letter eta, U+0397 -->
+<!ENTITY Theta    "&#920;" ><!-- greek capital letter theta, U+0398 ISOgrk3 -->
+<!ENTITY Iota     "&#921;" ><!-- greek capital letter iota, U+0399 -->
+<!ENTITY Kappa    "&#922;" ><!-- greek capital letter kappa, U+039A -->
+<!ENTITY Lambda   "&#923;" ><!-- greek capital letter lambda, U+039B ISOgrk3 -->
+<!ENTITY Mu       "&#924;" ><!-- greek capital letter mu, U+039C -->
+<!ENTITY Nu       "&#925;" ><!-- greek capital letter nu, U+039D -->
+<!ENTITY Xi       "&#926;" ><!-- greek capital letter xi, U+039E ISOgrk3 -->
+<!ENTITY Omicron  "&#927;" ><!-- greek capital letter omicron, U+039F -->
+<!ENTITY Pi       "&#928;" ><!-- greek capital letter pi, U+03A0 ISOgrk3 -->
+<!ENTITY Rho      "&#929;" ><!-- greek capital letter rho, U+03A1 -->
+<!-- there is no Sigmaf, and no U+03A2 character either -->
+<!ENTITY Sigma    "&#931;" ><!-- greek capital letter sigma, U+03A3 ISOgrk3 -->
+<!ENTITY Tau      "&#932;" ><!-- greek capital letter tau, U+03A4 -->
+<!ENTITY Upsilon  "&#933;" ><!-- greek capital letter upsilon,
+                              U+03A5 ISOgrk3 -->
+<!ENTITY Phi      "&#934;" ><!-- greek capital letter phi, U+03A6 ISOgrk3 -->
+<!ENTITY Chi      "&#935;" ><!-- greek capital letter chi, U+03A7 -->
+<!ENTITY Psi      "&#936;" ><!-- greek capital letter psi, U+03A8 ISOgrk3 -->
+<!ENTITY Omega    "&#937;" ><!-- greek capital letter omega, U+03A9 ISOgrk3 -->
+<!ENTITY alpha    "&#945;" ><!-- greek small letter alpha, U+03B1 ISOgrk3 -->
+<!ENTITY beta     "&#946;" ><!-- greek small letter beta, U+03B2 ISOgrk3 -->
+<!ENTITY gamma    "&#947;" ><!-- greek small letter gamma, U+03B3 ISOgrk3 -->
+<!ENTITY delta    "&#948;" ><!-- greek small letter delta, U+03B4 ISOgrk3 -->
+<!ENTITY epsilon  "&#949;" ><!-- greek small letter epsilon, U+03B5 ISOgrk3 -->
+<!ENTITY zeta     "&#950;" ><!-- greek small letter zeta, U+03B6 ISOgrk3 -->
+<!ENTITY eta      "&#951;" ><!-- greek small letter eta, U+03B7 ISOgrk3 -->
+<!ENTITY theta    "&#952;" ><!-- greek small letter theta, U+03B8 ISOgrk3 -->
+<!ENTITY iota     "&#953;" ><!-- greek small letter iota, U+03B9 ISOgrk3 -->
+<!ENTITY kappa    "&#954;" ><!-- greek small letter kappa, U+03BA ISOgrk3 -->
+<!ENTITY lambda   "&#955;" ><!-- greek small letter lambda, U+03BB ISOgrk3 -->
+<!ENTITY mu       "&#956;" ><!-- greek small letter mu, U+03BC ISOgrk3 -->
+<!ENTITY nu       "&#957;" ><!-- greek small letter nu, U+03BD ISOgrk3 -->
+<!ENTITY xi       "&#958;" ><!-- greek small letter xi, U+03BE ISOgrk3 -->
+<!ENTITY omicron  "&#959;" ><!-- greek small letter omicron, U+03BF NEW -->
+<!ENTITY pi       "&#960;" ><!-- greek small letter pi, U+03C0 ISOgrk3 -->
+<!ENTITY rho      "&#961;" ><!-- greek small letter rho, U+03C1 ISOgrk3 -->
+<!ENTITY sigmaf   "&#962;" ><!-- greek small letter final sigma, U+03C2 ISOgrk3 -->
+<!ENTITY sigma    "&#963;" ><!-- greek small letter sigma, U+03C3 ISOgrk3 -->
+<!ENTITY tau      "&#964;" ><!-- greek small letter tau, U+03C4 ISOgrk3 -->
+<!ENTITY upsilon  "&#965;" ><!-- greek small letter upsilon, U+03C5 ISOgrk3 -->
+<!ENTITY phi      "&#966;" ><!-- greek small letter phi, U+03C6 ISOgrk3 -->
+<!ENTITY chi      "&#967;" ><!-- greek small letter chi, U+03C7 ISOgrk3 -->
+<!ENTITY psi      "&#968;" ><!-- greek small letter psi, U+03C8 ISOgrk3 -->
+<!ENTITY omega    "&#969;" ><!-- greek small letter omega, U+03C9 ISOgrk3 -->
+<!ENTITY thetasym "&#977;" ><!-- greek small letter theta symbol, U+03D1 NEW -->
+<!ENTITY upsih    "&#978;" ><!-- greek upsilon with hook symbol, U+03D2 NEW -->
+<!ENTITY piv      "&#982;" ><!-- greek pi symbol, U+03D6 ISOgrk3 -->
+
+<!-- General Punctuation -->
+<!ENTITY bull     "&#8226;" ><!-- bullet = black small circle, U+2022 ISOpub  -->
+<!-- bullet is NOT the same as bullet operator, U+2219 -->
+<!ENTITY hellip   "&#8230;" ><!-- horizontal ellipsis = three dot leader, U+2026 ISOpub  -->
+<!ENTITY prime    "&#8242;" ><!-- prime = minutes = feet, U+2032 ISOtech -->
+<!ENTITY Prime    "&#8243;" ><!-- double prime = seconds = inches, U+2033 ISOtech -->
+<!ENTITY oline    "&#8254;" ><!-- overline = spacing overscore, U+203E NEW -->
+<!ENTITY frasl    "&#8260;" ><!-- fraction slash, U+2044 NEW -->
+
+<!-- Letterlike Symbols -->
+<!ENTITY weierp   "&#8472;" ><!-- script capital P = power set = Weierstrass p, U+2118 ISOamso -->
+<!ENTITY image    "&#8465;" ><!-- blackletter capital I = imaginary part, U+2111 ISOamso -->
+<!ENTITY real     "&#8476;" ><!-- blackletter capital R = real part symbol, U+211C ISOamso -->
+<!ENTITY trade    "&#8482;" ><!-- trade mark sign, U+2122 ISOnum -->
+<!ENTITY alefsym  "&#8501;" ><!-- alef symbol = first transfinite cardinal, U+2135 NEW -->
+<!-- alef symbol is NOT the same as hebrew letter alef, U+05D0 although
+     the same glyph could be used to depict both characters -->
+
+<!-- Arrows -->
+<!ENTITY larr     "&#8592;" ><!-- leftwards arrow, U+2190 ISOnum -->
+<!ENTITY uarr     "&#8593;" ><!-- upwards arrow, U+2191 ISOnum-->
+<!ENTITY rarr     "&#8594;" ><!-- rightwards arrow, U+2192 ISOnum -->
+<!ENTITY darr     "&#8595;" ><!-- downwards arrow, U+2193 ISOnum -->
+<!ENTITY harr     "&#8596;" ><!-- left right arrow, U+2194 ISOamsa -->
+<!ENTITY crarr    "&#8629;" ><!-- downwards arrow with corner leftwards
+                               = carriage return, U+21B5 NEW -->
+<!ENTITY lArr     "&#8656;" ><!-- leftwards double arrow, U+21D0 ISOtech -->
+<!-- Unicode does not say that lArr is the same as the 'is implied by' arrow
+    but also does not have any other character for that function. So ? lArr can
+    be used for 'is implied by' as ISOtech suggests -->
+<!ENTITY uArr     "&#8657;" ><!-- upwards double arrow, U+21D1 ISOamsa -->
+<!ENTITY rArr     "&#8658;" ><!-- rightwards double arrow, U+21D2 ISOtech -->
+<!-- Unicode does not say this is the 'implies' character but does not have
+     another character with this function so ?
+     rArr can be used for 'implies' as ISOtech suggests -->
+<!ENTITY dArr     "&#8659;" ><!-- downwards double arrow, U+21D3 ISOamsa -->
+<!ENTITY hArr     "&#8660;" ><!-- left right double arrow, U+21D4 ISOamsa -->
+
+<!-- Mathematical Operators -->
+<!ENTITY forall   "&#8704;" ><!-- for all, U+2200 ISOtech -->
+<!ENTITY part     "&#8706;" ><!-- partial differential, U+2202 ISOtech  -->
+<!ENTITY exist    "&#8707;" ><!-- there exists, U+2203 ISOtech -->
+<!ENTITY empty    "&#8709;" ><!-- empty set = null set = diameter, U+2205 ISOamso -->
+<!ENTITY nabla    "&#8711;" ><!-- nabla = backward difference, U+2207 ISOtech -->
+<!ENTITY isin     "&#8712;" ><!-- element of, U+2208 ISOtech -->
+<!ENTITY notin    "&#8713;" ><!-- not an element of, U+2209 ISOtech -->
+<!ENTITY ni       "&#8715;" ><!-- contains as member, U+220B ISOtech -->
+<!-- should there be a more memorable name than 'ni'? -->
+<!ENTITY prod     "&#8719;" ><!-- n-ary product = product sign, U+220F ISOamsb -->
+<!-- prod is NOT the same character as U+03A0 'greek capital letter pi' though
+     the same glyph might be used for both -->
+<!ENTITY sum      "&#8721;" ><!-- n-ary sumation, U+2211 ISOamsb -->
+<!-- sum is NOT the same character as U+03A3 'greek capital letter sigma'
+     though the same glyph might be used for both -->
+<!ENTITY minus    "&#8722;" ><!-- minus sign, U+2212 ISOtech -->
+<!ENTITY lowast   "&#8727;" ><!-- asterisk operator, U+2217 ISOtech -->
+<!ENTITY radic    "&#8730;" ><!-- square root = radical sign, U+221A ISOtech -->
+<!ENTITY prop     "&#8733;" ><!-- proportional to, U+221D ISOtech -->
+<!ENTITY infin    "&#8734;" ><!-- infinity, U+221E ISOtech -->
+<!ENTITY ang      "&#8736;" ><!-- angle, U+2220 ISOamso -->
+<!ENTITY and      "&#8743;" ><!-- logical and = wedge, U+2227 ISOtech -->
+<!ENTITY or       "&#8744;" ><!-- logical or = vee, U+2228 ISOtech -->
+<!ENTITY cap      "&#8745;" ><!-- intersection = cap, U+2229 ISOtech -->
+<!ENTITY cup      "&#8746;" ><!-- union = cup, U+222A ISOtech -->
+<!ENTITY int      "&#8747;" ><!-- integral, U+222B ISOtech -->
+<!ENTITY there4   "&#8756;" ><!-- therefore, U+2234 ISOtech -->
+<!ENTITY sim      "&#8764;" ><!-- tilde operator = varies with = similar to, U+223C ISOtech -->
+<!-- tilde operator is NOT the same character as the tilde, U+007E,
+     although the same glyph might be used to represent both  -->
+<!ENTITY cong     "&#8773;" ><!-- approximately equal to, U+2245 ISOtech -->
+<!ENTITY asymp    "&#8776;" ><!-- almost equal to = asymptotic to, U+2248 ISOamsr -->
+<!ENTITY ne       "&#8800;" ><!-- not equal to, U+2260 ISOtech -->
+<!ENTITY equiv    "&#8801;" ><!-- identical to, U+2261 ISOtech -->
+<!ENTITY le       "&#8804;" ><!-- less-than or equal to, U+2264 ISOtech -->
+<!ENTITY ge       "&#8805;" ><!-- greater-than or equal to, U+2265 ISOtech -->
+<!ENTITY sub      "&#8834;" ><!-- subset of, U+2282 ISOtech -->
+<!ENTITY sup      "&#8835;" ><!-- superset of, U+2283 ISOtech -->
+<!-- note that nsup, 'not a superset of, U+2283' is not covered by the Symbol
+     font encoding and is not included. Should it be, for symmetry?
+     It is in ISOamsn  -->
+<!ENTITY nsub     "&#8836;" ><!-- not a subset of, U+2284 ISOamsn -->
+<!ENTITY sube     "&#8838;" ><!-- subset of or equal to, U+2286 ISOtech -->
+<!ENTITY supe     "&#8839;" ><!-- superset of or equal to, U+2287 ISOtech -->
+<!ENTITY oplus    "&#8853;" ><!-- circled plus = direct sum, U+2295 ISOamsb -->
+<!ENTITY otimes   "&#8855;" ><!-- circled times = vector product, U+2297 ISOamsb -->
+<!ENTITY perp     "&#8869;" ><!-- up tack = orthogonal to = perpendicular, U+22A5 ISOtech -->
+<!ENTITY sdot     "&#8901;" ><!-- dot operator, U+22C5 ISOamsb -->
+<!-- dot operator is NOT the same character as U+00B7 middle dot -->
+
+<!-- Miscellaneous Technical -->
+<!ENTITY lceil    "&#8968;" ><!-- left ceiling = apl upstile, U+2308 ISOamsc  -->
+<!ENTITY rceil    "&#8969;" ><!-- right ceiling, U+2309 ISOamsc  -->
+<!ENTITY lfloor   "&#8970;" ><!-- left floor = apl downstile, U+230A ISOamsc  -->
+<!ENTITY rfloor   "&#8971;" ><!-- right floor, U+230B ISOamsc  -->
+<!ENTITY lang     "&#9001;" ><!-- left-pointing angle bracket = bra, U+2329 ISOtech -->
+<!-- lang is NOT the same character as U+003C 'less than'
+     or U+2039 'single left-pointing angle quotation mark' -->
+<!ENTITY rang     "&#9002;" ><!-- right-pointing angle bracket = ket, U+232A ISOtech -->
+<!-- rang is NOT the same character as U+003E 'greater than'
+     or U+203A 'single right-pointing angle quotation mark' -->
+
+<!-- Geometric Shapes -->
+<!ENTITY loz      "&#9674;" ><!-- lozenge, U+25CA ISOpub -->
+
+<!-- Miscellaneous Symbols -->
+<!ENTITY spades   "&#9824;" ><!-- black spade suit, U+2660 ISOpub -->
+<!-- black here seems to mean filled as opposed to hollow -->
+<!ENTITY clubs    "&#9827;" ><!-- black club suit = shamrock, U+2663 ISOpub -->
+<!ENTITY hearts   "&#9829;" ><!-- black heart suit = valentine, U+2665 ISOpub -->
+<!ENTITY diams    "&#9830;" ><!-- black diamond suit, U+2666 ISOpub -->
+
+<!-- end of xhtml-symbol.ent -->
+
+
+<!ENTITY % xhtml-special
+    PUBLIC "-//W3C//ENTITIES Special for XHTML//EN"
+           "../xhtml11/xhtml-special.ent" >
+<!-- ...................................................................... -->
+<!-- XML-compatible ISO Special Character Entity Set for XHTML ............ -->
+<!-- file: xhtml-special.ent
+
+     Typical invocation:
+
+       <!ENTITY % xhtml-special
+           PUBLIC "-//W3C//ENTITIES Special for XHTML//EN"
+                  "xhtml-special.ent" >
+       %xhtml-special;
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES Special for XHTML//EN"
+       SYSTEM "../xhtml11/xhtml-special.ent"
+
+     Revision:  $Id: xhtml-special.ent,v 4.1 2001/04/10 09:34:14 altheim Exp $ SMI
+
+     Portions (C) International Organization for Standardization 1986:
+     Permission to copy in any form is granted for use with conforming
+     SGML systems and applications as defined in ISO 8879, provided
+     this notice is included in all copies.
+
+     Revisions:
+2000-10-28: added &apos; and altered XML Predefined Entities for compatibility
+-->
+
+<!-- Relevant ISO entity set is given unless names are newly introduced.
+     New names (i.e., not in ISO 8879 [SGML] list) do not clash with
+     any existing ISO 8879 entity names. ISO 10646 [ISO10646] character
+     numbers are given for each character, in hex. Entity values are
+     decimal conversions of the ISO 10646 values and refer to the
+     document character set. Names are Unicode [UNICODE] names.
+-->
+
+<!-- C0 Controls and Basic Latin -->
+<!ENTITY lt      "&#38;&#60;" ><!-- less-than sign, U+003C ISOnum -->
+<!ENTITY gt      "&#62;" ><!-- greater-than sign, U+003E ISOnum -->
+<!ENTITY amp     "&#38;&#38;" ><!-- ampersand, U+0026 ISOnum -->
+<!ENTITY apos    "&#39;" ><!-- apostrophe, U+0027 ISOnum -->
+<!ENTITY quot    "&#34;" ><!-- quotation mark = APL quote, U+0022 ISOnum -->
+
+<!-- Latin Extended-A -->
+<!ENTITY OElig   "&#338;" ><!-- latin capital ligature OE, U+0152 ISOlat2 -->
+<!ENTITY oelig   "&#339;" ><!-- latin small ligature oe, U+0153 ISOlat2 -->
+
+<!-- ligature is a misnomer, this is a separate character in some languages -->
+<!ENTITY Scaron  "&#352;" ><!-- latin capital letter S with caron, U+0160 ISOlat2 -->
+<!ENTITY scaron  "&#353;" ><!-- latin small letter s with caron, U+0161 ISOlat2 -->
+<!ENTITY Yuml    "&#376;" ><!-- latin capital letter Y with diaeresis, U+0178 ISOlat2 -->
+
+<!-- Spacing Modifier Letters -->
+<!ENTITY circ    "&#710;" ><!-- modifier letter circumflex accent, U+02C6 ISOpub -->
+<!ENTITY tilde   "&#732;" ><!-- small tilde, U+02DC ISOdia -->
+
+<!-- General Punctuation -->
+<!ENTITY ensp    "&#8194;" ><!-- en space, U+2002 ISOpub -->
+<!ENTITY emsp    "&#8195;" ><!-- em space, U+2003 ISOpub -->
+<!ENTITY thinsp  "&#8201;" ><!-- thin space, U+2009 ISOpub -->
+<!ENTITY zwnj    "&#8204;" ><!-- zero width non-joiner, U+200C NEW RFC 2070 -->
+<!ENTITY zwj     "&#8205;" ><!-- zero width joiner, U+200D NEW RFC 2070 -->
+<!ENTITY lrm     "&#8206;" ><!-- left-to-right mark, U+200E NEW RFC 2070 -->
+<!ENTITY rlm     "&#8207;" ><!-- right-to-left mark, U+200F NEW RFC 2070 -->
+<!ENTITY ndash   "&#8211;" ><!-- en dash, U+2013 ISOpub -->
+<!ENTITY mdash   "&#8212;" ><!-- em dash, U+2014 ISOpub -->
+<!ENTITY lsquo   "&#8216;" ><!-- left single quotation mark, U+2018 ISOnum -->
+<!ENTITY rsquo   "&#8217;" ><!-- right single quotation mark, U+2019 ISOnum -->
+<!ENTITY sbquo   "&#8218;" ><!-- single low-9 quotation mark, U+201A NEW -->
+<!ENTITY ldquo   "&#8220;" ><!-- left double quotation mark, U+201C ISOnum -->
+<!ENTITY rdquo   "&#8221;" ><!-- right double quotation mark, U+201D ISOnum -->
+<!ENTITY bdquo   "&#8222;" ><!-- double low-9 quotation mark, U+201E NEW -->
+<!ENTITY dagger  "&#8224;" ><!-- dagger, U+2020 ISOpub -->
+<!ENTITY Dagger  "&#8225;" ><!-- double dagger, U+2021 ISOpub -->
+<!ENTITY permil  "&#8240;" ><!-- per mille sign, U+2030 ISOtech -->
+
+<!-- lsaquo is proposed but not yet ISO standardized -->
+<!ENTITY lsaquo  "&#8249;" ><!-- single left-pointing angle quotation mark, U+2039 ISO proposed -->
+<!-- rsaquo is proposed but not yet ISO standardized -->
+<!ENTITY rsaquo  "&#8250;" ><!-- single right-pointing angle quotation mark, U+203A ISO proposed -->
+<!ENTITY euro    "&#8364;" ><!-- euro sign, U+20AC NEW -->
+
+<!-- end of xhtml-special.ent -->
+
+
+<!-- end of xhtml-charent-1.mod -->
+]]>
+
+<!-- end of xhtml-framework-1.mod -->
+
+
+<!-- XHTML Core Modules ........................................ -->
+<!ENTITY % pre.content
+     "( #PCDATA
+      | %InlStruct.class;
+      %InlPhras.class;
+      %Anchor.class;
+      %Inline.extra; )*"
+>
+
+<!ENTITY % xhtml-text.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Text 1.0//EN"
+            "../xhtml11/xhtml-text-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Text Module  ................................................... -->
+<!-- file: xhtml-text-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-text-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Text 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-text-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Textual Content
+
+     The Text module includes declarations for all core
+     text container elements and their attributes.
+-->
+
+<!ENTITY % xhtml-inlstruct.module "INCLUDE" >
+<![%xhtml-inlstruct.module;[
+<!ENTITY % xhtml-inlstruct.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Inline Structural 1.0//EN"
+            "../xhtml11/xhtml-inlstruct-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Inline Structural Module  ...................................... -->
+<!-- file: xhtml-inlstruct-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-inlstruct-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Inline Structural 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-inlstruct-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Inline Structural
+
+        br, span
+
+     This module declares the elements and their attributes
+     used to support inline-level structural markup.
+-->
+
+<!-- br: forced line break ............................. -->
+
+<!ENTITY % br.element  "INCLUDE" >
+<![%br.element;[
+
+<!ENTITY % br.content  "EMPTY" >
+<!ENTITY % br.qname  "br" >
+<!ELEMENT %br.qname;  %br.content; >
+
+<!-- end of br.element -->]]>
+
+<!ENTITY % br.attlist  "INCLUDE" >
+<![%br.attlist;[
+<!ATTLIST %br.qname;
+      %Core.attrib;
+>
+<!-- end of br.attlist -->]]>
+
+<!-- span: generic inline container .................... -->
+
+<!ENTITY % span.element  "INCLUDE" >
+<![%span.element;[
+<!ENTITY % span.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % span.qname  "span" >
+<!ELEMENT %span.qname;  %span.content; >
+<!-- end of span.element -->]]>
+
+<!ENTITY % span.attlist  "INCLUDE" >
+<![%span.attlist;[
+<!ATTLIST %span.qname;
+      %Common.attrib;
+>
+<!-- end of span.attlist -->]]>
+
+<!-- end of xhtml-inlstruct-1.mod -->
+]]>
+
+<!ENTITY % xhtml-inlphras.module "INCLUDE" >
+<![%xhtml-inlphras.module;[
+<!ENTITY % xhtml-inlphras.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Inline Phrasal 1.0//EN"
+            "../xhtml11/xhtml-inlphras-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Inline Phrasal Module  ......................................... -->
+<!-- file: xhtml-inlphras-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-inlphras-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Inline Phrasal 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-inlphras-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Inline Phrasal
+
+        abbr, acronym, cite, code, dfn, em, kbd, q, samp, strong, var
+
+     This module declares the elements and their attributes used to
+     support inline-level phrasal markup.
+-->
+
+<!ENTITY % abbr.element  "INCLUDE" >
+<![%abbr.element;[
+<!ENTITY % abbr.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % abbr.qname  "abbr" >
+<!ELEMENT %abbr.qname;  %abbr.content; >
+<!-- end of abbr.element -->]]>
+
+<!ENTITY % abbr.attlist  "INCLUDE" >
+<![%abbr.attlist;[
+<!ATTLIST %abbr.qname;
+      %Common.attrib;
+>
+<!-- end of abbr.attlist -->]]>
+
+<!ENTITY % acronym.element  "INCLUDE" >
+<![%acronym.element;[
+<!ENTITY % acronym.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % acronym.qname  "acronym" >
+<!ELEMENT %acronym.qname;  %acronym.content; >
+<!-- end of acronym.element -->]]>
+
+<!ENTITY % acronym.attlist  "INCLUDE" >
+<![%acronym.attlist;[
+<!ATTLIST %acronym.qname;
+      %Common.attrib;
+>
+<!-- end of acronym.attlist -->]]>
+
+<!ENTITY % cite.element  "INCLUDE" >
+<![%cite.element;[
+<!ENTITY % cite.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % cite.qname  "cite" >
+<!ELEMENT %cite.qname;  %cite.content; >
+<!-- end of cite.element -->]]>
+
+<!ENTITY % cite.attlist  "INCLUDE" >
+<![%cite.attlist;[
+<!ATTLIST %cite.qname;
+      %Common.attrib;
+>
+<!-- end of cite.attlist -->]]>
+
+<!ENTITY % code.element  "INCLUDE" >
+<![%code.element;[
+<!ENTITY % code.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % code.qname  "code" >
+<!ELEMENT %code.qname;  %code.content; >
+<!-- end of code.element -->]]>
+
+<!ENTITY % code.attlist  "INCLUDE" >
+<![%code.attlist;[
+<!ATTLIST %code.qname;
+      %Common.attrib;
+>
+<!-- end of code.attlist -->]]>
+
+<!ENTITY % dfn.element  "INCLUDE" >
+<![%dfn.element;[
+<!ENTITY % dfn.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % dfn.qname  "dfn" >
+<!ELEMENT %dfn.qname;  %dfn.content; >
+<!-- end of dfn.element -->]]>
+
+<!ENTITY % dfn.attlist  "INCLUDE" >
+<![%dfn.attlist;[
+<!ATTLIST %dfn.qname;
+      %Common.attrib;
+>
+<!-- end of dfn.attlist -->]]>
+
+<!ENTITY % em.element  "INCLUDE" >
+<![%em.element;[
+<!ENTITY % em.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % em.qname  "em" >
+<!ELEMENT %em.qname;  %em.content; >
+<!-- end of em.element -->]]>
+
+<!ENTITY % em.attlist  "INCLUDE" >
+<![%em.attlist;[
+<!ATTLIST %em.qname;
+      %Common.attrib;
+>
+<!-- end of em.attlist -->]]>
+
+<!ENTITY % kbd.element  "INCLUDE" >
+<![%kbd.element;[
+<!ENTITY % kbd.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % kbd.qname  "kbd" >
+<!ELEMENT %kbd.qname;  %kbd.content; >
+<!-- end of kbd.element -->]]>
+
+<!ENTITY % kbd.attlist  "INCLUDE" >
+<![%kbd.attlist;[
+<!ATTLIST %kbd.qname;
+      %Common.attrib;
+>
+<!-- end of kbd.attlist -->]]>
+
+<!ENTITY % q.element  "INCLUDE" >
+<![%q.element;[
+<!ENTITY % q.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % q.qname  "q" >
+<!ELEMENT %q.qname;  %q.content; >
+<!-- end of q.element -->]]>
+
+<!ENTITY % q.attlist  "INCLUDE" >
+<![%q.attlist;[
+<!ATTLIST %q.qname;
+      %Common.attrib;
+      cite         %URI.datatype;           #IMPLIED
+>
+<!-- end of q.attlist -->]]>
+
+<!ENTITY % samp.element  "INCLUDE" >
+<![%samp.element;[
+<!ENTITY % samp.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % samp.qname  "samp" >
+<!ELEMENT %samp.qname;  %samp.content; >
+<!-- end of samp.element -->]]>
+
+<!ENTITY % samp.attlist  "INCLUDE" >
+<![%samp.attlist;[
+<!ATTLIST %samp.qname;
+      %Common.attrib;
+>
+<!-- end of samp.attlist -->]]>
+
+<!ENTITY % strong.element  "INCLUDE" >
+<![%strong.element;[
+<!ENTITY % strong.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % strong.qname  "strong" >
+<!ELEMENT %strong.qname;  %strong.content; >
+<!-- end of strong.element -->]]>
+
+<!ENTITY % strong.attlist  "INCLUDE" >
+<![%strong.attlist;[
+<!ATTLIST %strong.qname;
+      %Common.attrib;
+>
+<!-- end of strong.attlist -->]]>
+
+<!ENTITY % var.element  "INCLUDE" >
+<![%var.element;[
+<!ENTITY % var.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % var.qname  "var" >
+<!ELEMENT %var.qname;  %var.content; >
+<!-- end of var.element -->]]>
+
+<!ENTITY % var.attlist  "INCLUDE" >
+<![%var.attlist;[
+<!ATTLIST %var.qname;
+      %Common.attrib;
+>
+<!-- end of var.attlist -->]]>
+
+<!-- end of xhtml-inlphras-1.mod -->
+]]>
+
+<!ENTITY % xhtml-blkstruct.module "INCLUDE" >
+<![%xhtml-blkstruct.module;[
+<!ENTITY % xhtml-blkstruct.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Block Structural 1.0//EN"
+            "../xhtml11/xhtml-blkstruct-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Block Structural Module  ....................................... -->
+<!-- file: xhtml-blkstruct-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-blkstruct-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Block Structural 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-blkstruct-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Block Structural
+
+        div, p
+
+     This module declares the elements and their attributes used to
+     support block-level structural markup.
+-->
+
+<!ENTITY % div.element  "INCLUDE" >
+<![%div.element;[
+<!ENTITY % div.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ENTITY % div.qname  "div" >
+<!ELEMENT %div.qname;  %div.content; >
+<!-- end of div.element -->]]>
+
+<!ENTITY % div.attlist  "INCLUDE" >
+<![%div.attlist;[
+<!ATTLIST %div.qname;
+      %Common.attrib;
+>
+<!-- end of div.attlist -->]]>
+
+<!ENTITY % p.element  "INCLUDE" >
+<![%p.element;[
+<!ENTITY % p.content
+     "( #PCDATA | %Inline.mix; )*" >
+<!ENTITY % p.qname  "p" >
+<!ELEMENT %p.qname;  %p.content; >
+<!-- end of p.element -->]]>
+
+<!ENTITY % p.attlist  "INCLUDE" >
+<![%p.attlist;[
+<!ATTLIST %p.qname;
+      %Common.attrib;
+>
+<!-- end of p.attlist -->]]>
+
+<!-- end of xhtml-blkstruct-1.mod -->
+]]>
+
+<!ENTITY % xhtml-blkphras.module "INCLUDE" >
+<![%xhtml-blkphras.module;[
+<!ENTITY % xhtml-blkphras.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Block Phrasal 1.0//EN"
+            "../xhtml11/xhtml-blkphras-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Block Phrasal Module  .......................................... -->
+<!-- file: xhtml-blkphras-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-blkphras-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Block Phrasal 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-blkphras-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Block Phrasal
+
+        address, blockquote, pre, h1, h2, h3, h4, h5, h6
+
+     This module declares the elements and their attributes used to
+     support block-level phrasal markup.
+-->
+
+<!ENTITY % address.element  "INCLUDE" >
+<![%address.element;[
+<!ENTITY % address.content
+     "( #PCDATA | %Inline.mix; )*" >
+<!ENTITY % address.qname  "address" >
+<!ELEMENT %address.qname;  %address.content; >
+<!-- end of address.element -->]]>
+
+<!ENTITY % address.attlist  "INCLUDE" >
+<![%address.attlist;[
+<!ATTLIST %address.qname;
+      %Common.attrib;
+>
+<!-- end of address.attlist -->]]>
+
+<!ENTITY % blockquote.element  "INCLUDE" >
+<![%blockquote.element;[
+<!ENTITY % blockquote.content
+     "( %Block.mix; )+"
+>
+<!ENTITY % blockquote.qname  "blockquote" >
+<!ELEMENT %blockquote.qname;  %blockquote.content; >
+<!-- end of blockquote.element -->]]>
+
+<!ENTITY % blockquote.attlist  "INCLUDE" >
+<![%blockquote.attlist;[
+<!ATTLIST %blockquote.qname;
+      %Common.attrib;
+      cite         %URI.datatype;           #IMPLIED
+>
+<!-- end of blockquote.attlist -->]]>
+
+<!ENTITY % pre.element  "INCLUDE" >
+<![%pre.element;[
+<!ENTITY % pre.content
+     "( #PCDATA
+      | %InlStruct.class;
+      %InlPhras.class;
+      | %tt.qname; | %i.qname; | %b.qname;
+      %I18n.class;
+      %Anchor.class;
+      | %script.qname; | %map.qname;
+      %Inline.extra; )*"
+>
+<!ENTITY % pre.qname  "pre" >
+<!ELEMENT %pre.qname;  %pre.content; >
+<!-- end of pre.element -->]]>
+
+<!ENTITY % pre.attlist  "INCLUDE" >
+<![%pre.attlist;[
+<!ATTLIST %pre.qname;
+      %Common.attrib;
+      xml:space    ( preserve )             #FIXED 'preserve'
+>
+<!-- end of pre.attlist -->]]>
+
+<!-- ...................  Heading Elements  ................... -->
+
+<!ENTITY % Heading.content  "( #PCDATA | %Inline.mix; )*" >
+
+<!ENTITY % h1.element  "INCLUDE" >
+<![%h1.element;[
+<!ENTITY % h1.qname  "h1" >
+<!ELEMENT %h1.qname;  %Heading.content; >
+<!-- end of h1.element -->]]>
+
+<!ENTITY % h1.attlist  "INCLUDE" >
+<![%h1.attlist;[
+<!ATTLIST %h1.qname;
+      %Common.attrib;
+>
+<!-- end of h1.attlist -->]]>
+
+<!ENTITY % h2.element  "INCLUDE" >
+<![%h2.element;[
+<!ENTITY % h2.qname  "h2" >
+<!ELEMENT %h2.qname;  %Heading.content; >
+<!-- end of h2.element -->]]>
+
+<!ENTITY % h2.attlist  "INCLUDE" >
+<![%h2.attlist;[
+<!ATTLIST %h2.qname;
+      %Common.attrib;
+>
+<!-- end of h2.attlist -->]]>
+
+<!ENTITY % h3.element  "INCLUDE" >
+<![%h3.element;[
+<!ENTITY % h3.qname  "h3" >
+<!ELEMENT %h3.qname;  %Heading.content; >
+<!-- end of h3.element -->]]>
+
+<!ENTITY % h3.attlist  "INCLUDE" >
+<![%h3.attlist;[
+<!ATTLIST %h3.qname;
+      %Common.attrib;
+>
+<!-- end of h3.attlist -->]]>
+
+<!ENTITY % h4.element  "INCLUDE" >
+<![%h4.element;[
+<!ENTITY % h4.qname  "h4" >
+<!ELEMENT %h4.qname;  %Heading.content; >
+<!-- end of h4.element -->]]>
+
+<!ENTITY % h4.attlist  "INCLUDE" >
+<![%h4.attlist;[
+<!ATTLIST %h4.qname;
+      %Common.attrib;
+>
+<!-- end of h4.attlist -->]]>
+
+<!ENTITY % h5.element  "INCLUDE" >
+<![%h5.element;[
+<!ENTITY % h5.qname  "h5" >
+<!ELEMENT %h5.qname;  %Heading.content; >
+<!-- end of h5.element -->]]>
+
+<!ENTITY % h5.attlist  "INCLUDE" >
+<![%h5.attlist;[
+<!ATTLIST %h5.qname;
+      %Common.attrib;
+>
+<!-- end of h5.attlist -->]]>
+
+<!ENTITY % h6.element  "INCLUDE" >
+<![%h6.element;[
+<!ENTITY % h6.qname  "h6" >
+<!ELEMENT %h6.qname;  %Heading.content; >
+<!-- end of h6.element -->]]>
+
+<!ENTITY % h6.attlist  "INCLUDE" >
+<![%h6.attlist;[
+<!ATTLIST %h6.qname;
+      %Common.attrib;
+>
+<!-- end of h6.attlist -->]]>
+
+<!-- end of xhtml-blkphras-1.mod -->
+]]>
+
+<!-- end of xhtml-text-1.mod -->
+
+
+<!ENTITY % xhtml-hypertext.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN"
+            "../xhtml11/xhtml-hypertext-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Hypertext Module  .............................................. -->
+<!-- file: xhtml-hypertext-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-hypertext-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-hypertext-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Hypertext
+
+        a
+
+     This module declares the anchor ('a') element type, which
+     defines the source of a hypertext link. The destination
+     (or link 'target') is identified via its 'id' attribute
+     rather than the 'name' attribute as was used in HTML.
+-->
+
+<!-- ............  Anchor Element  ............ -->
+
+<!ENTITY % a.element  "INCLUDE" >
+<![%a.element;[
+<!ENTITY % a.content
+     "( #PCDATA | %InlNoAnchor.mix; )*"
+>
+<!ENTITY % a.qname  "a" >
+<!ELEMENT %a.qname;  %a.content; >
+<!-- end of a.element -->]]>
+
+<!ENTITY % a.attlist  "INCLUDE" >
+<![%a.attlist;[
+<!ATTLIST %a.qname;
+      %Common.attrib;
+      href         %URI.datatype;           #IMPLIED
+      charset      %Charset.datatype;       #IMPLIED
+      type         %ContentType.datatype;   #IMPLIED
+      hreflang     %LanguageCode.datatype;  #IMPLIED
+      rel          %LinkTypes.datatype;     #IMPLIED
+      rev          %LinkTypes.datatype;     #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+>
+<!-- end of a.attlist -->]]>
+
+<!-- end of xhtml-hypertext-1.mod -->
+
+
+<!ENTITY % xhtml-list.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Lists 1.0//EN"
+            "../xhtml11/xhtml-list-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Lists Module  .................................................. -->
+<!-- file: xhtml-list-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-list-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Lists 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-list-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Lists
+
+        dl, dt, dd, ol, ul, li
+
+     This module declares the list-oriented element types
+     and their attributes.
+-->
+
+<!ENTITY % dl.qname  "dl" >
+<!ENTITY % dt.qname  "dt" >
+<!ENTITY % dd.qname  "dd" >
+<!ENTITY % ol.qname  "ol" >
+<!ENTITY % ul.qname  "ul" >
+<!ENTITY % li.qname  "li" >
+
+<!-- dl: Definition List ............................... -->
+
+<!ENTITY % dl.element  "INCLUDE" >
+<![%dl.element;[
+<!ENTITY % dl.content  "( %dt.qname; | %dd.qname; )+" >
+<!ELEMENT %dl.qname;  %dl.content; >
+<!-- end of dl.element -->]]>
+
+<!ENTITY % dl.attlist  "INCLUDE" >
+<![%dl.attlist;[
+<!ATTLIST %dl.qname;
+      %Common.attrib;
+>
+<!-- end of dl.attlist -->]]>
+
+<!-- dt: Definition Term ............................... -->
+
+<!ENTITY % dt.element  "INCLUDE" >
+<![%dt.element;[
+<!ENTITY % dt.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ELEMENT %dt.qname;  %dt.content; >
+<!-- end of dt.element -->]]>
+
+<!ENTITY % dt.attlist  "INCLUDE" >
+<![%dt.attlist;[
+<!ATTLIST %dt.qname;
+      %Common.attrib;
+>
+<!-- end of dt.attlist -->]]>
+
+<!-- dd: Definition Description ........................ -->
+
+<!ENTITY % dd.element  "INCLUDE" >
+<![%dd.element;[
+<!ENTITY % dd.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ELEMENT %dd.qname;  %dd.content; >
+<!-- end of dd.element -->]]>
+
+<!ENTITY % dd.attlist  "INCLUDE" >
+<![%dd.attlist;[
+<!ATTLIST %dd.qname;
+      %Common.attrib;
+>
+<!-- end of dd.attlist -->]]>
+
+<!-- ol: Ordered List (numbered styles) ................ -->
+
+<!ENTITY % ol.element  "INCLUDE" >
+<![%ol.element;[
+<!ENTITY % ol.content  "( %li.qname; )+" >
+<!ELEMENT %ol.qname;  %ol.content; >
+<!-- end of ol.element -->]]>
+
+<!ENTITY % ol.attlist  "INCLUDE" >
+<![%ol.attlist;[
+<!ATTLIST %ol.qname;
+      %Common.attrib;
+>
+<!-- end of ol.attlist -->]]>
+
+<!-- ul: Unordered List (bullet styles) ................ -->
+
+<!ENTITY % ul.element  "INCLUDE" >
+<![%ul.element;[
+<!ENTITY % ul.content  "( %li.qname; )+" >
+<!ELEMENT %ul.qname;  %ul.content; >
+<!-- end of ul.element -->]]>
+
+<!ENTITY % ul.attlist  "INCLUDE" >
+<![%ul.attlist;[
+<!ATTLIST %ul.qname;
+      %Common.attrib;
+>
+<!-- end of ul.attlist -->]]>
+
+<!-- li: List Item ..................................... -->
+
+<!ENTITY % li.element  "INCLUDE" >
+<![%li.element;[
+<!ENTITY % li.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ELEMENT %li.qname;  %li.content; >
+<!-- end of li.element -->]]>
+
+<!ENTITY % li.attlist  "INCLUDE" >
+<![%li.attlist;[
+<!ATTLIST %li.qname;
+      %Common.attrib;
+>
+<!-- end of li.attlist -->]]>
+
+<!-- end of xhtml-list-1.mod -->
+
+<!-- Extend lists with value and start attributes -->
+<!ATTLIST %li.qname;
+      value        %Number.datatype;         #IMPLIED
+>
+<!ATTLIST %ol.qname;
+      start        %Number.datatype;        #IMPLIED
+>
+
+<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+
+<!-- Image Module  ............................................... -->
+<!ENTITY % xhtml-image.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Images 1.0//EN"
+            "../xhtml11/xhtml-image-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Images Module  ................................................. -->
+<!-- file: xhtml-image-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Rovision: $Id: xhtml-image-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Images 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-image-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Images
+
+        img
+
+     This module provides markup to support basic image embedding.
+-->
+
+<!-- To avoid problems with text-only UAs as well as to make
+     image content understandable and navigable to users of
+     non-visual UAs, you need to provide a description with
+     the 'alt' attribute, and avoid server-side image maps.
+-->
+
+<!ENTITY % img.element  "INCLUDE" >
+<![%img.element;[
+<!ENTITY % img.content  "EMPTY" >
+<!ENTITY % img.qname  "img" >
+<!ELEMENT %img.qname;  %img.content; >
+<!-- end of img.element -->]]>
+
+<!ENTITY % img.attlist  "INCLUDE" >
+<![%img.attlist;[
+<!ATTLIST %img.qname;
+      %Common.attrib;
+      src          %URI.datatype;           #REQUIRED
+      alt          %Text.datatype;          #REQUIRED
+      longdesc     %URI.datatype;           #IMPLIED
+      height       %Length.datatype;        #IMPLIED
+      width        %Length.datatype;        #IMPLIED
+>
+<!-- end of img.attlist -->]]>
+
+<!-- end of xhtml-image-1.mod -->
+
+
+<!-- Tables Module ............................................... -->
+<!ENTITY % xhtml-table.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Basic Tables 1.0//EN"
+            "../xhtml11/xhtml-basic-table-1.mod" >
+<!-- ....................................................................... -->
+<!-- XHTML Basic Table Module  ............................................. -->
+<!-- file: xhtml-basic-table-1.mod
+
+     This is XHTML Basic, a proper subset of XHTML.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-basic-table-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Basic Tables 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-basic-table-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Basic Tables
+
+        table, caption, tr, th, td
+
+     This table module declares elements and attributes defining
+     a table model based fundamentally on features found in the
+     widely-deployed HTML 3.2 table model.  While this module
+     mimics the content model and table attributes of HTML 3.2
+     tables, the element types declared herein also includes all
+     HTML 4 common and most of the HTML 4 table attributes.
+-->
+
+<!-- declare qualified element type names:
+-->
+<!ENTITY % table.qname  "table" >
+<!ENTITY % caption.qname  "caption" >
+<!ENTITY % tr.qname  "tr" >
+<!ENTITY % th.qname  "th" >
+<!ENTITY % td.qname  "td" >
+
+<!-- horizontal alignment attributes for cell contents
+-->
+<!ENTITY % CellHAlign.attrib
+     "align        ( left
+                   | center
+                   | right )                #IMPLIED"
+>
+
+<!-- vertical alignment attributes for cell contents
+-->
+<!ENTITY % CellVAlign.attrib
+     "valign       ( top
+                   | middle
+                   | bottom )               #IMPLIED"
+>
+
+<!-- scope is simpler than axes attribute for common tables
+-->
+<!ENTITY % scope.attrib
+     "scope        ( row | col  )           #IMPLIED"
+>
+
+<!-- table: Table Element .............................. -->
+
+<!ENTITY % table.element  "INCLUDE" >
+<![%table.element;[
+<!ENTITY % table.content
+     "( %caption.qname;?, %tr.qname;+ )"
+>
+<!ELEMENT %table.qname;  %table.content; >
+<!-- end of table.element -->]]>
+
+<!ENTITY % table.attlist  "INCLUDE" >
+<![%table.attlist;[
+<!ATTLIST %table.qname;
+      %Common.attrib;
+      summary      %Text.datatype;          #IMPLIED
+>
+<!-- end of table.attlist -->]]>
+
+<!-- caption: Table Caption ............................ -->
+
+<!ENTITY % caption.element  "INCLUDE" >
+<![%caption.element;[
+<!ENTITY % caption.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ELEMENT %caption.qname;  %caption.content; >
+<!-- end of caption.element -->]]>
+
+<!ENTITY % caption.attlist  "INCLUDE" >
+<![%caption.attlist;[
+<!ATTLIST %caption.qname;
+      %Common.attrib;
+>
+<!-- end of caption.attlist -->]]>
+
+<!-- tr: Table Row ..................................... -->
+
+<!ENTITY % tr.element  "INCLUDE" >
+<![%tr.element;[
+<!ENTITY % tr.content  "( %th.qname; | %td.qname; )+" >
+<!ELEMENT %tr.qname;  %tr.content; >
+<!-- end of tr.element -->]]>
+
+<!ENTITY % tr.attlist  "INCLUDE" >
+<![%tr.attlist;[
+<!ATTLIST %tr.qname;
+      %Common.attrib;
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of tr.attlist -->]]>
+
+<!-- th: Table Header Cell ............................. -->
+
+<!-- th is for header cells, td for data,
+     but for cells acting as both use td
+-->
+
+<!ENTITY % th.element  "INCLUDE" >
+<![%th.element;[
+<!ENTITY % th.content
+     "( #PCDATA | %FlowNoTable.mix; )*"
+>
+<!ELEMENT %th.qname;  %th.content; >
+<!-- end of th.element -->]]>
+
+<!ENTITY % th.attlist  "INCLUDE" >
+<![%th.attlist;[
+<!ATTLIST %th.qname;
+      %Common.attrib;
+      abbr         %Text.datatype;          #IMPLIED
+      axis         CDATA                    #IMPLIED
+      headers      IDREFS                   #IMPLIED
+      %scope.attrib;
+      rowspan      %Number.datatype;        '1'
+      colspan      %Number.datatype;        '1'
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of th.attlist -->]]>
+
+<!-- td: Table Data Cell ............................... -->
+
+<!ENTITY % td.element  "INCLUDE" >
+<![%td.element;[
+<!ENTITY % td.content
+     "( #PCDATA | %FlowNoTable.mix; )*"
+>
+<!ELEMENT %td.qname;  %td.content; >
+<!-- end of td.element -->]]>
+
+<!ENTITY % td.attlist  "INCLUDE" >
+<![%td.attlist;[
+<!ATTLIST %td.qname;
+      %Common.attrib;
+      abbr         %Text.datatype;          #IMPLIED
+      axis         CDATA                    #IMPLIED
+      headers      IDREFS                   #IMPLIED
+      %scope.attrib;
+      rowspan      %Number.datatype;        '1'
+      colspan      %Number.datatype;        '1'
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of td.attlist -->]]>
+
+<!-- end of xhtml-basic-table-1.mod -->
+
+
+<!-- Forms Module  ...............................................
+	XHTML basic forms module extended with optgroup and fieldset
+-->
+<!ELEMENT %optgroup.qname; (%option.qname;)+>
+<!ATTLIST %optgroup.qname;
+	%Common.attrib;
+	label %Text.datatype; #REQUIRED
+>
+<!ENTITY % select.content "( %optgroup.qname; | %option.qname; )+">
+<!ELEMENT %fieldset.qname; (#PCDATA | %Flow.mix;)*>
+<!ATTLIST %fieldset.qname;
+	%Common.attrib;
+>
+<!ENTITY % form.content "( %BlkNoForm.mix; | %fieldset.qname; )+">
+<!ENTITY % xhtml-form.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Basic Forms 1.0//EN"
+            "../xhtml11/xhtml-basic-form-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Simplified Forms Module  ....................................... -->
+<!-- file: xhtml-basic-form-1.mod
+
+     This is XHTML Basic, a proper subset of XHTML.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-basic-form-1.mod,v 4.1 2001/04/05 06:57:40 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Basic Forms 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-basic-form-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Basic Forms
+
+     This forms module is based on the HTML 3.2 forms model, with
+     the WAI-requested addition of the label element. While this
+     module essentially mimics the content model and attributes of
+     HTML 3.2 forms, the element types declared herein also include
+     all HTML 4 common attributes.
+
+        form, label, input, select, option, textarea
+-->
+
+<!-- declare qualified element type names:
+-->
+<!ENTITY % form.qname  "form" >
+<!ENTITY % label.qname  "label" >
+<!ENTITY % input.qname  "input" >
+<!ENTITY % select.qname  "select" >
+<!ENTITY % option.qname  "option" >
+<!ENTITY % textarea.qname  "textarea" >
+
+<!-- %BlkNoForm.mix; includes all non-form block elements,
+     plus %Misc.class;
+-->
+<!ENTITY % BlkNoForm.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      | %table.qname;
+      %Block.extra;
+      %Misc.class;"
+>
+
+<!-- form: Form Element ................................ -->
+
+<!ENTITY % form.element  "INCLUDE" >
+<![%form.element;[
+<!ENTITY % form.content
+     "( %BlkNoForm.mix; )+"
+>
+<!ELEMENT %form.qname;  %form.content; >
+<!-- end of form.element -->]]>
+
+<!ENTITY % form.attlist  "INCLUDE" >
+<![%form.attlist;[
+<!ATTLIST %form.qname;
+      %Common.attrib;
+      action       %URI.datatype;           #REQUIRED
+      method       ( get | post )           'get'
+      enctype      %ContentType.datatype;   'application/x-www-form-urlencoded'
+>
+<!-- end of form.attlist -->]]>
+
+<!-- label: Form Field Label Text ...................... -->
+
+<!ENTITY % label.element  "INCLUDE" >
+<![%label.element;[
+<!-- Each label must not contain more than ONE field
+-->
+<!ENTITY % label.content
+     "( #PCDATA
+      | %input.qname; | %select.qname; | %textarea.qname;
+      | %InlStruct.class;
+      %InlPhras.class;
+      %I18n.class;
+      %InlPres.class;
+      %InlSpecial.class;
+      %Misc.class; )*"
+>
+<!ELEMENT %label.qname;  %label.content; >
+<!-- end of label.element -->]]>
+
+<!ENTITY % label.attlist  "INCLUDE" >
+<![%label.attlist;[
+<!ATTLIST %label.qname;
+      %Common.attrib;
+      for          IDREF                    #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of label.attlist -->]]>
+
+<!-- input: Form Control ............................... -->
+
+<!ENTITY % input.element  "INCLUDE" >
+<![%input.element;[
+<!ENTITY % input.content  "EMPTY" >
+<!ELEMENT %input.qname;  %input.content; >
+<!-- end of input.element -->]]>
+
+<!-- Basic Forms removes 'image' and 'file' input types.
+-->
+<!ENTITY % input.attlist  "INCLUDE" >
+<![%input.attlist;[
+<!ENTITY % InputType.class
+     "( text | password | checkbox | radio
+      | submit | reset | hidden )"
+>
+<!-- attribute name required for all but submit & reset
+-->
+<!ATTLIST %input.qname;
+      %Common.attrib;
+      type         %InputType.class;        'text'
+      name         CDATA                    #IMPLIED
+      value        CDATA                    #IMPLIED
+      checked      ( checked )              #IMPLIED
+      size         CDATA                    #IMPLIED
+      maxlength    %Number.datatype;        #IMPLIED
+      src          %URI.datatype;           #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of input.attlist -->]]>
+
+<!-- select: Option Selector ........................... -->
+
+<!ENTITY % select.element  "INCLUDE" >
+<![%select.element;[
+<!ENTITY % select.content  "( %option.qname; )+" >
+<!ELEMENT %select.qname;  %select.content; >
+<!-- end of select.element -->]]>
+
+<!ENTITY % select.attlist  "INCLUDE" >
+<![%select.attlist;[
+<!ATTLIST %select.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      size         %Number.datatype;        #IMPLIED
+      multiple     ( multiple )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+>
+<!-- end of select.attlist -->]]>
+
+<!-- option: Selectable Choice ......................... -->
+
+<!ENTITY % option.element  "INCLUDE" >
+<![%option.element;[
+<!ENTITY % option.content  "( #PCDATA )" >
+<!ELEMENT %option.qname;  %option.content; >
+<!-- end of option.element -->]]>
+
+<!ENTITY % option.attlist  "INCLUDE" >
+<![%option.attlist;[
+<!ATTLIST %option.qname;
+      %Common.attrib;
+      selected     ( selected )             #IMPLIED
+      value        CDATA                    #IMPLIED
+>
+<!-- end of option.attlist -->]]>
+
+<!-- textarea: Multi-Line Text Field ................... -->
+
+<!ENTITY % textarea.element  "INCLUDE" >
+<![%textarea.element;[
+<!ENTITY % textarea.content  "( #PCDATA )" >
+<!ELEMENT %textarea.qname;  %textarea.content; >
+<!-- end of textarea.element -->]]>
+
+<!ENTITY % textarea.attlist  "INCLUDE" >
+<![%textarea.attlist;[
+<!ATTLIST %textarea.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      rows         %Number.datatype;        #REQUIRED
+      cols         %Number.datatype;        #REQUIRED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of textarea.attlist -->]]>
+
+<!-- end of xhtml-basic-form-1.mod -->
+
+
+<!-- Link Element Module  ........................................ -->
+<!ENTITY % xhtml-link.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Link Element 1.0//EN"
+            "../xhtml11/xhtml-link-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Link Element Module  ........................................... -->
+<!-- file: xhtml-link-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-link-1.mod,v 4.1 2001/04/05 06:57:40 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Link Element 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-link-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Link element
+
+        link
+
+     This module declares the link element type and its attributes,
+     which could (in principle) be used to define document-level links
+     to external resources such as:
+
+     a) for document specific toolbars/menus, e.g. start, contents,
+        previous, next, index, end, help
+     b) to link to a separate style sheet (rel="stylesheet")
+     c) to make a link to a script (rel="script")
+     d) by style sheets to control how collections of html nodes are
+        rendered into printed documents
+     e) to make a link to a printable version of this document
+        e.g. a postscript or pdf version (rel="alternate" media="print")
+-->
+
+<!-- link: Media-Independent Link ...................... -->
+
+<!ENTITY % link.element  "INCLUDE" >
+<![%link.element;[
+<!ENTITY % link.content  "EMPTY" >
+<!ENTITY % link.qname  "link" >
+<!ELEMENT %link.qname;  %link.content; >
+<!-- end of link.element -->]]>
+
+<!ENTITY % link.attlist  "INCLUDE" >
+<![%link.attlist;[
+<!ATTLIST %link.qname;
+      %Common.attrib;
+      charset      %Charset.datatype;       #IMPLIED
+      href         %URI.datatype;           #IMPLIED
+      hreflang     %LanguageCode.datatype;  #IMPLIED
+      type         %ContentType.datatype;   #IMPLIED
+      rel          %LinkTypes.datatype;     #IMPLIED
+      rev          %LinkTypes.datatype;     #IMPLIED
+      media        %MediaDesc.datatype;     #IMPLIED
+>
+<!-- end of link.attlist -->]]>
+
+<!-- end of xhtml-link-1.mod -->
+
+
+<!-- Document Metainformation Module  ............................ -->
+<!ENTITY % xhtml-meta.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN"
+            "../xhtml11/xhtml-meta-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Document Metainformation Module  ............................... -->
+<!-- file: xhtml-meta-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-meta-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-meta-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Meta Information
+
+        meta
+
+     This module declares the meta element type and its attributes,
+     used to provide declarative document metainformation.
+-->
+
+<!-- meta: Generic Metainformation ..................... -->
+
+<!ENTITY % meta.element  "INCLUDE" >
+<![%meta.element;[
+<!ENTITY % meta.content  "EMPTY" >
+<!ENTITY % meta.qname  "meta" >
+<!ELEMENT %meta.qname;  %meta.content; >
+<!-- end of meta.element -->]]>
+
+<!ENTITY % meta.attlist  "INCLUDE" >
+<![%meta.attlist;[
+<!ATTLIST %meta.qname;
+      %XHTML.xmlns.attrib;
+      %I18n.attrib;
+      http-equiv   NMTOKEN                  #IMPLIED
+      name         NMTOKEN                  #IMPLIED
+      content      CDATA                    #REQUIRED
+      scheme       CDATA                    #IMPLIED
+>
+<!-- end of meta.attlist -->]]>
+
+<!-- end of xhtml-meta-1.mod -->
+
+
+<!-- Base Element Module  ........................................ -->
+<!ENTITY % xhtml-base.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Base Element 1.0//EN"
+            "../xhtml11/xhtml-base-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Base Element Module  ........................................... -->
+<!-- file: xhtml-base-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-base-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Base Element 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-base-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Base element
+
+        base
+
+     This module declares the base element type and its attributes,
+     used to define a base URI against which relative URIs in the
+     document will be resolved.
+
+     Note that this module also redeclares the content model for
+     the head element to include the base element.
+-->
+
+<!-- base: Document Base URI ........................... -->
+
+<!ENTITY % base.element  "INCLUDE" >
+<![%base.element;[
+<!ENTITY % base.content  "EMPTY" >
+<!ENTITY % base.qname  "base" >
+<!ELEMENT %base.qname;  %base.content; >
+<!-- end of base.element -->]]>
+
+<!ENTITY % base.attlist  "INCLUDE" >
+<![%base.attlist;[
+<!ATTLIST %base.qname;
+      %XHTML.xmlns.attrib;
+      href         %URI.datatype;           #REQUIRED
+>
+<!-- end of base.attlist -->]]>
+
+<!ENTITY % head.content
+    "( %HeadOpts.mix;,
+     ( ( %title.qname;, %HeadOpts.mix;, ( %base.qname;, %HeadOpts.mix; )? )
+     | ( %base.qname;, %HeadOpts.mix;, ( %title.qname;, %HeadOpts.mix; ))))"
+>
+
+<!-- end of xhtml-base-1.mod -->
+
+
+<!-- Stylesheets Module  ......................................... -->
+<!ENTITY % xhtml-style.mod PUBLIC "-//W3C//ELEMENTS XHTML Style Sheets 1.0//EN"
+            "../xhtml11/xhtml-style-1.mod">
+<!-- ...................................................................... -->
+<!-- XHTML Document Style Sheet Module  ................................... -->
+<!-- file: xhtml-style-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-style-1.mod,v 4.1 2001/04/05 06:57:40 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//DTD XHTML Style Sheets 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-style-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Style Sheets
+
+        style
+
+     This module declares the style element type and its attributes,
+     used to embed style sheet information in the document head element.
+-->
+
+<!-- style: Style Sheet Information .................... -->
+
+<!ENTITY % style.element  "INCLUDE" >
+<![%style.element;[
+<!ENTITY % style.content  "( #PCDATA )" >
+<!ENTITY % style.qname  "style" >
+<!ELEMENT %style.qname;  %style.content; >
+<!-- end of style.element -->]]>
+
+<!ENTITY % style.attlist  "INCLUDE" >
+<![%style.attlist;[
+<!ATTLIST %style.qname;
+      %XHTML.xmlns.attrib;
+      %title.attrib;
+      %I18n.attrib;
+      type         %ContentType.datatype;   #REQUIRED
+      media        %MediaDesc.datatype;     #IMPLIED
+      xml:space    ( preserve )             #FIXED 'preserve'
+>
+<!-- end of style.attlist -->]]>
+
+<!-- end of xhtml-style-1.mod -->
+
+
+<!-- Param Element Module  ....................................... -->
+<!ENTITY % xhtml-param.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Param Element 1.0//EN"
+            "../xhtml11/xhtml-param-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Param Element Module  ..................................... -->
+<!-- file: xhtml-param-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-param-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Param Element 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-param-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Parameters for Java Applets and Embedded Objects
+
+        param
+
+     This module provides declarations for the param element,
+     used to provide named property values for the applet
+     and object elements.
+-->
+
+<!-- param: Named Property Value ....................... -->
+
+<!ENTITY % param.element  "INCLUDE" >
+<![%param.element;[
+<!ENTITY % param.content  "EMPTY" >
+<!ENTITY % param.qname  "param" >
+<!ELEMENT %param.qname;  %param.content; >
+<!-- end of param.element -->]]>
+
+<!ENTITY % param.attlist  "INCLUDE" >
+<![%param.attlist;[
+<!ATTLIST %param.qname;
+      %XHTML.xmlns.attrib;
+      %id.attrib;
+      name         CDATA                    #REQUIRED
+      value        CDATA                    #IMPLIED
+      valuetype    ( data | ref | object )  'data'
+      type         %ContentType.datatype;   #IMPLIED
+>
+<!-- end of param.attlist -->]]>
+
+<!-- end of xhtml-param-1.mod -->
+
+
+<!-- Embedded Object Module  ..................................... -->
+<!ENTITY % xhtml-object.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Embedded Object 1.0//EN"
+            "../xhtml11/xhtml-object-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Embedded Object Module  ........................................ -->
+<!-- file: xhtml-object-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-object-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Embedded Object 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-object-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Embedded Objects
+
+        object
+
+     This module declares the object element type and its attributes, used
+     to embed external objects as part of XHTML pages. In the document,
+     place param elements prior to other content within the object element.
+
+     Note that use of this module requires instantiation of the Param
+     Element Module.
+-->
+
+<!-- object: Generic Embedded Object ................... -->
+
+<!ENTITY % object.element  "INCLUDE" >
+<![%object.element;[
+<!ENTITY % object.content
+     "( #PCDATA | %Flow.mix; | %param.qname; )*"
+>
+<!ENTITY % object.qname  "object" >
+<!ELEMENT %object.qname;  %object.content; >
+<!-- end of object.element -->]]>
+
+<!ENTITY % object.attlist  "INCLUDE" >
+<![%object.attlist;[
+<!ATTLIST %object.qname;
+      %Common.attrib;
+      declare      ( declare )              #IMPLIED
+      classid      %URI.datatype;           #IMPLIED
+      codebase     %URI.datatype;           #IMPLIED
+      data         %URI.datatype;           #IMPLIED
+      type         %ContentType.datatype;   #IMPLIED
+      codetype     %ContentType.datatype;   #IMPLIED
+      archive      %URIs.datatype;          #IMPLIED
+      standby      %Text.datatype;          #IMPLIED
+      height       %Length.datatype;        #IMPLIED
+      width        %Length.datatype;        #IMPLIED
+      name         CDATA                    #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+>
+<!-- end of object.attlist -->]]>
+
+<!-- end of xhtml-object-1.mod -->
+
+
+<!-- Document Structure Module  ..................................... -->
+<!ENTITY % xhtml-struct.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN"
+            "../xhtml11/xhtml-struct-1.mod" >
+<!-- ...................................................................... -->
+<!-- XHTML Structure Module  .............................................. -->
+<!-- file: xhtml-struct-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-struct-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-struct-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Document Structure
+
+        title, head, body, html
+
+     The Structure Module defines the major structural elements and
+     their attributes.
+
+     Note that the content model of the head element type is redeclared
+     when the Base Module is included in the DTD.
+
+     The parameter entity containing the XML namespace URI value used
+     for XHTML is '%XHTML.xmlns;', defined in the Qualified Names module.
+-->
+
+<!-- title: Document Title ............................. -->
+
+<!-- The title element is not considered part of the flow of text.
+     It should be displayed, for example as the page header or
+     window title. Exactly one title is required per document.
+-->
+
+<!ENTITY % title.element  "INCLUDE" >
+<![%title.element;[
+<!ENTITY % title.content  "( #PCDATA )" >
+<!ENTITY % title.qname  "title" >
+<!ELEMENT %title.qname;  %title.content; >
+<!-- end of title.element -->]]>
+
+<!ENTITY % title.attlist  "INCLUDE" >
+<![%title.attlist;[
+<!ATTLIST %title.qname;
+      %XHTML.xmlns.attrib;
+      %I18n.attrib;
+>
+<!-- end of title.attlist -->]]>
+
+<!-- head: Document Head ............................... -->
+
+<!ENTITY % head.element  "INCLUDE" >
+<![%head.element;[
+<!ENTITY % head.content
+    "( %HeadOpts.mix;, %title.qname;, %HeadOpts.mix; )"
+>
+<!ENTITY % head.qname  "head" >
+<!ELEMENT %head.qname;  %head.content; >
+<!-- end of head.element -->]]>
+
+<!ENTITY % head.attlist  "INCLUDE" >
+<![%head.attlist;[
+<!-- reserved for future use with document profiles
+-->
+<!ENTITY % profile.attrib
+     "profile      %URI.datatype;           '%XHTML.profile;'"
+>
+
+<!ATTLIST %head.qname;
+      %XHTML.xmlns.attrib;
+      %I18n.attrib;
+      %profile.attrib;
+>
+<!-- end of head.attlist -->]]>
+
+<!-- body: Document Body ............................... -->
+
+<!ENTITY % body.element  "INCLUDE" >
+<![%body.element;[
+<!ENTITY % body.content
+     "( %Block.mix; )+"
+>
+<!ENTITY % body.qname  "body" >
+<!ELEMENT %body.qname;  %body.content; >
+<!-- end of body.element -->]]>
+
+<!ENTITY % body.attlist  "INCLUDE" >
+<![%body.attlist;[
+<!ATTLIST %body.qname;
+      %Common.attrib;
+>
+<!-- end of body.attlist -->]]>
+
+<!-- html: XHTML Document Element ...................... -->
+
+<!ENTITY % html.element  "INCLUDE" >
+<![%html.element;[
+<!ENTITY % html.content  "( %head.qname;, %body.qname; )" >
+<!ENTITY % html.qname  "html" >
+<!ELEMENT %html.qname;  %html.content; >
+<!-- end of html.element -->]]>
+
+<!ENTITY % html.attlist  "INCLUDE" >
+<![%html.attlist;[
+<!-- version attribute value defined in driver
+-->
+<!ENTITY % XHTML.version.attrib
+     "version      %FPI.datatype;           #FIXED '%XHTML.version;'"
+>
+
+<!-- see the Qualified Names module for information
+     on how to extend XHTML using XML namespaces
+-->
+<!ATTLIST %html.qname;
+      %XHTML.xmlns.attrib;
+      %XHTML.version.attrib;
+      %I18n.attrib;
+>
+<!-- end of html.attlist -->]]>
+
+<!-- end of xhtml-struct-1.mod -->
+
+
+<!-- Block Presentation ........................................ -->
+<!ENTITY % xhtml-blkpres.mod PUBLIC "-//W3C//ELEMENTS XHTML Block Presentation 1.0//EN"
+ 		"../xhtml11/xhtml-blkpres-1.mod">
+<!-- ...................................................................... -->
+<!-- XHTML Block Presentation Module  ..................................... -->
+<!-- file: xhtml-blkpres-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-blkpres-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Block Presentation 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-blkpres-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Block Presentational Elements
+
+        hr
+
+     This module declares the elements and their attributes used to
+     support block-level presentational markup.
+-->
+
+<!ENTITY % hr.element  "INCLUDE" >
+<![%hr.element;[
+<!ENTITY % hr.content  "EMPTY" >
+<!ENTITY % hr.qname  "hr" >
+<!ELEMENT %hr.qname;  %hr.content; >
+<!-- end of hr.element -->]]>
+
+<!ENTITY % hr.attlist  "INCLUDE" >
+<![%hr.attlist;[
+<!ATTLIST %hr.qname;
+      %Common.attrib;
+>
+<!-- end of hr.attlist -->]]>
+
+<!-- end of xhtml-blkpres-1.mod -->
+
+
+<!-- ========================================== -->
+<!--
+	Inline Presentation: b, big, i, small
+-->
+<!ENTITY % sub.element "IGNORE">
+<!ENTITY % sub.attlist "IGNORE">
+<!ENTITY % sup.element "IGNORE">
+<!ENTITY % sup.attlist "IGNORE">
+<!ENTITY % tt.element "IGNORE">
+<!ENTITY % tt.attlist "IGNORE">
+<!ENTITY % xhtml-inlpres.mod PUBLIC "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN"
+		"../xhtml11/xhtml-inlpres-1.mod">
+<!-- ...................................................................... -->
+<!-- XHTML Inline Presentation Module  .................................... -->
+<!-- file: xhtml-inlpres-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-inlpres-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN"
+       SYSTEM "../xhtml11/xhtml-inlpres-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Inline Presentational Elements
+
+        b, big, i, small, sub, sup, tt
+
+     This module declares the elements and their attributes used to
+     support inline-level presentational markup.
+-->
+
+<!ENTITY % b.element  "INCLUDE" >
+<![%b.element;[
+<!ENTITY % b.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % b.qname  "b" >
+<!ELEMENT %b.qname;  %b.content; >
+<!-- end of b.element -->]]>
+
+<!ENTITY % b.attlist  "INCLUDE" >
+<![%b.attlist;[
+<!ATTLIST %b.qname;
+      %Common.attrib;
+>
+<!-- end of b.attlist -->]]>
+
+<!ENTITY % big.element  "INCLUDE" >
+<![%big.element;[
+<!ENTITY % big.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % big.qname  "big" >
+<!ELEMENT %big.qname;  %big.content; >
+<!-- end of big.element -->]]>
+
+<!ENTITY % big.attlist  "INCLUDE" >
+<![%big.attlist;[
+<!ATTLIST %big.qname;
+      %Common.attrib;
+>
+<!-- end of big.attlist -->]]>
+
+<!ENTITY % i.element  "INCLUDE" >
+<![%i.element;[
+<!ENTITY % i.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % i.qname  "i" >
+<!ELEMENT %i.qname;  %i.content; >
+<!-- end of i.element -->]]>
+
+<!ENTITY % i.attlist  "INCLUDE" >
+<![%i.attlist;[
+<!ATTLIST %i.qname;
+      %Common.attrib;
+>
+<!-- end of i.attlist -->]]>
+
+<!ENTITY % small.element  "INCLUDE" >
+<![%small.element;[
+<!ENTITY % small.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % small.qname  "small" >
+<!ELEMENT %small.qname;  %small.content; >
+<!-- end of small.element -->]]>
+
+<!ENTITY % small.attlist  "INCLUDE" >
+<![%small.attlist;[
+<!ATTLIST %small.qname;
+      %Common.attrib;
+>
+<!-- end of small.attlist -->]]>
+
+<!ENTITY % sub.element  "INCLUDE" >
+<![%sub.element;[
+<!ENTITY % sub.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % sub.qname  "sub" >
+<!ELEMENT %sub.qname;  %sub.content; >
+<!-- end of sub.element -->]]>
+
+<!ENTITY % sub.attlist  "INCLUDE" >
+<![%sub.attlist;[
+<!ATTLIST %sub.qname;
+      %Common.attrib;
+>
+<!-- end of sub.attlist -->]]>
+
+<!ENTITY % sup.element  "INCLUDE" >
+<![%sup.element;[
+<!ENTITY % sup.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % sup.qname  "sup" >
+<!ELEMENT %sup.qname;  %sup.content; >
+<!-- end of sup.element -->]]>
+
+<!ENTITY % sup.attlist  "INCLUDE" >
+<![%sup.attlist;[
+<!ATTLIST %sup.qname;
+      %Common.attrib;
+>
+<!-- end of sup.attlist -->]]>
+
+<!ENTITY % tt.element  "INCLUDE" >
+<![%tt.element;[
+<!ENTITY % tt.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % tt.qname  "tt" >
+<!ELEMENT %tt.qname;  %tt.content; >
+<!-- end of tt.element -->]]>
+
+<!ENTITY % tt.attlist  "INCLUDE" >
+<![%tt.attlist;[
+<!ATTLIST %tt.qname;
+      %Common.attrib;
+>
+<!-- end of tt.attlist -->]]>
+
+<!-- end of xhtml-inlpres-1.mod -->
+
+
+<!-- end of XHTML Mobile 1.0 DTD  ........................................... -->
\ No newline at end of file
diff --git a/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile10-model-1.mod b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile10-model-1.mod
new file mode 100644
index 0000000..3ca3da8
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile10-model-1.mod
@@ -0,0 +1,167 @@
+<!-- ....................................................................... -->
+<!-- XHTML Mobile 1.0 Document Model Module
+.................................... -->
+<!-- file: xhtml-mobile10-model-1.mod
+
+     This is XHTML Mobile, a proper subset of XHTML.
+     	@Wireless Application Protocol Forum, Ltd. 2001.
+
+	Terms and conditions of use are available from the Wireless
+	Application Protocol Forum Ltd.
+	Web site (http://www.wapforum.org/what/copyright.htm).
+
+-->
+<!-- XHTML Mobile Document Model
+
+     This module describes the groupings of elements that make up
+     common content models for XHTML elements.
+-->
+
+<!-- Optional Elements in head  .............. -->
+
+<!ENTITY % HeadOpts.mix
+
+     "( %meta.qname; | %link.qname; | %object.qname; | %style.qname;
+     )*" >
+
+<!-- Miscellaneous Elements  ................. -->
+
+<!ENTITY % Misc.class "" >
+
+<!-- Inline Elements  ........................ -->
+
+<!ENTITY % InlStruct.class "%br.qname; | %span.qname;" >
+
+<!ENTITY % InlPhras.class
+     "| %em.qname; | %strong.qname; | %dfn.qname; | %code.qname;
+      | %samp.qname; | %kbd.qname; | %var.qname; | %cite.qname;
+      | %abbr.qname; | %acronym.qname; | %q.qname;" >
+
+<!ENTITY % InlPres.class
+     "| %i.qname; | %b.qname; | %big.qname; | %small.qname; " >
+
+
+<!ENTITY % I18n.class "" >
+
+<!ENTITY % Anchor.class "| %a.qname;" >
+
+<!ENTITY % InlSpecial.class "| %img.qname; | %object.qname;" >
+
+<!ENTITY % InlForm.class
+     "| %input.qname; | %select.qname; | %textarea.qname;
+      | %label.qname;"
+>
+
+<!ENTITY % Inline.extra "" >
+
+<!ENTITY % Inline.class
+     "%InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %Anchor.class;
+      %InlSpecial.class;
+      %InlForm.class;
+      %Inline.extra;"
+>
+
+<!ENTITY % InlNoAnchor.class
+     "%InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;      
+      %InlSpecial.class;
+      %InlForm.class;
+      %Inline.extra;"
+>
+
+<!ENTITY % InlNoAnchor.mix
+     "%InlNoAnchor.class;
+      %Misc.class;"
+>
+
+<!ENTITY % Inline.mix
+     "%Inline.class;
+      %Misc.class;"
+>
+
+<!-- Block Elements  ......................... -->
+
+<!ENTITY % Heading.class
+     "%h1.qname; | %h2.qname; | %h3.qname;
+      | %h4.qname; | %h5.qname; | %h6.qname;"
+>
+<!ENTITY % List.class  "%ul.qname; | %ol.qname; | %dl.qname;" >
+
+<!ENTITY % Table.class "| %table.qname;" >
+
+<!ENTITY % Form.class  "| %form.qname;" >
+
+<!ENTITY % Fieldset.class  "| %fieldset.qname;" >
+
+<!ENTITY % BlkStruct.class "%p.qname; | %div.qname;" >
+
+<!ENTITY % BlkPhras.class
+     "| %pre.qname; | %blockquote.qname; | %address.qname;"
+>
+
+<!ENTITY % BlkPres.class "| %hr.qname;" >
+
+<!ENTITY % BlkSpecial.class
+     "%Table.class;
+      %Form.class;
+      %Fieldset.class;"
+>
+
+<!ENTITY % Block.extra "" >
+
+<!ENTITY % Block.class
+     "%BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %BlkSpecial.class;
+      %Block.extra;"
+>
+
+<!ENTITY % BlkNoForm.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %Table.class;
+      %Block.extra;
+      %Misc.class;"
+>
+
+<!ENTITY % Block.mix
+     "%Heading.class;
+      | %List.class;
+      | %Block.class;
+      %Misc.class;"
+>
+
+<!-- All Content Elements  ................... -->
+
+<!-- declares all content except tables
+-->
+<!ENTITY % FlowNoTable.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %Form.class;
+      %Block.extra;
+      | %Inline.class;
+      %Misc.class;"
+>
+
+
+<!ENTITY % Flow.mix
+     "%Heading.class;
+      | %List.class;
+      | %Block.class;
+      | %Inline.class;
+      %Misc.class;"
+>
+
+<!-- end of xhtml-mobile10-model-1.mod -->
+
diff --git a/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile10.dtd b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile10.dtd
new file mode 100644
index 0000000..fbd62a7
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile10.dtd
@@ -0,0 +1,189 @@
+<!-- XHTML Mobile 1.0 DTD  ...................................................... -->
+<!-- file: xhtml-mobile10.dtd -->
+<!-- 
+     This is XHTML Mobile profile, a proper subset of XHTML.
+     
+     	@Wireless Application Protocol Forum, Ltd. 2001.
+
+	Terms and conditions of use are available from the Wireless Application Protocol Forum Ltd. 
+	Web site (http://www.wapforum.org/what/copyright.htm).
+    
+-->
+<!-- This is the driver file for version 1.0 of the XHTML Mobile DTD.
+
+     This DTD is identified by the PUBLIC and SYSTEM identifiers:
+
+     PUBLIC: "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
+     SYSTEM: "http://www.wapforum.org/DTD/xhtml-mobile10.dtd"
+-->
+<!ENTITY % XHTML.version  "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" >
+
+<!-- Use this URI to identify the default namespace:
+
+         "http://www.w3.org/1999/xhtml"
+
+     See the Qualified Names module for information
+     on the use of namespace prefixes in the DTD.
+-->
+<!ENTITY % NS.prefixed "IGNORE" >
+<!ENTITY % XHTML.prefix  "" >
+
+<!-- For example, if you are using XHTML Mobile 1.0 directly, use
+     the FPI in the DOCTYPE declaration, with the xmlns attribute
+     on the document element to identify the default namespace:
+
+         <?xml version="1.0"?>
+         <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
+             "http://www.wapforum.org/DTD/xhtml-mobile10.dtd" >
+         <html xmlns="http://www.w3.org/1999/xhtml"
+               xml:lang="en" >
+         ...
+         </html>
+-->
+
+<!-- reserved for future use with document profiles -->
+<!ENTITY % XHTML.profile  "" >
+
+<!-- Inline Style Module  ........................................ -->
+<!ENTITY % xhtml-inlstyle.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN"
+            "../xhtml11/xhtml-inlstyle-1.mod" >
+%xhtml-inlstyle.mod;
+
+<!-- Document Model ........................................ -->
+<!ENTITY % xhtml-model.mod
+     PUBLIC "-//WAPFORUM//ENTITIES XHTML Mobile 1.0 Document Model 1.0//EN"
+            "xhtml-mobile10-model-1.mod" >
+
+<!-- XHTML Framework ........................................ -->
+<!ENTITY % XHTML.bidi  "IGNORE" >
+<!ENTITY % xhtml-framework.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN"
+            "../xhtml11/xhtml-framework-1.mod" >
+%xhtml-framework.mod;
+
+<!-- XHTML Core Modules ........................................ -->
+<!ENTITY % pre.content
+     "( #PCDATA
+      | %InlStruct.class;
+      %InlPhras.class;
+      %Anchor.class;
+      %Inline.extra; )*"
+>
+
+<!ENTITY % xhtml-text.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Text 1.0//EN"
+            "../xhtml11/xhtml-text-1.mod" >
+%xhtml-text.mod;
+
+<!ENTITY % xhtml-hypertext.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN"
+            "../xhtml11/xhtml-hypertext-1.mod" >
+%xhtml-hypertext.mod;
+
+<!ENTITY % xhtml-list.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Lists 1.0//EN"
+            "../xhtml11/xhtml-list-1.mod" >
+%xhtml-list.mod;
+<!-- Extend lists with value and start attributes --> 
+<!ATTLIST %li.qname;
+      value        %Number.datatype;         #IMPLIED
+>
+<!ATTLIST %ol.qname;
+      start        %Number.datatype;        #IMPLIED
+>
+
+<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+
+<!-- Image Module  ............................................... -->
+<!ENTITY % xhtml-image.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Images 1.0//EN"
+            "../xhtml11/xhtml-image-1.mod" >
+%xhtml-image.mod;
+
+<!-- Tables Module ............................................... -->
+<!ENTITY % xhtml-table.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Basic Tables 1.0//EN"
+            "../xhtml11/xhtml-basic-table-1.mod" >
+%xhtml-table.mod;
+
+<!-- Forms Module  ............................................... 
+	XHTML basic forms module extended with optgroup and fieldset
+-->
+<!ELEMENT %optgroup.qname; (%option.qname;)+>
+<!ATTLIST %optgroup.qname;
+	%Common.attrib; 
+	label %Text.datatype; #REQUIRED
+>
+<!ENTITY % select.content "( %optgroup.qname; | %option.qname; )+">
+<!ELEMENT %fieldset.qname; (#PCDATA | %Flow.mix;)*>
+<!ATTLIST %fieldset.qname;
+	%Common.attrib; 
+>
+<!ENTITY % form.content "( %BlkNoForm.mix; | %fieldset.qname; )+">
+<!ENTITY % xhtml-form.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Basic Forms 1.0//EN"
+            "../xhtml11/xhtml-basic-form-1.mod" >
+%xhtml-form.mod;
+
+<!-- Link Element Module  ........................................ -->
+<!ENTITY % xhtml-link.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Link Element 1.0//EN"
+            "../xhtml11/xhtml-link-1.mod" >
+%xhtml-link.mod;
+
+<!-- Document Metainformation Module  ............................ -->
+<!ENTITY % xhtml-meta.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN"
+            "../xhtml11/xhtml-meta-1.mod" >
+%xhtml-meta.mod;
+
+<!-- Base Element Module  ........................................ -->
+<!ENTITY % xhtml-base.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Base Element 1.0//EN"
+            "../xhtml11/xhtml-base-1.mod" >
+%xhtml-base.mod;
+
+<!-- Stylesheets Module  ......................................... -->
+<!ENTITY % xhtml-style.mod PUBLIC "-//W3C//ELEMENTS XHTML Style Sheets 1.0//EN"
+            "../xhtml11/xhtml-style-1.mod">
+%xhtml-style.mod;
+
+<!-- Param Element Module  ....................................... -->
+<!ENTITY % xhtml-param.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Param Element 1.0//EN"
+            "../xhtml11/xhtml-param-1.mod" >
+%xhtml-param.mod;
+
+<!-- Embedded Object Module  ..................................... -->
+<!ENTITY % xhtml-object.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Embedded Object 1.0//EN"
+            "../xhtml11/xhtml-object-1.mod" >
+%xhtml-object.mod;
+
+<!-- Document Structure Module  ..................................... -->
+<!ENTITY % xhtml-struct.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN"
+            "../xhtml11/xhtml-struct-1.mod" >
+%xhtml-struct.mod;
+
+<!-- Block Presentation ........................................ -->
+<!ENTITY % xhtml-blkpres.mod PUBLIC "-//W3C//ELEMENTS XHTML Block Presentation 1.0//EN"
+ 		"../xhtml11/xhtml-blkpres-1.mod">
+%xhtml-blkpres.mod;
+
+<!-- ========================================== -->
+<!-- 
+	Inline Presentation: b, big, i, small		
+-->
+<!ENTITY % sub.element "IGNORE">
+<!ENTITY % sub.attlist "IGNORE">
+<!ENTITY % sup.element "IGNORE">
+<!ENTITY % sup.attlist "IGNORE">
+<!ENTITY % tt.element "IGNORE">
+<!ENTITY % tt.attlist "IGNORE">
+<!ENTITY % xhtml-inlpres.mod PUBLIC "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN"
+		"../xhtml11/xhtml-inlpres-1.mod">
+%xhtml-inlpres.mod;
+
+<!-- end of XHTML Mobile 1.0 DTD  ........................................... -->
\ No newline at end of file
diff --git a/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile12-form.mod b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile12-form.mod
new file mode 100644
index 0000000..415fc61
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile12-form.mod
@@ -0,0 +1,351 @@
+<!--
+    FILE INFORMATION
+
+    OMA Permanent Document
+       File: OMA-SUP-MOD_xhtml_mobile12-form-V1_2-20080331-A
+       Type: Text
+
+    Public Reachable Information
+       Path: http://www.openmobilealliance.org/tech/DTD
+       Name: xhtml-mobile12-form.mod
+
+    NORMATIVE INFORMATION
+
+    Information about this file can be found in the specification
+     OMA-TS-XHTMLMP-V1_2-20080331-A available at
+       http://www.openmobilealliance.org/
+
+    Send comments to technical-comments@mail.openmobilealliance.org
+	
+    LEGAL DISCLAIMER
+
+    Use of this document is subject to all of the terms and conditions
+    of the Use Agreement located at
+        http://www.openmobilealliance.org/UseAgreement.html
+
+    You may use this document or any part of the document for internal
+    or educational purposes only, provided you do not modify, edit or
+    take out of context the information in this document in any manner.
+    Information contained in this document may be used, at your sole
+    risk, for any purposes.
+
+    You may not use this document in any other manner without the prior
+    written permission of the Open Mobile Alliance.  The Open Mobile
+    Alliance authorizes you to copy this document, provided that you
+    retain all copyright and other proprietary notices contained in the
+    original materials on any copies of the materials and that you
+    comply strictly with these terms.  This copyright permission does
+    not constitute an endorsement of the products or services.  The
+    Open Mobile Alliance assumes no responsibility for errors or
+    omissions in this document.
+
+    Each Open Mobile Alliance member has agreed to use reasonable
+    endeavors to inform the Open Mobile Alliance in a timely manner of
+    Essential IPR as it becomes aware that the Essential IPR is related
+    to the prepared or published specification.  However, the members
+    do not have an obligation to conduct IPR searches.  The declared
+    Essential IPR is publicly available to members and non-members of
+    the Open Mobile Alliance and may be found on the "OMA IPR
+    Declarations" list at http://www.openmobilealliance.org/ipr.html.
+    The Open Mobile Alliance has not conducted an independent IPR review
+    of this document and the information contained herein, and makes no
+    representations or warranties regarding third party IPR, including
+    without limitation patents, copyrights or trade secret rights.  This
+    document may contain inventions for which you must obtain licenses
+    from third parties before making, using or selling the inventions.
+    Defined terms above are set forth in the schedule to the Open Mobile
+    Alliance Application Form.
+
+    NO REPRESENTATIONS OR WARRANTIES (WHETHER EXPRESS OR IMPLIED) ARE
+    MADE BY THE OPEN MOBILE ALLIANCE OR ANY OPEN MOBILE ALLIANCE MEMBER
+    OR ITS AFFILIATES REGARDING ANY OF THE IPR'S REPRESENTED ON THE "OMA
+    IPR DECLARATIONS" LIST, INCLUDING, BUT NOT LIMITED TO THE ACCURACY,
+    COMPLETENESS, VALIDITY OR RELEVANCE OF THE INFORMATION OR WHETHER OR     
+    NOT SUCH RIGHTS ARE ESSENTIAL OR NON-ESSENTIAL.
+
+    THE OPEN MOBILE ALLIANCE IS NOT LIABLE FOR AND HEREBY DISCLAIMS ANY
+    DIRECT, INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL, CONSEQUENTIAL, OR
+    EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THE USE OF
+    DOCUMENTS AND THE INFORMATION CONTAINED IN THE DOCUMENTS.
+
+    Copyright 2008 Open Mobile Alliance Ltd.  All Rights Reserved.
+    Used with the permission of the Open Mobile Alliance Ltd. under the
+    terms set forth above.
+-->
+
+<!-- Forms
+
+        form, label, input, select, optgroup, option,
+        textarea, fieldset, legend, button
+
+     This module declares markup to provide support for online
+     forms, based on the features found in HTML 4 forms.
+-->
+
+<!-- declare qualified element type names:
+-->
+<!ENTITY % form.qname  "form" >
+<!ENTITY % label.qname  "label" >
+<!ENTITY % input.qname  "input" >
+<!ENTITY % select.qname  "select" >
+<!ENTITY % optgroup.qname  "optgroup" >
+<!ENTITY % option.qname  "option" >
+<!ENTITY % textarea.qname  "textarea" >
+<!ENTITY % fieldset.qname  "fieldset" >
+<!ENTITY % legend.qname  "legend" >
+<!ENTITY % button.qname  "button" >
+
+<!-- %BlkNoForm.mix; includes all non-form block elements,
+     plus %Misc.class;
+-->
+<!ENTITY % BlkNoForm.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %Table.class;
+      %Block.extra;
+      %Misc.class;"
+>
+
+<!-- form: Form Element ................................ -->
+
+<!ENTITY % form.element  "INCLUDE" >
+<![%form.element;[
+<!ENTITY % form.content
+     "( %BlkNoForm.mix;
+      | %fieldset.qname; )+"
+>
+<!ELEMENT %form.qname;  %form.content; >
+<!-- end of form.element -->]]>
+
+<!ENTITY % form.attlist  "INCLUDE" >
+<![%form.attlist;[
+<!ATTLIST %form.qname;
+      %Common.attrib;
+      action       %URI.datatype;           #REQUIRED
+      method       ( get | post )           'get'
+      enctype      %ContentType.datatype;   'application/x-www-form-urlencoded'
+      accept-charset %Charsets.datatype;    #IMPLIED
+      accept       %ContentTypes.datatype;  #IMPLIED
+>
+<!-- end of form.attlist -->]]>
+
+<!-- label: Form Field Label Text ...................... -->
+
+<!-- Each label must not contain more than ONE field
+-->
+
+<!ENTITY % label.element  "INCLUDE" >
+<![%label.element;[
+<!ENTITY % label.content
+     "( #PCDATA
+      | %input.qname; | %select.qname; | %textarea.qname; | %button.qname;
+      | %InlStruct.class;
+      %InlPhras.class;
+      %I18n.class;
+      %InlPres.class;
+      %Anchor.class;
+      %InlSpecial.class;
+      %Inline.extra;
+      %Misc.class; )*"
+>
+<!ELEMENT %label.qname;  %label.content; >
+<!-- end of label.element -->]]>
+
+<!ENTITY % label.attlist  "INCLUDE" >
+<![%label.attlist;[
+<!ATTLIST %label.qname;
+      %Common.attrib;
+      for          IDREF                    #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of label.attlist -->]]>
+
+<!-- input: Form Control ............................... -->
+
+<!ENTITY % input.element  "INCLUDE" >
+<![%input.element;[
+<!ENTITY % input.content  "EMPTY" >
+<!ELEMENT %input.qname;  %input.content; >
+<!-- end of input.element -->]]>
+
+<!ENTITY % input.attlist  "INCLUDE" >
+<![%input.attlist;[
+<!ENTITY % InputType.class
+     "( text | password | checkbox | radio | submit
+      | reset | file | hidden | image | button )"
+>
+<!-- attribute 'name' required for all but submit & reset
+-->
+<!ATTLIST %input.qname;
+      %Common.attrib;
+      type         %InputType.class;        'text'
+      name         CDATA                    #IMPLIED
+      value        CDATA                    #IMPLIED
+      checked      ( checked )              #IMPLIED
+      disabled     ( disabled )             #IMPLIED
+      readonly     ( readonly )             #IMPLIED
+      size         %Number.datatype;        #IMPLIED
+      maxlength    %Number.datatype;        #IMPLIED
+      src          %URI.datatype;           #IMPLIED
+      alt          %Text.datatype;          #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+      accept       %ContentTypes.datatype;  #IMPLIED
+      inputmode    CDATA                    #IMPLIED
+>
+<!-- end of input.attlist -->]]>
+
+<!-- select: Option Selector ........................... -->
+
+<!ENTITY % select.element  "INCLUDE" >
+<![%select.element;[
+<!ENTITY % select.content
+     "( %optgroup.qname; | %option.qname; )+"
+>
+<!ELEMENT %select.qname;  %select.content; >
+<!-- end of select.element -->]]>
+
+<!ENTITY % select.attlist  "INCLUDE" >
+<![%select.attlist;[
+<!ATTLIST %select.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      size         %Number.datatype;        #IMPLIED
+      multiple     ( multiple )             #IMPLIED
+      disabled     ( disabled )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+>
+<!-- end of select.attlist -->]]>
+
+<!-- optgroup: Option Group ............................ -->
+
+<!ENTITY % optgroup.element  "INCLUDE" >
+<![%optgroup.element;[
+<!ENTITY % optgroup.content  "( %option.qname; )+" >
+<!ELEMENT %optgroup.qname;  %optgroup.content; >
+<!-- end of optgroup.element -->]]>
+
+<!ENTITY % optgroup.attlist  "INCLUDE" >
+<![%optgroup.attlist;[
+<!ATTLIST %optgroup.qname;
+      %Common.attrib;
+      disabled     ( disabled )             #IMPLIED
+      label        %Text.datatype;          #REQUIRED
+>
+<!-- end of optgroup.attlist -->]]>
+
+<!-- option: Selectable Choice ......................... -->
+
+<!ENTITY % option.element  "INCLUDE" >
+<![%option.element;[
+<!ENTITY % option.content  "( #PCDATA )" >
+<!ELEMENT %option.qname;  %option.content; >
+<!-- end of option.element -->]]>
+
+<!ENTITY % option.attlist  "INCLUDE" >
+<![%option.attlist;[
+<!ATTLIST %option.qname;
+      %Common.attrib;
+      selected     ( selected )             #IMPLIED
+      disabled     ( disabled )             #IMPLIED
+      label        %Text.datatype;          #IMPLIED
+      value        CDATA                    #IMPLIED
+>
+<!-- end of option.attlist -->]]>
+
+<!-- textarea: Multi-Line Text Field ................... -->
+
+<!ENTITY % textarea.element  "INCLUDE" >
+<![%textarea.element;[
+<!ENTITY % textarea.content  "( #PCDATA )" >
+<!ELEMENT %textarea.qname;  %textarea.content; >
+<!-- end of textarea.element -->]]>
+
+<!ENTITY % textarea.attlist  "INCLUDE" >
+<![%textarea.attlist;[
+<!ATTLIST %textarea.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      rows         %Number.datatype;        #REQUIRED
+      cols         %Number.datatype;        #REQUIRED
+      disabled     ( disabled )             #IMPLIED
+      readonly     ( readonly )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+      inputmode    CDATA                    #IMPLIED
+>
+<!-- end of textarea.attlist -->]]>
+
+<!-- fieldset: Form Control Group ...................... -->
+
+<!-- #PCDATA is to solve the mixed content problem,
+     per specification only whitespace is allowed
+-->
+
+<!ENTITY % fieldset.element  "INCLUDE" >
+<![%fieldset.element;[
+<!ENTITY % fieldset.content
+     "( #PCDATA | %legend.qname; | %Flow.mix; )*"
+>
+<!ELEMENT %fieldset.qname;  %fieldset.content; >
+<!-- end of fieldset.element -->]]>
+
+<!ENTITY % fieldset.attlist  "INCLUDE" >
+<![%fieldset.attlist;[
+<!ATTLIST %fieldset.qname;
+      %Common.attrib;
+>
+<!-- end of fieldset.attlist -->]]>
+
+<!-- legend: Fieldset Legend ........................... -->
+
+<!ENTITY % legend.element  "INCLUDE" >
+<![%legend.element;[
+<!ENTITY % legend.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ELEMENT %legend.qname;  %legend.content; >
+<!-- end of legend.element -->]]>
+
+<!ENTITY % legend.attlist  "INCLUDE" >
+<![%legend.attlist;[
+<!ATTLIST %legend.qname;
+      %Common.attrib;
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of legend.attlist -->]]>
+
+<!-- button: Push Button ............................... -->
+
+<!ENTITY % button.element  "INCLUDE" >
+<![%button.element;[
+<!ENTITY % button.content
+     "( #PCDATA
+      | %BlkNoForm.mix;
+      | %InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %I18n.class;
+      %InlSpecial.class;
+      %Inline.extra; )*"
+>
+<!ELEMENT %button.qname;  %button.content; >
+<!-- end of button.element -->]]>
+
+<!ENTITY % button.attlist  "INCLUDE" >
+<![%button.attlist;[
+<!ATTLIST %button.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      value        CDATA                    #IMPLIED
+      type         ( button | submit | reset ) 'submit'
+      disabled     ( disabled )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of button.attlist -->]]>
+
+<!-- end of xhtml-form-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile12-model-1.mod b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile12-model-1.mod
new file mode 100644
index 0000000..9beb71a
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile12-model-1.mod
@@ -0,0 +1,237 @@
+<!--
+    FILE INFORMATION
+
+    OMA Permanent Document
+       File: OMA-SUP-MOD_xhtml_mobile12-model-1-V1_2-20080331-A
+       Type: Text
+
+    Public Reachable Information
+       Path: http://www.openmobilealliance.org/tech/DTD
+       Name: xhtml-mobile12-model-1.mod
+
+    NORMATIVE INFORMATION
+
+    Information about this file can be found in the specification
+    OMA-TS-XHTMLMP-V1_2-20080331-A available at
+       http://www.openmobilealliance.org/
+
+    Send comments to technical-comments@mail.openmobilealliance.org
+	
+    LEGAL DISCLAIMER
+
+    Use of this document is subject to all of the terms and conditions
+    of the Use Agreement located at
+        http://www.openmobilealliance.org/UseAgreement.html
+
+    You may use this document or any part of the document for internal
+    or educational purposes only, provided you do not modify, edit or
+    take out of context the information in this document in any manner.
+    Information contained in this document may be used, at your sole
+    risk, for any purposes.
+
+    You may not use this document in any other manner without the prior
+    written permission of the Open Mobile Alliance.  The Open Mobile
+    Alliance authorizes you to copy this document, provided that you
+    retain all copyright and other proprietary notices contained in the
+    original materials on any copies of the materials and that you
+    comply strictly with these terms.  This copyright permission does
+    not constitute an endorsement of the products or services.  The
+    Open Mobile Alliance assumes no responsibility for errors or
+    omissions in this document.
+
+    Each Open Mobile Alliance member has agreed to use reasonable
+    endeavors to inform the Open Mobile Alliance in a timely manner of
+    Essential IPR as it becomes aware that the Essential IPR is related
+    to the prepared or published specification.  However, the members
+    do not have an obligation to conduct IPR searches.  The declared
+    Essential IPR is publicly available to members and non-members of
+    the Open Mobile Alliance and may be found on the "OMA IPR
+    Declarations" list at http://www.openmobilealliance.org/ipr.html.
+    The Open Mobile Alliance has not conducted an independent IPR review
+    of this document and the information contained herein, and makes no
+    representations or warranties regarding third party IPR, including
+    without limitation patents, copyrights or trade secret rights.  This
+    document may contain inventions for which you must obtain licenses
+    from third parties before making, using or selling the inventions.
+    Defined terms above are set forth in the schedule to the Open Mobile
+    Alliance Application Form.
+
+    NO REPRESENTATIONS OR WARRANTIES (WHETHER EXPRESS OR IMPLIED) ARE
+    MADE BY THE OPEN MOBILE ALLIANCE OR ANY OPEN MOBILE ALLIANCE MEMBER
+    OR ITS AFFILIATES REGARDING ANY OF THE IPR'S REPRESENTED ON THE "OMA
+    IPR DECLARATIONS" LIST, INCLUDING, BUT NOT LIMITED TO THE ACCURACY,
+    COMPLETENESS, VALIDITY OR RELEVANCE OF THE INFORMATION OR WHETHER OR     
+    NOT SUCH RIGHTS ARE ESSENTIAL OR NON-ESSENTIAL.
+
+    THE OPEN MOBILE ALLIANCE IS NOT LIABLE FOR AND HEREBY DISCLAIMS ANY
+    DIRECT, INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL, CONSEQUENTIAL, OR
+    EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THE USE OF
+    DOCUMENTS AND THE INFORMATION CONTAINED IN THE DOCUMENTS.
+
+    Copyright 2008 Open Mobile Alliance Ltd.  All Rights Reserved.
+    Used with the permission of the Open Mobile Alliance Ltd. under the
+    terms set forth above.
+-->
+<!-- XHTML Mobile Document Model
+
+     This module describes the groupings of elements that make up
+     common content models for XHTML elements.
+-->
+
+<!-- Optional Elements in head  .............. -->
+
+<!ENTITY % HeadOpts.mix
+
+     "( %script.qname; | %meta.qname; | %link.qname; | %object.qname; | %style.qname;
+     )*" >
+
+
+<!-- Miscellaneous Elements  ................. -->
+
+<!ENTITY % Script.class "| %script.qname; | %noscript.qname;" >
+
+<!ENTITY % Misc.extra "" >
+
+<!ENTITY % Misc.class
+      "%Script.class;
+      %Misc.extra;"
+>
+
+<!-- Inline Elements  ........................ -->
+
+<!ENTITY % InlStruct.class "%br.qname; | %span.qname;" >
+
+<!ENTITY % InlPhras.class
+     "| %em.qname; | %strong.qname; | %dfn.qname; | %code.qname;
+      | %samp.qname; | %kbd.qname; | %var.qname; | %cite.qname;
+      | %abbr.qname; | %acronym.qname; | %q.qname;" >
+
+<!ENTITY % InlPres.class
+     "| %i.qname; | %b.qname; | %big.qname; | %small.qname; " >
+
+
+<!ENTITY % I18n.class "" >
+
+<!ENTITY % Anchor.class "| %a.qname;" >
+
+<!ENTITY % InlSpecial.class "| %img.qname; | %object.qname;" >
+
+<!ENTITY % InlForm.class
+     "| %input.qname; | %select.qname; | %textarea.qname;
+      | %label.qname; | %button.qname;"
+>
+<!-- yam added button.qname 060612 -->
+
+<!ENTITY % Inline.extra "" >
+
+<!ENTITY % Inline.class
+     "%InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %Anchor.class;
+      %InlSpecial.class;
+      %InlForm.class;
+      %Inline.extra;"
+>
+
+<!ENTITY % InlNoAnchor.class
+     "%InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;      
+      %InlSpecial.class;
+      %InlForm.class;
+      %Inline.extra;"
+>
+
+<!ENTITY % InlNoAnchor.mix
+     "%InlNoAnchor.class;
+      %Misc.class;"
+>
+
+<!ENTITY % Inline.mix
+     "%Inline.class;
+      %Misc.class;"
+>
+
+<!-- Block Elements  ......................... -->
+
+<!ENTITY % Heading.class
+     "%h1.qname; | %h2.qname; | %h3.qname;
+      | %h4.qname; | %h5.qname; | %h6.qname;"
+>
+<!ENTITY % List.class  "%ul.qname; | %ol.qname; | %dl.qname;" >
+
+<!ENTITY % Table.class "| %table.qname;" >
+
+<!ENTITY % Form.class  "| %form.qname;" >
+
+<!ENTITY % Fieldset.class  "| %fieldset.qname;" >
+
+<!ENTITY % BlkStruct.class "%p.qname; | %div.qname;" >
+
+<!ENTITY % BlkPhras.class
+     "| %pre.qname; | %blockquote.qname; | %address.qname;"
+>
+
+<!ENTITY % BlkPres.class "| %hr.qname;" >
+
+<!ENTITY % BlkSpecial.class
+     "%Table.class;
+      %Form.class;
+      %Fieldset.class;"
+>
+
+<!ENTITY % Block.extra "" >
+
+<!ENTITY % Block.class
+     "%BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %BlkSpecial.class;
+      %Block.extra;"
+>
+
+<!ENTITY % BlkNoForm.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %Table.class;
+      %Block.extra;
+      %Misc.class;"
+>
+
+<!ENTITY % Block.mix
+     "%Heading.class;
+      | %List.class;
+      | %Block.class;
+      %Misc.class;"
+>
+
+<!-- All Content Elements  ................... -->
+
+<!-- declares all content except tables
+-->
+<!ENTITY % FlowNoTable.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %Form.class;
+      %Block.extra;
+      | %Inline.class;
+      %Misc.class;"
+>
+
+
+<!ENTITY % Flow.mix
+     "%Heading.class;
+      | %List.class;
+      | %Block.class;
+      | %Inline.class;
+      %Misc.class;"
+>
+
+<!-- end of xhtml-mobile12-model-1.mod -->
+
diff --git a/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile12.dtd b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile12.dtd
new file mode 100644
index 0000000..745c736
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtml-mobile12.dtd
@@ -0,0 +1,248 @@
+<!--
+    FILE INFORMATION
+
+    OMA Permanent Document
+       File: OMA-SUP-DTD_xhtml_mobile12-V1_2-20080331-A
+       Type: Text
+
+    Public Reachable Information
+       Path: http://www.openmobilealliance.org/tech/DTD
+       Name: xhtml-mobile12.dtd
+
+    NORMATIVE INFORMATION
+
+    Information about this file can be found in the specification
+     OMA-TS-XHTMLMP-V1_2-20080331-A available at
+       http://www.openmobilealliance.org/
+
+    Send comments to technical-comments@mail.openmobilealliance.org
+	
+    LEGAL DISCLAIMER
+
+    Use of this document is subject to all of the terms and conditions
+    of the Use Agreement located at
+        http://www.openmobilealliance.org/UseAgreement.html
+
+    You may use this document or any part of the document for internal
+    or educational purposes only, provided you do not modify, edit or
+    take out of context the information in this document in any manner.
+    Information contained in this document may be used, at your sole
+    risk, for any purposes.
+
+    You may not use this document in any other manner without the prior
+    written permission of the Open Mobile Alliance.  The Open Mobile
+    Alliance authorizes you to copy this document, provided that you
+    retain all copyright and other proprietary notices contained in the
+    original materials on any copies of the materials and that you
+    comply strictly with these terms.  This copyright permission does
+    not constitute an endorsement of the products or services.  The
+    Open Mobile Alliance assumes no responsibility for errors or
+    omissions in this document.
+
+    Each Open Mobile Alliance member has agreed to use reasonable
+    endeavors to inform the Open Mobile Alliance in a timely manner of
+    Essential IPR as it becomes aware that the Essential IPR is related
+    to the prepared or published specification.  However, the members
+    do not have an obligation to conduct IPR searches.  The declared
+    Essential IPR is publicly available to members and non-members of
+    the Open Mobile Alliance and may be found on the "OMA IPR
+    Declarations" list at http://www.openmobilealliance.org/ipr.html.
+    The Open Mobile Alliance has not conducted an independent IPR review
+    of this document and the information contained herein, and makes no
+    representations or warranties regarding third party IPR, including
+    without limitation patents, copyrights or trade secret rights.  This
+    document may contain inventions for which you must obtain licenses
+    from third parties before making, using or selling the inventions.
+    Defined terms above are set forth in the schedule to the Open Mobile
+    Alliance Application Form.
+
+    NO REPRESENTATIONS OR WARRANTIES (WHETHER EXPRESS OR IMPLIED) ARE
+    MADE BY THE OPEN MOBILE ALLIANCE OR ANY OPEN MOBILE ALLIANCE MEMBER
+    OR ITS AFFILIATES REGARDING ANY OF THE IPR'S REPRESENTED ON THE "OMA
+    IPR DECLARATIONS" LIST, INCLUDING, BUT NOT LIMITED TO THE ACCURACY,
+    COMPLETENESS, VALIDITY OR RELEVANCE OF THE INFORMATION OR WHETHER OR     
+    NOT SUCH RIGHTS ARE ESSENTIAL OR NON-ESSENTIAL.
+
+    THE OPEN MOBILE ALLIANCE IS NOT LIABLE FOR AND HEREBY DISCLAIMS ANY
+    DIRECT, INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL, CONSEQUENTIAL, OR
+    EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THE USE OF
+    DOCUMENTS AND THE INFORMATION CONTAINED IN THE DOCUMENTS.
+
+    Copyright 2008 Open Mobile Alliance Ltd.  All Rights Reserved.
+    Used with the permission of the Open Mobile Alliance Ltd. under the
+    terms set forth above.
+-->
+<!-- This is the driver file for version 1.2 of the XHTML Mobile DTD.
+
+     This DTD is identified by the PUBLIC and SYSTEM identifiers:
+
+     PUBLIC: "-//OMA//DTD XHTML Mobile 1.2//EN"
+     SYSTEM: "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd"
+-->
+<!ENTITY % XHTML.version  "-//OMA//DTD XHTML Mobile 1.2//EN" >
+
+<!-- Use this URI to identify the default namespace:
+
+         "http://www.w3.org/1999/xhtml"
+
+     See the Qualified Names module for information
+     on the use of namespace prefixes in the DTD.
+-->
+<!ENTITY % NS.prefixed "IGNORE" >
+<!ENTITY % XHTML.prefix  "" >
+
+<!-- For example, if you are using XHTML Mobile 1.2 directly, use
+     the FPI in the DOCTYPE declaration, with the xmlns attribute
+     on the document element to identify the default namespace:
+
+         <?xml version="1.0"?>
+         <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN"
+             "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd" >
+         <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+         ...
+         </html>
+-->
+
+<!-- Reserved for future use with document profiles -->
+<!ENTITY % XHTML.profile  "" >
+
+<!-- Intrinsic Events Module  ................................................... -->
+<!ENTITY % xhtml-events.module "INCLUDE" >
+
+<!-- Inline Style Module  ....................................................... -->
+<!ENTITY % xhtml-inlstyle.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN"
+            "../xhtml11/xhtml-inlstyle-1.mod" >
+%xhtml-inlstyle.mod;
+
+<!-- Document Model ............................................................. -->
+<!ENTITY % xhtml-model.mod
+     PUBLIC "-//OMA//ENTITIES XHTML Mobile 1.2 Document Model 1.0//EN"
+            "xhtml-mobile12-model-1.mod" >
+
+<!-- XHTML Framework ............................................................ -->
+<!ENTITY % XHTML.bidi  "IGNORE" >
+<!ENTITY % xhtml-framework.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN"
+            "../xhtml11/xhtml-framework-1.mod" >
+%xhtml-framework.mod;
+
+<!-- XHTML Core Modules ......................................................... -->
+<!ENTITY % pre.content
+     "( #PCDATA
+      | %InlStruct.class;
+      %InlPhras.class;
+      %Anchor.class;
+      %Inline.extra; )*"
+>
+
+<!ENTITY % xhtml-text.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Text 1.0//EN"
+            "../xhtml11/xhtml-text-1.mod" >
+%xhtml-text.mod;
+
+<!ENTITY % xhtml-hypertext.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN"
+            "../xhtml11/xhtml-hypertext-1.mod" >
+%xhtml-hypertext.mod;
+
+<!ENTITY % xhtml-list.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Lists 1.0//EN"
+            "../xhtml11/xhtml-list-1.mod" >
+%xhtml-list.mod;
+<!-- Extend lists with value and start attributes --> 
+<!ATTLIST %li.qname;
+      value        %Number.datatype;         #IMPLIED
+>
+<!ATTLIST %ol.qname;
+      start        %Number.datatype;        #IMPLIED
+>
+
+<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+
+<!-- Image Module  ............................................... -->
+<!ENTITY % xhtml-image.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Images 1.0//EN"
+            "../xhtml11/xhtml-image-1.mod" >
+%xhtml-image.mod;
+
+<!-- Tables Module ............................................... -->
+<!ENTITY % xhtml-table.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Basic Tables 1.0//EN"
+            "../xhtml11/xhtml-basic-table-1.mod" >
+%xhtml-table.mod;
+
+<!-- Forms Module  ............................................... 
+	XHTML Form with an inputmode extension from XForm 1.0
+-->
+
+<!ENTITY % xhtml-form.mod
+     PUBLIC "-//OMA//ELEMENTS XHTML MP 1.2 Forms 1.0//EN"
+            "xhtmlmp12-form-1.mod" >
+%xhtml-form.mod;
+
+<!-- Link Element Module  ........................................ -->
+<!ENTITY % xhtml-link.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Link Element 1.0//EN"
+            "../xhtml11/xhtml-link-1.mod" >
+%xhtml-link.mod;
+
+<!-- Document Metainformation Module  ............................ -->
+<!ENTITY % xhtml-meta.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN"
+            "../xhtml11/xhtml-meta-1.mod" >
+%xhtml-meta.mod;
+
+<!-- Base Element Module  ........................................ -->
+<!ENTITY % xhtml-base.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Base Element 1.0//EN"
+            "../xhtml11/xhtml-base-1.mod" >
+%xhtml-base.mod;
+
+<!-- Scripting Module  ........................................... -->
+<!ENTITY % xhtml-script.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Scripting 1.0//EN"
+            "../xhtml11/xhtml-script-1.mod" >
+%xhtml-script.mod;
+
+<!-- Style Sheets Module  ......................................... -->
+<!ENTITY % xhtml-style.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Style Sheets 1.0//EN"
+            "../xhtml11/xhtml-style-1.mod" >
+%xhtml-style.mod;
+
+<!-- Param Element Module  ....................................... -->
+<!ENTITY % xhtml-param.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Param Element 1.0//EN"
+            "../xhtml11/xhtml-param-1.mod" >
+%xhtml-param.mod;
+
+<!-- Embedded Object Module  ..................................... -->
+<!ENTITY % xhtml-object.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Embedded Object 1.0//EN"
+            "../xhtml11/xhtml-object-1.mod" >
+%xhtml-object.mod;
+
+<!-- Document Structure Module  ..................................... -->
+<!ENTITY % xhtml-struct.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN"
+            "../xhtml11/xhtml-struct-1.mod" >
+%xhtml-struct.mod;
+
+<!-- Block Presentation ........................................ -->
+<!ENTITY % xhtml-blkpres.mod PUBLIC "-//W3C//ELEMENTS XHTML Block Presentation 1.0//EN"
+ 		"../xhtml11/xhtml-blkpres-1.mod" >
+%xhtml-blkpres.mod;
+
+<!-- ========================================== -->
+<!--
+      XHTMLMP 1.2 Inline Presentation: all of XHTML Mod Presentation module
+(b, big, hr, i, small, sub, sup, tt) not just the subset (b, big, hr, i,
+small) as in XHTMLMP 1.1
+-->
+<!ENTITY % xhtml-inlpres.mod PUBLIC "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN"
+		"../xhtml11/xhtml-inlpres-1.mod">
+%xhtml-inlpres.mod;
+
+<!-- end of XHTML Mobile 1.2 DTD  ........................................... -->
+
diff --git a/xml/impl/resources/standardSchemas/xhtml-mobile/xhtmlmp12-form-1.mod b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtmlmp12-form-1.mod
new file mode 100644
index 0000000..97c8521
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-mobile/xhtmlmp12-form-1.mod
@@ -0,0 +1,306 @@
+
+<!-- saved from url=(0096)http://dev.w3.org/2007/mobileok-ref/dtd/www.openmobilealliance.org/tech/DTD/xhtmlmp12-form-1.mod -->
+<HTML><BODY><PRE style="word-wrap: break-word; white-space: pre-wrap;">&lt;!-- ...................................................................... --&gt;
+&lt;!-- XHTMLMP1.2 Forms Module  .................................................. --&gt;
+&lt;!-- file: xhtmlmp12-form-1.mod
+
+     This is a xhtmlmp12-form-1.mod with inputmode attribute.
+
+     (C) 2006 Open Mobile Alliance Ltd.  All Rights Reserved.	
+
+     LEGAL DISCLAIMER
+
+     Use of this document is subject to all of the terms and conditions
+     of the Use Agreement located at
+	http://www.openmobilealliance.org/UseAgreement.html
+
+    NO REPRESENTATIONS OR WARRANTIES (WHETHER EXPRESS OR IMPLIED) ARE
+    MADE BY THE OPEN MOBILE ALLIANCE OR ANY OPEN MOBILE ALLIANCE MEMBER
+    OR ITS AFFILIATES REGARDING ANY OF THE IPRS REPRESENTED ON THE OMA
+    IPR DECLARATIONS LIST, INCLUDING, BUT NOT LIMITED TO THE ACCURACY,
+    COMPLETENESS, VALIDITY OR RELEVANCE OF THE INFORMATION OR WHETHER OR
+    NOT SUCH RIGHTS ARE ESSENTIAL OR NON-ESSENTIAL.
+
+    THE OPEN MOBILE ALLIANCE IS NOT LIABLE FOR AND HEREBY DISCLAIMS ANY
+    DIRECT, INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL, CONSEQUENTIAL, OR
+    EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THE USE OF
+    DOCUMENTS AND THE INFORMATION CONTAINED IN THE DOCUMENTS.
+     ....................................................................... --&gt;
+
+&lt;!-- Forms
+
+        form, label, input, select, optgroup, option,
+        textarea, fieldset, legend, button
+
+     This module declares markup to provide support for online
+     forms, based on the features found in HTML 4 forms.
+--&gt;
+
+&lt;!-- declare qualified element type names:
+--&gt;
+&lt;!ENTITY % form.qname  "form" &gt;
+&lt;!ENTITY % label.qname  "label" &gt;
+&lt;!ENTITY % input.qname  "input" &gt;
+&lt;!ENTITY % select.qname  "select" &gt;
+&lt;!ENTITY % optgroup.qname  "optgroup" &gt;
+&lt;!ENTITY % option.qname  "option" &gt;
+&lt;!ENTITY % textarea.qname  "textarea" &gt;
+&lt;!ENTITY % fieldset.qname  "fieldset" &gt;
+&lt;!ENTITY % legend.qname  "legend" &gt;
+&lt;!ENTITY % button.qname  "button" &gt;
+
+&lt;!-- %BlkNoForm.mix; includes all non-form block elements,
+     plus %Misc.class;
+--&gt;
+&lt;!ENTITY % BlkNoForm.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %Table.class;
+      %Block.extra;
+      %Misc.class;"
+&gt;
+
+&lt;!-- form: Form Element ................................ --&gt;
+
+&lt;!ENTITY % form.element  "INCLUDE" &gt;
+&lt;![%form.element;[
+&lt;!ENTITY % form.content
+     "( %BlkNoForm.mix;
+      | %fieldset.qname; )+"
+&gt;
+&lt;!ELEMENT %form.qname;  %form.content; &gt;
+&lt;!-- end of form.element --&gt;]]&gt;
+
+&lt;!ENTITY % form.attlist  "INCLUDE" &gt;
+&lt;![%form.attlist;[
+&lt;!ATTLIST %form.qname;
+      %Common.attrib;
+      action       %URI.datatype;           #REQUIRED
+      method       ( get | post )           'get'
+      enctype      %ContentType.datatype;   'application/x-www-form-urlencoded'
+      accept-charset %Charsets.datatype;    #IMPLIED
+      accept       %ContentTypes.datatype;  #IMPLIED
+&gt;
+&lt;!-- end of form.attlist --&gt;]]&gt;
+
+&lt;!-- label: Form Field Label Text ...................... --&gt;
+
+&lt;!-- Each label must not contain more than ONE field
+--&gt;
+
+&lt;!ENTITY % label.element  "INCLUDE" &gt;
+&lt;![%label.element;[
+&lt;!ENTITY % label.content
+     "( #PCDATA
+      | %input.qname; | %select.qname; | %textarea.qname; | %button.qname;
+      | %InlStruct.class;
+      %InlPhras.class;
+      %I18n.class;
+      %InlPres.class;
+      %Anchor.class;
+      %InlSpecial.class;
+      %Inline.extra;
+      %Misc.class; )*"
+&gt;
+&lt;!ELEMENT %label.qname;  %label.content; &gt;
+&lt;!-- end of label.element --&gt;]]&gt;
+
+&lt;!ENTITY % label.attlist  "INCLUDE" &gt;
+&lt;![%label.attlist;[
+&lt;!ATTLIST %label.qname;
+      %Common.attrib;
+      for          IDREF                    #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+&gt;
+&lt;!-- end of label.attlist --&gt;]]&gt;
+
+&lt;!-- input: Form Control ............................... --&gt;
+
+&lt;!ENTITY % input.element  "INCLUDE" &gt;
+&lt;![%input.element;[
+&lt;!ENTITY % input.content  "EMPTY" &gt;
+&lt;!ELEMENT %input.qname;  %input.content; &gt;
+&lt;!-- end of input.element --&gt;]]&gt;
+
+&lt;!ENTITY % input.attlist  "INCLUDE" &gt;
+&lt;![%input.attlist;[
+&lt;!ENTITY % InputType.class
+     "( text | password | checkbox | radio | submit
+      | reset | file | hidden | image | button )"
+&gt;
+&lt;!-- attribute 'name' required for all but submit &amp; reset
+--&gt;
+&lt;!ATTLIST %input.qname;
+      %Common.attrib;
+      type         %InputType.class;        'text'
+      name         CDATA                    #IMPLIED
+      value        CDATA                    #IMPLIED
+      checked      ( checked )              #IMPLIED
+      disabled     ( disabled )             #IMPLIED
+      readonly     ( readonly )             #IMPLIED
+      size         %Number.datatype;        #IMPLIED
+      maxlength    %Number.datatype;        #IMPLIED
+      src          %URI.datatype;           #IMPLIED
+      alt          %Text.datatype;          #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+      accept       %ContentTypes.datatype;  #IMPLIED
+      inputmode    CDATA                    #IMPLIED
+&gt;
+&lt;!-- end of input.attlist --&gt;]]&gt;
+
+&lt;!-- select: Option Selector ........................... --&gt;
+
+&lt;!ENTITY % select.element  "INCLUDE" &gt;
+&lt;![%select.element;[
+&lt;!ENTITY % select.content
+     "( %optgroup.qname; | %option.qname; )+"
+&gt;
+&lt;!ELEMENT %select.qname;  %select.content; &gt;
+&lt;!-- end of select.element --&gt;]]&gt;
+
+&lt;!ENTITY % select.attlist  "INCLUDE" &gt;
+&lt;![%select.attlist;[
+&lt;!ATTLIST %select.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      size         %Number.datatype;        #IMPLIED
+      multiple     ( multiple )             #IMPLIED
+      disabled     ( disabled )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+&gt;
+&lt;!-- end of select.attlist --&gt;]]&gt;
+
+&lt;!-- optgroup: Option Group ............................ --&gt;
+
+&lt;!ENTITY % optgroup.element  "INCLUDE" &gt;
+&lt;![%optgroup.element;[
+&lt;!ENTITY % optgroup.content  "( %option.qname; )+" &gt;
+&lt;!ELEMENT %optgroup.qname;  %optgroup.content; &gt;
+&lt;!-- end of optgroup.element --&gt;]]&gt;
+
+&lt;!ENTITY % optgroup.attlist  "INCLUDE" &gt;
+&lt;![%optgroup.attlist;[
+&lt;!ATTLIST %optgroup.qname;
+      %Common.attrib;
+      disabled     ( disabled )             #IMPLIED
+      label        %Text.datatype;          #REQUIRED
+&gt;
+&lt;!-- end of optgroup.attlist --&gt;]]&gt;
+
+&lt;!-- option: Selectable Choice ......................... --&gt;
+
+&lt;!ENTITY % option.element  "INCLUDE" &gt;
+&lt;![%option.element;[
+&lt;!ENTITY % option.content  "( #PCDATA )" &gt;
+&lt;!ELEMENT %option.qname;  %option.content; &gt;
+&lt;!-- end of option.element --&gt;]]&gt;
+
+&lt;!ENTITY % option.attlist  "INCLUDE" &gt;
+&lt;![%option.attlist;[
+&lt;!ATTLIST %option.qname;
+      %Common.attrib;
+      selected     ( selected )             #IMPLIED
+      disabled     ( disabled )             #IMPLIED
+      label        %Text.datatype;          #IMPLIED
+      value        CDATA                    #IMPLIED
+&gt;
+&lt;!-- end of option.attlist --&gt;]]&gt;
+
+&lt;!-- textarea: Multi-Line Text Field ................... --&gt;
+
+&lt;!ENTITY % textarea.element  "INCLUDE" &gt;
+&lt;![%textarea.element;[
+&lt;!ENTITY % textarea.content  "( #PCDATA )" &gt;
+&lt;!ELEMENT %textarea.qname;  %textarea.content; &gt;
+&lt;!-- end of textarea.element --&gt;]]&gt;
+
+&lt;!ENTITY % textarea.attlist  "INCLUDE" &gt;
+&lt;![%textarea.attlist;[
+&lt;!ATTLIST %textarea.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      rows         %Number.datatype;        #REQUIRED
+      cols         %Number.datatype;        #REQUIRED
+      disabled     ( disabled )             #IMPLIED
+      readonly     ( readonly )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+      inputmode    CDATA                    #IMPLIED
+&gt;
+&lt;!-- end of textarea.attlist --&gt;]]&gt;
+
+&lt;!-- fieldset: Form Control Group ...................... --&gt;
+
+&lt;!-- #PCDATA is to solve the mixed content problem,
+     per specification only whitespace is allowed
+--&gt;
+
+&lt;!ENTITY % fieldset.element  "INCLUDE" &gt;
+&lt;![%fieldset.element;[
+&lt;!ENTITY % fieldset.content
+     "( #PCDATA | %legend.qname; | %Flow.mix; )*"
+&gt;
+&lt;!ELEMENT %fieldset.qname;  %fieldset.content; &gt;
+&lt;!-- end of fieldset.element --&gt;]]&gt;
+
+&lt;!ENTITY % fieldset.attlist  "INCLUDE" &gt;
+&lt;![%fieldset.attlist;[
+&lt;!ATTLIST %fieldset.qname;
+      %Common.attrib;
+&gt;
+&lt;!-- end of fieldset.attlist --&gt;]]&gt;
+
+&lt;!-- legend: Fieldset Legend ........................... --&gt;
+
+&lt;!ENTITY % legend.element  "INCLUDE" &gt;
+&lt;![%legend.element;[
+&lt;!ENTITY % legend.content
+     "( #PCDATA | %Inline.mix; )*"
+&gt;
+&lt;!ELEMENT %legend.qname;  %legend.content; &gt;
+&lt;!-- end of legend.element --&gt;]]&gt;
+
+&lt;!ENTITY % legend.attlist  "INCLUDE" &gt;
+&lt;![%legend.attlist;[
+&lt;!ATTLIST %legend.qname;
+      %Common.attrib;
+      accesskey    %Character.datatype;     #IMPLIED
+&gt;
+&lt;!-- end of legend.attlist --&gt;]]&gt;
+
+&lt;!-- button: Push Button ............................... --&gt;
+
+&lt;!ENTITY % button.element  "INCLUDE" &gt;
+&lt;![%button.element;[
+&lt;!ENTITY % button.content
+     "( #PCDATA
+      | %BlkNoForm.mix;
+      | %InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %I18n.class;
+      %InlSpecial.class;
+      %Inline.extra; )*"
+&gt;
+&lt;!ELEMENT %button.qname;  %button.content; &gt;
+&lt;!-- end of button.element --&gt;]]&gt;
+
+&lt;!ENTITY % button.attlist  "INCLUDE" &gt;
+&lt;![%button.attlist;[
+&lt;!ATTLIST %button.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      value        CDATA                    #IMPLIED
+      type         ( button | submit | reset ) 'submit'
+      disabled     ( disabled )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+&gt;
+&lt;!-- end of button.attlist --&gt;]]&gt;
+
+&lt;!-- end of xhtml-form-1.mod --&gt;
+</PRE></BODY></HTML>
\ No newline at end of file
diff --git a/xml/impl/resources/standardSchemas/xhtml-special.ent b/xml/impl/resources/standardSchemas/xhtml-special.ent
new file mode 100644
index 0000000..ca358b2
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-special.ent
@@ -0,0 +1,80 @@
+<!-- Special characters for XHTML -->
+
+<!-- Character entity set. Typical invocation:
+     <!ENTITY % HTMLspecial PUBLIC
+        "-//W3C//ENTITIES Special for XHTML//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+     %HTMLspecial;
+-->
+
+<!-- Portions (C) International Organization for Standardization 1986:
+     Permission to copy in any form is granted for use with
+     conforming SGML systems and applications as defined in
+     ISO 8879, provided this notice is included in all copies.
+-->
+
+<!-- Relevant ISO entity set is given unless names are newly introduced.
+     New names (i.e., not in ISO 8879 list) do not clash with any
+     existing ISO 8879 entity names. ISO 10646 character numbers
+     are given for each character, in hex. values are decimal
+     conversions of the ISO 10646 values and refer to the document
+     character set. Names are Unicode names. 
+-->
+
+<!-- C0 Controls and Basic Latin -->
+<!ENTITY quot    "&#34;"> <!--  quotation mark, U+0022 ISOnum -->
+<!ENTITY amp     "&#38;#38;"> <!--  ampersand, U+0026 ISOnum -->
+<!ENTITY lt      "&#38;#60;"> <!--  less-than sign, U+003C ISOnum -->
+<!ENTITY gt      "&#62;"> <!--  greater-than sign, U+003E ISOnum -->
+<!ENTITY apos	 "&#39;"> <!--  apostrophe = APL quote, U+0027 ISOnum -->
+
+<!-- Latin Extended-A -->
+<!ENTITY OElig   "&#338;"> <!--  latin capital ligature OE,
+                                    U+0152 ISOlat2 -->
+<!ENTITY oelig   "&#339;"> <!--  latin small ligature oe, U+0153 ISOlat2 -->
+<!-- ligature is a misnomer, this is a separate character in some languages -->
+<!ENTITY Scaron  "&#352;"> <!--  latin capital letter S with caron,
+                                    U+0160 ISOlat2 -->
+<!ENTITY scaron  "&#353;"> <!--  latin small letter s with caron,
+                                    U+0161 ISOlat2 -->
+<!ENTITY Yuml    "&#376;"> <!--  latin capital letter Y with diaeresis,
+                                    U+0178 ISOlat2 -->
+
+<!-- Spacing Modifier Letters -->
+<!ENTITY circ    "&#710;"> <!--  modifier letter circumflex accent,
+                                    U+02C6 ISOpub -->
+<!ENTITY tilde   "&#732;"> <!--  small tilde, U+02DC ISOdia -->
+
+<!-- General Punctuation -->
+<!ENTITY ensp    "&#8194;"> <!-- en space, U+2002 ISOpub -->
+<!ENTITY emsp    "&#8195;"> <!-- em space, U+2003 ISOpub -->
+<!ENTITY thinsp  "&#8201;"> <!-- thin space, U+2009 ISOpub -->
+<!ENTITY zwnj    "&#8204;"> <!-- zero width non-joiner,
+                                    U+200C NEW RFC 2070 -->
+<!ENTITY zwj     "&#8205;"> <!-- zero width joiner, U+200D NEW RFC 2070 -->
+<!ENTITY lrm     "&#8206;"> <!-- left-to-right mark, U+200E NEW RFC 2070 -->
+<!ENTITY rlm     "&#8207;"> <!-- right-to-left mark, U+200F NEW RFC 2070 -->
+<!ENTITY ndash   "&#8211;"> <!-- en dash, U+2013 ISOpub -->
+<!ENTITY mdash   "&#8212;"> <!-- em dash, U+2014 ISOpub -->
+<!ENTITY lsquo   "&#8216;"> <!-- left single quotation mark,
+                                    U+2018 ISOnum -->
+<!ENTITY rsquo   "&#8217;"> <!-- right single quotation mark,
+                                    U+2019 ISOnum -->
+<!ENTITY sbquo   "&#8218;"> <!-- single low-9 quotation mark, U+201A NEW -->
+<!ENTITY ldquo   "&#8220;"> <!-- left double quotation mark,
+                                    U+201C ISOnum -->
+<!ENTITY rdquo   "&#8221;"> <!-- right double quotation mark,
+                                    U+201D ISOnum -->
+<!ENTITY bdquo   "&#8222;"> <!-- double low-9 quotation mark, U+201E NEW -->
+<!ENTITY dagger  "&#8224;"> <!-- dagger, U+2020 ISOpub -->
+<!ENTITY Dagger  "&#8225;"> <!-- double dagger, U+2021 ISOpub -->
+<!ENTITY permil  "&#8240;"> <!-- per mille sign, U+2030 ISOtech -->
+<!ENTITY lsaquo  "&#8249;"> <!-- single left-pointing angle quotation mark,
+                                    U+2039 ISO proposed -->
+<!-- lsaquo is proposed but not yet ISO standardized -->
+<!ENTITY rsaquo  "&#8250;"> <!-- single right-pointing angle quotation mark,
+                                    U+203A ISO proposed -->
+<!-- rsaquo is proposed but not yet ISO standardized -->
+
+<!-- Currency Symbols -->
+<!ENTITY euro   "&#8364;"> <!--  euro sign, U+20AC NEW -->
diff --git a/xml/impl/resources/standardSchemas/xhtml-symbol.ent b/xml/impl/resources/standardSchemas/xhtml-symbol.ent
new file mode 100644
index 0000000..63c2abf
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml-symbol.ent
@@ -0,0 +1,237 @@
+<!-- Mathematical, Greek and Symbolic characters for XHTML -->
+
+<!-- Character entity set. Typical invocation:
+     <!ENTITY % HTMLsymbol PUBLIC
+        "-//W3C//ENTITIES Symbols for XHTML//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+     %HTMLsymbol;
+-->
+
+<!-- Portions (C) International Organization for Standardization 1986:
+     Permission to copy in any form is granted for use with
+     conforming SGML systems and applications as defined in
+     ISO 8879, provided this notice is included in all copies.
+-->
+
+<!-- Relevant ISO entity set is given unless names are newly introduced.
+     New names (i.e., not in ISO 8879 list) do not clash with any
+     existing ISO 8879 entity names. ISO 10646 character numbers
+     are given for each character, in hex. values are decimal
+     conversions of the ISO 10646 values and refer to the document
+     character set. Names are Unicode names. 
+-->
+
+<!-- Latin Extended-B -->
+<!ENTITY fnof     "&#402;"> <!-- latin small letter f with hook = function
+                                    = florin, U+0192 ISOtech -->
+
+<!-- Greek -->
+<!ENTITY Alpha    "&#913;"> <!-- greek capital letter alpha, U+0391 -->
+<!ENTITY Beta     "&#914;"> <!-- greek capital letter beta, U+0392 -->
+<!ENTITY Gamma    "&#915;"> <!-- greek capital letter gamma,
+                                    U+0393 ISOgrk3 -->
+<!ENTITY Delta    "&#916;"> <!-- greek capital letter delta,
+                                    U+0394 ISOgrk3 -->
+<!ENTITY Epsilon  "&#917;"> <!-- greek capital letter epsilon, U+0395 -->
+<!ENTITY Zeta     "&#918;"> <!-- greek capital letter zeta, U+0396 -->
+<!ENTITY Eta      "&#919;"> <!-- greek capital letter eta, U+0397 -->
+<!ENTITY Theta    "&#920;"> <!-- greek capital letter theta,
+                                    U+0398 ISOgrk3 -->
+<!ENTITY Iota     "&#921;"> <!-- greek capital letter iota, U+0399 -->
+<!ENTITY Kappa    "&#922;"> <!-- greek capital letter kappa, U+039A -->
+<!ENTITY Lambda   "&#923;"> <!-- greek capital letter lamda,
+                                    U+039B ISOgrk3 -->
+<!ENTITY Mu       "&#924;"> <!-- greek capital letter mu, U+039C -->
+<!ENTITY Nu       "&#925;"> <!-- greek capital letter nu, U+039D -->
+<!ENTITY Xi       "&#926;"> <!-- greek capital letter xi, U+039E ISOgrk3 -->
+<!ENTITY Omicron  "&#927;"> <!-- greek capital letter omicron, U+039F -->
+<!ENTITY Pi       "&#928;"> <!-- greek capital letter pi, U+03A0 ISOgrk3 -->
+<!ENTITY Rho      "&#929;"> <!-- greek capital letter rho, U+03A1 -->
+<!-- there is no Sigmaf, and no U+03A2 character either -->
+<!ENTITY Sigma    "&#931;"> <!-- greek capital letter sigma,
+                                    U+03A3 ISOgrk3 -->
+<!ENTITY Tau      "&#932;"> <!-- greek capital letter tau, U+03A4 -->
+<!ENTITY Upsilon  "&#933;"> <!-- greek capital letter upsilon,
+                                    U+03A5 ISOgrk3 -->
+<!ENTITY Phi      "&#934;"> <!-- greek capital letter phi,
+                                    U+03A6 ISOgrk3 -->
+<!ENTITY Chi      "&#935;"> <!-- greek capital letter chi, U+03A7 -->
+<!ENTITY Psi      "&#936;"> <!-- greek capital letter psi,
+                                    U+03A8 ISOgrk3 -->
+<!ENTITY Omega    "&#937;"> <!-- greek capital letter omega,
+                                    U+03A9 ISOgrk3 -->
+
+<!ENTITY alpha    "&#945;"> <!-- greek small letter alpha,
+                                    U+03B1 ISOgrk3 -->
+<!ENTITY beta     "&#946;"> <!-- greek small letter beta, U+03B2 ISOgrk3 -->
+<!ENTITY gamma    "&#947;"> <!-- greek small letter gamma,
+                                    U+03B3 ISOgrk3 -->
+<!ENTITY delta    "&#948;"> <!-- greek small letter delta,
+                                    U+03B4 ISOgrk3 -->
+<!ENTITY epsilon  "&#949;"> <!-- greek small letter epsilon,
+                                    U+03B5 ISOgrk3 -->
+<!ENTITY zeta     "&#950;"> <!-- greek small letter zeta, U+03B6 ISOgrk3 -->
+<!ENTITY eta      "&#951;"> <!-- greek small letter eta, U+03B7 ISOgrk3 -->
+<!ENTITY theta    "&#952;"> <!-- greek small letter theta,
+                                    U+03B8 ISOgrk3 -->
+<!ENTITY iota     "&#953;"> <!-- greek small letter iota, U+03B9 ISOgrk3 -->
+<!ENTITY kappa    "&#954;"> <!-- greek small letter kappa,
+                                    U+03BA ISOgrk3 -->
+<!ENTITY lambda   "&#955;"> <!-- greek small letter lamda,
+                                    U+03BB ISOgrk3 -->
+<!ENTITY mu       "&#956;"> <!-- greek small letter mu, U+03BC ISOgrk3 -->
+<!ENTITY nu       "&#957;"> <!-- greek small letter nu, U+03BD ISOgrk3 -->
+<!ENTITY xi       "&#958;"> <!-- greek small letter xi, U+03BE ISOgrk3 -->
+<!ENTITY omicron  "&#959;"> <!-- greek small letter omicron, U+03BF NEW -->
+<!ENTITY pi       "&#960;"> <!-- greek small letter pi, U+03C0 ISOgrk3 -->
+<!ENTITY rho      "&#961;"> <!-- greek small letter rho, U+03C1 ISOgrk3 -->
+<!ENTITY sigmaf   "&#962;"> <!-- greek small letter final sigma,
+                                    U+03C2 ISOgrk3 -->
+<!ENTITY sigma    "&#963;"> <!-- greek small letter sigma,
+                                    U+03C3 ISOgrk3 -->
+<!ENTITY tau      "&#964;"> <!-- greek small letter tau, U+03C4 ISOgrk3 -->
+<!ENTITY upsilon  "&#965;"> <!-- greek small letter upsilon,
+                                    U+03C5 ISOgrk3 -->
+<!ENTITY phi      "&#966;"> <!-- greek small letter phi, U+03C6 ISOgrk3 -->
+<!ENTITY chi      "&#967;"> <!-- greek small letter chi, U+03C7 ISOgrk3 -->
+<!ENTITY psi      "&#968;"> <!-- greek small letter psi, U+03C8 ISOgrk3 -->
+<!ENTITY omega    "&#969;"> <!-- greek small letter omega,
+                                    U+03C9 ISOgrk3 -->
+<!ENTITY thetasym "&#977;"> <!-- greek theta symbol,
+                                    U+03D1 NEW -->
+<!ENTITY upsih    "&#978;"> <!-- greek upsilon with hook symbol,
+                                    U+03D2 NEW -->
+<!ENTITY piv      "&#982;"> <!-- greek pi symbol, U+03D6 ISOgrk3 -->
+
+<!-- General Punctuation -->
+<!ENTITY bull     "&#8226;"> <!-- bullet = black small circle,
+                                     U+2022 ISOpub  -->
+<!-- bullet is NOT the same as bullet operator, U+2219 -->
+<!ENTITY hellip   "&#8230;"> <!-- horizontal ellipsis = three dot leader,
+                                     U+2026 ISOpub  -->
+<!ENTITY prime    "&#8242;"> <!-- prime = minutes = feet, U+2032 ISOtech -->
+<!ENTITY Prime    "&#8243;"> <!-- double prime = seconds = inches,
+                                     U+2033 ISOtech -->
+<!ENTITY oline    "&#8254;"> <!-- overline = spacing overscore,
+                                     U+203E NEW -->
+<!ENTITY frasl    "&#8260;"> <!-- fraction slash, U+2044 NEW -->
+
+<!-- Letterlike Symbols -->
+<!ENTITY weierp   "&#8472;"> <!-- script capital P = power set
+                                     = Weierstrass p, U+2118 ISOamso -->
+<!ENTITY image    "&#8465;"> <!-- black-letter capital I = imaginary part,
+                                     U+2111 ISOamso -->
+<!ENTITY real     "&#8476;"> <!-- black-letter capital R = real part symbol,
+                                     U+211C ISOamso -->
+<!ENTITY trade    "&#8482;"> <!-- trade mark sign, U+2122 ISOnum -->
+<!ENTITY alefsym  "&#8501;"> <!-- alef symbol = first transfinite cardinal,
+                                     U+2135 NEW -->
+<!-- alef symbol is NOT the same as hebrew letter alef,
+     U+05D0 although the same glyph could be used to depict both characters -->
+
+<!-- Arrows -->
+<!ENTITY larr     "&#8592;"> <!-- leftwards arrow, U+2190 ISOnum -->
+<!ENTITY uarr     "&#8593;"> <!-- upwards arrow, U+2191 ISOnum-->
+<!ENTITY rarr     "&#8594;"> <!-- rightwards arrow, U+2192 ISOnum -->
+<!ENTITY darr     "&#8595;"> <!-- downwards arrow, U+2193 ISOnum -->
+<!ENTITY harr     "&#8596;"> <!-- left right arrow, U+2194 ISOamsa -->
+<!ENTITY crarr    "&#8629;"> <!-- downwards arrow with corner leftwards
+                                     = carriage return, U+21B5 NEW -->
+<!ENTITY lArr     "&#8656;"> <!-- leftwards double arrow, U+21D0 ISOtech -->
+<!-- Unicode does not say that lArr is the same as the 'is implied by' arrow
+    but also does not have any other character for that function. So lArr can
+    be used for 'is implied by' as ISOtech suggests -->
+<!ENTITY uArr     "&#8657;"> <!-- upwards double arrow, U+21D1 ISOamsa -->
+<!ENTITY rArr     "&#8658;"> <!-- rightwards double arrow,
+                                     U+21D2 ISOtech -->
+<!-- Unicode does not say this is the 'implies' character but does not have 
+     another character with this function so rArr can be used for 'implies'
+     as ISOtech suggests -->
+<!ENTITY dArr     "&#8659;"> <!-- downwards double arrow, U+21D3 ISOamsa -->
+<!ENTITY hArr     "&#8660;"> <!-- left right double arrow,
+                                     U+21D4 ISOamsa -->
+
+<!-- Mathematical Operators -->
+<!ENTITY forall   "&#8704;"> <!-- for all, U+2200 ISOtech -->
+<!ENTITY part     "&#8706;"> <!-- partial differential, U+2202 ISOtech  -->
+<!ENTITY exist    "&#8707;"> <!-- there exists, U+2203 ISOtech -->
+<!ENTITY empty    "&#8709;"> <!-- empty set = null set, U+2205 ISOamso -->
+<!ENTITY nabla    "&#8711;"> <!-- nabla = backward difference,
+                                     U+2207 ISOtech -->
+<!ENTITY isin     "&#8712;"> <!-- element of, U+2208 ISOtech -->
+<!ENTITY notin    "&#8713;"> <!-- not an element of, U+2209 ISOtech -->
+<!ENTITY ni       "&#8715;"> <!-- contains as member, U+220B ISOtech -->
+<!ENTITY prod     "&#8719;"> <!-- n-ary product = product sign,
+                                     U+220F ISOamsb -->
+<!-- prod is NOT the same character as U+03A0 'greek capital letter pi' though
+     the same glyph might be used for both -->
+<!ENTITY sum      "&#8721;"> <!-- n-ary summation, U+2211 ISOamsb -->
+<!-- sum is NOT the same character as U+03A3 'greek capital letter sigma'
+     though the same glyph might be used for both -->
+<!ENTITY minus    "&#8722;"> <!-- minus sign, U+2212 ISOtech -->
+<!ENTITY lowast   "&#8727;"> <!-- asterisk operator, U+2217 ISOtech -->
+<!ENTITY radic    "&#8730;"> <!-- square root = radical sign,
+                                     U+221A ISOtech -->
+<!ENTITY prop     "&#8733;"> <!-- proportional to, U+221D ISOtech -->
+<!ENTITY infin    "&#8734;"> <!-- infinity, U+221E ISOtech -->
+<!ENTITY ang      "&#8736;"> <!-- angle, U+2220 ISOamso -->
+<!ENTITY and      "&#8743;"> <!-- logical and = wedge, U+2227 ISOtech -->
+<!ENTITY or       "&#8744;"> <!-- logical or = vee, U+2228 ISOtech -->
+<!ENTITY cap      "&#8745;"> <!-- intersection = cap, U+2229 ISOtech -->
+<!ENTITY cup      "&#8746;"> <!-- union = cup, U+222A ISOtech -->
+<!ENTITY int      "&#8747;"> <!-- integral, U+222B ISOtech -->
+<!ENTITY there4   "&#8756;"> <!-- therefore, U+2234 ISOtech -->
+<!ENTITY sim      "&#8764;"> <!-- tilde operator = varies with = similar to,
+                                     U+223C ISOtech -->
+<!-- tilde operator is NOT the same character as the tilde, U+007E,
+     although the same glyph might be used to represent both  -->
+<!ENTITY cong     "&#8773;"> <!-- approximately equal to, U+2245 ISOtech -->
+<!ENTITY asymp    "&#8776;"> <!-- almost equal to = asymptotic to,
+                                     U+2248 ISOamsr -->
+<!ENTITY ne       "&#8800;"> <!-- not equal to, U+2260 ISOtech -->
+<!ENTITY equiv    "&#8801;"> <!-- identical to, U+2261 ISOtech -->
+<!ENTITY le       "&#8804;"> <!-- less-than or equal to, U+2264 ISOtech -->
+<!ENTITY ge       "&#8805;"> <!-- greater-than or equal to,
+                                     U+2265 ISOtech -->
+<!ENTITY sub      "&#8834;"> <!-- subset of, U+2282 ISOtech -->
+<!ENTITY sup      "&#8835;"> <!-- superset of, U+2283 ISOtech -->
+<!ENTITY nsub     "&#8836;"> <!-- not a subset of, U+2284 ISOamsn -->
+<!ENTITY sube     "&#8838;"> <!-- subset of or equal to, U+2286 ISOtech -->
+<!ENTITY supe     "&#8839;"> <!-- superset of or equal to,
+                                     U+2287 ISOtech -->
+<!ENTITY oplus    "&#8853;"> <!-- circled plus = direct sum,
+                                     U+2295 ISOamsb -->
+<!ENTITY otimes   "&#8855;"> <!-- circled times = vector product,
+                                     U+2297 ISOamsb -->
+<!ENTITY perp     "&#8869;"> <!-- up tack = orthogonal to = perpendicular,
+                                     U+22A5 ISOtech -->
+<!ENTITY sdot     "&#8901;"> <!-- dot operator, U+22C5 ISOamsb -->
+<!-- dot operator is NOT the same character as U+00B7 middle dot -->
+
+<!-- Miscellaneous Technical -->
+<!ENTITY lceil    "&#8968;"> <!-- left ceiling = APL upstile,
+                                     U+2308 ISOamsc  -->
+<!ENTITY rceil    "&#8969;"> <!-- right ceiling, U+2309 ISOamsc  -->
+<!ENTITY lfloor   "&#8970;"> <!-- left floor = APL downstile,
+                                     U+230A ISOamsc  -->
+<!ENTITY rfloor   "&#8971;"> <!-- right floor, U+230B ISOamsc  -->
+<!ENTITY lang     "&#9001;"> <!-- left-pointing angle bracket = bra,
+                                     U+2329 ISOtech -->
+<!-- lang is NOT the same character as U+003C 'less than sign' 
+     or U+2039 'single left-pointing angle quotation mark' -->
+<!ENTITY rang     "&#9002;"> <!-- right-pointing angle bracket = ket,
+                                     U+232A ISOtech -->
+<!-- rang is NOT the same character as U+003E 'greater than sign' 
+     or U+203A 'single right-pointing angle quotation mark' -->
+
+<!-- Geometric Shapes -->
+<!ENTITY loz      "&#9674;"> <!-- lozenge, U+25CA ISOpub -->
+
+<!-- Miscellaneous Symbols -->
+<!ENTITY spades   "&#9824;"> <!-- black spade suit, U+2660 ISOpub -->
+<!-- black here seems to mean filled as opposed to hollow -->
+<!ENTITY clubs    "&#9827;"> <!-- black club suit = shamrock,
+                                     U+2663 ISOpub -->
+<!ENTITY hearts   "&#9829;"> <!-- black heart suit = valentine,
+                                     U+2665 ISOpub -->
+<!ENTITY diams    "&#9830;"> <!-- black diamond suit, U+2666 ISOpub -->
diff --git a/xml/impl/resources/standardSchemas/xhtml.dtd b/xml/impl/resources/standardSchemas/xhtml.dtd
new file mode 100644
index 0000000..9e5ccc9
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml.dtd
@@ -0,0 +1,1201 @@
+<!--
+   Extensible HTML version 1.0 Transitional DTD
+
+   This is the same as HTML 4 Transitional except for
+   changes due to the differences between XML and SGML.
+
+   Namespace = http://www.w3.org/1999/xhtml
+
+   For further information, see: http://www.w3.org/TR/xhtml1
+
+   Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+   All Rights Reserved.
+
+   This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+   PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+   SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+
+   $Revision: 1.1 $
+   $Date: 2004/06/09 12:44:55 $
+
+-->
+
+<!--================ Character mnemonic entities =========================-->
+
+<!ENTITY % HTMLlat1 PUBLIC
+   "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+   "xhtml-lat1.ent">
+%HTMLlat1;
+
+<!ENTITY % HTMLsymbol PUBLIC
+   "-//W3C//ENTITIES Symbols for XHTML//EN"
+   "xhtml-symbol.ent">
+%HTMLsymbol;
+
+<!ENTITY % HTMLspecial PUBLIC
+   "-//W3C//ENTITIES Special for XHTML//EN"
+   "xhtml-special.ent">
+%HTMLspecial;
+
+<!--================== Imported Names ====================================-->
+
+<!ENTITY % ContentType "CDATA">
+    <!-- media type, as per [RFC2045] -->
+
+<!ENTITY % ContentTypes "CDATA">
+    <!-- comma-separated list of media types, as per [RFC2045] -->
+
+<!ENTITY % Charset "CDATA">
+    <!-- a character encoding, as per [RFC2045] -->
+
+<!ENTITY % Charsets "CDATA">
+    <!-- a space separated list of character encodings, as per [RFC2045] -->
+
+<!ENTITY % LanguageCode "NMTOKEN">
+    <!-- a language code, as per [RFC3066] -->
+
+<!ENTITY % Character "CDATA">
+    <!-- a single character, as per section 2.2 of [XML] -->
+
+<!ENTITY % Number "CDATA">
+    <!-- one or more digits -->
+
+<!ENTITY % LinkTypes "CDATA">
+    <!-- space-separated list of link types -->
+
+<!ENTITY % MediaDesc "CDATA">
+    <!-- single or comma-separated list of media descriptors -->
+
+<!ENTITY % URI "CDATA">
+    <!-- a Uniform Resource Identifier, see [RFC2396] -->
+
+<!ENTITY % UriList "CDATA">
+    <!-- a space separated list of Uniform Resource Identifiers -->
+
+<!ENTITY % Datetime "CDATA">
+    <!-- date and time information. ISO date format -->
+
+<!ENTITY % Script "CDATA">
+    <!-- script expression -->
+
+<!ENTITY % StyleSheet "CDATA">
+    <!-- style sheet data -->
+
+<!ENTITY % Text "CDATA">
+    <!-- used for titles etc. -->
+
+<!ENTITY % FrameTarget "NMTOKEN">
+    <!-- render in this frame -->
+
+<!ENTITY % Length "CDATA">
+    <!-- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % MultiLength "CDATA">
+    <!-- pixel, percentage, or relative -->
+
+<!ENTITY % Pixels "CDATA">
+    <!-- integer representing length in pixels -->
+
+<!-- these are used for image maps -->
+
+<!ENTITY % Shape "(rect|circle|poly|default)">
+
+<!ENTITY % Coords "CDATA">
+    <!-- comma separated list of lengths -->
+
+<!-- used for object, applet, img, input and iframe -->
+<!ENTITY % ImgAlign "(top|middle|bottom|left|right)">
+
+<!-- a color using sRGB: #RRGGBB as Hex values -->
+<!ENTITY % Color "CDATA">
+
+<!-- There are also 16 widely known color names with their sRGB values:
+
+    Black  = #000000    Green  = #008000
+    Silver = #C0C0C0    Lime   = #00FF00
+    Gray   = #808080    Olive  = #808000
+    White  = #FFFFFF    Yellow = #FFFF00
+    Maroon = #800000    Navy   = #000080
+    Red    = #FF0000    Blue   = #0000FF
+    Purple = #800080    Teal   = #008080
+    Fuchsia= #FF00FF    Aqua   = #00FFFF
+-->
+
+<!--=================== Generic Attributes ===============================-->
+
+<!-- core attributes common to most elements
+  id       document-wide unique id
+  class    space separated list of classes
+  style    associated style info
+  title    advisory title/amplification
+-->
+<!ENTITY % coreattrs
+ "id          ID             #IMPLIED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED"
+  >
+
+<!-- internationalization attributes
+  lang        language code (backwards compatible)
+  xml:lang    language code (as per XML 1.0 spec)
+  dir         direction for weak/neutral text
+-->
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #IMPLIED"
+  >
+
+<!-- attributes for common UI events
+  onclick     a pointer button was clicked
+  ondblclick  a pointer button was double clicked
+  onmousedown a pointer button was pressed down
+  onmouseup   a pointer button was released
+  onmousemove a pointer was moved onto the element
+  onmouseout  a pointer was moved away from the element
+  onkeypress  a key was pressed and released
+  onkeydown   a key was pressed down
+  onkeyup     a key was released
+-->
+<!ENTITY % events
+ "onclick     %Script;       #IMPLIED
+  ondblclick  %Script;       #IMPLIED
+  onmousedown %Script;       #IMPLIED
+  onmouseup   %Script;       #IMPLIED
+  onmouseover %Script;       #IMPLIED
+  onmousemove %Script;       #IMPLIED
+  onmouseout  %Script;       #IMPLIED
+  onkeypress  %Script;       #IMPLIED
+  onkeydown   %Script;       #IMPLIED
+  onkeyup     %Script;       #IMPLIED"
+  >
+
+<!-- attributes for elements that can get the focus
+  accesskey   accessibility key character
+  tabindex    position in tabbing order
+  onfocus     the element got the focus
+  onblur      the element lost the focus
+-->
+<!ENTITY % focus
+ "accesskey   %Character;    #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED"
+  >
+
+<!ENTITY % attrs "%coreattrs; %i18n; %events;">
+
+<!-- text alignment for p, div, h1-h6. The default is
+     align="left" for ltr headings, "right" for rtl -->
+
+<!ENTITY % TextAlign "align (left|center|right|justify) #IMPLIED">
+
+<!--=================== Text Elements ====================================-->
+
+<!ENTITY % special.extra
+   "object | applet | img | map | iframe">
+
+<!ENTITY % special.basic
+	"br | span | bdo">
+
+<!ENTITY % special
+   "%special.basic; | %special.extra;">
+
+<!ENTITY % fontstyle.extra "big | small | font | basefont">
+
+<!ENTITY % fontstyle.basic "tt | i | b | u
+                      | s | strike ">
+
+<!ENTITY % fontstyle "%fontstyle.basic; | %fontstyle.extra;">
+
+<!ENTITY % phrase.extra "sub | sup">
+<!ENTITY % phrase.basic "em | strong | dfn | code | q |
+                   samp | kbd | var | cite | abbr | acronym">
+
+<!ENTITY % phrase "%phrase.basic; | %phrase.extra;">
+
+<!ENTITY % inline.forms "input | select | textarea | label | button">
+
+<!-- these can occur at block or inline level -->
+<!ENTITY % misc.inline "ins | del | script">
+
+<!-- these can only occur at block level -->
+<!ENTITY % misc "noscript | %misc.inline;">
+
+<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
+
+<!-- %Inline; covers inline or "text-level" elements -->
+<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
+
+<!--================== Block level elements ==============================-->
+
+<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
+<!ENTITY % lists "ul | ol | dl | menu | dir">
+<!ENTITY % blocktext "pre | hr | blockquote | address | center | noframes">
+
+<!ENTITY % block
+    "p | %heading; | div | %lists; | %blocktext; | isindex |fieldset | table">
+
+<!-- %Flow; mixes block and inline and is used for list items etc. -->
+<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
+
+<!--================== Content models for exclusions =====================-->
+
+<!-- a elements use %Inline; excluding a -->
+
+<!ENTITY % a.content
+   "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
+
+<!-- pre uses %Inline excluding img, object, applet, big, small,
+     font, or basefont -->
+
+<!ENTITY % pre.content
+   "(#PCDATA | a | %special.basic; | %fontstyle.basic; | %phrase.basic; |
+	   %inline.forms; | %misc.inline;)*">
+
+<!-- form uses %Flow; excluding form -->
+
+<!ENTITY % form.content "(#PCDATA | %block; | %inline; | %misc;)*">
+
+<!-- button uses %Flow; but excludes a, form, form controls, iframe -->
+
+<!ENTITY % button.content
+   "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
+      table | br | span | bdo | object | applet | img | map |
+      %fontstyle; | %phrase; | %misc;)*">
+
+<!--================ Document Structure ==================================-->
+
+<!-- the namespace URI designates the document profile -->
+
+<!ELEMENT html (head, body)>
+<!ATTLIST html
+  %i18n;
+  id          ID             #IMPLIED
+  xmlns       %URI;          #FIXED 'http://www.w3.org/1999/xhtml'
+  >
+
+<!--================ Document Head =======================================-->
+
+<!ENTITY % head.misc "(script|style|meta|link|object|isindex)*">
+
+<!-- content model is %head.misc; combined with a single
+     title and an optional base element in any order -->
+
+<!ELEMENT head (%head.misc;,
+     ((title, %head.misc;, (base, %head.misc;)?) |
+      (base, %head.misc;, (title, %head.misc;))))>
+
+<!ATTLIST head
+  %i18n;
+  id          ID             #IMPLIED
+  profile     %URI;          #IMPLIED
+  >
+
+<!-- The title element is not considered part of the flow of text.
+       It should be displayed, for example as the page header or
+       window title. Exactly one title is required per document.
+    -->
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+  %i18n;
+  id          ID             #IMPLIED
+  >
+
+<!-- document base URI -->
+
+<!ELEMENT base EMPTY>
+<!ATTLIST base
+  id          ID             #IMPLIED
+  href        %URI;          #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!-- generic metainformation -->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+  %i18n;
+  id          ID             #IMPLIED
+  http-equiv  CDATA          #IMPLIED
+  name        CDATA          #IMPLIED
+  content     CDATA          #REQUIRED
+  scheme      CDATA          #IMPLIED
+  >
+
+<!--
+  Relationship values can be used in principle:
+
+   a) for document specific toolbars/menus when used
+      with the link element in document head e.g.
+        start, contents, previous, next, index, end, help
+   b) to link to a separate style sheet (rel="stylesheet")
+   c) to make a link to a script (rel="script")
+   d) by stylesheets to control how collections of
+      html nodes are rendered into printed documents
+   e) to make a link to a printable version of this document
+      e.g. a PostScript or PDF version (rel="alternate" media="print")
+-->
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+  %attrs;
+  charset     %Charset;      #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  type        %ContentType;  #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  media       %MediaDesc;    #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!-- style info, which may include CDATA sections -->
+<!ELEMENT style (#PCDATA)>
+<!ATTLIST style
+  %i18n;
+  id          ID             #IMPLIED
+  type        %ContentType;  #REQUIRED
+  media       %MediaDesc;    #IMPLIED
+  title       %Text;         #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- script statements, which may include CDATA sections -->
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+  id          ID             #IMPLIED
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #REQUIRED
+  language    CDATA          #IMPLIED
+  src         %URI;          #IMPLIED
+  defer       (defer)        #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- alternate content container for non script-based rendering -->
+
+<!ELEMENT noscript %Flow;>
+<!ATTLIST noscript
+  %attrs;
+  >
+
+<!--======================= Frames =======================================-->
+
+<!-- inline subwindow -->
+
+<!ELEMENT iframe %Flow;>
+<!ATTLIST iframe
+  %coreattrs;
+  longdesc    %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  src         %URI;          #IMPLIED
+  frameborder (1|0)          "1"
+  marginwidth %Pixels;       #IMPLIED
+  marginheight %Pixels;      #IMPLIED
+  scrolling   (yes|no|auto)  "auto"
+  align       %ImgAlign;     #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  >
+
+<!-- alternate content container for non frame-based rendering -->
+
+<!ELEMENT noframes %Flow;>
+<!ATTLIST noframes
+  %attrs;
+  >
+
+<!--=================== Document Body ====================================-->
+
+<!ELEMENT body %Flow;>
+<!ATTLIST body
+  %attrs;
+  onload      %Script;       #IMPLIED
+  onunload    %Script;       #IMPLIED
+  background  %URI;          #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  text        %Color;        #IMPLIED
+  link        %Color;        #IMPLIED
+  vlink       %Color;        #IMPLIED
+  alink       %Color;        #IMPLIED
+  >
+
+<!ELEMENT div %Flow;>  <!-- generic language/style container -->
+<!ATTLIST div
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Paragraphs =======================================-->
+
+<!ELEMENT p %Inline;>
+<!ATTLIST p
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Headings =========================================-->
+
+<!--
+  There are six levels of headings from h1 (the most important)
+  to h6 (the least important).
+-->
+
+<!ELEMENT h1  %Inline;>
+<!ATTLIST h1
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h2 %Inline;>
+<!ATTLIST h2
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h3 %Inline;>
+<!ATTLIST h3
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h4 %Inline;>
+<!ATTLIST h4
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h5 %Inline;>
+<!ATTLIST h5
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h6 %Inline;>
+<!ATTLIST h6
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Lists ============================================-->
+
+<!-- Unordered list bullet styles -->
+
+<!ENTITY % ULStyle "(disc|square|circle)">
+
+<!-- Unordered list -->
+
+<!ELEMENT ul (li)+>
+<!ATTLIST ul
+  %attrs;
+  type        %ULStyle;     #IMPLIED
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- Ordered list numbering style
+
+    1   arabic numbers      1, 2, 3, ...
+    a   lower alpha         a, b, c, ...
+    A   upper alpha         A, B, C, ...
+    i   lower roman         i, ii, iii, ...
+    I   upper roman         I, II, III, ...
+
+    The style is applied to the sequence number which by default
+    is reset to 1 for the first list item in an ordered list.
+-->
+<!ENTITY % OLStyle "CDATA">
+
+<!-- Ordered (numbered) list -->
+
+<!ELEMENT ol (li)+>
+<!ATTLIST ol
+  %attrs;
+  type        %OLStyle;      #IMPLIED
+  compact     (compact)      #IMPLIED
+  start       %Number;       #IMPLIED
+  >
+
+<!-- single column list (DEPRECATED) -->
+<!ELEMENT menu (li)+>
+<!ATTLIST menu
+  %attrs;
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- multiple column list (DEPRECATED) -->
+<!ELEMENT dir (li)+>
+<!ATTLIST dir
+  %attrs;
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- LIStyle is constrained to: "(%ULStyle;|%OLStyle;)" -->
+<!ENTITY % LIStyle "CDATA">
+
+<!-- list item -->
+
+<!ELEMENT li %Flow;>
+<!ATTLIST li
+  %attrs;
+  type        %LIStyle;      #IMPLIED
+  value       %Number;       #IMPLIED
+  >
+
+<!-- definition lists - dt for term, dd for its definition -->
+
+<!ELEMENT dl (dt|dd)+>
+<!ATTLIST dl
+  %attrs;
+  compact     (compact)      #IMPLIED
+  >
+
+<!ELEMENT dt %Inline;>
+<!ATTLIST dt
+  %attrs;
+  >
+
+<!ELEMENT dd %Flow;>
+<!ATTLIST dd
+  %attrs;
+  >
+
+<!--=================== Address ==========================================-->
+
+<!-- information on author -->
+
+<!ELEMENT address (#PCDATA | %inline; | %misc.inline; | p)*>
+<!ATTLIST address
+  %attrs;
+  >
+
+<!--=================== Horizontal Rule ==================================-->
+
+<!ELEMENT hr EMPTY>
+<!ATTLIST hr
+  %attrs;
+  align       (left|center|right) #IMPLIED
+  noshade     (noshade)      #IMPLIED
+  size        %Pixels;       #IMPLIED
+  width       %Length;       #IMPLIED
+  >
+
+<!--=================== Preformatted Text ================================-->
+
+<!-- content is %Inline; excluding
+        "img|object|applet|big|small|sub|sup|font|basefont" -->
+
+<!ELEMENT pre %pre.content;>
+<!ATTLIST pre
+  %attrs;
+  width       %Number;      #IMPLIED
+  xml:space   (preserve)    #FIXED 'preserve'
+  >
+
+<!--=================== Block-like Quotes ================================-->
+
+<!ELEMENT blockquote %Flow;>
+<!ATTLIST blockquote
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!--=================== Text alignment ===================================-->
+
+<!-- center content -->
+<!ELEMENT center %Flow;>
+<!ATTLIST center
+  %attrs;
+  >
+
+<!--=================== Inserted/Deleted Text ============================-->
+
+<!--
+  ins/del are allowed in block and inline content, but its
+  inappropriate to include block content within an ins element
+  occurring in inline content.
+-->
+<!ELEMENT ins %Flow;>
+<!ATTLIST ins
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!ELEMENT del %Flow;>
+<!ATTLIST del
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!--================== The Anchor Element ================================-->
+
+<!-- content is %Inline; except that anchors shouldn't be nested -->
+
+<!ELEMENT a %a.content;>
+<!ATTLIST a
+  %attrs;
+  %focus;
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--===================== Inline Elements ================================-->
+
+<!ELEMENT span %Inline;> <!-- generic language/style container -->
+<!ATTLIST span
+  %attrs;
+  >
+
+<!ELEMENT bdo %Inline;>  <!-- I18N BiDi over-ride -->
+<!ATTLIST bdo
+  %coreattrs;
+  %events;
+  lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #REQUIRED
+  >
+
+<!ELEMENT br EMPTY>   <!-- forced line break -->
+<!ATTLIST br
+  %coreattrs;
+  clear       (left|all|right|none) "none"
+  >
+
+<!ELEMENT em %Inline;>   <!-- emphasis -->
+<!ATTLIST em %attrs;>
+
+<!ELEMENT strong %Inline;>   <!-- strong emphasis -->
+<!ATTLIST strong %attrs;>
+
+<!ELEMENT dfn %Inline;>   <!-- definitional -->
+<!ATTLIST dfn %attrs;>
+
+<!ELEMENT code %Inline;>   <!-- program code -->
+<!ATTLIST code %attrs;>
+
+<!ELEMENT samp %Inline;>   <!-- sample -->
+<!ATTLIST samp %attrs;>
+
+<!ELEMENT kbd %Inline;>  <!-- something user would type -->
+<!ATTLIST kbd %attrs;>
+
+<!ELEMENT var %Inline;>   <!-- variable -->
+<!ATTLIST var %attrs;>
+
+<!ELEMENT cite %Inline;>   <!-- citation -->
+<!ATTLIST cite %attrs;>
+
+<!ELEMENT abbr %Inline;>   <!-- abbreviation -->
+<!ATTLIST abbr %attrs;>
+
+<!ELEMENT acronym %Inline;>   <!-- acronym -->
+<!ATTLIST acronym %attrs;>
+
+<!ELEMENT q %Inline;>   <!-- inlined quote -->
+<!ATTLIST q
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!ELEMENT sub %Inline;> <!-- subscript -->
+<!ATTLIST sub %attrs;>
+
+<!ELEMENT sup %Inline;> <!-- superscript -->
+<!ATTLIST sup %attrs;>
+
+<!ELEMENT tt %Inline;>   <!-- fixed pitch font -->
+<!ATTLIST tt %attrs;>
+
+<!ELEMENT i %Inline;>   <!-- italic font -->
+<!ATTLIST i %attrs;>
+
+<!ELEMENT b %Inline;>   <!-- bold font -->
+<!ATTLIST b %attrs;>
+
+<!ELEMENT big %Inline;>   <!-- bigger font -->
+<!ATTLIST big %attrs;>
+
+<!ELEMENT small %Inline;>   <!-- smaller font -->
+<!ATTLIST small %attrs;>
+
+<!ELEMENT u %Inline;>   <!-- underline -->
+<!ATTLIST u %attrs;>
+
+<!ELEMENT s %Inline;>   <!-- strike-through -->
+<!ATTLIST s %attrs;>
+
+<!ELEMENT strike %Inline;>   <!-- strike-through -->
+<!ATTLIST strike %attrs;>
+
+<!ELEMENT basefont EMPTY>  <!-- base font size -->
+<!ATTLIST basefont
+  id          ID             #IMPLIED
+  size        CDATA          #REQUIRED
+  color       %Color;        #IMPLIED
+  face        CDATA          #IMPLIED
+  >
+
+<!ELEMENT font %Inline;> <!-- local change to font -->
+<!ATTLIST font
+  %coreattrs;
+  %i18n;
+  size        CDATA          #IMPLIED
+  color       %Color;        #IMPLIED
+  face        CDATA          #IMPLIED
+  >
+
+<!--==================== Object ======================================-->
+<!--
+  object is used to embed objects as part of HTML pages.
+  param elements should precede other content. Parameters
+  can also be expressed as attribute/value pairs on the
+  object element itself when brevity is desired.
+-->
+
+<!ELEMENT object (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST object
+  %attrs;
+  declare     (declare)      #IMPLIED
+  classid     %URI;          #IMPLIED
+  codebase    %URI;          #IMPLIED
+  data        %URI;          #IMPLIED
+  type        %ContentType;  #IMPLIED
+  codetype    %ContentType;  #IMPLIED
+  archive     %UriList;      #IMPLIED
+  standby     %Text;         #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  border      %Pixels;       #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!--
+  param is used to supply a named property value.
+  In XML it would seem natural to follow RDF and support an
+  abbreviated syntax where the param elements are replaced
+  by attribute value pairs on the object start tag.
+-->
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+  id          ID             #IMPLIED
+  name        CDATA          #REQUIRED
+  value       CDATA          #IMPLIED
+  valuetype   (data|ref|object) "data"
+  type        %ContentType;  #IMPLIED
+  >
+
+<!--=================== Java applet ==================================-->
+<!--
+  One of code or object attributes must be present.
+  Place param elements before other content.
+-->
+<!ELEMENT applet (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST applet
+  %coreattrs;
+  codebase    %URI;          #IMPLIED
+  archive     CDATA          #IMPLIED
+  code        CDATA          #IMPLIED
+  object      CDATA          #IMPLIED
+  alt         %Text;         #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  width       %Length;       #REQUIRED
+  height      %Length;       #REQUIRED
+  align       %ImgAlign;     #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!--=================== Images ===========================================-->
+
+<!--
+   To avoid accessibility problems for people who aren't
+   able to see the image, you should provide a text
+   description using the alt and longdesc attributes.
+   In addition, avoid the use of server-side image maps.
+-->
+
+<!ELEMENT img EMPTY>
+<!ATTLIST img
+  %attrs;
+  src         %URI;          #REQUIRED
+  alt         %Text;         #REQUIRED
+  name        NMTOKEN        #IMPLIED
+  longdesc    %URI;          #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  ismap       (ismap)        #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  border      %Length;       #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!-- usemap points to a map element which may be in this document
+  or an external document, although the latter is not widely supported -->
+
+<!--================== Client-side image maps ============================-->
+
+<!-- These can be placed in the same document or grouped in a
+     separate document although this isn't yet widely supported -->
+
+<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
+<!ATTLIST map
+  %i18n;
+  %events;
+  id          ID             #REQUIRED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED
+  name        CDATA          #IMPLIED
+  >
+
+<!ELEMENT area EMPTY>
+<!ATTLIST area
+  %attrs;
+  %focus;
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  href        %URI;          #IMPLIED
+  nohref      (nohref)       #IMPLIED
+  alt         %Text;         #REQUIRED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--================ Forms ===============================================-->
+
+<!ELEMENT form %form.content;>   <!-- forms shouldn't be nested -->
+
+<!ATTLIST form
+  %attrs;
+  action      %URI;          #REQUIRED
+  method      (get|post)     "get"
+  name        NMTOKEN        #IMPLIED
+  enctype     %ContentType;  "application/x-www-form-urlencoded"
+  onsubmit    %Script;       #IMPLIED
+  onreset     %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  accept-charset %Charsets;  #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--
+  Each label must not contain more than ONE field
+  Label elements shouldn't be nested.
+-->
+<!ELEMENT label %Inline;>
+<!ATTLIST label
+  %attrs;
+  for         IDREF          #IMPLIED
+  accesskey   %Character;    #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  >
+
+<!ENTITY % InputType
+  "(text | password | checkbox |
+    radio | submit | reset |
+    file | hidden | image | button)"
+   >
+
+<!-- the name attribute is required for all but submit & reset -->
+
+<!ELEMENT input EMPTY>     <!-- form control -->
+<!ATTLIST input
+  %attrs;
+  %focus;
+  type        %InputType;    "text"
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  checked     (checked)      #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  size        CDATA          #IMPLIED
+  maxlength   %Number;       #IMPLIED
+  src         %URI;          #IMPLIED
+  alt         CDATA          #IMPLIED
+  usemap      %URI;          #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  >
+
+<!ELEMENT select (optgroup|option)+>  <!-- option selector -->
+<!ATTLIST select
+  %attrs;
+  name        CDATA          #IMPLIED
+  size        %Number;       #IMPLIED
+  multiple    (multiple)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!ELEMENT optgroup (option)+>   <!-- option group -->
+<!ATTLIST optgroup
+  %attrs;
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #REQUIRED
+  >
+
+<!ELEMENT option (#PCDATA)>     <!-- selectable choice -->
+<!ATTLIST option
+  %attrs;
+  selected    (selected)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #IMPLIED
+  value       CDATA          #IMPLIED
+  >
+
+<!ELEMENT textarea (#PCDATA)>     <!-- multi-line text field -->
+<!ATTLIST textarea
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  rows        %Number;       #REQUIRED
+  cols        %Number;       #REQUIRED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!--
+  The fieldset element is used to group form fields.
+  Only one legend element should occur in the content
+  and if present should only be preceded by whitespace.
+-->
+<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
+<!ATTLIST fieldset
+  %attrs;
+  >
+
+<!ENTITY % LAlign "(top|bottom|left|right)">
+
+<!ELEMENT legend %Inline;>     <!-- fieldset label -->
+<!ATTLIST legend
+  %attrs;
+  accesskey   %Character;    #IMPLIED
+  align       %LAlign;       #IMPLIED
+  >
+
+<!--
+ Content is %Flow; excluding a, form, form controls, iframe
+-->
+<!ELEMENT button %button.content;>  <!-- push button -->
+<!ATTLIST button
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  type        (button|submit|reset) "submit"
+  disabled    (disabled)     #IMPLIED
+  >
+
+<!-- single-line text input control (DEPRECATED) -->
+<!ELEMENT isindex EMPTY>
+<!ATTLIST isindex
+  %coreattrs;
+  %i18n;
+  prompt      %Text;         #IMPLIED
+  >
+
+<!--======================= Tables =======================================-->
+
+<!-- Derived from IETF HTML table standard, see [RFC1942] -->
+
+<!--
+ The border attribute sets the thickness of the frame around the
+ table. The default units are screen pixels.
+
+ The frame attribute specifies which parts of the frame around
+ the table should be rendered. The values are not the same as
+ CALS to avoid a name clash with the valign attribute.
+-->
+<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
+
+<!--
+ The rules attribute defines which rules to draw between cells:
+
+ If rules is absent then assume:
+     "none" if border is absent or border="0" otherwise "all"
+-->
+
+<!ENTITY % TRules "(none | groups | rows | cols | all)">
+
+<!-- horizontal placement of table relative to document -->
+<!ENTITY % TAlign "(left|center|right)">
+
+<!-- horizontal alignment attributes for cell contents
+
+  char        alignment char, e.g. char=':'
+  charoff     offset for alignment char
+-->
+<!ENTITY % cellhalign
+  "align      (left|center|right|justify|char) #IMPLIED
+   char       %Character;    #IMPLIED
+   charoff    %Length;       #IMPLIED"
+  >
+
+<!-- vertical alignment attributes for cell contents -->
+<!ENTITY % cellvalign
+  "valign     (top|middle|bottom|baseline) #IMPLIED"
+  >
+
+<!ELEMENT table
+     (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
+<!ELEMENT caption  %Inline;>
+<!ELEMENT thead    (tr)+>
+<!ELEMENT tfoot    (tr)+>
+<!ELEMENT tbody    (tr)+>
+<!ELEMENT colgroup (col)*>
+<!ELEMENT col      EMPTY>
+<!ELEMENT tr       (th|td)+>
+<!ELEMENT th       %Flow;>
+<!ELEMENT td       %Flow;>
+
+<!ATTLIST table
+  %attrs;
+  summary     %Text;         #IMPLIED
+  width       %Length;       #IMPLIED
+  border      %Pixels;       #IMPLIED
+  frame       %TFrame;       #IMPLIED
+  rules       %TRules;       #IMPLIED
+  cellspacing %Length;       #IMPLIED
+  cellpadding %Length;       #IMPLIED
+  align       %TAlign;       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  >
+
+<!ENTITY % CAlign "(top|bottom|left|right)">
+
+<!ATTLIST caption
+  %attrs;
+  align       %CAlign;       #IMPLIED
+  >
+
+<!--
+colgroup groups a set of col elements. It allows you to group
+several semantically related columns together.
+-->
+<!ATTLIST colgroup
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+ col elements define the alignment properties for cells in
+ one or more columns.
+
+ The width attribute specifies the width of the columns, e.g.
+
+     width=64        width in screen pixels
+     width=0.5*      relative width of 0.5
+
+ The span attribute causes the attributes of one
+ col element to apply to more than one column.
+-->
+<!ATTLIST col
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+    Use thead to duplicate headers when breaking table
+    across page boundaries, or for static headers when
+    tbody sections are rendered in scrolling panel.
+
+    Use tfoot to duplicate footers when breaking table
+    across page boundaries, or for static footers when
+    tbody sections are rendered in scrolling panel.
+
+    Use multiple tbody sections when rules are needed
+    between groups of table rows.
+-->
+<!ATTLIST thead
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tfoot
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tbody
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tr
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  bgcolor     %Color;        #IMPLIED
+  >
+
+<!-- Scope is simpler than headers attribute for common tables -->
+<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
+
+<!-- th is for headers, td for data and for cells acting as both -->
+
+<!ATTLIST th
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  nowrap      (nowrap)       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  width       %Length;       #IMPLIED
+  height      %Length;       #IMPLIED
+  >
+
+<!ATTLIST td
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  nowrap      (nowrap)       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  width       %Length;       #IMPLIED
+  height      %Length;       #IMPLIED
+  >
+
diff --git a/xml/impl/resources/standardSchemas/xhtml1-frameset.dtd b/xml/impl/resources/standardSchemas/xhtml1-frameset.dtd
new file mode 100644
index 0000000..0a0f7f0
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml1-frameset.dtd
@@ -0,0 +1,1235 @@
+<!--
+   Extensible HTML version 1.0 Frameset DTD
+
+   This is the same as HTML 4 Frameset except for
+   changes due to the differences between XML and SGML.
+
+   Namespace = http://www.w3.org/1999/xhtml
+
+   For further information, see: http://www.w3.org/TR/xhtml1
+
+   Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+   All Rights Reserved. 
+
+   This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+   PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+   SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
+
+   $Revision: 1.1 $
+   $Date: 2004/09/17 17:05:38 $
+
+-->
+
+<!--================ Character mnemonic entities =========================-->
+
+<!ENTITY % HTMLlat1 PUBLIC
+   "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+   "xhtml-lat1.ent">
+%HTMLlat1;
+
+<!ENTITY % HTMLsymbol PUBLIC
+   "-//W3C//ENTITIES Symbols for XHTML//EN"
+   "xhtml-symbol.ent">
+%HTMLsymbol;
+
+<!ENTITY % HTMLspecial PUBLIC
+   "-//W3C//ENTITIES Special for XHTML//EN"
+   "xhtml-special.ent">
+%HTMLspecial;
+
+<!--================== Imported Names ====================================-->
+
+<!ENTITY % ContentType "CDATA">
+    <!-- media type, as per [RFC2045] -->
+
+<!ENTITY % ContentTypes "CDATA">
+    <!-- comma-separated list of media types, as per [RFC2045] -->
+
+<!ENTITY % Charset "CDATA">
+    <!-- a character encoding, as per [RFC2045] -->
+
+<!ENTITY % Charsets "CDATA">
+    <!-- a space separated list of character encodings, as per [RFC2045] -->
+
+<!ENTITY % LanguageCode "NMTOKEN">
+    <!-- a language code, as per [RFC3066] -->
+
+<!ENTITY % Character "CDATA">
+    <!-- a single character, as per section 2.2 of [XML] -->
+
+<!ENTITY % Number "CDATA">
+    <!-- one or more digits -->
+
+<!ENTITY % LinkTypes "CDATA">
+    <!-- space-separated list of link types -->
+
+<!ENTITY % MediaDesc "CDATA">
+    <!-- single or comma-separated list of media descriptors -->
+
+<!ENTITY % URI "CDATA">
+    <!-- a Uniform Resource Identifier, see [RFC2396] -->
+
+<!ENTITY % UriList "CDATA">
+    <!-- a space separated list of Uniform Resource Identifiers -->
+
+<!ENTITY % Datetime "CDATA">
+    <!-- date and time information. ISO date format -->
+
+<!ENTITY % Script "CDATA">
+    <!-- script expression -->
+
+<!ENTITY % StyleSheet "CDATA">
+    <!-- style sheet data -->
+
+<!ENTITY % Text "CDATA">
+    <!-- used for titles etc. -->
+
+<!ENTITY % FrameTarget "NMTOKEN">
+    <!-- render in this frame -->
+
+<!ENTITY % Length "CDATA">
+    <!-- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % MultiLength "CDATA">
+    <!-- pixel, percentage, or relative -->
+
+<!ENTITY % MultiLengths "CDATA">
+    <!-- comma-separated list of MultiLength -->
+
+<!ENTITY % Pixels "CDATA">
+    <!-- integer representing length in pixels -->
+
+<!-- these are used for image maps -->
+
+<!ENTITY % Shape "(rect|circle|poly|default)">
+
+<!ENTITY % Coords "CDATA">
+    <!-- comma separated list of lengths -->
+
+<!-- used for object, applet, img, input and iframe -->
+<!ENTITY % ImgAlign "(top|middle|bottom|left|right)">
+
+<!-- a color using sRGB: #RRGGBB as Hex values -->
+<!ENTITY % Color "CDATA">
+
+<!-- There are also 16 widely known color names with their sRGB values:
+
+    Black  = #000000    Green  = #008000
+    Silver = #C0C0C0    Lime   = #00FF00
+    Gray   = #808080    Olive  = #808000
+    White  = #FFFFFF    Yellow = #FFFF00
+    Maroon = #800000    Navy   = #000080
+    Red    = #FF0000    Blue   = #0000FF
+    Purple = #800080    Teal   = #008080
+    Fuchsia= #FF00FF    Aqua   = #00FFFF
+-->
+
+<!--=================== Generic Attributes ===============================-->
+
+<!-- core attributes common to most elements
+  id       document-wide unique id
+  class    space separated list of classes
+  style    associated style info
+  title    advisory title/amplification
+-->
+<!ENTITY % coreattrs
+ "id          ID             #IMPLIED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED"
+  >
+
+<!-- internationalization attributes
+  lang        language code (backwards compatible)
+  xml:lang    language code (as per XML 1.0 spec)
+  dir         direction for weak/neutral text
+-->
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #IMPLIED"
+  >
+
+<!-- attributes for common UI events
+  onclick     a pointer button was clicked
+  ondblclick  a pointer button was double clicked
+  onmousedown a pointer button was pressed down
+  onmouseup   a pointer button was released
+  onmousemove a pointer was moved onto the element
+  onmouseout  a pointer was moved away from the element
+  onkeypress  a key was pressed and released
+  onkeydown   a key was pressed down
+  onkeyup     a key was released
+-->
+<!ENTITY % events
+ "onclick     %Script;       #IMPLIED
+  ondblclick  %Script;       #IMPLIED
+  onmousedown %Script;       #IMPLIED
+  onmouseup   %Script;       #IMPLIED
+  onmouseover %Script;       #IMPLIED
+  onmousemove %Script;       #IMPLIED
+  onmouseout  %Script;       #IMPLIED
+  onkeypress  %Script;       #IMPLIED
+  onkeydown   %Script;       #IMPLIED
+  onkeyup     %Script;       #IMPLIED"
+  >
+
+<!-- attributes for elements that can get the focus
+  accesskey   accessibility key character
+  tabindex    position in tabbing order
+  onfocus     the element got the focus
+  onblur      the element lost the focus
+-->
+<!ENTITY % focus
+ "accesskey   %Character;    #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED"
+  >
+
+<!ENTITY % attrs "%coreattrs; %i18n; %events;">
+
+<!-- text alignment for p, div, h1-h6. The default is
+     align="left" for ltr headings, "right" for rtl -->
+
+<!ENTITY % TextAlign "align (left|center|right|justify) #IMPLIED">
+
+<!--=================== Text Elements ====================================-->
+
+<!ENTITY % special.extra
+   "object | applet | img | map | iframe">
+	
+<!ENTITY % special.basic
+	"br | span | bdo">
+
+<!ENTITY % special
+   "%special.basic; | %special.extra;">
+
+<!ENTITY % fontstyle.extra "big | small | font | basefont">
+
+<!ENTITY % fontstyle.basic "tt | i | b | u
+                      | s | strike ">
+
+<!ENTITY % fontstyle "%fontstyle.basic; | %fontstyle.extra;">
+
+<!ENTITY % phrase.extra "sub | sup">
+<!ENTITY % phrase.basic "em | strong | dfn | code | q |
+                   samp | kbd | var | cite | abbr | acronym">
+
+<!ENTITY % phrase "%phrase.basic; | %phrase.extra;">
+
+<!ENTITY % inline.forms "input | select | textarea | label | button">
+
+<!-- these can occur at block or inline level -->
+<!ENTITY % misc.inline "ins | del | script">
+
+<!-- these can only occur at block level -->
+<!ENTITY % misc "noscript | %misc.inline;">
+
+
+<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
+
+<!-- %Inline; covers inline or "text-level" elements -->
+<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
+
+<!--================== Block level elements ==============================-->
+
+<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
+<!ENTITY % lists "ul | ol | dl | menu | dir">
+<!ENTITY % blocktext "pre | hr | blockquote | address | center">
+
+<!ENTITY % block
+    "p | %heading; | div | %lists; | %blocktext; | isindex | fieldset | table">
+
+<!-- %Flow; mixes block and inline and is used for list items etc. -->
+<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
+
+<!--================== Content models for exclusions =====================-->
+
+<!-- a elements use %Inline; excluding a -->
+
+<!ENTITY % a.content
+   "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
+
+<!-- pre uses %Inline excluding img, object, applet, big, small,
+     sub, sup, font, or basefont -->
+
+<!ENTITY % pre.content
+   "(#PCDATA | a | %special.basic; | %fontstyle.basic; | %phrase.basic; |
+	   %inline.forms; | %misc.inline;)*">
+
+
+<!-- form uses %Flow; excluding form -->
+
+<!ENTITY % form.content "(#PCDATA | %block; | %inline; | %misc;)*">
+
+<!-- button uses %Flow; but excludes a, form, form controls, iframe -->
+
+<!ENTITY % button.content
+   "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
+      table | br | span | bdo | object | applet | img | map |
+      %fontstyle; | %phrase; | %misc;)*">
+
+<!--================ Document Structure ==================================-->
+
+<!-- the namespace URI designates the document profile -->
+
+<!ELEMENT html (head, frameset)>
+<!ATTLIST html
+  %i18n;
+  id          ID             #IMPLIED
+  xmlns       %URI;          #FIXED 'http://www.w3.org/1999/xhtml'
+  >
+
+<!--================ Document Head =======================================-->
+
+<!ENTITY % head.misc "(script|style|meta|link|object|isindex)*">
+
+<!-- content model is %head.misc; combined with a single
+     title and an optional base element in any order -->
+
+<!ELEMENT head (%head.misc;,
+     ((title, %head.misc;, (base, %head.misc;)?) |
+      (base, %head.misc;, (title, %head.misc;))))>
+
+<!ATTLIST head
+  %i18n;
+  id          ID             #IMPLIED
+  profile     %URI;          #IMPLIED
+  >
+
+<!-- The title element is not considered part of the flow of text.
+       It should be displayed, for example as the page header or
+       window title. Exactly one title is required per document.
+    -->
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title 
+  %i18n;
+  id          ID             #IMPLIED
+  >
+
+<!-- document base URI -->
+
+<!ELEMENT base EMPTY>
+<!ATTLIST base
+  id          ID             #IMPLIED
+  href        %URI;          #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!-- generic metainformation -->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+  %i18n;
+  id          ID             #IMPLIED
+  http-equiv  CDATA          #IMPLIED
+  name        CDATA          #IMPLIED
+  content     CDATA          #REQUIRED
+  scheme      CDATA          #IMPLIED
+  >
+
+<!--
+  Relationship values can be used in principle:
+
+   a) for document specific toolbars/menus when used
+      with the link element in document head e.g.
+        start, contents, previous, next, index, end, help
+   b) to link to a separate style sheet (rel="stylesheet")
+   c) to make a link to a script (rel="script")
+   d) by stylesheets to control how collections of
+      html nodes are rendered into printed documents
+   e) to make a link to a printable version of this document
+      e.g. a PostScript or PDF version (rel="alternate" media="print")
+-->
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+  %attrs;
+  charset     %Charset;      #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  type        %ContentType;  #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  media       %MediaDesc;    #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!-- style info, which may include CDATA sections -->
+<!ELEMENT style (#PCDATA)>
+<!ATTLIST style
+  %i18n;
+  id          ID             #IMPLIED
+  type        %ContentType;  #REQUIRED
+  media       %MediaDesc;    #IMPLIED
+  title       %Text;         #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- script statements, which may include CDATA sections -->
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+  id          ID             #IMPLIED
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #REQUIRED
+  language    CDATA          #IMPLIED
+  src         %URI;          #IMPLIED
+  defer       (defer)        #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- alternate content container for non script-based rendering -->
+
+<!ELEMENT noscript %Flow;>
+<!ATTLIST noscript
+  %attrs;
+  >
+
+<!--======================= Frames =======================================-->
+
+<!-- only one noframes element permitted per document -->
+
+<!ELEMENT frameset (frameset|frame|noframes)*>
+<!ATTLIST frameset
+  %coreattrs;
+  rows        %MultiLengths; #IMPLIED
+  cols        %MultiLengths; #IMPLIED
+  onload      %Script;       #IMPLIED
+  onunload    %Script;       #IMPLIED
+  >
+
+<!-- reserved frame names start with "_" otherwise starts with letter -->
+
+<!-- tiled window within frameset -->
+
+<!ELEMENT frame EMPTY>
+<!ATTLIST frame
+  %coreattrs;
+  longdesc    %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  src         %URI;          #IMPLIED
+  frameborder (1|0)          "1"
+  marginwidth %Pixels;       #IMPLIED
+  marginheight %Pixels;      #IMPLIED
+  noresize    (noresize)     #IMPLIED
+  scrolling   (yes|no|auto)  "auto"
+  >
+
+<!-- inline subwindow -->
+
+<!ELEMENT iframe %Flow;>
+<!ATTLIST iframe
+  %coreattrs;
+  longdesc    %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  src         %URI;          #IMPLIED
+  frameborder (1|0)          "1"
+  marginwidth %Pixels;       #IMPLIED
+  marginheight %Pixels;      #IMPLIED
+  scrolling   (yes|no|auto)  "auto"
+  align       %ImgAlign;     #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  >
+
+<!-- alternate content container for non frame-based rendering -->
+
+<!ELEMENT noframes (body)>
+<!ATTLIST noframes
+  %attrs;
+  >
+
+<!--=================== Document Body ====================================-->
+
+<!ELEMENT body %Flow;>
+<!ATTLIST body
+  %attrs;
+  onload      %Script;       #IMPLIED
+  onunload    %Script;       #IMPLIED
+  background  %URI;          #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  text        %Color;        #IMPLIED
+  link        %Color;        #IMPLIED
+  vlink       %Color;        #IMPLIED
+  alink       %Color;        #IMPLIED
+  >
+
+<!ELEMENT div %Flow;>  <!-- generic language/style container -->
+<!ATTLIST div
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Paragraphs =======================================-->
+
+<!ELEMENT p %Inline;>
+<!ATTLIST p
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Headings =========================================-->
+
+<!--
+  There are six levels of headings from h1 (the most important)
+  to h6 (the least important).
+-->
+
+<!ELEMENT h1  %Inline;>
+<!ATTLIST h1
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h2 %Inline;>
+<!ATTLIST h2
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h3 %Inline;>
+<!ATTLIST h3
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h4 %Inline;>
+<!ATTLIST h4
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h5 %Inline;>
+<!ATTLIST h5
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h6 %Inline;>
+<!ATTLIST h6
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Lists ============================================-->
+
+<!-- Unordered list bullet styles -->
+
+<!ENTITY % ULStyle "(disc|square|circle)">
+
+<!-- Unordered list -->
+
+<!ELEMENT ul (li)+>
+<!ATTLIST ul
+  %attrs;
+  type        %ULStyle;     #IMPLIED
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- Ordered list numbering style
+
+    1   arabic numbers      1, 2, 3, ...
+    a   lower alpha         a, b, c, ...
+    A   upper alpha         A, B, C, ...
+    i   lower roman         i, ii, iii, ...
+    I   upper roman         I, II, III, ...
+
+    The style is applied to the sequence number which by default
+    is reset to 1 for the first list item in an ordered list.
+-->
+<!ENTITY % OLStyle "CDATA">
+
+<!-- Ordered (numbered) list -->
+
+<!ELEMENT ol (li)+>
+<!ATTLIST ol
+  %attrs;
+  type        %OLStyle;      #IMPLIED
+  compact     (compact)      #IMPLIED
+  start       %Number;       #IMPLIED
+  >
+
+<!-- single column list (DEPRECATED) --> 
+<!ELEMENT menu (li)+>
+<!ATTLIST menu
+  %attrs;
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- multiple column list (DEPRECATED) --> 
+<!ELEMENT dir (li)+>
+<!ATTLIST dir
+  %attrs;
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- LIStyle is constrained to: "(%ULStyle;|%OLStyle;)" -->
+<!ENTITY % LIStyle "CDATA">
+
+<!-- list item -->
+
+<!ELEMENT li %Flow;>
+<!ATTLIST li
+  %attrs;
+  type        %LIStyle;      #IMPLIED
+  value       %Number;       #IMPLIED
+  >
+
+<!-- definition lists - dt for term, dd for its definition -->
+
+<!ELEMENT dl (dt|dd)+>
+<!ATTLIST dl
+  %attrs;
+  compact     (compact)      #IMPLIED
+  >
+
+<!ELEMENT dt %Inline;>
+<!ATTLIST dt
+  %attrs;
+  >
+
+<!ELEMENT dd %Flow;>
+<!ATTLIST dd
+  %attrs;
+  >
+
+<!--=================== Address ==========================================-->
+
+<!-- information on author -->
+
+<!ELEMENT address (#PCDATA | %inline; | %misc.inline; | p)*>
+<!ATTLIST address
+  %attrs;
+  >
+
+<!--=================== Horizontal Rule ==================================-->
+
+<!ELEMENT hr EMPTY>
+<!ATTLIST hr
+  %attrs;
+  align       (left|center|right) #IMPLIED
+  noshade     (noshade)      #IMPLIED
+  size        %Pixels;       #IMPLIED
+  width       %Length;       #IMPLIED
+  >
+
+<!--=================== Preformatted Text ================================-->
+
+<!-- content is %Inline; excluding 
+        "img|object|applet|big|small|sub|sup|font|basefont" -->
+
+<!ELEMENT pre %pre.content;>
+<!ATTLIST pre
+  %attrs;
+  width       %Number;      #IMPLIED
+  xml:space   (preserve)    #FIXED 'preserve'
+  >
+
+<!--=================== Block-like Quotes ================================-->
+
+<!ELEMENT blockquote %Flow;>
+<!ATTLIST blockquote
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!--=================== Text alignment ===================================-->
+
+<!-- center content -->
+<!ELEMENT center %Flow;>
+<!ATTLIST center
+  %attrs;
+  >
+
+<!--=================== Inserted/Deleted Text ============================-->
+
+
+<!--
+  ins/del are allowed in block and inline content, but its
+  inappropriate to include block content within an ins element
+  occurring in inline content.
+-->
+<!ELEMENT ins %Flow;>
+<!ATTLIST ins
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!ELEMENT del %Flow;>
+<!ATTLIST del
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!--================== The Anchor Element ================================-->
+
+<!-- content is %Inline; except that anchors shouldn't be nested -->
+
+<!ELEMENT a %a.content;>
+<!ATTLIST a
+  %attrs;
+  %focus;
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--===================== Inline Elements ================================-->
+
+<!ELEMENT span %Inline;> <!-- generic language/style container -->
+<!ATTLIST span
+  %attrs;
+  >
+
+<!ELEMENT bdo %Inline;>  <!-- I18N BiDi over-ride -->
+<!ATTLIST bdo
+  %coreattrs;
+  %events;
+  lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #REQUIRED
+  >
+
+<!ELEMENT br EMPTY>   <!-- forced line break -->
+<!ATTLIST br
+  %coreattrs;
+  clear       (left|all|right|none) "none"
+  >
+
+<!ELEMENT em %Inline;>   <!-- emphasis -->
+<!ATTLIST em %attrs;>
+
+<!ELEMENT strong %Inline;>   <!-- strong emphasis -->
+<!ATTLIST strong %attrs;>
+
+<!ELEMENT dfn %Inline;>   <!-- definitional -->
+<!ATTLIST dfn %attrs;>
+
+<!ELEMENT code %Inline;>   <!-- program code -->
+<!ATTLIST code %attrs;>
+
+<!ELEMENT samp %Inline;>   <!-- sample -->
+<!ATTLIST samp %attrs;>
+
+<!ELEMENT kbd %Inline;>  <!-- something user would type -->
+<!ATTLIST kbd %attrs;>
+
+<!ELEMENT var %Inline;>   <!-- variable -->
+<!ATTLIST var %attrs;>
+
+<!ELEMENT cite %Inline;>   <!-- citation -->
+<!ATTLIST cite %attrs;>
+
+<!ELEMENT abbr %Inline;>   <!-- abbreviation -->
+<!ATTLIST abbr %attrs;>
+
+<!ELEMENT acronym %Inline;>   <!-- acronym -->
+<!ATTLIST acronym %attrs;>
+
+<!ELEMENT q %Inline;>   <!-- inlined quote -->
+<!ATTLIST q
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!ELEMENT sub %Inline;> <!-- subscript -->
+<!ATTLIST sub %attrs;>
+
+<!ELEMENT sup %Inline;> <!-- superscript -->
+<!ATTLIST sup %attrs;>
+
+<!ELEMENT tt %Inline;>   <!-- fixed pitch font -->
+<!ATTLIST tt %attrs;>
+
+<!ELEMENT i %Inline;>   <!-- italic font -->
+<!ATTLIST i %attrs;>
+
+<!ELEMENT b %Inline;>   <!-- bold font -->
+<!ATTLIST b %attrs;>
+
+<!ELEMENT big %Inline;>   <!-- bigger font -->
+<!ATTLIST big %attrs;>
+
+<!ELEMENT small %Inline;>   <!-- smaller font -->
+<!ATTLIST small %attrs;>
+
+<!ELEMENT u %Inline;>   <!-- underline -->
+<!ATTLIST u %attrs;>
+
+<!ELEMENT s %Inline;>   <!-- strike-through -->
+<!ATTLIST s %attrs;>
+
+<!ELEMENT strike %Inline;>   <!-- strike-through -->
+<!ATTLIST strike %attrs;>
+
+<!ELEMENT basefont EMPTY>  <!-- base font size -->
+<!ATTLIST basefont
+  id          ID             #IMPLIED
+  size        CDATA          #REQUIRED
+  color       %Color;        #IMPLIED
+  face        CDATA          #IMPLIED
+  >
+
+<!ELEMENT font %Inline;> <!-- local change to font -->
+<!ATTLIST font
+  %coreattrs;
+  %i18n;
+  size        CDATA          #IMPLIED
+  color       %Color;        #IMPLIED
+  face        CDATA          #IMPLIED
+  >
+
+<!--==================== Object ======================================-->
+<!--
+  object is used to embed objects as part of HTML pages.
+  param elements should precede other content. Parameters
+  can also be expressed as attribute/value pairs on the
+  object element itself when brevity is desired.
+-->
+
+<!ELEMENT object (#PCDATA | param | %block; | form |%inline; | %misc;)*>
+<!ATTLIST object
+  %attrs;
+  declare     (declare)      #IMPLIED
+  classid     %URI;          #IMPLIED
+  codebase    %URI;          #IMPLIED
+  data        %URI;          #IMPLIED
+  type        %ContentType;  #IMPLIED
+  codetype    %ContentType;  #IMPLIED
+  archive     %UriList;      #IMPLIED
+  standby     %Text;         #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  border      %Pixels;       #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!--
+  param is used to supply a named property value.
+  In XML it would seem natural to follow RDF and support an
+  abbreviated syntax where the param elements are replaced
+  by attribute value pairs on the object start tag.
+-->
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+  id          ID             #IMPLIED
+  name        CDATA          #REQUIRED
+  value       CDATA          #IMPLIED
+  valuetype   (data|ref|object) "data"
+  type        %ContentType;  #IMPLIED
+  >
+
+<!--=================== Java applet ==================================-->
+<!--
+  One of code or object attributes must be present.
+  Place param elements before other content.
+-->
+<!ELEMENT applet (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST applet
+  %coreattrs;
+  codebase    %URI;          #IMPLIED
+  archive     CDATA          #IMPLIED
+  code        CDATA          #IMPLIED
+  object      CDATA          #IMPLIED
+  alt         %Text;         #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  width       %Length;       #REQUIRED
+  height      %Length;       #REQUIRED
+  align       %ImgAlign;     #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!--=================== Images ===========================================-->
+
+<!--
+   To avoid accessibility problems for people who aren't
+   able to see the image, you should provide a text
+   description using the alt and longdesc attributes.
+   In addition, avoid the use of server-side image maps.
+-->
+
+<!ELEMENT img EMPTY>
+<!ATTLIST img
+  %attrs;
+  src         %URI;          #REQUIRED
+  alt         %Text;         #REQUIRED
+  name        NMTOKEN        #IMPLIED
+  longdesc    %URI;          #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  ismap       (ismap)        #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  border      %Pixels;       #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!-- usemap points to a map element which may be in this document
+  or an external document, although the latter is not widely supported -->
+
+<!--================== Client-side image maps ============================-->
+
+<!-- These can be placed in the same document or grouped in a
+     separate document although this isn't yet widely supported -->
+
+<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
+<!ATTLIST map
+  %i18n;
+  %events;
+  id          ID             #REQUIRED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  >
+
+<!ELEMENT area EMPTY>
+<!ATTLIST area
+  %attrs;
+  %focus;
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  href        %URI;          #IMPLIED
+  nohref      (nohref)       #IMPLIED
+  alt         %Text;         #REQUIRED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--================ Forms ===============================================-->
+
+<!ELEMENT form %form.content;>   <!-- forms shouldn't be nested -->
+
+<!ATTLIST form
+  %attrs;
+  action      %URI;          #REQUIRED
+  method      (get|post)     "get"
+  name        NMTOKEN        #IMPLIED
+  enctype     %ContentType;  "application/x-www-form-urlencoded"
+  onsubmit    %Script;       #IMPLIED
+  onreset     %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  accept-charset %Charsets;  #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--
+  Each label must not contain more than ONE field
+  Label elements shouldn't be nested.
+-->
+<!ELEMENT label %Inline;>
+<!ATTLIST label
+  %attrs;
+  for         IDREF          #IMPLIED
+  accesskey   %Character;    #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  >
+
+<!ENTITY % InputType
+  "(text | password | checkbox |
+    radio | submit | reset |
+    file | hidden | image | button)"
+   >
+
+<!-- the name attribute is required for all but submit & reset -->
+
+<!ELEMENT input EMPTY>     <!-- form control -->
+<!ATTLIST input
+  %attrs;
+  %focus;
+  type        %InputType;    "text"
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  checked     (checked)      #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  size        CDATA          #IMPLIED
+  maxlength   %Number;       #IMPLIED
+  src         %URI;          #IMPLIED
+  alt         CDATA          #IMPLIED
+  usemap      %URI;          #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  >
+
+<!ELEMENT select (optgroup|option)+>  <!-- option selector -->
+<!ATTLIST select
+  %attrs;
+  name        CDATA          #IMPLIED
+  size        %Number;       #IMPLIED
+  multiple    (multiple)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!ELEMENT optgroup (option)+>   <!-- option group -->
+<!ATTLIST optgroup
+  %attrs;
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #REQUIRED
+  >
+
+<!ELEMENT option (#PCDATA)>     <!-- selectable choice -->
+<!ATTLIST option
+  %attrs;
+  selected    (selected)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #IMPLIED
+  value       CDATA          #IMPLIED
+  >
+
+<!ELEMENT textarea (#PCDATA)>     <!-- multi-line text field -->
+<!ATTLIST textarea
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  rows        %Number;       #REQUIRED
+  cols        %Number;       #REQUIRED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!--
+  The fieldset element is used to group form fields.
+  Only one legend element should occur in the content
+  and if present should only be preceded by whitespace.
+-->
+<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
+<!ATTLIST fieldset
+  %attrs;
+  >
+
+<!ENTITY % LAlign "(top|bottom|left|right)">
+
+<!ELEMENT legend %Inline;>     <!-- fieldset label -->
+<!ATTLIST legend
+  %attrs;
+  accesskey   %Character;    #IMPLIED
+  align       %LAlign;       #IMPLIED
+  >
+
+<!--
+ Content is %Flow; excluding a, form, form controls, iframe
+--> 
+<!ELEMENT button %button.content;>  <!-- push button -->
+<!ATTLIST button
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  type        (button|submit|reset) "submit"
+  disabled    (disabled)     #IMPLIED
+  >
+
+<!-- single-line text input control (DEPRECATED) -->
+<!ELEMENT isindex EMPTY>
+<!ATTLIST isindex
+  %coreattrs;
+  %i18n;
+  prompt      %Text;         #IMPLIED
+  >
+
+<!--======================= Tables =======================================-->
+
+<!-- Derived from IETF HTML table standard, see [RFC1942] -->
+
+<!--
+ The border attribute sets the thickness of the frame around the
+ table. The default units are screen pixels.
+
+ The frame attribute specifies which parts of the frame around
+ the table should be rendered. The values are not the same as
+ CALS to avoid a name clash with the valign attribute.
+-->
+<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
+
+<!--
+ The rules attribute defines which rules to draw between cells:
+
+ If rules is absent then assume:
+     "none" if border is absent or border="0" otherwise "all"
+-->
+
+<!ENTITY % TRules "(none | groups | rows | cols | all)">
+  
+<!-- horizontal placement of table relative to document -->
+<!ENTITY % TAlign "(left|center|right)">
+
+<!-- horizontal alignment attributes for cell contents
+
+  char        alignment char, e.g. char=":"
+  charoff     offset for alignment char
+-->
+<!ENTITY % cellhalign
+  "align      (left|center|right|justify|char) #IMPLIED
+   char       %Character;    #IMPLIED
+   charoff    %Length;       #IMPLIED"
+  >
+
+<!-- vertical alignment attributes for cell contents -->
+<!ENTITY % cellvalign
+  "valign     (top|middle|bottom|baseline) #IMPLIED"
+  >
+
+<!ELEMENT table
+     (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
+<!ELEMENT caption  %Inline;>
+<!ELEMENT thead    (tr)+>
+<!ELEMENT tfoot    (tr)+>
+<!ELEMENT tbody    (tr)+>
+<!ELEMENT colgroup (col)*>
+<!ELEMENT col      EMPTY>
+<!ELEMENT tr       (th|td)+>
+<!ELEMENT th       %Flow;>
+<!ELEMENT td       %Flow;>
+
+<!ATTLIST table
+  %attrs;
+  summary     %Text;         #IMPLIED
+  width       %Length;       #IMPLIED
+  border      %Pixels;       #IMPLIED
+  frame       %TFrame;       #IMPLIED
+  rules       %TRules;       #IMPLIED
+  cellspacing %Length;       #IMPLIED
+  cellpadding %Length;       #IMPLIED
+  align       %TAlign;       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  >
+
+<!ENTITY % CAlign "(top|bottom|left|right)">
+
+<!ATTLIST caption
+  %attrs;
+  align       %CAlign;       #IMPLIED
+  >
+
+<!--
+colgroup groups a set of col elements. It allows you to group
+several semantically related columns together.
+-->
+<!ATTLIST colgroup
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+ col elements define the alignment properties for cells in
+ one or more columns.
+
+ The width attribute specifies the width of the columns, e.g.
+
+     width=64        width in screen pixels
+     width=0.5*      relative width of 0.5
+
+ The span attribute causes the attributes of one
+ col element to apply to more than one column.
+-->
+<!ATTLIST col
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+    Use thead to duplicate headers when breaking table
+    across page boundaries, or for static headers when
+    tbody sections are rendered in scrolling panel.
+
+    Use tfoot to duplicate footers when breaking table
+    across page boundaries, or for static footers when
+    tbody sections are rendered in scrolling panel.
+
+    Use multiple tbody sections when rules are needed
+    between groups of table rows.
+-->
+<!ATTLIST thead
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tfoot
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tbody
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tr
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  bgcolor     %Color;        #IMPLIED
+  >
+
+<!-- Scope is simpler than headers attribute for common tables -->
+<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
+
+<!-- th is for headers, td for data and for cells acting as both -->
+
+<!ATTLIST th
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  nowrap      (nowrap)       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  width       %Pixels;       #IMPLIED
+  height      %Pixels;       #IMPLIED
+  >
+
+<!ATTLIST td
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  nowrap      (nowrap)       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  width       %Pixels;       #IMPLIED
+  height      %Pixels;       #IMPLIED
+  >
+
diff --git a/xml/impl/resources/standardSchemas/xhtml1-frameset.xsd b/xml/impl/resources/standardSchemas/xhtml1-frameset.xsd
new file mode 100644
index 0000000..741c9ab
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml1-frameset.xsd
@@ -0,0 +1,2848 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema version="1.0" xml:lang="en"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    targetNamespace="http://www.w3.org/1999/xhtml"
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:xml="http://www.w3.org/XML/1998/namespace"
+    elementFormDefault="qualified">
+
+  <xs:annotation>
+    <xs:documentation>
+    XHTML 1.0 (Second Edition) Frameset in XML Schema
+
+    This is the same as HTML 4 Frameset except for
+    changes due to the differences between XML and SGML.
+
+    Namespace = http://www.w3.org/1999/xhtml
+
+    For further information, see: http://www.w3.org/TR/xhtml1
+
+    Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+    All Rights Reserved.
+
+    The DTD version is identified by the PUBLIC and SYSTEM identifiers:
+
+    PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
+
+    $Id: xhtml1-frameset.xsd,v 1.5 2002/08/28 09:53:29 mimasa Exp $
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:import namespace="http://www.w3.org/XML/1998/namespace"
+      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Character mnemonic entities =========================
+
+    XHTML entity sets are identified by the PUBLIC and SYSTEM identifiers:
+
+    PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"
+
+    PUBLIC "-//W3C//ENTITIES Special for XHTML//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent"
+
+    PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent"
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Imported Names ====================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="ContentType">
+    <xs:annotation>
+      <xs:documentation>
+      media type, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="ContentTypes">
+    <xs:annotation>
+      <xs:documentation>
+      comma-separated list of media types, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Charset">
+    <xs:annotation>
+      <xs:documentation>
+      a character encoding, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Charsets">
+    <xs:annotation>
+      <xs:documentation>
+      a space separated list of character encodings, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="LanguageCode">
+    <xs:annotation>
+      <xs:documentation>
+      a language code, as per [RFC3066]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:language"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Character">
+    <xs:annotation>
+      <xs:documentation>
+      a single character, as per section 2.2 of [XML]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:length value="1" fixed="true"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Number">
+    <xs:annotation>
+      <xs:documentation>
+      one or more digits
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:nonNegativeInteger">
+      <xs:pattern value="[0-9]+"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="tabindexNumber">
+    <xs:annotation>
+      <xs:documentation>
+      tabindex attribute specifies the position of the current element
+      in the tabbing order for the current document. This value must be
+      a number between 0 and 32767. User agents should ignore leading zeros.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="Number">
+      <xs:minInclusive value="0"/>
+      <xs:maxInclusive value="32767"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="LinkTypes">
+    <xs:annotation>
+      <xs:documentation>
+      space-separated list of link types
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:NMTOKENS"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="MediaDesc">
+    <xs:annotation>
+      <xs:documentation>
+      single or comma-separated list of media descriptors
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[^,]+(,\s*[^,]+)*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="URI">
+    <xs:annotation>
+      <xs:documentation>
+      a Uniform Resource Identifier, see [RFC2396]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:anyURI"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="UriList">
+    <xs:annotation>
+      <xs:documentation>
+      a space separated list of Uniform Resource Identifiers
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Datetime">
+    <xs:annotation>
+      <xs:documentation>
+      date and time information. ISO date format
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:dateTime"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Script">
+    <xs:annotation>
+      <xs:documentation>
+      script expression
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="StyleSheet">
+    <xs:annotation>
+      <xs:documentation>
+      style sheet data
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Text">
+    <xs:annotation>
+      <xs:documentation>
+      used for titles etc.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="FrameTarget">
+    <xs:annotation>
+      <xs:documentation>
+      render in this frame
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:NMTOKEN">
+      <xs:pattern value="_(blank|self|parent|top)|[A-Za-z]\c*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Length">
+    <xs:annotation>
+      <xs:documentation>
+      nn for pixels or nn% for percentage length
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[\-+]?(\d+|\d+(\.\d+)?%)"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="MultiLength">
+    <xs:annotation>
+      <xs:documentation>
+      pixel, percentage, or relative
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[\-+]?(\d+|\d+(\.\d+)?%)|[1-9]?(\d+)?\*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="MultiLengths">
+    <xs:annotation>
+      <xs:documentation>
+      comma-separated list of MultiLength
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern
+          value="[\-+]?(\d+|\d+(\.\d+)?%)|[1-9]?(\d+)?\*(,\s*[\-+]?(\d+|\d+(\.\d+)?%)|[1-9]?(\d+)?\*)*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Pixels">
+    <xs:annotation>
+      <xs:documentation>
+      integer representing length in pixels
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:nonNegativeInteger"/>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+    these are used for image maps
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="Shape">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="rect"/>
+      <xs:enumeration value="circle"/>
+      <xs:enumeration value="poly"/>
+      <xs:enumeration value="default"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Coords">
+    <xs:annotation>
+      <xs:documentation>
+      comma separated list of lengths
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern
+          value="[\-+]?(\d+|\d+(\.\d+)?%)(,\s*[\-+]?(\d+|\d+(\.\d+)?%))*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="ImgAlign">
+    <xs:annotation>
+      <xs:documentation>
+      used for object, applet, img, input and iframe
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="top"/>
+      <xs:enumeration value="middle"/>
+      <xs:enumeration value="bottom"/>
+      <xs:enumeration value="left"/>
+      <xs:enumeration value="right"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Color">
+    <xs:annotation>
+      <xs:documentation>
+      a color using sRGB: #RRGGBB as Hex values
+
+      There are also 16 widely known color names with their sRGB values:
+
+      Black  = #000000    Green  = #008000
+      Silver = #C0C0C0    Lime   = #00FF00
+      Gray   = #808080    Olive  = #808000
+      White  = #FFFFFF    Yellow = #FFFF00
+      Maroon = #800000    Navy   = #000080
+      Red    = #FF0000    Blue   = #0000FF
+      Purple = #800080    Teal   = #008080
+      Fuchsia= #FF00FF    Aqua   = #00FFFF
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[A-Za-z]+|#[0-9A-Fa-f]{3}|#[0-9A-Fa-f]{6}"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Generic Attributes ===============================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:attributeGroup name="coreattrs">
+    <xs:annotation>
+      <xs:documentation>
+      core attributes common to most elements
+      id       document-wide unique id
+      class    space separated list of classes
+      style    associated style info
+      title    advisory title/amplification
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="id" type="xs:ID"/>
+    <xs:attribute name="class" type="xs:NMTOKENS"/>
+    <xs:attribute name="style" type="StyleSheet"/>
+    <xs:attribute name="title" type="Text"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="i18n">
+    <xs:annotation>
+      <xs:documentation>
+      internationalization attributes
+      lang        language code (backwards compatible)
+      xml:lang    language code (as per XML 1.0 spec)
+      dir         direction for weak/neutral text
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="lang" type="LanguageCode"/>
+    <xs:attribute ref="xml:lang"/>
+    <xs:attribute name="dir">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="ltr"/>
+          <xs:enumeration value="rtl"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="events">
+    <xs:annotation>
+      <xs:documentation>
+      attributes for common UI events
+      onclick     a pointer button was clicked
+      ondblclick  a pointer button was double clicked
+      onmousedown a pointer button was pressed down
+      onmouseup   a pointer button was released
+      onmousemove a pointer was moved onto the element
+      onmouseout  a pointer was moved away from the element
+      onkeypress  a key was pressed and released
+      onkeydown   a key was pressed down
+      onkeyup     a key was released
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="onclick" type="Script"/>
+    <xs:attribute name="ondblclick" type="Script"/>
+    <xs:attribute name="onmousedown" type="Script"/>
+    <xs:attribute name="onmouseup" type="Script"/>
+    <xs:attribute name="onmouseover" type="Script"/>
+    <xs:attribute name="onmousemove" type="Script"/>
+    <xs:attribute name="onmouseout" type="Script"/>
+    <xs:attribute name="onkeypress" type="Script"/>
+    <xs:attribute name="onkeydown" type="Script"/>
+    <xs:attribute name="onkeyup" type="Script"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="focus">
+    <xs:annotation>
+      <xs:documentation>
+      attributes for elements that can get the focus
+      accesskey   accessibility key character
+      tabindex    position in tabbing order
+      onfocus     the element got the focus
+      onblur      the element lost the focus
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="accesskey" type="Character"/>
+    <xs:attribute name="tabindex" type="tabindexNumber"/>
+    <xs:attribute name="onfocus" type="Script"/>
+    <xs:attribute name="onblur" type="Script"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="attrs">
+    <xs:attributeGroup ref="coreattrs"/>
+    <xs:attributeGroup ref="i18n"/>
+    <xs:attributeGroup ref="events"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="TextAlign">
+    <xs:annotation>
+      <xs:documentation>
+      text alignment for p, div, h1-h6. The default is
+      align="left" for ltr headings, "right" for rtl
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="align">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="left"/>
+          <xs:enumeration value="center"/>
+          <xs:enumeration value="right"/>
+          <xs:enumeration value="justify"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Text Elements ====================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:group name="special.extra">
+    <xs:choice>
+      <xs:element ref="object"/>
+      <xs:element ref="applet"/>
+      <xs:element ref="img"/>
+      <xs:element ref="map"/>
+      <xs:element ref="iframe"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="special.basic">
+    <xs:choice>
+      <xs:element ref="br"/>
+      <xs:element ref="span"/>
+      <xs:element ref="bdo"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="special">
+    <xs:choice>
+      <xs:group ref="special.basic"/>
+      <xs:group ref="special.extra"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="fontstyle.extra">
+    <xs:choice>
+      <xs:element ref="big"/>
+      <xs:element ref="small"/>
+      <xs:element ref="font"/>
+      <xs:element ref="basefont"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="fontstyle.basic">
+    <xs:choice>
+      <xs:element ref="tt"/>
+      <xs:element ref="i"/>
+      <xs:element ref="b"/>
+      <xs:element ref="u"/>
+      <xs:element ref="s"/>
+      <xs:element ref="strike"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="fontstyle">
+    <xs:choice>
+      <xs:group ref="fontstyle.basic"/>
+      <xs:group ref="fontstyle.extra"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="phrase.extra">
+    <xs:choice>
+      <xs:element ref="sub"/>
+      <xs:element ref="sup"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="phrase.basic">
+    <xs:choice>
+      <xs:element ref="em"/>
+      <xs:element ref="strong"/>
+      <xs:element ref="dfn"/>
+      <xs:element ref="code"/>
+      <xs:element ref="q"/>
+      <xs:element ref="samp"/>
+      <xs:element ref="kbd"/>
+      <xs:element ref="var"/>
+      <xs:element ref="cite"/>
+      <xs:element ref="abbr"/>
+      <xs:element ref="acronym"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="phrase">
+    <xs:choice>
+      <xs:group ref="phrase.basic"/>
+      <xs:group ref="phrase.extra"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="inline.forms">
+    <xs:choice>
+      <xs:element ref="input"/>
+      <xs:element ref="select"/>
+      <xs:element ref="textarea"/>
+      <xs:element ref="label"/>
+      <xs:element ref="button"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="misc.inline">
+    <xs:annotation>
+      <xs:documentation>
+      these can only occur at block level
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice>
+      <xs:element ref="ins"/>
+      <xs:element ref="del"/>
+      <xs:element ref="script"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="misc">
+    <xs:annotation>
+      <xs:documentation>
+      these can only occur at block level
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice>
+      <xs:element ref="noscript"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="inline">
+    <xs:choice>
+      <xs:element ref="a"/>
+      <xs:group ref="special"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="inline.forms"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:complexType name="Inline" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      "Inline" covers inline or "text-level" element
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="inline"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Block level elements ==============================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:group name="heading">
+    <xs:choice>
+      <xs:element ref="h1"/>
+      <xs:element ref="h2"/>
+      <xs:element ref="h3"/>
+      <xs:element ref="h4"/>
+      <xs:element ref="h5"/>
+      <xs:element ref="h6"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="lists">
+    <xs:choice>
+      <xs:element ref="ul"/>
+      <xs:element ref="ol"/>
+      <xs:element ref="dl"/>
+      <xs:element ref="menu"/>
+      <xs:element ref="dir"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="blocktext">
+    <xs:choice>
+      <xs:element ref="pre"/>
+      <xs:element ref="hr"/>
+      <xs:element ref="blockquote"/>
+      <xs:element ref="address"/>
+      <xs:element ref="center"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="block">
+    <xs:choice>
+      <xs:element ref="p"/>
+      <xs:group ref="heading"/>
+      <xs:element ref="div"/>
+      <xs:group ref="lists"/>
+      <xs:group ref="blocktext"/>
+      <xs:element ref="isindex"/>
+      <xs:element ref="fieldset"/>
+      <xs:element ref="table"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:complexType name="Flow" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      "Flow" mixes block and inline and is used for list items etc.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="block"/>
+      <xs:element ref="form"/>
+      <xs:group ref="inline"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Content models for exclusions =====================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:complexType name="a.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      a elements use "Inline" excluding a
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="special"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="inline.forms"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="pre.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      pre uses "Inline" excluding img, object, applet, big, small,
+      sub, sup, font, or basefont
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="a"/>
+      <xs:group ref="special.basic"/>
+      <xs:group ref="fontstyle.basic"/>
+      <xs:group ref="phrase.basic"/>
+      <xs:group ref="inline.forms"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="form.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      form uses "Flow" excluding form
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="block"/>
+      <xs:group ref="inline"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="button.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      button uses "Flow" but excludes a, form, form controls, iframe
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="p"/>
+      <xs:group ref="heading"/>
+      <xs:element ref="div"/>
+      <xs:group ref="lists"/>
+      <xs:group ref="blocktext"/>
+      <xs:element ref="table"/>
+      <xs:element ref="br"/>
+      <xs:element ref="span"/>
+      <xs:element ref="bdo"/>
+      <xs:element ref="object"/>
+      <xs:element ref="applet"/>
+      <xs:element ref="img"/>
+      <xs:element ref="map"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Document Structure ==================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="html">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element ref="head"/>
+        <xs:element ref="frameset"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Document Head =======================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:group name="head.misc">
+    <xs:sequence>
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="script"/>
+        <xs:element ref="style"/>
+        <xs:element ref="meta"/>
+        <xs:element ref="link"/>
+        <xs:element ref="object"/>
+        <xs:element ref="isindex"/>
+      </xs:choice>
+    </xs:sequence>
+  </xs:group>
+
+  <xs:element name="head">
+    <xs:annotation>
+      <xs:documentation>
+      content model is "head.misc" combined with a single
+      title and an optional base element in any order
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:group ref="head.misc"/>
+        <xs:choice>
+          <xs:sequence>
+            <xs:element ref="title"/>
+            <xs:group ref="head.misc"/>
+            <xs:sequence minOccurs="0">
+              <xs:element ref="base"/>
+              <xs:group ref="head.misc"/>
+            </xs:sequence>
+          </xs:sequence>
+          <xs:sequence>
+            <xs:element ref="base"/>
+            <xs:group ref="head.misc"/>
+            <xs:element ref="title"/>
+            <xs:group ref="head.misc"/>
+          </xs:sequence>
+        </xs:choice>
+      </xs:sequence>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="profile" type="URI"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="title">
+    <xs:annotation>
+      <xs:documentation>
+      The title element is not considered part of the flow of text.
+      It should be displayed, for example as the page header or
+      window title. Exactly one title is required per document.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="base">
+    <xs:annotation>
+      <xs:documentation>
+      document base URI
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="href" type="URI"/>
+      <xs:attribute name="target" type="FrameTarget"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="meta">
+    <xs:annotation>
+      <xs:documentation>
+      generic metainformation
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="http-equiv"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="content" use="required"/>
+      <xs:attribute name="scheme"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="link">
+    <xs:annotation>
+      <xs:documentation>
+      Relationship values can be used in principle:
+
+      a) for document specific toolbars/menus when used
+         with the link element in document head e.g.
+           start, contents, previous, next, index, end, help
+      b) to link to a separate style sheet (rel="stylesheet")
+      c) to make a link to a script (rel="script")
+      d) by stylesheets to control how collections of
+         html nodes are rendered into printed documents
+      e) to make a link to a printable version of this document
+         e.g. a PostScript or PDF version (rel="alternate" media="print")
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="charset" type="Charset"/>
+      <xs:attribute name="href" type="URI"/>
+      <xs:attribute name="hreflang" type="LanguageCode"/>
+      <xs:attribute name="type" type="ContentType"/>
+      <xs:attribute name="rel" type="LinkTypes"/>
+      <xs:attribute name="rev" type="LinkTypes"/>
+      <xs:attribute name="media" type="MediaDesc"/>
+      <xs:attribute name="target" type="FrameTarget"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="style">
+    <xs:annotation>
+      <xs:documentation>
+      style info, which may include CDATA sections
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="type" use="required" type="ContentType"/>
+      <xs:attribute name="media" type="MediaDesc"/>
+      <xs:attribute name="title" type="Text"/>
+      <xs:attribute ref="xml:space" fixed="preserve"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="script">
+    <xs:annotation>
+      <xs:documentation>
+      script statements, which may include CDATA sections
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="charset" type="Charset"/>
+      <xs:attribute name="type" use="required" type="ContentType"/>
+      <xs:attribute name="language"/>
+      <xs:attribute name="src" type="URI"/>
+      <xs:attribute name="defer">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="defer"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute ref="xml:space" fixed="preserve"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="noscript">
+    <xs:annotation>
+      <xs:documentation>
+      alternate content container for non script-based rendering
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ======================= Frames =======================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="frameset">
+    <xs:annotation>
+      <xs:documentation>
+      only one noframes element permitted per document
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="frameset"/>
+        <xs:element ref="frame"/>
+        <xs:element ref="noframes"/>
+      </xs:choice>
+      <xs:attributeGroup ref="coreattrs"/>
+      <xs:attribute name="rows" type="MultiLengths"/>
+      <xs:attribute name="cols" type="MultiLengths"/>
+      <xs:attribute name="onload" type="Script"/>
+      <xs:attribute name="onunload" type="Script"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    reserved frame names start with "_" otherwise starts with letter
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="frame">
+    <xs:annotation>
+      <xs:documentation>
+      tiled window within frameset
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="coreattrs"/>
+      <xs:attribute name="longdesc" type="URI"/>
+      <xs:attribute name="name" type="xs:NMTOKEN"/>
+      <xs:attribute name="src" type="URI"/>
+      <xs:attribute name="frameborder" default="1">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="1"/>
+            <xs:enumeration value="0"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="marginwidth" type="Pixels"/>
+      <xs:attribute name="marginheight" type="Pixels"/>
+      <xs:attribute name="noresize">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="noresize"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="scrolling" default="auto">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="yes"/>
+            <xs:enumeration value="no"/>
+            <xs:enumeration value="auto"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="iframe">
+    <xs:annotation>
+      <xs:documentation>
+      inline subwindow
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="coreattrs"/>
+          <xs:attribute name="longdesc" type="URI"/>
+          <xs:attribute name="name" type="xs:NMTOKEN"/>
+          <xs:attribute name="src" type="URI"/>
+          <xs:attribute name="frameborder" default="1">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="1"/>
+                <xs:enumeration value="0"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="marginwidth" type="Pixels"/>
+          <xs:attribute name="marginheight" type="Pixels"/>
+          <xs:attribute name="scrolling" default="auto">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="yes"/>
+                <xs:enumeration value="no"/>
+                <xs:enumeration value="auto"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="align" type="ImgAlign"/>
+          <xs:attribute name="height" type="Length"/>
+          <xs:attribute name="width" type="Length"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+<!--
+  <xs:element name="noframes">
+    <xs:annotation>
+      <xs:documentation>
+      alternate content container for non frame-based rendering
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="body">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+-->
+  <xs:element name="noframes">
+    <xs:annotation>
+      <xs:documentation>
+      alternate content container for non frame-based rendering
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element ref="body"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Document Body ====================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="body">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="onload" type="Script"/>
+          <xs:attribute name="onunload" type="Script"/>
+          <xs:attribute name="background" type="URI"/>
+          <xs:attribute name="bgcolor" type="Color"/>
+          <xs:attribute name="text" type="Color"/>
+          <xs:attribute name="link" type="Color"/>
+          <xs:attribute name="vlink" type="Color"/>
+          <xs:attribute name="alink" type="Color"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="div">
+    <xs:annotation>
+      <xs:documentation>
+      generic language/style container
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Paragraphs =======================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="p">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Headings =========================================
+
+    There are six levels of headings from h1 (the most important)
+    to h6 (the least important).
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="h1">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h2">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h3">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h4">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h5">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h6">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Lists ============================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="ULStyle">
+    <xs:annotation>
+      <xs:documentation>
+      Unordered list bullet styles
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="disc"/>
+      <xs:enumeration value="square"/>
+      <xs:enumeration value="circle"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="ul">
+    <xs:annotation>
+      <xs:documentation>
+      Unordered list
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="type" type="ULStyle"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="OLStyle">
+    <xs:annotation>
+      <xs:documentation>
+      Ordered list numbering style
+
+      1   arabic numbers      1, 2, 3, ...
+      a   lower alpha         a, b, c, ...
+      A   upper alpha         A, B, C, ...
+      i   lower roman         i, ii, iii, ...
+      I   upper roman         I, II, III, ...
+
+      The style is applied to the sequence number which by default
+      is reset to 1 for the first list item in an ordered list.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:element name="ol">
+    <xs:annotation>
+      <xs:documentation>
+      Ordered (numbered) list
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="type" type="OLStyle"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="start" type="Number"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="menu">
+    <xs:annotation>
+      <xs:documentation>
+      single column list (DEPRECATED)
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dir">
+    <xs:annotation>
+      <xs:documentation>
+      multiple column list (DEPRECATED)
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="LIStyle">
+    <xs:annotation>
+      <xs:documentation>
+      LIStyle is constrained to: "(ULStyle|OLStyle)"
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:element name="li">
+    <xs:annotation>
+      <xs:documentation>
+      list item
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="type" type="LIStyle"/>
+          <xs:attribute name="value" type="Number"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    definition lists - dt for term, dd for its definition
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="dl">
+    <xs:complexType>
+      <xs:choice maxOccurs="unbounded">
+        <xs:element ref="dt"/>
+        <xs:element ref="dd"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dt">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dd">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Address ==========================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="address">
+    <xs:annotation>
+      <xs:documentation>
+      information on author
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:group ref="inline"/>
+        <xs:group ref="misc.inline"/>
+        <xs:element ref="p"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Horizontal Rule ==================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="hr">
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="align">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="left"/>
+            <xs:enumeration value="center"/>
+            <xs:enumeration value="right"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="noshade">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="noshade"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="size" type="Pixels"/>
+      <xs:attribute name="width" type="Length"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Preformatted Text ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="pre">
+    <xs:annotation>
+      <xs:documentation>
+      content is "Inline" excluding
+         "img|object|applet|big|small|sub|sup|font|basefont"
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="pre.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="width" type="Number"/>
+          <xs:attribute ref="xml:space" fixed="preserve"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Block-like Quotes ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="blockquote">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Text alignment ===================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="center">
+    <xs:annotation>
+      <xs:documentation>
+      center content
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Inserted/Deleted Text ============================
+
+    ins/del are allowed in block and inline content, but its
+    inappropriate to include block content within an ins element
+    occurring in inline content.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="ins">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+          <xs:attribute name="datetime" type="Datetime"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="del">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+          <xs:attribute name="datetime" type="Datetime"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== The Anchor Element ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="a">
+    <xs:annotation>
+      <xs:documentation>
+      content is "Inline" except that anchors shouldn't be nested
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="a.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="focus"/>
+          <xs:attribute name="charset" type="Charset"/>
+          <xs:attribute name="type" type="ContentType"/>
+          <xs:attribute name="name" type="xs:ID"/>
+          <xs:attribute name="href" type="URI"/>
+          <xs:attribute name="hreflang" type="LanguageCode"/>
+          <xs:attribute name="rel" type="LinkTypes"/>
+          <xs:attribute name="rev" type="LinkTypes"/>
+          <xs:attribute name="shape" default="rect" type="Shape"/>
+          <xs:attribute name="coords" type="Coords"/>
+          <xs:attribute name="target" type="FrameTarget"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ===================== Inline Elements ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="span">
+    <xs:annotation>
+      <xs:documentation>
+      generic language/style container
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="bdo">
+    <xs:annotation>
+      <xs:documentation>
+      I18N BiDi over-ride
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="coreattrs"/>
+          <xs:attributeGroup ref="events"/>
+          <xs:attribute name="lang" type="LanguageCode"/>
+          <xs:attribute ref="xml:lang"/>
+          <xs:attribute name="dir" use="required">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="ltr"/>
+                <xs:enumeration value="rtl"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="br">
+    <xs:annotation>
+      <xs:documentation>
+      forced line break
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="coreattrs"/>
+      <xs:attribute name="clear" default="none">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="left"/>
+            <xs:enumeration value="all"/>
+            <xs:enumeration value="right"/>
+            <xs:enumeration value="none"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="em">
+    <xs:annotation>
+      <xs:documentation>
+      emphasis
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="strong">
+    <xs:annotation>
+      <xs:documentation>
+      strong emphasis
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dfn">
+    <xs:annotation>
+      <xs:documentation>
+      definitional
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="code">
+    <xs:annotation>
+      <xs:documentation>
+      program code
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="samp">
+    <xs:annotation>
+      <xs:documentation>
+      sample
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="kbd">
+    <xs:annotation>
+      <xs:documentation>
+      something user would type
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="var">
+    <xs:annotation>
+      <xs:documentation>
+      variable
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="cite">
+    <xs:annotation>
+      <xs:documentation>
+      citation
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="abbr">
+    <xs:annotation>
+      <xs:documentation>
+      abbreviation
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="acronym">
+    <xs:annotation>
+      <xs:documentation>
+      acronym
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="q">
+    <xs:annotation>
+      <xs:documentation>
+      inlined quote
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="sub">
+    <xs:annotation>
+      <xs:documentation>
+      subscript
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="sup">
+    <xs:annotation>
+      <xs:documentation>
+      superscript
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tt">
+    <xs:annotation>
+      <xs:documentation>
+      fixed pitch font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="i">
+    <xs:annotation>
+      <xs:documentation>
+      italic font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="b">
+    <xs:annotation>
+      <xs:documentation>
+      bold font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="big">
+    <xs:annotation>
+      <xs:documentation>
+      bigger font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="small">
+    <xs:annotation>
+      <xs:documentation>
+      smaller font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="u">
+    <xs:annotation>
+      <xs:documentation>
+      underline
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="s">
+    <xs:annotation>
+      <xs:documentation>
+      strike-through
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="strike">
+    <xs:annotation>
+      <xs:documentation>
+      strike-through
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="basefont">
+    <xs:annotation>
+      <xs:documentation>
+      base font size
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="size" use="required"/>
+      <xs:attribute name="color" type="Color"/>
+      <xs:attribute name="face"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="font">
+    <xs:annotation>
+      <xs:documentation>
+      local change to font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="coreattrs"/>
+          <xs:attributeGroup ref="i18n"/>
+          <xs:attribute name="size"/>
+          <xs:attribute name="color" type="Color"/>
+          <xs:attribute name="face"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ==================== Object ======================================
+
+    object is used to embed objects as part of HTML pages.
+    param elements should precede other content. Parameters
+    can also be expressed as attribute/value pairs on the
+    object element itself when brevity is desired.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="object">
+    <xs:complexType mixed="true">
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="param"/>
+        <xs:group ref="block"/>
+        <xs:element ref="form"/>
+        <xs:group ref="inline"/>
+        <xs:group ref="misc"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="declare">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="declare"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="classid" type="URI"/>
+      <xs:attribute name="codebase" type="URI"/>
+      <xs:attribute name="data" type="URI"/>
+      <xs:attribute name="type" type="ContentType"/>
+      <xs:attribute name="codetype" type="ContentType"/>
+      <xs:attribute name="archive" type="UriList"/>
+      <xs:attribute name="standby" type="Text"/>
+      <xs:attribute name="height" type="Length"/>
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="usemap" type="URI"/>
+      <xs:attribute name="name" type="xs:NMTOKEN"/>
+      <xs:attribute name="tabindex" type="Number"/>
+      <xs:attribute name="align" type="ImgAlign"/>
+      <xs:attribute name="border" type="Pixels"/>
+      <xs:attribute name="hspace" type="Pixels"/>
+      <xs:attribute name="vspace" type="Pixels"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="param">
+    <xs:annotation>
+      <xs:documentation>
+      param is used to supply a named property value.
+      In XML it would seem natural to follow RDF and support an
+      abbreviated syntax where the param elements are replaced
+      by attribute value pairs on the object start tag.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="name" use="required"/>
+      <xs:attribute name="value"/>
+      <xs:attribute name="valuetype" default="data">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="data"/>
+            <xs:enumeration value="ref"/>
+            <xs:enumeration value="object"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="type" type="ContentType"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Java applet ==================================
+
+    One of code or object attributes must be present.
+    Place param elements before other content.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="applet">
+    <xs:complexType mixed="true">
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="param"/>
+        <xs:group ref="block"/>
+        <xs:element ref="form"/>
+        <xs:group ref="inline"/>
+        <xs:group ref="misc"/>
+      </xs:choice>
+      <xs:attributeGroup ref="coreattrs"/>
+      <xs:attribute name="codebase" type="URI"/>
+      <xs:attribute name="archive"/>
+      <xs:attribute name="code"/>
+      <xs:attribute name="object"/>
+      <xs:attribute name="alt" type="Text"/>
+      <xs:attribute name="name" type="xs:NMTOKEN"/>
+      <xs:attribute name="width" use="required" type="Length"/>
+      <xs:attribute name="height" use="required" type="Length"/>
+      <xs:attribute name="align" type="ImgAlign"/>
+      <xs:attribute name="hspace" type="Pixels"/>
+      <xs:attribute name="vspace" type="Pixels"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Images ===========================================
+
+    To avoid accessibility problems for people who aren't
+    able to see the image, you should provide a text
+    description using the alt and longdesc attributes.
+    In addition, avoid the use of server-side image maps.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="img">
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="src" use="required" type="URI"/>
+      <xs:attribute name="alt" use="required" type="Text"/>
+      <xs:attribute name="name" type="xs:NMTOKEN"/>
+      <xs:attribute name="longdesc" type="URI"/>
+      <xs:attribute name="height" type="Length"/>
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="usemap" type="URI">
+  <xs:annotation>
+    <xs:documentation>
+          usemap points to a map element which may be in this document
+          or an external document, although the latter is not widely supported
+          </xs:documentation>
+  </xs:annotation>
+      </xs:attribute>
+      <xs:attribute name="ismap">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="ismap"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="align" type="ImgAlign"/>
+      <xs:attribute name="border" type="Length"/>
+      <xs:attribute name="hspace" type="Pixels"/>
+      <xs:attribute name="vspace" type="Pixels"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Client-side image maps ============================
+
+    These can be placed in the same document or grouped in a
+    separate document although this isn't yet widely supported
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="map">
+    <xs:complexType>
+      <xs:choice>
+        <xs:choice maxOccurs="unbounded">
+          <xs:group ref="block"/>
+          <xs:element ref="form"/>
+          <xs:group ref="misc"/>
+        </xs:choice>
+        <xs:element maxOccurs="unbounded" ref="area"/>
+      </xs:choice>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attributeGroup ref="events"/>
+      <xs:attribute name="id" use="required" type="xs:ID"/>
+      <xs:attribute name="class"/>
+      <xs:attribute name="style" type="StyleSheet"/>
+      <xs:attribute name="title" type="Text"/>
+      <xs:attribute name="name"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="area">
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="focus"/>
+      <xs:attribute name="shape" default="rect" type="Shape"/>
+      <xs:attribute name="coords" type="Coords"/>
+      <xs:attribute name="href" type="URI"/>
+      <xs:attribute name="nohref">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="nohref"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="alt" use="required" type="Text"/>
+      <xs:attribute name="target" type="FrameTarget"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Forms ===============================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="form">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="form.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="action" use="required" type="URI"/>
+          <xs:attribute name="name" type="xs:NMTOKEN"/>
+          <xs:attribute name="method" default="get">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="get"/>
+                <xs:enumeration value="post"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="enctype" type="ContentType"
+              default="application/x-www-form-urlencoded"/>
+          <xs:attribute name="onsubmit" type="Script"/>
+          <xs:attribute name="onreset" type="Script"/>
+          <xs:attribute name="accept" type="ContentTypes"/>
+          <xs:attribute name="accept-charset" type="Charsets"/>
+          <xs:attribute name="target" type="FrameTarget"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="label">
+    <xs:annotation>
+      <xs:documentation>
+      Each label must not contain more than ONE field
+      Label elements shouldn't be nested.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="for" type="xs:IDREF"/>
+          <xs:attribute name="accesskey" type="Character"/>
+          <xs:attribute name="onfocus" type="Script"/>
+          <xs:attribute name="onblur" type="Script"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="InputType">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="text"/>
+      <xs:enumeration value="password"/>
+      <xs:enumeration value="checkbox"/>
+      <xs:enumeration value="radio"/>
+      <xs:enumeration value="submit"/>
+      <xs:enumeration value="reset"/>
+      <xs:enumeration value="file"/>
+      <xs:enumeration value="hidden"/>
+      <xs:enumeration value="image"/>
+      <xs:enumeration value="button"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="input">
+    <xs:annotation>
+      <xs:documentation>
+      form control
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="focus"/>
+      <xs:attribute name="type" default="text" type="InputType"/>
+      <xs:attribute name="name">
+  <xs:annotation>
+    <xs:documentation>
+          the name attribute is required for all but submit &amp; reset
+          </xs:documentation>
+  </xs:annotation>
+      </xs:attribute>
+      <xs:attribute name="value"/>
+      <xs:attribute name="checked">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="checked"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="readonly">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="readonly"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="size"/>
+      <xs:attribute name="maxlength" type="Number"/>
+      <xs:attribute name="src" type="URI"/>
+      <xs:attribute name="alt"/>
+      <xs:attribute name="usemap" type="URI"/>
+      <xs:attribute name="onselect" type="Script"/>
+      <xs:attribute name="onchange" type="Script"/>
+      <xs:attribute name="accept" type="ContentTypes"/>
+      <xs:attribute name="align" type="ImgAlign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="select">
+    <xs:annotation>
+      <xs:documentation>
+      option selector
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:choice maxOccurs="unbounded">
+        <xs:element ref="optgroup"/>
+        <xs:element ref="option"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="size" type="Number"/>
+      <xs:attribute name="multiple">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="multiple"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="tabindex" type="tabindexNumber"/>
+      <xs:attribute name="onfocus" type="Script"/>
+      <xs:attribute name="onblur" type="Script"/>
+      <xs:attribute name="onchange" type="Script"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="optgroup">
+    <xs:annotation>
+      <xs:documentation>
+      option group
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="option"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="label" use="required" type="Text"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="option">
+    <xs:annotation>
+      <xs:documentation>
+      selectable choice
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="selected">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="selected"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="label" type="Text"/>
+      <xs:attribute name="value"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="textarea">
+    <xs:annotation>
+      <xs:documentation>
+      multi-line text field
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="focus"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="rows" use="required" type="Number"/>
+      <xs:attribute name="cols" use="required" type="Number"/>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="readonly">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="readonly"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="onselect" type="Script"/>
+      <xs:attribute name="onchange" type="Script"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="fieldset">
+    <xs:annotation>
+      <xs:documentation>
+      The fieldset element is used to group form fields.
+      Only one legend element should occur in the content
+      and if present should only be preceded by whitespace.
+
+      NOTE: this content model is different from the XHTML 1.0 DTD,
+      closer to the intended content model in HTML4 DTD
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:sequence>
+        <xs:element ref="legend"/>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:group ref="block"/>
+          <xs:element ref="form"/>
+          <xs:group ref="inline"/>
+          <xs:group ref="misc"/>
+        </xs:choice>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="LAlign">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="top"/>
+      <xs:enumeration value="bottom"/>
+      <xs:enumeration value="left"/>
+      <xs:enumeration value="right"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="legend">
+    <xs:annotation>
+      <xs:documentation>
+      fieldset label
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="accesskey" type="Character"/>
+          <xs:attribute name="align" type="LAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="button">
+    <xs:annotation>
+      <xs:documentation>
+      Content is "Flow" excluding a, form and form controls
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="button.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="focus"/>
+          <xs:attribute name="name"/>
+          <xs:attribute name="value"/>
+          <xs:attribute name="type" default="submit">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="button"/>
+                <xs:enumeration value="submit"/>
+                <xs:enumeration value="reset"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="disabled">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="disabled"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="isindex">
+    <xs:annotation>
+      <xs:documentation>
+      single-line text input control (DEPRECATED)
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="coreattrs"/>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="prompt" type="Text"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ======================= Tables =======================================
+
+    Derived from IETF HTML table standard, see [RFC1942]
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="TFrame">
+    <xs:annotation>
+      <xs:documentation>
+      The border attribute sets the thickness of the frame around the
+      table. The default units are screen pixels.
+
+      The frame attribute specifies which parts of the frame around
+      the table should be rendered. The values are not the same as
+      CALS to avoid a name clash with the valign attribute.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="void"/>
+      <xs:enumeration value="above"/>
+      <xs:enumeration value="below"/>
+      <xs:enumeration value="hsides"/>
+      <xs:enumeration value="lhs"/>
+      <xs:enumeration value="rhs"/>
+      <xs:enumeration value="vsides"/>
+      <xs:enumeration value="box"/>
+      <xs:enumeration value="border"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="TRules">
+    <xs:annotation>
+      <xs:documentation>
+      The rules attribute defines which rules to draw between cells:
+
+      If rules is absent then assume:
+          "none" if border is absent or border="0" otherwise "all"
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="none"/>
+      <xs:enumeration value="groups"/>
+      <xs:enumeration value="rows"/>
+      <xs:enumeration value="cols"/>
+      <xs:enumeration value="all"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="TAlign">
+    <xs:annotation>
+      <xs:documentation>
+      horizontal placement of table relative to document
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="left"/>
+      <xs:enumeration value="center"/>
+      <xs:enumeration value="right"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:attributeGroup name="cellhalign">
+    <xs:annotation>
+      <xs:documentation>
+      horizontal alignment attributes for cell contents
+
+      char        alignment char, e.g. char=":"
+      charoff     offset for alignment char
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="align">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="left"/>
+          <xs:enumeration value="center"/>
+          <xs:enumeration value="right"/>
+          <xs:enumeration value="justify"/>
+          <xs:enumeration value="char"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="char" type="Character"/>
+    <xs:attribute name="charoff" type="Length"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="cellvalign">
+    <xs:annotation>
+      <xs:documentation>
+      vertical alignment attributes for cell contents
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="valign">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="top"/>
+          <xs:enumeration value="middle"/>
+          <xs:enumeration value="bottom"/>
+          <xs:enumeration value="baseline"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:element name="table">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element minOccurs="0" ref="caption"/>
+        <xs:choice>
+          <xs:element minOccurs="0" maxOccurs="unbounded" ref="col"/>
+          <xs:element minOccurs="0" maxOccurs="unbounded" ref="colgroup"/>
+        </xs:choice>
+        <xs:element minOccurs="0" ref="thead"/>
+        <xs:element minOccurs="0" ref="tfoot"/>
+        <xs:choice>
+          <xs:element maxOccurs="unbounded" ref="tbody"/>
+          <xs:element maxOccurs="unbounded" ref="tr"/>
+        </xs:choice>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="summary" type="Text"/>
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="border" type="Pixels"/>
+      <xs:attribute name="frame" type="TFrame"/>
+      <xs:attribute name="rules" type="TRules"/>
+      <xs:attribute name="cellspacing" type="Length"/>
+      <xs:attribute name="cellpadding" type="Length"/>
+      <xs:attribute name="align" type="TAlign"/>
+      <xs:attribute name="bgcolor" type="Color"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="CAlign">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="top"/>
+      <xs:enumeration value="bottom"/>
+      <xs:enumeration value="left"/>
+      <xs:enumeration value="right"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="caption">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="align" type="CAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    Use thead to duplicate headers when breaking table
+    across page boundaries, or for static headers when
+    tbody sections are rendered in scrolling panel.
+
+    Use tfoot to duplicate footers when breaking table
+    across page boundaries, or for static footers when
+    tbody sections are rendered in scrolling panel.
+
+    Use multiple tbody sections when rules are needed
+    between groups of table rows.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="thead">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="tr"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tfoot">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="tr"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tbody">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="tr"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="colgroup">
+    <xs:annotation>
+      <xs:documentation>
+      colgroup groups a set of col elements. It allows you to group
+      several semantically related columns together.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element minOccurs="0" maxOccurs="unbounded" ref="col"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="span" default="1" type="Number"/>
+      <xs:attribute name="width" type="MultiLength"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="col">
+    <xs:annotation>
+      <xs:documentation>
+      col elements define the alignment properties for cells in
+      one or more columns.
+
+      The width attribute specifies the width of the columns, e.g.
+
+          width=64        width in screen pixels
+          width=0.5*      relative width of 0.5
+
+      The span attribute causes the attributes of one
+      col element to apply to more than one column.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="span" default="1" type="Number"/>
+      <xs:attribute name="width" type="MultiLength"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tr">
+    <xs:complexType>
+      <xs:choice maxOccurs="unbounded">
+        <xs:element ref="th"/>
+        <xs:element ref="td"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+      <xs:attribute name="bgcolor" type="Color"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="Scope">
+    <xs:annotation>
+      <xs:documentation>
+      Scope is simpler than headers attribute for common tables
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="row"/>
+      <xs:enumeration value="col"/>
+      <xs:enumeration value="rowgroup"/>
+      <xs:enumeration value="colgroup"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+    th is for headers, td for data and for cells acting as both
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="th">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="abbr" type="Text"/>
+          <xs:attribute name="axis"/>
+          <xs:attribute name="headers" type="xs:IDREFS"/>
+          <xs:attribute name="scope" type="Scope"/>
+          <xs:attribute name="rowspan" default="1" type="Number"/>
+          <xs:attribute name="colspan" default="1" type="Number"/>
+          <xs:attributeGroup ref="cellhalign"/>
+          <xs:attributeGroup ref="cellvalign"/>
+          <xs:attribute name="nowrap">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="nowrap"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="bgcolor" type="Color"/>
+          <xs:attribute name="width" type="Length"/>
+          <xs:attribute name="height" type="Length"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="td">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="abbr" type="Text"/>
+          <xs:attribute name="axis"/>
+          <xs:attribute name="headers" type="xs:IDREFS"/>
+          <xs:attribute name="scope" type="Scope"/>
+          <xs:attribute name="rowspan" default="1" type="Number"/>
+          <xs:attribute name="colspan" default="1" type="Number"/>
+          <xs:attributeGroup ref="cellhalign"/>
+          <xs:attributeGroup ref="cellvalign"/>
+          <xs:attribute name="nowrap">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="nowrap"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="bgcolor" type="Color"/>
+          <xs:attribute name="width" type="Length"/>
+          <xs:attribute name="height" type="Length"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+</xs:schema>
\ No newline at end of file
diff --git a/xml/impl/resources/standardSchemas/xhtml1-strict.dtd b/xml/impl/resources/standardSchemas/xhtml1-strict.dtd
new file mode 100644
index 0000000..c775f8b
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml1-strict.dtd
@@ -0,0 +1,978 @@
+<!--
+   Extensible HTML version 1.0 Strict DTD
+
+   This is the same as HTML 4 Strict except for
+   changes due to the differences between XML and SGML.
+
+   Namespace = http://www.w3.org/1999/xhtml
+
+   For further information, see: http://www.w3.org/TR/xhtml1
+
+   Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+   All Rights Reserved. 
+
+   This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+   PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+   SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+
+   $Revision: 1.1 $
+   $Date: 2004/09/17 17:05:38 $
+
+-->
+
+<!--================ Character mnemonic entities =========================-->
+
+<!ENTITY % HTMLlat1 PUBLIC
+   "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+   "xhtml-lat1.ent">
+%HTMLlat1;
+
+<!ENTITY % HTMLsymbol PUBLIC
+   "-//W3C//ENTITIES Symbols for XHTML//EN"
+   "xhtml-symbol.ent">
+%HTMLsymbol;
+
+<!ENTITY % HTMLspecial PUBLIC
+   "-//W3C//ENTITIES Special for XHTML//EN"
+   "xhtml-special.ent">
+%HTMLspecial;
+
+<!--================== Imported Names ====================================-->
+
+<!ENTITY % ContentType "CDATA">
+    <!-- media type, as per [RFC2045] -->
+
+<!ENTITY % ContentTypes "CDATA">
+    <!-- comma-separated list of media types, as per [RFC2045] -->
+
+<!ENTITY % Charset "CDATA">
+    <!-- a character encoding, as per [RFC2045] -->
+
+<!ENTITY % Charsets "CDATA">
+    <!-- a space separated list of character encodings, as per [RFC2045] -->
+
+<!ENTITY % LanguageCode "NMTOKEN">
+    <!-- a language code, as per [RFC3066] -->
+
+<!ENTITY % Character "CDATA">
+    <!-- a single character, as per section 2.2 of [XML] -->
+
+<!ENTITY % Number "CDATA">
+    <!-- one or more digits -->
+
+<!ENTITY % LinkTypes "CDATA">
+    <!-- space-separated list of link types -->
+
+<!ENTITY % MediaDesc "CDATA">
+    <!-- single or comma-separated list of media descriptors -->
+
+<!ENTITY % URI "CDATA">
+    <!-- a Uniform Resource Identifier, see [RFC2396] -->
+
+<!ENTITY % UriList "CDATA">
+    <!-- a space separated list of Uniform Resource Identifiers -->
+
+<!ENTITY % Datetime "CDATA">
+    <!-- date and time information. ISO date format -->
+
+<!ENTITY % Script "CDATA">
+    <!-- script expression -->
+
+<!ENTITY % StyleSheet "CDATA">
+    <!-- style sheet data -->
+
+<!ENTITY % Text "CDATA">
+    <!-- used for titles etc. -->
+
+<!ENTITY % Length "CDATA">
+    <!-- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % MultiLength "CDATA">
+    <!-- pixel, percentage, or relative -->
+
+<!ENTITY % Pixels "CDATA">
+    <!-- integer representing length in pixels -->
+
+<!-- these are used for image maps -->
+
+<!ENTITY % Shape "(rect|circle|poly|default)">
+
+<!ENTITY % Coords "CDATA">
+    <!-- comma separated list of lengths -->
+
+<!--=================== Generic Attributes ===============================-->
+
+<!-- core attributes common to most elements
+  id       document-wide unique id
+  class    space separated list of classes
+  style    associated style info
+  title    advisory title/amplification
+-->
+<!ENTITY % coreattrs
+ "id          ID             #IMPLIED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED"
+  >
+
+<!-- internationalization attributes
+  lang        language code (backwards compatible)
+  xml:lang    language code (as per XML 1.0 spec)
+  dir         direction for weak/neutral text
+-->
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #IMPLIED"
+  >
+
+<!-- attributes for common UI events
+  onclick     a pointer button was clicked
+  ondblclick  a pointer button was double clicked
+  onmousedown a pointer button was pressed down
+  onmouseup   a pointer button was released
+  onmousemove a pointer was moved onto the element
+  onmouseout  a pointer was moved away from the element
+  onkeypress  a key was pressed and released
+  onkeydown   a key was pressed down
+  onkeyup     a key was released
+-->
+<!ENTITY % events
+ "onclick     %Script;       #IMPLIED
+  ondblclick  %Script;       #IMPLIED
+  onmousedown %Script;       #IMPLIED
+  onmouseup   %Script;       #IMPLIED
+  onmouseover %Script;       #IMPLIED
+  onmousemove %Script;       #IMPLIED
+  onmouseout  %Script;       #IMPLIED
+  onkeypress  %Script;       #IMPLIED
+  onkeydown   %Script;       #IMPLIED
+  onkeyup     %Script;       #IMPLIED"
+  >
+
+<!-- attributes for elements that can get the focus
+  accesskey   accessibility key character
+  tabindex    position in tabbing order
+  onfocus     the element got the focus
+  onblur      the element lost the focus
+-->
+<!ENTITY % focus
+ "accesskey   %Character;    #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED"
+  >
+
+<!ENTITY % attrs "%coreattrs; %i18n; %events;">
+
+<!--=================== Text Elements ====================================-->
+
+<!ENTITY % special.pre
+   "br | span | bdo | map">
+
+
+<!ENTITY % special
+   "%special.pre; | object | img ">
+
+<!ENTITY % fontstyle "tt | i | b | big | small ">
+
+<!ENTITY % phrase "em | strong | dfn | code | q |
+                   samp | kbd | var | cite | abbr | acronym | sub | sup ">
+
+<!ENTITY % inline.forms "input | select | textarea | label | button">
+
+<!-- these can occur at block or inline level -->
+<!ENTITY % misc.inline "ins | del | script">
+
+<!-- these can only occur at block level -->
+<!ENTITY % misc "noscript | %misc.inline;">
+
+<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
+
+<!-- %Inline; covers inline or "text-level" elements -->
+<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
+
+<!--================== Block level elements ==============================-->
+
+<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
+<!ENTITY % lists "ul | ol | dl">
+<!ENTITY % blocktext "pre | hr | blockquote | address">
+
+<!ENTITY % block
+     "p | %heading; | div | %lists; | %blocktext; | fieldset | table">
+
+<!ENTITY % Block "(%block; | form | %misc;)*">
+
+<!-- %Flow; mixes block and inline and is used for list items etc. -->
+<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
+
+<!--================== Content models for exclusions =====================-->
+
+<!-- a elements use %Inline; excluding a -->
+
+<!ENTITY % a.content
+   "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
+
+<!-- pre uses %Inline excluding big, small, sup or sup -->
+
+<!ENTITY % pre.content
+   "(#PCDATA | a | %fontstyle; | %phrase; | %special.pre; | %misc.inline;
+      | %inline.forms;)*">
+
+<!-- form uses %Block; excluding form -->
+
+<!ENTITY % form.content "(%block; | %misc;)*">
+
+<!-- button uses %Flow; but excludes a, form and form controls -->
+
+<!ENTITY % button.content
+   "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
+    table | %special; | %fontstyle; | %phrase; | %misc;)*">
+
+<!--================ Document Structure ==================================-->
+
+<!-- the namespace URI designates the document profile -->
+
+<!ELEMENT html (head, body)>
+<!ATTLIST html
+  %i18n;
+  id          ID             #IMPLIED
+  xmlns       %URI;          #FIXED 'http://www.w3.org/1999/xhtml'
+  >
+
+<!--================ Document Head =======================================-->
+
+<!ENTITY % head.misc "(script|style|meta|link|object)*">
+
+<!-- content model is %head.misc; combined with a single
+     title and an optional base element in any order -->
+
+<!ELEMENT head (%head.misc;,
+     ((title, %head.misc;, (base, %head.misc;)?) |
+      (base, %head.misc;, (title, %head.misc;))))>
+
+<!ATTLIST head
+  %i18n;
+  id          ID             #IMPLIED
+  profile     %URI;          #IMPLIED
+  >
+
+<!-- The title element is not considered part of the flow of text.
+       It should be displayed, for example as the page header or
+       window title. Exactly one title is required per document.
+    -->
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title 
+  %i18n;
+  id          ID             #IMPLIED
+  >
+
+<!-- document base URI -->
+
+<!ELEMENT base EMPTY>
+<!ATTLIST base
+  href        %URI;          #REQUIRED
+  id          ID             #IMPLIED
+  >
+
+<!-- generic metainformation -->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+  %i18n;
+  id          ID             #IMPLIED
+  http-equiv  CDATA          #IMPLIED
+  name        CDATA          #IMPLIED
+  content     CDATA          #REQUIRED
+  scheme      CDATA          #IMPLIED
+  >
+
+<!--
+  Relationship values can be used in principle:
+
+   a) for document specific toolbars/menus when used
+      with the link element in document head e.g.
+        start, contents, previous, next, index, end, help
+   b) to link to a separate style sheet (rel="stylesheet")
+   c) to make a link to a script (rel="script")
+   d) by stylesheets to control how collections of
+      html nodes are rendered into printed documents
+   e) to make a link to a printable version of this document
+      e.g. a PostScript or PDF version (rel="alternate" media="print")
+-->
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+  %attrs;
+  charset     %Charset;      #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  type        %ContentType;  #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  media       %MediaDesc;    #IMPLIED
+  >
+
+<!-- style info, which may include CDATA sections -->
+<!ELEMENT style (#PCDATA)>
+<!ATTLIST style
+  %i18n;
+  id          ID             #IMPLIED
+  type        %ContentType;  #REQUIRED
+  media       %MediaDesc;    #IMPLIED
+  title       %Text;         #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- script statements, which may include CDATA sections -->
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+  id          ID             #IMPLIED
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #REQUIRED
+  src         %URI;          #IMPLIED
+  defer       (defer)        #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- alternate content container for non script-based rendering -->
+
+<!ELEMENT noscript %Block;>
+<!ATTLIST noscript
+  %attrs;
+  >
+
+<!--=================== Document Body ====================================-->
+
+<!ELEMENT body %Block;>
+<!ATTLIST body
+  %attrs;
+  onload          %Script;   #IMPLIED
+  onunload        %Script;   #IMPLIED
+  >
+
+<!ELEMENT div %Flow;>  <!-- generic language/style container -->
+<!ATTLIST div
+  %attrs;
+  >
+
+<!--=================== Paragraphs =======================================-->
+
+<!ELEMENT p %Inline;>
+<!ATTLIST p
+  %attrs;
+  >
+
+<!--=================== Headings =========================================-->
+
+<!--
+  There are six levels of headings from h1 (the most important)
+  to h6 (the least important).
+-->
+
+<!ELEMENT h1  %Inline;>
+<!ATTLIST h1
+   %attrs;
+   >
+
+<!ELEMENT h2 %Inline;>
+<!ATTLIST h2
+   %attrs;
+   >
+
+<!ELEMENT h3 %Inline;>
+<!ATTLIST h3
+   %attrs;
+   >
+
+<!ELEMENT h4 %Inline;>
+<!ATTLIST h4
+   %attrs;
+   >
+
+<!ELEMENT h5 %Inline;>
+<!ATTLIST h5
+   %attrs;
+   >
+
+<!ELEMENT h6 %Inline;>
+<!ATTLIST h6
+   %attrs;
+   >
+
+<!--=================== Lists ============================================-->
+
+<!-- Unordered list -->
+
+<!ELEMENT ul (li)+>
+<!ATTLIST ul
+  %attrs;
+  >
+
+<!-- Ordered (numbered) list -->
+
+<!ELEMENT ol (li)+>
+<!ATTLIST ol
+  %attrs;
+  >
+
+<!-- list item -->
+
+<!ELEMENT li %Flow;>
+<!ATTLIST li
+  %attrs;
+  >
+
+<!-- definition lists - dt for term, dd for its definition -->
+
+<!ELEMENT dl (dt|dd)+>
+<!ATTLIST dl
+  %attrs;
+  >
+
+<!ELEMENT dt %Inline;>
+<!ATTLIST dt
+  %attrs;
+  >
+
+<!ELEMENT dd %Flow;>
+<!ATTLIST dd
+  %attrs;
+  >
+
+<!--=================== Address ==========================================-->
+
+<!-- information on author -->
+
+<!ELEMENT address %Inline;>
+<!ATTLIST address
+  %attrs;
+  >
+
+<!--=================== Horizontal Rule ==================================-->
+
+<!ELEMENT hr EMPTY>
+<!ATTLIST hr
+  %attrs;
+  >
+
+<!--=================== Preformatted Text ================================-->
+
+<!-- content is %Inline; excluding "img|object|big|small|sub|sup" -->
+
+<!ELEMENT pre %pre.content;>
+<!ATTLIST pre
+  %attrs;
+  xml:space (preserve) #FIXED 'preserve'
+  >
+
+<!--=================== Block-like Quotes ================================-->
+
+<!ELEMENT blockquote %Block;>
+<!ATTLIST blockquote
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!--=================== Inserted/Deleted Text ============================-->
+
+<!--
+  ins/del are allowed in block and inline content, but its
+  inappropriate to include block content within an ins element
+  occurring in inline content.
+-->
+<!ELEMENT ins %Flow;>
+<!ATTLIST ins
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!ELEMENT del %Flow;>
+<!ATTLIST del
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!--================== The Anchor Element ================================-->
+
+<!-- content is %Inline; except that anchors shouldn't be nested -->
+
+<!ELEMENT a %a.content;>
+<!ATTLIST a
+  %attrs;
+  %focus;
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  >
+
+<!--===================== Inline Elements ================================-->
+
+<!ELEMENT span %Inline;> <!-- generic language/style container -->
+<!ATTLIST span
+  %attrs;
+  >
+
+<!ELEMENT bdo %Inline;>  <!-- I18N BiDi over-ride -->
+<!ATTLIST bdo
+  %coreattrs;
+  %events;
+  lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #REQUIRED
+  >
+
+<!ELEMENT br EMPTY>   <!-- forced line break -->
+<!ATTLIST br
+  %coreattrs;
+  >
+
+<!ELEMENT em %Inline;>   <!-- emphasis -->
+<!ATTLIST em %attrs;>
+
+<!ELEMENT strong %Inline;>   <!-- strong emphasis -->
+<!ATTLIST strong %attrs;>
+
+<!ELEMENT dfn %Inline;>   <!-- definitional -->
+<!ATTLIST dfn %attrs;>
+
+<!ELEMENT code %Inline;>   <!-- program code -->
+<!ATTLIST code %attrs;>
+
+<!ELEMENT samp %Inline;>   <!-- sample -->
+<!ATTLIST samp %attrs;>
+
+<!ELEMENT kbd %Inline;>  <!-- something user would type -->
+<!ATTLIST kbd %attrs;>
+
+<!ELEMENT var %Inline;>   <!-- variable -->
+<!ATTLIST var %attrs;>
+
+<!ELEMENT cite %Inline;>   <!-- citation -->
+<!ATTLIST cite %attrs;>
+
+<!ELEMENT abbr %Inline;>   <!-- abbreviation -->
+<!ATTLIST abbr %attrs;>
+
+<!ELEMENT acronym %Inline;>   <!-- acronym -->
+<!ATTLIST acronym %attrs;>
+
+<!ELEMENT q %Inline;>   <!-- inlined quote -->
+<!ATTLIST q
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!ELEMENT sub %Inline;> <!-- subscript -->
+<!ATTLIST sub %attrs;>
+
+<!ELEMENT sup %Inline;> <!-- superscript -->
+<!ATTLIST sup %attrs;>
+
+<!ELEMENT tt %Inline;>   <!-- fixed pitch font -->
+<!ATTLIST tt %attrs;>
+
+<!ELEMENT i %Inline;>   <!-- italic font -->
+<!ATTLIST i %attrs;>
+
+<!ELEMENT b %Inline;>   <!-- bold font -->
+<!ATTLIST b %attrs;>
+
+<!ELEMENT big %Inline;>   <!-- bigger font -->
+<!ATTLIST big %attrs;>
+
+<!ELEMENT small %Inline;>   <!-- smaller font -->
+<!ATTLIST small %attrs;>
+
+<!--==================== Object ======================================-->
+<!--
+  object is used to embed objects as part of HTML pages.
+  param elements should precede other content. Parameters
+  can also be expressed as attribute/value pairs on the
+  object element itself when brevity is desired.
+-->
+
+<!ELEMENT object (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST object
+  %attrs;
+  declare     (declare)      #IMPLIED
+  classid     %URI;          #IMPLIED
+  codebase    %URI;          #IMPLIED
+  data        %URI;          #IMPLIED
+  type        %ContentType;  #IMPLIED
+  codetype    %ContentType;  #IMPLIED
+  archive     %UriList;      #IMPLIED
+  standby     %Text;         #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  >
+
+<!--
+  param is used to supply a named property value.
+  In XML it would seem natural to follow RDF and support an
+  abbreviated syntax where the param elements are replaced
+  by attribute value pairs on the object start tag.
+-->
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+  id          ID             #IMPLIED
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  valuetype   (data|ref|object) "data"
+  type        %ContentType;  #IMPLIED
+  >
+
+<!--=================== Images ===========================================-->
+
+<!--
+   To avoid accessibility problems for people who aren't
+   able to see the image, you should provide a text
+   description using the alt and longdesc attributes.
+   In addition, avoid the use of server-side image maps.
+   Note that in this DTD there is no name attribute. That
+   is only available in the transitional and frameset DTD.
+-->
+
+<!ELEMENT img EMPTY>
+<!ATTLIST img
+  %attrs;
+  src         %URI;          #REQUIRED
+  alt         %Text;         #REQUIRED
+  longdesc    %URI;          #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  ismap       (ismap)        #IMPLIED
+  >
+
+<!-- usemap points to a map element which may be in this document
+  or an external document, although the latter is not widely supported -->
+
+<!--================== Client-side image maps ============================-->
+
+<!-- These can be placed in the same document or grouped in a
+     separate document although this isn't yet widely supported -->
+
+<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
+<!ATTLIST map
+  %i18n;
+  %events;
+  id          ID             #REQUIRED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  >
+
+<!ELEMENT area EMPTY>
+<!ATTLIST area
+  %attrs;
+  %focus;
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  href        %URI;          #IMPLIED
+  nohref      (nohref)       #IMPLIED
+  alt         %Text;         #REQUIRED
+  >
+
+<!--================ Forms ===============================================-->
+<!ELEMENT form %form.content;>   <!-- forms shouldn't be nested -->
+
+<!ATTLIST form
+  %attrs;
+  action      %URI;          #REQUIRED
+  method      (get|post)     "get"
+  enctype     %ContentType;  "application/x-www-form-urlencoded"
+  onsubmit    %Script;       #IMPLIED
+  onreset     %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  accept-charset %Charsets;  #IMPLIED
+  >
+
+<!--
+  Each label must not contain more than ONE field
+  Label elements shouldn't be nested.
+-->
+<!ELEMENT label %Inline;>
+<!ATTLIST label
+  %attrs;
+  for         IDREF          #IMPLIED
+  accesskey   %Character;    #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  >
+
+<!ENTITY % InputType
+  "(text | password | checkbox |
+    radio | submit | reset |
+    file | hidden | image | button)"
+   >
+
+<!-- the name attribute is required for all but submit & reset -->
+
+<!ELEMENT input EMPTY>     <!-- form control -->
+<!ATTLIST input
+  %attrs;
+  %focus;
+  type        %InputType;    "text"
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  checked     (checked)      #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  size        CDATA          #IMPLIED
+  maxlength   %Number;       #IMPLIED
+  src         %URI;          #IMPLIED
+  alt         CDATA          #IMPLIED
+  usemap      %URI;          #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  >
+
+<!ELEMENT select (optgroup|option)+>  <!-- option selector -->
+<!ATTLIST select
+  %attrs;
+  name        CDATA          #IMPLIED
+  size        %Number;       #IMPLIED
+  multiple    (multiple)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!ELEMENT optgroup (option)+>   <!-- option group -->
+<!ATTLIST optgroup
+  %attrs;
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #REQUIRED
+  >
+
+<!ELEMENT option (#PCDATA)>     <!-- selectable choice -->
+<!ATTLIST option
+  %attrs;
+  selected    (selected)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #IMPLIED
+  value       CDATA          #IMPLIED
+  >
+
+<!ELEMENT textarea (#PCDATA)>     <!-- multi-line text field -->
+<!ATTLIST textarea
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  rows        %Number;       #REQUIRED
+  cols        %Number;       #REQUIRED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!--
+  The fieldset element is used to group form fields.
+  Only one legend element should occur in the content
+  and if present should only be preceded by whitespace.
+-->
+<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
+<!ATTLIST fieldset
+  %attrs;
+  >
+
+<!ELEMENT legend %Inline;>     <!-- fieldset label -->
+<!ATTLIST legend
+  %attrs;
+  accesskey   %Character;    #IMPLIED
+  >
+
+<!--
+ Content is %Flow; excluding a, form and form controls
+--> 
+<!ELEMENT button %button.content;>  <!-- push button -->
+<!ATTLIST button
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  type        (button|submit|reset) "submit"
+  disabled    (disabled)     #IMPLIED
+  >
+
+<!--======================= Tables =======================================-->
+
+<!-- Derived from IETF HTML table standard, see [RFC1942] -->
+
+<!--
+ The border attribute sets the thickness of the frame around the
+ table. The default units are screen pixels.
+
+ The frame attribute specifies which parts of the frame around
+ the table should be rendered. The values are not the same as
+ CALS to avoid a name clash with the valign attribute.
+-->
+<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
+
+<!--
+ The rules attribute defines which rules to draw between cells:
+
+ If rules is absent then assume:
+     "none" if border is absent or border="0" otherwise "all"
+-->
+
+<!ENTITY % TRules "(none | groups | rows | cols | all)">
+  
+<!-- horizontal alignment attributes for cell contents
+
+  char        alignment char, e.g. char=':'
+  charoff     offset for alignment char
+-->
+<!ENTITY % cellhalign
+  "align      (left|center|right|justify|char) #IMPLIED
+   char       %Character;    #IMPLIED
+   charoff    %Length;       #IMPLIED"
+  >
+
+<!-- vertical alignment attributes for cell contents -->
+<!ENTITY % cellvalign
+  "valign     (top|middle|bottom|baseline) #IMPLIED"
+  >
+
+<!ELEMENT table
+     (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
+<!ELEMENT caption  %Inline;>
+<!ELEMENT thead    (tr)+>
+<!ELEMENT tfoot    (tr)+>
+<!ELEMENT tbody    (tr)+>
+<!ELEMENT colgroup (col)*>
+<!ELEMENT col      EMPTY>
+<!ELEMENT tr       (th|td)+>
+<!ELEMENT th       %Flow;>
+<!ELEMENT td       %Flow;>
+
+<!ATTLIST table
+  %attrs;
+  summary     %Text;         #IMPLIED
+  width       %Length;       #IMPLIED
+  border      %Pixels;       #IMPLIED
+  frame       %TFrame;       #IMPLIED
+  rules       %TRules;       #IMPLIED
+  cellspacing %Length;       #IMPLIED
+  cellpadding %Length;       #IMPLIED
+  >
+
+<!ATTLIST caption
+  %attrs;
+  >
+
+<!--
+colgroup groups a set of col elements. It allows you to group
+several semantically related columns together.
+-->
+<!ATTLIST colgroup
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+ col elements define the alignment properties for cells in
+ one or more columns.
+
+ The width attribute specifies the width of the columns, e.g.
+
+     width=64        width in screen pixels
+     width=0.5*      relative width of 0.5
+
+ The span attribute causes the attributes of one
+ col element to apply to more than one column.
+-->
+<!ATTLIST col
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+    Use thead to duplicate headers when breaking table
+    across page boundaries, or for static headers when
+    tbody sections are rendered in scrolling panel.
+
+    Use tfoot to duplicate footers when breaking table
+    across page boundaries, or for static footers when
+    tbody sections are rendered in scrolling panel.
+
+    Use multiple tbody sections when rules are needed
+    between groups of table rows.
+-->
+<!ATTLIST thead
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tfoot
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tbody
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tr
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+
+<!-- Scope is simpler than headers attribute for common tables -->
+<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
+
+<!-- th is for headers, td for data and for cells acting as both -->
+
+<!ATTLIST th
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST td
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  >
+
diff --git a/xml/impl/resources/standardSchemas/xhtml1-strict.xsd b/xml/impl/resources/standardSchemas/xhtml1-strict.xsd
new file mode 100644
index 0000000..fb70899
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml1-strict.xsd
@@ -0,0 +1,2212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema version="1.0" xml:lang="en"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    targetNamespace="http://www.w3.org/1999/xhtml"
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:xml="http://www.w3.org/XML/1998/namespace"
+    elementFormDefault="qualified">
+
+  <xs:annotation>
+    <xs:documentation>
+    XHTML 1.0 (Second Edition) Strict in XML Schema
+
+    This is the same as HTML 4 Strict except for
+    changes due to the differences between XML and SGML.
+
+    Namespace = http://www.w3.org/1999/xhtml
+
+    For further information, see: http://www.w3.org/TR/xhtml1
+
+    Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+    All Rights Reserved.
+
+    The DTD version is identified by the PUBLIC and SYSTEM identifiers:
+
+    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+
+    $Id: xhtml1-strict.xsd,v 1.2 2002/08/28 08:05:44 mimasa Exp $
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:import namespace="http://www.w3.org/XML/1998/namespace"
+      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Character mnemonic entities =========================
+
+    XHTML entity sets are identified by the PUBLIC and SYSTEM identifiers:
+
+    PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"
+
+    PUBLIC "-//W3C//ENTITIES Special for XHTML//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent"
+
+    PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent"
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Imported Names ====================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="ContentType">
+    <xs:annotation>
+      <xs:documentation>
+      media type, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="ContentTypes">
+    <xs:annotation>
+      <xs:documentation>
+      comma-separated list of media types, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Charset">
+    <xs:annotation>
+      <xs:documentation>
+      a character encoding, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Charsets">
+    <xs:annotation>
+      <xs:documentation>
+      a space separated list of character encodings, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="LanguageCode">
+    <xs:annotation>
+      <xs:documentation>
+      a language code, as per [RFC3066]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:language"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Character">
+    <xs:annotation>
+      <xs:documentation>
+      a single character, as per section 2.2 of [XML]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:length value="1" fixed="true"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Number">
+    <xs:annotation>
+      <xs:documentation>
+      one or more digits
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:nonNegativeInteger">
+      <xs:pattern value="[0-9]+"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="tabindexNumber">
+    <xs:annotation>
+      <xs:documentation>
+      tabindex attribute specifies the position of the current element
+      in the tabbing order for the current document. This value must be
+      a number between 0 and 32767. User agents should ignore leading zeros.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="Number">
+      <xs:minInclusive value="0"/>
+      <xs:maxInclusive value="32767"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="LinkTypes">
+    <xs:annotation>
+      <xs:documentation>
+      space-separated list of link types
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:NMTOKENS"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="MediaDesc">
+    <xs:annotation>
+      <xs:documentation>
+      single or comma-separated list of media descriptors
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[^,]+(,\s*[^,]+)*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="URI">
+    <xs:annotation>
+      <xs:documentation>
+      a Uniform Resource Identifier, see [RFC2396]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:anyURI"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="UriList">
+    <xs:annotation>
+      <xs:documentation>
+      a space separated list of Uniform Resource Identifiers
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Datetime">
+    <xs:annotation>
+      <xs:documentation>
+      date and time information. ISO date format
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:dateTime"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Script">
+    <xs:annotation>
+      <xs:documentation>
+      script expression
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="StyleSheet">
+    <xs:annotation>
+      <xs:documentation>
+      style sheet data
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Text">
+    <xs:annotation>
+      <xs:documentation>
+      used for titles etc.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Length">
+    <xs:annotation>
+      <xs:documentation>
+      nn for pixels or nn% for percentage length
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[\-+]?(\d+|\d+(\.\d+)?%)"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="MultiLength">
+    <xs:annotation>
+      <xs:documentation>
+      pixel, percentage, or relative
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[\-+]?(\d+|\d+(\.\d+)?%)|[1-9]?(\d+)?\*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Pixels">
+    <xs:annotation>
+      <xs:documentation>
+      integer representing length in pixels
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:nonNegativeInteger"/>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+    these are used for image maps
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="Shape">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="rect"/>
+      <xs:enumeration value="circle"/>
+      <xs:enumeration value="poly"/>
+      <xs:enumeration value="default"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Coords">
+    <xs:annotation>
+      <xs:documentation>
+      comma separated list of lengths
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern
+          value="[\-+]?(\d+|\d+(\.\d+)?%)(,\s*[\-+]?(\d+|\d+(\.\d+)?%))*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Generic Attributes ===============================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:attributeGroup name="coreattrs">
+    <xs:annotation>
+      <xs:documentation>
+      core attributes common to most elements
+      id       document-wide unique id
+      class    space separated list of classes
+      style    associated style info
+      title    advisory title/amplification
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="id" type="xs:ID"/>
+    <xs:attribute name="class" type="xs:NMTOKENS"/>
+    <xs:attribute name="style" type="StyleSheet"/>
+    <xs:attribute name="title" type="Text"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="i18n">
+    <xs:annotation>
+      <xs:documentation>
+      internationalization attributes
+      lang        language code (backwards compatible)
+      xml:lang    language code (as per XML 1.0 spec)
+      dir         direction for weak/neutral text
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="lang" type="LanguageCode"/>
+    <xs:attribute ref="xml:lang"/>
+    <xs:attribute name="dir">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="ltr"/>
+          <xs:enumeration value="rtl"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="events">
+    <xs:annotation>
+      <xs:documentation>
+      attributes for common UI events
+      onclick     a pointer button was clicked
+      ondblclick  a pointer button was double clicked
+      onmousedown a pointer button was pressed down
+      onmouseup   a pointer button was released
+      onmousemove a pointer was moved onto the element
+      onmouseout  a pointer was moved away from the element
+      onkeypress  a key was pressed and released
+      onkeydown   a key was pressed down
+      onkeyup     a key was released
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="onclick" type="Script"/>
+    <xs:attribute name="ondblclick" type="Script"/>
+    <xs:attribute name="onmousedown" type="Script"/>
+    <xs:attribute name="onmouseup" type="Script"/>
+    <xs:attribute name="onmouseover" type="Script"/>
+    <xs:attribute name="onmousemove" type="Script"/>
+    <xs:attribute name="onmouseout" type="Script"/>
+    <xs:attribute name="onkeypress" type="Script"/>
+    <xs:attribute name="onkeydown" type="Script"/>
+    <xs:attribute name="onkeyup" type="Script"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="focus">
+    <xs:annotation>
+      <xs:documentation>
+      attributes for elements that can get the focus
+      accesskey   accessibility key character
+      tabindex    position in tabbing order
+      onfocus     the element got the focus
+      onblur      the element lost the focus
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="accesskey" type="Character"/>
+    <xs:attribute name="tabindex" type="tabindexNumber"/>
+    <xs:attribute name="onfocus" type="Script"/>
+    <xs:attribute name="onblur" type="Script"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="attrs">
+    <xs:attributeGroup ref="coreattrs"/>
+    <xs:attributeGroup ref="i18n"/>
+    <xs:attributeGroup ref="events"/>
+  </xs:attributeGroup>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Text Elements ====================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:group name="special.pre">
+    <xs:choice>
+      <xs:element ref="br"/>
+      <xs:element ref="span"/>
+      <xs:element ref="bdo"/>
+      <xs:element ref="map"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="special">
+    <xs:choice>
+      <xs:group ref="special.pre"/>
+      <xs:element ref="object"/>
+      <xs:element ref="img"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="fontstyle">
+    <xs:choice>
+      <xs:element ref="tt"/>
+      <xs:element ref="i"/>
+      <xs:element ref="b"/>
+      <xs:element ref="big"/>
+      <xs:element ref="small"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="phrase">
+    <xs:choice>
+      <xs:element ref="em"/>
+      <xs:element ref="strong"/>
+      <xs:element ref="dfn"/>
+      <xs:element ref="code"/>
+      <xs:element ref="q"/>
+      <xs:element ref="samp"/>
+      <xs:element ref="kbd"/>
+      <xs:element ref="var"/>
+      <xs:element ref="cite"/>
+      <xs:element ref="abbr"/>
+      <xs:element ref="acronym"/>
+      <xs:element ref="sub"/>
+      <xs:element ref="sup"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="inline.forms">
+    <xs:choice>
+      <xs:element ref="input"/>
+      <xs:element ref="select"/>
+      <xs:element ref="textarea"/>
+      <xs:element ref="label"/>
+      <xs:element ref="button"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="misc.inline">
+    <xs:choice>
+      <xs:element ref="ins"/>
+      <xs:element ref="del"/>
+      <xs:element ref="script"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="misc">
+    <xs:annotation>
+      <xs:documentation>
+      these can only occur at block level
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice>
+      <xs:element ref="noscript"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="inline">
+    <xs:choice>
+      <xs:element ref="a"/>
+      <xs:group ref="special"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="inline.forms"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:complexType name="Inline" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      "Inline" covers inline or "text-level" elements
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="inline"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Block level elements ==============================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:group name="heading">
+    <xs:choice>
+      <xs:element ref="h1"/>
+      <xs:element ref="h2"/>
+      <xs:element ref="h3"/>
+      <xs:element ref="h4"/>
+      <xs:element ref="h5"/>
+      <xs:element ref="h6"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="lists">
+    <xs:choice>
+      <xs:element ref="ul"/>
+      <xs:element ref="ol"/>
+      <xs:element ref="dl"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="blocktext">
+    <xs:choice>
+      <xs:element ref="pre"/>
+      <xs:element ref="hr"/>
+      <xs:element ref="blockquote"/>
+      <xs:element ref="address"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="block">
+    <xs:choice>
+      <xs:element ref="p"/>
+      <xs:group ref="heading"/>
+      <xs:element ref="div"/>
+      <xs:group ref="lists"/>
+      <xs:group ref="blocktext"/>
+      <xs:element ref="fieldset"/>
+      <xs:element ref="table"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:complexType name="Block">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="block"/>
+      <xs:element ref="form"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="Flow" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      "Flow" mixes block and inline and is used for list items etc.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="block"/>
+      <xs:element ref="form"/>
+      <xs:group ref="inline"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Content models for exclusions =====================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:complexType name="a.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      a elements use "Inline" excluding a
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="special"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="inline.forms"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="pre.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      pre uses "Inline" excluding big, small, sup or sup
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="a"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="special.pre"/>
+      <xs:group ref="misc.inline"/>
+      <xs:group ref="inline.forms"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="form.content">
+    <xs:annotation>
+      <xs:documentation>
+      form uses "Block" excluding form
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="block"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="button.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      button uses "Flow" but excludes a, form and form controls
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="p"/>
+      <xs:group ref="heading"/>
+      <xs:element ref="div"/>
+      <xs:group ref="lists"/>
+      <xs:group ref="blocktext"/>
+      <xs:element ref="table"/>
+      <xs:group ref="special"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Document Structure ==================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="html">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element ref="head"/>
+        <xs:element ref="body"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Document Head =======================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:group name="head.misc">
+    <xs:sequence>
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="script"/>
+        <xs:element ref="style"/>
+        <xs:element ref="meta"/>
+        <xs:element ref="link"/>
+        <xs:element ref="object"/>
+      </xs:choice>
+    </xs:sequence>
+  </xs:group>
+
+  <xs:element name="head">
+    <xs:annotation>
+      <xs:documentation>
+      content model is "head.misc" combined with a single
+      title and an optional base element in any order
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:group ref="head.misc"/>
+        <xs:choice>
+          <xs:sequence>
+            <xs:element ref="title"/>
+            <xs:group ref="head.misc"/>
+            <xs:sequence minOccurs="0">
+              <xs:element ref="base"/>
+              <xs:group ref="head.misc"/>
+            </xs:sequence>
+          </xs:sequence>
+          <xs:sequence>
+            <xs:element ref="base"/>
+            <xs:group ref="head.misc"/>
+            <xs:element ref="title"/>
+            <xs:group ref="head.misc"/>
+          </xs:sequence>
+        </xs:choice>
+      </xs:sequence>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="profile" type="URI"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="title">
+    <xs:annotation>
+      <xs:documentation>
+      The title element is not considered part of the flow of text.
+      It should be displayed, for example as the page header or
+      window title. Exactly one title is required per document.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="base">
+    <xs:annotation>
+      <xs:documentation>
+      document base URI
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attribute name="href" use="required" type="URI"/>
+      <xs:attribute name="id" type="xs:ID"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="meta">
+    <xs:annotation>
+      <xs:documentation>
+      generic metainformation
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="http-equiv"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="content" use="required"/>
+      <xs:attribute name="scheme"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="link">
+    <xs:annotation>
+      <xs:documentation>
+      Relationship values can be used in principle:
+
+      a) for document specific toolbars/menus when used
+         with the link element in document head e.g.
+           start, contents, previous, next, index, end, help
+      b) to link to a separate style sheet (rel="stylesheet")
+      c) to make a link to a script (rel="script")
+      d) by stylesheets to control how collections of
+         html nodes are rendered into printed documents
+      e) to make a link to a printable version of this document
+         e.g. a PostScript or PDF version (rel="alternate" media="print")
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="charset" type="Charset"/>
+      <xs:attribute name="href" type="URI"/>
+      <xs:attribute name="hreflang" type="LanguageCode"/>
+      <xs:attribute name="type" type="ContentType"/>
+      <xs:attribute name="rel" type="LinkTypes"/>
+      <xs:attribute name="rev" type="LinkTypes"/>
+      <xs:attribute name="media" type="MediaDesc"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="style">
+    <xs:annotation>
+      <xs:documentation>
+      style info, which may include CDATA sections
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="type" use="required" type="ContentType"/>
+      <xs:attribute name="media" type="MediaDesc"/>
+      <xs:attribute name="title" type="Text"/>
+      <xs:attribute ref="xml:space" fixed="preserve"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="script">
+    <xs:annotation>
+      <xs:documentation>
+      script statements, which may include CDATA sections
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="charset" type="Charset"/>
+      <xs:attribute name="type" use="required" type="ContentType"/>
+      <xs:attribute name="src" type="URI"/>
+      <xs:attribute name="defer">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="defer"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute ref="xml:space" fixed="preserve"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="noscript">
+    <xs:annotation>
+      <xs:documentation>
+      alternate content container for non script-based rendering
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="Block">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Document Body ====================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="body">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="Block">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="onload" type="Script"/>
+          <xs:attribute name="onunload" type="Script"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="div">
+    <xs:annotation>
+      <xs:documentation>
+      generic language/style container
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Paragraphs =======================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="p">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Headings =========================================
+
+    There are six levels of headings from h1 (the most important)
+    to h6 (the least important).
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="h1">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h2">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h3">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h4">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h5">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h6">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Lists ============================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="ul">
+    <xs:annotation>
+      <xs:documentation>
+      Unordered list
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="ol">
+    <xs:annotation>
+      <xs:documentation>
+      Ordered (numbered) list
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="li">
+    <xs:annotation>
+      <xs:documentation>
+      list item
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    definition lists - dt for term, dd for its definition
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="dl">
+    <xs:complexType>
+      <xs:choice maxOccurs="unbounded">
+        <xs:element ref="dt"/>
+        <xs:element ref="dd"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dt">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dd">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Address ==========================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="address">
+    <xs:annotation>
+      <xs:documentation>
+      information on author
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Horizontal Rule ==================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="hr">
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Preformatted Text ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="pre">
+    <xs:annotation>
+      <xs:documentation>
+      content is "Inline" excluding "img|object|big|small|sub|sup"
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="pre.content">
+           <xs:attributeGroup ref="attrs"/>
+           <xs:attribute ref="xml:space" fixed="preserve"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Block-like Quotes ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="blockquote">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="Block">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Inserted/Deleted Text ============================
+
+    ins/del are allowed in block and inline content, but its
+    inappropriate to include block content within an ins element
+    occurring in inline content.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="ins">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+          <xs:attribute name="datetime" type="Datetime"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="del">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+          <xs:attribute name="datetime" type="Datetime"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== The Anchor Element ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="a">
+    <xs:annotation>
+      <xs:documentation>
+      content is "Inline" except that anchors shouldn't be nested
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="a.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="focus"/>
+          <xs:attribute name="charset" type="Charset"/>
+          <xs:attribute name="type" type="ContentType"/>
+          <xs:attribute name="name" type="xs:ID"/>
+          <xs:attribute name="href" type="URI"/>
+          <xs:attribute name="hreflang" type="LanguageCode"/>
+          <xs:attribute name="rel" type="LinkTypes"/>
+          <xs:attribute name="rev" type="LinkTypes"/>
+          <xs:attribute name="shape" default="rect" type="Shape"/>
+          <xs:attribute name="coords" type="Coords"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ===================== Inline Elements ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="span">
+    <xs:annotation>
+      <xs:documentation>
+      generic language/style container
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="bdo">
+    <xs:annotation>
+      <xs:documentation>
+      I18N BiDi over-ride
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="coreattrs"/>
+          <xs:attributeGroup ref="events"/>
+          <xs:attribute name="lang" type="LanguageCode"/>
+          <xs:attribute ref="xml:lang"/>
+          <xs:attribute name="dir" use="required">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="ltr"/>
+                <xs:enumeration value="rtl"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="br">
+    <xs:annotation>
+      <xs:documentation>
+      forced line break
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="coreattrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="em">
+    <xs:annotation>
+      <xs:documentation>
+      emphasis
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="strong">
+    <xs:annotation>
+      <xs:documentation>
+      strong emphasis
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dfn">
+    <xs:annotation>
+      <xs:documentation>
+      definitional
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="code">
+    <xs:annotation>
+      <xs:documentation>
+      program code
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="samp">
+    <xs:annotation>
+      <xs:documentation>
+      sample
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="kbd">
+    <xs:annotation>
+      <xs:documentation>
+      something user would type
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="var">
+    <xs:annotation>
+      <xs:documentation>
+      variable
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="cite">
+    <xs:annotation>
+      <xs:documentation>
+      citation
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="abbr">
+    <xs:annotation>
+      <xs:documentation>
+      abbreviation
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="acronym">
+    <xs:annotation>
+      <xs:documentation>
+      acronym
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="q">
+    <xs:annotation>
+      <xs:documentation>
+      inlined quote
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="sub">
+    <xs:annotation>
+      <xs:documentation>
+      subscript
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="sup">
+    <xs:annotation>
+      <xs:documentation>
+      superscript
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tt">
+    <xs:annotation>
+      <xs:documentation>
+      fixed pitch font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="i">
+    <xs:annotation>
+      <xs:documentation>
+      italic font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="b">
+    <xs:annotation>
+      <xs:documentation>
+      bold font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="big">
+    <xs:annotation>
+      <xs:documentation>
+      bigger font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="small">
+    <xs:annotation>
+      <xs:documentation>
+      smaller font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ==================== Object ======================================
+
+    object is used to embed objects as part of HTML pages.
+    param elements should precede other content. Parameters
+    can also be expressed as attribute/value pairs on the
+    object element itself when brevity is desired.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="object">
+    <xs:complexType mixed="true">
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="param"/>
+        <xs:group ref="block"/>
+        <xs:element ref="form"/>
+        <xs:group ref="inline"/>
+        <xs:group ref="misc"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="declare">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="declare"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="classid" type="URI"/>
+      <xs:attribute name="codebase" type="URI"/>
+      <xs:attribute name="data" type="URI"/>
+      <xs:attribute name="type" type="ContentType"/>
+      <xs:attribute name="codetype" type="ContentType"/>
+      <xs:attribute name="archive" type="UriList"/>
+      <xs:attribute name="standby" type="Text"/>
+      <xs:attribute name="height" type="Length"/>
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="usemap" type="URI"/>
+      <xs:attribute name="name" type="xs:NMTOKEN"/>
+      <xs:attribute name="tabindex" type="tabindexNumber"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="param">
+    <xs:annotation>
+      <xs:documentation>
+      param is used to supply a named property value.
+      In XML it would seem natural to follow RDF and support an
+      abbreviated syntax where the param elements are replaced
+      by attribute value pairs on the object start tag.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="value"/>
+      <xs:attribute name="valuetype" default="data">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="data"/>
+            <xs:enumeration value="ref"/>
+            <xs:enumeration value="object"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="type" type="ContentType"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Images ===========================================
+
+    To avoid accessibility problems for people who aren't
+    able to see the image, you should provide a text
+    description using the alt and longdesc attributes.
+    In addition, avoid the use of server-side image maps.
+    Note that in this DTD there is no name attribute. That
+    is only available in the transitional and frameset DTD.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="img">
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="src" use="required" type="URI"/>
+      <xs:attribute name="alt" use="required" type="Text"/>
+      <xs:attribute name="longdesc" type="URI"/>
+      <xs:attribute name="height" type="Length"/>
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="usemap" type="URI">
+  <xs:annotation>
+    <xs:documentation>
+          usemap points to a map element which may be in this document
+          or an external document, although the latter is not widely supported
+          </xs:documentation>
+  </xs:annotation>
+      </xs:attribute>
+      <xs:attribute name="ismap">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="ismap"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Client-side image maps ============================
+
+    These can be placed in the same document or grouped in a
+    separate document although this isn't yet widely supported
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="map">
+    <xs:complexType>
+      <xs:choice>
+        <xs:choice maxOccurs="unbounded">
+          <xs:group ref="block"/>
+          <xs:element ref="form"/>
+          <xs:group ref="misc"/>
+        </xs:choice>
+        <xs:element maxOccurs="unbounded" ref="area"/>
+      </xs:choice>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attributeGroup ref="events"/>
+      <xs:attribute name="id" use="required" type="xs:ID"/>
+      <xs:attribute name="class"/>
+      <xs:attribute name="style" type="StyleSheet"/>
+      <xs:attribute name="title" type="Text"/>
+      <xs:attribute name="name" type="xs:NMTOKEN"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="area">
+    <xs:complexType>
+        <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="focus"/>
+      <xs:attribute name="shape" default="rect" type="Shape"/>
+      <xs:attribute name="coords" type="Coords"/>
+      <xs:attribute name="href" type="URI"/>
+      <xs:attribute name="nohref">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="nohref"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="alt" use="required" type="Text"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Forms ===============================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="form">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="form.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="action" use="required" type="URI"/>
+          <xs:attribute name="name" type="xs:NMTOKEN"/>
+          <xs:attribute name="method" default="get">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="get"/>
+                <xs:enumeration value="post"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="enctype" type="ContentType"
+              default="application/x-www-form-urlencoded"/>
+          <xs:attribute name="onsubmit" type="Script"/>
+          <xs:attribute name="onreset" type="Script"/>
+          <xs:attribute name="accept" type="ContentTypes"/>
+          <xs:attribute name="accept-charset" type="Charsets"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="label">
+    <xs:annotation>
+      <xs:documentation>
+      Each label must not contain more than ONE field
+      Label elements shouldn't be nested.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="for" type="xs:IDREF"/>
+          <xs:attribute name="accesskey" type="Character"/>
+          <xs:attribute name="onfocus" type="Script"/>
+          <xs:attribute name="onblur" type="Script"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="InputType">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="text"/>
+      <xs:enumeration value="password"/>
+      <xs:enumeration value="checkbox"/>
+      <xs:enumeration value="radio"/>
+      <xs:enumeration value="submit"/>
+      <xs:enumeration value="reset"/>
+      <xs:enumeration value="file"/>
+      <xs:enumeration value="hidden"/>
+      <xs:enumeration value="image"/>
+      <xs:enumeration value="button"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="input">
+    <xs:annotation>
+      <xs:documentation>
+      form control
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="focus"/>
+      <xs:attribute name="type" default="text" type="InputType"/>
+      <xs:attribute name="name">
+  <xs:annotation>
+    <xs:documentation>
+          the name attribute is required for all but submit &amp; reset
+          </xs:documentation>
+  </xs:annotation>
+      </xs:attribute>
+      <xs:attribute name="value"/>
+      <xs:attribute name="checked">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="checked"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="readonly">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="readonly"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="size"/>
+      <xs:attribute name="maxlength" type="Number"/>
+      <xs:attribute name="src" type="URI"/>
+      <xs:attribute name="alt"/>
+      <xs:attribute name="usemap" type="URI"/>
+      <xs:attribute name="onselect" type="Script"/>
+      <xs:attribute name="onchange" type="Script"/>
+      <xs:attribute name="accept" type="ContentTypes"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="select">
+    <xs:annotation>
+      <xs:documentation>
+      option selector
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:choice maxOccurs="unbounded">
+        <xs:element ref="optgroup"/>
+        <xs:element ref="option"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="size" type="Number"/>
+      <xs:attribute name="multiple">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="multiple"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="tabindex" type="tabindexNumber"/>
+      <xs:attribute name="onfocus" type="Script"/>
+      <xs:attribute name="onblur" type="Script"/>
+      <xs:attribute name="onchange" type="Script"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="optgroup">
+    <xs:annotation>
+      <xs:documentation>
+      option group
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="option"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="label" use="required" type="Text"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="option">
+    <xs:annotation>
+      <xs:documentation>
+      selectable choice
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="selected">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="selected"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="label" type="Text"/>
+      <xs:attribute name="value"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="textarea">
+    <xs:annotation>
+      <xs:documentation>
+      multi-line text field
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="focus"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="rows" use="required" type="Number"/>
+      <xs:attribute name="cols" use="required" type="Number"/>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="readonly">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="readonly"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="onselect" type="Script"/>
+      <xs:attribute name="onchange" type="Script"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="fieldset">
+    <xs:annotation>
+      <xs:documentation>
+      The fieldset element is used to group form fields.
+      Only one legend element should occur in the content
+      and if present should only be preceded by whitespace.
+
+      NOTE: this content model is different from the XHTML 1.0 DTD,
+      closer to the intended content model in HTML4 DTD
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:sequence>
+        <xs:element ref="legend"/>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:group ref="block"/>
+          <xs:element ref="form"/>
+          <xs:group ref="inline"/>
+          <xs:group ref="misc"/>
+        </xs:choice>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="legend">
+    <xs:annotation>
+      <xs:documentation>
+      fieldset label
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="accesskey" type="Character"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="button">
+    <xs:annotation>
+      <xs:documentation>
+      Content is "Flow" excluding a, form and form controls
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="button.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="focus"/>
+          <xs:attribute name="name"/>
+          <xs:attribute name="value"/>
+          <xs:attribute name="type" default="submit">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="button"/>
+                <xs:enumeration value="submit"/>
+                <xs:enumeration value="reset"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="disabled">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="disabled"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ======================= Tables =======================================
+
+    Derived from IETF HTML table standard, see [RFC1942]
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="TFrame">
+    <xs:annotation>
+      <xs:documentation>
+      The border attribute sets the thickness of the frame around the
+      table. The default units are screen pixels.
+
+      The frame attribute specifies which parts of the frame around
+      the table should be rendered. The values are not the same as
+      CALS to avoid a name clash with the valign attribute.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="void"/>
+      <xs:enumeration value="above"/>
+      <xs:enumeration value="below"/>
+      <xs:enumeration value="hsides"/>
+      <xs:enumeration value="lhs"/>
+      <xs:enumeration value="rhs"/>
+      <xs:enumeration value="vsides"/>
+      <xs:enumeration value="box"/>
+      <xs:enumeration value="border"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="TRules">
+    <xs:annotation>
+      <xs:documentation>
+      The rules attribute defines which rules to draw between cells:
+
+      If rules is absent then assume:
+          "none" if border is absent or border="0" otherwise "all"
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="none"/>
+      <xs:enumeration value="groups"/>
+      <xs:enumeration value="rows"/>
+      <xs:enumeration value="cols"/>
+      <xs:enumeration value="all"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:attributeGroup name="cellhalign">
+    <xs:annotation>
+      <xs:documentation>
+      horizontal alignment attributes for cell contents
+
+      char        alignment char, e.g. char=':'
+      charoff     offset for alignment char
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="align">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="left"/>
+          <xs:enumeration value="center"/>
+          <xs:enumeration value="right"/>
+          <xs:enumeration value="justify"/>
+          <xs:enumeration value="char"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="char" type="Character"/>
+    <xs:attribute name="charoff" type="Length"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="cellvalign">
+    <xs:annotation>
+      <xs:documentation>
+      vertical alignment attributes for cell contents
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="valign">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="top"/>
+          <xs:enumeration value="middle"/>
+          <xs:enumeration value="bottom"/>
+          <xs:enumeration value="baseline"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:element name="table">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element minOccurs="0" ref="caption"/>
+        <xs:choice>
+          <xs:element minOccurs="0" maxOccurs="unbounded" ref="col"/>
+          <xs:element minOccurs="0" maxOccurs="unbounded" ref="colgroup"/>
+        </xs:choice>
+        <xs:element minOccurs="0" ref="thead"/>
+        <xs:element minOccurs="0" ref="tfoot"/>
+        <xs:choice>
+          <xs:element maxOccurs="unbounded" ref="tbody"/>
+          <xs:element maxOccurs="unbounded" ref="tr"/>
+        </xs:choice>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="summary" type="Text"/>
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="border" type="Pixels"/>
+      <xs:attribute name="frame" type="TFrame"/>
+      <xs:attribute name="rules" type="TRules"/>
+      <xs:attribute name="cellspacing" type="Length"/>
+      <xs:attribute name="cellpadding" type="Length"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="caption">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    Use thead to duplicate headers when breaking table
+    across page boundaries, or for static headers when
+    tbody sections are rendered in scrolling panel.
+
+    Use tfoot to duplicate footers when breaking table
+    across page boundaries, or for static footers when
+    tbody sections are rendered in scrolling panel.
+
+    Use multiple tbody sections when rules are needed
+    between groups of table rows.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="thead">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="tr"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tfoot">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="tr"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tbody">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="tr"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="colgroup">
+    <xs:annotation>
+      <xs:documentation>
+      colgroup groups a set of col elements. It allows you to group
+      several semantically related columns together.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element minOccurs="0" maxOccurs="unbounded" ref="col"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="span" default="1" type="Number"/>
+      <xs:attribute name="width" type="MultiLength"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="col">
+    <xs:annotation>
+      <xs:documentation>
+      col elements define the alignment properties for cells in
+      one or more columns.
+
+      The width attribute specifies the width of the columns, e.g.
+
+          width=64        width in screen pixels
+          width=0.5*      relative width of 0.5
+
+      The span attribute causes the attributes of one
+      col element to apply to more than one column.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="span" default="1" type="Number"/>
+      <xs:attribute name="width" type="MultiLength"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tr">
+    <xs:complexType>
+      <xs:choice maxOccurs="unbounded">
+        <xs:element ref="th"/>
+        <xs:element ref="td"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="Scope">
+    <xs:annotation>
+      <xs:documentation>
+      Scope is simpler than headers attribute for common tables
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="row"/>
+      <xs:enumeration value="col"/>
+      <xs:enumeration value="rowgroup"/>
+      <xs:enumeration value="colgroup"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+    th is for headers, td for data and for cells acting as both
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="th">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="abbr" type="Text"/>
+          <xs:attribute name="axis"/>
+          <xs:attribute name="headers" type="xs:IDREFS"/>
+          <xs:attribute name="scope" type="Scope"/>
+          <xs:attribute name="rowspan" default="1" type="Number"/>
+          <xs:attribute name="colspan" default="1" type="Number"/>
+          <xs:attributeGroup ref="cellhalign"/>
+          <xs:attributeGroup ref="cellvalign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="td">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="abbr" type="Text"/>
+          <xs:attribute name="axis"/>
+          <xs:attribute name="headers" type="xs:IDREFS"/>
+          <xs:attribute name="scope" type="Scope"/>
+          <xs:attribute name="rowspan" default="1" type="Number"/>
+          <xs:attribute name="colspan" default="1" type="Number"/>
+          <xs:attributeGroup ref="cellhalign"/>
+          <xs:attributeGroup ref="cellvalign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+</xs:schema>
\ No newline at end of file
diff --git a/xml/impl/resources/standardSchemas/xhtml1-transitional.dtd b/xml/impl/resources/standardSchemas/xhtml1-transitional.dtd
new file mode 100644
index 0000000..ff132b4
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml1-transitional.dtd
@@ -0,0 +1,1213 @@
+<!--
+   Extensible HTML version 1.0 Transitional DTD
+
+   This is the same as HTML 4 Transitional except for
+   changes due to the differences between XML and SGML.
+
+   Namespace = http://www.w3.org/1999/xhtml
+
+   For further information, see: http://www.w3.org/TR/xhtml1
+
+   Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+   All Rights Reserved. 
+
+   This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+   PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+   SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+
+   $Revision: 1.1 $
+   $Date: 2004/09/17 17:05:38 $
+
+-->
+
+<!--================ Character mnemonic entities =========================-->
+
+<!ENTITY % HTMLlat1 PUBLIC
+   "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+   "xhtml-lat1.ent">
+%HTMLlat1;
+
+<!ENTITY % HTMLsymbol PUBLIC
+   "-//W3C//ENTITIES Symbols for XHTML//EN"
+   "xhtml-symbol.ent">
+%HTMLsymbol;
+
+<!ENTITY % HTMLspecial PUBLIC
+   "-//W3C//ENTITIES Special for XHTML//EN"
+   "xhtml-special.ent">
+%HTMLspecial;
+
+<!--================== Imported Names ====================================-->
+
+<!ENTITY % ContentType "CDATA">
+    <!-- media type, as per [RFC2045] -->
+
+<!ENTITY % ContentTypes "CDATA">
+    <!-- comma-separated list of media types, as per [RFC2045] -->
+
+<!ENTITY % Charset "CDATA">
+    <!-- a character encoding, as per [RFC2045] -->
+
+<!ENTITY % Charsets "CDATA">
+    <!-- a space separated list of character encodings, as per [RFC2045] -->
+
+<!ENTITY % LanguageCode "NMTOKEN">
+    <!-- a language code, as per [RFC3066] -->
+
+<!ENTITY % Character "CDATA">
+    <!-- a single character, as per section 2.2 of [XML] -->
+
+<!ENTITY % Number "CDATA">
+    <!-- one or more digits -->
+
+<!ENTITY % LinkTypes "CDATA">
+    <!-- space-separated list of link types -->
+
+<!ENTITY % MediaDesc "CDATA">
+    <!-- single or comma-separated list of media descriptors -->
+
+<!ENTITY % URI "CDATA">
+    <!-- a Uniform Resource Identifier, see [RFC2396] -->
+
+<!ENTITY % UriList "CDATA">
+    <!-- a space separated list of Uniform Resource Identifiers -->
+
+<!ENTITY % Datetime "CDATA">
+    <!-- date and time information. ISO date format -->
+
+<!ENTITY % Script "CDATA">
+    <!-- script expression -->
+
+<!ENTITY % StyleSheet "CDATA">
+    <!-- style sheet data -->
+
+<!ENTITY % Text "CDATA">
+    <!-- used for titles etc. -->
+
+<!ENTITY % FrameTarget "NMTOKEN">
+    <!-- render in this frame -->
+
+<!ENTITY % Length "CDATA">
+    <!-- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % MultiLength "CDATA">
+    <!-- pixel, percentage, or relative -->
+
+<!ENTITY % Pixels "CDATA">
+    <!-- integer representing length in pixels -->
+
+<!-- these are used for image maps -->
+
+<!ENTITY % Shape "(rect|circle|poly|default)">
+
+<!ENTITY % Coords "CDATA">
+    <!-- comma separated list of lengths -->
+
+<!-- used for object, applet, img, input and iframe -->
+<!ENTITY % ImgAlign "(top|middle|bottom|left|right)">
+
+<!-- a color using sRGB: #RRGGBB as Hex values -->
+<!ENTITY % Color "CDATA">
+
+<!-- There are also 16 widely known color names with their sRGB values:
+
+    Black  = #000000    Green  = #008000
+    Silver = #C0C0C0    Lime   = #00FF00
+    Gray   = #808080    Olive  = #808000
+    White  = #FFFFFF    Yellow = #FFFF00
+    Maroon = #800000    Navy   = #000080
+    Red    = #FF0000    Blue   = #0000FF
+    Purple = #800080    Teal   = #008080
+    Fuchsia= #FF00FF    Aqua   = #00FFFF
+-->
+
+<!--=================== Generic Attributes ===============================-->
+
+<!-- core attributes common to most elements
+  id       document-wide unique id
+  class    space separated list of classes
+  style    associated style info
+  title    advisory title/amplification
+-->
+<!ENTITY % coreattrs
+ "id          ID             #IMPLIED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED"
+  >
+
+<!-- internationalization attributes
+  lang        language code (backwards compatible)
+  xml:lang    language code (as per XML 1.0 spec)
+  dir         direction for weak/neutral text
+-->
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #IMPLIED"
+  >
+
+<!-- attributes for common UI events
+  onclick     a pointer button was clicked
+  ondblclick  a pointer button was double clicked
+  onmousedown a pointer button was pressed down
+  onmouseup   a pointer button was released
+  onmousemove a pointer was moved onto the element
+  onmouseout  a pointer was moved away from the element
+  onkeypress  a key was pressed and released
+  onkeydown   a key was pressed down
+  onkeyup     a key was released
+-->
+<!ENTITY % events
+ "onclick     %Script;       #IMPLIED
+  ondblclick  %Script;       #IMPLIED
+  onmousedown %Script;       #IMPLIED
+  onmouseup   %Script;       #IMPLIED
+  onmouseover %Script;       #IMPLIED
+  onmousemove %Script;       #IMPLIED
+  onmouseout  %Script;       #IMPLIED
+  onkeypress  %Script;       #IMPLIED
+  onkeydown   %Script;       #IMPLIED
+  onkeyup     %Script;       #IMPLIED"
+  >
+
+<!-- attributes for elements that can get the focus
+  accesskey   accessibility key character
+  tabindex    position in tabbing order
+  onfocus     the element got the focus
+  onblur      the element lost the focus
+-->
+<!ENTITY % focus
+ "accesskey   %Character;    #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED"
+  >
+
+<!ENTITY % attrs "%coreattrs; %i18n; %events;">
+
+<!-- text alignment for p, div, h1-h6. The default is
+     align="left" for ltr headings, "right" for rtl -->
+
+<!ENTITY % TextAlign "align (left|center|right|justify) #IMPLIED">
+
+<!--=================== Text Elements ====================================-->
+
+<!ENTITY % special.extra
+   "object | applet | img | map | iframe">
+	
+<!ENTITY % special.basic
+	"br | span | bdo">
+
+<!ENTITY % special
+   "%special.basic; | %special.extra;">
+
+<!ENTITY % fontstyle.extra "big | small | font | basefont">
+
+<!ENTITY % fontstyle.basic "tt | i | b | u
+                      | s | strike ">
+
+<!ENTITY % fontstyle "%fontstyle.basic; | %fontstyle.extra;">
+
+<!ENTITY % phrase.extra "sub | sup">
+<!ENTITY % phrase.basic "em | strong | dfn | code | q |
+                   samp | kbd | var | cite | abbr | acronym">
+
+<!ENTITY % phrase "%phrase.basic; | %phrase.extra;">
+
+<!ENTITY % inline.forms "input | select | textarea | label | button">
+
+<!-- these can occur at block or inline level -->
+<!ENTITY % misc.inline "ins | del | script">
+
+<!-- these can only occur at block level -->
+<!ENTITY % misc "noscript | %misc.inline;">
+
+<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
+
+<!-- %Inline; covers inline or "text-level" elements -->
+<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
+
+<!--================== Block level elements ==============================-->
+
+<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
+<!ENTITY % lists "ul | ol | dl | menu | dir">
+<!ENTITY % blocktext "pre | hr | blockquote | address | center | noframes">
+
+<!ENTITY % block
+    "p | %heading; | div | %lists; | %blocktext; | isindex |fieldset | table">
+
+<!-- %Flow; mixes block and inline and is used for list items etc. -->
+<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
+
+<!--================== Content models for exclusions =====================-->
+
+<!-- a elements use %Inline; excluding a -->
+
+<!ENTITY % a.content
+   "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
+
+<!-- pre uses %Inline excluding img, object, applet, big, small,
+     font, or basefont -->
+
+<!ENTITY % pre.content
+   "(#PCDATA | a | %special.basic; | %fontstyle.basic; | %phrase.basic; |
+	   %inline.forms; | %misc.inline;)*">
+
+<!-- form uses %Flow; excluding form -->
+
+<!ENTITY % form.content "(#PCDATA | %block; | %inline; | %misc;)*">
+
+<!-- button uses %Flow; but excludes a, form, form controls, iframe -->
+
+<!ENTITY % button.content
+   "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
+      table | br | span | bdo | object | applet | img | map |
+      %fontstyle; | %phrase; | %misc;)*">
+
+<!--================ Document Structure ==================================-->
+
+<!-- the namespace URI designates the document profile -->
+
+<!ELEMENT html (head, body)>
+<!ATTLIST html
+  %i18n;
+  id          ID             #IMPLIED
+  xmlns       %URI;          #FIXED 'http://www.w3.org/1999/xhtml'
+  >
+
+<!--================ Document Head =======================================-->
+
+<!ENTITY % head.misc "(script|style|meta|link|object|isindex)*">
+
+<!-- content model is %head.misc; combined with a single
+     title and an optional base element in any order -->
+
+<!ELEMENT head (%head.misc;,
+     ((title, %head.misc;, (base, %head.misc;)?) |
+      (base, %head.misc;, (title, %head.misc;))))>
+
+<!ATTLIST head
+  %i18n;
+  id          ID             #IMPLIED
+  profile     %URI;          #IMPLIED
+  >
+
+<!-- The title element is not considered part of the flow of text.
+       It should be displayed, for example as the page header or
+       window title. Exactly one title is required per document.
+    -->
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title 
+  %i18n;
+  id          ID             #IMPLIED
+  >
+
+<!-- document base URI -->
+
+<!ELEMENT base EMPTY>
+<!ATTLIST base
+  id          ID             #IMPLIED
+  href        %URI;          #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!-- generic metainformation -->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+  %i18n;
+  id          ID             #IMPLIED
+  http-equiv  CDATA          #IMPLIED
+  name        CDATA          #IMPLIED
+  content     CDATA          #REQUIRED
+  scheme      CDATA          #IMPLIED
+  >
+
+<!--
+  Relationship values can be used in principle:
+
+   a) for document specific toolbars/menus when used
+      with the link element in document head e.g.
+        start, contents, previous, next, index, end, help
+   b) to link to a separate style sheet (rel="stylesheet")
+   c) to make a link to a script (rel="script")
+   d) by stylesheets to control how collections of
+      html nodes are rendered into printed documents
+   e) to make a link to a printable version of this document
+      e.g. a PostScript or PDF version (rel="alternate" media="print")
+-->
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+  %attrs;
+  charset     %Charset;      #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  type        %ContentType;  #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  media       %MediaDesc;    #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!-- style info, which may include CDATA sections -->
+<!ELEMENT style (#PCDATA)>
+<!ATTLIST style
+  %i18n;
+  id          ID             #IMPLIED
+  type        %ContentType;  #REQUIRED
+  media       %MediaDesc;    #IMPLIED
+  title       %Text;         #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- script statements, which may include CDATA sections -->
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+  id          ID             #IMPLIED
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #REQUIRED
+  language    CDATA          #IMPLIED
+  src         %URI;          #IMPLIED
+  defer       (defer)        #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- alternate content container for non script-based rendering -->
+
+<!ELEMENT noscript %Flow;>
+<!ATTLIST noscript
+  %attrs;
+  >
+
+<!--======================= Frames =======================================-->
+
+<!-- inline subwindow -->
+
+<!ELEMENT iframe %Flow;>
+<!ATTLIST iframe
+  %coreattrs;
+  longdesc    %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  src         %URI;          #IMPLIED
+  frameborder (1|0)          "1"
+  marginwidth %Pixels;       #IMPLIED
+  marginheight %Pixels;      #IMPLIED
+  scrolling   (yes|no|auto)  "auto"
+  align       %ImgAlign;     #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  >
+
+<!-- alternate content container for non frame-based rendering -->
+
+<!ELEMENT noframes %Flow;>
+<!ATTLIST noframes
+  %attrs;
+  >
+
+<!--=================== Document Body ====================================-->
+
+<!ELEMENT body %Flow;>
+<!ATTLIST body
+  %attrs;
+  onload      %Script;       #IMPLIED
+  onunload    %Script;       #IMPLIED
+  background  %URI;          #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  text        %Color;        #IMPLIED
+  link        %Color;        #IMPLIED
+  vlink       %Color;        #IMPLIED
+  alink       %Color;        #IMPLIED
+  >
+
+<!ELEMENT div %Flow;>  <!-- generic language/style container -->
+<!ATTLIST div
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Paragraphs =======================================-->
+
+<!ELEMENT p %Inline;>
+<!ATTLIST p
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Headings =========================================-->
+
+<!--
+  There are six levels of headings from h1 (the most important)
+  to h6 (the least important).
+-->
+
+<!ELEMENT h1  %Inline;>
+<!ATTLIST h1
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h2 %Inline;>
+<!ATTLIST h2
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h3 %Inline;>
+<!ATTLIST h3
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h4 %Inline;>
+<!ATTLIST h4
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h5 %Inline;>
+<!ATTLIST h5
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h6 %Inline;>
+<!ATTLIST h6
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Lists ============================================-->
+
+<!-- Unordered list bullet styles -->
+
+<!ENTITY % ULStyle "(disc|square|circle)">
+
+<!-- Unordered list -->
+
+<!ELEMENT ul (li)+>
+<!ATTLIST ul
+  %attrs;
+  type        %ULStyle;     #IMPLIED
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- Ordered list numbering style
+
+    1   arabic numbers      1, 2, 3, ...
+    a   lower alpha         a, b, c, ...
+    A   upper alpha         A, B, C, ...
+    i   lower roman         i, ii, iii, ...
+    I   upper roman         I, II, III, ...
+
+    The style is applied to the sequence number which by default
+    is reset to 1 for the first list item in an ordered list.
+-->
+<!ENTITY % OLStyle "CDATA">
+
+<!-- Ordered (numbered) list -->
+
+<!ELEMENT ol (li)+>
+<!ATTLIST ol
+  %attrs;
+  type        %OLStyle;      #IMPLIED
+  compact     (compact)      #IMPLIED
+  start       %Number;       #IMPLIED
+  >
+
+<!-- single column list (DEPRECATED) --> 
+<!ELEMENT menu (li)+>
+<!ATTLIST menu
+  %attrs;
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- multiple column list (DEPRECATED) --> 
+<!ELEMENT dir (li)+>
+<!ATTLIST dir
+  %attrs;
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- LIStyle is constrained to: "(%ULStyle;|%OLStyle;)" -->
+<!ENTITY % LIStyle "CDATA">
+
+<!-- list item -->
+
+<!ELEMENT li %Flow;>
+<!ATTLIST li
+  %attrs;
+  type        %LIStyle;      #IMPLIED
+  value       %Number;       #IMPLIED
+  >
+
+<!-- definition lists - dt for term, dd for its definition -->
+
+<!ELEMENT dl (dt|dd)+>
+<!ATTLIST dl
+  %attrs;
+  compact     (compact)      #IMPLIED
+  >
+
+<!ELEMENT dt %Inline;>
+<!ATTLIST dt
+  %attrs;
+  >
+
+<!ELEMENT dd %Flow;>
+<!ATTLIST dd
+  %attrs;
+  >
+
+<!--=================== Address ==========================================-->
+
+<!-- information on author -->
+
+<!ELEMENT address (#PCDATA | %inline; | %misc.inline; | p)*>
+<!ATTLIST address
+  %attrs;
+  >
+
+<!--=================== Horizontal Rule ==================================-->
+
+<!ELEMENT hr EMPTY>
+<!ATTLIST hr
+  %attrs;
+  align       (left|center|right) #IMPLIED
+  noshade     (noshade)      #IMPLIED
+  size        %Pixels;       #IMPLIED
+  width       %Length;       #IMPLIED
+  >
+
+<!--=================== Preformatted Text ================================-->
+
+<!-- content is %Inline; excluding 
+        "img|object|applet|big|small|sub|sup|font|basefont" -->
+
+<!ELEMENT pre %pre.content;>
+<!ATTLIST pre
+  %attrs;
+  width       %Number;      #IMPLIED
+  xml:space   (preserve)    #FIXED 'preserve'
+  >
+
+<!--=================== Block-like Quotes ================================-->
+
+<!ELEMENT blockquote %Flow;>
+<!ATTLIST blockquote
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!--=================== Text alignment ===================================-->
+
+<!-- center content -->
+<!ELEMENT center %Flow;>
+<!ATTLIST center
+  %attrs;
+  >
+
+<!--=================== Inserted/Deleted Text ============================-->
+
+<!--
+  ins/del are allowed in block and inline content, but its
+  inappropriate to include block content within an ins element
+  occurring in inline content.
+-->
+<!ELEMENT ins %Flow;>
+<!ATTLIST ins
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!ELEMENT del %Flow;>
+<!ATTLIST del
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!--================== The Anchor Element ================================-->
+
+<!-- content is %Inline; except that anchors shouldn't be nested -->
+
+<!ELEMENT a %a.content;>
+<!ATTLIST a
+  %attrs;
+  %focus;
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--===================== Inline Elements ================================-->
+
+<!ELEMENT span %Inline;> <!-- generic language/style container -->
+<!ATTLIST span
+  %attrs;
+  >
+
+<!ELEMENT bdo %Inline;>  <!-- I18N BiDi over-ride -->
+<!ATTLIST bdo
+  %coreattrs;
+  %events;
+  lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #REQUIRED
+  >
+
+<!ELEMENT br EMPTY>   <!-- forced line break -->
+<!ATTLIST br
+  %coreattrs;
+  clear       (left|all|right|none) "none"
+  >
+
+<!ELEMENT em %Inline;>   <!-- emphasis -->
+<!ATTLIST em %attrs;>
+
+<!ELEMENT strong %Inline;>   <!-- strong emphasis -->
+<!ATTLIST strong %attrs;>
+
+<!ELEMENT dfn %Inline;>   <!-- definitional -->
+<!ATTLIST dfn %attrs;>
+
+<!ELEMENT code %Inline;>   <!-- program code -->
+<!ATTLIST code %attrs;>
+
+<!ELEMENT samp %Inline;>   <!-- sample -->
+<!ATTLIST samp %attrs;>
+
+<!ELEMENT kbd %Inline;>  <!-- something user would type -->
+<!ATTLIST kbd %attrs;>
+
+<!ELEMENT var %Inline;>   <!-- variable -->
+<!ATTLIST var %attrs;>
+
+<!ELEMENT cite %Inline;>   <!-- citation -->
+<!ATTLIST cite %attrs;>
+
+<!ELEMENT abbr %Inline;>   <!-- abbreviation -->
+<!ATTLIST abbr %attrs;>
+
+<!ELEMENT acronym %Inline;>   <!-- acronym -->
+<!ATTLIST acronym %attrs;>
+
+<!ELEMENT q %Inline;>   <!-- inlined quote -->
+<!ATTLIST q
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!ELEMENT sub %Inline;> <!-- subscript -->
+<!ATTLIST sub %attrs;>
+
+<!ELEMENT sup %Inline;> <!-- superscript -->
+<!ATTLIST sup %attrs;>
+
+<!ELEMENT tt %Inline;>   <!-- fixed pitch font -->
+<!ATTLIST tt %attrs;>
+
+<!ELEMENT i %Inline;>   <!-- italic font -->
+<!ATTLIST i %attrs;>
+
+<!ELEMENT b %Inline;>   <!-- bold font -->
+<!ATTLIST b %attrs;>
+
+<!ELEMENT big %Inline;>   <!-- bigger font -->
+<!ATTLIST big %attrs;>
+
+<!ELEMENT small %Inline;>   <!-- smaller font -->
+<!ATTLIST small %attrs;>
+
+<!ELEMENT u %Inline;>   <!-- underline -->
+<!ATTLIST u %attrs;>
+
+<!ELEMENT s %Inline;>   <!-- strike-through -->
+<!ATTLIST s %attrs;>
+
+<!ELEMENT strike %Inline;>   <!-- strike-through -->
+<!ATTLIST strike %attrs;>
+
+<!ELEMENT basefont EMPTY>  <!-- base font size -->
+<!ATTLIST basefont
+  id          ID             #IMPLIED
+  size        CDATA          #REQUIRED
+  color       %Color;        #IMPLIED
+  face        CDATA          #IMPLIED
+  >
+
+<!ELEMENT font %Inline;> <!-- local change to font -->
+<!ATTLIST font
+  %coreattrs;
+  %i18n;
+  size        CDATA          #IMPLIED
+  color       %Color;        #IMPLIED
+  face        CDATA          #IMPLIED
+  >
+
+<!ELEMENT embed EMPTY> 
+<!ATTLIST embed
+  alt           CDATA          #IMPLIED
+  width         %Length;       #IMPLIED
+  height        %Length;       #IMPLIED
+  hidden        CDATA          #IMPLIED
+  pluginspage   %URI;          #IMPLIED
+  src           %URI;          #IMPLIED
+  type          CDATA          #IMPLIED
+  wmode         CDATA          #IMPLIED
+  >
+
+<!--==================== Object ======================================-->
+<!--
+  object is used to embed objects as part of HTML pages.
+  param elements should precede other content. Parameters
+  can also be expressed as attribute/value pairs on the
+  object element itself when brevity is desired.
+-->
+
+<!ELEMENT object (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST object
+  %attrs;
+  declare     (declare)      #IMPLIED
+  classid     %URI;          #IMPLIED
+  codebase    %URI;          #IMPLIED
+  data        %URI;          #IMPLIED
+  type        %ContentType;  #IMPLIED
+  codetype    %ContentType;  #IMPLIED
+  archive     %UriList;      #IMPLIED
+  standby     %Text;         #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  border      %Pixels;       #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!--
+  param is used to supply a named property value.
+  In XML it would seem natural to follow RDF and support an
+  abbreviated syntax where the param elements are replaced
+  by attribute value pairs on the object start tag.
+-->
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+  id          ID             #IMPLIED
+  name        CDATA          #REQUIRED
+  value       CDATA          #IMPLIED
+  valuetype   (data|ref|object) "data"
+  type        %ContentType;  #IMPLIED
+  >
+
+<!--=================== Java applet ==================================-->
+<!--
+  One of code or object attributes must be present.
+  Place param elements before other content.
+-->
+<!ELEMENT applet (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST applet
+  %coreattrs;
+  codebase    %URI;          #IMPLIED
+  archive     CDATA          #IMPLIED
+  code        CDATA          #IMPLIED
+  object      CDATA          #IMPLIED
+  alt         %Text;         #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  width       %Length;       #REQUIRED
+  height      %Length;       #REQUIRED
+  align       %ImgAlign;     #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!--=================== Images ===========================================-->
+
+<!--
+   To avoid accessibility problems for people who aren't
+   able to see the image, you should provide a text
+   description using the alt and longdesc attributes.
+   In addition, avoid the use of server-side image maps.
+-->
+
+<!ELEMENT img EMPTY>
+<!ATTLIST img
+  %attrs;
+  src         %URI;          #REQUIRED
+  alt         %Text;         #REQUIRED
+  name        NMTOKEN        #IMPLIED
+  longdesc    %URI;          #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  ismap       (ismap)        #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  border      %Length;       #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!-- usemap points to a map element which may be in this document
+  or an external document, although the latter is not widely supported -->
+
+<!--================== Client-side image maps ============================-->
+
+<!-- These can be placed in the same document or grouped in a
+     separate document although this isn't yet widely supported -->
+
+<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
+<!ATTLIST map
+  %i18n;
+  %events;
+  id          ID             #IMPLIED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED
+  name        CDATA          #REQUIRED
+  >
+
+<!ELEMENT area EMPTY>
+<!ATTLIST area
+  %attrs;
+  %focus;
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  href        %URI;          #IMPLIED
+  nohref      (nohref)       #IMPLIED
+  alt         %Text;         #REQUIRED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--================ Forms ===============================================-->
+
+<!ELEMENT form %form.content;>   <!-- forms shouldn't be nested -->
+
+<!ATTLIST form
+  %attrs;
+  action      %URI;          #REQUIRED
+  method      (get|post)     "get"
+  name        NMTOKEN        #IMPLIED
+  enctype     %ContentType;  "application/x-www-form-urlencoded"
+  onsubmit    %Script;       #IMPLIED
+  onreset     %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  accept-charset %Charsets;  #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--
+  Each label must not contain more than ONE field
+  Label elements shouldn't be nested.
+-->
+<!ELEMENT label %Inline;>
+<!ATTLIST label
+  %attrs;
+  for         IDREF          #IMPLIED
+  accesskey   %Character;    #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  >
+
+<!ENTITY % InputType
+  "(text | password | checkbox |
+    radio | submit | reset |
+    file | hidden | image | button)"
+   >
+
+<!-- the name attribute is required for all but submit & reset -->
+
+<!ELEMENT input EMPTY>     <!-- form control -->
+<!ATTLIST input
+  %attrs;
+  %focus;
+  type        %InputType;    "text"
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  checked     (checked)      #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  size        CDATA          #IMPLIED
+  maxlength   %Number;       #IMPLIED
+  src         %URI;          #IMPLIED
+  alt         CDATA          #IMPLIED
+  usemap      %URI;          #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  >
+
+<!ELEMENT select (optgroup|option)+>  <!-- option selector -->
+<!ATTLIST select
+  %attrs;
+  name        CDATA          #IMPLIED
+  size        %Number;       #IMPLIED
+  multiple    (multiple)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!ELEMENT optgroup (option)+>   <!-- option group -->
+<!ATTLIST optgroup
+  %attrs;
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #REQUIRED
+  >
+
+<!ELEMENT option (#PCDATA)>     <!-- selectable choice -->
+<!ATTLIST option
+  %attrs;
+  selected    (selected)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #IMPLIED
+  value       CDATA          #IMPLIED
+  >
+
+<!ELEMENT textarea (#PCDATA)>     <!-- multi-line text field -->
+<!ATTLIST textarea
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  rows        %Number;       #REQUIRED
+  cols        %Number;       #REQUIRED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!--
+  The fieldset element is used to group form fields.
+  Only one legend element should occur in the content
+  and if present should only be preceded by whitespace.
+-->
+<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
+<!ATTLIST fieldset
+  %attrs;
+  >
+
+<!ENTITY % LAlign "(top|bottom|left|right)">
+
+<!ELEMENT legend %Inline;>     <!-- fieldset label -->
+<!ATTLIST legend
+  %attrs;
+  accesskey   %Character;    #IMPLIED
+  align       %LAlign;       #IMPLIED
+  >
+
+<!--
+ Content is %Flow; excluding a, form, form controls, iframe
+--> 
+<!ELEMENT button %button.content;>  <!-- push button -->
+<!ATTLIST button
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  type        (button|submit|reset) "submit"
+  disabled    (disabled)     #IMPLIED
+  >
+
+<!-- single-line text input control (DEPRECATED) -->
+<!ELEMENT isindex EMPTY>
+<!ATTLIST isindex
+  %coreattrs;
+  %i18n;
+  prompt      %Text;         #IMPLIED
+  >
+
+<!--======================= Tables =======================================-->
+
+<!-- Derived from IETF HTML table standard, see [RFC1942] -->
+
+<!--
+ The border attribute sets the thickness of the frame around the
+ table. The default units are screen pixels.
+
+ The frame attribute specifies which parts of the frame around
+ the table should be rendered. The values are not the same as
+ CALS to avoid a name clash with the valign attribute.
+-->
+<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
+
+<!--
+ The rules attribute defines which rules to draw between cells:
+
+ If rules is absent then assume:
+     "none" if border is absent or border="0" otherwise "all"
+-->
+
+<!ENTITY % TRules "(none | groups | rows | cols | all)">
+  
+<!-- horizontal placement of table relative to document -->
+<!ENTITY % TAlign "(left|center|right)">
+
+<!-- horizontal alignment attributes for cell contents
+
+  char        alignment char, e.g. char=':'
+  charoff     offset for alignment char
+-->
+<!ENTITY % cellhalign
+  "align      (left|center|right|justify|char) #IMPLIED
+   char       %Character;    #IMPLIED
+   charoff    %Length;       #IMPLIED"
+  >
+
+<!-- vertical alignment attributes for cell contents -->
+<!ENTITY % cellvalign
+  "valign     (top|middle|bottom|baseline) #IMPLIED"
+  >
+
+<!ELEMENT table
+     (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
+<!ELEMENT caption  %Inline;>
+<!ELEMENT thead    (tr)+>
+<!ELEMENT tfoot    (tr)+>
+<!ELEMENT tbody    (tr)+>
+<!ELEMENT colgroup (col)*>
+<!ELEMENT col      EMPTY>
+<!ELEMENT tr       (th|td)+>
+<!ELEMENT th       %Flow;>
+<!ELEMENT td       %Flow;>
+
+<!ATTLIST table
+  %attrs;
+  summary     %Text;         #IMPLIED
+  width       %Length;       #IMPLIED
+  border      %Pixels;       #IMPLIED
+  frame       %TFrame;       #IMPLIED
+  rules       %TRules;       #IMPLIED
+  cellspacing %Length;       #IMPLIED
+  cellpadding %Length;       #IMPLIED
+  align       %TAlign;       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  >
+
+<!ENTITY % CAlign "(top|bottom|left|right)">
+
+<!ATTLIST caption
+  %attrs;
+  align       %CAlign;       #IMPLIED
+  >
+
+<!--
+colgroup groups a set of col elements. It allows you to group
+several semantically related columns together.
+-->
+<!ATTLIST colgroup
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+ col elements define the alignment properties for cells in
+ one or more columns.
+
+ The width attribute specifies the width of the columns, e.g.
+
+     width=64        width in screen pixels
+     width=0.5*      relative width of 0.5
+
+ The span attribute causes the attributes of one
+ col element to apply to more than one column.
+-->
+<!ATTLIST col
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+    Use thead to duplicate headers when breaking table
+    across page boundaries, or for static headers when
+    tbody sections are rendered in scrolling panel.
+
+    Use tfoot to duplicate footers when breaking table
+    across page boundaries, or for static footers when
+    tbody sections are rendered in scrolling panel.
+
+    Use multiple tbody sections when rules are needed
+    between groups of table rows.
+-->
+<!ATTLIST thead
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tfoot
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tbody
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tr
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  bgcolor     %Color;        #IMPLIED
+  >
+
+<!-- Scope is simpler than headers attribute for common tables -->
+<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
+
+<!-- th is for headers, td for data and for cells acting as both -->
+
+<!ATTLIST th
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  nowrap      (nowrap)       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  width       %Length;       #IMPLIED
+  height      %Length;       #IMPLIED
+  >
+
+<!ATTLIST td
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  nowrap      (nowrap)       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  width       %Length;       #IMPLIED
+  height      %Length;       #IMPLIED
+  >
+
diff --git a/xml/impl/resources/standardSchemas/xhtml1-transitional.xsd b/xml/impl/resources/standardSchemas/xhtml1-transitional.xsd
new file mode 100644
index 0000000..c77b53e
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml1-transitional.xsd
@@ -0,0 +1,2786 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE xs:schema [
+<!ENTITY % HTMLlat1 PUBLIC
+       "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+       "xhtml-lat1.ent">
+    %HTMLlat1;
+
+    <!ENTITY % HTMLsymbol PUBLIC
+       "-//W3C//ENTITIES Symbols for XHTML//EN"
+       "xhtml-symbol.ent">
+    %HTMLsymbol;
+
+    <!ENTITY % HTMLspecial PUBLIC
+       "-//W3C//ENTITIES Special for XHTML//EN"
+       "xhtml-special.ent">
+    %HTMLspecial;
+]>
+
+<xs:schema version="1.0" xml:lang="en"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    targetNamespace="http://www.w3.org/1999/xhtml"
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:xml="http://www.w3.org/XML/1998/namespace"
+    elementFormDefault="qualified">
+
+  <xs:annotation>
+    <xs:documentation>
+    XHTML 1.0 (Second Edition) Transitional in XML Schema
+
+    This is the same as HTML 4 Transitional except for
+    changes due to the differences between XML and SGML.
+
+    Namespace = http://www.w3.org/1999/xhtml
+
+    For further information, see: http://www.w3.org/TR/xhtml1
+
+    Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+    All Rights Reserved.
+
+    The DTD version is identified by the PUBLIC and SYSTEM identifiers:
+
+    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+
+    $Id: xhtml1-transitional.xsd,v 1.5 2002/08/28 09:53:29 mimasa Exp $
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:import namespace="http://www.w3.org/XML/1998/namespace"
+      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Character mnemonic entities =========================
+
+    XHTML entity sets are identified by the PUBLIC and SYSTEM identifiers:
+
+    PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"
+
+    PUBLIC "-//W3C//ENTITIES Special for XHTML//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent"
+
+    PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN"
+    SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent"
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Imported Names ====================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="ContentType">
+    <xs:annotation>
+      <xs:documentation>
+      media type, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="ContentTypes">
+    <xs:annotation>
+      <xs:documentation>
+      comma-separated list of media types, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Charset">
+    <xs:annotation>
+      <xs:documentation>
+      a character encoding, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Charsets">
+    <xs:annotation>
+      <xs:documentation>
+      a space separated list of character encodings, as per [RFC2045]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="LanguageCode">
+    <xs:annotation>
+      <xs:documentation>
+      a language code, as per [RFC3066]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:language"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Character">
+    <xs:annotation>
+      <xs:documentation>
+      a single character, as per section 2.2 of [XML]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:length value="1" fixed="true"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Number">
+    <xs:annotation>
+      <xs:documentation>
+      one or more digits
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:nonNegativeInteger">
+      <xs:pattern value="[0-9]+"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="tabindexNumber">
+    <xs:annotation>
+      <xs:documentation>
+      tabindex attribute specifies the position of the current element
+      in the tabbing order for the current document. This value must be
+      a number between 0 and 32767. User agents should ignore leading zeros.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="Number">
+      <xs:minInclusive value="0"/>
+      <xs:maxInclusive value="32767"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="LinkTypes">
+    <xs:annotation>
+      <xs:documentation>
+      space-separated list of link types
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:NMTOKENS"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="MediaDesc">
+    <xs:annotation>
+      <xs:documentation>
+      single or comma-separated list of media descriptors
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[^,]+(,\s*[^,]+)*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="URI">
+    <xs:annotation>
+      <xs:documentation>
+      a Uniform Resource Identifier, see [RFC2396]
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:anyURI"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="UriList">
+    <xs:annotation>
+      <xs:documentation>
+      a space separated list of Uniform Resource Identifiers
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Datetime">
+    <xs:annotation>
+      <xs:documentation>
+      date and time information. ISO date format
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:dateTime"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Script">
+    <xs:annotation>
+      <xs:documentation>
+      script expression
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="StyleSheet">
+    <xs:annotation>
+      <xs:documentation>
+      style sheet data
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="Text">
+    <xs:annotation>
+      <xs:documentation>
+      used for titles etc.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="FrameTarget">
+    <xs:annotation>
+      <xs:documentation>
+      render in this frame
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:NMTOKEN">
+      <xs:pattern value="_(blank|self|parent|top)|[A-Za-z]\c*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Length">
+    <xs:annotation>
+      <xs:documentation>
+      nn for pixels or nn% for percentage length
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[\-+]?(\d+|\d+(\.\d+)?%)"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="MultiLength">
+    <xs:annotation>
+      <xs:documentation>
+      pixel, percentage, or relative
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[\-+]?(\d+|\d+(\.\d+)?%)|[1-9]?(\d+)?\*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Pixels">
+    <xs:annotation>
+      <xs:documentation>
+      integer representing length in pixels
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:nonNegativeInteger"/>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+    these are used for image maps
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="Shape">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="rect"/>
+      <xs:enumeration value="circle"/>
+      <xs:enumeration value="poly"/>
+      <xs:enumeration value="default"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Coords">
+    <xs:annotation>
+      <xs:documentation>
+      comma separated list of lengths
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern
+          value="[\-+]?(\d+|\d+(\.\d+)?%)(,\s*[\-+]?(\d+|\d+(\.\d+)?%))*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="ImgAlign">
+    <xs:annotation>
+      <xs:documentation>
+      used for object, applet, img, input and iframe
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="top"/>
+      <xs:enumeration value="middle"/>
+      <xs:enumeration value="bottom"/>
+      <xs:enumeration value="left"/>
+      <xs:enumeration value="right"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="Color">
+    <xs:annotation>
+      <xs:documentation>
+      a color using sRGB: #RRGGBB as Hex values
+
+      There are also 16 widely known color names with their sRGB values:
+
+      Black  = #000000    Green  = #008000
+      Silver = #C0C0C0    Lime   = #00FF00
+      Gray   = #808080    Olive  = #808000
+      White  = #FFFFFF    Yellow = #FFFF00
+      Maroon = #800000    Navy   = #000080
+      Red    = #FF0000    Blue   = #0000FF
+      Purple = #800080    Teal   = #008080
+      Fuchsia= #FF00FF    Aqua   = #00FFFF
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[A-Za-z]+|#[0-9A-Fa-f]{3}|#[0-9A-Fa-f]{6}"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Generic Attributes ===============================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:attributeGroup name="coreattrs">
+    <xs:annotation>
+      <xs:documentation>
+      core attributes common to most elements
+      id       document-wide unique id
+      class    space separated list of classes
+      style    associated style info
+      title    advisory title/amplification
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="id" type="xs:ID"/>
+    <xs:attribute name="class" type="xs:NMTOKENS"/>
+    <xs:attribute name="style" type="StyleSheet"/>
+    <xs:attribute name="title" type="Text"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="i18n">
+    <xs:annotation>
+      <xs:documentation>
+      internationalization attributes
+      lang        language code (backwards compatible)
+      xml:lang    language code (as per XML 1.0 spec)
+      dir         direction for weak/neutral text
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="lang" type="LanguageCode"/>
+    <xs:attribute ref="xml:lang"/>
+    <xs:attribute name="dir">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="ltr"/>
+          <xs:enumeration value="rtl"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="events">
+    <xs:annotation>
+      <xs:documentation>
+      attributes for common UI events
+      onclick     a pointer button was clicked
+      ondblclick  a pointer button was double clicked
+      onmousedown a pointer button was pressed down
+      onmouseup   a pointer button was released
+      onmousemove a pointer was moved onto the element
+      onmouseout  a pointer was moved away from the element
+      onkeypress  a key was pressed and released
+      onkeydown   a key was pressed down
+      onkeyup     a key was released
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="onclick" type="Script"/>
+    <xs:attribute name="ondblclick" type="Script"/>
+    <xs:attribute name="onmousedown" type="Script"/>
+    <xs:attribute name="onmouseup" type="Script"/>
+    <xs:attribute name="onmouseover" type="Script"/>
+    <xs:attribute name="onmousemove" type="Script"/>
+    <xs:attribute name="onmouseout" type="Script"/>
+    <xs:attribute name="onkeypress" type="Script"/>
+    <xs:attribute name="onkeydown" type="Script"/>
+    <xs:attribute name="onkeyup" type="Script"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="focus">
+    <xs:annotation>
+      <xs:documentation>
+      attributes for elements that can get the focus
+      accesskey   accessibility key character
+      tabindex    position in tabbing order
+      onfocus     the element got the focus
+      onblur      the element lost the focus
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="accesskey" type="Character"/>
+    <xs:attribute name="tabindex" type="tabindexNumber"/>
+    <xs:attribute name="onfocus" type="Script"/>
+    <xs:attribute name="onblur" type="Script"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="attrs">
+    <xs:attributeGroup ref="coreattrs"/>
+    <xs:attributeGroup ref="i18n"/>
+    <xs:attributeGroup ref="events"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="TextAlign">
+    <xs:annotation>
+      <xs:documentation>
+      text alignment for p, div, h1-h6. The default is
+      align="left" for ltr headings, "right" for rtl
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="align">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="left"/>
+          <xs:enumeration value="center"/>
+          <xs:enumeration value="right"/>
+          <xs:enumeration value="justify"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Text Elements ====================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:group name="special.extra">
+    <xs:choice>
+      <xs:element ref="object"/>
+      <xs:element ref="applet"/>
+      <xs:element ref="img"/>
+      <xs:element ref="map"/>
+      <xs:element ref="iframe"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="special.basic">
+    <xs:choice>
+      <xs:element ref="br"/>
+      <xs:element ref="span"/>
+      <xs:element ref="bdo"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="special">
+    <xs:choice>
+      <xs:group ref="special.basic"/>
+      <xs:group ref="special.extra"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="fontstyle.extra">
+    <xs:choice>
+      <xs:element ref="big"/>
+      <xs:element ref="small"/>
+      <xs:element ref="font"/>
+      <xs:element ref="basefont"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="fontstyle.basic">
+    <xs:choice>
+      <xs:element ref="tt"/>
+      <xs:element ref="i"/>
+      <xs:element ref="b"/>
+      <xs:element ref="u"/>
+      <xs:element ref="s"/>
+      <xs:element ref="strike"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="fontstyle">
+    <xs:choice>
+      <xs:group ref="fontstyle.basic"/>
+      <xs:group ref="fontstyle.extra"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="phrase.extra">
+    <xs:choice>
+      <xs:element ref="sub"/>
+      <xs:element ref="sup"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="phrase.basic">
+    <xs:choice>
+      <xs:element ref="em"/>
+      <xs:element ref="strong"/>
+      <xs:element ref="dfn"/>
+      <xs:element ref="code"/>
+      <xs:element ref="q"/>
+      <xs:element ref="samp"/>
+      <xs:element ref="kbd"/>
+      <xs:element ref="var"/>
+      <xs:element ref="cite"/>
+      <xs:element ref="abbr"/>
+      <xs:element ref="acronym"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="phrase">
+    <xs:choice>
+      <xs:group ref="phrase.basic"/>
+      <xs:group ref="phrase.extra"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="inline.forms">
+    <xs:choice>
+      <xs:element ref="input"/>
+      <xs:element ref="select"/>
+      <xs:element ref="textarea"/>
+      <xs:element ref="label"/>
+      <xs:element ref="button"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="misc.inline">
+    <xs:annotation>
+      <xs:documentation>
+      these can only occur at block level
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice>
+      <xs:element ref="ins"/>
+      <xs:element ref="del"/>
+      <xs:element ref="script"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="misc">
+    <xs:annotation>
+      <xs:documentation>
+      these can only occur at block level
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice>
+      <xs:element ref="noscript"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="inline">
+    <xs:choice>
+      <xs:element ref="a"/>
+      <xs:group ref="special"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="inline.forms"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:complexType name="Inline" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      "Inline" covers inline or "text-level" element
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="inline"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Block level elements ==============================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:group name="heading">
+    <xs:choice>
+      <xs:element ref="h1"/>
+      <xs:element ref="h2"/>
+      <xs:element ref="h3"/>
+      <xs:element ref="h4"/>
+      <xs:element ref="h5"/>
+      <xs:element ref="h6"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="lists">
+    <xs:choice>
+      <xs:element ref="ul"/>
+      <xs:element ref="ol"/>
+      <xs:element ref="dl"/>
+      <xs:element ref="menu"/>
+      <xs:element ref="dir"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="blocktext">
+    <xs:choice>
+      <xs:element ref="pre"/>
+      <xs:element ref="hr"/>
+      <xs:element ref="blockquote"/>
+      <xs:element ref="address"/>
+      <xs:element ref="center"/>
+      <xs:element ref="noframes"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:group name="block">
+    <xs:choice>
+      <xs:element ref="p"/>
+      <xs:group ref="heading"/>
+      <xs:element ref="div"/>
+      <xs:group ref="lists"/>
+      <xs:group ref="blocktext"/>
+      <xs:element ref="isindex"/>
+      <xs:element ref="fieldset"/>
+      <xs:element ref="table"/>
+    </xs:choice>
+  </xs:group>
+
+  <xs:complexType name="Flow" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      "Flow" mixes block and inline and is used for list items etc.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="block"/>
+      <xs:element ref="form"/>
+      <xs:element ref="embed"/>
+      <xs:group ref="inline"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Content models for exclusions =====================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:complexType name="a.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      a elements use "Inline" excluding a
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="special"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="inline.forms"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="pre.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      pre uses "Inline" excluding img, object, applet, big, small,
+      font, or basefont
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="a"/>
+      <xs:group ref="special.basic"/>
+      <xs:group ref="fontstyle.basic"/>
+      <xs:group ref="phrase.basic"/>
+      <xs:group ref="inline.forms"/>
+      <xs:group ref="misc.inline"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="form.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      form uses "Flow" excluding form
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:group ref="block"/>
+      <xs:group ref="inline"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:complexType name="button.content" mixed="true">
+    <xs:annotation>
+      <xs:documentation>
+      button uses "Flow" but excludes a, form, form controls, iframe
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="p"/>
+      <xs:group ref="heading"/>
+      <xs:element ref="div"/>
+      <xs:group ref="lists"/>
+      <xs:group ref="blocktext"/>
+      <xs:element ref="table"/>
+      <xs:element ref="br"/>
+      <xs:element ref="span"/>
+      <xs:element ref="bdo"/>
+      <xs:element ref="object"/>
+      <xs:element ref="applet"/>
+      <xs:element ref="img"/>
+      <xs:element ref="map"/>
+      <xs:group ref="fontstyle"/>
+      <xs:group ref="phrase"/>
+      <xs:group ref="misc"/>
+    </xs:choice>
+  </xs:complexType>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Document Structure ==================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="html">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element ref="head"/>
+        <xs:element ref="body"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Document Head =======================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:group name="head.misc">
+    <xs:sequence>
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="script"/>
+        <xs:element ref="style"/>
+        <xs:element ref="meta"/>
+        <xs:element ref="link"/>
+        <xs:element ref="object"/>
+        <xs:element ref="isindex"/>
+      </xs:choice>
+    </xs:sequence>
+  </xs:group>
+
+  <xs:element name="head">
+    <xs:annotation>
+      <xs:documentation>
+      content model is "head.misc" combined with a single
+      title and an optional base element in any order
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:group ref="head.misc"/>
+        <xs:choice>
+          <xs:sequence>
+            <xs:element ref="title"/>
+            <xs:group ref="head.misc"/>
+            <xs:sequence minOccurs="0">
+              <xs:element ref="base"/>
+              <xs:group ref="head.misc"/>
+            </xs:sequence>
+          </xs:sequence>
+          <xs:sequence>
+            <xs:element ref="base"/>
+            <xs:group ref="head.misc"/>
+            <xs:element ref="title"/>
+            <xs:group ref="head.misc"/>
+          </xs:sequence>
+        </xs:choice>
+      </xs:sequence>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="profile" type="URI"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="title">
+    <xs:annotation>
+      <xs:documentation>
+      The title element is not considered part of the flow of text.
+      It should be displayed, for example as the page header or
+      window title. Exactly one title is required per document.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="base">
+    <xs:annotation>
+      <xs:documentation>
+      document base URI
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="href" type="URI"/>
+      <xs:attribute name="target" type="FrameTarget"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="meta">
+    <xs:annotation>
+      <xs:documentation>
+      generic metainformation
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="http-equiv"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="content" use="required"/>
+      <xs:attribute name="scheme"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="link">
+    <xs:annotation>
+      <xs:documentation>
+      Relationship values can be used in principle:
+
+      a) for document specific toolbars/menus when used
+         with the link element in document head e.g.
+           start, contents, previous, next, index, end, help
+      b) to link to a separate style sheet (rel="stylesheet")
+      c) to make a link to a script (rel="script")
+      d) by stylesheets to control how collections of
+         html nodes are rendered into printed documents
+      e) to make a link to a printable version of this document
+         e.g. a PostScript or PDF version (rel="alternate" media="print")
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="charset" type="Charset"/>
+      <xs:attribute name="href" type="URI"/>
+      <xs:attribute name="hreflang" type="LanguageCode"/>
+      <xs:attribute name="type" type="ContentType"/>
+      <xs:attribute name="rel" type="LinkTypes"/>
+      <xs:attribute name="rev" type="LinkTypes"/>
+      <xs:attribute name="media" type="MediaDesc"/>
+      <xs:attribute name="target" type="FrameTarget"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="style">
+    <xs:annotation>
+      <xs:documentation>
+      style info, which may include CDATA sections
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="type" use="required" type="ContentType"/>
+      <xs:attribute name="media" type="MediaDesc"/>
+      <xs:attribute name="title" type="Text"/>
+      <xs:attribute ref="xml:space" fixed="preserve"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="script">
+    <xs:annotation>
+      <xs:documentation>
+      script statements, which may include CDATA sections
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="charset" type="Charset"/>
+      <xs:attribute name="type" use="required" type="ContentType"/>
+      <xs:attribute name="language"/>
+      <xs:attribute name="src" type="URI"/>
+      <xs:attribute name="defer">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="defer"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute ref="xml:space" fixed="preserve"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="noscript">
+    <xs:annotation>
+      <xs:documentation>
+      alternate content container for non script-based rendering
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ======================= Frames =======================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="iframe">
+    <xs:annotation>
+      <xs:documentation>
+      inline subwindow
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="coreattrs"/>
+          <xs:attribute name="longdesc" type="URI"/>
+          <xs:attribute name="name" type="xs:NMTOKEN"/>
+          <xs:attribute name="src" type="URI"/>
+          <xs:attribute name="frameborder" default="1">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="1"/>
+                <xs:enumeration value="0"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="marginwidth" type="Pixels"/>
+          <xs:attribute name="marginheight" type="Pixels"/>
+          <xs:attribute name="scrolling" default="auto">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="yes"/>
+                <xs:enumeration value="no"/>
+                <xs:enumeration value="auto"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="align" type="ImgAlign"/>
+          <xs:attribute name="height" type="Length"/>
+          <xs:attribute name="width" type="Length"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="noframes">
+    <xs:annotation>
+      <xs:documentation>
+      alternate content container for non frame-based rendering
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Document Body ====================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="body">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="onload" type="Script"/>
+          <xs:attribute name="onunload" type="Script"/>
+          <xs:attribute name="background" type="URI"/>
+          <xs:attribute name="bgcolor" type="Color"/>
+          <xs:attribute name="text" type="Color"/>
+          <xs:attribute name="link" type="Color"/>
+          <xs:attribute name="vlink" type="Color"/>
+          <xs:attribute name="alink" type="Color"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="div">
+    <xs:annotation>
+      <xs:documentation>
+      generic language/style container
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Paragraphs =======================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="p">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Headings =========================================
+
+    There are six levels of headings from h1 (the most important)
+    to h6 (the least important).
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="h1">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h2">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h3">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h4">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h5">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="h6">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="TextAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Lists ============================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="ULStyle">
+    <xs:annotation>
+      <xs:documentation>
+      Unordered list bullet styles
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="disc"/>
+      <xs:enumeration value="square"/>
+      <xs:enumeration value="circle"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="ul">
+    <xs:annotation>
+      <xs:documentation>
+      Unordered list
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="type" type="ULStyle"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="OLStyle">
+    <xs:annotation>
+      <xs:documentation>
+      Ordered list numbering style
+
+      1   arabic numbers      1, 2, 3, ...
+      a   lower alpha         a, b, c, ...
+      A   upper alpha         A, B, C, ...
+      i   lower roman         i, ii, iii, ...
+      I   upper roman         I, II, III, ...
+
+      The style is applied to the sequence number which by default
+      is reset to 1 for the first list item in an ordered list.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:element name="ol">
+    <xs:annotation>
+      <xs:documentation>
+      Ordered (numbered) list
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="type" type="OLStyle"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="start" type="Number"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="menu">
+    <xs:annotation>
+      <xs:documentation>
+      single column list (DEPRECATED)
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dir">
+    <xs:annotation>
+      <xs:documentation>
+      multiple column list (DEPRECATED)
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="li"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="LIStyle">
+    <xs:annotation>
+      <xs:documentation>
+      LIStyle is constrained to: "(ULStyle|OLStyle)"
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:element name="li">
+    <xs:annotation>
+      <xs:documentation>
+      list item
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="type" type="LIStyle"/>
+          <xs:attribute name="value" type="Number"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    definition lists - dt for term, dd for its definition
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="dl">
+    <xs:complexType>
+      <xs:choice maxOccurs="unbounded">
+        <xs:element ref="dt"/>
+        <xs:element ref="dd"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="compact">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="compact"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dt">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dd">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Address ==========================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="address">
+    <xs:annotation>
+      <xs:documentation>
+      information on author
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:group ref="inline"/>
+        <xs:group ref="misc.inline"/>
+        <xs:element ref="p"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Horizontal Rule ==================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="hr">
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="align">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="left"/>
+            <xs:enumeration value="center"/>
+            <xs:enumeration value="right"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="noshade">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="noshade"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="size" type="Pixels"/>
+      <xs:attribute name="width" type="Length"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Preformatted Text ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="pre">
+    <xs:annotation>
+      <xs:documentation>
+      content is "Inline" excluding
+         "img|object|applet|big|small|sub|sup|font|basefont"
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="pre.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="width" type="Number"/>
+          <xs:attribute ref="xml:space" fixed="preserve"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Block-like Quotes ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="blockquote">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Text alignment ===================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="center">
+    <xs:annotation>
+      <xs:documentation>
+      center content
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Inserted/Deleted Text ============================
+
+    ins/del are allowed in block and inline content, but its
+    inappropriate to include block content within an ins element
+    occurring in inline content.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="ins">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+          <xs:attribute name="datetime" type="Datetime"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="del">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+          <xs:attribute name="datetime" type="Datetime"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== The Anchor Element ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="a">
+    <xs:annotation>
+      <xs:documentation>
+      content is "Inline" except that anchors shouldn't be nested
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="a.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="focus"/>
+          <xs:attribute name="charset" type="Charset"/>
+          <xs:attribute name="type" type="ContentType"/>
+          <xs:attribute name="name" type="xs:ID"/>
+          <xs:attribute name="href" type="URI"/>
+          <xs:attribute name="hreflang" type="LanguageCode"/>
+          <xs:attribute name="rel" type="LinkTypes"/>
+          <xs:attribute name="rev" type="LinkTypes"/>
+          <xs:attribute name="shape" default="rect" type="Shape"/>
+          <xs:attribute name="coords" type="Coords"/>
+          <xs:attribute name="target" type="FrameTarget"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ===================== Inline Elements ================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="span">
+    <xs:annotation>
+      <xs:documentation>
+      generic language/style container
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="bdo">
+    <xs:annotation>
+      <xs:documentation>
+      I18N BiDi over-ride
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="coreattrs"/>
+          <xs:attributeGroup ref="events"/>
+          <xs:attribute name="lang" type="LanguageCode"/>
+          <xs:attribute ref="xml:lang"/>
+          <xs:attribute name="dir" use="required">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="ltr"/>
+                <xs:enumeration value="rtl"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="br">
+    <xs:annotation>
+      <xs:documentation>
+      forced line break
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="coreattrs"/>
+      <xs:attribute name="clear" default="none">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="left"/>
+            <xs:enumeration value="all"/>
+            <xs:enumeration value="right"/>
+            <xs:enumeration value="none"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="em">
+    <xs:annotation>
+      <xs:documentation>
+      emphasis
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="strong">
+    <xs:annotation>
+      <xs:documentation>
+      strong emphasis
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="dfn">
+    <xs:annotation>
+      <xs:documentation>
+      definitional
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="code">
+    <xs:annotation>
+      <xs:documentation>
+      program code
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="samp">
+    <xs:annotation>
+      <xs:documentation>
+      sample
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="kbd">
+    <xs:annotation>
+      <xs:documentation>
+      something user would type
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="var">
+    <xs:annotation>
+      <xs:documentation>
+      variable
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="cite">
+    <xs:annotation>
+      <xs:documentation>
+      citation
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="abbr">
+    <xs:annotation>
+      <xs:documentation>
+      abbreviation
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="acronym">
+    <xs:annotation>
+      <xs:documentation>
+      acronym
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="q">
+    <xs:annotation>
+      <xs:documentation>
+      inlined quote
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="cite" type="URI"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="sub">
+    <xs:annotation>
+      <xs:documentation>
+      subscript
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="sup">
+    <xs:annotation>
+      <xs:documentation>
+      superscript
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tt">
+    <xs:annotation>
+      <xs:documentation>
+      fixed pitch font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="i">
+    <xs:annotation>
+      <xs:documentation>
+      italic font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="b">
+    <xs:annotation>
+      <xs:documentation>
+      bold font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="big">
+    <xs:annotation>
+      <xs:documentation>
+      bigger font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="small">
+    <xs:annotation>
+      <xs:documentation>
+      smaller font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="u">
+    <xs:annotation>
+      <xs:documentation>
+      underline
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="s">
+    <xs:annotation>
+      <xs:documentation>
+      strike-through
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="strike">
+    <xs:annotation>
+      <xs:documentation>
+      strike-through
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="basefont">
+    <xs:annotation>
+      <xs:documentation>
+      base font size
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="size" use="required"/>
+      <xs:attribute name="color" type="Color"/>
+      <xs:attribute name="face"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="font">
+    <xs:annotation>
+      <xs:documentation>
+      local change to font
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="coreattrs"/>
+          <xs:attributeGroup ref="i18n"/>
+          <xs:attribute name="size"/>
+          <xs:attribute name="color" type="Color"/>
+          <xs:attribute name="face"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ==================== Object ======================================
+
+    object is used to embed objects as part of HTML pages.
+    param elements should precede other content. Parameters
+    can also be expressed as attribute/value pairs on the
+    object element itself when brevity is desired.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="object">
+    <xs:complexType mixed="true">
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="param"/>
+        <xs:group ref="block"/>
+        <xs:element ref="form"/>
+        <xs:group ref="inline"/>
+        <xs:group ref="misc"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="declare">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="declare"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="classid" type="URI"/>
+      <xs:attribute name="codebase" type="URI"/>
+      <xs:attribute name="data" type="URI"/>
+      <xs:attribute name="type" type="ContentType"/>
+      <xs:attribute name="codetype" type="ContentType"/>
+      <xs:attribute name="archive" type="UriList"/>
+      <xs:attribute name="standby" type="Text"/>
+      <xs:attribute name="height" type="Length"/>
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="usemap" type="URI"/>
+      <xs:attribute name="name" type="xs:NMTOKEN"/>
+      <xs:attribute name="tabindex" type="Number"/>
+      <xs:attribute name="align" type="ImgAlign"/>
+      <xs:attribute name="border" type="Pixels"/>
+      <xs:attribute name="hspace" type="Pixels"/>
+      <xs:attribute name="vspace" type="Pixels"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="param">
+    <xs:annotation>
+      <xs:documentation>
+      param is used to supply a named property value.
+      In XML it would seem natural to follow RDF and support an
+      abbreviated syntax where the param elements are replaced
+      by attribute value pairs on the object start tag.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attribute name="id" type="xs:ID"/>
+      <xs:attribute name="name" use="required"/>
+      <xs:attribute name="value"/>
+      <xs:attribute name="valuetype" default="data">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="data"/>
+            <xs:enumeration value="ref"/>
+            <xs:enumeration value="object"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="type" type="ContentType"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Java applet ==================================
+
+    One of code or object attributes must be present.
+    Place param elements before other content.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="applet">
+    <xs:complexType mixed="true">
+      <xs:choice minOccurs="0" maxOccurs="unbounded">
+        <xs:element ref="param"/>
+        <xs:group ref="block"/>
+        <xs:element ref="form"/>
+        <xs:group ref="inline"/>
+        <xs:group ref="misc"/>
+      </xs:choice>
+      <xs:attributeGroup ref="coreattrs"/>
+      <xs:attribute name="codebase" type="URI"/>
+      <xs:attribute name="archive"/>
+      <xs:attribute name="code"/>
+      <xs:attribute name="object"/>
+      <xs:attribute name="alt" type="Text"/>
+      <xs:attribute name="name" type="xs:NMTOKEN"/>
+      <xs:attribute name="width" use="required" type="Length"/>
+      <xs:attribute name="height" use="required" type="Length"/>
+      <xs:attribute name="align" type="ImgAlign"/>
+      <xs:attribute name="hspace" type="Pixels"/>
+      <xs:attribute name="vspace" type="Pixels"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    =================== Images ===========================================
+
+    To avoid accessibility problems for people who aren't
+    able to see the image, you should provide a text
+    description using the alt and longdesc attributes.
+    In addition, avoid the use of server-side image maps.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="img">
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="src" use="required" type="URI"/>
+      <xs:attribute name="alt" use="required" type="Text"/>
+      <xs:attribute name="name" type="xs:NMTOKEN"/>
+      <xs:attribute name="longdesc" type="URI"/>
+      <xs:attribute name="height" type="Length"/>
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="usemap" type="URI">
+  <xs:annotation>
+    <xs:documentation>
+          usemap points to a map element which may be in this document
+          or an external document, although the latter is not widely supported
+          </xs:documentation>
+  </xs:annotation>
+      </xs:attribute>
+      <xs:attribute name="ismap">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="ismap"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="align" type="ImgAlign"/>
+      <xs:attribute name="border" type="Length"/>
+      <xs:attribute name="hspace" type="Pixels"/>
+      <xs:attribute name="vspace" type="Pixels"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================== Client-side image maps ============================
+
+    These can be placed in the same document or grouped in a
+    separate document although this isn't yet widely supported
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="map">
+    <xs:complexType>
+      <xs:choice>
+        <xs:choice maxOccurs="unbounded">
+          <xs:group ref="block"/>
+          <xs:element ref="form"/>
+          <xs:group ref="misc"/>
+        </xs:choice>
+        <xs:element maxOccurs="unbounded" ref="area"/>
+      </xs:choice>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attributeGroup ref="events"/>
+      <xs:attribute name="id" use="required" type="xs:ID"/>
+      <xs:attribute name="class"/>
+      <xs:attribute name="style" type="StyleSheet"/>
+      <xs:attribute name="title" type="Text"/>
+      <xs:attribute name="name"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="area">
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="focus"/>
+      <xs:attribute name="shape" default="rect" type="Shape"/>
+      <xs:attribute name="coords" type="Coords"/>
+      <xs:attribute name="href" type="URI"/>
+      <xs:attribute name="nohref">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="nohref"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="alt" use="required" type="Text"/>
+      <xs:attribute name="target" type="FrameTarget"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ================ Forms ===============================================
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="form">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="form.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="action" use="required" type="URI"/>
+          <xs:attribute name="name" type="xs:NMTOKEN"/>
+          <xs:attribute name="method" default="get">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="get"/>
+                <xs:enumeration value="post"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="enctype" type="ContentType"
+              default="application/x-www-form-urlencoded"/>
+          <xs:attribute name="onsubmit" type="Script"/>
+          <xs:attribute name="onreset" type="Script"/>
+          <xs:attribute name="accept" type="ContentTypes"/>
+          <xs:attribute name="accept-charset" type="Charsets"/>
+          <xs:attribute name="target" type="FrameTarget"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="label">
+    <xs:annotation>
+      <xs:documentation>
+      Each label must not contain more than ONE field
+      Label elements shouldn't be nested.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="for" type="xs:IDREF"/>
+          <xs:attribute name="accesskey" type="Character"/>
+          <xs:attribute name="onfocus" type="Script"/>
+          <xs:attribute name="onblur" type="Script"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="InputType">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="text"/>
+      <xs:enumeration value="password"/>
+      <xs:enumeration value="checkbox"/>
+      <xs:enumeration value="radio"/>
+      <xs:enumeration value="submit"/>
+      <xs:enumeration value="reset"/>
+      <xs:enumeration value="file"/>
+      <xs:enumeration value="hidden"/>
+      <xs:enumeration value="image"/>
+      <xs:enumeration value="button"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="input">
+    <xs:annotation>
+      <xs:documentation>
+      form control
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="focus"/>
+      <xs:attribute name="type" default="text" type="InputType"/>
+      <xs:attribute name="name">
+  <xs:annotation>
+    <xs:documentation>
+          the name attribute is required for all but submit &amp; reset
+          </xs:documentation>
+  </xs:annotation>
+      </xs:attribute>
+      <xs:attribute name="value"/>
+      <xs:attribute name="checked">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="checked"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="readonly">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="readonly"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="size"/>
+      <xs:attribute name="maxlength" type="Number"/>
+      <xs:attribute name="src" type="URI"/>
+      <xs:attribute name="alt"/>
+      <xs:attribute name="usemap" type="URI"/>
+      <xs:attribute name="onselect" type="Script"/>
+      <xs:attribute name="onchange" type="Script"/>
+      <xs:attribute name="accept" type="ContentTypes"/>
+      <xs:attribute name="align" type="ImgAlign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="select">
+    <xs:annotation>
+      <xs:documentation>
+      option selector
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:choice maxOccurs="unbounded">
+        <xs:element ref="optgroup"/>
+        <xs:element ref="option"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="size" type="Number"/>
+      <xs:attribute name="multiple">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="multiple"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="tabindex" type="tabindexNumber"/>
+      <xs:attribute name="onfocus" type="Script"/>
+      <xs:attribute name="onblur" type="Script"/>
+      <xs:attribute name="onchange" type="Script"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="optgroup">
+    <xs:annotation>
+      <xs:documentation>
+      option group
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="option"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="label" use="required" type="Text"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="option">
+    <xs:annotation>
+      <xs:documentation>
+      selectable choice
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="selected">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="selected"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="label" type="Text"/>
+      <xs:attribute name="value"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="textarea">
+    <xs:annotation>
+      <xs:documentation>
+      multi-line text field
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="focus"/>
+      <xs:attribute name="name"/>
+      <xs:attribute name="rows" use="required" type="Number"/>
+      <xs:attribute name="cols" use="required" type="Number"/>
+      <xs:attribute name="disabled">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="disabled"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="readonly">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="readonly"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:attribute>
+      <xs:attribute name="onselect" type="Script"/>
+      <xs:attribute name="onchange" type="Script"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="fieldset">
+    <xs:annotation>
+      <xs:documentation>
+      The fieldset element is used to group form fields.
+      Only one legend element should occur in the content
+      and if present should only be preceded by whitespace.
+
+      NOTE: this content model is different from the XHTML 1.0 DTD,
+      closer to the intended content model in HTML4 DTD
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:sequence>
+        <xs:element ref="legend"/>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:group ref="block"/>
+          <xs:element ref="form"/>
+          <xs:group ref="inline"/>
+          <xs:group ref="misc"/>
+        </xs:choice>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="LAlign">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="top"/>
+      <xs:enumeration value="bottom"/>
+      <xs:enumeration value="left"/>
+      <xs:enumeration value="right"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="legend">
+    <xs:annotation>
+      <xs:documentation>
+      fieldset label
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="accesskey" type="Character"/>
+          <xs:attribute name="align" type="LAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="button">
+    <xs:annotation>
+      <xs:documentation>
+      Content is "Flow" excluding a, form and form controls
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="button.content">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attributeGroup ref="focus"/>
+          <xs:attribute name="name"/>
+          <xs:attribute name="value"/>
+          <xs:attribute name="type" default="submit">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="button"/>
+                <xs:enumeration value="submit"/>
+                <xs:enumeration value="reset"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="disabled">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="disabled"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="isindex">
+    <xs:annotation>
+      <xs:documentation>
+      single-line text input control (DEPRECATED)
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="coreattrs"/>
+      <xs:attributeGroup ref="i18n"/>
+      <xs:attribute name="prompt" type="Text"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    ======================= Tables =======================================
+
+    Derived from IETF HTML table standard, see [RFC1942]
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:simpleType name="TFrame">
+    <xs:annotation>
+      <xs:documentation>
+      The border attribute sets the thickness of the frame around the
+      table. The default units are screen pixels.
+
+      The frame attribute specifies which parts of the frame around
+      the table should be rendered. The values are not the same as
+      CALS to avoid a name clash with the valign attribute.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="void"/>
+      <xs:enumeration value="above"/>
+      <xs:enumeration value="below"/>
+      <xs:enumeration value="hsides"/>
+      <xs:enumeration value="lhs"/>
+      <xs:enumeration value="rhs"/>
+      <xs:enumeration value="vsides"/>
+      <xs:enumeration value="box"/>
+      <xs:enumeration value="border"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="TRules">
+    <xs:annotation>
+      <xs:documentation>
+      The rules attribute defines which rules to draw between cells:
+
+      If rules is absent then assume:
+          "none" if border is absent or border="0" otherwise "all"
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="none"/>
+      <xs:enumeration value="groups"/>
+      <xs:enumeration value="rows"/>
+      <xs:enumeration value="cols"/>
+      <xs:enumeration value="all"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:simpleType name="TAlign">
+    <xs:annotation>
+      <xs:documentation>
+      horizontal placement of table relative to document
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="left"/>
+      <xs:enumeration value="center"/>
+      <xs:enumeration value="right"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:attributeGroup name="cellhalign">
+    <xs:annotation>
+      <xs:documentation>
+      horizontal alignment attributes for cell contents
+
+      char        alignment char, e.g. char=':'
+      charoff     offset for alignment char
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="align">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="left"/>
+          <xs:enumeration value="center"/>
+          <xs:enumeration value="right"/>
+          <xs:enumeration value="justify"/>
+          <xs:enumeration value="char"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+    <xs:attribute name="char" type="Character"/>
+    <xs:attribute name="charoff" type="Length"/>
+  </xs:attributeGroup>
+
+  <xs:attributeGroup name="cellvalign">
+    <xs:annotation>
+      <xs:documentation>
+      vertical alignment attributes for cell contents
+      </xs:documentation>
+    </xs:annotation>
+    <xs:attribute name="valign">
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="top"/>
+          <xs:enumeration value="middle"/>
+          <xs:enumeration value="bottom"/>
+          <xs:enumeration value="baseline"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:attributeGroup>
+
+  <xs:element name="table">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element minOccurs="0" ref="caption"/>
+        <xs:choice>
+          <xs:element minOccurs="0" maxOccurs="unbounded" ref="col"/>
+          <xs:element minOccurs="0" maxOccurs="unbounded" ref="colgroup"/>
+        </xs:choice>
+        <xs:element minOccurs="0" ref="thead"/>
+        <xs:element minOccurs="0" ref="tfoot"/>
+        <xs:choice>
+          <xs:element maxOccurs="unbounded" ref="tbody"/>
+          <xs:element maxOccurs="unbounded" ref="tr"/>
+        </xs:choice>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="summary" type="Text"/>
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="border" type="Pixels"/>
+      <xs:attribute name="frame" type="TFrame"/>
+      <xs:attribute name="rules" type="TRules"/>
+      <xs:attribute name="cellspacing" type="Length"/>
+      <xs:attribute name="cellpadding" type="Length"/>
+      <xs:attribute name="align" type="TAlign"/>
+      <xs:attribute name="bgcolor" type="Color"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="CAlign">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="top"/>
+      <xs:enumeration value="bottom"/>
+      <xs:enumeration value="left"/>
+      <xs:enumeration value="right"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="caption">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Inline">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="align" type="CAlign"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:annotation>
+    <xs:documentation>
+    Use thead to duplicate headers when breaking table
+    across page boundaries, or for static headers when
+    tbody sections are rendered in scrolling panel.
+
+    Use tfoot to duplicate footers when breaking table
+    across page boundaries, or for static footers when
+    tbody sections are rendered in scrolling panel.
+
+    Use multiple tbody sections when rules are needed
+    between groups of table rows.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="thead">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="tr"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tfoot">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="tr"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tbody">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element maxOccurs="unbounded" ref="tr"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="colgroup">
+    <xs:annotation>
+      <xs:documentation>
+      colgroup groups a set of col elements. It allows you to group
+      several semantically related columns together.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element minOccurs="0" maxOccurs="unbounded" ref="col"/>
+      </xs:sequence>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="span" default="1" type="Number"/>
+      <xs:attribute name="width" type="MultiLength"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="col">
+    <xs:annotation>
+      <xs:documentation>
+      col elements define the alignment properties for cells in
+      one or more columns.
+
+      The width attribute specifies the width of the columns, e.g.
+
+          width=64        width in screen pixels
+          width=0.5*      relative width of 0.5
+
+      The span attribute causes the attributes of one
+      col element to apply to more than one column.
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexType>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attribute name="span" default="1" type="Number"/>
+      <xs:attribute name="width" type="MultiLength"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="tr">
+    <xs:complexType>
+      <xs:choice maxOccurs="unbounded">
+        <xs:element ref="th"/>
+        <xs:element ref="td"/>
+      </xs:choice>
+      <xs:attributeGroup ref="attrs"/>
+      <xs:attributeGroup ref="cellhalign"/>
+      <xs:attributeGroup ref="cellvalign"/>
+      <xs:attribute name="bgcolor" type="Color"/>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="Scope">
+    <xs:annotation>
+      <xs:documentation>
+      Scope is simpler than headers attribute for common tables
+      </xs:documentation>
+    </xs:annotation>
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="row"/>
+      <xs:enumeration value="col"/>
+      <xs:enumeration value="rowgroup"/>
+      <xs:enumeration value="colgroup"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:annotation>
+    <xs:documentation>
+    th is for headers, td for data and for cells acting as both
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="th">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="abbr" type="Text"/>
+          <xs:attribute name="axis"/>
+          <xs:attribute name="headers" type="xs:IDREFS"/>
+          <xs:attribute name="scope" type="Scope"/>
+          <xs:attribute name="rowspan" default="1" type="Number"/>
+          <xs:attribute name="colspan" default="1" type="Number"/>
+          <xs:attributeGroup ref="cellhalign"/>
+          <xs:attributeGroup ref="cellvalign"/>
+          <xs:attribute name="nowrap">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="nowrap"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="bgcolor" type="Color"/>
+          <xs:attribute name="width" type="Length"/>
+          <xs:attribute name="height" type="Length"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="td">
+    <xs:complexType mixed="true">
+      <xs:complexContent>
+        <xs:extension base="Flow">
+          <xs:attributeGroup ref="attrs"/>
+          <xs:attribute name="abbr" type="Text"/>
+          <xs:attribute name="axis"/>
+          <xs:attribute name="headers" type="xs:IDREFS"/>
+          <xs:attribute name="scope" type="Scope"/>
+          <xs:attribute name="rowspan" default="1" type="Number"/>
+          <xs:attribute name="colspan" default="1" type="Number"/>
+          <xs:attributeGroup ref="cellhalign"/>
+          <xs:attributeGroup ref="cellvalign"/>
+          <xs:attribute name="nowrap">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="nowrap"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:attribute>
+          <xs:attribute name="bgcolor" type="Color"/>
+          <xs:attribute name="width" type="Length"/>
+          <xs:attribute name="height" type="Length"/>
+        </xs:extension>
+      </xs:complexContent>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:element name="embed">
+    <xs:complexType>
+      <xs:attribute name="alt" type="Text" />
+      <xs:attribute name="width" type="Length"/>
+      <xs:attribute name="height" type="Length"/>
+      <xs:attribute name="hidden" type="xs:boolean"/>
+      <xs:attribute name="pluginspage" type="URI"/>
+      <xs:attribute name="src" type="URI"/>
+      <xs:attribute name="type" type="xs:string"/>
+      <xs:attribute name="wmode" type="xs:string"/>
+    </xs:complexType>
+  </xs:element>
+</xs:schema>
\ No newline at end of file
diff --git a/xml/impl/resources/standardSchemas/xhtml1.dtd b/xml/impl/resources/standardSchemas/xhtml1.dtd
new file mode 100644
index 0000000..60ab4ae
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml1.dtd
@@ -0,0 +1,1201 @@
+<!--
+   Extensible HTML version 1.0 Transitional DTD
+
+   This is the same as HTML 4 Transitional except for
+   changes due to the differences between XML and SGML.
+
+   Namespace = http://www.w3.org/1999/xhtml
+
+   For further information, see: http://www.w3.org/TR/xhtml1
+
+   Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+   All Rights Reserved. 
+
+   This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+   PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+   SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+
+   $Revision: 1.1 $
+   $Date: 2004/09/17 17:05:38 $
+
+-->
+
+<!--================ Character mnemonic entities =========================-->
+
+<!ENTITY % HTMLlat1 PUBLIC
+   "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+   "xhtml-lat1.ent">
+%HTMLlat1;
+
+<!ENTITY % HTMLsymbol PUBLIC
+   "-//W3C//ENTITIES Symbols for XHTML//EN"
+   "xhtml-symbol.ent">
+%HTMLsymbol;
+
+<!ENTITY % HTMLspecial PUBLIC
+   "-//W3C//ENTITIES Special for XHTML//EN"
+   "xhtml-special.ent">
+%HTMLspecial;
+
+<!--================== Imported Names ====================================-->
+
+<!ENTITY % ContentType "CDATA">
+    <!-- media type, as per [RFC2045] -->
+
+<!ENTITY % ContentTypes "CDATA">
+    <!-- comma-separated list of media types, as per [RFC2045] -->
+
+<!ENTITY % Charset "CDATA">
+    <!-- a character encoding, as per [RFC2045] -->
+
+<!ENTITY % Charsets "CDATA">
+    <!-- a space separated list of character encodings, as per [RFC2045] -->
+
+<!ENTITY % LanguageCode "NMTOKEN">
+    <!-- a language code, as per [RFC3066] -->
+
+<!ENTITY % Character "CDATA">
+    <!-- a single character, as per section 2.2 of [XML] -->
+
+<!ENTITY % Number "CDATA">
+    <!-- one or more digits -->
+
+<!ENTITY % LinkTypes "CDATA">
+    <!-- space-separated list of link types -->
+
+<!ENTITY % MediaDesc "CDATA">
+    <!-- single or comma-separated list of media descriptors -->
+
+<!ENTITY % URI "CDATA">
+    <!-- a Uniform Resource Identifier, see [RFC2396] -->
+
+<!ENTITY % UriList "CDATA">
+    <!-- a space separated list of Uniform Resource Identifiers -->
+
+<!ENTITY % Datetime "CDATA">
+    <!-- date and time information. ISO date format -->
+
+<!ENTITY % Script "CDATA">
+    <!-- script expression -->
+
+<!ENTITY % StyleSheet "CDATA">
+    <!-- style sheet data -->
+
+<!ENTITY % Text "CDATA">
+    <!-- used for titles etc. -->
+
+<!ENTITY % FrameTarget "NMTOKEN">
+    <!-- render in this frame -->
+
+<!ENTITY % Length "CDATA">
+    <!-- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % MultiLength "CDATA">
+    <!-- pixel, percentage, or relative -->
+
+<!ENTITY % Pixels "CDATA">
+    <!-- integer representing length in pixels -->
+
+<!-- these are used for image maps -->
+
+<!ENTITY % Shape "(rect|circle|poly|default)">
+
+<!ENTITY % Coords "CDATA">
+    <!-- comma separated list of lengths -->
+
+<!-- used for object, applet, img, input and iframe -->
+<!ENTITY % ImgAlign "(top|middle|bottom|left|right)">
+
+<!-- a color using sRGB: #RRGGBB as Hex values -->
+<!ENTITY % Color "CDATA">
+
+<!-- There are also 16 widely known color names with their sRGB values:
+
+    Black  = #000000    Green  = #008000
+    Silver = #C0C0C0    Lime   = #00FF00
+    Gray   = #808080    Olive  = #808000
+    White  = #FFFFFF    Yellow = #FFFF00
+    Maroon = #800000    Navy   = #000080
+    Red    = #FF0000    Blue   = #0000FF
+    Purple = #800080    Teal   = #008080
+    Fuchsia= #FF00FF    Aqua   = #00FFFF
+-->
+
+<!--=================== Generic Attributes ===============================-->
+
+<!-- core attributes common to most elements
+  id       document-wide unique id
+  class    space separated list of classes
+  style    associated style info
+  title    advisory title/amplification
+-->
+<!ENTITY % coreattrs
+ "id          ID             #IMPLIED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED"
+  >
+
+<!-- internationalization attributes
+  lang        language code (backwards compatible)
+  xml:lang    language code (as per XML 1.0 spec)
+  dir         direction for weak/neutral text
+-->
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #IMPLIED"
+  >
+
+<!-- attributes for common UI events
+  onclick     a pointer button was clicked
+  ondblclick  a pointer button was double clicked
+  onmousedown a pointer button was pressed down
+  onmouseup   a pointer button was released
+  onmousemove a pointer was moved onto the element
+  onmouseout  a pointer was moved away from the element
+  onkeypress  a key was pressed and released
+  onkeydown   a key was pressed down
+  onkeyup     a key was released
+-->
+<!ENTITY % events
+ "onclick     %Script;       #IMPLIED
+  ondblclick  %Script;       #IMPLIED
+  onmousedown %Script;       #IMPLIED
+  onmouseup   %Script;       #IMPLIED
+  onmouseover %Script;       #IMPLIED
+  onmousemove %Script;       #IMPLIED
+  onmouseout  %Script;       #IMPLIED
+  onkeypress  %Script;       #IMPLIED
+  onkeydown   %Script;       #IMPLIED
+  onkeyup     %Script;       #IMPLIED"
+  >
+
+<!-- attributes for elements that can get the focus
+  accesskey   accessibility key character
+  tabindex    position in tabbing order
+  onfocus     the element got the focus
+  onblur      the element lost the focus
+-->
+<!ENTITY % focus
+ "accesskey   %Character;    #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED"
+  >
+
+<!ENTITY % attrs "%coreattrs; %i18n; %events;">
+
+<!-- text alignment for p, div, h1-h6. The default is
+     align="left" for ltr headings, "right" for rtl -->
+
+<!ENTITY % TextAlign "align (left|center|right|justify) #IMPLIED">
+
+<!--=================== Text Elements ====================================-->
+
+<!ENTITY % special.extra
+   "object | applet | img | map | iframe">
+	
+<!ENTITY % special.basic
+	"br | span | bdo">
+
+<!ENTITY % special
+   "%special.basic; | %special.extra;">
+
+<!ENTITY % fontstyle.extra "big | small | font | basefont">
+
+<!ENTITY % fontstyle.basic "tt | i | b | u
+                      | s | strike ">
+
+<!ENTITY % fontstyle "%fontstyle.basic; | %fontstyle.extra;">
+
+<!ENTITY % phrase.extra "sub | sup">
+<!ENTITY % phrase.basic "em | strong | dfn | code | q |
+                   samp | kbd | var | cite | abbr | acronym">
+
+<!ENTITY % phrase "%phrase.basic; | %phrase.extra;">
+
+<!ENTITY % inline.forms "input | select | textarea | label | button">
+
+<!-- these can occur at block or inline level -->
+<!ENTITY % misc.inline "ins | del | script">
+
+<!-- these can only occur at block level -->
+<!ENTITY % misc "noscript | %misc.inline;">
+
+<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
+
+<!-- %Inline; covers inline or "text-level" elements -->
+<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
+
+<!--================== Block level elements ==============================-->
+
+<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
+<!ENTITY % lists "ul | ol | dl | menu | dir">
+<!ENTITY % blocktext "pre | hr | blockquote | address | center | noframes">
+
+<!ENTITY % block
+    "p | %heading; | div | %lists; | %blocktext; | isindex |fieldset | table">
+
+<!-- %Flow; mixes block and inline and is used for list items etc. -->
+<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
+
+<!--================== Content models for exclusions =====================-->
+
+<!-- a elements use %Inline; excluding a -->
+
+<!ENTITY % a.content
+   "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
+
+<!-- pre uses %Inline excluding img, object, applet, big, small,
+     font, or basefont -->
+
+<!ENTITY % pre.content
+   "(#PCDATA | a | %special.basic; | %fontstyle.basic; | %phrase.basic; |
+	   %inline.forms; | %misc.inline;)*">
+
+<!-- form uses %Flow; excluding form -->
+
+<!ENTITY % form.content "(#PCDATA | %block; | %inline; | %misc;)*">
+
+<!-- button uses %Flow; but excludes a, form, form controls, iframe -->
+
+<!ENTITY % button.content
+   "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
+      table | br | span | bdo | object | applet | img | map |
+      %fontstyle; | %phrase; | %misc;)*">
+
+<!--================ Document Structure ==================================-->
+
+<!-- the namespace URI designates the document profile -->
+
+<!ELEMENT html (head, body)>
+<!ATTLIST html
+  %i18n;
+  id          ID             #IMPLIED
+  xmlns       %URI;          #FIXED 'http://www.w3.org/1999/xhtml'
+  >
+
+<!--================ Document Head =======================================-->
+
+<!ENTITY % head.misc "(script|style|meta|link|object|isindex)*">
+
+<!-- content model is %head.misc; combined with a single
+     title and an optional base element in any order -->
+
+<!ELEMENT head (%head.misc;,
+     ((title, %head.misc;, (base, %head.misc;)?) |
+      (base, %head.misc;, (title, %head.misc;))))>
+
+<!ATTLIST head
+  %i18n;
+  id          ID             #IMPLIED
+  profile     %URI;          #IMPLIED
+  >
+
+<!-- The title element is not considered part of the flow of text.
+       It should be displayed, for example as the page header or
+       window title. Exactly one title is required per document.
+    -->
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title 
+  %i18n;
+  id          ID             #IMPLIED
+  >
+
+<!-- document base URI -->
+
+<!ELEMENT base EMPTY>
+<!ATTLIST base
+  id          ID             #IMPLIED
+  href        %URI;          #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!-- generic metainformation -->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+  %i18n;
+  id          ID             #IMPLIED
+  http-equiv  CDATA          #IMPLIED
+  name        CDATA          #IMPLIED
+  content     CDATA          #REQUIRED
+  scheme      CDATA          #IMPLIED
+  >
+
+<!--
+  Relationship values can be used in principle:
+
+   a) for document specific toolbars/menus when used
+      with the link element in document head e.g.
+        start, contents, previous, next, index, end, help
+   b) to link to a separate style sheet (rel="stylesheet")
+   c) to make a link to a script (rel="script")
+   d) by stylesheets to control how collections of
+      html nodes are rendered into printed documents
+   e) to make a link to a printable version of this document
+      e.g. a PostScript or PDF version (rel="alternate" media="print")
+-->
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+  %attrs;
+  charset     %Charset;      #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  type        %ContentType;  #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  media       %MediaDesc;    #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!-- style info, which may include CDATA sections -->
+<!ELEMENT style (#PCDATA)>
+<!ATTLIST style
+  %i18n;
+  id          ID             #IMPLIED
+  type        %ContentType;  #REQUIRED
+  media       %MediaDesc;    #IMPLIED
+  title       %Text;         #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- script statements, which may include CDATA sections -->
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+  id          ID             #IMPLIED
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #REQUIRED
+  language    CDATA          #IMPLIED
+  src         %URI;          #IMPLIED
+  defer       (defer)        #IMPLIED
+  xml:space   (preserve)     #FIXED 'preserve'
+  >
+
+<!-- alternate content container for non script-based rendering -->
+
+<!ELEMENT noscript %Flow;>
+<!ATTLIST noscript
+  %attrs;
+  >
+
+<!--======================= Frames =======================================-->
+
+<!-- inline subwindow -->
+
+<!ELEMENT iframe %Flow;>
+<!ATTLIST iframe
+  %coreattrs;
+  longdesc    %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  src         %URI;          #IMPLIED
+  frameborder (1|0)          "1"
+  marginwidth %Pixels;       #IMPLIED
+  marginheight %Pixels;      #IMPLIED
+  scrolling   (yes|no|auto)  "auto"
+  align       %ImgAlign;     #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  >
+
+<!-- alternate content container for non frame-based rendering -->
+
+<!ELEMENT noframes %Flow;>
+<!ATTLIST noframes
+  %attrs;
+  >
+
+<!--=================== Document Body ====================================-->
+
+<!ELEMENT body %Flow;>
+<!ATTLIST body
+  %attrs;
+  onload      %Script;       #IMPLIED
+  onunload    %Script;       #IMPLIED
+  background  %URI;          #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  text        %Color;        #IMPLIED
+  link        %Color;        #IMPLIED
+  vlink       %Color;        #IMPLIED
+  alink       %Color;        #IMPLIED
+  >
+
+<!ELEMENT div %Flow;>  <!-- generic language/style container -->
+<!ATTLIST div
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Paragraphs =======================================-->
+
+<!ELEMENT p %Inline;>
+<!ATTLIST p
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Headings =========================================-->
+
+<!--
+  There are six levels of headings from h1 (the most important)
+  to h6 (the least important).
+-->
+
+<!ELEMENT h1  %Inline;>
+<!ATTLIST h1
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h2 %Inline;>
+<!ATTLIST h2
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h3 %Inline;>
+<!ATTLIST h3
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h4 %Inline;>
+<!ATTLIST h4
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h5 %Inline;>
+<!ATTLIST h5
+  %attrs;
+  %TextAlign;
+  >
+
+<!ELEMENT h6 %Inline;>
+<!ATTLIST h6
+  %attrs;
+  %TextAlign;
+  >
+
+<!--=================== Lists ============================================-->
+
+<!-- Unordered list bullet styles -->
+
+<!ENTITY % ULStyle "(disc|square|circle)">
+
+<!-- Unordered list -->
+
+<!ELEMENT ul (li)+>
+<!ATTLIST ul
+  %attrs;
+  type        %ULStyle;     #IMPLIED
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- Ordered list numbering style
+
+    1   arabic numbers      1, 2, 3, ...
+    a   lower alpha         a, b, c, ...
+    A   upper alpha         A, B, C, ...
+    i   lower roman         i, ii, iii, ...
+    I   upper roman         I, II, III, ...
+
+    The style is applied to the sequence number which by default
+    is reset to 1 for the first list item in an ordered list.
+-->
+<!ENTITY % OLStyle "CDATA">
+
+<!-- Ordered (numbered) list -->
+
+<!ELEMENT ol (li)+>
+<!ATTLIST ol
+  %attrs;
+  type        %OLStyle;      #IMPLIED
+  compact     (compact)      #IMPLIED
+  start       %Number;       #IMPLIED
+  >
+
+<!-- single column list (DEPRECATED) --> 
+<!ELEMENT menu (li)+>
+<!ATTLIST menu
+  %attrs;
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- multiple column list (DEPRECATED) --> 
+<!ELEMENT dir (li)+>
+<!ATTLIST dir
+  %attrs;
+  compact     (compact)     #IMPLIED
+  >
+
+<!-- LIStyle is constrained to: "(%ULStyle;|%OLStyle;)" -->
+<!ENTITY % LIStyle "CDATA">
+
+<!-- list item -->
+
+<!ELEMENT li %Flow;>
+<!ATTLIST li
+  %attrs;
+  type        %LIStyle;      #IMPLIED
+  value       %Number;       #IMPLIED
+  >
+
+<!-- definition lists - dt for term, dd for its definition -->
+
+<!ELEMENT dl (dt|dd)+>
+<!ATTLIST dl
+  %attrs;
+  compact     (compact)      #IMPLIED
+  >
+
+<!ELEMENT dt %Inline;>
+<!ATTLIST dt
+  %attrs;
+  >
+
+<!ELEMENT dd %Flow;>
+<!ATTLIST dd
+  %attrs;
+  >
+
+<!--=================== Address ==========================================-->
+
+<!-- information on author -->
+
+<!ELEMENT address (#PCDATA | %inline; | %misc.inline; | p)*>
+<!ATTLIST address
+  %attrs;
+  >
+
+<!--=================== Horizontal Rule ==================================-->
+
+<!ELEMENT hr EMPTY>
+<!ATTLIST hr
+  %attrs;
+  align       (left|center|right) #IMPLIED
+  noshade     (noshade)      #IMPLIED
+  size        %Pixels;       #IMPLIED
+  width       %Length;       #IMPLIED
+  >
+
+<!--=================== Preformatted Text ================================-->
+
+<!-- content is %Inline; excluding 
+        "img|object|applet|big|small|sub|sup|font|basefont" -->
+
+<!ELEMENT pre %pre.content;>
+<!ATTLIST pre
+  %attrs;
+  width       %Number;      #IMPLIED
+  xml:space   (preserve)    #FIXED 'preserve'
+  >
+
+<!--=================== Block-like Quotes ================================-->
+
+<!ELEMENT blockquote %Flow;>
+<!ATTLIST blockquote
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!--=================== Text alignment ===================================-->
+
+<!-- center content -->
+<!ELEMENT center %Flow;>
+<!ATTLIST center
+  %attrs;
+  >
+
+<!--=================== Inserted/Deleted Text ============================-->
+
+<!--
+  ins/del are allowed in block and inline content, but its
+  inappropriate to include block content within an ins element
+  occurring in inline content.
+-->
+<!ELEMENT ins %Flow;>
+<!ATTLIST ins
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!ELEMENT del %Flow;>
+<!ATTLIST del
+  %attrs;
+  cite        %URI;          #IMPLIED
+  datetime    %Datetime;     #IMPLIED
+  >
+
+<!--================== The Anchor Element ================================-->
+
+<!-- content is %Inline; except that anchors shouldn't be nested -->
+
+<!ELEMENT a %a.content;>
+<!ATTLIST a
+  %attrs;
+  %focus;
+  charset     %Charset;      #IMPLIED
+  type        %ContentType;  #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  href        %URI;          #IMPLIED
+  hreflang    %LanguageCode; #IMPLIED
+  rel         %LinkTypes;    #IMPLIED
+  rev         %LinkTypes;    #IMPLIED
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--===================== Inline Elements ================================-->
+
+<!ELEMENT span %Inline;> <!-- generic language/style container -->
+<!ATTLIST span
+  %attrs;
+  >
+
+<!ELEMENT bdo %Inline;>  <!-- I18N BiDi over-ride -->
+<!ATTLIST bdo
+  %coreattrs;
+  %events;
+  lang        %LanguageCode; #IMPLIED
+  xml:lang    %LanguageCode; #IMPLIED
+  dir         (ltr|rtl)      #REQUIRED
+  >
+
+<!ELEMENT br EMPTY>   <!-- forced line break -->
+<!ATTLIST br
+  %coreattrs;
+  clear       (left|all|right|none) "none"
+  >
+
+<!ELEMENT em %Inline;>   <!-- emphasis -->
+<!ATTLIST em %attrs;>
+
+<!ELEMENT strong %Inline;>   <!-- strong emphasis -->
+<!ATTLIST strong %attrs;>
+
+<!ELEMENT dfn %Inline;>   <!-- definitional -->
+<!ATTLIST dfn %attrs;>
+
+<!ELEMENT code %Inline;>   <!-- program code -->
+<!ATTLIST code %attrs;>
+
+<!ELEMENT samp %Inline;>   <!-- sample -->
+<!ATTLIST samp %attrs;>
+
+<!ELEMENT kbd %Inline;>  <!-- something user would type -->
+<!ATTLIST kbd %attrs;>
+
+<!ELEMENT var %Inline;>   <!-- variable -->
+<!ATTLIST var %attrs;>
+
+<!ELEMENT cite %Inline;>   <!-- citation -->
+<!ATTLIST cite %attrs;>
+
+<!ELEMENT abbr %Inline;>   <!-- abbreviation -->
+<!ATTLIST abbr %attrs;>
+
+<!ELEMENT acronym %Inline;>   <!-- acronym -->
+<!ATTLIST acronym %attrs;>
+
+<!ELEMENT q %Inline;>   <!-- inlined quote -->
+<!ATTLIST q
+  %attrs;
+  cite        %URI;          #IMPLIED
+  >
+
+<!ELEMENT sub %Inline;> <!-- subscript -->
+<!ATTLIST sub %attrs;>
+
+<!ELEMENT sup %Inline;> <!-- superscript -->
+<!ATTLIST sup %attrs;>
+
+<!ELEMENT tt %Inline;>   <!-- fixed pitch font -->
+<!ATTLIST tt %attrs;>
+
+<!ELEMENT i %Inline;>   <!-- italic font -->
+<!ATTLIST i %attrs;>
+
+<!ELEMENT b %Inline;>   <!-- bold font -->
+<!ATTLIST b %attrs;>
+
+<!ELEMENT big %Inline;>   <!-- bigger font -->
+<!ATTLIST big %attrs;>
+
+<!ELEMENT small %Inline;>   <!-- smaller font -->
+<!ATTLIST small %attrs;>
+
+<!ELEMENT u %Inline;>   <!-- underline -->
+<!ATTLIST u %attrs;>
+
+<!ELEMENT s %Inline;>   <!-- strike-through -->
+<!ATTLIST s %attrs;>
+
+<!ELEMENT strike %Inline;>   <!-- strike-through -->
+<!ATTLIST strike %attrs;>
+
+<!ELEMENT basefont EMPTY>  <!-- base font size -->
+<!ATTLIST basefont
+  id          ID             #IMPLIED
+  size        CDATA          #REQUIRED
+  color       %Color;        #IMPLIED
+  face        CDATA          #IMPLIED
+  >
+
+<!ELEMENT font %Inline;> <!-- local change to font -->
+<!ATTLIST font
+  %coreattrs;
+  %i18n;
+  size        CDATA          #IMPLIED
+  color       %Color;        #IMPLIED
+  face        CDATA          #IMPLIED
+  >
+
+<!--==================== Object ======================================-->
+<!--
+  object is used to embed objects as part of HTML pages.
+  param elements should precede other content. Parameters
+  can also be expressed as attribute/value pairs on the
+  object element itself when brevity is desired.
+-->
+
+<!ELEMENT object (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST object
+  %attrs;
+  declare     (declare)      #IMPLIED
+  classid     %URI;          #IMPLIED
+  codebase    %URI;          #IMPLIED
+  data        %URI;          #IMPLIED
+  type        %ContentType;  #IMPLIED
+  codetype    %ContentType;  #IMPLIED
+  archive     %UriList;      #IMPLIED
+  standby     %Text;         #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  border      %Pixels;       #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!--
+  param is used to supply a named property value.
+  In XML it would seem natural to follow RDF and support an
+  abbreviated syntax where the param elements are replaced
+  by attribute value pairs on the object start tag.
+-->
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+  id          ID             #IMPLIED
+  name        CDATA          #REQUIRED
+  value       CDATA          #IMPLIED
+  valuetype   (data|ref|object) "data"
+  type        %ContentType;  #IMPLIED
+  >
+
+<!--=================== Java applet ==================================-->
+<!--
+  One of code or object attributes must be present.
+  Place param elements before other content.
+-->
+<!ELEMENT applet (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST applet
+  %coreattrs;
+  codebase    %URI;          #IMPLIED
+  archive     CDATA          #IMPLIED
+  code        CDATA          #IMPLIED
+  object      CDATA          #IMPLIED
+  alt         %Text;         #IMPLIED
+  name        NMTOKEN        #IMPLIED
+  width       %Length;       #REQUIRED
+  height      %Length;       #REQUIRED
+  align       %ImgAlign;     #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!--=================== Images ===========================================-->
+
+<!--
+   To avoid accessibility problems for people who aren't
+   able to see the image, you should provide a text
+   description using the alt and longdesc attributes.
+   In addition, avoid the use of server-side image maps.
+-->
+
+<!ELEMENT img EMPTY>
+<!ATTLIST img
+  %attrs;
+  src         %URI;          #REQUIRED
+  alt         %Text;         #REQUIRED
+  name        NMTOKEN        #IMPLIED
+  longdesc    %URI;          #IMPLIED
+  height      %Length;       #IMPLIED
+  width       %Length;       #IMPLIED
+  usemap      %URI;          #IMPLIED
+  ismap       (ismap)        #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  border      %Length;       #IMPLIED
+  hspace      %Pixels;       #IMPLIED
+  vspace      %Pixels;       #IMPLIED
+  >
+
+<!-- usemap points to a map element which may be in this document
+  or an external document, although the latter is not widely supported -->
+
+<!--================== Client-side image maps ============================-->
+
+<!-- These can be placed in the same document or grouped in a
+     separate document although this isn't yet widely supported -->
+
+<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
+<!ATTLIST map
+  %i18n;
+  %events;
+  id          ID             #REQUIRED
+  class       CDATA          #IMPLIED
+  style       %StyleSheet;   #IMPLIED
+  title       %Text;         #IMPLIED
+  name        CDATA          #IMPLIED
+  >
+
+<!ELEMENT area EMPTY>
+<!ATTLIST area
+  %attrs;
+  %focus;
+  shape       %Shape;        "rect"
+  coords      %Coords;       #IMPLIED
+  href        %URI;          #IMPLIED
+  nohref      (nohref)       #IMPLIED
+  alt         %Text;         #REQUIRED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--================ Forms ===============================================-->
+
+<!ELEMENT form %form.content;>   <!-- forms shouldn't be nested -->
+
+<!ATTLIST form
+  %attrs;
+  action      %URI;          #REQUIRED
+  method      (get|post)     "get"
+  name        NMTOKEN        #IMPLIED
+  enctype     %ContentType;  "application/x-www-form-urlencoded"
+  onsubmit    %Script;       #IMPLIED
+  onreset     %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  accept-charset %Charsets;  #IMPLIED
+  target      %FrameTarget;  #IMPLIED
+  >
+
+<!--
+  Each label must not contain more than ONE field
+  Label elements shouldn't be nested.
+-->
+<!ELEMENT label %Inline;>
+<!ATTLIST label
+  %attrs;
+  for         IDREF          #IMPLIED
+  accesskey   %Character;    #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  >
+
+<!ENTITY % InputType
+  "(text | password | checkbox |
+    radio | submit | reset |
+    file | hidden | image | button)"
+   >
+
+<!-- the name attribute is required for all but submit & reset -->
+
+<!ELEMENT input EMPTY>     <!-- form control -->
+<!ATTLIST input
+  %attrs;
+  %focus;
+  type        %InputType;    "text"
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  checked     (checked)      #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  size        CDATA          #IMPLIED
+  maxlength   %Number;       #IMPLIED
+  src         %URI;          #IMPLIED
+  alt         CDATA          #IMPLIED
+  usemap      %URI;          #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  accept      %ContentTypes; #IMPLIED
+  align       %ImgAlign;     #IMPLIED
+  >
+
+<!ELEMENT select (optgroup|option)+>  <!-- option selector -->
+<!ATTLIST select
+  %attrs;
+  name        CDATA          #IMPLIED
+  size        %Number;       #IMPLIED
+  multiple    (multiple)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  tabindex    %Number;       #IMPLIED
+  onfocus     %Script;       #IMPLIED
+  onblur      %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!ELEMENT optgroup (option)+>   <!-- option group -->
+<!ATTLIST optgroup
+  %attrs;
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #REQUIRED
+  >
+
+<!ELEMENT option (#PCDATA)>     <!-- selectable choice -->
+<!ATTLIST option
+  %attrs;
+  selected    (selected)     #IMPLIED
+  disabled    (disabled)     #IMPLIED
+  label       %Text;         #IMPLIED
+  value       CDATA          #IMPLIED
+  >
+
+<!ELEMENT textarea (#PCDATA)>     <!-- multi-line text field -->
+<!ATTLIST textarea
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  rows        %Number;       #REQUIRED
+  cols        %Number;       #REQUIRED
+  disabled    (disabled)     #IMPLIED
+  readonly    (readonly)     #IMPLIED
+  onselect    %Script;       #IMPLIED
+  onchange    %Script;       #IMPLIED
+  >
+
+<!--
+  The fieldset element is used to group form fields.
+  Only one legend element should occur in the content
+  and if present should only be preceded by whitespace.
+-->
+<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
+<!ATTLIST fieldset
+  %attrs;
+  >
+
+<!ENTITY % LAlign "(top|bottom|left|right)">
+
+<!ELEMENT legend %Inline;>     <!-- fieldset label -->
+<!ATTLIST legend
+  %attrs;
+  accesskey   %Character;    #IMPLIED
+  align       %LAlign;       #IMPLIED
+  >
+
+<!--
+ Content is %Flow; excluding a, form, form controls, iframe
+--> 
+<!ELEMENT button %button.content;>  <!-- push button -->
+<!ATTLIST button
+  %attrs;
+  %focus;
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED
+  type        (button|submit|reset) "submit"
+  disabled    (disabled)     #IMPLIED
+  >
+
+<!-- single-line text input control (DEPRECATED) -->
+<!ELEMENT isindex EMPTY>
+<!ATTLIST isindex
+  %coreattrs;
+  %i18n;
+  prompt      %Text;         #IMPLIED
+  >
+
+<!--======================= Tables =======================================-->
+
+<!-- Derived from IETF HTML table standard, see [RFC1942] -->
+
+<!--
+ The border attribute sets the thickness of the frame around the
+ table. The default units are screen pixels.
+
+ The frame attribute specifies which parts of the frame around
+ the table should be rendered. The values are not the same as
+ CALS to avoid a name clash with the valign attribute.
+-->
+<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
+
+<!--
+ The rules attribute defines which rules to draw between cells:
+
+ If rules is absent then assume:
+     "none" if border is absent or border="0" otherwise "all"
+-->
+
+<!ENTITY % TRules "(none | groups | rows | cols | all)">
+  
+<!-- horizontal placement of table relative to document -->
+<!ENTITY % TAlign "(left|center|right)">
+
+<!-- horizontal alignment attributes for cell contents
+
+  char        alignment char, e.g. char=':'
+  charoff     offset for alignment char
+-->
+<!ENTITY % cellhalign
+  "align      (left|center|right|justify|char) #IMPLIED
+   char       %Character;    #IMPLIED
+   charoff    %Length;       #IMPLIED"
+  >
+
+<!-- vertical alignment attributes for cell contents -->
+<!ENTITY % cellvalign
+  "valign     (top|middle|bottom|baseline) #IMPLIED"
+  >
+
+<!ELEMENT table
+     (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
+<!ELEMENT caption  %Inline;>
+<!ELEMENT thead    (tr)+>
+<!ELEMENT tfoot    (tr)+>
+<!ELEMENT tbody    (tr)+>
+<!ELEMENT colgroup (col)*>
+<!ELEMENT col      EMPTY>
+<!ELEMENT tr       (th|td)+>
+<!ELEMENT th       %Flow;>
+<!ELEMENT td       %Flow;>
+
+<!ATTLIST table
+  %attrs;
+  summary     %Text;         #IMPLIED
+  width       %Length;       #IMPLIED
+  border      %Pixels;       #IMPLIED
+  frame       %TFrame;       #IMPLIED
+  rules       %TRules;       #IMPLIED
+  cellspacing %Length;       #IMPLIED
+  cellpadding %Length;       #IMPLIED
+  align       %TAlign;       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  >
+
+<!ENTITY % CAlign "(top|bottom|left|right)">
+
+<!ATTLIST caption
+  %attrs;
+  align       %CAlign;       #IMPLIED
+  >
+
+<!--
+colgroup groups a set of col elements. It allows you to group
+several semantically related columns together.
+-->
+<!ATTLIST colgroup
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+ col elements define the alignment properties for cells in
+ one or more columns.
+
+ The width attribute specifies the width of the columns, e.g.
+
+     width=64        width in screen pixels
+     width=0.5*      relative width of 0.5
+
+ The span attribute causes the attributes of one
+ col element to apply to more than one column.
+-->
+<!ATTLIST col
+  %attrs;
+  span        %Number;       "1"
+  width       %MultiLength;  #IMPLIED
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!--
+    Use thead to duplicate headers when breaking table
+    across page boundaries, or for static headers when
+    tbody sections are rendered in scrolling panel.
+
+    Use tfoot to duplicate footers when breaking table
+    across page boundaries, or for static footers when
+    tbody sections are rendered in scrolling panel.
+
+    Use multiple tbody sections when rules are needed
+    between groups of table rows.
+-->
+<!ATTLIST thead
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tfoot
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tbody
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  >
+
+<!ATTLIST tr
+  %attrs;
+  %cellhalign;
+  %cellvalign;
+  bgcolor     %Color;        #IMPLIED
+  >
+
+<!-- Scope is simpler than headers attribute for common tables -->
+<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
+
+<!-- th is for headers, td for data and for cells acting as both -->
+
+<!ATTLIST th
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  nowrap      (nowrap)       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  width       %Length;       #IMPLIED
+  height      %Length;       #IMPLIED
+  >
+
+<!ATTLIST td
+  %attrs;
+  abbr        %Text;         #IMPLIED
+  axis        CDATA          #IMPLIED
+  headers     IDREFS         #IMPLIED
+  scope       %Scope;        #IMPLIED
+  rowspan     %Number;       "1"
+  colspan     %Number;       "1"
+  %cellhalign;
+  %cellvalign;
+  nowrap      (nowrap)       #IMPLIED
+  bgcolor     %Color;        #IMPLIED
+  width       %Length;       #IMPLIED
+  height      %Length;       #IMPLIED
+  >
+
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-attribs-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-attribs-1.mod
new file mode 100644
index 0000000..865634b
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-attribs-1.mod
@@ -0,0 +1,142 @@
+<!-- ...................................................................... -->
+<!-- XHTML Common Attributes Module  ...................................... -->
+<!-- file: xhtml-attribs-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-attribs-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Common Attributes 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-attribs-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Common Attributes
+
+     This module declares many of the common attributes for the XHTML DTD.
+     %NS.decl.attrib; is declared in the XHTML Qname module.
+
+	 Note that this file was extended in XHTML Modularization 1.1 to 
+	 include declarations of "global" versions of the attribute collections.
+	 The global versions of the attributes are for use on elements in other 
+	 namespaces.  The global version of "common" includes the xmlns declaration
+	 for the prefixed version of the xhtml namespace.  If you are only using a
+	 specific attribute or an individual attribute collection, you must also
+	 include the XHTML.xmlns.attrib.prefixed PE on your elements.
+-->
+
+<!ENTITY % id.attrib
+     "id           ID                       #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.id.attrib
+     "%XHTML.prefix;:id           ID        #IMPLIED"
+>
+]]>
+
+<!ENTITY % class.attrib
+     "class        NMTOKENS                 #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.class.attrib
+     "%XHTML.prefix;:class        NMTOKENS                 #IMPLIED"
+>
+]]>
+
+<!ENTITY % title.attrib
+     "title        %Text.datatype;          #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.title.attrib
+     "%XHTML.prefix;:title        %Text.datatype;          #IMPLIED"
+>
+]]>
+
+<!ENTITY % Core.extra.attrib "" >
+
+<!ENTITY % Core.attrib
+     "%XHTML.xmlns.attrib;
+      %id.attrib;
+      %class.attrib;
+      %title.attrib;
+      xml:space    ( preserve )             #FIXED 'preserve'
+      %Core.extra.attrib;"
+>
+
+<!ENTITY % XHTML.global.core.extra.attrib "" >
+
+<![%XHTML.global.attrs.prefixed;[
+
+<!ENTITY % XHTML.global.core.attrib
+     "%XHTML.global.id.attrib;
+      %XHTML.global.class.attrib;
+      %XHTML.global.title.attrib;
+      %XHTML.global.core.extra.attrib;"
+>
+]]>
+
+<!ENTITY % XHTML.global.core.attrib "" >
+
+
+<!ENTITY % lang.attrib
+     "xml:lang     %LanguageCode.datatype;  #IMPLIED"
+>
+
+<![%XHTML.bidi;[
+<!ENTITY % dir.attrib
+     "dir          ( ltr | rtl )            #IMPLIED"
+>
+
+<!ENTITY % I18n.attrib
+     "%dir.attrib;
+      %lang.attrib;"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY XHTML.global.i18n.attrib
+     "%XHTML.prefix;:dir          ( ltr | rtl )            #IMPLIED
+      %lang.attrib;"
+>
+]]>
+<!ENTITY XHTML.global.i18n.attrib "" >
+
+]]>
+<!ENTITY % I18n.attrib
+     "%lang.attrib;"
+>
+<!ENTITY % XHTML.global.i18n.attrib
+     "%lang.attrib;"
+>
+
+<!ENTITY % Common.extra.attrib "" >
+<!ENTITY % XHTML.global.common.extra.attrib "" >
+
+<!-- intrinsic event attributes declared previously
+-->
+<!ENTITY % Events.attrib "" >
+
+<!ENTITY % XHTML.global.events.attrib "" >
+
+<!ENTITY % Common.attrib
+     "%Core.attrib;
+      %I18n.attrib;
+      %Events.attrib;
+      %Common.extra.attrib;"
+>
+
+<!ENTITY % XHTML.global.common.attrib
+     "%XHTML.xmlns.attrib.prefixed;
+      %XHTML.global.core.attrib;
+	  %XHTML.global.i18n.attrib;
+	  %XHTML.global.events.attrib;
+	  %XHTML.global.common.extra.attrib;"
+>
+
+<!-- end of xhtml-attribs-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-base-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-base-1.mod
new file mode 100644
index 0000000..ba47b40
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-base-1.mod
@@ -0,0 +1,53 @@
+<!-- ...................................................................... -->
+<!-- XHTML Base Element Module  ........................................... -->
+<!-- file: xhtml-base-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-base-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Base Element 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-base-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Base element
+
+        base
+
+     This module declares the base element type and its attributes,
+     used to define a base URI against which relative URIs in the
+     document will be resolved.
+
+     Note that this module also redeclares the content model for
+     the head element to include the base element.
+-->
+
+<!-- base: Document Base URI ........................... -->
+
+<!ENTITY % base.element  "INCLUDE" >
+<![%base.element;[
+<!ENTITY % base.content  "EMPTY" >
+<!ENTITY % base.qname  "base" >
+<!ELEMENT %base.qname;  %base.content; >
+<!-- end of base.element -->]]>
+
+<!ENTITY % base.attlist  "INCLUDE" >
+<![%base.attlist;[
+<!ATTLIST %base.qname;
+      %XHTML.xmlns.attrib;
+      href         %URI.datatype;           #REQUIRED
+>
+<!-- end of base.attlist -->]]>
+
+<!ENTITY % head.content
+    "( %HeadOpts.mix;,
+     ( ( %title.qname;, %HeadOpts.mix;, ( %base.qname;, %HeadOpts.mix; )? )
+     | ( %base.qname;, %HeadOpts.mix;, ( %title.qname;, %HeadOpts.mix; ))))"
+>
+
+<!-- end of xhtml-base-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-basic-form-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-basic-form-1.mod
new file mode 100644
index 0000000..de1b7df
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-basic-form-1.mod
@@ -0,0 +1,188 @@
+
+<!-- saved from url=(0042)http://www.rddl.org/xhtml-basic-form-1.mod -->
+<HTML><BODY><PRE style="word-wrap: break-word; white-space: pre-wrap;">&lt;!-- ...................................................................... --&gt;
+&lt;!-- XHTML Simplified Forms Module  ....................................... --&gt;
+&lt;!-- file: xhtml-basic-form-1.mod
+
+     This is XHTML Basic, a proper subset of XHTML.
+     Copyright 1998-2000 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-basic-form-1.mod,v 1.10 2000/10/16 21:15:23 radams Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Basic Forms 1.0//EN"  
+       SYSTEM "http://www.w3.org/TR/xhtml-modulatization/DTD/xhtml-basic-form-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... --&gt;
+
+&lt;!-- Basic Forms
+
+     This forms module is based on the HTML 3.2 forms model, with
+     the WAI-requested addition of the label element. While this 
+     module essentially mimics the content model and attributes of 
+     HTML 3.2 forms, the element types declared herein also include
+     all HTML 4 common attributes.
+
+        form, label, input, select, option, textarea
+--&gt;
+
+&lt;!-- declare qualified element type names:
+--&gt;
+&lt;!ENTITY % form.qname  "form" &gt;
+&lt;!ENTITY % label.qname  "label" &gt;
+&lt;!ENTITY % input.qname  "input" &gt;
+&lt;!ENTITY % select.qname  "select" &gt;
+&lt;!ENTITY % option.qname  "option" &gt;
+&lt;!ENTITY % textarea.qname  "textarea" &gt;
+
+&lt;!-- %BlkNoForm.mix; includes all non-form block elements,
+     plus %Misc.class;
+--&gt;
+&lt;!ENTITY % BlkNoForm.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      | %table.qname; 
+      %Block.extra;
+      %Misc.class;"
+&gt;
+
+&lt;!-- form: Form Element ................................ --&gt;
+
+&lt;!ENTITY % form.element  "INCLUDE" &gt;
+&lt;![%form.element;[
+&lt;!ENTITY % form.content
+     "( %BlkNoForm.mix; )+"
+&gt;
+&lt;!ELEMENT %form.qname;  %form.content; &gt;
+&lt;!-- end of form.element --&gt;]]&gt;
+
+&lt;!ENTITY % form.attlist  "INCLUDE" &gt;
+&lt;![%form.attlist;[
+&lt;!ATTLIST %form.qname;
+      %Common.attrib;
+      action       %URI.datatype;           #REQUIRED
+      method       ( get | post )           'get'
+      enctype      %ContentType.datatype;   'application/x-www-form-urlencoded'
+&gt;
+&lt;!-- end of form.attlist --&gt;]]&gt;
+
+&lt;!-- label: Form Field Label Text ...................... --&gt;
+
+&lt;!ENTITY % label.element  "INCLUDE" &gt;
+&lt;![%label.element;[
+&lt;!-- Each label must not contain more than ONE field
+--&gt;
+&lt;!ENTITY % label.content
+     "( #PCDATA 
+      | %input.qname; | %select.qname; | %textarea.qname;
+      | %InlStruct.class;
+      %InlPhras.class;
+      %I18n.class;
+      %InlPres.class;
+      %InlSpecial.class;
+      %Misc.class; )*"
+&gt;
+&lt;!ELEMENT %label.qname;  %label.content; &gt;
+&lt;!-- end of label.element --&gt;]]&gt;
+
+&lt;!ENTITY % label.attlist  "INCLUDE" &gt;
+&lt;![%label.attlist;[
+&lt;!ATTLIST %label.qname;
+      %Common.attrib;
+      for          IDREF                    #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+&gt;
+&lt;!-- end of label.attlist --&gt;]]&gt;
+
+&lt;!-- input: Form Control ............................... --&gt;
+
+&lt;!ENTITY % input.element  "INCLUDE" &gt;
+&lt;![%input.element;[
+&lt;!ENTITY % input.content  "EMPTY" &gt;
+&lt;!ELEMENT %input.qname;  %input.content; &gt;
+&lt;!-- end of input.element --&gt;]]&gt;
+
+&lt;!-- Basic Forms removes 'image' and 'file' input types.
+--&gt;
+&lt;!ENTITY % input.attlist  "INCLUDE" &gt;
+&lt;![%input.attlist;[
+&lt;!ENTITY % InputType.class
+     "( text | password | checkbox | radio 
+      | submit | reset | hidden )"
+&gt;
+&lt;!-- attribute name required for all but submit &amp; reset
+--&gt;
+&lt;!ATTLIST %input.qname;
+      %Common.attrib;
+      type         %InputType.class;        'text'
+      name         CDATA                    #IMPLIED
+      value        CDATA                    #IMPLIED
+      checked      ( checked )              #IMPLIED
+      size         CDATA                    #IMPLIED
+      maxlength    %Number.datatype;        #IMPLIED
+      src          %URI.datatype;           #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+&gt;
+&lt;!-- end of input.attlist --&gt;]]&gt;
+
+&lt;!-- select: Option Selector ........................... --&gt;
+
+&lt;!ENTITY % select.element  "INCLUDE" &gt;
+&lt;![%select.element;[
+&lt;!ENTITY % select.content  "( %option.qname; )+" &gt;
+&lt;!ELEMENT %select.qname;  %select.content; &gt;
+&lt;!-- end of select.element --&gt;]]&gt;
+
+&lt;!ENTITY % select.attlist  "INCLUDE" &gt;
+&lt;![%select.attlist;[
+&lt;!ATTLIST %select.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      size         %Number.datatype;        #IMPLIED
+      multiple     ( multiple )             #IMPLIED
+&gt;
+&lt;!-- end of select.attlist --&gt;]]&gt;
+
+&lt;!-- option: Selectable Choice ......................... --&gt;
+
+&lt;!ENTITY % option.element  "INCLUDE" &gt;
+&lt;![%option.element;[
+&lt;!ENTITY % option.content  "( #PCDATA )" &gt;
+&lt;!ELEMENT %option.qname;  %option.content; &gt;
+&lt;!-- end of option.element --&gt;]]&gt;
+
+&lt;!ENTITY % option.attlist  "INCLUDE" &gt;
+&lt;![%option.attlist;[
+&lt;!ATTLIST %option.qname;
+      %Common.attrib;
+      selected     ( selected )             #IMPLIED
+      value        CDATA                    #IMPLIED
+&gt;
+&lt;!-- end of option.attlist --&gt;]]&gt;
+
+&lt;!-- textarea: Multi-Line Text Field ................... --&gt;
+
+&lt;!ENTITY % textarea.element  "INCLUDE" &gt;
+&lt;![%textarea.element;[
+&lt;!ENTITY % textarea.content  "( #PCDATA )" &gt;
+&lt;!ELEMENT %textarea.qname;  %textarea.content; &gt;
+&lt;!-- end of textarea.element --&gt;]]&gt;
+
+&lt;!ENTITY % textarea.attlist  "INCLUDE" &gt;
+&lt;![%textarea.attlist;[
+&lt;!ATTLIST %textarea.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      rows         %Number.datatype;        #REQUIRED
+      cols         %Number.datatype;        #REQUIRED
+      accesskey    %Character.datatype;     #IMPLIED
+&gt;
+&lt;!-- end of textarea.attlist --&gt;]]&gt;
+
+&lt;!-- end of xhtml-basic-form-1.mod --&gt;
+</PRE></BODY></HTML>
\ No newline at end of file
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-basic-table-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-basic-table-1.mod
new file mode 100644
index 0000000..170164e
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-basic-table-1.mod
@@ -0,0 +1,167 @@
+<!-- ....................................................................... -->
+<!-- XHTML Basic Table Module  ............................................. -->
+<!-- file: xhtml-basic-table-1.mod
+
+     This is XHTML Basic, a proper subset of XHTML.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-basic-table-1.mod,v 1.1 2010/07/29 13:42:46 bertails Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Basic Tables 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-basic-table-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Basic Tables
+
+        table, caption, tr, th, td
+
+     This table module declares elements and attributes defining
+     a table model based fundamentally on features found in the
+     widely-deployed HTML 3.2 table model.  While this module
+     mimics the content model and table attributes of HTML 3.2
+     tables, the element types declared herein also includes all
+     HTML 4 common and most of the HTML 4 table attributes.
+-->
+
+<!-- declare qualified element type names:
+-->
+<!ENTITY % table.qname  "table" >
+<!ENTITY % caption.qname  "caption" >
+<!ENTITY % tr.qname  "tr" >
+<!ENTITY % th.qname  "th" >
+<!ENTITY % td.qname  "td" >
+
+<!-- horizontal alignment attributes for cell contents
+-->
+<!ENTITY % CellHAlign.attrib
+     "align        ( left
+                   | center
+                   | right )                #IMPLIED"
+>
+
+<!-- vertical alignment attributes for cell contents
+-->
+<!ENTITY % CellVAlign.attrib
+     "valign       ( top
+                   | middle
+                   | bottom )               #IMPLIED"
+>
+
+<!-- scope is simpler than axes attribute for common tables
+-->
+<!ENTITY % scope.attrib
+     "scope        ( row | col  )           #IMPLIED"
+>
+
+<!-- table: Table Element .............................. -->
+
+<!ENTITY % table.element  "INCLUDE" >
+<![%table.element;[
+<!ENTITY % table.content
+     "( %caption.qname;?, %tr.qname;+ )"
+>
+<!ELEMENT %table.qname;  %table.content; >
+<!-- end of table.element -->]]>
+
+<!ENTITY % table.attlist  "INCLUDE" >
+<![%table.attlist;[
+<!ATTLIST %table.qname;
+      %Common.attrib;
+      summary      %Text.datatype;          #IMPLIED
+      width        %Length.datatype;        #IMPLIED
+>
+<!-- end of table.attlist -->]]>
+
+<!-- caption: Table Caption ............................ -->
+
+<!ENTITY % caption.element  "INCLUDE" >
+<![%caption.element;[
+<!ENTITY % caption.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ELEMENT %caption.qname;  %caption.content; >
+<!-- end of caption.element -->]]>
+
+<!ENTITY % caption.attlist  "INCLUDE" >
+<![%caption.attlist;[
+<!ATTLIST %caption.qname;
+      %Common.attrib;
+>
+<!-- end of caption.attlist -->]]>
+
+<!-- tr: Table Row ..................................... -->
+
+<!ENTITY % tr.element  "INCLUDE" >
+<![%tr.element;[
+<!ENTITY % tr.content  "( %th.qname; | %td.qname; )+" >
+<!ELEMENT %tr.qname;  %tr.content; >
+<!-- end of tr.element -->]]>
+
+<!ENTITY % tr.attlist  "INCLUDE" >
+<![%tr.attlist;[
+<!ATTLIST %tr.qname;
+      %Common.attrib;
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of tr.attlist -->]]>
+
+<!-- th: Table Header Cell ............................. -->
+
+<!-- th is for header cells, td for data,
+     but for cells acting as both use td
+-->
+
+<!ENTITY % th.element  "INCLUDE" >
+<![%th.element;[
+<!ENTITY % th.content
+     "( #PCDATA | %FlowNoTable.mix; )*"
+>
+<!ELEMENT %th.qname;  %th.content; >
+<!-- end of th.element -->]]>
+
+<!ENTITY % th.attlist  "INCLUDE" >
+<![%th.attlist;[
+<!ATTLIST %th.qname;
+      %Common.attrib;
+      abbr         %Text.datatype;          #IMPLIED
+      axis         CDATA                    #IMPLIED
+      headers      IDREFS                   #IMPLIED
+      %scope.attrib;
+      rowspan      %Number.datatype;        '1'
+      colspan      %Number.datatype;        '1'
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of th.attlist -->]]>
+
+<!-- td: Table Data Cell ............................... -->
+
+<!ENTITY % td.element  "INCLUDE" >
+<![%td.element;[
+<!ENTITY % td.content
+     "( #PCDATA | %FlowNoTable.mix; )*"
+>
+<!ELEMENT %td.qname;  %td.content; >
+<!-- end of td.element -->]]>
+
+<!ENTITY % td.attlist  "INCLUDE" >
+<![%td.attlist;[
+<!ATTLIST %td.qname;
+      %Common.attrib;
+      abbr         %Text.datatype;          #IMPLIED
+      axis         CDATA                    #IMPLIED
+      headers      IDREFS                   #IMPLIED
+      %scope.attrib;
+      rowspan      %Number.datatype;        '1'
+      colspan      %Number.datatype;        '1'
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of td.attlist -->]]>
+
+<!-- end of xhtml-basic-table-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-blkphras-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-blkphras-1.mod
new file mode 100644
index 0000000..9172463
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-blkphras-1.mod
@@ -0,0 +1,164 @@
+<!-- ...................................................................... -->
+<!-- XHTML Block Phrasal Module  .......................................... -->
+<!-- file: xhtml-blkphras-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-blkphras-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Block Phrasal 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-blkphras-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Block Phrasal
+
+        address, blockquote, pre, h1, h2, h3, h4, h5, h6
+
+     This module declares the elements and their attributes used to
+     support block-level phrasal markup.
+-->
+
+<!ENTITY % address.element  "INCLUDE" >
+<![%address.element;[
+<!ENTITY % address.content
+     "( #PCDATA | %Inline.mix; )*" >
+<!ENTITY % address.qname  "address" >
+<!ELEMENT %address.qname;  %address.content; >
+<!-- end of address.element -->]]>
+
+<!ENTITY % address.attlist  "INCLUDE" >
+<![%address.attlist;[
+<!ATTLIST %address.qname;
+      %Common.attrib;
+>
+<!-- end of address.attlist -->]]>
+
+<!ENTITY % blockquote.element  "INCLUDE" >
+<![%blockquote.element;[
+<!ENTITY % blockquote.content
+     "( %Block.mix; )*"
+>
+<!ENTITY % blockquote.qname  "blockquote" >
+<!ELEMENT %blockquote.qname;  %blockquote.content; >
+<!-- end of blockquote.element -->]]>
+
+<!ENTITY % blockquote.attlist  "INCLUDE" >
+<![%blockquote.attlist;[
+<!ATTLIST %blockquote.qname;
+      %Common.attrib;
+      cite         %URI.datatype;           #IMPLIED
+>
+<!-- end of blockquote.attlist -->]]>
+
+<!ENTITY % pre.element  "INCLUDE" >
+<![%pre.element;[
+<!ENTITY % pre.content
+     "( #PCDATA
+      | %InlStruct.class;
+      %InlPhras.class;
+      | %tt.qname; | %i.qname; | %b.qname;
+      %I18n.class;
+      %Anchor.class;
+      | %map.qname;
+      %Misc.class;
+      %Inline.extra; )*"
+>
+<!ENTITY % pre.qname  "pre" >
+<!ELEMENT %pre.qname;  %pre.content; >
+<!-- end of pre.element -->]]>
+
+<!ENTITY % pre.attlist  "INCLUDE" >
+<![%pre.attlist;[
+<!ATTLIST %pre.qname;
+      %Common.attrib;
+>
+<!-- end of pre.attlist -->]]>
+
+<!-- ...................  Heading Elements  ................... -->
+
+<!ENTITY % Heading.content  "( #PCDATA | %Inline.mix; )*" >
+
+<!ENTITY % h1.element  "INCLUDE" >
+<![%h1.element;[
+<!ENTITY % h1.qname  "h1" >
+<!ELEMENT %h1.qname;  %Heading.content; >
+<!-- end of h1.element -->]]>
+
+<!ENTITY % h1.attlist  "INCLUDE" >
+<![%h1.attlist;[
+<!ATTLIST %h1.qname;
+      %Common.attrib;
+>
+<!-- end of h1.attlist -->]]>
+
+<!ENTITY % h2.element  "INCLUDE" >
+<![%h2.element;[
+<!ENTITY % h2.qname  "h2" >
+<!ELEMENT %h2.qname;  %Heading.content; >
+<!-- end of h2.element -->]]>
+
+<!ENTITY % h2.attlist  "INCLUDE" >
+<![%h2.attlist;[
+<!ATTLIST %h2.qname;
+      %Common.attrib;
+>
+<!-- end of h2.attlist -->]]>
+
+<!ENTITY % h3.element  "INCLUDE" >
+<![%h3.element;[
+<!ENTITY % h3.qname  "h3" >
+<!ELEMENT %h3.qname;  %Heading.content; >
+<!-- end of h3.element -->]]>
+
+<!ENTITY % h3.attlist  "INCLUDE" >
+<![%h3.attlist;[
+<!ATTLIST %h3.qname;
+      %Common.attrib;
+>
+<!-- end of h3.attlist -->]]>
+
+<!ENTITY % h4.element  "INCLUDE" >
+<![%h4.element;[
+<!ENTITY % h4.qname  "h4" >
+<!ELEMENT %h4.qname;  %Heading.content; >
+<!-- end of h4.element -->]]>
+
+<!ENTITY % h4.attlist  "INCLUDE" >
+<![%h4.attlist;[
+<!ATTLIST %h4.qname;
+      %Common.attrib;
+>
+<!-- end of h4.attlist -->]]>
+
+<!ENTITY % h5.element  "INCLUDE" >
+<![%h5.element;[
+<!ENTITY % h5.qname  "h5" >
+<!ELEMENT %h5.qname;  %Heading.content; >
+<!-- end of h5.element -->]]>
+
+<!ENTITY % h5.attlist  "INCLUDE" >
+<![%h5.attlist;[
+<!ATTLIST %h5.qname;
+      %Common.attrib;
+>
+<!-- end of h5.attlist -->]]>
+
+<!ENTITY % h6.element  "INCLUDE" >
+<![%h6.element;[
+<!ENTITY % h6.qname  "h6" >
+<!ELEMENT %h6.qname;  %Heading.content; >
+<!-- end of h6.element -->]]>
+
+<!ENTITY % h6.attlist  "INCLUDE" >
+<![%h6.attlist;[
+<!ATTLIST %h6.qname;
+      %Common.attrib;
+>
+<!-- end of h6.attlist -->]]>
+
+<!-- end of xhtml-blkphras-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-blkpres-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-blkpres-1.mod
new file mode 100644
index 0000000..c342f8b
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-blkpres-1.mod
@@ -0,0 +1,40 @@
+<!-- ...................................................................... -->
+<!-- XHTML Block Presentation Module  ..................................... -->
+<!-- file: xhtml-blkpres-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-blkpres-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Block Presentation 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-blkpres-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Block Presentational Elements
+
+        hr
+
+     This module declares the elements and their attributes used to
+     support block-level presentational markup.
+-->
+
+<!ENTITY % hr.element  "INCLUDE" >
+<![%hr.element;[
+<!ENTITY % hr.content  "EMPTY" >
+<!ENTITY % hr.qname  "hr" >
+<!ELEMENT %hr.qname;  %hr.content; >
+<!-- end of hr.element -->]]>
+
+<!ENTITY % hr.attlist  "INCLUDE" >
+<![%hr.attlist;[
+<!ATTLIST %hr.qname;
+      %Common.attrib;
+>
+<!-- end of hr.attlist -->]]>
+
+<!-- end of xhtml-blkpres-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-blkstruct-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-blkstruct-1.mod
new file mode 100644
index 0000000..ce6a95c
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-blkstruct-1.mod
@@ -0,0 +1,57 @@
+<!-- ...................................................................... -->
+<!-- XHTML Block Structural Module  ....................................... -->
+<!-- file: xhtml-blkstruct-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-blkstruct-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Block Structural 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-blkstruct-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Block Structural
+
+        div, p
+
+     This module declares the elements and their attributes used to
+     support block-level structural markup.
+-->
+
+<!ENTITY % div.element  "INCLUDE" >
+<![%div.element;[
+<!ENTITY % div.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ENTITY % div.qname  "div" >
+<!ELEMENT %div.qname;  %div.content; >
+<!-- end of div.element -->]]>
+
+<!ENTITY % div.attlist  "INCLUDE" >
+<![%div.attlist;[
+<!ATTLIST %div.qname;
+      %Common.attrib;
+>
+<!-- end of div.attlist -->]]>
+
+<!ENTITY % p.element  "INCLUDE" >
+<![%p.element;[
+<!ENTITY % p.content
+     "( #PCDATA | %Inline.mix; )*" >
+<!ENTITY % p.qname  "p" >
+<!ELEMENT %p.qname;  %p.content; >
+<!-- end of p.element -->]]>
+
+<!ENTITY % p.attlist  "INCLUDE" >
+<![%p.attlist;[
+<!ATTLIST %p.qname;
+      %Common.attrib;
+>
+<!-- end of p.attlist -->]]>
+
+<!-- end of xhtml-blkstruct-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-charent-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-charent-1.mod
new file mode 100644
index 0000000..824c3ed
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-charent-1.mod
@@ -0,0 +1,39 @@
+<!-- ...................................................................... -->
+<!-- XHTML Character Entities Module  ......................................... -->
+<!-- file: xhtml-charent-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-charent-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Character Entities 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-charent-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Character Entities for XHTML
+
+     This module declares the set of character entities for XHTML,
+     including the Latin 1, Symbol and Special character collections.
+-->
+
+<!ENTITY % xhtml-lat1
+    PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+           "xhtml-lat1.ent" >
+%xhtml-lat1;
+
+<!ENTITY % xhtml-symbol
+    PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN"
+           "xhtml-symbol.ent" >
+%xhtml-symbol;
+
+<!ENTITY % xhtml-special
+    PUBLIC "-//W3C//ENTITIES Special for XHTML//EN"
+           "xhtml-special.ent" >
+%xhtml-special;
+
+<!-- end of xhtml-charent-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-csismap-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-csismap-1.mod
new file mode 100644
index 0000000..09b3720
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-csismap-1.mod
@@ -0,0 +1,114 @@
+<!-- ...................................................................... -->
+<!-- XHTML Client-side Image Map Module  .................................. -->
+<!-- file: xhtml-csismap-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-csismap-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Client-side Image Maps 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-csismap-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Client-side Image Maps
+
+        area, map
+
+     This module declares elements and attributes to support client-side
+     image maps. This requires that the Image Module (or a module
+     declaring the img element type) be included in the DTD.
+
+     These can be placed in the same document or grouped in a
+     separate document, although the latter isn't widely supported
+-->
+
+<!ENTITY % area.element  "INCLUDE" >
+<![%area.element;[
+<!ENTITY % area.content  "EMPTY" >
+<!ENTITY % area.qname  "area" >
+<!ELEMENT %area.qname;  %area.content; >
+<!-- end of area.element -->]]>
+
+<!ENTITY % Shape.datatype "( rect | circle | poly | default )">
+<!ENTITY % Coords.datatype "CDATA" >
+
+<!ENTITY % area.attlist  "INCLUDE" >
+<![%area.attlist;[
+<!ATTLIST %area.qname;
+      %Common.attrib;
+      href         %URI.datatype;           #IMPLIED
+      shape        %Shape.datatype;         'rect'
+      coords       %Coords.datatype;        #IMPLIED
+      nohref       ( nohref )               #IMPLIED
+      alt          %Text.datatype;          #REQUIRED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of area.attlist -->]]>
+
+<!-- modify anchor attribute definition list
+     to allow for client-side image maps
+-->
+<!ATTLIST %a.qname;
+      shape        %Shape.datatype;         'rect'
+      coords       %Coords.datatype;        #IMPLIED
+>
+
+<!-- modify img attribute definition list
+     to allow for client-side image maps
+-->
+<!ATTLIST %img.qname;
+      usemap       IDREF                    #IMPLIED
+>
+
+<!-- modify form input attribute definition list
+     to allow for client-side image maps
+-->
+<!ATTLIST %input.qname;
+      usemap       IDREF                    #IMPLIED
+>
+
+<!-- modify object attribute definition list
+     to allow for client-side image maps
+-->
+<!ATTLIST %object.qname;
+      usemap       IDREF                    #IMPLIED
+>
+
+<!-- 'usemap' points to the 'id' attribute of a <map> element,
+     which must be in the same document; support for external
+     document maps was not widely supported in HTML and is
+     eliminated in XHTML.
+
+     It is considered an error for the element pointed to by
+     a usemap IDREF to occur in anything but a <map> element.
+-->
+
+<!ENTITY % map.element  "INCLUDE" >
+<![%map.element;[
+<!ENTITY % map.content
+     "(( %Block.mix; ) | %area.qname; )+"
+>
+<!ENTITY % map.qname  "map" >
+<!ELEMENT %map.qname;  %map.content; >
+<!-- end of map.element -->]]>
+
+<!ENTITY % map.attlist  "INCLUDE" >
+<![%map.attlist;[
+<!ATTLIST %map.qname;
+      %XHTML.xmlns.attrib;
+      id           ID                       #REQUIRED
+      %class.attrib;
+      %title.attrib;
+      %Core.extra.attrib;
+      %I18n.attrib;
+      %Events.attrib;
+>
+<!-- end of map.attlist -->]]>
+
+<!-- end of xhtml-csismap-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-datatypes-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-datatypes-1.mod
new file mode 100644
index 0000000..7e07ff1
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-datatypes-1.mod
@@ -0,0 +1,100 @@
+<!-- ...................................................................... -->
+<!-- XHTML Datatypes Module  .............................................. -->
+<!-- file: xhtml-datatypes-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-datatypes-1.mod,v 4.1 2001/04/06 19:23:32 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Datatypes 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-datatypes-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Datatypes
+
+     defines containers for the following datatypes, many of
+     these imported from other specifications and standards.
+-->
+
+<!-- Length defined for cellpadding/cellspacing -->
+
+<!-- nn for pixels or nn% for percentage length -->
+<!ENTITY % Length.datatype "CDATA" >
+
+<!-- space-separated list of link types -->
+<!ENTITY % LinkTypes.datatype "NMTOKENS" >
+
+<!-- single or comma-separated list of media descriptors -->
+<!ENTITY % MediaDesc.datatype "CDATA" >
+
+<!-- pixel, percentage, or relative -->
+<!ENTITY % MultiLength.datatype "CDATA" >
+
+<!-- one or more digits (NUMBER) -->
+<!ENTITY % Number.datatype "CDATA" >
+
+<!-- integer representing length in pixels -->
+<!ENTITY % Pixels.datatype "CDATA" >
+
+<!-- script expression -->
+<!ENTITY % Script.datatype "CDATA" >
+
+<!-- textual content -->
+<!ENTITY % Text.datatype "CDATA" >
+
+<!-- Placeholder Compact URI-related types -->
+<!ENTITY % CURIE.datatype "CDATA" >
+<!ENTITY % CURIEs.datatype "CDATA" >
+<!ENTITY % SafeCURIE.datatype "CDATA" >
+<!ENTITY % SafeCURIEs.datatype "CDATA" >
+<!ENTITY % URIorSafeCURIE.datatype "CDATA" >
+<!ENTITY % URIorSafeCURIEs.datatype "CDATA" >
+
+<!-- Imported Datatypes ................................ -->
+
+<!-- a single character from [ISO10646] -->
+<!ENTITY % Character.datatype "CDATA" >
+
+<!-- a character encoding, as per [RFC2045] -->
+<!ENTITY % Charset.datatype "CDATA" >
+
+<!-- a space separated list of character encodings, as per [RFC2045] -->
+<!ENTITY % Charsets.datatype "CDATA" >
+
+<!-- Color specification using color name or sRGB (#RRGGBB) values -->
+<!ENTITY % Color.datatype "CDATA" >
+
+<!-- media type, as per [RFC2045] -->
+<!ENTITY % ContentType.datatype "CDATA" >
+
+<!-- comma-separated list of media types, as per [RFC2045] -->
+<!ENTITY % ContentTypes.datatype "CDATA" >
+
+<!-- date and time information. ISO date format -->
+<!ENTITY % Datetime.datatype "CDATA" >
+
+<!-- formal public identifier, as per [ISO8879] -->
+<!ENTITY % FPI.datatype "CDATA" >
+
+<!-- a language code, as per [RFC3066] or its successor -->
+<!ENTITY % LanguageCode.datatype "CDATA" >
+
+<!-- a comma separated list of language code ranges -->
+<!ENTITY % LanguageCodes.datatype "CDATA" >
+
+<!-- a qualified name , as per [XMLNS] or its successor -->
+<!ENTITY % QName.datatype "CDATA" >
+<!ENTITY % QNames.datatype "CDATA" >
+
+<!-- a Uniform Resource Identifier, see [URI] -->
+<!ENTITY % URI.datatype "CDATA" >
+
+<!-- a space-separated list of Uniform Resource Identifiers, see [URI] -->
+<!ENTITY % URIs.datatype "CDATA" >
+
+<!-- end of xhtml-datatypes-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-edit-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-edit-1.mod
new file mode 100644
index 0000000..b2a328e
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-edit-1.mod
@@ -0,0 +1,66 @@
+<!-- ...................................................................... -->
+<!-- XHTML Editing Elements Module  ....................................... -->
+<!-- file: xhtml-edit-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-edit-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Editing Markup 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-edit-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Editing Elements
+
+        ins, del
+
+     This module declares element types and attributes used to indicate
+     inserted and deleted content while editing a document.
+-->
+
+<!-- ins: Inserted Text  ............................... -->
+
+<!ENTITY % ins.element  "INCLUDE" >
+<![%ins.element;[
+<!ENTITY % ins.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ENTITY % ins.qname  "ins" >
+<!ELEMENT %ins.qname;  %ins.content; >
+<!-- end of ins.element -->]]>
+
+<!ENTITY % ins.attlist  "INCLUDE" >
+<![%ins.attlist;[
+<!ATTLIST %ins.qname;
+      %Common.attrib;
+      cite         %URI.datatype;           #IMPLIED
+      datetime     %Datetime.datatype;      #IMPLIED
+>
+<!-- end of ins.attlist -->]]>
+
+<!-- del: Deleted Text  ................................ -->
+
+<!ENTITY % del.element  "INCLUDE" >
+<![%del.element;[
+<!ENTITY % del.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ENTITY % del.qname  "del" >
+<!ELEMENT %del.qname;  %del.content; >
+<!-- end of del.element -->]]>
+
+<!ENTITY % del.attlist  "INCLUDE" >
+<![%del.attlist;[
+<!ATTLIST %del.qname;
+      %Common.attrib;
+      cite         %URI.datatype;           #IMPLIED
+      datetime     %Datetime.datatype;      #IMPLIED
+>
+<!-- end of del.attlist -->]]>
+
+<!-- end of xhtml-edit-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-events-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-events-1.mod
new file mode 100644
index 0000000..03fd46c
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-events-1.mod
@@ -0,0 +1,135 @@
+<!-- ...................................................................... -->
+<!-- XHTML Intrinsic Events Module  ....................................... -->
+<!-- file: xhtml-events-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-events-1.mod,v 4.1 2001/04/10 09:42:30 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Intrinsic Events 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-events-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Intrinsic Event Attributes
+
+     These are the event attributes defined in HTML 4,
+     Section 18.2.3 "Intrinsic Events". This module must be
+     instantiated prior to the Attributes Module but after
+     the Datatype Module in the Modular Framework module.
+
+    "Note: Authors of HTML documents are advised that changes
+     are likely to occur in the realm of intrinsic events
+     (e.g., how scripts are bound to events). Research in
+     this realm is carried on by members of the W3C Document
+     Object Model Working Group (see the W3C Web site at
+     http://www.w3.org/ for more information)."
+-->
+<!-- NOTE: Because the ATTLIST declarations in this module occur
+     before their respective ELEMENT declarations in other
+     modules, there may be a dependency on this module that
+     should be considered if any of the parameter entities used
+     for element type names (eg., %a.qname;) are redeclared.
+-->
+
+<!ENTITY % Events.attrib
+     "onclick      %Script.datatype;        #IMPLIED
+      ondblclick   %Script.datatype;        #IMPLIED
+      onmousedown  %Script.datatype;        #IMPLIED
+      onmouseup    %Script.datatype;        #IMPLIED
+      onmouseover  %Script.datatype;        #IMPLIED
+      onmousemove  %Script.datatype;        #IMPLIED
+      onmouseout   %Script.datatype;        #IMPLIED
+      onkeypress   %Script.datatype;        #IMPLIED
+      onkeydown    %Script.datatype;        #IMPLIED
+      onkeyup      %Script.datatype;        #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.events.attrib
+     "%XHTML.prefix;:onclick      %Script.datatype;        #IMPLIED
+      %XHTML.prefix;:ondblclick   %Script.datatype;        #IMPLIED
+      %XHTML.prefix;:onmousedown  %Script.datatype;        #IMPLIED
+      %XHTML.prefix;:onmouseup    %Script.datatype;        #IMPLIED
+      %XHTML.prefix;:onmouseover  %Script.datatype;        #IMPLIED
+      %XHTML.prefix;:onmousemove  %Script.datatype;        #IMPLIED
+      %XHTML.prefix;:onmouseout   %Script.datatype;        #IMPLIED
+      %XHTML.prefix;:onkeypress   %Script.datatype;        #IMPLIED
+      %XHTML.prefix;:onkeydown    %Script.datatype;        #IMPLIED
+      %XHTML.prefix;:onkeyup      %Script.datatype;        #IMPLIED"
+>
+]]>
+
+<!-- additional attributes on anchor element
+-->
+<!ATTLIST %a.qname;
+     onfocus      %Script.datatype;         #IMPLIED
+     onblur       %Script.datatype;         #IMPLIED
+>
+
+<!-- additional attributes on form element
+-->
+<!ATTLIST %form.qname;
+      onsubmit     %Script.datatype;        #IMPLIED
+      onreset      %Script.datatype;        #IMPLIED
+>
+
+<!-- additional attributes on label element
+-->
+<!ATTLIST %label.qname;
+      onfocus      %Script.datatype;        #IMPLIED
+      onblur       %Script.datatype;        #IMPLIED
+>
+
+<!-- additional attributes on input element
+-->
+<!ATTLIST %input.qname;
+      onfocus      %Script.datatype;        #IMPLIED
+      onblur       %Script.datatype;        #IMPLIED
+      onselect     %Script.datatype;        #IMPLIED
+      onchange     %Script.datatype;        #IMPLIED
+>
+
+<!-- additional attributes on select element
+-->
+<!ATTLIST %select.qname;
+      onfocus      %Script.datatype;        #IMPLIED
+      onblur       %Script.datatype;        #IMPLIED
+      onchange     %Script.datatype;        #IMPLIED
+>
+
+<!-- additional attributes on textarea element
+-->
+<!ATTLIST %textarea.qname;
+      onfocus      %Script.datatype;        #IMPLIED
+      onblur       %Script.datatype;        #IMPLIED
+      onselect     %Script.datatype;        #IMPLIED
+      onchange     %Script.datatype;        #IMPLIED
+>
+
+<!-- additional attributes on button element
+-->
+<!ATTLIST %button.qname;
+      onfocus      %Script.datatype;        #IMPLIED
+      onblur       %Script.datatype;        #IMPLIED
+>
+
+<!-- additional attributes on body element
+-->
+<!ATTLIST %body.qname;
+      onload       %Script.datatype;        #IMPLIED
+      onunload     %Script.datatype;        #IMPLIED
+>
+
+<!-- additional attributes on area element
+-->
+<!ATTLIST %area.qname;
+      onfocus      %Script.datatype;        #IMPLIED
+      onblur       %Script.datatype;        #IMPLIED
+>
+
+<!-- end of xhtml-events-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-form-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-form-1.mod
new file mode 100644
index 0000000..467ea02
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-form-1.mod
@@ -0,0 +1,291 @@
+<!-- ...................................................................... -->
+<!-- XHTML Forms Module  .................................................. -->
+<!-- file: xhtml-form-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-form-1.mod,v 4.1 2001/04/10 09:42:30 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Forms 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-form-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Forms
+
+        form, label, input, select, optgroup, option,
+        textarea, fieldset, legend, button
+
+     This module declares markup to provide support for online
+     forms, based on the features found in HTML 4 forms.
+-->
+
+<!-- declare qualified element type names:
+-->
+<!ENTITY % form.qname  "form" >
+<!ENTITY % label.qname  "label" >
+<!ENTITY % input.qname  "input" >
+<!ENTITY % select.qname  "select" >
+<!ENTITY % optgroup.qname  "optgroup" >
+<!ENTITY % option.qname  "option" >
+<!ENTITY % textarea.qname  "textarea" >
+<!ENTITY % fieldset.qname  "fieldset" >
+<!ENTITY % legend.qname  "legend" >
+<!ENTITY % button.qname  "button" >
+
+<!-- %BlkNoForm.mix; includes all non-form block elements,
+     plus %Misc.class;
+-->
+<!ENTITY % BlkNoForm.mix
+     "%Heading.class;
+      | %List.class;
+      | %BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %Table.class;
+      %Block.extra;
+      %Misc.class;"
+>
+
+<!-- form: Form Element ................................ -->
+
+<!ENTITY % form.element  "INCLUDE" >
+<![%form.element;[
+<!ENTITY % form.content
+     "( %BlkNoForm.mix;
+      | %fieldset.qname; )+"
+>
+<!ELEMENT %form.qname;  %form.content; >
+<!-- end of form.element -->]]>
+
+<!ENTITY % form.attlist  "INCLUDE" >
+<![%form.attlist;[
+<!ATTLIST %form.qname;
+      %Common.attrib;
+      action       %URI.datatype;           #REQUIRED
+      method       ( get | post )           'get'
+      enctype      %ContentType.datatype;   'application/x-www-form-urlencoded'
+      accept-charset %Charsets.datatype;    #IMPLIED
+      accept       %ContentTypes.datatype;  #IMPLIED
+>
+<!-- end of form.attlist -->]]>
+
+<!-- label: Form Field Label Text ...................... -->
+
+<!-- Each label must not contain more than ONE field
+-->
+
+<!ENTITY % label.element  "INCLUDE" >
+<![%label.element;[
+<!ENTITY % label.content
+     "( #PCDATA
+      | %input.qname; | %select.qname; | %textarea.qname; | %button.qname;
+      | %InlStruct.class;
+      %InlPhras.class;
+      %I18n.class;
+      %InlPres.class;
+      %Anchor.class;
+      %InlSpecial.class;
+      %Inline.extra;
+      %Misc.class; )*"
+>
+<!ELEMENT %label.qname;  %label.content; >
+<!-- end of label.element -->]]>
+
+<!ENTITY % label.attlist  "INCLUDE" >
+<![%label.attlist;[
+<!ATTLIST %label.qname;
+      %Common.attrib;
+      for          IDREF                    #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of label.attlist -->]]>
+
+<!-- input: Form Control ............................... -->
+
+<!ENTITY % input.element  "INCLUDE" >
+<![%input.element;[
+<!ENTITY % input.content  "EMPTY" >
+<!ELEMENT %input.qname;  %input.content; >
+<!-- end of input.element -->]]>
+
+<!ENTITY % input.attlist  "INCLUDE" >
+<![%input.attlist;[
+<!ENTITY % InputType.class
+     "( text | password | checkbox | radio | submit
+      | reset | file | hidden | image | button )"
+>
+<!-- attribute 'name' required for all but submit & reset
+-->
+<!ATTLIST %input.qname;
+      %Common.attrib;
+      type         %InputType.class;        'text'
+      name         CDATA                    #IMPLIED
+      value        CDATA                    #IMPLIED
+      checked      ( checked )              #IMPLIED
+      disabled     ( disabled )             #IMPLIED
+      readonly     ( readonly )             #IMPLIED
+      size         %Number.datatype;        #IMPLIED
+      maxlength    %Number.datatype;        #IMPLIED
+      src          %URI.datatype;           #IMPLIED
+      alt          %Text.datatype;          #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+      accept       %ContentTypes.datatype;  #IMPLIED
+>
+<!-- end of input.attlist -->]]>
+
+<!-- select: Option Selector ........................... -->
+
+<!ENTITY % select.element  "INCLUDE" >
+<![%select.element;[
+<!ENTITY % select.content
+     "( %optgroup.qname; | %option.qname; )+"
+>
+<!ELEMENT %select.qname;  %select.content; >
+<!-- end of select.element -->]]>
+
+<!ENTITY % select.attlist  "INCLUDE" >
+<![%select.attlist;[
+<!ATTLIST %select.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      size         %Number.datatype;        #IMPLIED
+      multiple     ( multiple )             #IMPLIED
+      disabled     ( disabled )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+>
+<!-- end of select.attlist -->]]>
+
+<!-- optgroup: Option Group ............................ -->
+
+<!ENTITY % optgroup.element  "INCLUDE" >
+<![%optgroup.element;[
+<!ENTITY % optgroup.content  "( %option.qname; )+" >
+<!ELEMENT %optgroup.qname;  %optgroup.content; >
+<!-- end of optgroup.element -->]]>
+
+<!ENTITY % optgroup.attlist  "INCLUDE" >
+<![%optgroup.attlist;[
+<!ATTLIST %optgroup.qname;
+      %Common.attrib;
+      disabled     ( disabled )             #IMPLIED
+      label        %Text.datatype;          #REQUIRED
+>
+<!-- end of optgroup.attlist -->]]>
+
+<!-- option: Selectable Choice ......................... -->
+
+<!ENTITY % option.element  "INCLUDE" >
+<![%option.element;[
+<!ENTITY % option.content  "( #PCDATA )" >
+<!ELEMENT %option.qname;  %option.content; >
+<!-- end of option.element -->]]>
+
+<!ENTITY % option.attlist  "INCLUDE" >
+<![%option.attlist;[
+<!ATTLIST %option.qname;
+      %Common.attrib;
+      selected     ( selected )             #IMPLIED
+      disabled     ( disabled )             #IMPLIED
+      label        %Text.datatype;          #IMPLIED
+      value        CDATA                    #IMPLIED
+>
+<!-- end of option.attlist -->]]>
+
+<!-- textarea: Multi-Line Text Field ................... -->
+
+<!ENTITY % textarea.element  "INCLUDE" >
+<![%textarea.element;[
+<!ENTITY % textarea.content  "( #PCDATA )" >
+<!ELEMENT %textarea.qname;  %textarea.content; >
+<!-- end of textarea.element -->]]>
+
+<!ENTITY % textarea.attlist  "INCLUDE" >
+<![%textarea.attlist;[
+<!ATTLIST %textarea.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      rows         %Number.datatype;        #REQUIRED
+      cols         %Number.datatype;        #REQUIRED
+      disabled     ( disabled )             #IMPLIED
+      readonly     ( readonly )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of textarea.attlist -->]]>
+
+<!-- fieldset: Form Control Group ...................... -->
+
+<!-- #PCDATA is to solve the mixed content problem,
+     per specification only whitespace is allowed
+-->
+
+<!ENTITY % fieldset.element  "INCLUDE" >
+<![%fieldset.element;[
+<!ENTITY % fieldset.content
+     "( #PCDATA | %legend.qname; | %Flow.mix; )*"
+>
+<!ELEMENT %fieldset.qname;  %fieldset.content; >
+<!-- end of fieldset.element -->]]>
+
+<!ENTITY % fieldset.attlist  "INCLUDE" >
+<![%fieldset.attlist;[
+<!ATTLIST %fieldset.qname;
+      %Common.attrib;
+>
+<!-- end of fieldset.attlist -->]]>
+
+<!-- legend: Fieldset Legend ........................... -->
+
+<!ENTITY % legend.element  "INCLUDE" >
+<![%legend.element;[
+<!ENTITY % legend.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ELEMENT %legend.qname;  %legend.content; >
+<!-- end of legend.element -->]]>
+
+<!ENTITY % legend.attlist  "INCLUDE" >
+<![%legend.attlist;[
+<!ATTLIST %legend.qname;
+      %Common.attrib;
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of legend.attlist -->]]>
+
+<!-- button: Push Button ............................... -->
+
+<!ENTITY % button.element  "INCLUDE" >
+<![%button.element;[
+<!ENTITY % button.content
+     "( #PCDATA
+      | %BlkNoForm.mix;
+      | %InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %I18n.class;
+      %InlSpecial.class;
+      %Inline.extra; )*"
+>
+<!ELEMENT %button.qname;  %button.content; >
+<!-- end of button.element -->]]>
+
+<!ENTITY % button.attlist  "INCLUDE" >
+<![%button.attlist;[
+<!ATTLIST %button.qname;
+      %Common.attrib;
+      name         CDATA                    #IMPLIED
+      value        CDATA                    #IMPLIED
+      type         ( button | submit | reset ) 'submit'
+      disabled     ( disabled )             #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+>
+<!-- end of button.attlist -->]]>
+
+<!-- end of xhtml-form-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-framework-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-framework-1.mod
new file mode 100644
index 0000000..7d9d972
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-framework-1.mod
@@ -0,0 +1,97 @@
+<!-- ...................................................................... -->
+<!-- XHTML Modular Framework Module  ...................................... -->
+<!-- file: xhtml-framework-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-framework-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-framework-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Modular Framework
+
+     This required module instantiates the modules needed
+     to support the XHTML modularization model, including:
+
+        +  datatypes
+        +  namespace-qualified names
+        +  common attributes
+        +  document model
+        +  character entities
+
+     The Intrinsic Events module is ignored by default but
+     occurs in this module because it must be instantiated
+     prior to Attributes but after Datatypes.
+-->
+
+<!ENTITY % xhtml-arch.module "IGNORE" >
+<![%xhtml-arch.module;[
+<!ENTITY % xhtml-arch.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Base Architecture 1.0//EN"
+            "xhtml-arch-1.mod" >
+%xhtml-arch.mod;]]>
+
+<!ENTITY % xhtml-notations.module "IGNORE" >
+<![%xhtml-notations.module;[
+<!ENTITY % xhtml-notations.mod
+     PUBLIC "-//W3C//NOTATIONS XHTML Notations 1.0//EN"
+            "xhtml-notations-1.mod" >
+%xhtml-notations.mod;]]>
+
+<!ENTITY % xhtml-datatypes.module "INCLUDE" >
+<![%xhtml-datatypes.module;[
+<!ENTITY % xhtml-datatypes.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Datatypes 1.0//EN"
+            "xhtml-datatypes-1.mod" >
+%xhtml-datatypes.mod;]]>
+
+<!-- placeholder for XLink support module -->
+<!ENTITY % xhtml-xlink.mod "" >
+%xhtml-xlink.mod;
+
+<!ENTITY % xhtml-qname.module "INCLUDE" >
+<![%xhtml-qname.module;[
+<!ENTITY % xhtml-qname.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Qualified Names 1.0//EN"
+            "xhtml-qname-1.mod" >
+%xhtml-qname.mod;]]>
+
+<!ENTITY % xhtml-events.module "IGNORE" >
+<![%xhtml-events.module;[
+<!ENTITY % xhtml-events.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Intrinsic Events 1.0//EN"
+            "xhtml-events-1.mod" >
+%xhtml-events.mod;]]>
+
+<!ENTITY % xhtml-attribs.module "INCLUDE" >
+<![%xhtml-attribs.module;[
+<!ENTITY % xhtml-attribs.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Common Attributes 1.0//EN"
+            "xhtml-attribs-1.mod" >
+%xhtml-attribs.mod;]]>
+
+<!-- placeholder for content model redeclarations -->
+<!ENTITY % xhtml-model.redecl "" >
+%xhtml-model.redecl;
+
+<!ENTITY % xhtml-model.module "INCLUDE" >
+<![%xhtml-model.module;[
+<!-- instantiate the Document Model module declared in the DTD driver
+-->
+%xhtml-model.mod;]]>
+
+<!ENTITY % xhtml-charent.module "INCLUDE" >
+<![%xhtml-charent.module;[
+<!ENTITY % xhtml-charent.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Character Entities 1.0//EN"
+            "xhtml-charent-1.mod" >
+%xhtml-charent.mod;]]>
+
+<!-- end of xhtml-framework-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-hypertext-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-hypertext-1.mod
new file mode 100644
index 0000000..7a7d8ca
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-hypertext-1.mod
@@ -0,0 +1,54 @@
+<!-- ...................................................................... -->
+<!-- XHTML Hypertext Module  .............................................. -->
+<!-- file: xhtml-hypertext-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-hypertext-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-hypertext-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Hypertext
+
+        a
+
+     This module declares the anchor ('a') element type, which
+     defines the source of a hypertext link. The destination
+     (or link 'target') is identified via its 'id' attribute
+     rather than the 'name' attribute as was used in HTML.
+-->
+
+<!-- ............  Anchor Element  ............ -->
+
+<!ENTITY % a.element  "INCLUDE" >
+<![%a.element;[
+<!ENTITY % a.content
+     "( #PCDATA | %InlNoAnchor.mix; )*"
+>
+<!ENTITY % a.qname  "a" >
+<!ELEMENT %a.qname;  %a.content; >
+<!-- end of a.element -->]]>
+
+<!ENTITY % a.attlist  "INCLUDE" >
+<![%a.attlist;[
+<!ATTLIST %a.qname;
+      %Common.attrib;
+      href         %URI.datatype;           #IMPLIED
+      charset      %Charset.datatype;       #IMPLIED
+      type         %ContentType.datatype;   #IMPLIED
+      hreflang     %LanguageCode.datatype;  #IMPLIED
+      rel          %LinkTypes.datatype;     #IMPLIED
+      rev          %LinkTypes.datatype;     #IMPLIED
+      accesskey    %Character.datatype;     #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+>
+<!-- end of a.attlist -->]]>
+
+<!-- end of xhtml-hypertext-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-image-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-image-1.mod
new file mode 100644
index 0000000..01b6f2c
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-image-1.mod
@@ -0,0 +1,50 @@
+<!-- ...................................................................... -->
+<!-- XHTML Images Module  ................................................. -->
+<!-- file: xhtml-image-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Rovision: $Id: xhtml-image-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Images 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-image-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Images
+
+        img
+
+     This module provides markup to support basic image embedding.
+-->
+
+<!-- To avoid problems with text-only UAs as well as to make
+     image content understandable and navigable to users of
+     non-visual UAs, you need to provide a description with
+     the 'alt' attribute, and avoid server-side image maps.
+-->
+
+<!ENTITY % img.element  "INCLUDE" >
+<![%img.element;[
+<!ENTITY % img.content  "EMPTY" >
+<!ENTITY % img.qname  "img" >
+<!ELEMENT %img.qname;  %img.content; >
+<!-- end of img.element -->]]>
+
+<!ENTITY % img.attlist  "INCLUDE" >
+<![%img.attlist;[
+<!ATTLIST %img.qname;
+      %Common.attrib;
+      src          %URI.datatype;           #REQUIRED
+      alt          %Text.datatype;          #REQUIRED
+      longdesc     %URI.datatype;           #IMPLIED
+      height       %Length.datatype;        #IMPLIED
+      width        %Length.datatype;        #IMPLIED
+>
+<!-- end of img.attlist -->]]>
+
+<!-- end of xhtml-image-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlphras-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlphras-1.mod
new file mode 100644
index 0000000..d749b2e
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlphras-1.mod
@@ -0,0 +1,203 @@
+<!-- ...................................................................... -->
+<!-- XHTML Inline Phrasal Module  ......................................... -->
+<!-- file: xhtml-inlphras-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-inlphras-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Inline Phrasal 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-inlphras-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Inline Phrasal
+
+        abbr, acronym, cite, code, dfn, em, kbd, q, samp, strong, var
+
+     This module declares the elements and their attributes used to
+     support inline-level phrasal markup.
+-->
+
+<!ENTITY % abbr.element  "INCLUDE" >
+<![%abbr.element;[
+<!ENTITY % abbr.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % abbr.qname  "abbr" >
+<!ELEMENT %abbr.qname;  %abbr.content; >
+<!-- end of abbr.element -->]]>
+
+<!ENTITY % abbr.attlist  "INCLUDE" >
+<![%abbr.attlist;[
+<!ATTLIST %abbr.qname;
+      %Common.attrib;
+>
+<!-- end of abbr.attlist -->]]>
+
+<!ENTITY % acronym.element  "INCLUDE" >
+<![%acronym.element;[
+<!ENTITY % acronym.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % acronym.qname  "acronym" >
+<!ELEMENT %acronym.qname;  %acronym.content; >
+<!-- end of acronym.element -->]]>
+
+<!ENTITY % acronym.attlist  "INCLUDE" >
+<![%acronym.attlist;[
+<!ATTLIST %acronym.qname;
+      %Common.attrib;
+>
+<!-- end of acronym.attlist -->]]>
+
+<!ENTITY % cite.element  "INCLUDE" >
+<![%cite.element;[
+<!ENTITY % cite.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % cite.qname  "cite" >
+<!ELEMENT %cite.qname;  %cite.content; >
+<!-- end of cite.element -->]]>
+
+<!ENTITY % cite.attlist  "INCLUDE" >
+<![%cite.attlist;[
+<!ATTLIST %cite.qname;
+      %Common.attrib;
+>
+<!-- end of cite.attlist -->]]>
+
+<!ENTITY % code.element  "INCLUDE" >
+<![%code.element;[
+<!ENTITY % code.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % code.qname  "code" >
+<!ELEMENT %code.qname;  %code.content; >
+<!-- end of code.element -->]]>
+
+<!ENTITY % code.attlist  "INCLUDE" >
+<![%code.attlist;[
+<!ATTLIST %code.qname;
+      %Common.attrib;
+>
+<!-- end of code.attlist -->]]>
+
+<!ENTITY % dfn.element  "INCLUDE" >
+<![%dfn.element;[
+<!ENTITY % dfn.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % dfn.qname  "dfn" >
+<!ELEMENT %dfn.qname;  %dfn.content; >
+<!-- end of dfn.element -->]]>
+
+<!ENTITY % dfn.attlist  "INCLUDE" >
+<![%dfn.attlist;[
+<!ATTLIST %dfn.qname;
+      %Common.attrib;
+>
+<!-- end of dfn.attlist -->]]>
+
+<!ENTITY % em.element  "INCLUDE" >
+<![%em.element;[
+<!ENTITY % em.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % em.qname  "em" >
+<!ELEMENT %em.qname;  %em.content; >
+<!-- end of em.element -->]]>
+
+<!ENTITY % em.attlist  "INCLUDE" >
+<![%em.attlist;[
+<!ATTLIST %em.qname;
+      %Common.attrib;
+>
+<!-- end of em.attlist -->]]>
+
+<!ENTITY % kbd.element  "INCLUDE" >
+<![%kbd.element;[
+<!ENTITY % kbd.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % kbd.qname  "kbd" >
+<!ELEMENT %kbd.qname;  %kbd.content; >
+<!-- end of kbd.element -->]]>
+
+<!ENTITY % kbd.attlist  "INCLUDE" >
+<![%kbd.attlist;[
+<!ATTLIST %kbd.qname;
+      %Common.attrib;
+>
+<!-- end of kbd.attlist -->]]>
+
+<!ENTITY % q.element  "INCLUDE" >
+<![%q.element;[
+<!ENTITY % q.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % q.qname  "q" >
+<!ELEMENT %q.qname;  %q.content; >
+<!-- end of q.element -->]]>
+
+<!ENTITY % q.attlist  "INCLUDE" >
+<![%q.attlist;[
+<!ATTLIST %q.qname;
+      %Common.attrib;
+      cite         %URI.datatype;           #IMPLIED
+>
+<!-- end of q.attlist -->]]>
+
+<!ENTITY % samp.element  "INCLUDE" >
+<![%samp.element;[
+<!ENTITY % samp.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % samp.qname  "samp" >
+<!ELEMENT %samp.qname;  %samp.content; >
+<!-- end of samp.element -->]]>
+
+<!ENTITY % samp.attlist  "INCLUDE" >
+<![%samp.attlist;[
+<!ATTLIST %samp.qname;
+      %Common.attrib;
+>
+<!-- end of samp.attlist -->]]>
+
+<!ENTITY % strong.element  "INCLUDE" >
+<![%strong.element;[
+<!ENTITY % strong.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % strong.qname  "strong" >
+<!ELEMENT %strong.qname;  %strong.content; >
+<!-- end of strong.element -->]]>
+
+<!ENTITY % strong.attlist  "INCLUDE" >
+<![%strong.attlist;[
+<!ATTLIST %strong.qname;
+      %Common.attrib;
+>
+<!-- end of strong.attlist -->]]>
+
+<!ENTITY % var.element  "INCLUDE" >
+<![%var.element;[
+<!ENTITY % var.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % var.qname  "var" >
+<!ELEMENT %var.qname;  %var.content; >
+<!-- end of var.element -->]]>
+
+<!ENTITY % var.attlist  "INCLUDE" >
+<![%var.attlist;[
+<!ATTLIST %var.qname;
+      %Common.attrib;
+>
+<!-- end of var.attlist -->]]>
+
+<!-- end of xhtml-inlphras-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlpres-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlpres-1.mod
new file mode 100644
index 0000000..8717d54
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlpres-1.mod
@@ -0,0 +1,138 @@
+<!-- ...................................................................... -->
+<!-- XHTML Inline Presentation Module  .................................... -->
+<!-- file: xhtml-inlpres-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-inlpres-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-inlpres-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Inline Presentational Elements
+
+        b, big, i, small, sub, sup, tt
+
+     This module declares the elements and their attributes used to
+     support inline-level presentational markup.
+-->
+
+<!ENTITY % b.element  "INCLUDE" >
+<![%b.element;[
+<!ENTITY % b.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % b.qname  "b" >
+<!ELEMENT %b.qname;  %b.content; >
+<!-- end of b.element -->]]>
+
+<!ENTITY % b.attlist  "INCLUDE" >
+<![%b.attlist;[
+<!ATTLIST %b.qname;
+      %Common.attrib;
+>
+<!-- end of b.attlist -->]]>
+
+<!ENTITY % big.element  "INCLUDE" >
+<![%big.element;[
+<!ENTITY % big.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % big.qname  "big" >
+<!ELEMENT %big.qname;  %big.content; >
+<!-- end of big.element -->]]>
+
+<!ENTITY % big.attlist  "INCLUDE" >
+<![%big.attlist;[
+<!ATTLIST %big.qname;
+      %Common.attrib;
+>
+<!-- end of big.attlist -->]]>
+
+<!ENTITY % i.element  "INCLUDE" >
+<![%i.element;[
+<!ENTITY % i.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % i.qname  "i" >
+<!ELEMENT %i.qname;  %i.content; >
+<!-- end of i.element -->]]>
+
+<!ENTITY % i.attlist  "INCLUDE" >
+<![%i.attlist;[
+<!ATTLIST %i.qname;
+      %Common.attrib;
+>
+<!-- end of i.attlist -->]]>
+
+<!ENTITY % small.element  "INCLUDE" >
+<![%small.element;[
+<!ENTITY % small.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % small.qname  "small" >
+<!ELEMENT %small.qname;  %small.content; >
+<!-- end of small.element -->]]>
+
+<!ENTITY % small.attlist  "INCLUDE" >
+<![%small.attlist;[
+<!ATTLIST %small.qname;
+      %Common.attrib;
+>
+<!-- end of small.attlist -->]]>
+
+<!ENTITY % sub.element  "INCLUDE" >
+<![%sub.element;[
+<!ENTITY % sub.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % sub.qname  "sub" >
+<!ELEMENT %sub.qname;  %sub.content; >
+<!-- end of sub.element -->]]>
+
+<!ENTITY % sub.attlist  "INCLUDE" >
+<![%sub.attlist;[
+<!ATTLIST %sub.qname;
+      %Common.attrib;
+>
+<!-- end of sub.attlist -->]]>
+
+<!ENTITY % sup.element  "INCLUDE" >
+<![%sup.element;[
+<!ENTITY % sup.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % sup.qname  "sup" >
+<!ELEMENT %sup.qname;  %sup.content; >
+<!-- end of sup.element -->]]>
+
+<!ENTITY % sup.attlist  "INCLUDE" >
+<![%sup.attlist;[
+<!ATTLIST %sup.qname;
+      %Common.attrib;
+>
+<!-- end of sup.attlist -->]]>
+
+<!ENTITY % tt.element  "INCLUDE" >
+<![%tt.element;[
+<!ENTITY % tt.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % tt.qname  "tt" >
+<!ELEMENT %tt.qname;  %tt.content; >
+<!-- end of tt.element -->]]>
+
+<!ENTITY % tt.attlist  "INCLUDE" >
+<![%tt.attlist;[
+<!ATTLIST %tt.qname;
+      %Common.attrib;
+>
+<!-- end of tt.attlist -->]]>
+
+<!-- end of xhtml-inlpres-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlstruct-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlstruct-1.mod
new file mode 100644
index 0000000..3d43d28
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlstruct-1.mod
@@ -0,0 +1,62 @@
+<!-- ...................................................................... -->
+<!-- XHTML Inline Structural Module  ...................................... -->
+<!-- file: xhtml-inlstruct-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-inlstruct-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Inline Structural 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-inlstruct-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Inline Structural
+
+        br, span
+
+     This module declares the elements and their attributes
+     used to support inline-level structural markup.
+-->
+
+<!-- br: forced line break ............................. -->
+
+<!ENTITY % br.element  "INCLUDE" >
+<![%br.element;[
+
+<!ENTITY % br.content  "EMPTY" >
+<!ENTITY % br.qname  "br" >
+<!ELEMENT %br.qname;  %br.content; >
+
+<!-- end of br.element -->]]>
+
+<!ENTITY % br.attlist  "INCLUDE" >
+<![%br.attlist;[
+<!ATTLIST %br.qname;
+      %Core.attrib;
+>
+<!-- end of br.attlist -->]]>
+
+<!-- span: generic inline container .................... -->
+
+<!ENTITY % span.element  "INCLUDE" >
+<![%span.element;[
+<!ENTITY % span.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ENTITY % span.qname  "span" >
+<!ELEMENT %span.qname;  %span.content; >
+<!-- end of span.element -->]]>
+
+<!ENTITY % span.attlist  "INCLUDE" >
+<![%span.attlist;[
+<!ATTLIST %span.qname;
+      %Common.attrib;
+>
+<!-- end of span.attlist -->]]>
+
+<!-- end of xhtml-inlstruct-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlstyle-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlstyle-1.mod
new file mode 100644
index 0000000..305680f
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-inlstyle-1.mod
@@ -0,0 +1,34 @@
+<!-- ...................................................................... -->
+<!-- XHTML Inline Style Module  ........................................... -->
+<!-- file: xhtml-inlstyle-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-inlstyle-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Inline Style 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-inlstyle-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Inline Style
+
+     This module declares the 'style' attribute, used to support inline
+     style markup. This module must be instantiated prior to the XHTML
+     Common Attributes module in order to be included in %Core.attrib;.
+-->
+
+<!ENTITY % style.attrib
+     "style        CDATA                    #IMPLIED"
+>
+
+
+<!ENTITY % Core.extra.attrib
+     "%style.attrib;"
+>
+
+<!-- end of xhtml-inlstyle-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-lat1.ent b/xml/impl/resources/standardSchemas/xhtml11/xhtml-lat1.ent
new file mode 100644
index 0000000..929aa3d
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-lat1.ent
@@ -0,0 +1,121 @@
+<!-- ...................................................................... -->
+<!-- XML-compatible ISO Latin 1 Character Entity Set for XHTML ............ -->
+<!-- file: xhtml-lat1.ent
+
+     Typical invocation:
+
+       <!ENTITY % xhtml-lat1
+           PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+                  "xhtml-lat1.ent" >
+       %xhtml-lat1;
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-lat1.ent"
+
+     Revision:  $Id: xhtml-lat1.ent,v 4.1 2001/04/10 09:34:14 altheim Exp $ SMI
+
+     Portions (C) International Organization for Standardization 1986:
+     Permission to copy in any form is granted for use with conforming
+     SGML systems and applications as defined in ISO 8879, provided
+     this notice is included in all copies.
+-->
+
+<!ENTITY nbsp   "&#160;" ><!-- no-break space = non-breaking space, U+00A0 ISOnum -->
+<!ENTITY iexcl  "&#161;" ><!-- inverted exclamation mark, U+00A1 ISOnum -->
+<!ENTITY cent   "&#162;" ><!-- cent sign, U+00A2 ISOnum -->
+<!ENTITY pound  "&#163;" ><!-- pound sign, U+00A3 ISOnum -->
+<!ENTITY curren "&#164;" ><!-- currency sign, U+00A4 ISOnum -->
+<!ENTITY yen    "&#165;" ><!-- yen sign = yuan sign, U+00A5 ISOnum -->
+<!ENTITY brvbar "&#166;" ><!-- broken bar = broken vertical bar, U+00A6 ISOnum -->
+<!ENTITY sect   "&#167;" ><!-- section sign, U+00A7 ISOnum -->
+<!ENTITY uml    "&#168;" ><!-- diaeresis = spacing diaeresis, U+00A8 ISOdia -->
+<!ENTITY copy   "&#169;" ><!-- copyright sign, U+00A9 ISOnum -->
+<!ENTITY ordf   "&#170;" ><!-- feminine ordinal indicator, U+00AA ISOnum -->
+<!ENTITY laquo  "&#171;" ><!-- left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum -->
+<!ENTITY not    "&#172;" ><!-- not sign, U+00AC ISOnum -->
+<!ENTITY shy    "&#173;" ><!-- soft hyphen = discretionary hyphen, U+00AD ISOnum -->
+<!ENTITY reg    "&#174;" ><!-- registered sign = registered trade mark sign, U+00AE ISOnum -->
+<!ENTITY macr   "&#175;" ><!-- macron = spacing macron = overline = APL overbar, U+00AF ISOdia -->
+<!ENTITY deg    "&#176;" ><!-- degree sign, U+00B0 ISOnum -->
+<!ENTITY plusmn "&#177;" ><!-- plus-minus sign = plus-or-minus sign, U+00B1 ISOnum -->
+<!ENTITY sup2   "&#178;" ><!-- superscript two = superscript digit two = squared, U+00B2 ISOnum -->
+<!ENTITY sup3   "&#179;" ><!-- superscript three = superscript digit three = cubed, U+00B3 ISOnum -->
+<!ENTITY acute  "&#180;" ><!-- acute accent = spacing acute, U+00B4 ISOdia -->
+<!ENTITY micro  "&#181;" ><!-- micro sign, U+00B5 ISOnum -->
+<!ENTITY para   "&#182;" ><!-- pilcrow sign = paragraph sign, U+00B6 ISOnum -->
+<!ENTITY middot "&#183;" ><!-- middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum -->
+<!ENTITY cedil  "&#184;" ><!-- cedilla = spacing cedilla, U+00B8 ISOdia -->
+<!ENTITY sup1   "&#185;" ><!-- superscript one = superscript digit one, U+00B9 ISOnum -->
+<!ENTITY ordm   "&#186;" ><!-- masculine ordinal indicator, U+00BA ISOnum -->
+<!ENTITY raquo  "&#187;" ><!-- right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum -->
+<!ENTITY frac14 "&#188;" ><!-- vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum -->
+<!ENTITY frac12 "&#189;" ><!-- vulgar fraction one half = fraction one half, U+00BD ISOnum -->
+<!ENTITY frac34 "&#190;" ><!-- vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum -->
+<!ENTITY iquest "&#191;" ><!-- inverted question mark = turned question mark, U+00BF ISOnum -->
+<!ENTITY Agrave "&#192;" ><!-- latin capital A with grave = latin capital A grave, U+00C0 ISOlat1 -->
+<!ENTITY Aacute "&#193;" ><!-- latin capital A with acute, U+00C1 ISOlat1 -->
+<!ENTITY Acirc  "&#194;" ><!-- latin capital A with circumflex, U+00C2 ISOlat1 -->
+<!ENTITY Atilde "&#195;" ><!-- latin capital A with tilde, U+00C3 ISOlat1 -->
+<!ENTITY Auml   "&#196;" ><!-- latin capital A with diaeresis, U+00C4 ISOlat1 -->
+<!ENTITY Aring  "&#197;" ><!-- latin capital A with ring above = latin capital A ring, U+00C5 ISOlat1 -->
+<!ENTITY AElig  "&#198;" ><!-- latin capital AE = latin capital ligature AE, U+00C6 ISOlat1 -->
+<!ENTITY Ccedil "&#199;" ><!-- latin capital C with cedilla, U+00C7 ISOlat1 -->
+<!ENTITY Egrave "&#200;" ><!-- latin capital E with grave, U+00C8 ISOlat1 -->
+<!ENTITY Eacute "&#201;" ><!-- latin capital E with acute, U+00C9 ISOlat1 -->
+<!ENTITY Ecirc  "&#202;" ><!-- latin capital E with circumflex, U+00CA ISOlat1 -->
+<!ENTITY Euml   "&#203;" ><!-- latin capital E with diaeresis, U+00CB ISOlat1 -->
+<!ENTITY Igrave "&#204;" ><!-- latin capital I with grave, U+00CC ISOlat1 -->
+<!ENTITY Iacute "&#205;" ><!-- latin capital I with acute, U+00CD ISOlat1 -->
+<!ENTITY Icirc  "&#206;" ><!-- latin capital I with circumflex, U+00CE ISOlat1 -->
+<!ENTITY Iuml   "&#207;" ><!-- latin capital I with diaeresis, U+00CF ISOlat1 -->
+<!ENTITY ETH    "&#208;" ><!-- latin capital ETH, U+00D0 ISOlat1 -->
+<!ENTITY Ntilde "&#209;" ><!-- latin capital N with tilde, U+00D1 ISOlat1 -->
+<!ENTITY Ograve "&#210;" ><!-- latin capital O with grave, U+00D2 ISOlat1 -->
+<!ENTITY Oacute "&#211;" ><!-- latin capital O with acute, U+00D3 ISOlat1 -->
+<!ENTITY Ocirc  "&#212;" ><!-- latin capital O with circumflex, U+00D4 ISOlat1 -->
+<!ENTITY Otilde "&#213;" ><!-- latin capital O with tilde, U+00D5 ISOlat1 -->
+<!ENTITY Ouml   "&#214;" ><!-- latin capital O with diaeresis, U+00D6 ISOlat1 -->
+<!ENTITY times  "&#215;" ><!-- multiplication sign, U+00D7 ISOnum -->
+<!ENTITY Oslash "&#216;" ><!-- latin capital O with stroke = latin capital O slash, U+00D8 ISOlat1 -->
+<!ENTITY Ugrave "&#217;" ><!-- latin capital U with grave, U+00D9 ISOlat1 -->
+<!ENTITY Uacute "&#218;" ><!-- latin capital U with acute, U+00DA ISOlat1 -->
+<!ENTITY Ucirc  "&#219;" ><!-- latin capital U with circumflex, U+00DB ISOlat1 -->
+<!ENTITY Uuml   "&#220;" ><!-- latin capital U with diaeresis, U+00DC ISOlat1 -->
+<!ENTITY Yacute "&#221;" ><!-- latin capital Y with acute, U+00DD ISOlat1 -->
+<!ENTITY THORN  "&#222;" ><!-- latin capital THORN, U+00DE ISOlat1 -->
+<!ENTITY szlig  "&#223;" ><!-- latin small sharp s = ess-zed, U+00DF ISOlat1 -->
+<!ENTITY agrave "&#224;" ><!-- latin small a with grave = latin small a grave, U+00E0 ISOlat1 -->
+<!ENTITY aacute "&#225;" ><!-- latin small a with acute, U+00E1 ISOlat1 -->
+<!ENTITY acirc  "&#226;" ><!-- latin small a with circumflex, U+00E2 ISOlat1 -->
+<!ENTITY atilde "&#227;" ><!-- latin small a with tilde, U+00E3 ISOlat1 -->
+<!ENTITY auml   "&#228;" ><!-- latin small a with diaeresis, U+00E4 ISOlat1 -->
+<!ENTITY aring  "&#229;" ><!-- latin small a with ring above = latin small a ring, U+00E5 ISOlat1 -->
+<!ENTITY aelig  "&#230;" ><!-- latin small ae = latin small ligature ae, U+00E6 ISOlat1 -->
+<!ENTITY ccedil "&#231;" ><!-- latin small c with cedilla, U+00E7 ISOlat1 -->
+<!ENTITY egrave "&#232;" ><!-- latin small e with grave, U+00E8 ISOlat1 -->
+<!ENTITY eacute "&#233;" ><!-- latin small e with acute, U+00E9 ISOlat1 -->
+<!ENTITY ecirc  "&#234;" ><!-- latin small e with circumflex, U+00EA ISOlat1 -->
+<!ENTITY euml   "&#235;" ><!-- latin small e with diaeresis, U+00EB ISOlat1 -->
+<!ENTITY igrave "&#236;" ><!-- latin small i with grave, U+00EC ISOlat1 -->
+<!ENTITY iacute "&#237;" ><!-- latin small i with acute, U+00ED ISOlat1 -->
+<!ENTITY icirc  "&#238;" ><!-- latin small i with circumflex, U+00EE ISOlat1 -->
+<!ENTITY iuml   "&#239;" ><!-- latin small i with diaeresis, U+00EF ISOlat1 -->
+<!ENTITY eth    "&#240;" ><!-- latin small eth, U+00F0 ISOlat1 -->
+<!ENTITY ntilde "&#241;" ><!-- latin small n with tilde, U+00F1 ISOlat1 -->
+<!ENTITY ograve "&#242;" ><!-- latin small o with grave, U+00F2 ISOlat1 -->
+<!ENTITY oacute "&#243;" ><!-- latin small o with acute, U+00F3 ISOlat1 -->
+<!ENTITY ocirc  "&#244;" ><!-- latin small o with circumflex, U+00F4 ISOlat1 -->
+<!ENTITY otilde "&#245;" ><!-- latin small o with tilde, U+00F5 ISOlat1 -->
+<!ENTITY ouml   "&#246;" ><!-- latin small o with diaeresis, U+00F6 ISOlat1 -->
+<!ENTITY divide "&#247;" ><!-- division sign, U+00F7 ISOnum -->
+<!ENTITY oslash "&#248;" ><!-- latin small o with stroke, = latin small o slash, U+00F8 ISOlat1 -->
+<!ENTITY ugrave "&#249;" ><!-- latin small u with grave, U+00F9 ISOlat1 -->
+<!ENTITY uacute "&#250;" ><!-- latin small u with acute, U+00FA ISOlat1 -->
+<!ENTITY ucirc  "&#251;" ><!-- latin small u with circumflex, U+00FB ISOlat1 -->
+<!ENTITY uuml   "&#252;" ><!-- latin small u with diaeresis, U+00FC ISOlat1 -->
+<!ENTITY yacute "&#253;" ><!-- latin small y with acute, U+00FD ISOlat1 -->
+<!ENTITY thorn  "&#254;" ><!-- latin small thorn with, U+00FE ISOlat1 -->
+<!ENTITY yuml   "&#255;" ><!-- latin small y with diaeresis, U+00FF ISOlat1 -->
+<!-- end of xhtml-lat1.ent -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-link-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-link-1.mod
new file mode 100644
index 0000000..2b4f92c
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-link-1.mod
@@ -0,0 +1,59 @@
+<!-- ...................................................................... -->
+<!-- XHTML Link Element Module  ........................................... -->
+<!-- file: xhtml-link-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-link-1.mod,v 4.1 2001/04/05 06:57:40 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Link Element 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-link-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Link element
+
+        link
+
+     This module declares the link element type and its attributes,
+     which could (in principle) be used to define document-level links
+     to external resources such as:
+
+     a) for document specific toolbars/menus, e.g. start, contents,
+        previous, next, index, end, help
+     b) to link to a separate style sheet (rel="stylesheet")
+     c) to make a link to a script (rel="script")
+     d) by style sheets to control how collections of html nodes are
+        rendered into printed documents
+     e) to make a link to a printable version of this document
+        e.g. a postscript or pdf version (rel="alternate" media="print")
+-->
+
+<!-- link: Media-Independent Link ...................... -->
+
+<!ENTITY % link.element  "INCLUDE" >
+<![%link.element;[
+<!ENTITY % link.content  "EMPTY" >
+<!ENTITY % link.qname  "link" >
+<!ELEMENT %link.qname;  %link.content; >
+<!-- end of link.element -->]]>
+
+<!ENTITY % link.attlist  "INCLUDE" >
+<![%link.attlist;[
+<!ATTLIST %link.qname;
+      %Common.attrib;
+      charset      %Charset.datatype;       #IMPLIED
+      href         %URI.datatype;           #IMPLIED
+      hreflang     %LanguageCode.datatype;  #IMPLIED
+      type         %ContentType.datatype;   #IMPLIED
+      rel          %LinkTypes.datatype;     #IMPLIED
+      rev          %LinkTypes.datatype;     #IMPLIED
+      media        %MediaDesc.datatype;     #IMPLIED
+>
+<!-- end of link.attlist -->]]>
+
+<!-- end of xhtml-link-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-list-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-list-1.mod
new file mode 100644
index 0000000..6c85f20
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-list-1.mod
@@ -0,0 +1,129 @@
+<!-- ...................................................................... -->
+<!-- XHTML Lists Module  .................................................. -->
+<!-- file: xhtml-list-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-list-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Lists 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-list-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Lists
+
+        dl, dt, dd, ol, ul, li
+
+     This module declares the list-oriented element types
+     and their attributes.
+-->
+
+<!ENTITY % dl.qname  "dl" >
+<!ENTITY % dt.qname  "dt" >
+<!ENTITY % dd.qname  "dd" >
+<!ENTITY % ol.qname  "ol" >
+<!ENTITY % ul.qname  "ul" >
+<!ENTITY % li.qname  "li" >
+
+<!-- dl: Definition List ............................... -->
+
+<!ENTITY % dl.element  "INCLUDE" >
+<![%dl.element;[
+<!ENTITY % dl.content  "( %dt.qname; | %dd.qname; )+" >
+<!ELEMENT %dl.qname;  %dl.content; >
+<!-- end of dl.element -->]]>
+
+<!ENTITY % dl.attlist  "INCLUDE" >
+<![%dl.attlist;[
+<!ATTLIST %dl.qname;
+      %Common.attrib;
+>
+<!-- end of dl.attlist -->]]>
+
+<!-- dt: Definition Term ............................... -->
+
+<!ENTITY % dt.element  "INCLUDE" >
+<![%dt.element;[
+<!ENTITY % dt.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ELEMENT %dt.qname;  %dt.content; >
+<!-- end of dt.element -->]]>
+
+<!ENTITY % dt.attlist  "INCLUDE" >
+<![%dt.attlist;[
+<!ATTLIST %dt.qname;
+      %Common.attrib;
+>
+<!-- end of dt.attlist -->]]>
+
+<!-- dd: Definition Description ........................ -->
+
+<!ENTITY % dd.element  "INCLUDE" >
+<![%dd.element;[
+<!ENTITY % dd.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ELEMENT %dd.qname;  %dd.content; >
+<!-- end of dd.element -->]]>
+
+<!ENTITY % dd.attlist  "INCLUDE" >
+<![%dd.attlist;[
+<!ATTLIST %dd.qname;
+      %Common.attrib;
+>
+<!-- end of dd.attlist -->]]>
+
+<!-- ol: Ordered List (numbered styles) ................ -->
+
+<!ENTITY % ol.element  "INCLUDE" >
+<![%ol.element;[
+<!ENTITY % ol.content  "( %li.qname; )+" >
+<!ELEMENT %ol.qname;  %ol.content; >
+<!-- end of ol.element -->]]>
+
+<!ENTITY % ol.attlist  "INCLUDE" >
+<![%ol.attlist;[
+<!ATTLIST %ol.qname;
+      %Common.attrib;
+>
+<!-- end of ol.attlist -->]]>
+
+<!-- ul: Unordered List (bullet styles) ................ -->
+
+<!ENTITY % ul.element  "INCLUDE" >
+<![%ul.element;[
+<!ENTITY % ul.content  "( %li.qname; )+" >
+<!ELEMENT %ul.qname;  %ul.content; >
+<!-- end of ul.element -->]]>
+
+<!ENTITY % ul.attlist  "INCLUDE" >
+<![%ul.attlist;[
+<!ATTLIST %ul.qname;
+      %Common.attrib;
+>
+<!-- end of ul.attlist -->]]>
+
+<!-- li: List Item ..................................... -->
+
+<!ENTITY % li.element  "INCLUDE" >
+<![%li.element;[
+<!ENTITY % li.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ELEMENT %li.qname;  %li.content; >
+<!-- end of li.element -->]]>
+
+<!ENTITY % li.attlist  "INCLUDE" >
+<![%li.attlist;[
+<!ATTLIST %li.qname;
+      %Common.attrib;
+>
+<!-- end of li.attlist -->]]>
+
+<!-- end of xhtml-list-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-meta-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-meta-1.mod
new file mode 100644
index 0000000..24a0b22
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-meta-1.mod
@@ -0,0 +1,47 @@
+<!-- ...................................................................... -->
+<!-- XHTML Document Metainformation Module  ............................... -->
+<!-- file: xhtml-meta-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-meta-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-meta-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Meta Information
+
+        meta
+
+     This module declares the meta element type and its attributes,
+     used to provide declarative document metainformation.
+-->
+
+<!-- meta: Generic Metainformation ..................... -->
+
+<!ENTITY % meta.element  "INCLUDE" >
+<![%meta.element;[
+<!ENTITY % meta.content  "EMPTY" >
+<!ENTITY % meta.qname  "meta" >
+<!ELEMENT %meta.qname;  %meta.content; >
+<!-- end of meta.element -->]]>
+
+<!ENTITY % meta.attlist  "INCLUDE" >
+<![%meta.attlist;[
+<!ATTLIST %meta.qname;
+      %XHTML.xmlns.attrib;
+      %I18n.attrib;
+      http-equiv   NMTOKEN                  #IMPLIED
+      name         NMTOKEN                  #IMPLIED
+      content      CDATA                    #REQUIRED
+      scheme       CDATA                    #IMPLIED
+>
+<!-- end of meta.attlist -->]]>
+
+<!-- end of xhtml-meta-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-object-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-object-1.mod
new file mode 100644
index 0000000..0d14cc5
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-object-1.mod
@@ -0,0 +1,60 @@
+<!-- ...................................................................... -->
+<!-- XHTML Embedded Object Module  ........................................ -->
+<!-- file: xhtml-object-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-object-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Embedded Object 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-object-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Embedded Objects
+
+        object
+
+     This module declares the object element type and its attributes, used
+     to embed external objects as part of XHTML pages. In the document,
+     place param elements prior to other content within the object element.
+
+     Note that use of this module requires instantiation of the Param
+     Element Module.
+-->
+
+<!-- object: Generic Embedded Object ................... -->
+
+<!ENTITY % object.element  "INCLUDE" >
+<![%object.element;[
+<!ENTITY % object.content
+     "( #PCDATA | %Flow.mix; | %param.qname; )*"
+>
+<!ENTITY % object.qname  "object" >
+<!ELEMENT %object.qname;  %object.content; >
+<!-- end of object.element -->]]>
+
+<!ENTITY % object.attlist  "INCLUDE" >
+<![%object.attlist;[
+<!ATTLIST %object.qname;
+      %Common.attrib;
+      declare      ( declare )              #IMPLIED
+      classid      %URI.datatype;           #IMPLIED
+      codebase     %URI.datatype;           #IMPLIED
+      data         %URI.datatype;           #IMPLIED
+      type         %ContentType.datatype;   #IMPLIED
+      codetype     %ContentType.datatype;   #IMPLIED
+      archive      %URIs.datatype;          #IMPLIED
+      standby      %Text.datatype;          #IMPLIED
+      height       %Length.datatype;        #IMPLIED
+      width        %Length.datatype;        #IMPLIED
+      name         CDATA                    #IMPLIED
+      tabindex     %Number.datatype;        #IMPLIED
+>
+<!-- end of object.attlist -->]]>
+
+<!-- end of xhtml-object-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-param-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-param-1.mod
new file mode 100644
index 0000000..c101bed
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-param-1.mod
@@ -0,0 +1,48 @@
+<!-- ...................................................................... -->
+<!-- XHTML Param Element Module  ..................................... -->
+<!-- file: xhtml-param-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-param-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Param Element 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-param-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Parameters for Java Applets and Embedded Objects
+
+        param
+
+     This module provides declarations for the param element,
+     used to provide named property values for the applet
+     and object elements.
+-->
+
+<!-- param: Named Property Value ....................... -->
+
+<!ENTITY % param.element  "INCLUDE" >
+<![%param.element;[
+<!ENTITY % param.content  "EMPTY" >
+<!ENTITY % param.qname  "param" >
+<!ELEMENT %param.qname;  %param.content; >
+<!-- end of param.element -->]]>
+
+<!ENTITY % param.attlist  "INCLUDE" >
+<![%param.attlist;[
+<!ATTLIST %param.qname;
+      %XHTML.xmlns.attrib;
+      %id.attrib;
+      name         CDATA                    #REQUIRED
+      value        CDATA                    #IMPLIED
+      valuetype    ( data | ref | object )  'data'
+      type         %ContentType.datatype;   #IMPLIED
+>
+<!-- end of param.attlist -->]]>
+
+<!-- end of xhtml-param-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-pres-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-pres-1.mod
new file mode 100644
index 0000000..6a2f34d
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-pres-1.mod
@@ -0,0 +1,38 @@
+<!-- ...................................................................... -->
+<!-- XHTML Presentation Module ............................................ -->
+<!-- file: xhtml-pres-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-pres-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Presentation 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-pres-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Presentational Elements
+
+     This module defines elements and their attributes for
+     simple presentation-related markup.
+-->
+
+<!ENTITY % xhtml-inlpres.module "INCLUDE" >
+<![%xhtml-inlpres.module;[
+<!ENTITY % xhtml-inlpres.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN"
+            "xhtml-inlpres-1.mod" >
+%xhtml-inlpres.mod;]]>
+
+<!ENTITY % xhtml-blkpres.module "INCLUDE" >
+<![%xhtml-blkpres.module;[
+<!ENTITY % xhtml-blkpres.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Block Presentation 1.0//EN"
+            "xhtml-blkpres-1.mod" >
+%xhtml-blkpres.mod;]]>
+
+<!-- end of xhtml-pres-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-qname-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-qname-1.mod
new file mode 100644
index 0000000..c7586a5
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-qname-1.mod
@@ -0,0 +1,318 @@
+<!-- ....................................................................... -->
+<!-- XHTML Qname Module  ................................................... -->
+<!-- file: xhtml-qname-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-qname-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML Qualified Names 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-qname-1.mod"
+
+     Revisions:
+	   #2000-10-22: added qname declarations for ruby elements
+     ....................................................................... -->
+
+<!-- XHTML Qname (Qualified Name) Module
+
+     This module is contained in two parts, labeled Section 'A' and 'B':
+
+       Section A declares parameter entities to support namespace-
+       qualified names, namespace declarations, and name prefixing
+       for XHTML and extensions.
+
+       Section B declares parameter entities used to provide
+       namespace-qualified names for all XHTML element types:
+
+         %applet.qname;   the xmlns-qualified name for <applet>
+         %base.qname;     the xmlns-qualified name for <base>
+         ...
+
+     XHTML extensions would create a module similar to this one.
+     Included in the XHTML distribution is a template module
+     ('template-qname-1.mod') suitable for this purpose.
+-->
+
+<!-- Section A: XHTML XML Namespace Framework :::::::::::::::::::: -->
+
+<!-- 1. Declare a %XHTML.prefixed; conditional section keyword, used
+        to activate namespace prefixing. The default value should
+        inherit '%NS.prefixed;' from the DTD driver, so that unless
+        overridden, the default behaviour follows the overall DTD
+        prefixing scheme.
+-->
+<!ENTITY % NS.prefixed "IGNORE" >
+<!ENTITY % XHTML.prefixed "%NS.prefixed;" >
+
+<!-- By default, we always permit XHTML attribute collections to have
+     namespace-qualified prefixes as well.
+-->
+<!ENTITY % XHTML.global.attrs.prefixed "INCLUDE" >
+<!-- By default, we allow the XML Schema attributes on the root
+     element.
+-->
+<!ENTITY % XHTML.xsi.attrs "INCLUDE" >
+
+<!-- 2. Declare a parameter entity (eg., %XHTML.xmlns;) containing
+        the URI reference used to identify the XHTML namespace:
+-->
+<!ENTITY % XHTML.xmlns  "http://www.w3.org/1999/xhtml" >
+
+<!-- 3. Declare parameter entities (eg., %XHTML.prefix;) containing
+        the default namespace prefix string(s) to use when prefixing
+        is enabled. This may be overridden in the DTD driver or the
+        internal subset of an document instance. If no default prefix
+        is desired, this may be declared as an empty string.
+
+     NOTE: As specified in [XMLNAMES], the namespace prefix serves
+     as a proxy for the URI reference, and is not in itself significant.
+-->
+<!ENTITY % XHTML.prefix  "xhtml" >
+
+<!-- 4. Declare parameter entities (eg., %XHTML.pfx;) containing the
+        colonized prefix(es) (eg., '%XHTML.prefix;:') used when
+        prefixing is active, an empty string when it is not.
+-->
+<![%XHTML.prefixed;[
+<!ENTITY % XHTML.pfx  "%XHTML.prefix;:" >
+]]>
+<!ENTITY % XHTML.pfx  "" >
+
+<!-- declare qualified name extensions here ............ -->
+<!ENTITY % xhtml-qname-extra.mod "" >
+%xhtml-qname-extra.mod;
+
+<!-- 5. The parameter entity %XHTML.xmlns.extra.attrib; may be
+        redeclared to contain any non-XHTML namespace declaration
+        attributes for namespaces embedded in XHTML. The default
+        is an empty string.  XLink should be included here if used
+        in the DTD.
+-->
+<!ENTITY % XHTML.xmlns.extra.attrib "" >
+
+<!-- The remainder of Section A is only followed in XHTML, not extensions. -->
+
+<!-- Declare a parameter entity %NS.decl.attrib; containing
+     all XML Namespace declarations used in the DTD, plus the
+     xmlns declaration for XHTML, its form dependent on whether
+     prefixing is active.
+-->
+<!ENTITY % XHTML.xmlns.attrib.prefixed
+     "xmlns:%XHTML.prefix;  %URI.datatype;   #FIXED '%XHTML.xmlns;'"
+>
+<![%XHTML.prefixed;[
+<!ENTITY % NS.decl.attrib
+     "%XHTML.xmlns.attrib.prefixed;
+      %XHTML.xmlns.extra.attrib;"
+>
+]]>
+<!ENTITY % NS.decl.attrib
+     "%XHTML.xmlns.extra.attrib;"
+>
+
+<!-- Declare a parameter entity %XSI.prefix as a prefix to use for XML
+     Schema Instance attributes.
+-->
+<!ENTITY % XSI.prefix "xsi" >
+
+<!ENTITY % XSI.xmlns "http://www.w3.org/2001/XMLSchema-instance" >
+
+<!-- Declare a parameter entity %XSI.xmlns.attrib as support for the
+     schemaLocation attribute, since this is legal throughout the DTD.
+-->
+<!ENTITY % XSI.xmlns.attrib
+     "xmlns:%XSI.prefix;  %URI.datatype;   #FIXED '%XSI.xmlns;'" >
+
+<!-- This is a placeholder for future XLink support.
+-->
+<!ENTITY % XLINK.xmlns.attrib "" >
+
+<!-- This is the attribute for the XML Schema namespace - XHTML
+     Modularization is also expressed in XML Schema, and it needs to
+	 be legal to declare the XML Schema namespace and the
+	 schemaLocation attribute on the root element of XHTML family
+	 documents.
+-->
+<![%XHTML.xsi.attrs;[
+<!ENTITY % XSI.prefix "xsi" >
+<!ENTITY % XSI.pfx "%XSI.prefix;:" >
+<!ENTITY % XSI.xmlns "http://www.w3.org/2001/XMLSchema-instance" >
+
+<!ENTITY % XSI.xmlns.attrib
+     "xmlns:%XSI.prefix;  %URI.datatype;    #FIXED '%XSI.xmlns;'"
+>
+]]>
+<!ENTITY % XSI.prefix "" >
+<!ENTITY % XSI.pfx "" >
+<!ENTITY % XSI.xmlns.attrib "" >
+
+
+<!-- Declare a parameter entity %NS.decl.attrib; containing all
+     XML namespace declaration attributes used by XHTML, including
+     a default xmlns attribute when prefixing is inactive.
+-->
+<![%XHTML.prefixed;[
+<!ENTITY % XHTML.xmlns.attrib
+     "%NS.decl.attrib;
+      %XSI.xmlns.attrib;
+      %XLINK.xmlns.attrib;"
+>
+]]>
+<!ENTITY % XHTML.xmlns.attrib
+     "xmlns        %URI.datatype;           #FIXED '%XHTML.xmlns;'
+      %NS.decl.attrib;
+      %XSI.xmlns.attrib;
+      %XLINK.xmlns.attrib;"
+>
+
+<!-- placeholder for qualified name redeclarations -->
+<!ENTITY % xhtml-qname.redecl "" >
+%xhtml-qname.redecl;
+
+<!-- Section B: XHTML Qualified Names ::::::::::::::::::::::::::::: -->
+
+<!-- 6. This section declares parameter entities used to provide
+        namespace-qualified names for all XHTML element types.
+-->
+
+<!-- module:  xhtml-applet-1.mod -->
+<!ENTITY % applet.qname  "%XHTML.pfx;applet" >
+
+<!-- module:  xhtml-base-1.mod -->
+<!ENTITY % base.qname    "%XHTML.pfx;base" >
+
+<!-- module:  xhtml-bdo-1.mod -->
+<!ENTITY % bdo.qname     "%XHTML.pfx;bdo" >
+
+<!-- module:  xhtml-blkphras-1.mod -->
+<!ENTITY % address.qname "%XHTML.pfx;address" >
+<!ENTITY % blockquote.qname  "%XHTML.pfx;blockquote" >
+<!ENTITY % pre.qname     "%XHTML.pfx;pre" >
+<!ENTITY % h1.qname      "%XHTML.pfx;h1" >
+<!ENTITY % h2.qname      "%XHTML.pfx;h2" >
+<!ENTITY % h3.qname      "%XHTML.pfx;h3" >
+<!ENTITY % h4.qname      "%XHTML.pfx;h4" >
+<!ENTITY % h5.qname      "%XHTML.pfx;h5" >
+<!ENTITY % h6.qname      "%XHTML.pfx;h6" >
+
+<!-- module:  xhtml-blkpres-1.mod -->
+<!ENTITY % hr.qname      "%XHTML.pfx;hr" >
+
+<!-- module:  xhtml-blkstruct-1.mod -->
+<!ENTITY % div.qname     "%XHTML.pfx;div" >
+<!ENTITY % p.qname       "%XHTML.pfx;p" >
+
+<!-- module:  xhtml-edit-1.mod -->
+<!ENTITY % ins.qname     "%XHTML.pfx;ins" >
+<!ENTITY % del.qname     "%XHTML.pfx;del" >
+
+<!-- module:  xhtml-form-1.mod -->
+<!ENTITY % form.qname    "%XHTML.pfx;form" >
+<!ENTITY % label.qname   "%XHTML.pfx;label" >
+<!ENTITY % input.qname   "%XHTML.pfx;input" >
+<!ENTITY % select.qname  "%XHTML.pfx;select" >
+<!ENTITY % optgroup.qname  "%XHTML.pfx;optgroup" >
+<!ENTITY % option.qname  "%XHTML.pfx;option" >
+<!ENTITY % textarea.qname  "%XHTML.pfx;textarea" >
+<!ENTITY % fieldset.qname  "%XHTML.pfx;fieldset" >
+<!ENTITY % legend.qname  "%XHTML.pfx;legend" >
+<!ENTITY % button.qname  "%XHTML.pfx;button" >
+
+<!-- module:  xhtml-hypertext-1.mod -->
+<!ENTITY % a.qname       "%XHTML.pfx;a" >
+
+<!-- module:  xhtml-image-1.mod -->
+<!ENTITY % img.qname     "%XHTML.pfx;img" >
+
+<!-- module:  xhtml-inlphras-1.mod -->
+<!ENTITY % abbr.qname    "%XHTML.pfx;abbr" >
+<!ENTITY % acronym.qname "%XHTML.pfx;acronym" >
+<!ENTITY % cite.qname    "%XHTML.pfx;cite" >
+<!ENTITY % code.qname    "%XHTML.pfx;code" >
+<!ENTITY % dfn.qname     "%XHTML.pfx;dfn" >
+<!ENTITY % em.qname      "%XHTML.pfx;em" >
+<!ENTITY % kbd.qname     "%XHTML.pfx;kbd" >
+<!ENTITY % q.qname       "%XHTML.pfx;q" >
+<!ENTITY % samp.qname    "%XHTML.pfx;samp" >
+<!ENTITY % strong.qname  "%XHTML.pfx;strong" >
+<!ENTITY % var.qname     "%XHTML.pfx;var" >
+
+<!-- module:  xhtml-inlpres-1.mod -->
+<!ENTITY % b.qname       "%XHTML.pfx;b" >
+<!ENTITY % big.qname     "%XHTML.pfx;big" >
+<!ENTITY % i.qname       "%XHTML.pfx;i" >
+<!ENTITY % small.qname   "%XHTML.pfx;small" >
+<!ENTITY % sub.qname     "%XHTML.pfx;sub" >
+<!ENTITY % sup.qname     "%XHTML.pfx;sup" >
+<!ENTITY % tt.qname      "%XHTML.pfx;tt" >
+
+<!-- module:  xhtml-inlstruct-1.mod -->
+<!ENTITY % br.qname      "%XHTML.pfx;br" >
+<!ENTITY % span.qname    "%XHTML.pfx;span" >
+
+<!-- module:  xhtml-ismap-1.mod (also csismap, ssismap) -->
+<!ENTITY % map.qname     "%XHTML.pfx;map" >
+<!ENTITY % area.qname    "%XHTML.pfx;area" >
+
+<!-- module:  xhtml-link-1.mod -->
+<!ENTITY % link.qname    "%XHTML.pfx;link" >
+
+<!-- module:  xhtml-list-1.mod -->
+<!ENTITY % dl.qname      "%XHTML.pfx;dl" >
+<!ENTITY % dt.qname      "%XHTML.pfx;dt" >
+<!ENTITY % dd.qname      "%XHTML.pfx;dd" >
+<!ENTITY % ol.qname      "%XHTML.pfx;ol" >
+<!ENTITY % ul.qname      "%XHTML.pfx;ul" >
+<!ENTITY % li.qname      "%XHTML.pfx;li" >
+
+<!-- module:  xhtml-meta-1.mod -->
+<!ENTITY % meta.qname    "%XHTML.pfx;meta" >
+
+<!-- module:  xhtml-param-1.mod -->
+<!ENTITY % param.qname   "%XHTML.pfx;param" >
+
+<!-- module:  xhtml-object-1.mod -->
+<!ENTITY % object.qname  "%XHTML.pfx;object" >
+
+<!-- module:  xhtml-script-1.mod -->
+<!ENTITY % script.qname  "%XHTML.pfx;script" >
+<!ENTITY % noscript.qname  "%XHTML.pfx;noscript" >
+
+<!-- module:  xhtml-struct-1.mod -->
+<!ENTITY % html.qname    "%XHTML.pfx;html" >
+<!ENTITY % head.qname    "%XHTML.pfx;head" >
+<!ENTITY % title.qname   "%XHTML.pfx;title" >
+<!ENTITY % body.qname    "%XHTML.pfx;body" >
+
+<!-- module:  xhtml-style-1.mod -->
+<!ENTITY % style.qname   "%XHTML.pfx;style" >
+
+<!-- module:  xhtml-table-1.mod -->
+<!ENTITY % table.qname   "%XHTML.pfx;table" >
+<!ENTITY % caption.qname "%XHTML.pfx;caption" >
+<!ENTITY % thead.qname   "%XHTML.pfx;thead" >
+<!ENTITY % tfoot.qname   "%XHTML.pfx;tfoot" >
+<!ENTITY % tbody.qname   "%XHTML.pfx;tbody" >
+<!ENTITY % colgroup.qname  "%XHTML.pfx;colgroup" >
+<!ENTITY % col.qname     "%XHTML.pfx;col" >
+<!ENTITY % tr.qname      "%XHTML.pfx;tr" >
+<!ENTITY % th.qname      "%XHTML.pfx;th" >
+<!ENTITY % td.qname      "%XHTML.pfx;td" >
+
+<!-- module:  xhtml-ruby-1.mod -->
+
+<!ENTITY % ruby.qname    "%XHTML.pfx;ruby" >
+<!ENTITY % rbc.qname     "%XHTML.pfx;rbc" >
+<!ENTITY % rtc.qname     "%XHTML.pfx;rtc" >
+<!ENTITY % rb.qname      "%XHTML.pfx;rb" >
+<!ENTITY % rt.qname      "%XHTML.pfx;rt" >
+<!ENTITY % rp.qname      "%XHTML.pfx;rp" >
+
+<!-- Provisional XHTML 2.0 Qualified Names  ...................... -->
+
+<!-- module:  xhtml-image-2.mod -->
+<!ENTITY % alt.qname     "%XHTML.pfx;alt" >
+
+<!-- end of xhtml-qname-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-ruby-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-ruby-1.mod
new file mode 100644
index 0000000..a44bb3f
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-ruby-1.mod
@@ -0,0 +1,242 @@
+<!-- ...................................................................... -->
+<!-- XHTML Ruby Module .................................................... -->
+<!-- file: xhtml-ruby-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1999-2001 W3C (MIT, INRIA, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-ruby-1.mod,v 4.0 2001/04/03 23:14:33 altheim Exp $
+
+     This module is based on the W3C Ruby Annotation Specification:
+
+        http://www.w3.org/TR/ruby
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Ruby 1.0//EN"
+       SYSTEM "http://www.w3.org/TR/ruby/xhtml-ruby-1.mod"
+
+     ...................................................................... -->
+
+<!-- Ruby Elements
+
+        ruby, rbc, rtc, rb, rt, rp
+
+     This module declares the elements and their attributes used to
+     support ruby annotation markup.
+-->
+
+<!-- declare qualified element type names:
+-->
+<!ENTITY % ruby.qname  "ruby" >
+<!ENTITY % rbc.qname  "rbc" >
+<!ENTITY % rtc.qname  "rtc" >
+<!ENTITY % rb.qname  "rb" >
+<!ENTITY % rt.qname  "rt" >
+<!ENTITY % rp.qname  "rp" >
+
+<!-- rp fallback is included by default.
+-->
+<!ENTITY % Ruby.fallback "INCLUDE" >
+<!ENTITY % Ruby.fallback.mandatory "IGNORE" >
+
+<!-- Complex ruby is included by default; it may be 
+     overridden by other modules to ignore it.
+-->
+<!ENTITY % Ruby.complex "INCLUDE" >
+
+<!-- Fragments for the content model of the ruby element -->
+<![%Ruby.fallback;[
+<![%Ruby.fallback.mandatory;[
+<!ENTITY % Ruby.content.simple 
+     "( %rb.qname;, %rp.qname;, %rt.qname;, %rp.qname; )"
+>
+]]>
+<!ENTITY % Ruby.content.simple 
+     "( %rb.qname;, ( %rt.qname; | ( %rp.qname;, %rt.qname;, %rp.qname; ) ) )"
+>
+]]>
+<!ENTITY % Ruby.content.simple "( %rb.qname;, %rt.qname; )" >
+
+<![%Ruby.complex;[
+<!ENTITY % Ruby.content.complex 
+     "| ( %rbc.qname;, %rtc.qname;, %rtc.qname;? )"
+>
+]]>
+<!ENTITY % Ruby.content.complex "" >
+
+<!-- Content models of the rb and the rt elements are intended to
+     allow other inline-level elements of its parent markup language,
+     but it should not include ruby descendent elements. The following
+     parameter entity %NoRuby.content; can be used to redefine
+     those content models with minimum effort.  It's defined as
+     '( #PCDATA )' by default.
+-->
+<!ENTITY % NoRuby.content "( #PCDATA )" >
+
+<!-- one or more digits (NUMBER) -->
+<!ENTITY % Number.datatype "CDATA" >
+
+<!-- ruby element ...................................... -->
+
+<!ENTITY % ruby.element  "INCLUDE" >
+<![%ruby.element;[
+<!ENTITY % ruby.content
+     "( %Ruby.content.simple; %Ruby.content.complex; )"
+>
+<!ELEMENT %ruby.qname;  %ruby.content; >
+<!-- end of ruby.element -->]]>
+
+<![%Ruby.complex;[
+<!-- rbc (ruby base component) element ................. -->
+
+<!ENTITY % rbc.element  "INCLUDE" >
+<![%rbc.element;[
+<!ENTITY % rbc.content
+     "(%rb.qname;)+"
+>
+<!ELEMENT %rbc.qname;  %rbc.content; >
+<!-- end of rbc.element -->]]>
+
+<!-- rtc (ruby text component) element ................. -->
+
+<!ENTITY % rtc.element  "INCLUDE" >
+<![%rtc.element;[
+<!ENTITY % rtc.content
+     "(%rt.qname;)+"
+>
+<!ELEMENT %rtc.qname;  %rtc.content; >
+<!-- end of rtc.element -->]]>
+]]>
+
+<!-- rb (ruby base) element ............................ -->
+
+<!ENTITY % rb.element  "INCLUDE" >
+<![%rb.element;[
+<!-- %rb.content; uses %NoRuby.content; as its content model,
+     which is '( #PCDATA )' by default. It may be overridden
+     by other modules to allow other inline-level elements
+     of its parent markup language, but it should not include
+     ruby descendent elements.
+-->
+<!ENTITY % rb.content "%NoRuby.content;" >
+<!ELEMENT %rb.qname;  %rb.content; >
+<!-- end of rb.element -->]]>
+
+<!-- rt (ruby text) element ............................ -->
+
+<!ENTITY % rt.element  "INCLUDE" >
+<![%rt.element;[
+<!-- %rt.content; uses %NoRuby.content; as its content model,
+     which is '( #PCDATA )' by default. It may be overridden
+     by other modules to allow other inline-level elements
+     of its parent markup language, but it should not include
+     ruby descendent elements.
+-->
+<!ENTITY % rt.content "%NoRuby.content;" >
+
+<!ELEMENT %rt.qname;  %rt.content; >
+<!-- end of rt.element -->]]>
+
+<!-- rbspan attribute is used for complex ruby only ...... -->
+<![%Ruby.complex;[
+<!ENTITY % rt.attlist  "INCLUDE" >
+<![%rt.attlist;[
+<!ATTLIST %rt.qname;
+      rbspan         %Number.datatype;      "1"
+>
+<!-- end of rt.attlist -->]]>
+]]>
+
+<!-- rp (ruby parenthesis) element ..................... -->
+
+<![%Ruby.fallback;[
+<!ENTITY % rp.element  "INCLUDE" >
+<![%rp.element;[
+<!ENTITY % rp.content
+     "( #PCDATA )"
+>
+<!ELEMENT %rp.qname;  %rp.content; >
+<!-- end of rp.element -->]]>
+]]>
+
+<!-- Ruby Common Attributes
+
+     The following optional ATTLIST declarations provide an easy way
+     to define common attributes for ruby elements.  These declarations
+     are ignored by default.
+
+     Ruby elements are intended to have common attributes of its
+     parent markup language.  For example, if a markup language defines
+     common attributes as a parameter entity %attrs;, you may add
+     those attributes by just declaring the following parameter entities
+
+         <!ENTITY % Ruby.common.attlists  "INCLUDE" >
+         <!ENTITY % Ruby.common.attrib  "%attrs;" >
+
+     before including the Ruby module.
+-->
+
+<!ENTITY % Ruby.common.attlists  "IGNORE" >
+<![%Ruby.common.attlists;[
+<!ENTITY % Ruby.common.attrib  "" >
+
+<!-- common attributes for ruby ........................ -->
+
+<!ENTITY % Ruby.common.attlist  "INCLUDE" >
+<![%Ruby.common.attlist;[
+<!ATTLIST %ruby.qname;
+      %Ruby.common.attrib;
+>
+<!-- end of Ruby.common.attlist -->]]>
+
+<![%Ruby.complex;[
+<!-- common attributes for rbc ......................... -->
+
+<!ENTITY % Rbc.common.attlist  "INCLUDE" >
+<![%Rbc.common.attlist;[
+<!ATTLIST %rbc.qname;
+      %Ruby.common.attrib;
+>
+<!-- end of Rbc.common.attlist -->]]>
+
+<!-- common attributes for rtc ......................... -->
+
+<!ENTITY % Rtc.common.attlist  "INCLUDE" >
+<![%Rtc.common.attlist;[
+<!ATTLIST %rtc.qname;
+      %Ruby.common.attrib;
+>
+<!-- end of Rtc.common.attlist -->]]>
+]]>
+
+<!-- common attributes for rb .......................... -->
+
+<!ENTITY % Rb.common.attlist  "INCLUDE" >
+<![%Rb.common.attlist;[
+<!ATTLIST %rb.qname;
+      %Ruby.common.attrib;
+>
+<!-- end of Rb.common.attlist -->]]>
+
+<!-- common attributes for rt .......................... -->
+
+<!ENTITY % Rt.common.attlist  "INCLUDE" >
+<![%Rt.common.attlist;[
+<!ATTLIST %rt.qname;
+      %Ruby.common.attrib;
+>
+<!-- end of Rt.common.attlist -->]]>
+
+<![%Ruby.fallback;[
+<!-- common attributes for rp .......................... -->
+
+<!ENTITY % Rp.common.attlist  "INCLUDE" >
+<![%Rp.common.attlist;[
+<!ATTLIST %rp.qname;
+      %Ruby.common.attrib;
+>
+<!-- end of Rp.common.attlist -->]]>
+]]>
+]]>
+
+<!-- end of xhtml-ruby-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-script-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-script-1.mod
new file mode 100644
index 0000000..aa702f1
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-script-1.mod
@@ -0,0 +1,67 @@
+<!-- ...................................................................... -->
+<!-- XHTML Document Scripting Module  ..................................... -->
+<!-- file: xhtml-script-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-script-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Scripting 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-script-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Scripting
+
+        script, noscript
+
+     This module declares element types and attributes used to provide
+     support for executable scripts as well as an alternate content
+     container where scripts are not supported.
+-->
+
+<!-- script: Scripting Statement ....................... -->
+
+<!ENTITY % script.element  "INCLUDE" >
+<![%script.element;[
+<!ENTITY % script.content  "( #PCDATA )" >
+<!ENTITY % script.qname  "script" >
+<!ELEMENT %script.qname;  %script.content; >
+<!-- end of script.element -->]]>
+
+<!ENTITY % script.attlist  "INCLUDE" >
+<![%script.attlist;[
+<!ATTLIST %script.qname;
+      %XHTML.xmlns.attrib;
+	  %id.attrib;
+      xml:space    ( preserve )             #FIXED 'preserve'
+      charset      %Charset.datatype;       #IMPLIED
+      type         %ContentType.datatype;   #REQUIRED
+      src          %URI.datatype;           #IMPLIED
+      defer        ( defer )                #IMPLIED
+>
+<!-- end of script.attlist -->]]>
+
+<!-- noscript: No-Script Alternate Content ............. -->
+
+<!ENTITY % noscript.element  "INCLUDE" >
+<![%noscript.element;[
+<!ENTITY % noscript.content
+     "( %Block.mix; )+"
+>
+<!ENTITY % noscript.qname  "noscript" >
+<!ELEMENT %noscript.qname;  %noscript.content; >
+<!-- end of noscript.element -->]]>
+
+<!ENTITY % noscript.attlist  "INCLUDE" >
+<![%noscript.attlist;[
+<!ATTLIST %noscript.qname;
+      %Common.attrib;
+>
+<!-- end of noscript.attlist -->]]>
+
+<!-- end of xhtml-script-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-special.ent b/xml/impl/resources/standardSchemas/xhtml11/xhtml-special.ent
new file mode 100644
index 0000000..0af4654
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-special.ent
@@ -0,0 +1,82 @@
+<!-- ...................................................................... -->
+<!-- XML-compatible ISO Special Character Entity Set for XHTML ............ -->
+<!-- file: xhtml-special.ent
+
+     Typical invocation:
+
+       <!ENTITY % xhtml-special
+           PUBLIC "-//W3C//ENTITIES Special for XHTML//EN"
+                  "xhtml-special.ent" >
+       %xhtml-special;
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES Special for XHTML//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-special.ent"
+
+     Revision:  $Id: xhtml-special.ent,v 4.1 2001/04/10 09:34:14 altheim Exp $ SMI
+
+     Portions (C) International Organization for Standardization 1986:
+     Permission to copy in any form is granted for use with conforming
+     SGML systems and applications as defined in ISO 8879, provided
+     this notice is included in all copies.
+
+     Revisions:
+2000-10-28: added &apos; and altered XML Predefined Entities for compatibility
+-->
+
+<!-- Relevant ISO entity set is given unless names are newly introduced.
+     New names (i.e., not in ISO 8879 [SGML] list) do not clash with
+     any existing ISO 8879 entity names. ISO 10646 [ISO10646] character
+     numbers are given for each character, in hex. Entity values are
+     decimal conversions of the ISO 10646 values and refer to the
+     document character set. Names are Unicode [UNICODE] names.
+-->
+
+<!-- C0 Controls and Basic Latin -->
+<!ENTITY lt      "&#38;#60;" ><!-- less-than sign, U+003C ISOnum -->
+<!ENTITY gt      "&#62;" ><!-- greater-than sign, U+003E ISOnum -->
+<!ENTITY amp     "&#38;#38;" ><!-- ampersand, U+0026 ISOnum -->
+<!ENTITY apos    "&#39;" ><!-- The Apostrophe (Apostrophe Quote, APL Quote), U+0027 ISOnum -->
+<!ENTITY quot    "&#34;" ><!-- quotation mark (Quote Double), U+0022 ISOnum -->
+
+<!-- Latin Extended-A -->
+<!ENTITY OElig   "&#338;" ><!-- latin capital ligature OE, U+0152 ISOlat2 -->
+<!ENTITY oelig   "&#339;" ><!-- latin small ligature oe, U+0153 ISOlat2 -->
+
+<!-- ligature is a misnomer, this is a separate character in some languages -->
+<!ENTITY Scaron  "&#352;" ><!-- latin capital letter S with caron, U+0160 ISOlat2 -->
+<!ENTITY scaron  "&#353;" ><!-- latin small letter s with caron, U+0161 ISOlat2 -->
+<!ENTITY Yuml    "&#376;" ><!-- latin capital letter Y with diaeresis, U+0178 ISOlat2 -->
+
+<!-- Spacing Modifier Letters -->
+<!ENTITY circ    "&#710;" ><!-- modifier letter circumflex accent, U+02C6 ISOpub -->
+<!ENTITY tilde   "&#732;" ><!-- small tilde, U+02DC ISOdia -->
+
+<!-- General Punctuation -->
+<!ENTITY ensp    "&#8194;" ><!-- en space, U+2002 ISOpub -->
+<!ENTITY emsp    "&#8195;" ><!-- em space, U+2003 ISOpub -->
+<!ENTITY thinsp  "&#8201;" ><!-- thin space, U+2009 ISOpub -->
+<!ENTITY zwnj    "&#8204;" ><!-- zero width non-joiner, U+200C NEW RFC 2070 -->
+<!ENTITY zwj     "&#8205;" ><!-- zero width joiner, U+200D NEW RFC 2070 -->
+<!ENTITY lrm     "&#8206;" ><!-- left-to-right mark, U+200E NEW RFC 2070 -->
+<!ENTITY rlm     "&#8207;" ><!-- right-to-left mark, U+200F NEW RFC 2070 -->
+<!ENTITY ndash   "&#8211;" ><!-- en dash, U+2013 ISOpub -->
+<!ENTITY mdash   "&#8212;" ><!-- em dash, U+2014 ISOpub -->
+<!ENTITY lsquo   "&#8216;" ><!-- left single quotation mark, U+2018 ISOnum -->
+<!ENTITY rsquo   "&#8217;" ><!-- right single quotation mark, U+2019 ISOnum -->
+<!ENTITY sbquo   "&#8218;" ><!-- single low-9 quotation mark, U+201A NEW -->
+<!ENTITY ldquo   "&#8220;" ><!-- left double quotation mark, U+201C ISOnum -->
+<!ENTITY rdquo   "&#8221;" ><!-- right double quotation mark, U+201D ISOnum -->
+<!ENTITY bdquo   "&#8222;" ><!-- double low-9 quotation mark, U+201E NEW -->
+<!ENTITY dagger  "&#8224;" ><!-- dagger, U+2020 ISOpub -->
+<!ENTITY Dagger  "&#8225;" ><!-- double dagger, U+2021 ISOpub -->
+<!ENTITY permil  "&#8240;" ><!-- per mille sign, U+2030 ISOtech -->
+
+<!-- lsaquo is proposed but not yet ISO standardized -->
+<!ENTITY lsaquo  "&#8249;" ><!-- single left-pointing angle quotation mark, U+2039 ISO proposed -->
+<!-- rsaquo is proposed but not yet ISO standardized -->
+<!ENTITY rsaquo  "&#8250;" ><!-- single right-pointing angle quotation mark, U+203A ISO proposed -->
+<!ENTITY euro    "&#8364;" ><!-- euro sign, U+20AC NEW -->
+
+<!-- end of xhtml-special.ent -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-ssismap-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-ssismap-1.mod
new file mode 100644
index 0000000..4e2b8d7
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-ssismap-1.mod
@@ -0,0 +1,32 @@
+<!-- ...................................................................... -->
+<!-- XHTML Server-side Image Map Module  .................................. -->
+<!-- file: xhtml-ssismap-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-ssismap-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Server-side Image Maps 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-ssismap-1.mod"
+
+     Revisions:
+#2000-10-22: added declaration for 'ismap' on <input>
+     ....................................................................... -->
+
+<!-- Server-side Image Maps
+
+     This adds the 'ismap' attribute to the img and input elements
+     to support server-side processing of a user selection.
+-->
+
+<!ATTLIST %img.qname;
+      ismap        ( ismap )                #IMPLIED
+>
+
+<!ATTLIST %input.qname;
+      ismap        ( ismap )                #IMPLIED
+>
+
+<!-- end of xhtml-ssismap-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-struct-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-struct-1.mod
new file mode 100644
index 0000000..580eb92
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-struct-1.mod
@@ -0,0 +1,136 @@
+<!-- ...................................................................... -->
+<!-- XHTML Structure Module  .............................................. -->
+<!-- file: xhtml-struct-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-struct-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-struct-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Document Structure
+
+        title, head, body, html
+
+     The Structure Module defines the major structural elements and
+     their attributes.
+
+     Note that the content model of the head element type is redeclared
+     when the Base Module is included in the DTD.
+
+     The parameter entity containing the XML namespace URI value used
+     for XHTML is '%XHTML.xmlns;', defined in the Qualified Names module.
+-->
+
+<!-- title: Document Title ............................. -->
+
+<!-- The title element is not considered part of the flow of text.
+     It should be displayed, for example as the page header or
+     window title. Exactly one title is required per document.
+-->
+
+<!ENTITY % title.element  "INCLUDE" >
+<![%title.element;[
+<!ENTITY % title.content  "( #PCDATA )" >
+<!ENTITY % title.qname  "title" >
+<!ELEMENT %title.qname;  %title.content; >
+<!-- end of title.element -->]]>
+
+<!ENTITY % title.attlist  "INCLUDE" >
+<![%title.attlist;[
+<!ATTLIST %title.qname;
+      %XHTML.xmlns.attrib;
+      %I18n.attrib;
+>
+<!-- end of title.attlist -->]]>
+
+<!-- head: Document Head ............................... -->
+
+<!ENTITY % head.element  "INCLUDE" >
+<![%head.element;[
+<!ENTITY % head.content
+    "( %HeadOpts.mix;, %title.qname;, %HeadOpts.mix; )"
+>
+<!ENTITY % head.qname  "head" >
+<!ELEMENT %head.qname;  %head.content; >
+<!-- end of head.element -->]]>
+
+<!ENTITY % head.attlist  "INCLUDE" >
+<![%head.attlist;[
+<!-- reserved for future use with document profiles
+-->
+<!ENTITY % profile.attrib
+     "profile      %URI.datatype;           '%XHTML.profile;'"
+>
+
+<!ATTLIST %head.qname;
+      %XHTML.xmlns.attrib;
+      %I18n.attrib;
+      %profile.attrib;
+      %id.attrib;
+>
+<!-- end of head.attlist -->]]>
+
+<!-- body: Document Body ............................... -->
+
+<!ENTITY % body.element  "INCLUDE" >
+<![%body.element;[
+<!ENTITY % body.content
+     "( %Block.mix; )*"
+>
+<!ENTITY % body.qname  "body" >
+<!ELEMENT %body.qname;  %body.content; >
+<!-- end of body.element -->]]>
+
+<!ENTITY % body.attlist  "INCLUDE" >
+<![%body.attlist;[
+<!ATTLIST %body.qname;
+      %Common.attrib;
+>
+<!-- end of body.attlist -->]]>
+
+<!-- html: XHTML Document Element ...................... -->
+
+<!ENTITY % html.element  "INCLUDE" >
+<![%html.element;[
+<!ENTITY % html.content  "( %head.qname;, %body.qname; )" >
+<!ENTITY % html.qname  "html" >
+<!ELEMENT %html.qname;  %html.content; >
+<!-- end of html.element -->]]>
+
+<![%XHTML.xsi.attrs;[
+<!-- define a parameter for the XSI schemaLocation attribute -->
+<!ENTITY % XSI.schemaLocation.attrib
+     "%XSI.pfx;schemaLocation  %URIs.datatype;    #IMPLIED"
+>
+]]>
+<!ENTITY % XSI.schemaLocation.attrib "">
+
+<!ENTITY % html.attlist  "INCLUDE" >
+<![%html.attlist;[
+<!-- version attribute value defined in driver
+-->
+<!ENTITY % XHTML.version.attrib
+     "version      %FPI.datatype;           #FIXED '%XHTML.version;'"
+>
+
+<!-- see the Qualified Names module for information
+     on how to extend XHTML using XML namespaces
+-->
+<!ATTLIST %html.qname;
+      %XHTML.xmlns.attrib;
+      %XSI.schemaLocation.attrib;
+      %XHTML.version.attrib;
+      %I18n.attrib;
+      %id.attrib;
+>
+<!-- end of html.attlist -->]]>
+
+<!-- end of xhtml-struct-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-style-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-style-1.mod
new file mode 100644
index 0000000..3105b2a
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-style-1.mod
@@ -0,0 +1,48 @@
+<!-- ...................................................................... -->
+<!-- XHTML Document Style Sheet Module  ................................... -->
+<!-- file: xhtml-style-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-style-1.mod,v 4.1 2001/04/05 06:57:40 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//DTD XHTML Style Sheets 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-style-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Style Sheets
+
+        style
+
+     This module declares the style element type and its attributes,
+     used to embed style sheet information in the document head element.
+-->
+
+<!-- style: Style Sheet Information .................... -->
+
+<!ENTITY % style.element  "INCLUDE" >
+<![%style.element;[
+<!ENTITY % style.content  "( #PCDATA )" >
+<!ENTITY % style.qname  "style" >
+<!ELEMENT %style.qname;  %style.content; >
+<!-- end of style.element -->]]>
+
+<!ENTITY % style.attlist  "INCLUDE" >
+<![%style.attlist;[
+<!ATTLIST %style.qname;
+      %XHTML.xmlns.attrib;
+      %id.attrib;
+      %title.attrib;
+      %I18n.attrib;
+      xml:space    ( preserve )             #FIXED 'preserve'
+      type         %ContentType.datatype;   #REQUIRED
+      media        %MediaDesc.datatype;     #IMPLIED
+>
+<!-- end of style.attlist -->]]>
+
+<!-- end of xhtml-style-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-symbol.ent b/xml/impl/resources/standardSchemas/xhtml11/xhtml-symbol.ent
new file mode 100644
index 0000000..e92a1c7
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-symbol.ent
@@ -0,0 +1,204 @@
+<!-- ...................................................................... -->
+<!-- ISO Math, Greek and Symbolic Character Entity Set for XHTML .......... -->
+<!-- file: xhtml-symbol.ent
+
+     Typical invocation:
+
+       <!ENTITY % xhtml-symbol
+           PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN"
+                  "xhtml-symbol.ent" >
+       %xhtml-symbol;
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-symbol.ent"
+
+     Revision:  $Id: xhtml-symbol.ent,v 4.1 2001/04/10 09:34:14 altheim Exp $ SMI
+
+     Portions (C) International Organization for Standardization 1986:
+     Permission to copy in any form is granted for use with conforming
+     SGML systems and applications as defined in ISO 8879, provided
+     this notice is included in all copies.
+-->
+
+<!-- Relevant ISO entity set is given unless names are newly introduced.
+     New names (i.e., not in ISO 8879 [SGML] list) do not clash with
+     any existing ISO 8879 entity names. ISO 10646 [ISO10646] character
+     numbers are given for each character, in hex. Entity values are
+     decimal conversions of the ISO 10646 values and refer to the
+     document character set. Names are Unicode [UNICODE] names.
+-->
+
+<!-- Latin Extended-B -->
+<!ENTITY fnof     "&#402;" ><!-- latin small f with hook = function
+                              = florin, U+0192 ISOtech -->
+
+<!-- Greek -->
+<!ENTITY Alpha    "&#913;" ><!-- greek capital letter alpha, U+0391 -->
+<!ENTITY Beta     "&#914;" ><!-- greek capital letter beta, U+0392 -->
+<!ENTITY Gamma    "&#915;" ><!-- greek capital letter gamma, U+0393 ISOgrk3 -->
+<!ENTITY Delta    "&#916;" ><!-- greek capital letter delta, U+0394 ISOgrk3 -->
+<!ENTITY Epsilon  "&#917;" ><!-- greek capital letter epsilon, U+0395 -->
+<!ENTITY Zeta     "&#918;" ><!-- greek capital letter zeta, U+0396 -->
+<!ENTITY Eta      "&#919;" ><!-- greek capital letter eta, U+0397 -->
+<!ENTITY Theta    "&#920;" ><!-- greek capital letter theta, U+0398 ISOgrk3 -->
+<!ENTITY Iota     "&#921;" ><!-- greek capital letter iota, U+0399 -->
+<!ENTITY Kappa    "&#922;" ><!-- greek capital letter kappa, U+039A -->
+<!ENTITY Lambda   "&#923;" ><!-- greek capital letter lambda, U+039B ISOgrk3 -->
+<!ENTITY Mu       "&#924;" ><!-- greek capital letter mu, U+039C -->
+<!ENTITY Nu       "&#925;" ><!-- greek capital letter nu, U+039D -->
+<!ENTITY Xi       "&#926;" ><!-- greek capital letter xi, U+039E ISOgrk3 -->
+<!ENTITY Omicron  "&#927;" ><!-- greek capital letter omicron, U+039F -->
+<!ENTITY Pi       "&#928;" ><!-- greek capital letter pi, U+03A0 ISOgrk3 -->
+<!ENTITY Rho      "&#929;" ><!-- greek capital letter rho, U+03A1 -->
+<!-- there is no Sigmaf, and no U+03A2 character either -->
+<!ENTITY Sigma    "&#931;" ><!-- greek capital letter sigma, U+03A3 ISOgrk3 -->
+<!ENTITY Tau      "&#932;" ><!-- greek capital letter tau, U+03A4 -->
+<!ENTITY Upsilon  "&#933;" ><!-- greek capital letter upsilon,
+                              U+03A5 ISOgrk3 -->
+<!ENTITY Phi      "&#934;" ><!-- greek capital letter phi, U+03A6 ISOgrk3 -->
+<!ENTITY Chi      "&#935;" ><!-- greek capital letter chi, U+03A7 -->
+<!ENTITY Psi      "&#936;" ><!-- greek capital letter psi, U+03A8 ISOgrk3 -->
+<!ENTITY Omega    "&#937;" ><!-- greek capital letter omega, U+03A9 ISOgrk3 -->
+<!ENTITY alpha    "&#945;" ><!-- greek small letter alpha, U+03B1 ISOgrk3 -->
+<!ENTITY beta     "&#946;" ><!-- greek small letter beta, U+03B2 ISOgrk3 -->
+<!ENTITY gamma    "&#947;" ><!-- greek small letter gamma, U+03B3 ISOgrk3 -->
+<!ENTITY delta    "&#948;" ><!-- greek small letter delta, U+03B4 ISOgrk3 -->
+<!ENTITY epsilon  "&#949;" ><!-- greek small letter epsilon, U+03B5 ISOgrk3 -->
+<!ENTITY zeta     "&#950;" ><!-- greek small letter zeta, U+03B6 ISOgrk3 -->
+<!ENTITY eta      "&#951;" ><!-- greek small letter eta, U+03B7 ISOgrk3 -->
+<!ENTITY theta    "&#952;" ><!-- greek small letter theta, U+03B8 ISOgrk3 -->
+<!ENTITY iota     "&#953;" ><!-- greek small letter iota, U+03B9 ISOgrk3 -->
+<!ENTITY kappa    "&#954;" ><!-- greek small letter kappa, U+03BA ISOgrk3 -->
+<!ENTITY lambda   "&#955;" ><!-- greek small letter lambda, U+03BB ISOgrk3 -->
+<!ENTITY mu       "&#956;" ><!-- greek small letter mu, U+03BC ISOgrk3 -->
+<!ENTITY nu       "&#957;" ><!-- greek small letter nu, U+03BD ISOgrk3 -->
+<!ENTITY xi       "&#958;" ><!-- greek small letter xi, U+03BE ISOgrk3 -->
+<!ENTITY omicron  "&#959;" ><!-- greek small letter omicron, U+03BF NEW -->
+<!ENTITY pi       "&#960;" ><!-- greek small letter pi, U+03C0 ISOgrk3 -->
+<!ENTITY rho      "&#961;" ><!-- greek small letter rho, U+03C1 ISOgrk3 -->
+<!ENTITY sigmaf   "&#962;" ><!-- greek small letter final sigma, U+03C2 ISOgrk3 -->
+<!ENTITY sigma    "&#963;" ><!-- greek small letter sigma, U+03C3 ISOgrk3 -->
+<!ENTITY tau      "&#964;" ><!-- greek small letter tau, U+03C4 ISOgrk3 -->
+<!ENTITY upsilon  "&#965;" ><!-- greek small letter upsilon, U+03C5 ISOgrk3 -->
+<!ENTITY phi      "&#966;" ><!-- greek small letter phi, U+03C6 ISOgrk3 -->
+<!ENTITY chi      "&#967;" ><!-- greek small letter chi, U+03C7 ISOgrk3 -->
+<!ENTITY psi      "&#968;" ><!-- greek small letter psi, U+03C8 ISOgrk3 -->
+<!ENTITY omega    "&#969;" ><!-- greek small letter omega, U+03C9 ISOgrk3 -->
+<!ENTITY thetasym "&#977;" ><!-- greek small letter theta symbol, U+03D1 NEW -->
+<!ENTITY upsih    "&#978;" ><!-- greek upsilon with hook symbol, U+03D2 NEW -->
+<!ENTITY piv      "&#982;" ><!-- greek pi symbol, U+03D6 ISOgrk3 -->
+
+<!-- General Punctuation -->
+<!ENTITY bull     "&#8226;" ><!-- bullet = black small circle, U+2022 ISOpub  -->
+<!-- bullet is NOT the same as bullet operator, U+2219 -->
+<!ENTITY hellip   "&#8230;" ><!-- horizontal ellipsis = three dot leader, U+2026 ISOpub  -->
+<!ENTITY prime    "&#8242;" ><!-- prime = minutes = feet, U+2032 ISOtech -->
+<!ENTITY Prime    "&#8243;" ><!-- double prime = seconds = inches, U+2033 ISOtech -->
+<!ENTITY oline    "&#8254;" ><!-- overline = spacing overscore, U+203E NEW -->
+<!ENTITY frasl    "&#8260;" ><!-- fraction slash, U+2044 NEW -->
+
+<!-- Letterlike Symbols -->
+<!ENTITY weierp   "&#8472;" ><!-- script capital P = power set = Weierstrass p, U+2118 ISOamso -->
+<!ENTITY image    "&#8465;" ><!-- blackletter capital I = imaginary part, U+2111 ISOamso -->
+<!ENTITY real     "&#8476;" ><!-- blackletter capital R = real part symbol, U+211C ISOamso -->
+<!ENTITY trade    "&#8482;" ><!-- trade mark sign, U+2122 ISOnum -->
+<!ENTITY alefsym  "&#8501;" ><!-- alef symbol = first transfinite cardinal, U+2135 NEW -->
+<!-- alef symbol is NOT the same as hebrew letter alef, U+05D0 although
+     the same glyph could be used to depict both characters -->
+
+<!-- Arrows -->
+<!ENTITY larr     "&#8592;" ><!-- leftwards arrow, U+2190 ISOnum -->
+<!ENTITY uarr     "&#8593;" ><!-- upwards arrow, U+2191 ISOnum-->
+<!ENTITY rarr     "&#8594;" ><!-- rightwards arrow, U+2192 ISOnum -->
+<!ENTITY darr     "&#8595;" ><!-- downwards arrow, U+2193 ISOnum -->
+<!ENTITY harr     "&#8596;" ><!-- left right arrow, U+2194 ISOamsa -->
+<!ENTITY crarr    "&#8629;" ><!-- downwards arrow with corner leftwards
+                               = carriage return, U+21B5 NEW -->
+<!ENTITY lArr     "&#8656;" ><!-- leftwards double arrow, U+21D0 ISOtech -->
+<!-- Unicode does not say that lArr is the same as the 'is implied by' arrow
+    but also does not have any other character for that function. So ? lArr can
+    be used for 'is implied by' as ISOtech suggests -->
+<!ENTITY uArr     "&#8657;" ><!-- upwards double arrow, U+21D1 ISOamsa -->
+<!ENTITY rArr     "&#8658;" ><!-- rightwards double arrow, U+21D2 ISOtech -->
+<!-- Unicode does not say this is the 'implies' character but does not have
+     another character with this function so ?
+     rArr can be used for 'implies' as ISOtech suggests -->
+<!ENTITY dArr     "&#8659;" ><!-- downwards double arrow, U+21D3 ISOamsa -->
+<!ENTITY hArr     "&#8660;" ><!-- left right double arrow, U+21D4 ISOamsa -->
+
+<!-- Mathematical Operators -->
+<!ENTITY forall   "&#8704;" ><!-- for all, U+2200 ISOtech -->
+<!ENTITY part     "&#8706;" ><!-- partial differential, U+2202 ISOtech  -->
+<!ENTITY exist    "&#8707;" ><!-- there exists, U+2203 ISOtech -->
+<!ENTITY empty    "&#8709;" ><!-- empty set = null set, U+2205 ISOamso -->
+<!ENTITY nabla    "&#8711;" ><!-- nabla = backward difference, U+2207 ISOtech -->
+<!ENTITY isin     "&#8712;" ><!-- element of, U+2208 ISOtech -->
+<!ENTITY notin    "&#8713;" ><!-- not an element of, U+2209 ISOtech -->
+<!ENTITY ni       "&#8715;" ><!-- contains as member, U+220B ISOtech -->
+<!-- should there be a more memorable name than 'ni'? -->
+<!ENTITY prod     "&#8719;" ><!-- n-ary product = product sign, U+220F ISOamsb -->
+<!-- prod is NOT the same character as U+03A0 'greek capital letter pi' though
+     the same glyph might be used for both -->
+<!ENTITY sum      "&#8721;" ><!-- n-ary sumation, U+2211 ISOamsb -->
+<!-- sum is NOT the same character as U+03A3 'greek capital letter sigma'
+     though the same glyph might be used for both -->
+<!ENTITY minus    "&#8722;" ><!-- minus sign, U+2212 ISOtech -->
+<!ENTITY lowast   "&#8727;" ><!-- asterisk operator, U+2217 ISOtech -->
+<!ENTITY radic    "&#8730;" ><!-- square root = radical sign, U+221A ISOtech -->
+<!ENTITY prop     "&#8733;" ><!-- proportional to, U+221D ISOtech -->
+<!ENTITY infin    "&#8734;" ><!-- infinity, U+221E ISOtech -->
+<!ENTITY ang      "&#8736;" ><!-- angle, U+2220 ISOamso -->
+<!ENTITY and      "&#8743;" ><!-- logical and = wedge, U+2227 ISOtech -->
+<!ENTITY or       "&#8744;" ><!-- logical or = vee, U+2228 ISOtech -->
+<!ENTITY cap      "&#8745;" ><!-- intersection = cap, U+2229 ISOtech -->
+<!ENTITY cup      "&#8746;" ><!-- union = cup, U+222A ISOtech -->
+<!ENTITY int      "&#8747;" ><!-- integral, U+222B ISOtech -->
+<!ENTITY there4   "&#8756;" ><!-- therefore, U+2234 ISOtech -->
+<!ENTITY sim      "&#8764;" ><!-- tilde operator = varies with = similar to, U+223C ISOtech -->
+<!-- tilde operator is NOT the same character as the tilde, U+007E,
+     although the same glyph might be used to represent both  -->
+<!ENTITY cong     "&#8773;" ><!-- approximately equal to, U+2245 ISOtech -->
+<!ENTITY asymp    "&#8776;" ><!-- almost equal to = asymptotic to, U+2248 ISOamsr -->
+<!ENTITY ne       "&#8800;" ><!-- not equal to, U+2260 ISOtech -->
+<!ENTITY equiv    "&#8801;" ><!-- identical to, U+2261 ISOtech -->
+<!ENTITY le       "&#8804;" ><!-- less-than or equal to, U+2264 ISOtech -->
+<!ENTITY ge       "&#8805;" ><!-- greater-than or equal to, U+2265 ISOtech -->
+<!ENTITY sub      "&#8834;" ><!-- subset of, U+2282 ISOtech -->
+<!ENTITY sup      "&#8835;" ><!-- superset of, U+2283 ISOtech -->
+<!-- note that nsup, 'not a superset of, U+2283' is not covered by the Symbol
+     font encoding and is not included. Should it be, for symmetry?
+     It is in ISOamsn  -->
+<!ENTITY nsub     "&#8836;" ><!-- not a subset of, U+2284 ISOamsn -->
+<!ENTITY sube     "&#8838;" ><!-- subset of or equal to, U+2286 ISOtech -->
+<!ENTITY supe     "&#8839;" ><!-- superset of or equal to, U+2287 ISOtech -->
+<!ENTITY oplus    "&#8853;" ><!-- circled plus = direct sum, U+2295 ISOamsb -->
+<!ENTITY otimes   "&#8855;" ><!-- circled times = vector product, U+2297 ISOamsb -->
+<!ENTITY perp     "&#8869;" ><!-- up tack = orthogonal to = perpendicular, U+22A5 ISOtech -->
+<!ENTITY sdot     "&#8901;" ><!-- dot operator, U+22C5 ISOamsb -->
+<!-- dot operator is NOT the same character as U+00B7 middle dot -->
+
+<!-- Miscellaneous Technical -->
+<!ENTITY lceil    "&#8968;" ><!-- left ceiling = apl upstile, U+2308 ISOamsc  -->
+<!ENTITY rceil    "&#8969;" ><!-- right ceiling, U+2309 ISOamsc  -->
+<!ENTITY lfloor   "&#8970;" ><!-- left floor = apl downstile, U+230A ISOamsc  -->
+<!ENTITY rfloor   "&#8971;" ><!-- right floor, U+230B ISOamsc  -->
+<!ENTITY lang     "&#9001;" ><!-- left-pointing angle bracket = bra, U+2329 ISOtech -->
+<!-- lang is NOT the same character as U+003C 'less than'
+     or U+2039 'single left-pointing angle quotation mark' -->
+<!ENTITY rang     "&#9002;" ><!-- right-pointing angle bracket = ket, U+232A ISOtech -->
+<!-- rang is NOT the same character as U+003E 'greater than'
+     or U+203A 'single right-pointing angle quotation mark' -->
+
+<!-- Geometric Shapes -->
+<!ENTITY loz      "&#9674;" ><!-- lozenge, U+25CA ISOpub -->
+
+<!-- Miscellaneous Symbols -->
+<!ENTITY spades   "&#9824;" ><!-- black spade suit, U+2660 ISOpub -->
+<!-- black here seems to mean filled as opposed to hollow -->
+<!ENTITY clubs    "&#9827;" ><!-- black club suit = shamrock, U+2663 ISOpub -->
+<!ENTITY hearts   "&#9829;" ><!-- black heart suit = valentine, U+2665 ISOpub -->
+<!ENTITY diams    "&#9830;" ><!-- black diamond suit, U+2666 ISOpub -->
+
+<!-- end of xhtml-symbol.ent -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-table-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-table-1.mod
new file mode 100644
index 0000000..3fc0360
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-table-1.mod
@@ -0,0 +1,333 @@
+<!-- ...................................................................... -->
+<!-- XHTML Table Module  .................................................. -->
+<!-- file: xhtml-table-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-table-1.mod,v 4.1 2001/04/10 09:42:30 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Tables 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-table-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Tables
+
+        table, caption, thead, tfoot, tbody, colgroup, col, tr, th, td
+
+     This module declares element types and attributes used to provide
+     table markup similar to HTML 4, including features that enable
+     better accessibility for non-visual user agents.
+-->
+
+<!-- declare qualified element type names:
+-->
+<!ENTITY % table.qname  "table" >
+<!ENTITY % caption.qname  "caption" >
+<!ENTITY % thead.qname  "thead" >
+<!ENTITY % tfoot.qname  "tfoot" >
+<!ENTITY % tbody.qname  "tbody" >
+<!ENTITY % colgroup.qname  "colgroup" >
+<!ENTITY % col.qname  "col" >
+<!ENTITY % tr.qname  "tr" >
+<!ENTITY % th.qname  "th" >
+<!ENTITY % td.qname  "td" >
+
+<!-- The frame attribute specifies which parts of the frame around
+     the table should be rendered. The values are not the same as
+     CALS to avoid a name clash with the valign attribute.
+-->
+<!ENTITY % frame.attrib
+     "frame        ( void
+                   | above
+                   | below
+                   | hsides
+                   | lhs
+                   | rhs
+                   | vsides
+                   | box
+                   | border )               #IMPLIED"
+>
+
+<!-- The rules attribute defines which rules to draw between cells:
+
+     If rules is absent then assume:
+
+       "none" if border is absent or border="0" otherwise "all"
+-->
+<!ENTITY % rules.attrib
+     "rules        ( none
+                   | groups
+                   | rows
+                   | cols
+                   | all )                  #IMPLIED"
+>
+
+<!-- horizontal alignment attributes for cell contents
+-->
+<!ENTITY % CellHAlign.attrib
+     "align        ( left
+                   | center
+                   | right
+                   | justify
+                   | char )                 #IMPLIED
+      char         %Character.datatype;     #IMPLIED
+      charoff      %Length.datatype;        #IMPLIED"
+>
+
+<!-- vertical alignment attribute for cell contents
+-->
+<!ENTITY % CellVAlign.attrib
+     "valign       ( top
+                   | middle
+                   | bottom
+                   | baseline )             #IMPLIED"
+>
+
+<!-- scope is simpler than axes attribute for common tables
+-->
+<!ENTITY % scope.attrib
+     "scope        ( row
+                   | col
+                   | rowgroup
+                   | colgroup )             #IMPLIED"
+>
+
+<!-- table: Table Element .............................. -->
+
+<!ENTITY % table.element  "INCLUDE" >
+<![%table.element;[
+<!ENTITY % table.content
+     "( %caption.qname;?, ( %col.qname;* | %colgroup.qname;* ),
+      (( %thead.qname;?, %tfoot.qname;?, %tbody.qname;+ ) | ( %tr.qname;+ )))"
+>
+<!ELEMENT %table.qname;  %table.content; >
+<!-- end of table.element -->]]>
+
+<!ENTITY % table.attlist  "INCLUDE" >
+<![%table.attlist;[
+<!ATTLIST %table.qname;
+      %Common.attrib;
+      summary      %Text.datatype;          #IMPLIED
+      width        %Length.datatype;        #IMPLIED
+      border       %Pixels.datatype;        #IMPLIED
+      %frame.attrib;
+      %rules.attrib;
+      cellspacing  %Length.datatype;        #IMPLIED
+      cellpadding  %Length.datatype;        #IMPLIED
+>
+<!-- end of table.attlist -->]]>
+
+<!-- caption: Table Caption ............................ -->
+
+<!ENTITY % caption.element  "INCLUDE" >
+<![%caption.element;[
+<!ENTITY % caption.content
+     "( #PCDATA | %Inline.mix; )*"
+>
+<!ELEMENT %caption.qname;  %caption.content; >
+<!-- end of caption.element -->]]>
+
+<!ENTITY % caption.attlist  "INCLUDE" >
+<![%caption.attlist;[
+<!ATTLIST %caption.qname;
+      %Common.attrib;
+>
+<!-- end of caption.attlist -->]]>
+
+<!-- thead: Table Header ............................... -->
+
+<!-- Use thead to duplicate headers when breaking table
+     across page boundaries, or for static headers when
+     tbody sections are rendered in scrolling panel.
+-->
+
+<!ENTITY % thead.element  "INCLUDE" >
+<![%thead.element;[
+<!ENTITY % thead.content  "( %tr.qname; )+" >
+<!ELEMENT %thead.qname;  %thead.content; >
+<!-- end of thead.element -->]]>
+
+<!ENTITY % thead.attlist  "INCLUDE" >
+<![%thead.attlist;[
+<!ATTLIST %thead.qname;
+      %Common.attrib;
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of thead.attlist -->]]>
+
+<!-- tfoot: Table Footer ............................... -->
+
+<!-- Use tfoot to duplicate footers when breaking table
+     across page boundaries, or for static footers when
+     tbody sections are rendered in scrolling panel.
+-->
+
+<!ENTITY % tfoot.element  "INCLUDE" >
+<![%tfoot.element;[
+<!ENTITY % tfoot.content  "( %tr.qname; )+" >
+<!ELEMENT %tfoot.qname;  %tfoot.content; >
+<!-- end of tfoot.element -->]]>
+
+<!ENTITY % tfoot.attlist  "INCLUDE" >
+<![%tfoot.attlist;[
+<!ATTLIST %tfoot.qname;
+      %Common.attrib;
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of tfoot.attlist -->]]>
+
+<!-- tbody: Table Body ................................. -->
+
+<!-- Use multiple tbody sections when rules are needed
+     between groups of table rows.
+-->
+
+<!ENTITY % tbody.element  "INCLUDE" >
+<![%tbody.element;[
+<!ENTITY % tbody.content  "( %tr.qname; )+" >
+<!ELEMENT %tbody.qname;  %tbody.content; >
+<!-- end of tbody.element -->]]>
+
+<!ENTITY % tbody.attlist  "INCLUDE" >
+<![%tbody.attlist;[
+<!ATTLIST %tbody.qname;
+      %Common.attrib;
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of tbody.attlist -->]]>
+
+<!-- colgroup: Table Column Group ...................... -->
+
+<!-- colgroup groups a set of col elements. It allows you
+     to group several semantically-related columns together.
+-->
+
+<!ENTITY % colgroup.element  "INCLUDE" >
+<![%colgroup.element;[
+<!ENTITY % colgroup.content  "( %col.qname; )*" >
+<!ELEMENT %colgroup.qname;  %colgroup.content; >
+<!-- end of colgroup.element -->]]>
+
+<!ENTITY % colgroup.attlist  "INCLUDE" >
+<![%colgroup.attlist;[
+<!ATTLIST %colgroup.qname;
+      %Common.attrib;
+      span         %Number.datatype;        '1'
+      width        %MultiLength.datatype;   #IMPLIED
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of colgroup.attlist -->]]>
+
+<!-- col: Table Column ................................. -->
+
+<!-- col elements define the alignment properties for
+     cells in one or more columns.
+
+     The width attribute specifies the width of the
+     columns, e.g.
+
+       width="64"        width in screen pixels
+       width="0.5*"      relative width of 0.5
+
+     The span attribute causes the attributes of one
+     col element to apply to more than one column.
+-->
+
+<!ENTITY % col.element  "INCLUDE" >
+<![%col.element;[
+<!ENTITY % col.content  "EMPTY" >
+<!ELEMENT %col.qname;  %col.content; >
+<!-- end of col.element -->]]>
+
+<!ENTITY % col.attlist  "INCLUDE" >
+<![%col.attlist;[
+<!ATTLIST %col.qname;
+      %Common.attrib;
+      span         %Number.datatype;        '1'
+      width        %MultiLength.datatype;   #IMPLIED
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of col.attlist -->]]>
+
+<!-- tr: Table Row ..................................... -->
+
+<!ENTITY % tr.element  "INCLUDE" >
+<![%tr.element;[
+<!ENTITY % tr.content  "( %th.qname; | %td.qname; )+" >
+<!ELEMENT %tr.qname;  %tr.content; >
+<!-- end of tr.element -->]]>
+
+<!ENTITY % tr.attlist  "INCLUDE" >
+<![%tr.attlist;[
+<!ATTLIST %tr.qname;
+      %Common.attrib;
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of tr.attlist -->]]>
+
+<!-- th: Table Header Cell ............................. -->
+
+<!-- th is for header cells, td for data,
+     but for cells acting as both use td
+-->
+
+<!ENTITY % th.element  "INCLUDE" >
+<![%th.element;[
+<!ENTITY % th.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ELEMENT %th.qname;  %th.content; >
+<!-- end of th.element -->]]>
+
+<!ENTITY % th.attlist  "INCLUDE" >
+<![%th.attlist;[
+<!ATTLIST %th.qname;
+      %Common.attrib;
+      abbr         %Text.datatype;          #IMPLIED
+      axis         CDATA                    #IMPLIED
+      headers      IDREFS                   #IMPLIED
+      %scope.attrib;
+      rowspan      %Number.datatype;        '1'
+      colspan      %Number.datatype;        '1'
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of th.attlist -->]]>
+
+<!-- td: Table Data Cell ............................... -->
+
+<!ENTITY % td.element  "INCLUDE" >
+<![%td.element;[
+<!ENTITY % td.content
+     "( #PCDATA | %Flow.mix; )*"
+>
+<!ELEMENT %td.qname;  %td.content; >
+<!-- end of td.element -->]]>
+
+<!ENTITY % td.attlist  "INCLUDE" >
+<![%td.attlist;[
+<!ATTLIST %td.qname;
+      %Common.attrib;
+      abbr         %Text.datatype;          #IMPLIED
+      axis         CDATA                    #IMPLIED
+      headers      IDREFS                   #IMPLIED
+      %scope.attrib;
+      rowspan      %Number.datatype;        '1'
+      colspan      %Number.datatype;        '1'
+      %CellHAlign.attrib;
+      %CellVAlign.attrib;
+>
+<!-- end of td.attlist -->]]>
+
+<!-- end of xhtml-table-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-target-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-target-1.mod
new file mode 100644
index 0000000..3739ef1
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-target-1.mod
@@ -0,0 +1,53 @@
+<!-- ...................................................................... -->
+<!-- XHTML Target Module  ................................................. -->
+<!-- file: xhtml-target-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-target-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Target 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-target-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Target 
+
+        target
+
+     This module declares the 'target' attribute used for opening windows
+-->
+
+<!-- render in this frame --> 
+<!ENTITY % FrameTarget.datatype "CDATA" >
+
+<!-- add 'target' attribute to 'a' element -->
+<!ATTLIST %a.qname;
+      target       %FrameTarget.datatype;   #IMPLIED
+>
+
+<!-- add 'target' attribute to 'area' element -->
+<!ATTLIST %area.qname;
+      target       %FrameTarget.datatype;   #IMPLIED
+>
+
+<!-- add 'target' attribute to 'link' element -->
+<!ATTLIST %link.qname;
+      target       %FrameTarget.datatype;   #IMPLIED
+>
+
+<!-- add 'target' attribute to 'form' element -->
+<!ATTLIST %form.qname;
+      target       %FrameTarget.datatype;   #IMPLIED
+>
+
+<!-- add 'target' attribute to 'base' element -->
+<!ATTLIST %base.qname;
+      target       %FrameTarget.datatype;   #IMPLIED
+>
+
+<!-- end of xhtml-target-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml-text-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml-text-1.mod
new file mode 100644
index 0000000..07ccb81
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml-text-1.mod
@@ -0,0 +1,52 @@
+<!-- ...................................................................... -->
+<!-- XHTML Text Module  ................................................... -->
+<!-- file: xhtml-text-1.mod
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml-text-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ELEMENTS XHTML Text 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-text-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- Textual Content
+
+     The Text module includes declarations for all core
+     text container elements and their attributes.
+-->
+
+<!ENTITY % xhtml-inlstruct.module "INCLUDE" >
+<![%xhtml-inlstruct.module;[
+<!ENTITY % xhtml-inlstruct.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Inline Structural 1.0//EN"
+            "xhtml-inlstruct-1.mod" >
+%xhtml-inlstruct.mod;]]>
+
+<!ENTITY % xhtml-inlphras.module "INCLUDE" >
+<![%xhtml-inlphras.module;[
+<!ENTITY % xhtml-inlphras.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Inline Phrasal 1.0//EN"
+            "xhtml-inlphras-1.mod" >
+%xhtml-inlphras.mod;]]>
+
+<!ENTITY % xhtml-blkstruct.module "INCLUDE" >
+<![%xhtml-blkstruct.module;[
+<!ENTITY % xhtml-blkstruct.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Block Structural 1.0//EN"
+            "xhtml-blkstruct-1.mod" >
+%xhtml-blkstruct.mod;]]>
+
+<!ENTITY % xhtml-blkphras.module "INCLUDE" >
+<![%xhtml-blkphras.module;[
+<!ENTITY % xhtml-blkphras.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Block Phrasal 1.0//EN"
+            "xhtml-blkphras-1.mod" >
+%xhtml-blkphras.mod;]]>
+
+<!-- end of xhtml-text-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml11-model-1.mod b/xml/impl/resources/standardSchemas/xhtml11/xhtml11-model-1.mod
new file mode 100644
index 0000000..4d9fcd9
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml11-model-1.mod
@@ -0,0 +1,250 @@
+<!-- ....................................................................... -->
+<!-- XHTML 1.1 Document Model Module  ...................................... -->
+<!-- file: xhtml11-model-1.mod
+
+     This is XHTML 1.1, a reformulation of HTML as a modular XML application.
+     Copyright 1998-2008 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+     Revision: $Id: xhtml11-model-1.mod,v 1.16 2008/06/21 18:52:27 ahby Exp $ SMI
+
+     This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+       PUBLIC "-//W3C//ENTITIES XHTML 1.1 Document Model 1.0//EN"
+       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml11-model-1.mod"
+
+     Revisions:
+     (none)
+     ....................................................................... -->
+
+<!-- XHTML 1.1 Document Model
+
+     This module describes the groupings of elements that make up
+     common content models for XHTML elements.
+
+     XHTML has three basic content models:
+
+         %Inline.mix;  character-level elements
+         %Block.mix;   block-like elements, eg., paragraphs and lists
+         %Flow.mix;    any block or inline elements
+
+     Any parameter entities declared in this module may be used
+     to create element content models, but the above three are
+     considered 'global' (insofar as that term applies here).
+
+     The reserved word '#PCDATA' (indicating a text string) is now
+     included explicitly with each element declaration that is
+     declared as mixed content, as XML requires that this token
+     occur first in a content model specification.
+-->
+<!-- Extending the Model
+
+     While in some cases this module may need to be rewritten to
+     accommodate changes to the document model, minor extensions
+     may be accomplished by redeclaring any of the three *.extra;
+     parameter entities to contain extension element types as follows:
+
+         %Misc.extra;    whose parent may be any block or
+                         inline element.
+
+         %Inline.extra;  whose parent may be any inline element.
+
+         %Block.extra;   whose parent may be any block element.
+
+     If used, these parameter entities must be an OR-separated
+     list beginning with an OR separator ("|"), eg., "| a | b | c"
+
+     All block and inline *.class parameter entities not part
+     of the *struct.class classes begin with "| " to allow for
+     exclusion from mixes.
+-->
+
+<!-- ..............  Optional Elements in head  .................. -->
+
+<!ENTITY % HeadOpts.mix
+     "( %script.qname; | %style.qname; | %meta.qname;
+      | %link.qname; | %object.qname; )*"
+>
+
+<!-- .................  Miscellaneous Elements  .................. -->
+
+<!-- ins and del are used to denote editing changes
+-->
+<!ENTITY % Edit.class "| %ins.qname; | %del.qname;" >
+
+<!-- script and noscript are used to contain scripts
+     and alternative content
+-->
+<!ENTITY % Script.class "| %script.qname; | %noscript.qname;" >
+
+<!ENTITY % Misc.extra "" >
+
+<!-- These elements are neither block nor inline, and can
+     essentially be used anywhere in the document body.
+-->
+<!ENTITY % Misc.class
+     "%Edit.class;
+      %Script.class;
+      %Misc.extra;"
+>
+
+<!-- ....................  Inline Elements  ...................... -->
+
+<!ENTITY % InlStruct.class "%br.qname; | %span.qname;" >
+
+<!ENTITY % InlPhras.class
+     "| %em.qname; | %strong.qname; | %dfn.qname; | %code.qname;
+      | %samp.qname; | %kbd.qname; | %var.qname; | %cite.qname;
+      | %abbr.qname; | %acronym.qname; | %q.qname;" >
+
+<!ENTITY % InlPres.class
+     "| %tt.qname; | %i.qname; | %b.qname; | %big.qname;
+      | %small.qname; | %sub.qname; | %sup.qname;" >
+
+<!ENTITY % I18n.class "| %bdo.qname;" >
+
+<!ENTITY % Anchor.class "| %a.qname;" >
+
+<!ENTITY % InlSpecial.class
+     "| %img.qname; | %map.qname;
+      | %object.qname;" >
+
+<!ENTITY % InlForm.class
+     "| %input.qname; | %select.qname; | %textarea.qname;
+      | %label.qname; | %button.qname;" >
+
+<!ENTITY % Inline.extra "" >
+
+<!ENTITY % Ruby.class "| %ruby.qname;" >
+
+<!-- %Inline.class; includes all inline elements,
+     used as a component in mixes
+-->
+<!ENTITY % Inline.class
+     "%InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %I18n.class;
+      %Anchor.class;
+      %InlSpecial.class;
+      %InlForm.class;
+      %Ruby.class;
+      %Inline.extra;"
+>
+
+<!-- %InlNoRuby.class; includes all inline elements
+     except ruby, used as a component in mixes
+-->
+<!ENTITY % InlNoRuby.class
+     "%InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %I18n.class;
+      %Anchor.class;
+      %InlSpecial.class;
+      %InlForm.class;
+      %Inline.extra;"
+>
+
+<!-- %NoRuby.content; includes all inlines except ruby
+-->
+<!ENTITY % NoRuby.content
+     "( #PCDATA
+      | %InlNoRuby.class;
+      %Misc.class; )*"
+>
+
+<!-- %InlNoAnchor.class; includes all non-anchor inlines,
+     used as a component in mixes
+-->
+<!ENTITY % InlNoAnchor.class
+     "%InlStruct.class;
+      %InlPhras.class;
+      %InlPres.class;
+      %I18n.class;
+      %InlSpecial.class;
+      %InlForm.class;
+      %Ruby.class;
+      %Inline.extra;"
+>
+
+<!-- %InlNoAnchor.mix; includes all non-anchor inlines
+-->
+<!ENTITY % InlNoAnchor.mix
+     "%InlNoAnchor.class;
+      %Misc.class;"
+>
+
+<!-- %Inline.mix; includes all inline elements, including %Misc.class;
+-->
+<!ENTITY % Inline.mix
+     "%Inline.class;
+      %Misc.class;"
+>
+
+<!-- .....................  Block Elements  ...................... -->
+
+<!-- In the HTML 4.0 DTD, heading and list elements were included
+     in the %block; parameter entity. The %Heading.class; and
+     %List.class; parameter entities must now be included explicitly
+     on element declarations where desired.
+-->
+
+<!ENTITY % Heading.class
+     "%h1.qname; | %h2.qname; | %h3.qname;
+      | %h4.qname; | %h5.qname; | %h6.qname;" >
+
+<!ENTITY % List.class "%ul.qname; | %ol.qname; | %dl.qname;" >
+
+<!ENTITY % Table.class "| %table.qname;" >
+
+<!ENTITY % Form.class  "| %form.qname;" >
+
+<!ENTITY % Fieldset.class  "| %fieldset.qname;" >
+
+<!ENTITY % BlkStruct.class "%p.qname; | %div.qname;" >
+
+<!ENTITY % BlkPhras.class
+     "| %pre.qname; | %blockquote.qname; | %address.qname;" >
+
+<!ENTITY % BlkPres.class "| %hr.qname;" >
+
+<!ENTITY % BlkSpecial.class
+     "%Table.class;
+      %Form.class;
+      %Fieldset.class;"
+>
+
+<!ENTITY % Block.extra "" >
+
+<!-- %Block.class; includes all block elements,
+     used as an component in mixes
+-->
+<!ENTITY % Block.class
+     "%BlkStruct.class;
+      %BlkPhras.class;
+      %BlkPres.class;
+      %BlkSpecial.class;
+      %Block.extra;"
+>
+
+<!-- %Block.mix; includes all block elements plus %Misc.class;
+-->
+<!ENTITY % Block.mix
+     "%Heading.class;
+      | %List.class;
+      | %Block.class;
+      %Misc.class;"
+>
+
+<!-- ................  All Content Elements  .................. -->
+
+<!-- %Flow.mix; includes all text content, block and inline
+-->
+<!ENTITY % Flow.mix
+     "%Heading.class;
+      | %List.class;
+      | %Block.class;
+      | %Inline.class;
+      %Misc.class;"
+>
+
+<!-- end of xhtml11-model-1.mod -->
diff --git a/xml/impl/resources/standardSchemas/xhtml11/xhtml11.dtd b/xml/impl/resources/standardSchemas/xhtml11/xhtml11.dtd
new file mode 100644
index 0000000..bc67157
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xhtml11/xhtml11.dtd
@@ -0,0 +1,317 @@
+<!-- ....................................................................... -->
+<!-- XHTML 1.1 DTD  ........................................................ -->
+<!-- file: xhtml11.dtd
+-->
+
+<!-- XHTML 1.1 DTD
+
+     This is XHTML, a reformulation of HTML as a modular XML application.
+
+     The Extensible HyperText Markup Language (XHTML)
+     Copyright 1998-2007 World Wide Web Consortium
+        (Massachusetts Institute of Technology, European Research Consortium
+         for Informatics and Mathematics, Keio University).
+         All Rights Reserved.
+
+     Permission to use, copy, modify and distribute the XHTML DTD and its 
+     accompanying documentation for any purpose and without fee is hereby 
+     granted in perpetuity, provided that the above copyright notice and 
+     this paragraph appear in all copies.  The copyright holders make no 
+     representation about the suitability of the DTD for any purpose.
+
+     It is provided "as is" without expressed or implied warranty.
+
+        Author:     Murray M. Altheim <altheim@eng.sun.com>
+        Revision:   $Id: xhtml11.dtd,v 1.1 2007/02/15 23:14:56 jean-gui Exp $
+
+-->
+<!-- This is the driver file for version 1.1 of the XHTML DTD.
+
+     Please use this public identifier to identify it:
+
+         "-//W3C//DTD XHTML 1.1//EN"
+-->
+<!ENTITY % XHTML.version  "-//W3C//DTD XHTML 1.1//EN" >
+
+<!-- Use this URI to identify the default namespace:
+
+         "http://www.w3.org/1999/xhtml"
+
+     See the Qualified Names module for information
+     on the use of namespace prefixes in the DTD.
+
+	 Note that XHTML namespace elements are not prefixed by default,
+	 but the XHTML namespace prefix is defined as "xhtml" so that
+	 other markup languages can extend this one and use the XHTML
+	 prefixed global attributes if required.
+
+-->
+<!ENTITY % NS.prefixed "IGNORE" >
+<!ENTITY % XHTML.prefix "xhtml" >
+
+<!-- Be sure to include prefixed global attributes - we don't need
+     them, but languages that extend XHTML 1.1 might.
+-->
+<!ENTITY % XHTML.global.attrs.prefixed "INCLUDE" >
+
+<!-- Reserved for use with the XLink namespace:
+-->
+<!ENTITY % XLINK.xmlns "" >
+<!ENTITY % XLINK.xmlns.attrib "" >
+
+<!-- For example, if you are using XHTML 1.1 directly, use the public
+     identifier in the DOCTYPE declaration, with the namespace declaration
+     on the document element to identify the default namespace:
+
+       <?xml version="1.0"?>
+       <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+                             "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+       <html xmlns="http://www.w3.org/1999/xhtml"
+             xml:lang="en">
+       ...
+       </html>
+
+     Revisions:
+     (none)
+-->
+
+<!-- reserved for future use with document profiles -->
+<!ENTITY % XHTML.profile  "" >
+
+<!-- ensure XHTML Notations are disabled -->
+<!ENTITY % xhtml-notations.module "IGNORE" >
+
+<!-- Bidirectional Text features
+     This feature-test entity is used to declare elements
+     and attributes used for bidirectional text support.
+-->
+<!ENTITY % XHTML.bidi  "INCLUDE" >
+
+<!--<?doc type="doctype" role="title" { XHTML 1.1 } ?>-->
+
+<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+
+<!-- Pre-Framework Redeclaration placeholder  .................... -->
+<!-- this serves as a location to insert markup declarations
+     into the DTD prior to the framework declarations.
+-->
+<!ENTITY % xhtml-prefw-redecl.module "IGNORE" >
+<![%xhtml-prefw-redecl.module;[
+%xhtml-prefw-redecl.mod;
+<!-- end of xhtml-prefw-redecl.module -->]]>
+
+<!ENTITY % xhtml-events.module "INCLUDE" >
+
+<!-- Inline Style Module  ........................................ -->
+<!ENTITY % xhtml-inlstyle.module "INCLUDE" >
+<![%xhtml-inlstyle.module;[
+<!ENTITY % xhtml-inlstyle.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN"
+            "xhtml-inlstyle-1.mod" >
+%xhtml-inlstyle.mod;]]>
+
+<!-- declare Document Model module instantiated in framework
+-->
+<!ENTITY % xhtml-model.mod
+     PUBLIC "-//W3C//ENTITIES XHTML 1.1 Document Model 1.0//EN"
+            "xhtml11-model-1.mod" >
+
+<!-- Modular Framework Module (required) ......................... -->
+<!ENTITY % xhtml-framework.module "INCLUDE" >
+<![%xhtml-framework.module;[
+<!ENTITY % xhtml-framework.mod
+     PUBLIC "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN"
+            "xhtml-framework-1.mod" >
+%xhtml-framework.mod;]]>
+
+<!-- Post-Framework Redeclaration placeholder  ................... -->
+<!-- this serves as a location to insert markup declarations
+     into the DTD following the framework declarations.
+-->
+<!ENTITY % xhtml-postfw-redecl.module "IGNORE" >
+<![%xhtml-postfw-redecl.module;[
+%xhtml-postfw-redecl.mod;
+<!-- end of xhtml-postfw-redecl.module -->]]>
+
+<!-- Text Module (Required)  ..................................... -->
+<!ENTITY % xhtml-text.module "INCLUDE" >
+<![%xhtml-text.module;[
+<!ENTITY % xhtml-text.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Text 1.0//EN"
+            "xhtml-text-1.mod" >
+%xhtml-text.mod;]]>
+
+<!-- Hypertext Module (required) ................................. -->
+<!ENTITY % xhtml-hypertext.module "INCLUDE" >
+<![%xhtml-hypertext.module;[
+<!ENTITY % xhtml-hypertext.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN"
+            "xhtml-hypertext-1.mod" >
+%xhtml-hypertext.mod;]]>
+
+<!-- Lists Module (required)  .................................... -->
+<!ENTITY % xhtml-list.module "INCLUDE" >
+<![%xhtml-list.module;[
+<!ENTITY % xhtml-list.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Lists 1.0//EN"
+            "xhtml-list-1.mod" >
+%xhtml-list.mod;]]>
+
+<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+
+<!-- Edit Module  ................................................ -->
+<!ENTITY % xhtml-edit.module "INCLUDE" >
+<![%xhtml-edit.module;[
+<!ENTITY % xhtml-edit.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Editing Elements 1.0//EN"
+            "xhtml-edit-1.mod" >
+%xhtml-edit.mod;]]>
+
+<!-- BIDI Override Module  ....................................... -->
+<!ENTITY % xhtml-bdo.module "%XHTML.bidi;" >
+<![%xhtml-bdo.module;[
+<!ENTITY % xhtml-bdo.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML BIDI Override Element 1.0//EN"
+            "xhtml-bdo-1.mod" >
+%xhtml-bdo.mod;]]>
+
+<!-- Ruby Module  ................................................ -->
+<!ENTITY % Ruby.common.attlists "INCLUDE" >
+<!ENTITY % Ruby.common.attrib "%Common.attrib;" >
+<!ENTITY % xhtml-ruby.module "INCLUDE" >
+<![%xhtml-ruby.module;[
+<!ENTITY % xhtml-ruby.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Ruby 1.0//EN"
+            "xhtml-ruby-1.mod" >
+%xhtml-ruby.mod;]]>
+
+<!-- Presentation Module  ........................................ -->
+<!ENTITY % xhtml-pres.module "INCLUDE" >
+<![%xhtml-pres.module;[
+<!ENTITY % xhtml-pres.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Presentation 1.0//EN"
+            "xhtml-pres-1.mod" >
+%xhtml-pres.mod;]]>
+
+<!-- Link Element Module  ........................................ -->
+<!ENTITY % xhtml-link.module "INCLUDE" >
+<![%xhtml-link.module;[
+<!ENTITY % xhtml-link.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Link Element 1.0//EN"
+            "xhtml-link-1.mod" >
+%xhtml-link.mod;]]>
+
+<!-- Document Metainformation Module  ............................ -->
+<!ENTITY % xhtml-meta.module "INCLUDE" >
+<![%xhtml-meta.module;[
+<!ENTITY % xhtml-meta.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN"
+            "xhtml-meta-1.mod" >
+%xhtml-meta.mod;]]>
+
+<!-- Base Element Module  ........................................ -->
+<!ENTITY % xhtml-base.module "INCLUDE" >
+<![%xhtml-base.module;[
+<!ENTITY % xhtml-base.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Base Element 1.0//EN"
+            "xhtml-base-1.mod" >
+%xhtml-base.mod;]]>
+
+<!-- Scripting Module  ........................................... -->
+<!ENTITY % xhtml-script.module "INCLUDE" >
+<![%xhtml-script.module;[
+<!ENTITY % xhtml-script.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Scripting 1.0//EN"
+            "xhtml-script-1.mod" >
+%xhtml-script.mod;]]>
+
+<!-- Style Sheets Module  ......................................... -->
+<!ENTITY % xhtml-style.module "INCLUDE" >
+<![%xhtml-style.module;[
+<!ENTITY % xhtml-style.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Style Sheets 1.0//EN"
+            "xhtml-style-1.mod" >
+%xhtml-style.mod;]]>
+
+<!-- Image Module  ............................................... -->
+<!ENTITY % xhtml-image.module "INCLUDE" >
+<![%xhtml-image.module;[
+<!ENTITY % xhtml-image.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Images 1.0//EN"
+            "xhtml-image-1.mod" >
+%xhtml-image.mod;]]>
+
+<!-- Client-side Image Map Module  ............................... -->
+<!ENTITY % xhtml-csismap.module "INCLUDE" >
+<![%xhtml-csismap.module;[
+<!ENTITY % xhtml-csismap.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Client-side Image Maps 1.0//EN"
+            "xhtml-csismap-1.mod" >
+%xhtml-csismap.mod;]]>
+
+<!-- Server-side Image Map Module  ............................... -->
+<!ENTITY % xhtml-ssismap.module "INCLUDE" >
+<![%xhtml-ssismap.module;[
+<!ENTITY % xhtml-ssismap.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Server-side Image Maps 1.0//EN"
+            "xhtml-ssismap-1.mod" >
+%xhtml-ssismap.mod;]]>
+
+<!-- Param Element Module  ....................................... -->
+<!ENTITY % xhtml-param.module "INCLUDE" >
+<![%xhtml-param.module;[
+<!ENTITY % xhtml-param.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Param Element 1.0//EN"
+            "xhtml-param-1.mod" >
+%xhtml-param.mod;]]>
+
+<!-- Embedded Object Module  ..................................... -->
+<!ENTITY % xhtml-object.module "INCLUDE" >
+<![%xhtml-object.module;[
+<!ENTITY % xhtml-object.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Embedded Object 1.0//EN"
+            "xhtml-object-1.mod" >
+%xhtml-object.mod;]]>
+
+<!-- Tables Module ............................................... -->
+<!ENTITY % xhtml-table.module "INCLUDE" >
+<![%xhtml-table.module;[
+<!ENTITY % xhtml-table.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Tables 1.0//EN"
+            "xhtml-table-1.mod" >
+%xhtml-table.mod;]]>
+
+<!-- Forms Module  ............................................... -->
+<!ENTITY % xhtml-form.module "INCLUDE" >
+<![%xhtml-form.module;[
+<!ENTITY % xhtml-form.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Forms 1.0//EN"
+            "xhtml-form-1.mod" >
+%xhtml-form.mod;]]>
+
+<!-- Target Attribute Module  .................................... -->
+<!ENTITY % xhtml-target.module "INCLUDE" >
+<![%xhtml-target.module;[
+<!ENTITY % xhtml-target.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Target 1.0//EN"
+            "xhtml-target-1.mod" >
+%xhtml-target.mod;]]>
+
+<!-- Legacy Markup ............................................... -->
+<!ENTITY % xhtml-legacy.module "IGNORE" >
+<![%xhtml-legacy.module;[
+<!ENTITY % xhtml-legacy.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Legacy Markup 1.0//EN"
+            "xhtml-legacy-1.mod" >
+%xhtml-legacy.mod;]]>
+
+<!-- Document Structure Module (required)  ....................... -->
+<!ENTITY % xhtml-struct.module "INCLUDE" >
+<![%xhtml-struct.module;[
+<!ENTITY % xhtml-struct.mod
+     PUBLIC "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN"
+            "xhtml-struct-1.mod" >
+%xhtml-struct.mod;]]>
+
+<!-- end of XHTML 1.1 DTD  ................................................. -->
+<!-- ....................................................................... -->
diff --git a/xml/impl/resources/standardSchemas/xinclude.xsd b/xml/impl/resources/standardSchemas/xinclude.xsd
new file mode 100644
index 0000000..c0e0a0b
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xinclude.xsd
@@ -0,0 +1,49 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:xi="http://www.w3.org/2001/XInclude"
+           targetNamespace="http://www.w3.org/2001/XInclude"
+           finalDefault="extension">
+  <xs:annotation>
+   <xs:documentation>
+    Not normative, but may be useful.
+    See the REC http://www.w3.org/TR/XInclude for definitive
+    information about this namespace.
+   </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="include" type="xi:includeType" />
+
+  <xs:complexType name="includeType" mixed="true">
+    <xs:choice minOccurs='0' maxOccurs='unbounded' >
+      <xs:element ref='xi:fallback' />
+      <xs:any namespace='##other' processContents='lax' />
+      <xs:any namespace='##local' processContents='lax' />
+    </xs:choice>
+    <xs:attribute name="href" use="optional" type="xs:anyURI"/>
+    <xs:attribute name="parse" use="optional" default="xml"
+                  type="xi:parseType" />
+    <xs:attribute name="xpointer" use="optional" type="xs:string"/>
+    <xs:attribute name="encoding" use="optional" type="xs:string"/>
+    <xs:attribute name="accept" use="optional" type="xs:string"/>
+    <xs:attribute name="accept-language" use="optional" type="xs:string"/>
+    <xs:anyAttribute namespace="##other" processContents="lax"/>
+  </xs:complexType>
+
+  <xs:simpleType name="parseType">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="xml"/>
+      <xs:enumeration value="text"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="fallback" type="xi:fallbackType" />
+
+  <xs:complexType name="fallbackType" mixed="true">
+    <xs:choice minOccurs="0" maxOccurs="unbounded">
+      <xs:element ref="xi:include"/>
+      <xs:any namespace="##other" processContents="lax"/>
+      <xs:any namespace="##local" processContents="lax"/>
+    </xs:choice>
+    <xs:anyAttribute namespace="##other" processContents="lax" />
+  </xs:complexType>
+
+</xs:schema>
diff --git a/xml/impl/resources/standardSchemas/xml.xsd b/xml/impl/resources/standardSchemas/xml.xsd
new file mode 100644
index 0000000..47c929f
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xml.xsd
@@ -0,0 +1,145 @@
+<?xml version='1.0'?>
+<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" xml:lang="en">
+
+ <xs:annotation>
+  <xs:documentation>
+   See http://www.w3.org/XML/1998/namespace.html and
+   http://www.w3.org/TR/REC-xml for information about this namespace.
+
+    This schema document describes the XML namespace, in a form
+    suitable for import by other schema documents.
+
+    Note that local names in this namespace are intended to be defined
+    only by the World Wide Web Consortium or its subgroups.  The
+    following names are currently defined in this namespace and should
+    not be used with conflicting semantics by any Working Group,
+    specification, or document instance:
+
+    base (as an attribute name): denotes an attribute whose value
+         provides a URI to be used as the base for interpreting any
+         relative URIs in the scope of the element on which it
+         appears; its value is inherited.  This name is reserved
+         by virtue of its definition in the XML Base specification.
+
+    id   (as an attribute name): denotes an attribute whose value
+         should be interpreted as if declared to be of type ID.
+         This name is reserved by virtue of its definition in the
+         xml:id specification.
+
+    lang (as an attribute name): denotes an attribute whose value
+         is a language code for the natural language of the content of
+         any element; its value is inherited.  This name is reserved
+         by virtue of its definition in the XML specification.
+
+    space (as an attribute name): denotes an attribute whose
+         value is a keyword indicating what whitespace processing
+         discipline is intended for the content of the element; its
+         value is inherited.  This name is reserved by virtue of its
+         definition in the XML specification.
+
+    Father (in any context at all): denotes Jon Bosak, the chair of
+         the original XML Working Group.  This name is reserved by
+         the following decision of the W3C XML Plenary and
+         XML Coordination groups:
+
+             In appreciation for his vision, leadership and dedication
+             the W3C XML Plenary on this 10th day of February, 2000
+             reserves for Jon Bosak in perpetuity the XML name
+             xml:Father
+  </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+  <xs:documentation>This schema defines attributes and an attribute group
+        suitable for use by
+        schemas wishing to allow xml:base, xml:lang, xml:space or xml:id
+        attributes on elements they define.
+
+        To enable this, such a schema must import this schema
+        for the XML namespace, e.g. as follows:
+        &lt;schema . . .>
+         . . .
+         &lt;import namespace="http://www.w3.org/XML/1998/namespace"
+                    schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+        Subsequently, qualified reference to any of the attributes
+        or the group defined below will have the desired effect, e.g.
+
+        &lt;type . . .>
+         . . .
+         &lt;attributeGroup ref="xml:specialAttrs"/>
+
+         will define a type which will schema-validate an instance
+         element with any of those attributes</xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+  <xs:documentation>In keeping with the XML Schema WG's standard versioning
+   policy, this schema document will persist at
+   http://www.w3.org/2007/08/xml.xsd.
+   At the date of issue it can also be found at
+   http://www.w3.org/2001/xml.xsd.
+   The schema document at that URI may however change in the future,
+   in order to remain compatible with the latest version of XML Schema
+   itself, or with the XML namespace itself.  In other words, if the XML
+   Schema or XML namespaces change, the version of this document at
+   http://www.w3.org/2001/xml.xsd will change
+   accordingly; the version at
+   http://www.w3.org/2007/08/xml.xsd will not change.
+  </xs:documentation>
+ </xs:annotation>
+
+ <xs:attribute name="lang">
+  <xs:annotation>
+   <xs:documentation>Attempting to install the relevant ISO 2- and 3-letter
+         codes as the enumerated possible values is probably never
+         going to be a realistic possibility.  See
+         RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry
+         at http://www.iana.org/assignments/lang-tag-apps.htm for
+         further information.
+
+         The union allows for the 'un-declaration' of xml:lang with
+         the empty string.</xs:documentation>
+  </xs:annotation>
+  <xs:simpleType>
+   <xs:union memberTypes="xs:language">
+    <xs:simpleType>
+     <xs:restriction base="xs:string">
+      <xs:enumeration value=""/>
+     </xs:restriction>
+    </xs:simpleType>
+   </xs:union>
+  </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="space">
+  <xs:simpleType>
+   <xs:restriction base="xs:NCName">
+    <xs:enumeration value="default"/>
+    <xs:enumeration value="preserve"/>
+   </xs:restriction>
+  </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="base" type="xs:anyURI">
+  <xs:annotation>
+   <xs:documentation>See http://www.w3.org/TR/xmlbase/ for
+                     information about this attribute.</xs:documentation>
+  </xs:annotation>
+ </xs:attribute>
+
+ <xs:attribute name="id" type="xs:ID">
+  <xs:annotation>
+   <xs:documentation>See http://www.w3.org/TR/xml-id/ for
+                     information about this attribute.</xs:documentation>
+  </xs:annotation>
+ </xs:attribute>
+
+ <xs:attributeGroup name="specialAttrs">
+  <xs:attribute ref="xml:base"/>
+  <xs:attribute ref="xml:lang"/>
+  <xs:attribute ref="xml:space"/>
+  <xs:attribute ref="xml:id"/>
+ </xs:attributeGroup>
+
+</xs:schema>
diff --git a/xml/impl/resources/standardSchemas/xslt-1_0.xsd b/xml/impl/resources/standardSchemas/xslt-1_0.xsd
new file mode 100644
index 0000000..f805b2c
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xslt-1_0.xsd
@@ -0,0 +1,1244 @@
+<?xml version="1.0" ?>
+
+<!--
+
+This is an updated version of the XSLT schema originally published by WebMethods
+in March 2001. This version complies with the current W3C XML Schema
+recommendation. To use this schema, start you stylesheet with:
+
+    <xsl:stylesheet version="1.0"
+            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            xsi:schemaLocation="http://www.w3.org/1999/XSL/Transform http://www.orbeon.com/1999/XSL/Transform">
+
+If you have any question or comment, please feel free to contact us:
+
+    Orbeon, Inc.
+    http://www.orbeon.com/
+    info@orbeon.com
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+DISCLAIMER OF WARRANTY
+
+THIS CODE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND,
+EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A
+PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY
+AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED
+CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL
+DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY
+CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED
+CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+LIMITATION OF LIABILITY
+
+UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY
+INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK
+STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY
+SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM
+SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH
+LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION
+MAY NOT APPLY TO YOU.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+This free of charge Software is provided on an "AS IS" basis, without
+warranty of any kind. The entire risk as to the quality and performance of
+the software is borne by you. Should the software prove defective, you and
+only you assume the entire cost of any service and repair.
+
+WEBMETHODS DOES NOT MAKE ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND
+INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF TITLE, MERCHANTABILITY OR
+FITNESS FOR A PARTICULAR PURPOSE, OR WARRANTIES ARISING BY STATUTE, COURSE
+OF DEALING, CUSTOM OR USAGE, TRADE PRACTICE OR OTHERWISE.
+
+IN NO EVENT WILL WEBMETHODS BE LIABLE FOR ANY LOST REVENUES, PROFITS,
+BUSINESS OR INTERRUPTION OF BUSINESS OR OTHER SPECIAL, INDIRECT, INCIDENTAL
+OR CONSEQUENTIAL DAMAGES, EVEN IF WEBMETHODS HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES, AND NOTWITHSTANDING ANY FAILURE OF ESSENTIAL
+PURPOSE OF ANY LIMITED REMEDY OF ANY KIND, HOWEVER CAUSED AND UNDER ANY
+THEORY OF LIABILITY.
+
+
+
+
+
+
+
+Schema for XSLT 1.0 Recommendation, http://www.w3.org/TR/1999/REC-xslt-19991116
+Using XML Schema CR Drafts,
+
+- Part 1, http://www.w3.org/TR/2000/CR-xmlschema-1-20001024/
+- Part 2, http://www.w3.org/TR/2000/CR-xmlschema-2-20001024/
+
+Author: Asir S Vedamuthu
+Member, XML Schema WG representing webMethods, Inc.
+Member, XML Schema Processor design and implementation team at webMethods
+
+webMethods, Inc.
+3930 Pender Drive
+Fairfax VA 22030
+
+(703) 450-2500
+
+Date - February 28th, 2001
+Version - 0.4
+
+This work is a product of the W3C XML Schema WG Task Force for authoring schema
+for W3C Recommendations as an illustration of the XML Schema Language. This schema
+is illustrative and non-normative. Internal names created by this schema follows the
+same convention used by XSLT 1.0 specification.
+
+Comments were stolen from the XSLT 1.0 specification,
+    http://www.w3.org/TR/1999/REC-xslt-19991116#element-syntax-summary
+
+Asir intends to update this schema as the XML Schema drafts advance from CR to
+PR and then REC. Expected changes are,
+
+[1] XML Schema Namespace URI
+[2] Change attribute declaration syntax
+
+
+KNOWN ISSUES,
+
+(a) XML Schema Definition Language cannot capture a unique wild card expression in XSLT: "In addition, the xsl:stylesheet element may contain any element not from the XSLT namespace, provided that the expanded-name of the element has a non-null namespace URI" - http://www.w3.org/TR/1999/REC-xslt-19991116#stylesheet-element (This will not be an issue as per XML Schema PR)
+
+
+Revision History
+
+0.1 - Created
+0.2 - Fixed minor typos
+0.3 - Implemented suggestions and added fragments from James Clark
+0.4 - Fixed a minor typo
+
+Acknowledgement
+
+The following have contributed material to this draft:
+
+- James Clark, jjc@jclark.com
+
+
+Please send your comments and suggestions to asirv@webmethods.com
+
+
+-->
+
+
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd"
+        targetNamespace="http://www.w3.org/1999/XSL/Transform"
+        elementFormDefault="qualified">
+
+
+  <import namespace="http://www.w3.org/XML/1998/namespace"
+          schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+  <!--<import namespace="http://www.w3.org/2001/XMLSchema" />-->
+
+
+
+  <!-- *** import schema for xpath
+         authored by C. M. Sperberg-McQueen [cmsmcq@acm.org]
+         Chair, XML Schema WG
+
+  <import namespace="http://www.w3.org/TR/2001/WD-xptr-20010108/"
+      schemaLocation="xpath.xsd"/>
+  -->
+
+
+  <!-- *** result elements *** -->
+  <!-- ***                  *** -->
+
+  <!--     There are three ways that you can construct a
+          schema for XSLT stylesheets that create instances of a
+          particular result structure
+
+          (a)    Declare all your result elements as a member of
+              xsl:result-element substitution group
+
+          (b) Redefine model group xsl:result-element to accomodate
+              the desired structure
+
+          (c)    Do nothing. This schema is designed to allow any element node
+              or nodes if they have any namespace other than the XSLT
+              namespace or not namespace qualified
+
+          I recommend (a) or (b)
+
+          In addition, I added a an attributeGroup util, 'result-element'
+          for your convenience
+
+  -->
+
+  <element name="result-element" abstract="true" type="anyType"/>
+
+
+  <attributeGroup name="result-element">
+    <attribute name="extension-element-prefixes" form="qualified" type="string"/>
+    <attribute name="exclude-result-prefixes" form="qualified" type="string"/>
+    <attribute name="use-attribute-sets" form="qualified" type="xsl:QNames"/>
+    <attribute name="version" form="qualified" type="NMTOKEN"/>
+    <anyAttribute namespace="##other" processContents="skip"/>
+  </attributeGroup>
+
+
+  <group name="result-element">
+    <choice>
+      <element ref="xsl:result-element"/>
+      <any namespace="##other" processContents="skip"/>
+      <any namespace="##local" processContents="skip"/>
+    </choice>
+  </group>
+
+
+
+
+
+  <!-- *** Style Sheet Elements *** -->
+  <!-- ***                       *** -->
+
+
+  <element name="stylesheet" type="xsl:wrapper"/>
+  <element name="transform" type="xsl:wrapper"/>
+
+  <complexType name="wrapper">
+    <complexContent>
+      <extension base="xsl:anyType">
+        <sequence>
+          <element ref="xsl:import" minOccurs="0" maxOccurs="unbounded"/>
+          <choice  minOccurs="0" maxOccurs="unbounded">
+            <element ref="xsl:top-level-element"/>
+            <element ref="xsl:variable"/>
+            <any namespace="##other" processContents="skip"/> <!-- weaker than XSLT 1.0 -->
+          </choice>
+        </sequence>
+        <attribute name="id" type="ID"/>
+        <attribute name="extension-element-prefixes" type="xsl:tokens"/>
+        <attribute name="exclude-result-prefixes" type="xsl:tokens"/>
+        <attribute name="version" type="decimal" use="required"/>
+        <attribute ref="xml:space"/>
+      </extension>
+    </complexContent>
+  </complexType>
+
+
+
+
+
+
+  <!-- *** top level elements *** -->
+  <!-- ***                    *** -->
+
+
+  <element name="top-level-element" type="xsl:anyType" abstract="true"/>
+  <element name="top-level-element-and-char-instruction" type="xsl:anyType" abstract="true"/>
+
+  <element name="attribute-set" substitutionGroup="xsl:top-level-element">
+
+    <!-- ***
+
+    <xsl:attribute-set
+      name = qname
+      use-attribute-sets = qnames>
+      Content: xsl:attribute*
+    </xsl:attribute-set>
+
+    -->
+
+    <complexType>
+      <complexContent>
+        <extension base="xsl:anyType">
+          <sequence minOccurs="0" maxOccurs="unbounded">
+            <element ref="xsl:attribute"/>
+          </sequence>
+          <attributeGroup ref="xsl:name"/>
+          <attributeGroup ref="xsl:use-attribute-sets"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="decimal-format" substitutionGroup="xsl:top-level-element">
+
+    <!-- ***
+
+   <xsl:decimal-format
+     name = qname
+     decimal-separator = char
+     grouping-separator = char
+     infinity = string
+     minus-sign = char
+     NaN = string
+     percent = char
+     per-mille = char
+     zero-digit = char
+     digit = char
+     pattern-separator = char />
+
+    -->
+
+    <complexType>
+      <complexContent>
+        <extension base="xsl:anyType">
+          <attribute name="name" type="xsl:QName"/>
+          <attribute name="decimal-separator" type="string" use="optional" default="."/>
+          <attribute name="grouping-separator" type="string" use="optional" default=","/>
+          <attribute name="infinity" type="string" use="optional" default="Infinity"/>
+          <attribute name="minus-sign" type="string" use="optional" default="-"/>
+          <attribute name="NaN" type="string" use="optional" default="NaN"/>
+          <attribute name="percent" type="string" use="optional" default="%"/>
+          <attribute name="per-mille" type="string" use="optional" default="&#x2030;"/>
+          <attribute name="zero-digit" type="string" use="optional" default="0"/>
+          <attribute name="digit" type="string" use="optional" default="#"/>
+          <attribute name="pattern-separator" type="string" use="optional" default=";"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="include" substitutionGroup="xsl:top-level-element" type="xsl:combine-stylesheets">
+
+    <!-- ***
+
+        <xsl:include
+          href = uri-reference />
+
+    -->
+
+  </element>
+
+
+  <element name="key" substitutionGroup="xsl:top-level-element">
+
+    <!-- ***
+
+        <xsl:key
+          name = qname
+          match = pattern
+            use = expression />
+
+    -->
+
+    <complexType>
+      <complexContent>
+        <extension base="xsl:anyType">
+          <attributeGroup ref="xsl:name"/>
+          <attribute name="match" type="xsl:pattern" use="required"/>
+          <attribute name="use" type="xsl:expression" use="required"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="namespace-alias" substitutionGroup="xsl:top-level-element">
+
+    <!-- ***
+
+    -->
+
+    <complexType>
+      <complexContent>
+        <extension base="xsl:anyType">
+          <attribute name="stylesheet-prefix" type="xsl:prefix" use="required"/>
+          <attribute name="result-prefix" type="xsl:prefix" use="required"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="output" substitutionGroup="xsl:top-level-element">
+
+    <!-- ***
+
+        <xsl:output
+          method = "xml" | "html" | "text" | qname-but-not-ncname
+          version = nmtoken
+          encoding = string
+          omit-xml-declaration = "yes" | "no"
+          standalone = "yes" | "no"
+          doctype-public = string
+          doctype-system = string
+          cdata-section-elements = qnames
+          indent = "yes" | "no"
+          media-type = string />
+
+    -->
+
+    <complexType>
+
+      <complexContent>
+        <extension base="xsl:anyType">
+          <attribute name="method">
+            <simpleType>
+              <union>
+                <simpleType>
+                  <restriction base="string">
+                    <enumeration value="xml"/>
+                    <enumeration value="html"/>
+                    <enumeration value="text"/>
+                  </restriction>
+                </simpleType>
+                <simpleType>
+                  <restriction base="xsl:QName">
+                    <pattern value="\c*:\c*"/>
+                  </restriction>
+                </simpleType>
+              </union>
+            </simpleType>
+          </attribute>
+
+          <attribute name="version" type="NMTOKEN"/>
+          <attribute name="encoding" type="string"/>
+          <attribute name="omit-xml-declaration" type="xsl:YesOrNo"/>
+          <attribute name="standalone" type="xsl:YesOrNo"/>
+          <attribute name="doctype-public" type="string"/>
+          <attribute name="doctype-system" type="string"/>
+          <attribute name="cdata-section-elements" type="xsl:QNames"/>
+          <attribute name="indent" type="xsl:YesOrNo"/>
+          <attribute name="media-type" type="string"/>
+        </extension>
+      </complexContent>
+
+    </complexType>
+
+  </element>
+
+
+  <element name="param" substitutionGroup="xsl:top-level-element" type="xsl:variable">
+
+    <!-- ***
+
+        <xsl:param
+          name = qname
+          select = expression>
+          Content: template
+        </xsl:param>
+
+    -->
+
+  </element>
+
+
+  <element name="preserve-space" substitutionGroup="xsl:top-level-element" type="xsl:preserve-space">
+
+    <!-- ***
+
+        <xsl:preserve-space
+          elements = tokens />
+
+    -->
+  </element>
+
+  <complexType name="preserve-space">
+    <complexContent>
+      <extension base="xsl:anyType">
+        <attribute name="elements" type="xsl:element-names" use="required"/>
+      </extension>
+    </complexContent>
+  </complexType>
+
+  <element name="strip-space" substitutionGroup="xsl:preserve-space" type="xsl:preserve-space"/>
+
+
+  <element name="template" substitutionGroup="xsl:top-level-element">
+
+    <!-- ***
+
+        <xsl:template
+          match = pattern
+          name = qname
+          priority = number
+          mode = qname>
+          Content: (xsl:param*, template)
+        </xsl:template>
+
+    -->
+
+    <complexType mixed="true">
+
+      <complexContent>
+        <extension base="xsl:anyType">
+          <sequence>
+            <element ref="xsl:param" minOccurs="0" maxOccurs="unbounded"/>
+            <choice minOccurs="0" maxOccurs="unbounded">
+              <element ref="xsl:top-level-element-and-char-instruction"/>
+              <element ref="xsl:instruction"/>
+              <group ref="xsl:result-element"/>
+            </choice>
+          </sequence>
+          <attribute name="match" type="xsl:pattern"/>
+          <attribute name="name" type="xsl:QName"/>
+          <attribute name="priority" type="decimal"/>
+          <attribute name="mode" type="xsl:QName"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+
+    </complexType>
+
+  </element>
+
+
+  <!-- *** top level elements and char instructions *** -->
+  <!-- ***                                          *** -->
+
+
+  <element name="variable" type="xsl:variable" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:variable
+          name = qname
+          select = expression>
+          Content: template
+        </xsl:variable>
+
+    -->
+
+  </element>
+
+
+
+
+  <!-- *** instructions *** -->
+  <!-- ***               *** -->
+
+
+  <element name="instruction" type="xsl:anyType" abstract="true"/>
+
+  <element name="char-instruction" type="xsl:anyType" abstract="true"
+           substitutionGroup="xsl:instruction"/>
+
+  <element name="apply-imports" type="xsl:anyType" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:apply-imports />
+
+    -->
+
+  </element>
+
+
+  <element name="apply-templates" substitutionGroup="xsl:char-instruction">
+
+
+    <!-- ***
+
+    <xsl:apply-templates
+      select = node-set-expression
+      mode = qname>
+      Content: (xsl:sort | xsl:with-param)*
+    </xsl:apply-templates>
+
+    -->
+
+    <complexType>
+
+      <complexContent>
+        <extension base="xsl:anyType">
+          <choice minOccurs="0" maxOccurs="unbounded">
+            <element ref="xsl:sort"/>
+            <element ref="xsl:with-param"/>
+          </choice>
+          <attribute name="select" type="xsl:expression" use="optional" default="node()"/>
+          <attribute name="mode" type="xsl:QName"/>
+        </extension>
+      </complexContent>
+
+    </complexType>
+
+  </element>
+
+
+  <element name="attribute" type="xsl:attribute-type" substitutionGroup="xsl:instruction"/>
+
+
+  <element name="call-template" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+    <xsl:call-template
+      name = qname>
+      Content: xsl:with-param*
+    </xsl:call-template>
+
+    -->
+
+    <complexType>
+      <complexContent>
+        <extension base="xsl:anyType">
+          <sequence minOccurs="0" maxOccurs="unbounded">
+            <element ref="xsl:with-param"/>
+          </sequence>
+          <attributeGroup ref="xsl:name"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="choose" substitutionGroup="xsl:char-instruction">
+
+
+    <!-- ***
+
+        <xsl:choose>
+          Content: (xsl:when+, xsl:otherwise?)
+        </xsl:choose>
+
+    -->
+
+    <complexType>
+      <complexContent>
+        <extension base="xsl:anyType">
+          <sequence>
+            <element ref="xsl:when" minOccurs="1" maxOccurs="unbounded"/>
+            <element ref="xsl:otherwise" minOccurs="0"/>
+          </sequence>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+  <element name="comment" substitutionGroup="xsl:instruction">
+
+    <!-- ***
+
+        <xsl:comment>
+          Content: template
+        </xsl:comment>
+
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <choice minOccurs="0" maxOccurs="unbounded">
+            <element ref="xsl:char-instruction"/>
+            <element ref="xsl:top-level-element-and-char-instruction"/>
+          </choice>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="copy" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+    <xsl:copy
+      use-attribute-sets = qnames>
+      Content: template
+    </xsl:copy>
+
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <group ref="xsl:template" minOccurs="0" maxOccurs="unbounded"/>
+          <attribute ref="xml:space"/>
+          <attributeGroup ref="xsl:use-attribute-sets"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="copy-of" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:copy-of
+          select = expression />
+
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <attributeGroup ref="xsl:select-required"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="element" substitutionGroup="xsl:instruction">
+
+    <!-- ***
+
+        <xsl:element
+          name = { qname }
+          namespace = { uri-reference }
+          use-attribute-sets = qnames>
+          Content: template
+        </xsl:element>
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <group ref="xsl:template" minOccurs="0" maxOccurs="unbounded"/>
+          <attributeGroup ref="xsl:name-avt"/>
+          <attribute name="namespace" type="xsl:expr-avt"/>
+          <attributeGroup ref="xsl:use-attribute-sets"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="fallback" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:fallback>
+          Content: template
+        </xsl:fallback>
+
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <group ref="xsl:template" minOccurs="0" maxOccurs="unbounded"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="for-each" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:for-each
+          select = node-set-expression>
+          Content: (xsl:sort*, template)
+        </xsl:for-each>
+
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <sequence>
+            <element ref="xsl:sort" minOccurs="0" maxOccurs="unbounded"/>
+            <choice minOccurs="0" maxOccurs="unbounded">
+              <element ref="xsl:top-level-element-and-char-instruction"/>
+              <element ref="xsl:instruction"/>
+              <group ref="xsl:result-element"/>
+            </choice>
+          </sequence>
+          <attributeGroup ref="xsl:select-required"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+  <element name="if" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:if
+          test = boolean-expression>
+          Content: template
+        </xsl:if>
+
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <group ref="xsl:template" minOccurs="0" maxOccurs="unbounded"/>
+          <attribute name="test" type="xsl:expression" use="required"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="message" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:message
+          terminate = "yes" | "no">
+          Content: template
+        </xsl:message>
+
+    -->
+
+    <complexType mixed="true">
+
+      <complexContent>
+        <extension base="xsl:anyType">
+          <group ref="xsl:template" minOccurs="0" maxOccurs="unbounded"/>
+          <attribute ref="xml:space"/>
+          <attribute name="terminate" use="optional" default="no" type="xsl:YesOrNo"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="number" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:number
+          level = "single" | "multiple" | "any"
+          count = pattern
+          from = pattern
+          value = number-expression
+          format = { string }
+          lang = { nmtoken }
+          letter-value = { "alphabetic" | "traditional" }
+          grouping-separator = { char }
+            grouping-size = { number } />
+
+    -->
+
+    <complexType>
+
+      <complexContent>
+        <extension base="xsl:anyType">
+          <attribute name="level" use="optional" default="single">
+            <simpleType>
+              <restriction base="NMTOKEN">
+                <enumeration value="single"/>
+                <enumeration value="multiple"/>
+                <enumeration value="any"/>
+              </restriction>
+            </simpleType>
+          </attribute>
+
+          <attribute name="count" type="xsl:pattern"/>
+          <attribute name="from" type="xsl:pattern"/>
+          <attribute name="value" type="xsl:expression"/>
+          <attribute name="format" type="xsl:expr-avt" use="optional" default="1"/>
+          <attribute name="lang" type="xsl:expr-avt"/>
+          <attribute name="letter-value" type="xsl:expr-avt"/>
+          <attribute name="grouping-separator" type="xsl:expr-avt"/>
+          <attribute name="grouping-size" type="xsl:expr-avt"/>
+        </extension>
+      </complexContent>
+
+    </complexType>
+
+  </element>
+
+
+  <element name="processing-instruction" substitutionGroup="xsl:instruction">
+
+    <!-- ***
+
+        <xsl:processing-instruction
+          name = { ncname }>
+          Content: template
+        </xsl:processing-instruction>
+
+    -->
+
+    <complexType mixed="true">
+
+      <complexContent>
+        <extension base="xsl:anyType">
+          <choice minOccurs="0" maxOccurs="unbounded">
+            <element ref="xsl:char-instruction"/>
+            <element ref="xsl:top-level-element-and-char-instruction"/>
+          </choice>
+          <attributeGroup ref="xsl:name-avt"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="text" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:text
+          disable-output-escaping = "yes" | "no">
+          Content: #PCDATA
+        </xsl:text>
+
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <attributeGroup ref="xsl:disable-output-escaping"/>
+          <attribute ref="xml:lang"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="value-of" substitutionGroup="xsl:char-instruction">
+
+    <!-- ***
+
+        <xsl:value-of
+          select = string-expression
+          disable-output-escaping = "yes" | "no" />
+
+    -->
+
+    <complexType>
+      <complexContent>
+        <extension base="xsl:anyType">
+          <attributeGroup ref="xsl:select-required"/>
+          <attributeGroup ref="xsl:disable-output-escaping"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+
+  <!-- *** orphans *** -->
+  <!-- ***          *** -->
+
+  <element name="import" type="xsl:combine-stylesheets">
+
+    <!-- ***
+
+      <xsl:import
+            href = uri-reference />
+    -->
+
+  </element>
+
+
+  <element name="otherwise">
+
+    <!-- ***
+
+        <xsl:otherwise>
+          Content: template
+        </xsl:otherwise>
+
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <group ref="xsl:template" minOccurs="0" maxOccurs="unbounded"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="sort">
+
+    <!-- ***
+
+        xsl:sort
+          select = string-expression
+          lang = { nmtoken }
+          data-type = { "text" | "number" | qname-but-not-ncname }
+          order = { "ascending" | "descending" }
+          case-order = { "upper-first" | "lower-first" } />
+
+    -->
+
+    <complexType>
+      <complexContent>
+        <extension base="xsl:anyType">
+          <attribute name="select" type="xsl:expression" use="optional" default="."/>
+          <attribute name="lang" type="xsl:expr-avt"/>
+          <attribute name="data-type" use="optional" default="text">
+            <simpleType>
+              <union memberTypes="xsl:expr-avt">
+                <simpleType>
+                  <restriction base="string">
+                    <enumeration value="text" />
+                    <enumeration value="number" />
+                  </restriction>
+                </simpleType>
+              </union>
+            </simpleType>
+          </attribute>
+          <attribute name="order" use="optional" default="ascending">
+            <simpleType>
+              <union memberTypes="xsl:expr-avt">
+                <simpleType>
+                  <restriction base="string">
+                    <enumeration value="ascending" />
+                    <enumeration value="descending" />
+                  </restriction>
+                </simpleType>
+              </union>
+            </simpleType>
+          </attribute>
+          <attribute name="case-order">
+            <simpleType>
+              <union memberTypes="xsl:expr-avt">
+                <simpleType>
+                  <restriction base="string">
+                    <enumeration value="upper-first" />
+                    <enumeration value="lower-first" />
+                  </restriction>
+                </simpleType>
+              </union>
+            </simpleType>
+          </attribute>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="when">
+
+    <!-- ***
+        <xsl:when
+          test = boolean-expression>
+          Content: template
+        </xsl:when>
+    -->
+
+    <complexType mixed="true">
+      <complexContent>
+        <extension base="xsl:anyType">
+          <group ref="xsl:template" minOccurs="0" maxOccurs="unbounded"/>
+          <attribute name="test" type="xsl:expression" use="required"/>
+          <attribute ref="xml:space"/>
+        </extension>
+      </complexContent>
+    </complexType>
+
+  </element>
+
+
+  <element name="with-param" type="xsl:variable">
+
+    <!-- ***
+
+        <xsl:with-param
+          name = qname
+          select = expression>
+          Content: template
+        </xsl:with-param>
+    -->
+
+  </element>
+
+
+
+
+
+
+  <!-- *** utils - internal types and groups *** -->
+  <!-- *** not for public use                *** -->
+  <!-- ***                                   *** -->
+
+  <complexType name="attribute-type" mixed="true">
+
+    <!-- ***
+
+     <xsl:attribute
+       name = { qname }
+       namespace = { uri-reference }>
+       Content: template
+     </xsl:attribute>
+
+    -->
+    <complexContent>
+      <extension base="xsl:anyType">
+        <choice minOccurs="0" maxOccurs="unbounded">
+          <element ref="xsl:char-instruction"/>
+          <element ref="xsl:top-level-element-and-char-instruction"/>
+        </choice>
+
+        <attributeGroup ref="xsl:name-avt"/>
+        <attribute name="namespace" type="xsl:expr-avt"/>
+        <attribute ref="xml:space"/>
+      </extension>
+    </complexContent>
+
+  </complexType>
+
+
+  <simpleType name="tokens">
+    <list itemType="token"/>
+  </simpleType>
+
+  <simpleType name="QNames">
+    <list itemType="xsl:QName"/>
+  </simpleType>
+
+  <attributeGroup name="name">
+    <attribute name="name" type="xsl:QName" use="required"/>
+  </attributeGroup>
+
+  <attributeGroup name="name-avt">
+    <attribute name="name" type="xsl:expr-avt" use="required"/>
+  </attributeGroup>
+
+  <attributeGroup name="select-optional">
+    <attribute name="select" type="xsl:expression"/>
+  </attributeGroup>
+
+  <attributeGroup name="select-required">
+    <attribute name="select" type="xsl:expression" use="required"/>
+  </attributeGroup>
+
+  <attributeGroup name="use-attribute-sets">
+    <attribute name="use-attribute-sets" type="xsl:QNames"/>
+  </attributeGroup>
+
+
+
+
+  <group name="template">
+    <choice>
+      <element ref="xsl:top-level-element-and-char-instruction"/>
+      <element ref="xsl:instruction"/>
+      <group ref="xsl:result-element"/>
+    </choice>
+  </group>
+
+  <complexType name="combine-stylesheets">
+    <complexContent>
+      <extension base="xsl:anyType">
+        <attribute name="href" type="anyURI" use="required"/>
+      </extension>
+    </complexContent>
+  </complexType>
+
+  <simpleType name="YesOrNo">
+    <restriction base="string">
+      <enumeration value="yes"/>
+      <enumeration value="no"/>
+    </restriction>
+  </simpleType>
+
+  <simpleType name="QName">
+    <union memberTypes="NCName QName"/>
+  </simpleType>
+
+  <simpleType name="element-names">
+    <list>
+      <simpleType>
+        <union memberTypes="QName">
+          <simpleType>
+            <restriction base="string">
+              <pattern value="\*"/>
+              <pattern value="\i\c*:\*"/>
+            </restriction>
+          </simpleType>
+        </union>
+      </simpleType>
+    </list>
+  </simpleType>
+
+  <attributeGroup name="disable-output-escaping">
+    <attribute name="disable-output-escaping" type="xsl:YesOrNo"
+               use="optional" default="no"/>
+  </attributeGroup>
+
+  <complexType name="variable" mixed="true">
+    <complexContent>
+      <extension base="xsl:anyType">
+        <group ref="xsl:template" minOccurs="0" maxOccurs="unbounded"/>
+        <attributeGroup ref="xsl:name"/>
+        <attributeGroup ref="xsl:select-optional"/>
+        <attribute name="as" use="optional" /> <!-- supported by Saxon XSLT Processor -->
+      </extension>
+    </complexContent>
+  </complexType>
+
+
+  <simpleType name="expr-avt">
+    <restriction base="string">
+      <!-- <pattern
+     value="([^\{\}]|\{\{|\}\})*\{([^&quot;'\{\}]|&quot;[^&quot;]*&quot;|'[^']*')+\}([^\{\}]|\{\{|\}\}|\{([^&quot;'\{\}]|&quot;[^&quot;]*&quot;|'[^']*')+\})*"/> -->
+    </restriction>
+  </simpleType>
+
+  <simpleType name="expression">
+    <restriction base="string">
+      <!-- ****
+
+      patterns go here
+
+      -->
+    </restriction>
+  </simpleType>
+
+  <simpleType name="pattern">
+    <restriction base="string">
+      <!-- ***
+
+      patterns go here
+
+      -->
+    </restriction>
+  </simpleType>
+
+  <simpleType name="prefix">
+    <union memberTypes="NCName">
+      <simpleType>
+        <restriction base="string">
+          <enumeration value="#default"/>
+        </restriction>
+      </simpleType>
+    </union>
+  </simpleType>
+
+
+  <complexType name="anyType">
+    <anyAttribute namespace="##other" processContents="skip"/>
+  </complexType>
+</schema>
diff --git a/xml/impl/resources/standardSchemas/xslt-2_0.xsd b/xml/impl/resources/standardSchemas/xslt-2_0.xsd
new file mode 100644
index 0000000..f268991
--- /dev/null
+++ b/xml/impl/resources/standardSchemas/xslt-2_0.xsd
@@ -0,0 +1,1152 @@
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3.org/1999/XSL/Transform" elementFormDefault="qualified" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<xs:annotation>
+  <xs:documentation>
+
+    This is a schema for XSLT 2.0 stylesheets.
+
+    It defines all the elements that appear in the XSLT namespace; it also
+    provides hooks that allow the inclusion of user-defined literal result elements,
+    extension instructions, and top-level data elements.
+
+    The schema is derived (with kind permission) from a schema for XSLT 1.0 stylesheets
+    produced by Asir S Vedamuthu of WebMethods Inc.
+
+    This schema is available for use under the conditions of the W3C Software License
+    published at http://www.w3.org/Consortium/Legal/copyright-software-19980720
+
+    The schema is organized as follows:
+
+    PART A: definitions of complex types and model groups used as the basis
+            for element definitions
+    PART B: definitions of individual XSLT elements
+    PART C: definitions for literal result elements
+    PART D: definitions of simple types used in attribute definitions
+
+    This schema does not attempt to define all the constraints that apply to a valid
+    XSLT 2.0 stylesheet module. It is the intention that all valid stylesheet modules
+    should conform to this schema; however, the schema is non-normative and in the event
+    of any conflict, the text of the Recommendation takes precedence.
+
+    This schema does not implement the special rules that apply when a stylesheet
+    has sections that use forwards-compatible-mode. In this mode, setting version="3.0"
+    allows elements from the XSLT namespace to be used that are not defined in XSLT 2.0.
+
+    Simplified stylesheets (those with a literal result element as the outermost element)
+    will validate against this schema only if validation starts in lax mode.
+
+    This version is dated 2005-02-11
+    Authors: Michael H Kay, Saxonica Limited
+             Jeni Tennison, Jeni Tennison Consulting Ltd.
+
+  </xs:documentation>
+</xs:annotation>
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<!--
+The declaration of xml:space and xml:lang may need to be commented out because
+of problems processing the schema using various tools
+-->
+
+<xs:import namespace="http://www.w3.org/XML/1998/namespace"
+  schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+<!--
+    An XSLT stylesheet may contain an in-line schema within an xsl:import-schema element,
+    so the Schema for schemas needs to be imported
+-->
+
+<xs:import namespace="http://www.w3.org/2001/XMLSchema"
+                  schemaLocation="http://www.w3.org/2001/XMLSchema.xsd"/>
+
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<xs:annotation>
+  <xs:documentation>
+    PART A: definitions of complex types and model groups used as the basis
+            for element definitions
+  </xs:documentation>
+</xs:annotation>
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<xs:complexType name="generic-element-type" mixed="true">
+  <xs:attribute name="default-collation" type="xsl:uri-list"/>
+  <xs:attribute name="exclude-result-prefixes" type="xsl:prefix-list-or-all"/>
+  <xs:attribute name="extension-element-prefixes" type="xsl:prefix-list"/>
+  <xs:attribute name="use-when" type="xsl:expression"/>
+  <xs:attribute name="xpath-default-namespace" type="xs:anyURI"/>
+  <xs:anyAttribute namespace="##other" processContents="lax"/>
+</xs:complexType>
+
+<xs:complexType name="versioned-element-type" mixed="true">
+  <xs:complexContent>
+    <xs:extension base="xsl:generic-element-type">
+      <xs:attribute name="version" type="xs:decimal" use="optional"/>
+    </xs:extension>
+  </xs:complexContent>
+</xs:complexType>
+
+<xs:complexType name="element-only-versioned-element-type" mixed="false">
+  <xs:complexContent>
+    <xs:restriction base="xsl:versioned-element-type">
+      <xs:anyAttribute namespace="##other" processContents="lax"/>
+    </xs:restriction>
+  </xs:complexContent>
+</xs:complexType>
+
+<xs:complexType name="sequence-constructor">
+  <xs:complexContent mixed="true">
+    <xs:extension base="xsl:versioned-element-type">
+      <xs:group ref="xsl:sequence-constructor-group" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:extension>
+  </xs:complexContent>
+</xs:complexType>
+
+<xs:group name="sequence-constructor-group">
+  <xs:choice>
+    <xs:element ref="xsl:variable"/>
+    <xs:element ref="xsl:instruction"/>
+    <xs:group ref="xsl:result-elements"/>
+  </xs:choice>
+</xs:group>
+
+<xs:element name="declaration" type="xsl:generic-element-type" abstract="true"/>
+
+<xs:element name="instruction" type="xsl:versioned-element-type" abstract="true"/>
+
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<xs:annotation>
+  <xs:documentation>
+    PART B: definitions of individual XSLT elements
+    Elements are listed in alphabetical order.
+  </xs:documentation>
+</xs:annotation>
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<xs:element name="analyze-string" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:matching-substring" minOccurs="0"/>
+          <xs:element ref="xsl:non-matching-substring" minOccurs="0"/>
+          <xs:element ref="xsl:fallback" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="select" type="xsl:expression" use="required"/>
+        <xs:attribute name="regex" type="xsl:avt" use="required"/>
+        <xs:attribute name="flags" type="xsl:avt" default=""/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="apply-imports" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:with-param" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="apply-templates" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element ref="xsl:sort"/>
+          <xs:element ref="xsl:with-param"/>
+        </xs:choice>
+        <xs:attribute name="select" type="xsl:expression" default="child::node()"/>
+        <xs:attribute name="mode" type="xsl:mode"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="attribute" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="name" type="xsl:avt" use="required"/>
+        <xs:attribute name="namespace" type="xsl:avt"/>
+        <xs:attribute name="select" type="xsl:expression"/>
+        <xs:attribute name="separator" type="xsl:avt"/>
+        <xs:attribute name="type" type="xsl:QName"/>
+        <xs:attribute name="validation" type="xsl:validation-type"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="attribute-set" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:sequence minOccurs="0" maxOccurs="unbounded">
+          <xs:element ref="xsl:attribute"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xsl:QName" use="required"/>
+        <xs:attribute name="use-attribute-sets" type="xsl:QNames" default=""/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="call-template" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:with-param" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xsl:QName" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="character-map" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:output-character" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xsl:QName" use="required"/>
+        <xs:attribute name="use-character-maps" type="xsl:QNames" default=""/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="choose" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:when" maxOccurs="unbounded"/>
+          <xs:element ref="xsl:otherwise" minOccurs="0"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="comment" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="select" type="xsl:expression"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="copy" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="copy-namespaces" type="xsl:yes-or-no" default="yes"/>
+        <xs:attribute name="inherit-namespaces" type="xsl:yes-or-no" default="yes"/>
+        <xs:attribute name="use-attribute-sets" type="xsl:QNames" default=""/>
+        <xs:attribute name="type" type="xsl:QName"/>
+        <xs:attribute name="validation" type="xsl:validation-type"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="copy-of" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:versioned-element-type">
+        <xs:attribute name="select" type="xsl:expression" use="required"/>
+        <xs:attribute name="copy-namespaces" type="xsl:yes-or-no" default="yes"/>
+        <xs:attribute name="type" type="xsl:QName"/>
+        <xs:attribute name="validation" type="xsl:validation-type"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="decimal-format" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:attribute name="name" type="xsl:QName"/>
+        <xs:attribute name="decimal-separator" type="xsl:char" default="."/>
+        <xs:attribute name="grouping-separator" type="xsl:char" default=","/>
+        <xs:attribute name="infinity" type="xs:string" default="Infinity"/>
+        <xs:attribute name="minus-sign" type="xsl:char" default="-"/>
+        <xs:attribute name="NaN" type="xs:string" default="NaN"/>
+        <xs:attribute name="percent" type="xsl:char" default="%"/>
+        <xs:attribute name="per-mille" type="xsl:char" default="&#x2030;"/>
+        <xs:attribute name="zero-digit" type="xsl:char" default="0"/>
+        <xs:attribute name="digit" type="xsl:char" default="#"/>
+        <xs:attribute name="pattern-separator" type="xsl:char" default=";"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="element" substitutionGroup="xsl:instruction">
+  <xs:complexType mixed="true">
+    <xs:complexContent>
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="name" type="xsl:avt" use="required"/>
+        <xs:attribute name="namespace" type="xsl:avt"/>
+        <xs:attribute name="inherit-namespaces" type="xsl:yes-or-no" default="yes"/>
+        <xs:attribute name="use-attribute-sets" type="xsl:QNames" default=""/>
+        <xs:attribute name="type" type="xsl:QName"/>
+        <xs:attribute name="validation" type="xsl:validation-type"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="fallback" substitutionGroup="xsl:instruction" type="xsl:sequence-constructor"/>
+
+<xs:element name="for-each" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:sort" minOccurs="0" maxOccurs="unbounded"/>
+          <xs:group ref="xsl:sequence-constructor-group" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="select" type="xsl:expression" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="for-each-group" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:sort" minOccurs="0" maxOccurs="unbounded"/>
+          <xs:group ref="xsl:sequence-constructor-group" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="select" type="xsl:expression" use="required"/>
+        <xs:attribute name="group-by" type="xsl:expression"/>
+        <xs:attribute name="group-adjacent" type="xsl:expression"/>
+        <xs:attribute name="group-starting-with" type="xsl:pattern"/>
+        <xs:attribute name="group-ending-with" type="xsl:pattern"/>
+        <xs:attribute name="collation" type="xs:anyURI"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="function" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:param" minOccurs="0" maxOccurs="unbounded"/>
+          <xs:group ref="xsl:sequence-constructor-group" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xsl:QName" use="required"/>
+        <xs:attribute name="override" type="xsl:yes-or-no" default="yes"/>
+        <xs:attribute name="as" type="xsl:sequence-type" default="item()*"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="if" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="test" type="xsl:expression" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="import">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:attribute name="href" type="xs:anyURI" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="import-schema" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xs:schema" minOccurs="0" maxOccurs="1"/>
+        </xs:sequence>
+        <xs:attribute name="namespace" type="xs:anyURI"/>
+        <xs:attribute name="schema-location" type="xs:anyURI"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="include" substitutionGroup="xsl:declaration">
+    <xs:complexType>
+      <xs:complexContent>
+        <xs:extension base="xsl:element-only-versioned-element-type">
+          <xs:attribute name="href" type="xs:anyURI" use="required"/>
+        </xs:extension>
+      </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="key" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="name" type="xsl:QName" use="required"/>
+        <xs:attribute name="match" type="xsl:pattern" use="required"/>
+        <xs:attribute name="use" type="xsl:expression"/>
+        <xs:attribute name="collation" type="xs:anyURI"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="matching-substring" type="xsl:sequence-constructor"/>
+
+<xs:element name="message" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="select" type="xsl:expression"/>
+        <xs:attribute name="terminate" type="xsl:avt" default="no"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="namespace" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="name" type="xsl:avt" use="required"/>
+        <xs:attribute name="select" type="xsl:expression"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="namespace-alias" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:attribute name="stylesheet-prefix" type="xsl:prefix-or-default" use="required"/>
+        <xs:attribute name="result-prefix" type="xsl:prefix-or-default" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="next-match" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+          <xs:element ref="xsl:with-param"/>
+          <xs:element ref="xsl:fallback"/>
+        </xs:choice>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="non-matching-substring" type="xsl:sequence-constructor"/>
+
+<xs:element name="number" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:versioned-element-type">
+        <xs:attribute name="value" type="xsl:expression"/>
+        <xs:attribute name="select" type="xsl:expression"/>
+        <xs:attribute name="level" type="xsl:level" default="single"/>
+        <xs:attribute name="count" type="xsl:pattern"/>
+        <xs:attribute name="from" type="xsl:pattern"/>
+        <xs:attribute name="format" type="xsl:avt" default="1"/>
+        <xs:attribute name="lang" type="xsl:avt"/>
+        <xs:attribute name="letter-value" type="xsl:avt"/>
+        <xs:attribute name="ordinal" type="xsl:avt"/>
+        <xs:attribute name="grouping-separator" type="xsl:avt"/>
+        <xs:attribute name="grouping-size" type="xsl:avt"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="otherwise" type="xsl:sequence-constructor"/>
+
+<xs:element name="output" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:generic-element-type">
+        <xs:attribute name="name" type="xsl:QName"/>
+        <xs:attribute name="method" type="xsl:method"/>
+        <xs:attribute name="byte-order-mark" type="xsl:yes-or-no"/>
+        <xs:attribute name="cdata-section-elements" type="xsl:QNames"/>
+        <xs:attribute name="doctype-public" type="xs:string"/>
+        <xs:attribute name="doctype-system" type="xs:string"/>
+        <xs:attribute name="encoding" type="xs:string"/>
+        <xs:attribute name="escape-uri-attributes" type="xsl:yes-or-no"/>
+        <xs:attribute name="include-content-type" type="xsl:yes-or-no"/>
+        <xs:attribute name="indent" type="xsl:yes-or-no"/>
+        <xs:attribute name="media-type" type="xs:string"/>
+        <xs:attribute name="normalization-form" type="xs:NMTOKEN"/>
+        <xs:attribute name="omit-xml-declaration" type="xsl:yes-or-no"/>
+        <xs:attribute name="standalone" type="xsl:yes-or-no-or-omit"/>
+        <xs:attribute name="undeclare-prefixes" type="xsl:yes-or-no"/>
+        <xs:attribute name="use-character-maps" type="xsl:QNames"/>
+        <xs:attribute name="version" type="xs:NMTOKEN"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="output-character">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:attribute name="character" type="xsl:char" use="required"/>
+        <xs:attribute name="string" type="xs:string" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="param">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="name" type="xsl:QName" use="required"/>
+        <xs:attribute name="select" type="xsl:expression"/>
+        <xs:attribute name="as" type="xsl:sequence-type"/>
+        <xs:attribute name="required" type="xsl:yes-or-no"/>
+        <xs:attribute name="tunnel" type="xsl:yes-or-no"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="perform-sort" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:sort" minOccurs="1" maxOccurs="unbounded"/>
+          <xs:group ref="xsl:sequence-constructor-group" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="select" type="xsl:expression"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="preserve-space" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:attribute name="elements" type="xsl:nametests" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="processing-instruction" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="name" type="xsl:avt" use="required"/>
+        <xs:attribute name="select" type="xsl:expression"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="result-document" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="format" type="xsl:avt"/>
+        <xs:attribute name="href" type="xsl:avt"/>
+        <xs:attribute name="type" type="xsl:QName"/>
+        <xs:attribute name="validation" type="xsl:validation-type"/>
+        <xs:attribute name="method" type="xsl:avt"/>
+        <xs:attribute name="byte-order-mark" type="xsl:avt"/>
+        <xs:attribute name="cdata-section-elements" type="xsl:avt"/>
+        <xs:attribute name="doctype-public" type="xsl:avt"/>
+        <xs:attribute name="doctype-system" type="xsl:avt"/>
+        <xs:attribute name="encoding" type="xsl:avt"/>
+        <xs:attribute name="escape-uri-attributes" type="xsl:avt"/>
+        <xs:attribute name="include-content-type" type="xsl:avt"/>
+        <xs:attribute name="indent" type="xsl:avt"/>
+        <xs:attribute name="media-type" type="xsl:avt"/>
+        <xs:attribute name="normalization-form" type="xsl:avt"/>
+        <xs:attribute name="omit-xml-declaration" type="xsl:avt"/>
+        <xs:attribute name="standalone" type="xsl:avt"/>
+        <xs:attribute name="undeclare-prefixes" type="xsl:avt"/>
+        <xs:attribute name="use-character-maps" type="xsl:QNames"/>
+        <xs:attribute name="output-version" type="xsl:avt"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="sequence" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="select" type="xsl:expression"/>
+        <xs:attribute name="as" type="xsl:sequence-type"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="sort">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="select" type="xsl:expression"/>
+        <xs:attribute name="lang" type="xsl:avt"/>
+        <xs:attribute name="data-type" default="text">
+          <xs:simpleType>
+            <xs:union memberTypes="xsl:avt">
+              <xs:simpleType>
+                <xs:restriction base="xs:string">
+                  <xs:enumeration value="text" />
+                  <xs:enumeration value="number" />
+                </xs:restriction>
+              </xs:simpleType>
+            </xs:union>
+          </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="order" default="ascending">
+          <xs:simpleType>
+            <xs:union memberTypes="xsl:avt">
+              <xs:simpleType>
+                <xs:restriction base="xs:string">
+                  <xs:enumeration value="ascending" />
+                  <xs:enumeration value="descending" />
+                </xs:restriction>
+              </xs:simpleType>
+            </xs:union>
+          </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="case-order">
+          <xs:simpleType>
+            <xs:union memberTypes="xsl:avt">
+              <xs:simpleType>
+                <xs:restriction base="xs:string">
+                  <xs:enumeration value="upp-first" />
+                  <xs:enumeration value="lower-first" />
+                </xs:restriction>
+              </xs:simpleType>
+            </xs:union>
+          </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="collation" type="xsl:avt"/>
+        <xs:attribute name="stable" type="xsl:yes-or-no"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="strip-space" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:element-only-versioned-element-type">
+        <xs:attribute name="elements" type="xsl:nametests" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="stylesheet" substitutionGroup="xsl:transform"/>
+
+<xs:element name="template" substitutionGroup="xsl:declaration">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:versioned-element-type">
+        <xs:sequence>
+          <xs:element ref="xsl:param" minOccurs="0" maxOccurs="unbounded"/>
+          <xs:group ref="xsl:sequence-constructor-group" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="match" type="xsl:pattern"/>
+        <xs:attribute name="priority" type="xs:decimal"/>
+        <xs:attribute name="mode" type="xsl:modes"/>
+        <xs:attribute name="name" type="xsl:QName"/>
+        <xs:attribute name="as" type="xsl:sequence-type" default="item()*"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:complexType name="text-element-base-type">
+  <xs:simpleContent>
+    <xs:restriction base="xsl:versioned-element-type">
+      <xs:simpleType>
+        <xs:restriction base="xs:string"/>
+      </xs:simpleType>
+      <xs:anyAttribute namespace="##other" processContents="lax"/>
+    </xs:restriction>
+  </xs:simpleContent>
+</xs:complexType>
+
+<xs:element name="text" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:simpleContent>
+      <xs:extension base="xsl:text-element-base-type">
+        <xs:attribute name="disable-output-escaping" type="xsl:yes-or-no" default="no"/>
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:complexType name="transform-element-base-type">
+  <xs:complexContent>
+    <xs:restriction base="xsl:element-only-versioned-element-type">
+      <xs:attribute name="version" type="xs:decimal" use="required"/>
+      <xs:anyAttribute namespace="##other" processContents="lax"/>
+    </xs:restriction>
+  </xs:complexContent>
+</xs:complexType>
+
+<xs:element name="transform">
+  <xs:complexType>
+    <xs:complexContent>
+      <xs:extension base="xsl:transform-element-base-type">
+        <xs:sequence>
+          <xs:element ref="xsl:import" minOccurs="0" maxOccurs="unbounded"/>
+          <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element ref="xsl:declaration"/>
+            <xs:element ref="xsl:variable"/>
+            <xs:element ref="xsl:param"/>
+            <xs:any namespace="##other" processContents="lax"/> <!-- weaker than XSLT 1.0 -->
+          </xs:choice>
+        </xs:sequence>
+        <xs:attribute name="id" type="xs:ID"/>
+        <xs:attribute name="default-validation" type="xsl:validation-strip-or-preserve" default="strip"/>
+        <xs:attribute name="input-type-annotations" type="xsl:input-type-annotations-type" default="unspecified"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="value-of" substitutionGroup="xsl:instruction">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="select" type="xsl:expression"/>
+        <xs:attribute name="separator" type="xsl:avt"/>
+        <xs:attribute name="disable-output-escaping" type="xsl:yes-or-no" default="no"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="variable">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="name" type="xsl:QName" use="required"/>
+        <xs:attribute name="select" type="xsl:expression" use="optional"/>
+        <xs:attribute name="as" type="xsl:sequence-type" use="optional"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="when">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="test" type="xsl:expression" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="with-param">
+  <xs:complexType>
+    <xs:complexContent mixed="true">
+      <xs:extension base="xsl:sequence-constructor">
+        <xs:attribute name="name" type="xsl:QName" use="required"/>
+        <xs:attribute name="select" type="xsl:expression"/>
+        <xs:attribute name="as" type="xsl:sequence-type"/>
+        <xs:attribute name="tunnel" type="xsl:yes-or-no"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+</xs:element>
+
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<xs:annotation>
+  <xs:documentation>
+    PART C: definition of literal result elements
+
+    There are three ways to define the literal result elements
+    permissible in a stylesheet.
+
+    (a) do nothing. This allows any element to be used as a literal
+        result element, provided it is not in the XSLT namespace
+
+    (b) declare all permitted literal result elements as members
+        of the xsl:literal-result-element substitution group
+
+    (c) redefine the model group xsl:result-elements to accommodate
+        all permitted literal result elements.
+
+    Literal result elements are allowed to take certain attributes
+    in the XSLT namespace. These are defined in the attribute group
+    literal-result-element-attributes, which can be included in the
+    definition of any literal result element.
+
+  </xs:documentation>
+</xs:annotation>
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<xs:element name="literal-result-element" abstract="true" type="xs:anyType"/>
+
+<xs:attributeGroup name="literal-result-element-attributes">
+  <xs:attribute name="default-collation" form="qualified" type="xsl:uri-list"/>
+  <xs:attribute name="extension-element-prefixes" form="qualified" type="xsl:prefixes"/>
+  <xs:attribute name="exclude-result-prefixes" form="qualified" type="xsl:prefixes"/>
+  <xs:attribute name="xpath-default-namespace" form="qualified" type="xs:anyURI"/>
+  <xs:attribute name="inherit-namespaces" form="qualified" type="xsl:yes-or-no" default="yes"/>
+  <xs:attribute name="use-attribute-sets" form="qualified" type="xsl:QNames" default=""/>
+  <xs:attribute name="use-when" form="qualified" type="xsl:expression"/>
+  <xs:attribute name="version" form="qualified" type="xs:decimal"/>
+  <xs:attribute name="type" form="qualified" type="xsl:QName"/>
+  <xs:attribute name="validation" form="qualified" type="xsl:validation-type"/>
+</xs:attributeGroup>
+
+<xs:group name="result-elements">
+  <xs:choice>
+    <xs:element ref="xsl:literal-result-element"/>
+    <xs:any namespace="##other" processContents="lax"/>
+    <xs:any namespace="##local" processContents="lax"/>
+  </xs:choice>
+</xs:group>
+
+
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<xs:annotation>
+  <xs:documentation>
+    PART D: definitions of simple types used in stylesheet attributes
+  </xs:documentation>
+</xs:annotation>
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+<xs:simpleType name="avt">
+  <xs:annotation>
+    <xs:documentation>
+      This type is used for all attributes that allow an attribute value template.
+      The general rules for the syntax of attribute value templates, and the specific
+      rules for each such attribute, are described in the XSLT 2.0 Recommendation.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:string"/>
+</xs:simpleType>
+
+<xs:simpleType name="char">
+  <xs:annotation>
+    <xs:documentation>
+      A string containing exactly one character.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:string">
+    <xs:length value="1"/>
+  </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="expression">
+  <xs:annotation>
+    <xs:documentation>
+      An XPath 2.0 expression.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:token">
+    <xs:pattern value=".+"/>
+  </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="input-type-annotations-type">
+  <xs:annotation>
+    <xs:documentation>
+      Describes how type annotations in source documents are handled.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:token">
+    <xs:enumeration value="preserve"/>
+    <xs:enumeration value="strip"/>
+    <xs:enumeration value="unspecified"/>
+  </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="level">
+  <xs:annotation>
+    <xs:documentation>
+      The level attribute of xsl:number:
+      one of single, multiple, or any.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:NCName">
+    <xs:enumeration value="single"/>
+    <xs:enumeration value="multiple"/>
+    <xs:enumeration value="any"/>
+  </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="mode">
+  <xs:annotation>
+    <xs:documentation>
+      The mode attribute of xsl:apply-templates:
+      either a QName, or #current, or #default.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:union memberTypes="xsl:QName">
+    <xs:simpleType>
+      <xs:restriction base="xs:token">
+        <xs:enumeration value="#default"/>
+        <xs:enumeration value="#current"/>
+      </xs:restriction>
+    </xs:simpleType>
+  </xs:union>
+</xs:simpleType>
+
+<xs:simpleType name="modes">
+  <xs:annotation>
+    <xs:documentation>
+      The mode attribute of xsl:template:
+      either a list, each member being either a QName or #default;
+      or the value #all
+    </xs:documentation>
+  </xs:annotation>
+  <xs:union>
+    <xs:simpleType>
+      <xs:list>
+        <xs:simpleType>
+          <xs:union memberTypes="xsl:QName">
+            <xs:simpleType>
+              <xs:restriction base="xs:token">
+                <xs:enumeration value="#default"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:union>
+        </xs:simpleType>
+      </xs:list>
+    </xs:simpleType>
+    <xs:simpleType>
+      <xs:restriction base="xs:token">
+        <xs:enumeration value="#all"/>
+      </xs:restriction>
+    </xs:simpleType>
+  </xs:union>
+</xs:simpleType>
+
+<xs:simpleType name="nametests">
+  <xs:annotation>
+    <xs:documentation>
+      A list of NameTests, as defined in the XPath 2.0 Recommendation.
+      Each NameTest is either a QName, or "*", or "prefix:*", or "*:localname"
+    </xs:documentation>
+  </xs:annotation>
+  <xs:list>
+    <xs:simpleType>
+      <xs:union memberTypes="xsl:QName">
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:enumeration value="*"/>
+          </xs:restriction>
+        </xs:simpleType>
+        <xs:simpleType>
+          <xs:restriction base="xs:token">
+            <xs:pattern value="\i\c*:\*"/>
+            <xs:pattern value="\*:\i\c*"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:union>
+    </xs:simpleType>
+  </xs:list>
+</xs:simpleType>
+
+<xs:simpleType name="prefixes">
+  <xs:list itemType="xs:NCName"/>
+</xs:simpleType>
+
+<xs:simpleType name="prefix-list-or-all">
+  <xs:union memberTypes="xsl:prefix-list">
+    <xs:simpleType>
+      <xs:restriction base="xs:token">
+        <xs:enumeration value="#all"/>
+      </xs:restriction>
+    </xs:simpleType>
+  </xs:union>
+</xs:simpleType>
+
+<xs:simpleType name="prefix-list">
+  <xs:list itemType="xsl:prefix-or-default"/>
+</xs:simpleType>
+
+<xs:simpleType name="method">
+  <xs:annotation>
+    <xs:documentation>
+      The method attribute of xsl:output:
+      Either one of the recognized names "xml", "xhtml", "html", "text",
+      or a QName that must include a prefix.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:union>
+    <xs:simpleType>
+      <xs:restriction base="xs:NCName">
+        <xs:enumeration value="xml"/>
+        <xs:enumeration value="xhtml"/>
+        <xs:enumeration value="html"/>
+        <xs:enumeration value="text"/>
+      </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType>
+      <xs:restriction base="xsl:QName">
+        <xs:pattern value="\c*:\c*"/>
+      </xs:restriction>
+    </xs:simpleType>
+  </xs:union>
+</xs:simpleType>
+
+<xs:simpleType name="pattern">
+  <xs:annotation>
+    <xs:documentation>
+      A match pattern as defined in the XSLT 2.0 Recommendation.
+      The syntax for patterns is a restricted form of the syntax for
+      XPath 2.0 expressions.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xsl:expression"/>
+</xs:simpleType>
+
+<xs:simpleType name="prefix-or-default">
+  <xs:annotation>
+    <xs:documentation>
+      Either a namespace prefix, or #default.
+      Used in the xsl:namespace-alias element.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:union memberTypes="xs:NCName">
+    <xs:simpleType>
+      <xs:restriction base="xs:token">
+        <xs:enumeration value="#default"/>
+      </xs:restriction>
+    </xs:simpleType>
+  </xs:union>
+</xs:simpleType>
+
+<xs:simpleType name="QNames">
+  <xs:annotation>
+    <xs:documentation>
+      A list of QNames.
+      Used in the [xsl:]use-attribute-sets attribute of various elements,
+      and in the cdata-section-elements attribute of xsl:output
+    </xs:documentation>
+  </xs:annotation>
+  <xs:list itemType="xsl:QName"/>
+</xs:simpleType>
+
+<xs:simpleType name="QName">
+  <xs:annotation>
+    <xs:documentation>
+      A QName.
+      This schema does not use the built-in type xs:QName, but rather defines its own
+      QName type. Although xs:QName would define the correct validation on these attributes,
+      a schema processor would expand unprefixed QNames incorrectly when constructing the PSVI,
+      because (as defined in XML Schema errata) an unprefixed xs:QName is assumed to be in
+      the default namespace, which is not the correct assumption for XSLT.
+      The data type is defined as a restriction of the built-in type Name, restricted
+      so that it can only contain one colon which must not be the first or last character.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:Name">
+    <xs:pattern value="([^:]+:)?[^:]+"/>
+  </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="sequence-type">
+  <xs:annotation>
+    <xs:documentation>
+      The description of a data type, conforming to the
+      SequenceType production defined in the XPath 2.0 Recommendation
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:token">
+    <xs:pattern value=".+"/>
+  </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="uri-list">
+  <xs:list itemType="xs:anyURI"/>
+</xs:simpleType>
+
+<xs:simpleType name="validation-strip-or-preserve">
+  <xs:annotation>
+    <xs:documentation>
+      Describes different ways of type-annotating an element or attribute.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xsl:validation-type">
+    <xs:enumeration value="preserve"/>
+    <xs:enumeration value="strip"/>
+  </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="validation-type">
+  <xs:annotation>
+    <xs:documentation>
+      Describes different ways of type-annotating an element or attribute.
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:token">
+    <xs:enumeration value="strict"/>
+    <xs:enumeration value="lax"/>
+    <xs:enumeration value="preserve"/>
+    <xs:enumeration value="strip"/>
+  </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="yes-or-no">
+  <xs:annotation>
+    <xs:documentation>
+      One of the values "yes" or "no".
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:token">
+    <xs:enumeration value="yes"/>
+    <xs:enumeration value="no"/>
+  </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="yes-or-no-or-omit">
+  <xs:annotation>
+    <xs:documentation>
+      One of the values "yes" or "no" or "omit".
+    </xs:documentation>
+  </xs:annotation>
+  <xs:restriction base="xs:token">
+    <xs:enumeration value="yes"/>
+    <xs:enumeration value="no"/>
+    <xs:enumeration value="omit"/>
+  </xs:restriction>
+</xs:simpleType>
+
+</xs:schema>
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form
new file mode 100644
index 0000000..01f7df0
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form
@@ -0,0 +1,347 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.CodeStyleHtmlPanel">
+  <grid id="97358" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="4" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="4" y="8" width="828" height="588"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <xy id="3dbb2" binding="myPreviewPanel" layout-manager="XYLayout" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children/>
+      </xy>
+      <grid id="1b801" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <scrollpane id="3e3f1" class="com.intellij.ui.components.JBScrollPane" binding="myJBScrollPane" custom-create="true">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <horizontalScrollBarPolicy value="31"/>
+            </properties>
+            <border type="empty"/>
+            <children>
+              <grid id="b4cfb" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                <margin top="0" left="0" bottom="0" right="0"/>
+                <constraints/>
+                <properties/>
+                <border type="none"/>
+                <children>
+                  <grid id="ca5bb" layout-manager="GridLayoutManager" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                    <margin top="0" left="0" bottom="0" right="0"/>
+                    <constraints>
+                      <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties/>
+                    <border type="none"/>
+                    <children>
+                      <component id="121a0" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="label.or.if.tag.size.more.than"/>
+                        </properties>
+                      </component>
+                      <component id="547a0" class="javax.swing.JTextField" binding="myDoNotAlignChildrenMinSize">
+                        <constraints>
+                          <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                            <preferred-size width="50" height="-1"/>
+                          </grid>
+                        </constraints>
+                        <properties/>
+                      </component>
+                      <component id="a3eda" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="4" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="label.lines"/>
+                        </properties>
+                      </component>
+                      <component id="fe20d" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="label.insert.new.line.before"/>
+                        </properties>
+                      </component>
+                      <component id="160eb" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="label.remove.new.line.before"/>
+                        </properties>
+                      </component>
+                      <component id="93fdf" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="label.do.not.indent.children.of"/>
+                        </properties>
+                      </component>
+                      <component id="d6b64" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myInsertNewLineTagNames">
+                        <constraints>
+                          <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="1" anchor="8" fill="3" indent="0" use-parent-layout="false">
+                            <preferred-size width="100" height="-1"/>
+                          </grid>
+                        </constraints>
+                        <properties>
+                          <text value=""/>
+                        </properties>
+                      </component>
+                      <component id="47f60" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myRemoveNewLineTagNames">
+                        <constraints>
+                          <grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="1" anchor="8" fill="3" indent="0" use-parent-layout="false">
+                            <preferred-size width="100" height="-1"/>
+                          </grid>
+                        </constraints>
+                        <properties>
+                          <text value=""/>
+                        </properties>
+                      </component>
+                      <component id="655c2" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myDoNotAlignChildrenTagNames">
+                        <constraints>
+                          <grid row="2" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="1" anchor="8" fill="3" indent="0" use-parent-layout="false">
+                            <preferred-size width="100" height="-1"/>
+                          </grid>
+                        </constraints>
+                        <properties>
+                          <text value=""/>
+                        </properties>
+                      </component>
+                      <component id="c0d93" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myInlineElementsTagNames">
+                        <constraints>
+                          <grid row="4" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="1" anchor="8" fill="3" indent="0" use-parent-layout="false">
+                            <preferred-size width="100" height="-1"/>
+                          </grid>
+                        </constraints>
+                        <properties>
+                          <text value=""/>
+                        </properties>
+                      </component>
+                      <component id="9646b" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="inline.elements"/>
+                        </properties>
+                      </component>
+                      <component id="1ade9" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="label.keep.white.spaces.inside"/>
+                        </properties>
+                      </component>
+                      <component id="a2288" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="don.t.break.if.inline.content"/>
+                        </properties>
+                      </component>
+                      <component id="77303" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myKeepWhiteSpacesTagNames">
+                        <constraints>
+                          <grid row="5" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="1" anchor="8" fill="3" indent="0" use-parent-layout="false">
+                            <preferred-size width="100" height="-1"/>
+                          </grid>
+                        </constraints>
+                        <properties>
+                          <text value=""/>
+                        </properties>
+                      </component>
+                      <component id="c854c" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myDontBreakIfInlineContent">
+                        <constraints>
+                          <grid row="6" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="1" anchor="8" fill="3" indent="0" use-parent-layout="false">
+                            <preferred-size width="100" height="-1"/>
+                          </grid>
+                        </constraints>
+                        <properties>
+                          <text value=""/>
+                        </properties>
+                      </component>
+                    </children>
+                  </grid>
+                  <grid id="b8acc" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                    <margin top="0" left="0" bottom="0" right="0"/>
+                    <constraints>
+                      <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties/>
+                    <border type="none"/>
+                    <children>
+                      <grid id="c0323" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                        <margin top="0" left="0" bottom="0" right="0"/>
+                        <constraints>
+                          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties/>
+                        <border type="none"/>
+                        <children>
+                          <component id="8a13c" class="javax.swing.JCheckBox" binding="myAlignAttributes">
+                            <constraints>
+                              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                            </constraints>
+                            <properties>
+                              <margin top="0" left="0" bottom="0" right="0"/>
+                              <text resource-bundle="messages/ApplicationBundle" key="checkbox.align.attributes"/>
+                            </properties>
+                          </component>
+                          <component id="165dc" class="javax.swing.JCheckBox" binding="myAlignText">
+                            <constraints>
+                              <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                            </constraints>
+                            <properties>
+                              <margin top="0" left="0" bottom="0" right="0"/>
+                              <text resource-bundle="messages/ApplicationBundle" key="checkbox.align.text"/>
+                            </properties>
+                          </component>
+                          <component id="959da" class="javax.swing.JCheckBox" binding="myKeepWhiteSpaces">
+                            <constraints>
+                              <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                            </constraints>
+                            <properties>
+                              <margin top="0" left="0" bottom="0" right="0"/>
+                              <text resource-bundle="messages/ApplicationBundle" key="checkbox.keep.white.spaces"/>
+                            </properties>
+                          </component>
+                          <component id="bfd7f" class="javax.swing.JCheckBox" binding="myWrapText">
+                            <constraints>
+                              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                            </constraints>
+                            <properties>
+                              <text resource-bundle="messages/ApplicationBundle" key="checkbox.wrap.text"/>
+                            </properties>
+                          </component>
+                        </children>
+                      </grid>
+                      <grid id="6063" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                        <margin top="0" left="0" bottom="0" right="0"/>
+                        <constraints>
+                          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties/>
+                        <clientProperties>
+                          <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
+                        </clientProperties>
+                        <border type="etched" title-resource-bundle="messages/ApplicationBundle" title-key="title.spaces"/>
+                        <children>
+                          <component id="f4575" class="javax.swing.JCheckBox" binding="mySpacesAroundEquality">
+                            <constraints>
+                              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                            </constraints>
+                            <properties>
+                              <text resource-bundle="messages/ApplicationBundle" key="checkbox.spaces.around.equals.in.attribute"/>
+                            </properties>
+                          </component>
+                          <component id="8f9a9" class="javax.swing.JCheckBox" binding="mySpacesAroundTagName">
+                            <constraints>
+                              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                            </constraints>
+                            <properties>
+                              <text resource-bundle="messages/ApplicationBundle" key="checkbox.spaces.around.tag.name"/>
+                            </properties>
+                          </component>
+                          <component id="2830e" class="javax.swing.JCheckBox" binding="mySpaceInEmptyTag">
+                            <constraints>
+                              <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                            </constraints>
+                            <properties>
+                              <text resource-bundle="messages/ApplicationBundle" key="checkbox.spaces.in.empty.tag"/>
+                            </properties>
+                          </component>
+                        </children>
+                      </grid>
+                    </children>
+                  </grid>
+                  <grid id="6dece" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                    <margin top="0" left="0" bottom="0" right="0"/>
+                    <constraints>
+                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties/>
+                    <border type="none"/>
+                    <children>
+                      <component id="c888a" class="javax.swing.JCheckBox" binding="myShouldKeepBlankLines">
+                        <constraints>
+                          <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <margin top="0" left="0" bottom="0" right="0"/>
+                          <text resource-bundle="messages/ApplicationBundle" key="checkbox.keep.line.breaks"/>
+                        </properties>
+                      </component>
+                      <component id="d4efa" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="label.wrap.attributes"/>
+                        </properties>
+                      </component>
+                      <component id="e4b98" class="javax.swing.JLabel">
+                        <constraints>
+                          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <text resource-bundle="messages/ApplicationBundle" key="editbox.keep.blank.lines"/>
+                        </properties>
+                      </component>
+                      <component id="18182" class="javax.swing.JTextField" binding="myKeepBlankLines">
+                        <constraints>
+                          <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                            <preferred-size width="50" height="-1"/>
+                          </grid>
+                        </constraints>
+                        <properties>
+                          <columns value="3"/>
+                        </properties>
+                      </component>
+                      <component id="8bb88" class="javax.swing.JComboBox" binding="myWrapAttributes">
+                        <constraints>
+                          <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <enabled value="true"/>
+                        </properties>
+                      </component>
+                      <component id="f6beb" class="javax.swing.JCheckBox" binding="myShouldKeepLineBreaksInText">
+                        <constraints>
+                          <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <margin top="0" left="0" bottom="0" right="0"/>
+                          <text resource-bundle="messages/ApplicationBundle" key="checkbox.keep.line.breaks.in.text"/>
+                        </properties>
+                      </component>
+                    </children>
+                  </grid>
+                </children>
+              </grid>
+            </children>
+          </scrollpane>
+        </children>
+      </grid>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java
new file mode 100644
index 0000000..bde6a85
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.ide.highlighter.XmlHighlighterFactory;
+import com.intellij.openapi.application.ApplicationBundle;
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.ui.components.JBScrollPane;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.PlatformIcons;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
+
+  private JTextField myKeepBlankLines;
+  private JComboBox myWrapAttributes;
+  private JCheckBox myAlignAttributes;
+  private JCheckBox myKeepWhiteSpaces;
+
+  private JPanel myPanel;
+  private JPanel myPreviewPanel;
+
+  private JCheckBox mySpacesAroundEquality;
+  private JCheckBox mySpacesAroundTagName;
+  private JCheckBox myAlignText;
+  private TextFieldWithBrowseButton myInsertNewLineTagNames;
+  private TextFieldWithBrowseButton myRemoveNewLineTagNames;
+  private TextFieldWithBrowseButton myDoNotAlignChildrenTagNames;
+  private TextFieldWithBrowseButton myKeepWhiteSpacesTagNames;
+  private TextFieldWithBrowseButton myInlineElementsTagNames;
+  private JTextField myDoNotAlignChildrenMinSize;
+  private JCheckBox myShouldKeepBlankLines;
+  private JCheckBox mySpaceInEmptyTag;
+  private JCheckBox myWrapText;
+  private JCheckBox myShouldKeepLineBreaksInText;
+  private TextFieldWithBrowseButton myDontBreakIfInlineContent;
+  private JBScrollPane myJBScrollPane;
+
+  public CodeStyleHtmlPanel(CodeStyleSettings settings) {
+    super(settings);
+    installPreviewPanel(myPreviewPanel);
+
+    fillWrappingCombo(myWrapAttributes);
+
+    customizeField(ApplicationBundle.message("title.insert.new.line.before.tags"), myInsertNewLineTagNames);
+    customizeField(ApplicationBundle.message("title.remove.line.breaks.before.tags"), myRemoveNewLineTagNames);
+    customizeField(ApplicationBundle.message("title.do.not.indent.children.of"), myDoNotAlignChildrenTagNames);
+    customizeField(ApplicationBundle.message("title.inline.elements"), myInlineElementsTagNames);
+    customizeField(ApplicationBundle.message("title.keep.whitespaces.inside"), myKeepWhiteSpacesTagNames);
+    customizeField(ApplicationBundle.message("title.dont.wrap.if.inline.content"), myDontBreakIfInlineContent);
+
+    myInsertNewLineTagNames.getTextField().setColumns(5);
+    myRemoveNewLineTagNames.getTextField().setColumns(5);
+    myDoNotAlignChildrenTagNames.getTextField().setColumns(5);
+    myKeepWhiteSpacesTagNames.getTextField().setColumns(5);
+    myInlineElementsTagNames.getTextField().setColumns(5);
+    myDontBreakIfInlineContent.getTextField().setColumns(5);
+
+
+    addPanelToWatch(myPanel);
+  }
+
+  protected EditorHighlighter createHighlighter(final EditorColorsScheme scheme) {
+    return XmlHighlighterFactory.createXMLHighlighter(scheme);
+  }
+
+  private void createUIComponents() {
+    myJBScrollPane = new JBScrollPane() {
+      @Override
+      public Dimension getPreferredSize() {
+        Dimension prefSize = super.getPreferredSize();
+        return new Dimension(prefSize.width + 15, prefSize.height);
+      }
+    };
+  }
+
+  private static void customizeField(final String title, final TextFieldWithBrowseButton uiField) {
+    uiField.getTextField().setEditable(false);
+    uiField.setButtonIcon(PlatformIcons.OPEN_EDIT_DIALOG_ICON);
+    uiField.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        final TagListDialog tagListDialog = new TagListDialog(title);
+        tagListDialog.setData(createCollectionOn(uiField.getText()));
+        tagListDialog.show();
+        if (tagListDialog.isOK()) {
+          uiField.setText(createStringOn(tagListDialog.getData()));
+        }
+      }
+
+      private String createStringOn(final ArrayList<String> data) {
+        return StringUtil.join(ArrayUtil.toStringArray(data), ",");
+      }
+
+      private ArrayList<String> createCollectionOn(final String data) {
+        if (data == null) {
+          return new ArrayList<String>();
+        }
+        return new ArrayList<String>(Arrays.asList(data.split(",")));
+      }
+
+    });
+  }
+
+  protected int getRightMargin() {
+    return 60;
+  }
+
+  public void apply(CodeStyleSettings settings) {
+    settings.HTML_KEEP_BLANK_LINES = getIntValue(myKeepBlankLines);
+    settings.HTML_ATTRIBUTE_WRAP = ourWrappings[myWrapAttributes.getSelectedIndex()];
+    settings.HTML_TEXT_WRAP = myWrapText.isSelected() ? CodeStyleSettings.WRAP_AS_NEEDED : CodeStyleSettings.DO_NOT_WRAP;
+    settings.HTML_SPACE_INSIDE_EMPTY_TAG = mySpaceInEmptyTag.isSelected();
+    settings.HTML_ALIGN_ATTRIBUTES = myAlignAttributes.isSelected();
+    settings.HTML_ALIGN_TEXT = myAlignText.isSelected();
+    settings.HTML_KEEP_WHITESPACES = myKeepWhiteSpaces.isSelected();
+    settings.HTML_SPACE_AROUND_EQUALITY_IN_ATTRINUTE = mySpacesAroundEquality.isSelected();
+    settings.HTML_SPACE_AFTER_TAG_NAME = mySpacesAroundTagName.isSelected();
+
+    settings.HTML_ELEMENTS_TO_INSERT_NEW_LINE_BEFORE = myInsertNewLineTagNames.getText();
+    settings.HTML_ELEMENTS_TO_REMOVE_NEW_LINE_BEFORE = myRemoveNewLineTagNames.getText();
+    settings.HTML_DO_NOT_INDENT_CHILDREN_OF = myDoNotAlignChildrenTagNames.getText();
+    settings.HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES = getIntValue(myDoNotAlignChildrenMinSize);
+    settings.HTML_INLINE_ELEMENTS = myInlineElementsTagNames.getText();
+    settings.HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT = myDontBreakIfInlineContent.getText();
+    settings.HTML_KEEP_WHITESPACES_INSIDE = myKeepWhiteSpacesTagNames.getText();
+    settings.HTML_KEEP_LINE_BREAKS = myShouldKeepBlankLines.isSelected();
+    settings.HTML_KEEP_LINE_BREAKS_IN_TEXT = myShouldKeepLineBreaksInText.isSelected();
+  }
+
+  private static int getIntValue(JTextField keepBlankLines) {
+    try {
+      return Integer.parseInt(keepBlankLines.getText());
+    }
+    catch (NumberFormatException e) {
+      return 0;
+    }
+  }
+
+  protected void resetImpl(final CodeStyleSettings settings) {
+    myKeepBlankLines.setText(String.valueOf(settings.HTML_KEEP_BLANK_LINES));
+    myWrapAttributes.setSelectedIndex(getIndexForWrapping(settings.HTML_ATTRIBUTE_WRAP));
+    myWrapText.setSelected(settings.HTML_TEXT_WRAP != CodeStyleSettings.DO_NOT_WRAP);
+    mySpaceInEmptyTag.setSelected(settings.HTML_SPACE_INSIDE_EMPTY_TAG);
+    myAlignAttributes.setSelected(settings.HTML_ALIGN_ATTRIBUTES);
+    myAlignText.setSelected(settings.HTML_ALIGN_TEXT);
+    myKeepWhiteSpaces.setSelected(settings.HTML_KEEP_WHITESPACES);
+    mySpacesAroundTagName.setSelected(settings.HTML_SPACE_AFTER_TAG_NAME);
+    mySpacesAroundEquality.setSelected(settings.HTML_SPACE_AROUND_EQUALITY_IN_ATTRINUTE);
+    myShouldKeepBlankLines.setSelected(settings.HTML_KEEP_LINE_BREAKS);
+    myShouldKeepLineBreaksInText.setSelected(settings.HTML_KEEP_LINE_BREAKS_IN_TEXT);
+
+    myInsertNewLineTagNames.setText(settings.HTML_ELEMENTS_TO_INSERT_NEW_LINE_BEFORE);
+    myRemoveNewLineTagNames.setText(settings.HTML_ELEMENTS_TO_REMOVE_NEW_LINE_BEFORE);
+    myDoNotAlignChildrenTagNames.setText(settings.HTML_DO_NOT_INDENT_CHILDREN_OF);
+    myDoNotAlignChildrenMinSize.setText(String.valueOf(settings.HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES));
+    myInlineElementsTagNames.setText(settings.HTML_INLINE_ELEMENTS);
+    myDontBreakIfInlineContent.setText(settings.HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT);
+    myKeepWhiteSpacesTagNames.setText(settings.HTML_KEEP_WHITESPACES_INSIDE);
+  }
+
+  public boolean isModified(CodeStyleSettings settings) {
+    if (settings.HTML_KEEP_BLANK_LINES != getIntValue(myKeepBlankLines)) {
+      return true;
+    }
+    if (settings.HTML_ATTRIBUTE_WRAP != ourWrappings[myWrapAttributes.getSelectedIndex()]) {
+      return true;
+    }
+
+    if ((settings.HTML_TEXT_WRAP == CodeStyleSettings.WRAP_AS_NEEDED) != myWrapText.isSelected()) {
+      return true;
+    }
+
+    if (settings.HTML_SPACE_INSIDE_EMPTY_TAG != mySpaceInEmptyTag.isSelected()) {
+      return true;
+    }
+
+    if (settings.HTML_ALIGN_ATTRIBUTES != myAlignAttributes.isSelected()) {
+      return true;
+    }
+
+    if (settings.HTML_ALIGN_TEXT != myAlignText.isSelected()) {
+      return true;
+    }
+
+    if (settings.HTML_KEEP_WHITESPACES != myKeepWhiteSpaces.isSelected()) {
+      return true;
+    }
+
+    if (settings.HTML_SPACE_AROUND_EQUALITY_IN_ATTRINUTE != mySpacesAroundEquality.isSelected()) {
+      return true;
+    }
+
+    if (settings.HTML_SPACE_AFTER_TAG_NAME != mySpacesAroundTagName.isSelected()) {
+      return true;
+    }
+
+    if (!Comparing.equal(settings.HTML_ELEMENTS_TO_INSERT_NEW_LINE_BEFORE, myInsertNewLineTagNames.getText().trim())) {
+      return true;
+    }
+
+    if (!Comparing.equal(settings.HTML_ELEMENTS_TO_REMOVE_NEW_LINE_BEFORE, myRemoveNewLineTagNames.getText().trim())) {
+      return true;
+    }
+
+    if (!Comparing.equal(settings.HTML_DO_NOT_INDENT_CHILDREN_OF, myDoNotAlignChildrenTagNames.getText().trim())) {
+      return true;
+    }
+
+    if (settings.HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES != getIntValue(myDoNotAlignChildrenMinSize)) {
+      return true;
+    }
+
+    if (!Comparing.equal(settings.HTML_INLINE_ELEMENTS, myInlineElementsTagNames.getText().trim())) return true;
+    if (!Comparing.equal(settings.HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT, myDontBreakIfInlineContent.getText().trim())) return true;
+
+    if (!Comparing.equal(settings.HTML_KEEP_WHITESPACES_INSIDE, myKeepWhiteSpacesTagNames.getText().trim())) {
+      return true;
+    }
+
+    if (myShouldKeepBlankLines.isSelected() != settings.HTML_KEEP_LINE_BREAKS) {
+      return true;
+    }
+
+    if (myShouldKeepLineBreaksInText.isSelected() != settings.HTML_KEEP_LINE_BREAKS_IN_TEXT) {
+      return true;
+    }
+
+    return false;
+  }
+
+  public JComponent getPanel() {
+    return myPanel;
+  }
+
+  protected String getPreviewText() {
+    return readFromFile(this.getClass(), "preview.html.template");
+
+  }
+
+  @NotNull
+  protected FileType getFileType() {
+    return StdFileTypes.HTML;
+  }
+
+  protected void prepareForReformat(final PsiFile psiFile) {
+    //psiFile.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, LanguageLevel.HIGHEST);
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form
new file mode 100644
index 0000000..28d48d0
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.CodeStyleXmlPanel">
+  <grid id="634cb" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="4" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="12" y="7" width="679" height="672"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <scrollpane id="a9b52" class="com.intellij.ui.components.JBScrollPane" binding="myJBScrollPane" custom-create="true">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <horizontalScrollBarPolicy value="31"/>
+        </properties>
+        <border type="empty"/>
+        <children>
+          <grid id="265f" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints/>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <grid id="417cd" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                <margin top="0" left="0" bottom="0" right="0"/>
+                <constraints>
+                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+                <border type="none"/>
+                <children>
+                  <grid id="367a8" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                    <margin top="0" left="0" bottom="0" right="0"/>
+                    <constraints>
+                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties/>
+                    <border type="none"/>
+                    <children>
+                      <component id="8a13c" class="javax.swing.JCheckBox" binding="myAlignAttributes">
+                        <constraints>
+                          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <margin top="0" left="0" bottom="0" right="0"/>
+                          <text resource-bundle="messages/ApplicationBundle" key="checkbox.align.attributes"/>
+                        </properties>
+                      </component>
+                      <component id="959da" class="javax.swing.JCheckBox" binding="myKeepWhiteSpaces">
+                        <constraints>
+                          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <margin top="0" left="0" bottom="0" right="0"/>
+                          <text resource-bundle="messages/ApplicationBundle" key="checkbox.keep.white.spaces"/>
+                        </properties>
+                      </component>
+                      <component id="c5160" class="javax.swing.JCheckBox" binding="myWrapText">
+                        <constraints>
+                          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <margin top="2" left="0" bottom="2" right="3"/>
+                          <text resource-bundle="messages/ApplicationBundle" key="checkbox.wrap.text"/>
+                        </properties>
+                      </component>
+                    </children>
+                  </grid>
+                  <grid id="6063" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                    <margin top="0" left="0" bottom="0" right="0"/>
+                    <constraints>
+                      <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties/>
+                    <clientProperties>
+                      <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
+                      <html.disable class="java.lang.Boolean" value="true"/>
+                    </clientProperties>
+                    <border type="etched" title-resource-bundle="messages/ApplicationBundle" title-key="title.spaces"/>
+                    <children>
+                      <component id="f4575" class="javax.swing.JCheckBox" binding="mySpacesAroundEquality">
+                        <constraints>
+                          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <margin top="0" left="0" bottom="0" right="0"/>
+                          <text resource-bundle="messages/ApplicationBundle" key="checkbox.spaces.around.equals.in.attribute"/>
+                        </properties>
+                      </component>
+                      <component id="8f9a9" class="javax.swing.JCheckBox" binding="mySpacesAfterTagName">
+                        <constraints>
+                          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <margin top="0" left="0" bottom="0" right="0"/>
+                          <text resource-bundle="messages/ApplicationBundle" key="checkbox.spaces.around.tag.name"/>
+                        </properties>
+                      </component>
+                      <component id="e8439" class="javax.swing.JCheckBox" binding="myInEmptyTag">
+                        <constraints>
+                          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                        </constraints>
+                        <properties>
+                          <margin top="0" left="0" bottom="0" right="0"/>
+                          <text resource-bundle="messages/ApplicationBundle" key="checkbox.spaces.in.empty.tag"/>
+                        </properties>
+                      </component>
+                    </children>
+                  </grid>
+                </children>
+              </grid>
+              <grid id="e7045" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                <margin top="0" left="0" bottom="0" right="0"/>
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+                <border type="none"/>
+                <children>
+                  <component id="d4efa" class="javax.swing.JLabel">
+                    <constraints>
+                      <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <text resource-bundle="messages/ApplicationBundle" key="label.wrap.attributes"/>
+                    </properties>
+                  </component>
+                  <component id="8bb88" class="javax.swing.JComboBox" binding="myWrapAttributes">
+                    <constraints>
+                      <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <enabled value="true"/>
+                    </properties>
+                  </component>
+                  <component id="f230c" class="javax.swing.JLabel">
+                    <constraints>
+                      <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <text resource-bundle="messages/ApplicationBundle" key="editbox.keep.blank.lines"/>
+                    </properties>
+                  </component>
+                  <component id="d9f7d" class="javax.swing.JCheckBox" binding="myKeepLineBreaksInText">
+                    <constraints>
+                      <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <margin top="0" left="0" bottom="0" right="0"/>
+                      <text resource-bundle="messages/ApplicationBundle" key="checkbox.keep.line.breaks.in.text"/>
+                    </properties>
+                  </component>
+                  <component id="18182" class="javax.swing.JTextField" binding="myKeepBlankLines">
+                    <constraints>
+                      <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                        <preferred-size width="50" height="-1"/>
+                      </grid>
+                    </constraints>
+                    <properties>
+                      <columns value="3"/>
+                    </properties>
+                  </component>
+                  <component id="3cead" class="javax.swing.JCheckBox" binding="myKeepLineBreaks">
+                    <constraints>
+                      <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <margin top="0" left="0" bottom="0" right="0"/>
+                      <text resource-bundle="messages/ApplicationBundle" key="checkbox.keep.line.breaks"/>
+                    </properties>
+                  </component>
+                </children>
+              </grid>
+              <grid id="bcc6c" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                <margin top="0" left="0" bottom="0" right="0"/>
+                <constraints>
+                  <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+                <clientProperties>
+                  <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
+                </clientProperties>
+                <border type="etched" title="CDATA"/>
+                <children>
+                  <component id="a3e4f" class="javax.swing.JLabel">
+                    <constraints>
+                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <labelFor value="ecfb8"/>
+                      <text value="Whitespace around:"/>
+                    </properties>
+                  </component>
+                  <component id="9ab20" class="javax.swing.JCheckBox" binding="myKeepWhitespaceInsideCDATACheckBox">
+                    <constraints>
+                      <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <text value="Keep whitespace inside"/>
+                    </properties>
+                  </component>
+                  <component id="ecfb8" class="javax.swing.JComboBox" binding="myWhiteSpaceAroundCDATA">
+                    <constraints>
+                      <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <model>
+                        <item value="Preserve"/>
+                        <item value="Remove (keep with tags)"/>
+                        <item value="Add new lines"/>
+                      </model>
+                    </properties>
+                  </component>
+                </children>
+              </grid>
+            </children>
+          </grid>
+        </children>
+      </scrollpane>
+      <xy id="3dbb2" binding="myPreviewPanel" layout-manager="XYLayout" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children/>
+      </xy>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java
new file mode 100644
index 0000000..b7f0bd3
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.ide.highlighter.XmlHighlighterFactory;
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.formatter.xml.XmlCodeStyleSettings;
+import com.intellij.ui.components.JBScrollPane;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class CodeStyleXmlPanel extends CodeStyleAbstractPanel{
+  private JTextField myKeepBlankLines;
+  private JComboBox myWrapAttributes;
+  private JCheckBox myAlignAttributes;
+  private JCheckBox myKeepWhiteSpaces;
+
+  private JPanel myPanel;
+  private JPanel myPreviewPanel;
+
+  private JCheckBox mySpacesAroundEquality;
+  private JCheckBox mySpacesAfterTagName;
+  private JCheckBox myKeepLineBreaks;
+  private JCheckBox myInEmptyTag;
+  private JCheckBox myWrapText;
+  private JCheckBox myKeepLineBreaksInText;
+  private JComboBox myWhiteSpaceAroundCDATA;
+  private JCheckBox myKeepWhitespaceInsideCDATACheckBox;
+  private JBScrollPane myJBScrollPane;
+
+  public CodeStyleXmlPanel(CodeStyleSettings settings) {
+    super(settings);
+    installPreviewPanel(myPreviewPanel);
+
+    fillWrappingCombo(myWrapAttributes);
+
+    addPanelToWatch(myPanel);
+  }
+
+  protected EditorHighlighter createHighlighter(final EditorColorsScheme scheme) {
+    return XmlHighlighterFactory.createXMLHighlighter(scheme);
+  }
+
+  protected int getRightMargin() {
+    return 60;
+  }
+
+  public void apply(CodeStyleSettings settings) {
+    XmlCodeStyleSettings xmlSettings = settings.getCustomSettings(XmlCodeStyleSettings.class);
+    xmlSettings.XML_KEEP_BLANK_LINES = getIntValue(myKeepBlankLines);
+    xmlSettings.XML_KEEP_LINE_BREAKS = myKeepLineBreaks.isSelected();
+    xmlSettings.XML_KEEP_LINE_BREAKS_IN_TEXT = myKeepLineBreaksInText.isSelected();
+    xmlSettings.XML_ATTRIBUTE_WRAP = ourWrappings[myWrapAttributes.getSelectedIndex()];
+    xmlSettings.XML_TEXT_WRAP = myWrapText.isSelected() ? CodeStyleSettings.WRAP_AS_NEEDED : CodeStyleSettings.DO_NOT_WRAP;
+    xmlSettings.XML_ALIGN_ATTRIBUTES = myAlignAttributes.isSelected();
+    xmlSettings.XML_KEEP_WHITESPACES = myKeepWhiteSpaces.isSelected();
+    xmlSettings.XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE = mySpacesAroundEquality.isSelected();
+    xmlSettings.XML_SPACE_AFTER_TAG_NAME = mySpacesAfterTagName.isSelected();
+    xmlSettings.XML_SPACE_INSIDE_EMPTY_TAG = myInEmptyTag.isSelected();
+    xmlSettings.XML_WHITE_SPACE_AROUND_CDATA = myWhiteSpaceAroundCDATA.getSelectedIndex();
+    xmlSettings.XML_KEEP_WHITE_SPACES_INSIDE_CDATA = myKeepWhitespaceInsideCDATACheckBox.isSelected();
+  }
+
+  private int getIntValue(JTextField keepBlankLines) {
+    try {
+      return Integer.parseInt(keepBlankLines.getText());
+    }
+    catch (NumberFormatException e) {
+      return 0;
+    }
+  }
+
+  protected void resetImpl(final CodeStyleSettings settings) {
+    XmlCodeStyleSettings xmlSettings = settings.getCustomSettings(XmlCodeStyleSettings.class);
+    myKeepBlankLines.setText(String.valueOf(xmlSettings.XML_KEEP_BLANK_LINES));
+    myWrapAttributes.setSelectedIndex(getIndexForWrapping(xmlSettings.XML_ATTRIBUTE_WRAP));
+    myAlignAttributes.setSelected(xmlSettings.XML_ALIGN_ATTRIBUTES);
+    myKeepWhiteSpaces.setSelected(xmlSettings.XML_KEEP_WHITESPACES);
+    mySpacesAfterTagName.setSelected(xmlSettings.XML_SPACE_AFTER_TAG_NAME);
+    mySpacesAroundEquality.setSelected(xmlSettings.XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE);
+    myKeepLineBreaks.setSelected(xmlSettings.XML_KEEP_LINE_BREAKS);
+    myKeepLineBreaksInText.setSelected(xmlSettings.XML_KEEP_LINE_BREAKS_IN_TEXT);
+    myInEmptyTag.setSelected(xmlSettings.XML_SPACE_INSIDE_EMPTY_TAG);
+    myWrapText.setSelected(wrapText(settings));
+    myWhiteSpaceAroundCDATA.setSelectedIndex(xmlSettings.XML_WHITE_SPACE_AROUND_CDATA);
+    myKeepWhitespaceInsideCDATACheckBox.setSelected(xmlSettings.XML_KEEP_WHITE_SPACES_INSIDE_CDATA);
+  }
+
+  public boolean isModified(CodeStyleSettings settings) {
+    XmlCodeStyleSettings xmlSettings = settings.getCustomSettings(XmlCodeStyleSettings.class);
+    if (myWrapText.isSelected() != wrapText(settings)) {
+      return true;
+    }
+    if (xmlSettings.XML_KEEP_BLANK_LINES != getIntValue(myKeepBlankLines)) {
+      return true;
+    }
+    if (xmlSettings.XML_ATTRIBUTE_WRAP != ourWrappings[myWrapAttributes.getSelectedIndex()]) {
+      return true;
+    }
+    if (xmlSettings.XML_ALIGN_ATTRIBUTES != myAlignAttributes.isSelected()) {
+      return true;
+    }
+    if (xmlSettings.XML_KEEP_WHITESPACES != myKeepWhiteSpaces.isSelected()) {
+      return true;
+    }
+
+    if (xmlSettings.XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE != mySpacesAroundEquality.isSelected()){
+      return true;
+    }
+
+    if (xmlSettings.XML_SPACE_AFTER_TAG_NAME != mySpacesAfterTagName.isSelected()){
+      return true;
+    }
+
+    if (xmlSettings.XML_KEEP_LINE_BREAKS != myKeepLineBreaks.isSelected()) {
+      return true;
+    }
+
+    if (xmlSettings.XML_KEEP_LINE_BREAKS_IN_TEXT != myKeepLineBreaksInText.isSelected()) {
+      return true;
+    }
+
+    if (xmlSettings.XML_SPACE_INSIDE_EMPTY_TAG != myInEmptyTag.isSelected()){
+      return true;
+    }
+    if (xmlSettings.XML_WHITE_SPACE_AROUND_CDATA != myWhiteSpaceAroundCDATA.getSelectedIndex()) {
+      return true;
+    }
+    if (xmlSettings.XML_KEEP_WHITE_SPACES_INSIDE_CDATA != this.myKeepWhitespaceInsideCDATACheckBox.isSelected()) {
+      return true;
+    }
+
+    return false;
+  }
+
+  private boolean wrapText(final CodeStyleSettings settings) {
+    XmlCodeStyleSettings xmlSettings = settings.getCustomSettings(XmlCodeStyleSettings.class);
+    return xmlSettings.XML_TEXT_WRAP == CodeStyleSettings.WRAP_AS_NEEDED;
+  }
+
+  public JComponent getPanel() {
+    return myPanel;
+  }
+
+  protected String getPreviewText() {
+    return readFromFile(getClass(), "preview.xml.template");
+  }
+
+  @NotNull
+  protected FileType getFileType() {
+    return StdFileTypes.XML;
+  }
+
+  protected void prepareForReformat(final PsiFile psiFile) {
+    //psiFile.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, LanguageLevel.HIGHEST);
+  }
+
+  private void createUIComponents() {
+    myJBScrollPane = new JBScrollPane() {
+      @Override
+      public Dimension getPreferredSize() {
+        Dimension prefSize = super.getPreferredSize();
+        return new Dimension(prefSize.width + 15, prefSize.height);
+      }
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/HtmlCodeStyleMainPanel.java b/xml/impl/src/com/intellij/application/options/HtmlCodeStyleMainPanel.java
new file mode 100644
index 0000000..ba622bf
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/HtmlCodeStyleMainPanel.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Rustam Vishnyakov
+ */
+public class HtmlCodeStyleMainPanel extends TabbedLanguageCodeStylePanel {
+  protected HtmlCodeStyleMainPanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) {
+    super(HTMLLanguage.INSTANCE, currentSettings, settings);
+  }
+
+  @Override
+  protected void initTabs(CodeStyleSettings settings) {
+    addIndentOptionsTab(settings);
+    addTab(new CodeStyleHtmlPanel(settings));
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/HtmlCodeStyleSettingsProvider.java b/xml/impl/src/com/intellij/application/options/HtmlCodeStyleSettingsProvider.java
new file mode 100644
index 0000000..0d2edf5
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/HtmlCodeStyleSettingsProvider.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.openapi.application.ApplicationBundle;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class HtmlCodeStyleSettingsProvider extends CodeStyleSettingsProvider {
+  @NotNull
+  public Configurable createSettingsPage(final CodeStyleSettings settings, final CodeStyleSettings originalSettings) {
+    return new CodeStyleAbstractConfigurable(settings, originalSettings, ApplicationBundle.message("title.html")) {
+      protected CodeStyleAbstractPanel createPanel(final CodeStyleSettings settings) {
+        return new HtmlCodeStyleMainPanel(settings, originalSettings);
+      }
+
+      public String getHelpTopic() {
+        return "reference.settingsdialog.IDE.globalcodestyle.html";
+      }
+    };
+  }
+
+  @Override
+  public String getConfigurableDisplayName() {
+    return ApplicationBundle.message("title.html");
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java b/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java
new file mode 100644
index 0000000..aa36d1b
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Rustam Vishnyakov
+ */
+public class HtmlLanguageCodeStyleSettings extends LanguageCodeStyleSettingsProvider {
+  @NotNull
+  @Override
+  public Language getLanguage() {
+    return HTMLLanguage.INSTANCE;
+  }
+
+  @Override
+  public String getCodeSample(@NotNull SettingsType settingsType) {
+    return CodeStyleAbstractPanel.readFromFile(this.getClass(), "preview.html.template");
+  }
+
+  @Override
+  public CommonCodeStyleSettings getDefaultCommonSettings() {
+    CommonCodeStyleSettings defaultSettings = new CommonCodeStyleSettings(HTMLLanguage.INSTANCE);
+    defaultSettings.initIndentOptions();
+    return defaultSettings;
+  }
+
+  @Override
+  public IndentOptionsEditor getIndentOptionsEditor() {
+    return new SmartIndentOptionsEditor();
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/TagListDialog.java b/xml/impl/src/com/intellij/application/options/TagListDialog.java
new file mode 100644
index 0000000..9cdb941
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/TagListDialog.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.openapi.application.ApplicationBundle;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.ui.AnActionButton;
+import com.intellij.ui.AnActionButtonRunnable;
+import com.intellij.ui.ToolbarDecorator;
+import com.intellij.ui.components.JBList;
+
+import javax.swing.*;
+import java.util.ArrayList;
+
+public class TagListDialog extends DialogWrapper {
+  private final JPanel myPanel;
+  private final JList myList = new JBList(new DefaultListModel());
+  private ArrayList<String> myData;
+
+  public TagListDialog(String title) {
+    super(true);
+    myPanel = ToolbarDecorator.createDecorator(myList)
+      .setAddAction(new AnActionButtonRunnable() {
+        @Override
+        public void run(AnActionButton button) {
+          final String tagName = Messages.showInputDialog(ApplicationBundle.message("editbox.enter.tag.name"),
+                                                          ApplicationBundle.message("title.tag.name"), Messages.getQuestionIcon());
+          if (tagName != null) {
+            while (myData.contains(tagName)) {
+              myData.remove(tagName);
+            }
+            myData.add(tagName);
+            updateData();
+            myList.setSelectedIndex(myData.size() - 1);
+          }
+        }
+      }).setRemoveAction(new AnActionButtonRunnable() {
+        @Override
+        public void run(AnActionButton button) {
+          int selectedIndex = myList.getSelectedIndex();
+          if (selectedIndex >= 0) {
+            myData.remove(selectedIndex);
+            updateData();
+            if (selectedIndex >= myData.size()) {
+              selectedIndex -= 1;
+            }
+            if (selectedIndex >= 0) {
+              myList.setSelectedIndex(selectedIndex);
+            }
+          }
+        }
+      }).disableUpDownActions().createPanel();
+    setTitle(title);
+    init();
+  }
+
+  public void setData(ArrayList<String> data) {
+    myData = data;
+    updateData();
+    if (!myData.isEmpty()) {
+      myList.setSelectedIndex(0);
+    }
+  }
+
+  private void updateData() {
+    final DefaultListModel model = ((DefaultListModel)myList.getModel());
+    model.clear();
+    for (String data : myData) {
+      model.addElement(data);
+    }
+  }
+
+  public ArrayList<String> getData() {
+    return myData;
+  }
+
+  protected JComponent createCenterPanel() {
+    return myPanel;
+  }
+
+  public JComponent getPreferredFocusedComponent() {
+    return myList;
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/XmlAutoImportOptionsProvider.form b/xml/impl/src/com/intellij/application/options/XmlAutoImportOptionsProvider.form
new file mode 100644
index 0000000..cd42e37
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/XmlAutoImportOptionsProvider.form
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.XmlAutoImportOptionsProvider">
+  <grid id="ccd60" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="175" height="59"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="etched" title="XML"/>
+        <clientProperties>
+          <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
+        </clientProperties>
+        <children>
+          <component id="5cbfc" class="javax.swing.JCheckBox" binding="myShowAutoImportPopups" default-binding="true">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text resource-bundle="messages/ApplicationBundle" key="checkbox.show.import.popup"/>
+            </properties>
+          </component>
+        </children>
+      </grid>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/application/options/XmlAutoImportOptionsProvider.java b/xml/impl/src/com/intellij/application/options/XmlAutoImportOptionsProvider.java
new file mode 100644
index 0000000..23e7083
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/XmlAutoImportOptionsProvider.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.application.options.editor.AutoImportOptionsProvider;
+import com.intellij.openapi.options.ConfigurationException;
+
+import javax.swing.*;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlAutoImportOptionsProvider implements AutoImportOptionsProvider {
+
+  private JPanel myPanel;
+  private JCheckBox myShowAutoImportPopups;
+
+  public JComponent createComponent() {
+    return myPanel;
+  }
+
+  public boolean isModified() {
+    return XmlSettings.getInstance().SHOW_XML_ADD_IMPORT_HINTS != myShowAutoImportPopups.isSelected();
+  }
+
+  public void apply() throws ConfigurationException {
+    XmlSettings.getInstance().SHOW_XML_ADD_IMPORT_HINTS = myShowAutoImportPopups.isSelected();
+  }
+
+  public void reset() {
+    myShowAutoImportPopups.setSelected(XmlSettings.getInstance().SHOW_XML_ADD_IMPORT_HINTS);    
+  }
+
+  public void disposeUIResources() {
+
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/XmlCodeStyleMainPanel.java b/xml/impl/src/com/intellij/application/options/XmlCodeStyleMainPanel.java
new file mode 100644
index 0000000..e465fb0
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/XmlCodeStyleMainPanel.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
+
+/**
+ * @author Rustam Vishnyakov
+ */
+public class XmlCodeStyleMainPanel extends TabbedLanguageCodeStylePanel {
+  protected XmlCodeStyleMainPanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) {
+    super(XMLLanguage.INSTANCE, currentSettings, settings);
+  }
+
+  @Override
+  protected void initTabs(CodeStyleSettings settings) {
+    addIndentOptionsTab(settings);
+    addTab(new CodeStyleXmlPanel(settings));
+
+    for (CodeStyleSettingsProvider provider : Extensions.getExtensions(CodeStyleSettingsProvider.EXTENSION_POINT_NAME)) {
+      if (provider.getLanguage() == XMLLanguage.INSTANCE && !provider.hasSettingsPage()) {
+        createTab(provider);
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/XmlCodeStyleSettingsProvider.java b/xml/impl/src/com/intellij/application/options/XmlCodeStyleSettingsProvider.java
new file mode 100644
index 0000000..62ae4f8
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/XmlCodeStyleSettingsProvider.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.openapi.application.ApplicationBundle;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
+import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
+import com.intellij.psi.formatter.xml.XmlCodeStyleSettings;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class XmlCodeStyleSettingsProvider extends CodeStyleSettingsProvider {
+
+  public static final String CONFIGURABLE_DISPLAY_NAME = ApplicationBundle.message("title.xml");
+
+  @NotNull
+  public Configurable createSettingsPage(final CodeStyleSettings settings, final CodeStyleSettings originalSettings) {
+    return new CodeStyleAbstractConfigurable(settings, originalSettings, ApplicationBundle.message("title.xml")){
+      protected CodeStyleAbstractPanel createPanel(final CodeStyleSettings settings) {
+        return new XmlCodeStyleMainPanel(getCurrentSettings(), settings);
+      }
+
+      public String getHelpTopic() {
+        return "reference.settingsdialog.IDE.globalcodestyle.xml";
+      }
+    };
+  }
+
+  @Override
+  public String getConfigurableDisplayName() {
+    return CONFIGURABLE_DISPLAY_NAME;
+  }
+
+  @Override
+  public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) {
+    return new XmlCodeStyleSettings(settings);
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java b/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java
new file mode 100644
index 0000000..0541efe
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
+import com.intellij.util.PlatformUtils;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Rustam Vishnyakov
+ */
+public class XmlLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider {
+  @NotNull
+  @Override
+  public Language getLanguage() {
+    return XMLLanguage.INSTANCE;
+  }
+
+  @Override
+  public String getCodeSample(@NotNull SettingsType settingsType) {
+    if (settingsType == SettingsType.INDENT_SETTINGS) {
+      return CodeStyleAbstractPanel.readFromFile(getClass(), "preview.xml.template");
+    }
+    return "";
+  }
+
+  @Override
+  public CommonCodeStyleSettings getDefaultCommonSettings() {
+    CommonCodeStyleSettings xmlSettings = new CommonCodeStyleSettings(getLanguage());
+    CommonCodeStyleSettings.IndentOptions indentOptions = xmlSettings.initIndentOptions();
+    // HACK [yole]
+    if (PlatformUtils.isRubyMine()) {
+      indentOptions.INDENT_SIZE = 2;
+    }
+    return xmlSettings;
+  }
+
+  @Override
+  public IndentOptionsEditor getIndentOptionsEditor() {
+    return new SmartIndentOptionsEditor();
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/XmlSettings.java b/xml/impl/src/com/intellij/application/options/XmlSettings.java
new file mode 100644
index 0000000..5dd5a46
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/XmlSettings.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.components.*;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+
+/**
+ * @author Dmitry Avdeev
+ */
+
+@State(
+  name="XmlSettings",
+  storages= {
+    @Storage(
+      file = StoragePathMacros.APP_CONFIG + "/editor.codeinsight.xml"
+    )}
+)
+public class XmlSettings implements PersistentStateComponent<XmlSettings>, ExportableComponent {
+
+  public boolean SHOW_XML_ADD_IMPORT_HINTS = true;
+
+  public static XmlSettings getInstance() {
+    return ServiceManager.getService(XmlSettings.class);
+  }
+
+  public XmlSettings getState() {
+    return this;
+  }
+
+  public void loadState(final XmlSettings state) {
+    XmlSerializerUtil.copyBean(state, this);
+  }
+
+  @NotNull
+  public File[] getExportFiles() {
+    return new File[]{PathManager.getOptionsFile("editor.codeinsight")};
+  }
+
+  @NotNull
+  public String getPresentableName() {
+    return XmlBundle.message("xml.settings");
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/editor/WebEditorAppearanceConfigurable.java b/xml/impl/src/com/intellij/application/options/editor/WebEditorAppearanceConfigurable.java
new file mode 100644
index 0000000..da3701d
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/editor/WebEditorAppearanceConfigurable.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options.editor;
+
+import com.intellij.openapi.options.BeanConfigurable;
+import com.intellij.openapi.options.UnnamedConfigurable;
+import com.intellij.xml.XmlBundle;
+
+/**
+ * @author yole
+ */
+public class WebEditorAppearanceConfigurable extends BeanConfigurable<WebEditorOptions> implements UnnamedConfigurable {
+  public WebEditorAppearanceConfigurable() {
+    super(WebEditorOptions.getInstance());
+    checkBox("breadcrumbsEnabled", XmlBundle.message("xml.editor.options.breadcrumbs.title"));
+    checkBox("breadcrumbsEnabledInXml", XmlBundle.message("xml.editor.options.breadcrumbs.for.xml.title"));
+    checkBox("showCssColorPreviewInGutter", "Show CSS color preview icon in gutter");
+    checkBox("showCssInlineColorPreview", "Show CSS color preview as background");
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptions.java b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptions.java
new file mode 100644
index 0000000..570014a
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptions.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options.editor;
+
+import com.intellij.codeInsight.template.impl.TemplateSettings;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.components.*;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+
+/**
+ * @author spleaner
+ */
+@State(
+  name="XmlEditorOptions",
+  storages= {
+    @Storage(
+      file = StoragePathMacros.APP_CONFIG + "/editor.xml"
+    )}
+)
+public class WebEditorOptions implements PersistentStateComponent<WebEditorOptions>, ExportableComponent {
+
+  private boolean myBreadcrumbsEnabled = true;
+  private boolean myBreadcrumbsEnabledInXml = false;
+  private boolean myShowCssColorPreviewInGutter = true;
+  private boolean myShowCssInlineColorPreview = false;
+  private boolean myAutomaticallyInsertClosingTag = true;
+  private boolean myAutomaticallyInsertRequiredAttributes = true;
+  private boolean myAutomaticallyInsertRequiredSubTags = true;
+  private boolean myAutomaticallyStartAttribute = true;
+  private boolean myZenCodingEnabled = true;
+  private int myZenCodingExpandShortcut = TemplateSettings.TAB_CHAR;
+
+  private boolean myTagTreeHighlightingEnabled = true;
+  private int myTagTreeHighlightingLevelCount = 6;
+  private int myTagTreeHighlightingOpacity = 10;
+
+  public static WebEditorOptions getInstance() {
+    return ServiceManager.getService(WebEditorOptions.class);
+  }
+
+  public WebEditorOptions() {
+    setTagTreeHighlightingEnabled(!ApplicationManager.getApplication().isUnitTestMode());
+  }
+
+  public void setBreadcrumbsEnabled(boolean b) {
+    myBreadcrumbsEnabled = b;
+  }
+
+  public boolean isBreadcrumbsEnabled() {
+    return myBreadcrumbsEnabled;
+  }
+
+  public void setBreadcrumbsEnabledInXml(boolean b) {
+    myBreadcrumbsEnabledInXml = b;
+  }
+
+  public boolean isBreadcrumbsEnabledInXml() {
+    return myBreadcrumbsEnabledInXml;
+  }
+
+  public boolean isShowCssInlineColorPreview() {
+    return myShowCssInlineColorPreview;
+  }
+
+  public void setShowCssInlineColorPreview(final boolean showCssInlineColorPreview) {
+    myShowCssInlineColorPreview = showCssInlineColorPreview;
+  }
+
+  public boolean isShowCssColorPreviewInGutter() {
+    return myShowCssColorPreviewInGutter;
+  }
+
+  public void setShowCssColorPreviewInGutter(final boolean showCssColorPreviewInGutter) {
+    myShowCssColorPreviewInGutter = showCssColorPreviewInGutter;
+  }
+
+  public boolean isAutomaticallyInsertClosingTag() {
+    return myAutomaticallyInsertClosingTag;
+  }
+
+  public void setAutomaticallyInsertClosingTag(final boolean automaticallyInsertClosingTag) {
+    myAutomaticallyInsertClosingTag = automaticallyInsertClosingTag;
+  }
+
+  public boolean isAutomaticallyInsertRequiredAttributes() {
+    return myAutomaticallyInsertRequiredAttributes;
+  }
+
+  public void setAutomaticallyInsertRequiredAttributes(final boolean automaticallyInsertRequiredAttributes) {
+    myAutomaticallyInsertRequiredAttributes = automaticallyInsertRequiredAttributes;
+  }
+
+  public int getZenCodingExpandShortcut() {
+    return myZenCodingExpandShortcut;
+  }
+
+  public void setZenCodingExpandShortcut(int zenCodingExpandShortcut) {
+    myZenCodingExpandShortcut = zenCodingExpandShortcut;
+  }
+
+  public boolean isAutomaticallyStartAttribute() {
+    return myAutomaticallyStartAttribute;
+  }
+
+  public boolean isZenCodingEnabled() {
+    return myZenCodingEnabled;
+  }
+
+  public void setAutomaticallyStartAttribute(final boolean automaticallyStartAttribute) {
+    myAutomaticallyStartAttribute = automaticallyStartAttribute;
+  }
+
+  public void setZenCodingEnabled(boolean zenCodingEnabled) {
+    myZenCodingEnabled = zenCodingEnabled;
+  }
+
+  public boolean isAutomaticallyInsertRequiredSubTags() {
+    return myAutomaticallyInsertRequiredSubTags;
+  }
+
+  public void setAutomaticallyInsertRequiredSubTags(boolean automaticallyInsertRequiredSubTags) {
+    myAutomaticallyInsertRequiredSubTags = automaticallyInsertRequiredSubTags;
+  }
+
+  public void setTagTreeHighlightingLevelCount(int tagTreeHighlightingLevelCount) {
+    myTagTreeHighlightingLevelCount = tagTreeHighlightingLevelCount;
+  }
+
+  public int getTagTreeHighlightingLevelCount() {
+    return myTagTreeHighlightingLevelCount;
+  }
+
+  public void setTagTreeHighlightingOpacity(int tagTreeHighlightingOpacity) {
+    myTagTreeHighlightingOpacity = tagTreeHighlightingOpacity;
+  }
+
+  public int getTagTreeHighlightingOpacity() {
+    return myTagTreeHighlightingOpacity;
+  }
+
+  public void setTagTreeHighlightingEnabled(boolean tagTreeHighlightingEnabled) {
+    myTagTreeHighlightingEnabled = tagTreeHighlightingEnabled;
+  }
+
+  public boolean isTagTreeHighlightingEnabled() {
+    return myTagTreeHighlightingEnabled;
+  }
+
+  @NotNull
+  public File[] getExportFiles() {
+    return new File[]{PathManager.getOptionsFile("editor")};
+  }
+
+  @NotNull
+  public String getPresentableName() {
+    return XmlBundle.message("xml.options");
+  }
+
+  @Nullable
+  public Object clone() {
+    try {
+      return super.clone();
+    }
+    catch (CloneNotSupportedException e) {
+      return null;
+    }
+  }
+
+  public WebEditorOptions getState() {
+    return this;
+  }
+
+  public void loadState(final WebEditorOptions state) {
+    XmlSerializerUtil.copyBean(state, this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsForm.form b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsForm.form
new file mode 100644
index 0000000..0030a84
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsForm.form
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.editor.WebEditorOptionsProvider">
+  <grid id="27dc6" binding="myWholePanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="362" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <grid id="247ce" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <clientProperties>
+          <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
+        </clientProperties>
+        <border type="none" title-resource-bundle="messages/XmlBundle" title-key="xml.editor.options.misc.title"/>
+        <children>
+          <component id="f6c8c" class="javax.swing.JCheckBox" binding="myAutomaticallyInsertClosingTagCheckBox" default-binding="true">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="Automatically insert closing tag"/>
+            </properties>
+          </component>
+          <component id="9f825" class="javax.swing.JCheckBox" binding="myAutomaticallyInsertRequiredAttributesCheckBox" default-binding="true">
+            <constraints>
+              <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="Automatically insert required attributes"/>
+            </properties>
+          </component>
+          <component id="4bf74" class="javax.swing.JCheckBox" binding="myAutomaticallyStartAttributeAfterCheckBox" default-binding="true">
+            <constraints>
+              <grid row="3" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <selected value="false"/>
+              <text value="Automatically start attribute"/>
+            </properties>
+          </component>
+          <component id="ba426" class="javax.swing.JCheckBox" binding="myEnableZenCodingCheckBox">
+            <constraints>
+              <grid row="4" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="Enable Zen Coding"/>
+            </properties>
+          </component>
+          <component id="7c51c" class="javax.swing.JLabel">
+            <constraints>
+              <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="3" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="Expand abbreviation with"/>
+            </properties>
+          </component>
+          <component id="ed567" class="javax.swing.JComboBox" binding="myZenCodingExpandShortcutCombo">
+            <constraints>
+              <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+          </component>
+          <hspacer id="8ee6f">
+            <constraints>
+              <grid row="5" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+            </constraints>
+          </hspacer>
+          <component id="c21d3" class="javax.swing.JCheckBox" binding="myAutomaticallyInsertRequiredSubTagsCheckBox" default-binding="true">
+            <constraints>
+              <grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="Automatically insert required subtags"/>
+            </properties>
+          </component>
+        </children>
+      </grid>
+      <vspacer id="e0bcf">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+        </constraints>
+      </vspacer>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java
new file mode 100644
index 0000000..eb1ff2a
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options.editor;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.template.impl.TemplateSettings;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @author spleaner
+ */
+public class WebEditorOptionsProvider implements EditorOptionsProvider {
+  private JPanel myWholePanel;
+  private JCheckBox myAutomaticallyInsertClosingTagCheckBox;
+  private JCheckBox myAutomaticallyInsertRequiredAttributesCheckBox;
+  private JCheckBox myAutomaticallyInsertRequiredSubTagsCheckBox;
+  private JCheckBox myAutomaticallyStartAttributeAfterCheckBox;
+  private JCheckBox myEnableZenCodingCheckBox;
+  private JComboBox myZenCodingExpandShortcutCombo;
+
+  private static final String SPACE = CodeInsightBundle.message("template.shortcut.space");
+  private static final String TAB = CodeInsightBundle.message("template.shortcut.tab");
+  private static final String ENTER = CodeInsightBundle.message("template.shortcut.enter");
+
+  {
+    myZenCodingExpandShortcutCombo.addItem(SPACE);
+    myZenCodingExpandShortcutCombo.addItem(TAB);
+    myZenCodingExpandShortcutCombo.addItem(ENTER);
+    myEnableZenCodingCheckBox.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        myZenCodingExpandShortcutCombo.setEnabled(myEnableZenCodingCheckBox.isSelected());
+      }
+    });
+  }
+
+  public String getDisplayName() {
+    return XmlBundle.message("web.editor.configuration.title");
+  }
+
+  public String getHelpTopic() {
+    return null;
+  }
+
+  public JComponent createComponent() {
+    return myWholePanel;
+  }
+
+  private char getSelectedZenCodingExpandShortcut() {
+    Object selectedItem = myZenCodingExpandShortcutCombo.getSelectedItem();
+    if (TAB.equals(selectedItem)) {
+      return TemplateSettings.TAB_CHAR;
+    }
+    else if (ENTER.equals(selectedItem)) {
+      return TemplateSettings.ENTER_CHAR;
+    }
+    return TemplateSettings.SPACE_CHAR;
+  }
+
+  public boolean isModified() {
+    final WebEditorOptions xmlEditorOptions = WebEditorOptions.getInstance();
+    return xmlEditorOptions.isAutomaticallyInsertClosingTag() != myAutomaticallyInsertClosingTagCheckBox.isSelected() ||
+           xmlEditorOptions.isAutomaticallyInsertRequiredAttributes() != myAutomaticallyInsertRequiredAttributesCheckBox.isSelected() ||
+           xmlEditorOptions.isAutomaticallyStartAttribute() != myAutomaticallyStartAttributeAfterCheckBox.isSelected() ||
+           xmlEditorOptions.isZenCodingEnabled() != myEnableZenCodingCheckBox.isSelected() ||
+           xmlEditorOptions.getZenCodingExpandShortcut() != getSelectedZenCodingExpandShortcut() ||
+           xmlEditorOptions.isAutomaticallyInsertRequiredSubTags() != myAutomaticallyInsertRequiredSubTagsCheckBox.isSelected();
+  }
+
+  public void apply() throws ConfigurationException {
+    final WebEditorOptions xmlEditorOptions = WebEditorOptions.getInstance();
+    xmlEditorOptions.setAutomaticallyInsertClosingTag(myAutomaticallyInsertClosingTagCheckBox.isSelected());
+    xmlEditorOptions.setAutomaticallyInsertRequiredAttributes(myAutomaticallyInsertRequiredAttributesCheckBox.isSelected());
+    xmlEditorOptions.setAutomaticallyInsertRequiredSubTags(myAutomaticallyInsertRequiredSubTagsCheckBox.isSelected());
+    xmlEditorOptions.setAutomaticallyStartAttribute(myAutomaticallyStartAttributeAfterCheckBox.isSelected());
+    xmlEditorOptions.setZenCodingEnabled(myEnableZenCodingCheckBox.isSelected());
+    xmlEditorOptions.setZenCodingExpandShortcut(getSelectedZenCodingExpandShortcut());
+  }
+
+  public void reset() {
+    final WebEditorOptions xmlEditorOptions = WebEditorOptions.getInstance();
+    myAutomaticallyInsertClosingTagCheckBox.setSelected(xmlEditorOptions.isAutomaticallyInsertClosingTag());
+    myAutomaticallyInsertRequiredAttributesCheckBox.setSelected(xmlEditorOptions.isAutomaticallyInsertRequiredAttributes());
+    myAutomaticallyInsertRequiredSubTagsCheckBox.setSelected(xmlEditorOptions.isAutomaticallyInsertRequiredSubTags());
+    myAutomaticallyStartAttributeAfterCheckBox.setSelected(xmlEditorOptions.isAutomaticallyStartAttribute());
+    myEnableZenCodingCheckBox.setSelected(xmlEditorOptions.isZenCodingEnabled());
+    myZenCodingExpandShortcutCombo.setEnabled(xmlEditorOptions.isZenCodingEnabled());
+
+    char shortcut = (char)WebEditorOptions.getInstance().getZenCodingExpandShortcut();
+    if (shortcut == TemplateSettings.TAB_CHAR) {
+      myZenCodingExpandShortcutCombo.setSelectedItem(TAB);
+    }
+    else if (shortcut == TemplateSettings.ENTER_CHAR) {
+      myZenCodingExpandShortcutCombo.setSelectedItem(ENTER);
+    }
+    else {
+      myZenCodingExpandShortcutCombo.setSelectedItem(SPACE);
+    }
+  }
+
+  public void disposeUIResources() {
+  }
+
+  @NotNull
+  public String getId() {
+    return "editor.preferences.webOptions";
+  }
+
+  public Runnable enableSearch(final String option) {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/application/options/editor/XmlCodeFoldingOptionsProvider.java b/xml/impl/src/com/intellij/application/options/editor/XmlCodeFoldingOptionsProvider.java
new file mode 100644
index 0000000..2c685df
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/editor/XmlCodeFoldingOptionsProvider.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * User: anna
+ * Date: 14-Feb-2008
+ */
+package com.intellij.application.options.editor;
+
+import com.intellij.openapi.application.ApplicationBundle;
+import com.intellij.openapi.options.BeanConfigurable;
+
+public class XmlCodeFoldingOptionsProvider extends BeanConfigurable<XmlFoldingSettings> implements CodeFoldingOptionsProvider {
+  public XmlCodeFoldingOptionsProvider() {
+    super(XmlFoldingSettings.getInstance());
+    checkBox("COLLAPSE_XML_TAGS", ApplicationBundle.message("checkbox.collapse.xml.tags"));
+    checkBox("COLLAPSE_HTML_STYLE_ATTRIBUTE", ApplicationBundle.message("checkbox.collapse.html.style.attribute"));
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/application/options/editor/XmlFoldingSettings.java b/xml/impl/src/com/intellij/application/options/editor/XmlFoldingSettings.java
new file mode 100644
index 0000000..05b3e8e
--- /dev/null
+++ b/xml/impl/src/com/intellij/application/options/editor/XmlFoldingSettings.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.application.options.editor;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.components.*;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+
+
+@State(
+  name="XmlFoldingSettings",
+  storages= {
+    @Storage(
+      file = StoragePathMacros.APP_CONFIG + "/editor.codeinsight.xml"
+    )}
+)
+public class XmlFoldingSettings implements PersistentStateComponent<XmlFoldingSettings>, ExportableComponent {
+
+  public static XmlFoldingSettings getInstance() {
+    return ServiceManager.getService(XmlFoldingSettings.class);
+  }
+
+  public boolean isCollapseXmlTags() {
+    return COLLAPSE_XML_TAGS;
+  }
+
+  public void setCollapseXmlTags(boolean value) {
+    COLLAPSE_XML_TAGS = value;
+  }
+
+  public boolean isCollapseHtmlStyleAttribute() {
+    return COLLAPSE_HTML_STYLE_ATTRIBUTE;
+  }
+
+  public void setCollapseHtmlStyleAttribute(boolean value) {
+    this.COLLAPSE_HTML_STYLE_ATTRIBUTE = value;
+  }
+
+  @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_XML_TAGS = false;
+  @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_HTML_STYLE_ATTRIBUTE = true;
+
+  @NotNull
+  public File[] getExportFiles() {
+    return new File[]{PathManager.getOptionsFile("editor.codeinsight")};
+  }
+
+  @NotNull
+  public String getPresentableName() {
+    return XmlBundle.message("xml.folding.settings");
+  }
+
+  public XmlFoldingSettings getState() {
+    return this;
+  }
+
+  public void loadState(final XmlFoldingSettings state) {
+    XmlSerializerUtil.copyBean(state, this);
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/actions/GenerateDTDAction.java b/xml/impl/src/com/intellij/codeInsight/actions/GenerateDTDAction.java
new file mode 100644
index 0000000..1aa5ae4
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/actions/GenerateDTDAction.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.actions;
+
+import com.intellij.codeInsight.CodeInsightActionHandler;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlProcessingInstruction;
+import com.intellij.psi.xml.XmlProlog;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 22.05.2003
+ * Time: 13:46:54
+ * To change this template use Options | File Templates.
+ */
+public class GenerateDTDAction extends BaseCodeInsightAction{
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.GenerateDTDAction");
+  protected CodeInsightActionHandler getHandler(){
+    return new CodeInsightActionHandler(){
+      public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
+        final XmlDocument document = findSuitableXmlDocument(file);
+        if (document != null) {
+          final @NonNls StringBuffer buffer = new StringBuffer();
+          buffer.append("<!DOCTYPE " + document.getRootTag().getName() + " [\n");
+          buffer.append(XmlUtil.generateDocumentDTD(document, true));
+          buffer.append("]>\n");
+          XmlFile tempFile;
+            try{
+              final XmlProlog prolog = document.getProlog();
+              final PsiElement childOfType = PsiTreeUtil.getChildOfType(prolog, XmlProcessingInstruction.class);
+              if (childOfType != null) {
+                final String text = childOfType.getText();
+                buffer.insert(0,text);
+                final PsiElement nextSibling = childOfType.getNextSibling();
+                if (nextSibling instanceof PsiWhiteSpace) {
+                  buffer.insert(text.length(),nextSibling.getText());
+                }
+              }
+              tempFile = (XmlFile)PsiFileFactory.getInstance(file.getProject()).createFileFromText("dummy.xml", buffer.toString());
+              prolog.replace(tempFile.getDocument().getProlog());
+            }
+          catch (IncorrectOperationException e) {
+            LOG.error(e);
+          }
+        }
+      }
+
+      public boolean startInWriteAction(){
+        return true;
+      }
+    };
+  }
+
+  @Nullable
+  private static XmlDocument findSuitableXmlDocument(@Nullable PsiFile psiFile) {
+    if (psiFile instanceof XmlFile) {
+      final VirtualFile virtualFile = psiFile.getVirtualFile();
+      if (virtualFile != null && virtualFile.isWritable()) {
+        final XmlDocument document = ((XmlFile)psiFile).getDocument();
+        if (document != null && document.getRootTag() != null) {
+          return document;
+        }
+      }
+    }
+    return null;
+  }
+
+  public void update(AnActionEvent event) {
+    super.update(event);
+
+    final DataContext dataContext = event.getDataContext();
+    final Presentation presentation = event.getPresentation();
+    Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
+    Project project = PlatformDataKeys.PROJECT.getData(dataContext);
+
+    final boolean enabled;
+    if (editor != null && project != null) {
+      PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+      enabled = findSuitableXmlDocument(file) != null;
+    }
+    else {
+      enabled = false;
+    }
+
+    presentation.setEnabled(enabled);
+    if (ActionPlaces.isPopupPlace(event.getPlace())) {
+      presentation.setVisible(enabled);
+    }
+  }
+
+  protected boolean isValidForFile(Project project, Editor editor, PsiFile file){
+    return file instanceof XmlFile;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/DtdCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/DtdCompletionData.java
new file mode 100644
index 0000000..cdc9649
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/DtdCompletionData.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: Maxim.Mossienko
+ * Date: Oct 19, 2006
+ * Time: 9:41:42 PM
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.TailType;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.filters.*;
+import com.intellij.psi.filters.position.LeftNeighbour;
+import com.intellij.psi.filters.position.XmlTokenTypeFilter;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlEntityDecl;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 05.06.2003
+ * Time: 18:55:15
+ * To change this template use Options | File Templates.
+ */
+public class DtdCompletionData extends CompletionData {
+  public DtdCompletionData() {
+    final LeftNeighbour entityFilter = new LeftNeighbour(new XmlTextFilter("%"));
+
+    declareFinalScope(XmlToken.class);
+
+    {
+      final CompletionVariant variant = new CompletionVariant(
+        new AndFilter(
+          new LeftNeighbour(
+            new OrFilter(
+              new XmlTextFilter(new String[] {"#", "!", "(", ",", "|", "["}),
+              new XmlTokenTypeFilter(XmlTokenType.XML_NAME)
+            )
+          ),
+          new NotFilter(entityFilter)
+        )
+      );
+      variant.includeScopeClass(XmlToken.class, true);
+      variant.addCompletion(
+        new String[] {
+          "#PCDATA","#IMPLIED","#REQUIRED","#FIXED","<!ATTLIST", "<!ELEMENT", "<!NOTATION", "INCLUDE", "IGNORE", "CDATA", "ID" , "IDREF", "EMPTY", "ANY",
+          "IDREFS", "ENTITIES", "ENTITY", "<!ENTITY", "NMTOKEN", "NMTOKENS", "SYSTEM", "PUBLIC"
+        },
+        TailType.NONE
+      );
+      variant.setInsertHandler(new MyInsertHandler());
+      registerVariant(variant);
+    }
+
+    {
+      final CompletionVariant variant = new CompletionVariant(entityFilter);
+      variant.includeScopeClass(XmlToken.class, true);
+      variant.addCompletion(new DtdEntityGetter());
+      variant.setInsertHandler(new XmlCompletionData.EntityRefInsertHandler());
+      registerVariant(variant);
+    }
+  }
+
+  public String findPrefix(PsiElement insertedElement, int offset) {
+    final PsiElement prevLeaf = PsiTreeUtil.prevLeaf(insertedElement);
+    final PsiElement prevPrevLeaf = prevLeaf != null ? PsiTreeUtil.prevLeaf(prevLeaf):null;
+    String prefix = super.findPrefix(insertedElement, offset);
+
+    if (prevLeaf != null) {
+      final String prevLeafText = prevLeaf.getText();
+
+      if("#".equals(prevLeafText)) {
+        prefix = "#" + prefix;
+      } else if ("!".equals(prevLeafText) && prevPrevLeaf != null && "<".equals(prevPrevLeaf.getText())) {
+        prefix = "<!" + prefix;
+      }
+    }
+
+    return prefix;
+  }
+
+  static class DtdEntityGetter implements ContextGetter {
+
+    public Object[] get(final PsiElement context, CompletionContext completionContext) {
+      final List<String> results = new LinkedList<String>();
+
+      final PsiElementProcessor processor = new PsiElementProcessor() {
+        public boolean execute(@NotNull final PsiElement element) {
+          if (element instanceof XmlEntityDecl) {
+            final XmlEntityDecl xmlEntityDecl = (XmlEntityDecl)element;
+            if (xmlEntityDecl.isInternalReference()) {
+              results.add(xmlEntityDecl.getName());
+            }
+          }
+          return true;
+        }
+      };
+
+      XmlUtil.processXmlElements((XmlFile)context.getContainingFile().getOriginalFile(), processor, true);
+      return ArrayUtil.toObjectArray(results);
+    }
+  }
+  static class MyInsertHandler extends BasicInsertHandler {
+
+    public void handleInsert(InsertionContext context, LookupElement item) {
+      super.handleInsert(context, item);
+
+      if (item.getObject().toString().startsWith("<!")) {
+        PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments();
+
+        int caretOffset = context.getEditor().getCaretModel().getOffset();
+        PsiElement tag = PsiTreeUtil.getParentOfType(context.getFile().findElementAt(caretOffset), PsiNamedElement.class);
+
+        if (tag == null) {
+          context.getEditor().getDocument().insertString(caretOffset, " >");
+          context.getEditor().getCaretModel().moveToOffset(caretOffset + 1);
+        }
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/ExtendedTagInsertHandler.java b/xml/impl/src/com/intellij/codeInsight/completion/ExtendedTagInsertHandler.java
new file mode 100644
index 0000000..644dcb9
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/ExtendedTagInsertHandler.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.featureStatistics.FeatureUsageTracker;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.XmlSchemaProvider;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author Dmitry Avdeev
+*/
+public class ExtendedTagInsertHandler extends XmlTagInsertHandler {
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.ExtendedTagInsertHandler");
+
+  protected final String myElementName;
+  @Nullable protected final String myNamespace;
+  @Nullable protected final String myNamespacePrefix;
+
+  public ExtendedTagInsertHandler(final String elementName, @Nullable final String namespace, @Nullable final String namespacePrefix) {
+    myElementName = elementName;
+    myNamespace = namespace;
+    myNamespacePrefix = namespacePrefix;
+  }
+
+  public void handleInsert(final InsertionContext context, final LookupElement item) {
+
+    final XmlFile contextFile = (XmlFile)context.getFile();
+    final XmlExtension extension = XmlExtension.getExtension(contextFile);
+    final XmlFile file = extension.getContainingFile(contextFile);
+    final Project project = context.getProject();
+
+    assert file != null;
+    final PsiElement psiElement = file.findElementAt(context.getStartOffset());
+    assert psiElement != null;
+    if (isNamespaceBound(psiElement)) {
+      doDefault(context, item);
+      return;
+    }
+
+    final Editor editor = context.getEditor();
+    final Document document = editor.getDocument();
+    PsiDocumentManager.getInstance(project).commitDocument(document);
+
+    final int caretOffset = editor.getCaretModel().getOffset();
+    final RangeMarker caretMarker = document.createRangeMarker(caretOffset, caretOffset);
+    caretMarker.setGreedyToRight(true);
+
+    final XmlExtension.Runner<String, IncorrectOperationException> runAfter =
+      new XmlExtension.Runner<String, IncorrectOperationException>() {
+
+        public void run(final String namespacePrefix) {
+
+          PsiDocumentManager.getInstance(project).commitDocument(document);
+          final PsiElement element = file.findElementAt(context.getStartOffset());
+          if (element != null) {
+            qualifyWithPrefix(namespacePrefix, element, document);
+            PsiDocumentManager.getInstance(project).commitDocument(document);
+          }
+          editor.getCaretModel().moveToOffset(caretMarker.getEndOffset());
+          PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
+          doDefault(context, item);
+        }
+      };
+
+    try {
+      final String prefixByNamespace = getPrefixByNamespace(file, myNamespace);
+      if (myNamespacePrefix != null || StringUtil.isEmpty(prefixByNamespace)) {
+        final String nsPrefix = myNamespacePrefix == null ? suggestPrefix(file, myNamespace) : myNamespacePrefix;
+        extension.insertNamespaceDeclaration(file, editor, Collections.singleton(myNamespace), nsPrefix, runAfter);
+        FeatureUsageTracker.getInstance().triggerFeatureUsed(XmlCompletionContributor.TAG_NAME_COMPLETION_FEATURE);
+      } else {
+        runAfter.run(prefixByNamespace);    // qualify && complete
+      }
+    }
+    catch (IncorrectOperationException e) {
+      LOG.error(e);
+    }
+  }
+
+  protected void doDefault(final InsertionContext context, final LookupElement item) {
+    ExtendedTagInsertHandler.super.handleInsert(context, item);
+  }
+
+  protected boolean isNamespaceBound(PsiElement psiElement) {
+    PsiElement parent = psiElement.getParent();
+    if (!(parent instanceof XmlTag)) return false;
+    final XmlTag tag = (XmlTag)parent;
+    final XmlElementDescriptor tagDescriptor = tag.getDescriptor();
+    final String tagNamespace = tag.getNamespace();
+    assert myNamespace != null;
+    return tagDescriptor != null && !(tagDescriptor instanceof AnyXmlElementDescriptor) && myNamespace.equals(tagNamespace);
+  }
+
+  @Nullable
+  public static String getPrefixByNamespace(XmlFile file, final String namespace) {
+    final XmlTag tag = file.getRootTag();
+    return tag == null ? null : tag.getPrefixByNamespace(namespace);
+  }
+
+  @Nullable
+  public static String suggestPrefix(XmlFile file, @Nullable String namespace) {
+    if (namespace == null) {
+      return null;
+    }
+    for (XmlSchemaProvider provider : XmlSchemaProvider.getAvailableProviders(file)) {
+      String prefix = provider.getDefaultPrefix(namespace, file);
+      if (prefix != null) {
+        return prefix;
+      }
+    }
+    return null; 
+  }
+
+  protected Set<String> getNamespaces(final XmlFile file) {
+    return XmlExtension.getExtension(file).getNamespacesByTagName(myElementName, file);
+  }
+
+  protected void qualifyWithPrefix(final String namespacePrefix, final PsiElement element, final Document document) {
+    qualifyWithPrefix(namespacePrefix, element);
+  }
+
+  public static void qualifyWithPrefix(final String namespacePrefix, final PsiElement element) {
+    final PsiElement tag = element.getParent();
+    if (tag instanceof XmlTag) {
+      final String prefix = ((XmlTag)tag).getNamespacePrefix();
+      if (!prefix.equals(namespacePrefix)) {
+        final String name = namespacePrefix + ":" + ((XmlTag)tag).getLocalName();
+        try {
+          ((XmlTag)tag).setName(name);
+        }
+        catch (IncorrectOperationException e) {
+          LOG.error(e);
+        }
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java
new file mode 100644
index 0000000..dbf7393
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.lang.Language;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.filters.AndFilter;
+import com.intellij.psi.filters.ElementFilter;
+import com.intellij.psi.filters.OrFilter;
+import com.intellij.psi.filters.TextContainFilter;
+import com.intellij.psi.filters.getters.HtmlAttributeValueGetter;
+import com.intellij.psi.filters.getters.XmlAttributeValueGetter;
+import com.intellij.psi.filters.position.XmlTokenTypeFilter;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * @author Maxim.Mossienko
+ */
+@SuppressWarnings({"RefusedBequest"})
+public class HtmlCompletionData extends XmlCompletionData {
+  private boolean myCaseInsensitive;
+  private static final @NonNls String JAVASCRIPT_LANGUAGE_ID = "JavaScript";
+  private static final @NonNls String STYLE_TAG = "style";
+  private static final @NonNls String SCRIPT_TAG = "script";
+
+  public HtmlCompletionData() {
+    this(true);
+  }
+
+  protected HtmlCompletionData(boolean _caseInsensitive) {
+    myCaseInsensitive = _caseInsensitive;
+  }
+
+  protected ElementFilter createXmlEntityCompletionFilter() {
+    if (isCaseInsensitive()) {
+      return new AndFilter(
+        new OrFilter (
+          new XmlTokenTypeFilter(XmlTokenType.XML_DATA_CHARACTERS),
+          new XmlTokenTypeFilter(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN)
+        ),
+        new TextContainFilter("&")
+      );
+    }
+    
+    return super.createXmlEntityCompletionFilter();
+  }
+
+  private boolean equalNames(String str,String str2) {
+    if (!myCaseInsensitive) return str.equals(str2);
+    return str.equalsIgnoreCase(str2);
+  }
+
+  protected boolean isCaseInsensitive() {
+    return true;
+  }
+
+  public final boolean isCaseSensitive() {
+    return !isCaseInsensitive();
+  }
+
+  protected void setCaseInsensitive(final boolean caseInsensitive) {
+    myCaseInsensitive = caseInsensitive;
+  }
+
+  protected XmlAttributeValueGetter getAttributeValueGetter() {
+    return new HtmlAttributeValueGetter(!isCaseInsensitive());
+  }
+
+  protected ElementFilter createTagCompletionFilter() {
+    return new ElementFilter() {
+      public boolean isAcceptable(Object element, PsiElement context) {
+        String name = ((XmlTag)context).getName();
+
+        if (element instanceof PsiElement && 
+            ((PsiElement)element).getParent() == context) {
+          return true;
+        }
+
+        if (equalNames(name, STYLE_TAG) ||
+            equalNames(name,SCRIPT_TAG)) {
+          return false;
+        }
+
+        if ( isStyleAttributeContext((PsiElement)element) ) return false;
+        return true;
+      }
+
+      public boolean isClassAcceptable(Class hintClass) {
+        return true;
+      }
+    };
+  }
+
+  protected ElementFilter createAttributeCompletionFilter() {
+    return new ElementFilter() {
+      public boolean isAcceptable(Object element, PsiElement context) {
+        if (isStyleAttributeContext(context)) return false;
+        return true;
+      }
+
+      public boolean isClassAcceptable(Class hintClass) {
+        return true;
+      }
+    };
+  }
+
+  protected ElementFilter createAttributeValueCompletionFilter() {
+    return new ElementFilter() {
+      public boolean isAcceptable(Object element, PsiElement context) {
+        if (isStyleAttributeContext(context)) return false;
+        if ( isScriptContext((PsiElement)element) ) return false;
+        return true;
+      }
+
+      public boolean isClassAcceptable(Class hintClass) {
+        return true;
+      }
+    };
+  }
+
+  private static boolean isScriptContext(PsiElement element) {
+    final Language language = element.getLanguage();
+
+    return language.getID().equals(JAVASCRIPT_LANGUAGE_ID);
+  }
+
+  private boolean isStyleAttributeContext(PsiElement position) {
+    XmlAttribute parentOfType = PsiTreeUtil.getParentOfType(position, XmlAttribute.class, false);
+
+    if (parentOfType != null) {
+      String name = parentOfType.getName();
+      if (myCaseInsensitive) return STYLE_TAG.equalsIgnoreCase(name);
+      return STYLE_TAG.equals(name); //name.endsWith("style");
+    }
+
+    return false;
+  }
+
+  public void registerVariant(CompletionVariant variant) {
+    super.registerVariant(variant);
+    if (isCaseInsensitive()) variant.setCaseInsensitive(true);
+  }
+
+  public String findPrefix(PsiElement insertedElement, int offset) {
+    String prefix = super.findPrefix(insertedElement, offset);
+
+    boolean searchForEntities =
+      insertedElement instanceof XmlToken &&
+      ( ((XmlToken)insertedElement).getTokenType() == XmlTokenType.XML_DATA_CHARACTERS ||
+        ((XmlToken)insertedElement).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN
+      );
+
+    if (searchForEntities) {
+      if (prefix.startsWith("&")) {
+        prefix = prefix.substring(1);
+      } else if (prefix.contains("&")) {
+        prefix = prefix.substring(prefix.indexOf("&") + 1);
+      }
+    }
+
+    return prefix;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XHtmlCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/XHtmlCompletionData.java
new file mode 100644
index 0000000..c7ce4e6
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XHtmlCompletionData.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+/**
+ * @author maxim
+ */
+public class XHtmlCompletionData extends HtmlCompletionData {
+  public XHtmlCompletionData() {
+    super(false);
+  }
+
+  protected boolean isCaseInsensitive() {
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeInsertHandler.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeInsertHandler.java
new file mode 100644
index 0000000..20b3611
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeInsertHandler.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.text.CharArrayUtil;
+import com.intellij.xml.util.HtmlUtil;
+
+/**
+* @author peter
+*/
+public class XmlAttributeInsertHandler implements InsertHandler<LookupElement> {
+  public static final XmlAttributeInsertHandler INSTANCE = new XmlAttributeInsertHandler();
+
+  public void handleInsert(InsertionContext context, LookupElement item) {
+    final Editor editor = context.getEditor();
+
+    final Document document = editor.getDocument();
+    final int caretOffset = editor.getCaretModel().getOffset();
+    PsiFile file = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(document);
+    if (file.getLanguage() == HTMLLanguage.INSTANCE &&
+        HtmlUtil.isSingleHtmlAttribute((String)item.getObject())) {
+      return;
+    }
+
+    final CharSequence chars = document.getCharsSequence();
+    if (!CharArrayUtil.regionMatches(chars, caretOffset, "=\"") && !CharArrayUtil.regionMatches(chars, caretOffset, "='")) {
+      PsiElement fileContext = file.getContext();
+      String toInsert= "=\"\"";
+
+      if(fileContext != null) {
+        if (fileContext.getText().startsWith("\"")) toInsert = "=''";
+      }
+      
+      if (caretOffset >= document.getTextLength() || "/> \n\t\r".indexOf(document.getCharsSequence().charAt(caretOffset)) < 0) {
+        document.insertString(caretOffset, toInsert + " ");
+      }
+      else {
+        document.insertString(caretOffset, toInsert);
+      }
+
+      if ('=' == context.getCompletionChar()) {
+        context.setAddCompletionChar(false); // IDEA-19449
+      }
+    }
+
+    editor.getCaretModel().moveToOffset(caretOffset + 2);
+    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+    editor.getSelectionModel().removeSelection();
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCharFilter.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCharFilter.java
new file mode 100644
index 0000000..9f09962
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCharFilter.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: mike
+ * Date: Jul 23, 2002
+ * Time: 3:15:07 PM
+ * To change template for new class use 
+ * Code Style | Class Templates options (Tools | IDE Options).
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.editorActions.XmlAutoPopupHandler;
+import com.intellij.codeInsight.lookup.CharFilter;
+import com.intellij.codeInsight.lookup.Lookup;
+import com.intellij.lang.Language;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlText;
+
+public class XmlCharFilter extends CharFilter {
+
+  public static boolean isInXmlContext(Lookup lookup) {
+    if (!lookup.isCompletion()) return false;
+
+    PsiElement psiElement = lookup.getPsiElement();
+    PsiFile file = lookup.getPsiFile();
+    if (!(file instanceof XmlFile) && psiElement != null) {
+      file = psiElement.getContainingFile();
+    }
+
+
+    if (file instanceof XmlFile) {
+      if (psiElement != null) {
+        PsiElement elementToTest = psiElement;
+        if (elementToTest instanceof PsiWhiteSpace) {
+          elementToTest = elementToTest.getParent(); // JSPX has whitespace with language Java
+        }
+
+        final Language language = elementToTest.getLanguage();
+        if (!(language instanceof XMLLanguage)) {
+          return false;
+        }
+      }
+      return true;
+    }
+    return false;
+  }
+
+  public static boolean isWithinTag(Lookup lookup) {
+    if (isInXmlContext(lookup)) {
+      PsiElement psiElement = lookup.getPsiElement();
+      final PsiElement parentElement = psiElement.getParent() != null ? psiElement.getParent():null;
+      String s;
+      return parentElement != null &&
+             ( parentElement instanceof XmlTag ||
+               ( parentElement instanceof PsiErrorElement &&
+                 parentElement.getParent() instanceof XmlDocument
+               ) ||
+                 ((parentElement instanceof XmlDocument || parentElement instanceof XmlText) &&
+                  ((s = psiElement.getText()).equals("<") || s.equals("\""))));
+    }
+    return false;
+  }
+
+  public Result acceptChar(char c, final int prefixLength, final Lookup lookup) {
+    if (!isInXmlContext(lookup)) return null;
+
+    if (Character.isJavaIdentifierPart(c)) return Result.ADD_TO_PREFIX;
+    switch(c){
+      case '-':
+      case ':':
+        return Result.ADD_TO_PREFIX;
+      case '/':
+        if (isWithinTag(lookup)) {
+          if (prefixLength > 0) {
+            return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
+          }
+          XmlAutoPopupHandler.autoPopupXmlLookup(lookup.getEditor().getProject(), lookup.getEditor());
+          return Result.HIDE_LOOKUP;
+        }
+        return Result.ADD_TO_PREFIX;
+
+      case '>': if (prefixLength > 0) {
+        return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
+      }
+
+      case '\'':
+      case '\"':
+        return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
+      default:
+        return null;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java
new file mode 100644
index 0000000..3979367
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.lookup.InsertHandlerDecorator;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.codeInsight.lookup.LookupElementDecorator;
+import com.intellij.featureStatistics.FeatureUsageTracker;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.patterns.PlatformPatterns;
+import com.intellij.patterns.XmlPatterns;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.Consumer;
+import com.intellij.util.ProcessingContext;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlExtension;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlCompletionContributor extends CompletionContributor {
+  public static final Key<Boolean> WORD_COMPLETION_COMPATIBLE = Key.create("WORD_COMPLETION_COMPATIBLE");
+
+  @NonNls public static final String TAG_NAME_COMPLETION_FEATURE = "tag.name.completion";
+  private static final InsertHandlerDecorator<LookupElement> QUOTE_EATER = new InsertHandlerDecorator<LookupElement>() {
+    public void handleInsert(InsertionContext context, LookupElementDecorator<LookupElement> item) {
+      final char completionChar = context.getCompletionChar();
+      if (completionChar == '\'' || completionChar == '\"') {
+        context.setAddCompletionChar(false);
+        item.getDelegate().handleInsert(context);
+
+        final Editor editor = context.getEditor();
+        final Document document = editor.getDocument();
+        int tailOffset = editor.getCaretModel().getOffset();
+        if (document.getTextLength() > tailOffset) {
+          final char c = document.getCharsSequence().charAt(tailOffset);
+          if (c == completionChar || completionChar == '\'') {
+            editor.getCaretModel().moveToOffset(tailOffset + 1);
+          }
+        }
+      } else {
+        item.getDelegate().handleInsert(context);
+      }
+    }
+  };
+
+  public XmlCompletionContributor() {
+    extend(CompletionType.BASIC,
+           PlatformPatterns.psiElement().inside(XmlPatterns.xmlAttributeValue()),
+           new CompletionProvider<CompletionParameters>() {
+             @Override
+             protected void addCompletions(@NotNull CompletionParameters parameters,
+                                           ProcessingContext context,
+                                           @NotNull final CompletionResultSet result) {
+               final XmlAttributeValue attributeValue = PsiTreeUtil.getParentOfType(parameters.getPosition(), XmlAttributeValue.class, false);
+               if (attributeValue == null) {
+                 // we are injected, only getContext() returns attribute value
+                 return;
+               }
+
+               final Set<String> usedWords = new THashSet<String>();
+               final Ref<Boolean> addWordVariants = Ref.create(true);
+               result.runRemainingContributors(parameters, new Consumer<CompletionResult>() {
+                 public void consume(CompletionResult r) {
+                   if (r.getLookupElement().getUserData(WORD_COMPLETION_COMPATIBLE) == null) {
+                     addWordVariants.set(false);
+                   }
+                   usedWords.add(r.getLookupElement().getLookupString());
+                   result.passResult(r.withLookupElement(LookupElementDecorator.withInsertHandler(r.getLookupElement(), QUOTE_EATER)));
+                 }
+               });
+               if (addWordVariants.get().booleanValue()) {
+                 addWordVariants.set(attributeValue.getReferences().length == 0);
+               }
+
+               if (addWordVariants.get().booleanValue() && parameters.getInvocationCount() > 0) {
+                 WordCompletionContributor.addWordCompletionVariants(result, parameters, usedWords);
+               }
+             }
+           });
+  }
+
+  public static boolean isXmlNameCompletion(final CompletionParameters parameters) {
+    final ASTNode node = parameters.getPosition().getNode();
+    return node != null && node.getElementType() == XmlTokenType.XML_NAME;
+  }
+
+  public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
+    super.fillCompletionVariants(parameters, result);
+    if (result.isStopped()) {
+      return;
+    }
+
+    final PsiElement element = parameters.getPosition();
+
+    if (parameters.isExtendedCompletion()) {
+      completeTagName(parameters, result);
+    }
+
+    else if (parameters.getCompletionType() == CompletionType.SMART) {
+      new XmlSmartCompletionProvider().complete(parameters, result, element);
+    }
+  }
+
+  static void completeTagName(CompletionParameters parameters, CompletionResultSet result) {
+    PsiElement element = parameters.getPosition();
+    if (!isXmlNameCompletion(parameters)) return;
+    result.stopHere();
+    PsiElement parent = element.getParent();
+    if (!(parent instanceof XmlTag) ||
+        !(parameters.getOriginalFile() instanceof XmlFile)) {
+      return;
+    }
+    final XmlTag tag = (XmlTag)parent;
+    final String namespace = tag.getNamespace();
+    final String prefix = result.getPrefixMatcher().getPrefix();
+    final int pos = prefix.indexOf(':');
+
+    final PsiReference reference = tag.getReference();
+    String namespacePrefix = tag.getNamespacePrefix();
+
+    if (reference != null && !namespace.isEmpty() && !namespacePrefix.isEmpty()) {
+      // fallback to simple completion
+      final Set<LookupElement> set = new HashSet<LookupElement>();
+      new XmlCompletionData().completeReference(reference, set, element, parameters.getOriginalFile(), parameters.getOffset());
+      for (final LookupElement item : set) {
+        result.addElement(item);
+      }
+    }
+    else {
+
+      final CompletionResultSet newResult = result.withPrefixMatcher(pos >= 0 ? prefix.substring(pos + 1) : prefix);
+
+      final XmlFile file = (XmlFile)parameters.getOriginalFile();
+      final List<Pair<String,String>> names = XmlExtension.getExtension(file).getAvailableTagNames(file, tag);
+      for (Pair<String, String> pair : names) {
+        final String name = pair.getFirst();
+        final String ns = pair.getSecond();
+        final LookupElement item = createLookupElement(name, ns, ns, namespacePrefix.isEmpty() ? null : namespacePrefix);
+        newResult.addElement(item);
+      }
+    }
+  }
+
+  public static LookupElement createLookupElement(final String name,
+                                                  final String namespace,
+                                                  final String tailText, @Nullable String namespacePrefix) {
+    LookupElementBuilder builder =
+      LookupElementBuilder.create(Pair.create(name, namespace), name).withInsertHandler(
+        new ExtendedTagInsertHandler(name, namespace, namespacePrefix));
+    if (!StringUtil.isEmpty(namespace)) {
+      builder = builder.withTypeText(tailText, true);
+    }
+    return builder;
+  }
+
+  @Override
+  public String advertise(@NotNull final CompletionParameters parameters) {
+    if (isXmlNameCompletion(parameters) && parameters.getCompletionType() == CompletionType.BASIC) {
+      if (FeatureUsageTracker.getInstance().isToBeAdvertisedInLookup(TAG_NAME_COMPLETION_FEATURE, parameters.getPosition().getProject())) {
+        final String shortcut = getActionShortcut(IdeActions.ACTION_CODE_COMPLETION);
+        if (shortcut != null) {
+          return XmlBundle.message("tag.name.completion.hint", shortcut);
+        }
+
+      }
+    }
+    return super.advertise(parameters);
+  }
+
+  public void beforeCompletion(@NotNull final CompletionInitializationContext context) {
+    final int offset = context.getStartOffset();
+    final XmlAttributeValue attributeValue = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), offset, XmlAttributeValue.class, true);
+    if (attributeValue != null && offset == attributeValue.getTextRange().getStartOffset()) {
+      context.setDummyIdentifier("");
+    }
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
new file mode 100644
index 0000000..00d6c1e
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.TailType;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupValueFactory;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.editor.CaretModel;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.filters.*;
+import com.intellij.psi.filters.getters.XmlAttributeValueGetter;
+import com.intellij.psi.filters.position.LeftNeighbour;
+import com.intellij.psi.filters.position.XmlTokenTypeFilter;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 05.06.2003
+ * Time: 18:55:15
+ * To change this template use Options | File Templates.
+ */
+public class XmlCompletionData extends CompletionData {
+  public XmlCompletionData() {
+    declareFinalScope(XmlTag.class);
+    declareFinalScope(XmlAttribute.class);
+    declareFinalScope(XmlAttributeValue.class);
+
+    {
+      final CompletionVariant variant = new CompletionVariant(createTagCompletionFilter());
+      variant.includeScopeClass(XmlTag.class);
+      variant.addCompletionFilter(TrueFilter.INSTANCE);
+      registerVariant(variant);
+    }
+
+    {
+      final CompletionVariant variant = new CompletionVariant(createAttributeCompletionFilter());
+      variant.includeScopeClass(XmlAttribute.class);
+      variant.addCompletionFilter(TrueFilter.INSTANCE);
+      registerVariant(variant);
+    }
+
+    {
+      final CompletionVariant variant = new CompletionVariant(createAttributeValueCompletionFilter());
+      variant.includeScopeClass(XmlAttributeValue.class);
+      variant.addCompletion(getAttributeValueGetter(), TailType.NONE);
+      variant.addCompletionFilter(TrueFilter.INSTANCE, TailType.NONE);
+      registerVariant(variant);
+    }
+
+    final ElementFilter entityCompletionFilter = createXmlEntityCompletionFilter();
+
+    {
+      final CompletionVariant variant = new CompletionVariant(
+        new AndFilter(new XmlTokenTypeFilter(XmlTokenType.XML_DATA_CHARACTERS), new NotFilter(entityCompletionFilter), new ElementFilter() {
+          public boolean isAcceptable(Object element, PsiElement context) {
+            XmlTag tag = PsiTreeUtil.getParentOfType(context, XmlTag.class, false);
+            if (tag != null) {
+              return XmlUtil.getSchemaSimpleContent(tag) != null;
+            }
+            return false;
+          }
+
+          public boolean isClassAcceptable(Class hintClass) {
+            return true;
+          }
+        }));
+      variant.includeScopeClass(XmlToken.class, true);
+      variant.addCompletion(new SimpleTagContentEnumerationValuesGetter(), TailType.NONE);
+
+      registerVariant(variant);
+    }
+    
+    {
+      final CompletionVariant variant = new CompletionVariant(
+        new AndFilter(new XmlTokenTypeFilter(XmlTokenType.XML_DATA_CHARACTERS), new NotFilter(entityCompletionFilter)));
+      variant.includeScopeClass(XmlToken.class, true);
+      registerVariant(variant);
+    }
+
+    {
+      final CompletionVariant variant = new CompletionVariant(entityCompletionFilter);
+      variant.includeScopeClass(XmlToken.class, true);
+      variant.addCompletion(new EntityRefGetter());
+      variant.setInsertHandler(new EntityRefInsertHandler());
+      registerVariant(variant);
+    }
+  }
+
+  protected ElementFilter createXmlEntityCompletionFilter() {
+    return new AndFilter(new LeftNeighbour(new XmlTextFilter("&")), new OrFilter(new XmlTokenTypeFilter(XmlTokenType.XML_DATA_CHARACTERS),
+                                                                                 new XmlTokenTypeFilter(
+                                                                                     XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN)));
+  }
+
+  protected XmlAttributeValueGetter getAttributeValueGetter() {
+    return new XmlAttributeValueGetter();
+  }
+
+  protected ElementFilter createAttributeCompletionFilter() {
+    return TrueFilter.INSTANCE;
+  }
+
+  protected ElementFilter createAttributeValueCompletionFilter() {
+    return TrueFilter.INSTANCE;
+  }
+
+  protected ElementFilter createTagCompletionFilter() {
+    return TrueFilter.INSTANCE;
+  }
+
+  private static class SimpleTagContentEnumerationValuesGetter implements ContextGetter {
+    public Object[] get(final PsiElement context, CompletionContext completionContext) {
+      XmlTag tag = PsiTreeUtil.getParentOfType(context, XmlTag.class, false);
+      if (tag != null) {
+        final XmlTag simpleContent = XmlUtil.getSchemaSimpleContent(tag);
+        if (simpleContent != null) {
+          final HashSet<String> variants = new HashSet<String>();
+          XmlUtil.collectEnumerationValues(simpleContent, variants);
+          return ArrayUtil.toObjectArray(variants);
+        }
+      }
+
+      return ArrayUtil.EMPTY_OBJECT_ARRAY;
+    }
+  }
+
+  protected static class EntityRefGetter implements ContextGetter {
+
+    @Nullable
+    private static Object getLookupItem(@Nullable final XmlEntityDecl decl) {
+      if (decl == null) {
+        return null;
+      }
+
+      final String name = decl.getName();
+      if (name == null) {
+        return null;
+      }
+
+      final XmlAttributeValue value = decl.getValueElement();
+      final ASTNode node = value.getNode();
+      if (node != null) {
+        final ASTNode[] nodes = node.getChildren(TokenSet.create(XmlTokenType.XML_CHAR_ENTITY_REF));
+        if (nodes.length == 1) {
+          final String valueText = nodes[0].getText();
+          final int i = valueText.indexOf('#');
+          if (i > 0) {
+            String s = valueText.substring(i + 1);
+            if (s.endsWith(";")) {
+              s = s.substring(0, s.length() - 1);
+            }
+
+            try {
+              final int unicodeChar = Integer.valueOf(s).intValue();
+              return LookupValueFactory.createLookupValueWithHint(name, null, new String(Character.toChars(unicodeChar)));
+            }
+            catch (NumberFormatException e) {
+              return null;
+            }
+          }
+        }
+      }
+
+      return null;
+    }
+
+    public Object[] get(final PsiElement context, CompletionContext completionContext) {
+      XmlFile containingFile = null;
+      XmlFile descriptorFile = null;
+      final XmlTag tag = PsiTreeUtil.getParentOfType(context, XmlTag.class);
+
+      if (tag != null) {
+        containingFile = (XmlFile)tag.getContainingFile();
+        descriptorFile = findDescriptorFile(tag, containingFile);
+      }
+
+      boolean isHtml5 = false;
+      if (tag == null || (isHtml5 = HtmlUtil.isHtml5Context(tag))) {  // Html5 RNG does not have entities
+        final XmlDocument document = PsiTreeUtil.getParentOfType(context, XmlDocument.class);
+
+        if (document != null) {
+          containingFile = (XmlFile)document.getContainingFile();
+
+          final FileType ft = containingFile.getFileType();
+
+          if(ft != StdFileTypes.XML) {
+            final String namespace = ft == StdFileTypes.XHTML || ft == StdFileTypes.JSPX || isHtml5? XmlUtil.XHTML_URI:XmlUtil.HTML_URI;
+            final XmlNSDescriptor nsDescriptor = document.getDefaultNSDescriptor(namespace, true);
+
+            if (nsDescriptor != null) {
+              descriptorFile = nsDescriptor.getDescriptorFile();
+            }
+          }
+        }
+      }
+
+      if (descriptorFile != null) {
+        final List<Object> results = new ArrayList<Object>();
+        final boolean acceptSystemEntities = containingFile.getFileType() == StdFileTypes.XML;
+
+        final PsiElementProcessor processor = new PsiElementProcessor() {
+          public boolean execute(@NotNull final PsiElement element) {
+            if (element instanceof XmlEntityDecl) {
+              final XmlEntityDecl xmlEntityDecl = (XmlEntityDecl)element;
+              if (xmlEntityDecl.isInternalReference() || acceptSystemEntities) {
+                final String name = xmlEntityDecl.getName();
+                final Object _item = getLookupItem(xmlEntityDecl);
+                results.add(_item == null ? name : _item);
+              }
+            }
+            return true;
+          }
+        };
+
+        XmlUtil.processXmlElements(descriptorFile, processor, true);
+        if (descriptorFile != containingFile && containingFile.getFileType() == StdFileTypes.XML) {
+          final XmlProlog element = containingFile.getDocument().getProlog();
+          if (element != null) XmlUtil.processXmlElements(element, processor, true);
+        }
+
+        return ArrayUtil.toObjectArray(results);
+      }
+
+      return ArrayUtil.EMPTY_OBJECT_ARRAY;
+    }
+  }
+
+  public static XmlFile findDescriptorFile(final XmlTag tag, final XmlFile containingFile) {
+    final XmlElementDescriptor descriptor = tag.getDescriptor();
+    final XmlNSDescriptor nsDescriptor = descriptor != null ? descriptor.getNSDescriptor() : null;
+    XmlFile descriptorFile = nsDescriptor != null
+                             ? nsDescriptor.getDescriptorFile()
+                             : containingFile.getDocument().getProlog().getDoctype() != null ? containingFile : null;
+    if (nsDescriptor != null && (descriptorFile == null || descriptorFile.getName().equals(containingFile.getName() + ".dtd"))) {
+      descriptorFile = containingFile;
+    }
+    return descriptorFile;
+  }
+
+  protected static class EntityRefInsertHandler extends BasicInsertHandler {
+    public void handleInsert(InsertionContext context, LookupElement item) {
+      super.handleInsert(context, item);
+      context.setAddCompletionChar(false);
+      final CaretModel caretModel = context.getEditor().getCaretModel();
+      context.getEditor().getDocument().insertString(caretModel.getOffset(), ";");
+      caretModel.moveToOffset(caretModel.getOffset() + 1);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlNoVariantsDelegator.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlNoVariantsDelegator.java
new file mode 100644
index 0000000..9166b67
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlNoVariantsDelegator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+/**
+ * @author Dmitry Avdeev
+ *         Date: 12/19/11
+ */
+public class XmlNoVariantsDelegator extends CompletionContributor {
+
+  @Override
+  public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
+    final boolean empty = result.runRemainingContributors(parameters, true).isEmpty();
+
+    if (!empty && parameters.getInvocationCount() == 0) {
+      result.restartCompletionWhenNothingMatches();
+    }
+
+    if (empty && parameters.getCompletionType() == CompletionType.BASIC) {
+      XmlCompletionContributor.completeTagName(parameters, result);
+    }
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartCompletionProvider.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartCompletionProvider.java
new file mode 100644
index 0000000..5321d85
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartCompletionProvider.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.source.xml.XmlContentDFA;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.impl.schema.XmlElementDescriptorImpl;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlSmartCompletionProvider {
+
+  public void complete(CompletionParameters parameters, final CompletionResultSet result, PsiElement element) {
+    if (!XmlCompletionContributor.isXmlNameCompletion(parameters)) {
+      return;
+    }
+    result.stopHere();
+    if (!(element.getParent() instanceof XmlTag)) {
+      return;
+    }
+
+    final XmlTag tag = (XmlTag)element.getParent();
+    final XmlTag parentTag = tag.getParentTag();
+    if (parentTag == null) return;
+    final XmlContentDFA dfa = XmlContentDFA.getContentDFA(parentTag);
+    if (dfa == null) return;
+    ApplicationManager.getApplication().runReadAction(new Runnable() {
+      @Override
+      public void run() {
+        for (XmlTag subTag : parentTag.getSubTags()) {
+          if (subTag == tag) {
+            break;
+          }
+          dfa.transition(subTag);
+        }
+        List<XmlElementDescriptor> elements = dfa.getPossibleElements();
+        for (XmlElementDescriptor elementDescriptor: elements) {
+          addElementToResult(elementDescriptor, result);
+        }
+      }
+    });
+  }
+
+  private static void addElementToResult(@NotNull XmlElementDescriptor descriptor, CompletionResultSet result) {
+    XmlTagInsertHandler insertHandler = XmlTagInsertHandler.INSTANCE;
+    if (descriptor instanceof XmlElementDescriptorImpl) {
+      String name = descriptor.getName();
+      if (name != null) {
+        insertHandler = new ExtendedTagInsertHandler(name, ((XmlElementDescriptorImpl)descriptor).getNamespace(), null);
+      }
+    }
+    result.addElement(createLookupElement(descriptor).withInsertHandler(insertHandler));
+  }
+
+  public static LookupElementBuilder createLookupElement(@NotNull XmlElementDescriptor descriptor) {
+    LookupElementBuilder builder = LookupElementBuilder.create(descriptor.getName());
+    if (descriptor instanceof XmlElementDescriptorImpl) {
+      builder = builder.withTypeText(((XmlElementDescriptorImpl)descriptor).getNamespace(), true);
+    }
+    return builder;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartEnterProcessor.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartEnterProcessor.java
new file mode 100644
index 0000000..e01a7e4
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartEnterProcessor.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.text.CharArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author spleaner
+ */
+public class XmlSmartEnterProcessor extends SmartEnterProcessor {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.XmlSmartEnterProcessor");
+
+  public boolean process(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile psiFile) {
+    /*if (!completeEndTag(project, editor, psiFile)) {
+      return XmlZenCodingTemplate.startZenCoding(editor, psiFile, null);
+    }
+    return true;*/
+    return completeEndTag(project, editor, psiFile);
+  }
+
+  private boolean completeEndTag(Project project, Editor editor, PsiFile psiFile) {
+    final PsiElement atCaret = getStatementAtCaret(editor, psiFile);
+    XmlTag tagAtCaret = PsiTreeUtil.getParentOfType(atCaret, XmlTag.class);
+    if (tagAtCaret == null) {
+      return false;
+    }
+    try {
+      final ASTNode emptyTagEnd = XmlChildRole.EMPTY_TAG_END_FINDER.findChild(tagAtCaret.getNode());
+      final ASTNode endTagEnd = XmlChildRole.START_TAG_END_FINDER.findChild(tagAtCaret.getNode());
+      final Document doc = editor.getDocument();
+      if (emptyTagEnd == null && endTagEnd == null) {
+        int insertionOffset = tagAtCaret.getTextRange().getEndOffset();
+        int caretAt = editor.getCaretModel().getOffset();
+        final CharSequence text = doc.getCharsSequence();
+        final int probableCommaOffset = CharArrayUtil.shiftForward(text, insertionOffset, " \t");
+        final PsiElement siebling = tagAtCaret.getNextSibling();
+        int caretTo = caretAt;
+        char ch;
+
+        if (caretAt < probableCommaOffset) {
+          final XmlAttribute xmlAttribute = PsiTreeUtil.getParentOfType(atCaret, XmlAttribute.class, false, XmlTag.class);
+
+          CharSequence tagNameText = null;
+          if (xmlAttribute != null) {
+            final ASTNode node = tagAtCaret.getNode();
+            if (node != null) {
+              final ASTNode tagName = XmlChildRole.START_TAG_NAME_FINDER.findChild(node);
+              if (tagName != null) {
+                tagNameText = tagName.getText();
+              }
+            }
+
+            final XmlAttributeValue valueElement = xmlAttribute.getValueElement();
+            final TextRange textRange = xmlAttribute.getTextRange();
+            caretAt = valueElement == null
+                      ? textRange.getStartOffset()
+                      : getClosingQuote(xmlAttribute).length() == 0 ? textRange.getEndOffset() : caretAt;
+          }
+
+          if (tagNameText == null) {
+            tagNameText = text.subSequence(tagAtCaret.getTextRange().getStartOffset() + 1, caretAt);
+          }
+
+          final PsiElement element = psiFile.findElementAt(probableCommaOffset);
+          final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
+          final CharSequence text2insert = getClosingPart(xmlAttribute, tagAtCaret, false);
+
+          if (tag != null && tag.getTextRange().getStartOffset() == probableCommaOffset) {
+            doc.insertString(caretAt, text2insert);
+            if (shouldInsertClosingTag(xmlAttribute, tagAtCaret)) {
+              doc.insertString(tag.getTextRange().getEndOffset() + text2insert.length(), "</" + tagAtCaret.getName() + ">");
+            }
+
+            caretTo = tag.getTextRange().getEndOffset() + text2insert.length();
+          }
+          else {
+            doc.insertString(caretAt, text2insert);
+            if (shouldInsertClosingTag(xmlAttribute, tagAtCaret)) {
+              doc.insertString(probableCommaOffset + text2insert.length(), "</" + tagNameText + ">");
+            }
+
+            caretTo = probableCommaOffset + text2insert.length();
+          }
+        }
+        else if (siebling instanceof XmlTag && siebling.getTextRange().getStartOffset() == caretAt) {
+          final XmlAttribute xmlAttribute = PsiTreeUtil.getParentOfType(atCaret, XmlAttribute.class, false, XmlTag.class);
+          final CharSequence text2insert = getClosingPart(xmlAttribute, tagAtCaret, false);
+
+          doc.insertString(caretAt, text2insert);
+          if (shouldInsertClosingTag(xmlAttribute, tagAtCaret)) {
+            doc.insertString(siebling.getTextRange().getEndOffset() + text2insert.length(), "</" + tagAtCaret.getName() + ">");
+          }
+
+          caretTo = siebling.getTextRange().getEndOffset() + text2insert.length();
+        }
+        else if (probableCommaOffset >= text.length() || ((ch = text.charAt(probableCommaOffset)) != '/' && ch != '>')) {
+          final XmlAttribute xmlAttribute = PsiTreeUtil.getParentOfType(atCaret, XmlAttribute.class, false, XmlTag.class);
+          final CharSequence text2insert = getClosingPart(xmlAttribute, tagAtCaret, true);
+
+          doc.insertString(insertionOffset, text2insert);
+          caretTo = insertionOffset + text2insert.length();
+        }
+
+        commitChanges(project, editor, psiFile, caretTo, null);
+
+        return true;
+      }
+      else {
+        final XmlTag unclosedTag = findClosestUnclosedTag(tagAtCaret);
+        if (unclosedTag == null) {
+          return false;
+        }
+
+        final String closingTagString = "</" + unclosedTag.getName() + ">";
+
+        final XmlTag parentTag = unclosedTag.getParentTag();
+        final ASTNode parentEndTagNode = parentTag != null ? XmlChildRole.CLOSING_TAG_START_FINDER.findChild(parentTag.getNode()) : null;
+        final int offset = parentEndTagNode != null
+                           ? parentEndTagNode.getTextRange().getStartOffset()
+                           : unclosedTag.getTextRange().getEndOffset();
+
+        doc.insertString(offset, closingTagString);
+        commitChanges(project, editor, psiFile, offset, parentTag != null ? parentTag : unclosedTag);
+        return true;
+      }
+    }
+    catch (IncorrectOperationException e) {
+      LOG.error(e);
+    }
+    return false;
+  }
+
+  private void commitChanges(Project project, Editor editor, PsiFile psiFile, int caretOffset, @Nullable XmlTag tagToReformat) {
+    if (isUncommited(project)) {
+      commit(editor);
+      if (tagToReformat == null) {
+        tagToReformat = PsiTreeUtil.getParentOfType(getStatementAtCaret(editor, psiFile), XmlTag.class);
+      }
+      editor.getCaretModel().moveToOffset(caretOffset);
+    }
+    if (tagToReformat != null) {
+      reformat(tagToReformat);
+    }
+    commit(editor);
+  }
+
+  @Nullable
+  private static XmlTag findClosestUnclosedTag(final XmlTag tag) {
+    XmlTag unclosedTag = tag;
+    while (unclosedTag != null) {
+      final PsiElement lastChild = unclosedTag.getLastChild();
+      if (isTagUnclosed(lastChild)) {
+        return unclosedTag;
+      }
+      final XmlTag prevTag = PsiTreeUtil.getPrevSiblingOfType(unclosedTag, XmlTag.class);
+      unclosedTag = prevTag != null ? prevTag : PsiTreeUtil.getParentOfType(unclosedTag, XmlTag.class);
+    }
+    return null;
+  }
+
+  protected static boolean isTagUnclosed(PsiElement lastChild) {
+  //strange approach, but it's universal for xml and html
+    return lastChild != null &&
+           lastChild.getNode().getElementType() != XmlTokenType.XML_TAG_END &&
+           lastChild.getNode().getElementType() != XmlTokenType.XML_EMPTY_ELEMENT_END;
+  }
+
+  protected boolean shouldInsertClosingTag(final XmlAttribute xmlAttribute, final XmlTag tagAtCaret) {
+    return true;
+  }
+
+  protected String getClosingPart(final XmlAttribute xmlAttribute, final XmlTag tagAtCaret, final boolean emptyTag) {
+    return getClosingQuote(xmlAttribute) + (emptyTag ? "/>" : ">");
+  }
+
+  @NotNull
+  protected static CharSequence getClosingQuote(@Nullable final XmlAttribute attribute) {
+    if (attribute == null) {
+      return "";
+    }
+
+    final XmlAttributeValue element = attribute.getValueElement();
+    if (element == null) {
+      return "";
+    }
+
+    final String s = element.getText();
+    if (s != null && s.length() > 0) {
+      if (s.charAt(0) == '"' && s.charAt(s.length() - 1) != '"') {
+        return "\"";
+      }
+      else if (s.charAt(0) == '\'' && s.charAt(s.length() - 1) != '\'') {
+        return "'";
+      }
+    }
+
+    return "";
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java
new file mode 100644
index 0000000..5294534
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.application.options.editor.WebEditorOptions;
+import com.intellij.codeInsight.TailType;
+import com.intellij.codeInsight.lookup.Lookup;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupItem;
+import com.intellij.codeInsight.template.Template;
+import com.intellij.codeInsight.template.TemplateEditingAdapter;
+import com.intellij.codeInsight.template.TemplateManager;
+import com.intellij.codeInsight.template.impl.MacroCallNode;
+import com.intellij.codeInsight.template.macro.CompleteMacro;
+import com.intellij.codeInsight.template.macro.CompleteSmartMacro;
+import com.intellij.codeInspection.InspectionProfile;
+import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.command.undo.UndoManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.xml.*;
+import com.intellij.xml.actions.GenerateXmlTagAction;
+import com.intellij.xml.impl.schema.XmlElementDescriptorImpl;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.XmlTagInsertHandler");
+  public static final XmlTagInsertHandler INSTANCE = new XmlTagInsertHandler();
+
+  public void handleInsert(InsertionContext context, LookupElement item) {
+    Project project = context.getProject();
+    Editor editor = context.getEditor();
+    // Need to insert " " to prevent creating tags like <tagThis is my text
+    final int offset = editor.getCaretModel().getOffset();
+    editor.getDocument().insertString(offset, " ");
+    PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
+    PsiElement current = context.getFile().findElementAt(context.getStartOffset());
+    editor.getDocument().deleteString(offset, offset + 1);
+
+    final XmlTag tag = PsiTreeUtil.getContextOfType(current, XmlTag.class, true);
+
+    if (tag == null) return;
+
+    if (context.getCompletionChar() != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
+      context.setAddCompletionChar(false);
+    }
+
+    final XmlElementDescriptor descriptor = tag.getDescriptor();
+
+    if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) == null &&
+        XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) == null) {
+
+      if (descriptor != null) {
+        insertIncompleteTag(context.getCompletionChar(), editor, project, descriptor, tag);
+      }
+    }
+    else if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) {
+      PsiDocumentManager.getInstance(project).commitAllDocuments();
+
+      int caretOffset = editor.getCaretModel().getOffset();
+
+      PsiElement otherTag = PsiTreeUtil.getParentOfType(context.getFile().findElementAt(caretOffset), XmlTag.class);
+
+      PsiElement endTagStart = XmlUtil.getTokenOfType(otherTag, XmlTokenType.XML_END_TAG_START);
+
+      if (endTagStart != null) {
+        PsiElement sibling = endTagStart.getNextSibling();
+
+        assert sibling != null;
+        ASTNode node = sibling.getNode();
+        assert node != null;
+        if (node.getElementType() == XmlTokenType.XML_NAME) {
+          int sOffset = sibling.getTextRange().getStartOffset();
+          int eOffset = sibling.getTextRange().getEndOffset();
+
+          editor.getDocument().deleteString(sOffset, eOffset);
+          assert otherTag != null;
+          editor.getDocument().insertString(sOffset, ((XmlTag)otherTag).getName());
+        }
+      }
+
+      editor.getCaretModel().moveToOffset(caretOffset + 1);
+      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+      editor.getSelectionModel().removeSelection();
+    }
+
+    if (context.getCompletionChar() == ' ' && TemplateManager.getInstance(project).getActiveTemplate(editor) != null) {
+      return;
+    }
+
+    final TailType tailType = LookupItem.handleCompletionChar(editor, item, context.getCompletionChar());
+    tailType.processTail(editor, editor.getCaretModel().getOffset());
+  }
+
+  private static void insertIncompleteTag(char completionChar,
+                                          final Editor editor,
+                                          final Project project,
+                                          XmlElementDescriptor descriptor,
+                                          XmlTag tag) {
+    TemplateManager templateManager = TemplateManager.getInstance(project);
+    Template template = templateManager.createTemplate("", "");
+
+    template.setToIndent(true);
+
+    // temp code
+    PsiFile containingFile = tag.getContainingFile();
+    boolean htmlCode = HtmlUtil.hasHtml(containingFile);
+    template.setToReformat(!htmlCode);
+
+    StringBuilder indirectRequiredAttrs = addRequiredAttributes(descriptor, tag, template, containingFile);
+    final boolean chooseAttributeName = addTail(completionChar, descriptor, htmlCode, tag, template, indirectRequiredAttrs);
+
+    templateManager.startTemplate(editor, template, new TemplateEditingAdapter() {
+      private RangeMarker myAttrValueMarker;
+
+      @Override
+      public void waitingForInput(Template template) {
+        int offset = editor.getCaretModel().getOffset();
+        myAttrValueMarker = editor.getDocument().createRangeMarker(offset + 1, offset + 4);
+      }
+
+      public void templateFinished(final Template template, boolean brokenOff) {
+        final int offset = editor.getCaretModel().getOffset();
+
+        if (chooseAttributeName && offset >= 3) {
+          char c = editor.getDocument().getCharsSequence().charAt(offset - 3);
+          if (c == '/' || (c == ' ' && brokenOff)) {
+            new WriteCommandAction.Simple(project) {
+              protected void run() throws Throwable {
+                editor.getDocument().replaceString(offset - 2, offset + 1, ">");
+              }
+            }.execute();
+          }
+        }
+      }
+
+      public void templateCancelled(final Template template) {
+        if (myAttrValueMarker == null) {
+          return;
+        }
+
+        final UndoManager manager = UndoManager.getInstance(project);
+        if (manager.isUndoInProgress() || manager.isRedoInProgress()) {
+          return;
+        }
+
+        if (chooseAttributeName) {
+          final int startOffset = myAttrValueMarker.getStartOffset();
+          final int endOffset = myAttrValueMarker.getEndOffset();
+          new WriteCommandAction.Simple(project) {
+            protected void run() throws Throwable {
+              editor.getDocument().replaceString(startOffset, endOffset, ">");
+            }
+          }.execute();
+        }
+      }
+    });
+  }
+
+  @Nullable
+  private static StringBuilder addRequiredAttributes(XmlElementDescriptor descriptor,
+                                                     @Nullable XmlTag tag,
+                                                     Template template,
+                                                     PsiFile containingFile) {
+
+    boolean htmlCode = HtmlUtil.hasHtml(containingFile);
+    Set<String> notRequiredAttributes = Collections.emptySet();
+
+    if (tag instanceof HtmlTag) {
+      final InspectionProfile profile = InspectionProjectProfileManager.getInstance(tag.getProject()).getInspectionProfile();
+      LocalInspectionToolWrapper localInspectionToolWrapper = (LocalInspectionToolWrapper) profile.getInspectionTool(
+        RequiredAttributesInspection.SHORT_NAME, tag);
+      RequiredAttributesInspection inspection = localInspectionToolWrapper != null ?
+        (RequiredAttributesInspection) localInspectionToolWrapper.getTool(): null;
+
+      if (inspection != null) {
+        StringTokenizer tokenizer = new StringTokenizer(inspection.getAdditionalEntries(0));
+        notRequiredAttributes = new HashSet<String>();
+
+        while(tokenizer.hasMoreElements()) notRequiredAttributes.add(tokenizer.nextToken());
+      }
+    }
+
+    XmlAttributeDescriptor[] attributes = descriptor.getAttributesDescriptors(tag);
+    StringBuilder indirectRequiredAttrs = null;
+
+    if (WebEditorOptions.getInstance().isAutomaticallyInsertRequiredAttributes()) {
+      final XmlExtension extension = XmlExtension.getExtension(containingFile);
+
+      for (XmlAttributeDescriptor attributeDecl : attributes) {
+        String attributeName = attributeDecl.getName(tag);
+
+        if (attributeDecl.isRequired() && (tag == null || tag.getAttributeValue(attributeName) == null)) {
+          if (!notRequiredAttributes.contains(attributeName)) {
+            if (!extension.isIndirectSyntax(attributeDecl)) {
+              template.addTextSegment(" " + attributeName + "=\"");
+              template.addVariable(new MacroCallNode(new CompleteMacro()), true);
+              template.addTextSegment("\"");
+            }
+            else {
+              if (indirectRequiredAttrs == null) indirectRequiredAttrs = new StringBuilder();
+              indirectRequiredAttrs.append("\n<jsp:attribute name=\"").append(attributeName).append("\"></jsp:attribute>\n");
+            }
+          }
+        }
+        else if (attributeDecl.isRequired() && attributeDecl.isFixed() && attributeDecl.getDefaultValue() != null && !htmlCode) {
+          template.addTextSegment(" " + attributeName + "=\"" + attributeDecl.getDefaultValue() + "\"");
+        }
+      }
+    }
+    return indirectRequiredAttrs;
+  }
+
+  protected static boolean addTail(char completionChar,
+                                   XmlElementDescriptor descriptor,
+                                   boolean isHtmlCode,
+                                   XmlTag tag,
+                                   Template template,
+                                   StringBuilder indirectRequiredAttrs) {
+
+    if (completionChar == '>' || (completionChar == '/' && indirectRequiredAttrs != null)) {
+      template.addTextSegment(">");
+      boolean toInsertCDataEnd = false;
+
+      if (descriptor instanceof XmlElementDescriptorWithCDataContent) {
+        final XmlElementDescriptorWithCDataContent cDataContainer = (XmlElementDescriptorWithCDataContent)descriptor;
+
+        if (cDataContainer.requiresCdataBracesInContext(tag)) {
+          template.addTextSegment("<![CDATA[\n");
+          toInsertCDataEnd = true;
+        }
+      }
+
+      if (indirectRequiredAttrs != null) template.addTextSegment(indirectRequiredAttrs.toString());
+      template.addEndVariable();
+
+      if (toInsertCDataEnd) template.addTextSegment("\n]]>");
+
+      if ((!(tag instanceof HtmlTag) || !HtmlUtil.isSingleHtmlTag(tag.getName())) && tag.getAttributes().length == 0) {
+        if (WebEditorOptions.getInstance().isAutomaticallyInsertClosingTag()) {
+          final String name = descriptor.getName(tag);
+          if (name != null) {
+            template.addTextSegment("</");
+            template.addTextSegment(name);
+            template.addTextSegment(">");
+          }
+        }
+      }
+    }
+    else if (completionChar == '/') {
+      template.addTextSegment("/>");
+    }
+    else if (completionChar == ' ' && template.getSegmentsCount() == 0) {
+      if (WebEditorOptions.getInstance().isAutomaticallyStartAttribute() &&
+          (descriptor.getAttributesDescriptors(tag).length > 0 || isTagFromHtml(tag) && !HtmlUtil.isTagWithoutAttributes(tag.getName()))) {
+        completeAttribute(template);
+        return true;
+      }
+    }
+    else if (completionChar == Lookup.AUTO_INSERT_SELECT_CHAR || completionChar == Lookup.NORMAL_SELECT_CHAR || completionChar == Lookup.REPLACE_SELECT_CHAR) {
+      if (WebEditorOptions.getInstance().isAutomaticallyInsertClosingTag() && isHtmlCode && HtmlUtil.isSingleHtmlTag(tag.getName())) {
+        template.addTextSegment(tag instanceof HtmlTag ? ">" : "/>");
+      }
+      else {
+        if (needAlLeastOneAttribute(tag) && WebEditorOptions.getInstance().isAutomaticallyStartAttribute() && tag.getAttributes().length == 0
+            && template.getSegmentsCount() == 0) {
+          completeAttribute(template);
+          return true;
+        }
+        else {
+          completeTagTail(template, descriptor, tag.getContainingFile(), tag, true);
+        }
+      }
+    }
+
+    return false;
+  }
+
+  private static void completeAttribute(Template template) {
+    template.addTextSegment(" ");
+    template.addVariable(new MacroCallNode(new CompleteMacro()), true);
+    template.addTextSegment("=\"");
+    template.addEndVariable();
+    template.addTextSegment("\"");
+  }
+
+  private static boolean needAlLeastOneAttribute(XmlTag tag) {
+    for (XmlTagRuleProvider ruleProvider : XmlTagRuleProvider.EP_NAME.getExtensions()) {
+      for (XmlTagRuleProvider.Rule rule : ruleProvider.getTagRule(tag)) {
+        if (rule.needAtLeastOneAttribute(tag)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  private static boolean addRequiredSubTags(Template template, XmlElementDescriptor descriptor, PsiFile file, XmlTag context) {
+
+    if (!WebEditorOptions.getInstance().isAutomaticallyInsertRequiredSubTags()) return false;
+    List<XmlElementDescriptor> requiredSubTags = GenerateXmlTagAction.getRequiredSubTags(descriptor);
+    if (!requiredSubTags.isEmpty()) {
+      template.addTextSegment(">");
+      template.setToReformat(true);
+    }
+    for (XmlElementDescriptor subTag : requiredSubTags) {
+      if (subTag == null) { // placeholder for smart completion
+        template.addTextSegment("<");
+        template.addVariable(new MacroCallNode(new CompleteSmartMacro()), true);
+        continue;
+      }
+      String qname = subTag.getName();
+      if (subTag instanceof XmlElementDescriptorImpl) {
+        String prefixByNamespace = context.getPrefixByNamespace(((XmlElementDescriptorImpl)subTag).getNamespace());
+        if (StringUtil.isNotEmpty(prefixByNamespace)) {
+          qname = prefixByNamespace + ":" + subTag.getName();
+        }
+      }
+      template.addTextSegment("<" + qname);
+      addRequiredAttributes(subTag, null, template, file);
+      completeTagTail(template, subTag, file, context, false);
+    }
+    if (!requiredSubTags.isEmpty()) {
+      addTagEnd(template, descriptor, context);
+    }
+    return !requiredSubTags.isEmpty();
+  }
+
+  private static void completeTagTail(Template template, XmlElementDescriptor descriptor, PsiFile file, XmlTag context, boolean firstLevel) {
+    boolean completeIt = !firstLevel || descriptor.getAttributesDescriptors(null).length == 0;
+    switch (descriptor.getContentType()) {
+      case XmlElementDescriptor.CONTENT_TYPE_UNKNOWN:
+        return;
+      case XmlElementDescriptor.CONTENT_TYPE_EMPTY:
+        if (completeIt) {
+          template.addTextSegment("/>");
+        }
+        break;
+      case XmlElementDescriptor.CONTENT_TYPE_MIXED:
+         if (completeIt) {
+           template.addTextSegment(">");
+           if (firstLevel) {
+             template.addEndVariable();
+           }
+           else {
+             template.addVariable(new MacroCallNode(new CompleteMacro()), true);
+           }
+           addTagEnd(template, descriptor, context);
+         }
+         break;
+       default:
+         if (!addRequiredSubTags(template, descriptor, file, context)) {
+           if (completeIt) {
+             template.addTextSegment(">");
+             template.addEndVariable();
+             addTagEnd(template, descriptor, context);
+           }
+         }
+         break;
+    }
+  }
+
+  private static void addTagEnd(Template template, XmlElementDescriptor descriptor, XmlTag context) {
+    template.addTextSegment("</" + descriptor.getName(context) + ">");
+  }
+
+  private static boolean isTagFromHtml(final XmlTag tag) {
+    final String ns = tag.getNamespace();
+    return XmlUtil.XHTML_URI.equals(ns) || XmlUtil.HTML_URI.equals(ns);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/XmlErrorMessages.java b/xml/impl/src/com/intellij/codeInsight/daemon/XmlErrorMessages.java
new file mode 100644
index 0000000..dab60a7
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/XmlErrorMessages.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon;
+
+import com.intellij.CommonBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.PropertyKey;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ResourceBundle;
+
+/**
+ * @author max
+ */
+public class XmlErrorMessages {
+  private static Reference<ResourceBundle> ourBundle;
+
+  @NonNls private static final String BUNDLE = "messages.XmlErrorMessages";
+
+  private XmlErrorMessages() {
+  }
+
+  public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+    return CommonBundle.message(getBundle(), key, params);
+  }
+
+  private static ResourceBundle getBundle() {
+    ResourceBundle bundle = null;
+    if (ourBundle != null) bundle = ourBundle.get();
+    if (bundle == null) {
+      bundle = ResourceBundle.getBundle(BUNDLE);
+      ourBundle = new SoftReference<ResourceBundle>(bundle);
+    }
+    return bundle;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java
new file mode 100644
index 0000000..e7d6565
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.InputValidator;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.XmlRecursiveElementVisitor;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaReferencesProvider;
+import com.intellij.psi.impl.source.xml.SchemaPrefixReference;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class AddSchemaPrefixIntention extends PsiElementBaseIntentionAction {
+  public static final String NAME = "Insert Namespace Prefix";
+
+  public AddSchemaPrefixIntention() {
+    setText(NAME);
+  }
+
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return NAME;
+  }
+
+  @Override
+  public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
+    final XmlAttribute xmlns = getXmlnsDeclaration(element);
+    if (xmlns == null) return;
+    final String namespace = xmlns.getValue();
+    final XmlTag tag = xmlns.getParent();
+
+    if (tag != null) {
+      final Set<String> ns = tag.getLocalNamespaceDeclarations().keySet();
+      final String nsPrefix = Messages.showInputDialog(project, "Namespace Prefix:", NAME, Messages.getInformationIcon(), "",
+                               new InputValidator() {
+                                 @Override
+                                 public boolean checkInput(String inputString) {
+                                   return !ns.contains(inputString);
+                                 }
+
+                                 @Override
+                                 public boolean canClose(String inputString) {
+                                   return checkInput(inputString);
+                                 }
+                               });
+      if (nsPrefix == null) return;
+      final List<XmlTag> tags = new ArrayList<XmlTag>();
+      final List<XmlAttributeValue> values = new ArrayList<XmlAttributeValue>();
+      new WriteCommandAction(project, NAME, tag.getContainingFile()) {
+        @Override
+        protected void run(Result result) throws Throwable {
+          tag.accept(new XmlRecursiveElementVisitor() {
+            @Override
+            public void visitXmlTag(XmlTag tag) {
+              if (namespace.equals(tag.getNamespace()) && tag.getNamespacePrefix().length() == 0) {
+                tags.add(tag);
+              }
+              super.visitXmlTag(tag);
+            }
+
+            @Override
+            public void visitXmlAttributeValue(XmlAttributeValue value) {
+              PsiReference ref = null;
+              boolean skip = false;
+              for (PsiReference reference : value.getReferences()) {
+                if (reference instanceof SchemaReferencesProvider.TypeOrElementOrAttributeReference) {
+                  ref = reference;
+                } else if (reference instanceof SchemaPrefixReference) {
+                  skip = true;
+                  break;
+                }
+              }
+              if (!skip && ref != null) {
+                final PsiElement xmlElement = ref.resolve();
+                if (xmlElement instanceof XmlElement) {
+                  final XmlTag tag = PsiTreeUtil.getParentOfType(xmlElement, XmlTag.class, false);
+                  if (tag != null) {
+                    if (namespace.equals(tag.getNamespace())) {
+                      if (ref.getRangeInElement().getLength() == value.getValue().length()) { //no ns prefix
+                        values.add(value);
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          });
+          for (XmlAttributeValue value : values) {
+            ((XmlAttribute)value.getParent()).setValue(nsPrefix + ":" + value.getValue());
+          }
+          for (XmlTag xmlTag : tags) {
+            xmlTag.setName(nsPrefix + ":" + xmlTag.getLocalName());
+          }
+          xmlns.setName("xmlns:" + nsPrefix);
+        }
+      }.execute();
+    }
+  }
+
+  @Override
+  public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
+    return getXmlnsDeclaration(element) != null;
+  }
+
+  @Nullable
+  private static XmlAttribute getXmlnsDeclaration(PsiElement element) {
+    final PsiElement parent = element.getParent();
+    if (parent instanceof XmlTag) {
+      XmlTag tag = (XmlTag)parent;
+      if (tag.getNamespacePrefix().length() == 0) {
+        while (tag != null) {
+          final XmlAttribute attr = tag.getAttribute("xmlns");
+          if (attr != null) return attr;
+          tag = tag.getParentTag();
+        }
+      }
+    } else if (parent instanceof XmlAttribute && ((XmlAttribute)parent).getName().equals("xmlns")) {
+      return (XmlAttribute)parent;
+    }
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java
new file mode 100644
index 0000000..34c4809
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.XmlRecursiveElementVisitor;
+import com.intellij.psi.impl.source.xml.SchemaPrefix;
+import com.intellij.psi.impl.source.xml.SchemaPrefixReference;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class ConvertSchemaPrefixToDefaultIntention extends PsiElementBaseIntentionAction {
+  public static final String NAME = "Set Namespace Prefix to Empty";
+
+  public ConvertSchemaPrefixToDefaultIntention() {
+    setText(NAME);
+  }
+
+  @Override
+  public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
+    final XmlAttribute xmlns = getXmlnsDeclaration(element);
+    if (xmlns == null) return;
+    SchemaPrefixReference prefixRef = null;
+    for (PsiReference ref : xmlns.getReferences()) {
+      if (ref instanceof SchemaPrefixReference) {
+        prefixRef = (SchemaPrefixReference)ref;
+        break;
+      }
+    }
+    if (prefixRef == null) return;
+
+    final SchemaPrefix prefix = prefixRef.resolve();
+    final String ns = prefixRef.getNamespacePrefix();
+    final ArrayList<XmlTag> tags = new ArrayList<XmlTag>();
+    final ArrayList<XmlAttribute> attrs = new ArrayList<XmlAttribute>();
+    xmlns.getParent().accept(new XmlRecursiveElementVisitor() {
+      @Override
+      public void visitXmlTag(XmlTag tag) {
+        if (ns.equals(tag.getNamespacePrefix())) {
+          tags.add(tag);
+        }
+        super.visitXmlTag(tag);
+      }
+
+      @Override
+      public void visitXmlAttributeValue(XmlAttributeValue value) {
+        if (value.getValue().startsWith(ns + ":")) {
+          for (PsiReference ref : value.getReferences()) {
+            if (ref instanceof SchemaPrefixReference && ref.isReferenceTo(prefix)) {
+              attrs.add((XmlAttribute)value.getParent());
+            }
+          }
+        }
+      }
+    });
+    new WriteCommandAction(project, "Convert namespace prefix to default", xmlns.getContainingFile()) {
+      @Override
+      protected void run(Result result) throws Throwable {
+        final int index = ns.length() + 1;
+        for (XmlTag tag : tags) {
+          final String s = tag.getName().substring(index);
+          if (s.length() > 0) {
+            tag.setName(s);
+          }
+        }
+        for (XmlAttribute attr : attrs) {
+          attr.setValue(attr.getValue().substring(index));
+        }
+        xmlns.setName("xmlns");
+      }
+    }.execute();
+  }
+
+  @Override
+  public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
+    return getXmlnsDeclaration(element) != null;
+  }
+
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return NAME;
+  }
+
+  @Nullable
+  private static XmlAttribute getXmlnsDeclaration(PsiElement element) {
+    final PsiElement parent = element.getParent();
+    if (parent == null) return null;
+    for (PsiReference ref : parent.getReferences()) {
+      if (ref instanceof SchemaPrefixReference) {
+        final PsiElement elem = ref.resolve();
+        if (elem != null) {
+          final PsiElement attr = elem.getParent();
+          if (attr instanceof XmlAttribute) {
+            final PsiElement tag = attr.getParent();
+            if (tag instanceof XmlTag && ((XmlTag)tag).getAttribute("xmlns") == null) {
+              return (XmlAttribute)attr;
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java
new file mode 100644
index 0000000..21c8b0d
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.application.options.XmlSettings;
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.completion.ExtendedTagInsertHandler;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass;
+import com.intellij.codeInsight.daemon.impl.VisibleHighlightingPassFactory;
+import com.intellij.codeInsight.hint.HintManager;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.HintAction;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.PopupChooserBuilder;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiAnchor;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.cache.impl.id.IdTableBuilding;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class CreateNSDeclarationIntentionFix implements HintAction, LocalQuickFix {
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.CreateNSDeclarationIntentionFix");
+
+  private final String myNamespacePrefix;
+  private final PsiAnchor myElement;
+  private final PsiAnchor myToken;
+
+  @NotNull
+  private XmlFile getFile() {
+    return (XmlFile)myElement.getFile();
+  }
+
+  @Nullable
+  public static CreateNSDeclarationIntentionFix createFix(@NotNull final PsiElement element, @NotNull final String namespacePrefix) {
+    PsiFile file = element.getContainingFile();
+    return file instanceof XmlFile ? new CreateNSDeclarationIntentionFix(element, namespacePrefix) : null;
+  }
+
+  protected CreateNSDeclarationIntentionFix(@NotNull final PsiElement element,
+                                            @NotNull final String namespacePrefix) {
+    this(element, namespacePrefix, null);
+  }
+
+  public CreateNSDeclarationIntentionFix(@NotNull final PsiElement element,
+                                         final String namespacePrefix,
+                                         @Nullable final XmlToken token) {
+    myNamespacePrefix = namespacePrefix;
+    myElement = PsiAnchor.create(element);
+    myToken = token == null ? null : PsiAnchor.create(token);
+  }
+
+  @Override
+  @NotNull
+  public String getText() {
+    final String alias = StringUtil.capitalize(getXmlExtension().getNamespaceAlias(getFile()));
+    return XmlErrorMessages.message("create.namespace.declaration.quickfix", alias);
+  }
+
+  private XmlExtension getXmlExtension() {
+    return XmlExtension.getExtension(getFile());
+  }
+
+  @Override
+  @NotNull
+  public String getName() {
+    return getFamilyName();
+  }
+
+  @Override
+  @NotNull
+  public String getFamilyName() {
+    return getText();
+  }
+
+  @Override
+  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+    final PsiFile containingFile = descriptor.getPsiElement().getContainingFile();
+    Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
+    final PsiFile file = editor != null ? PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()):null;
+    if (file == null || !Comparing.equal(file.getVirtualFile(), containingFile.getVirtualFile())) return;
+
+    try { invoke(project, editor, containingFile); } catch (IncorrectOperationException ex) {
+      LOG.error(ex);
+    }
+  }
+
+  @Override
+  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+    PsiElement element = myElement.retrieve();
+    return element != null && element.isValid();
+  }
+
+  @Override
+  public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
+    if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
+
+    final PsiElement element = myElement.retrieve();
+    if (element == null) return;
+    final Set<String> set = getXmlExtension().guessUnboundNamespaces(element, getFile());
+    final String[] namespaces = ArrayUtil.toStringArray(set);
+    Arrays.sort(namespaces);
+
+    runActionOverSeveralAttributeValuesAfterLettingUserSelectTheNeededOne(
+      namespaces,
+      project,
+      new StringToAttributeProcessor() {
+        @Override
+        public void doSomethingWithGivenStringToProduceXmlAttributeNowPlease(@NotNull final String namespace) throws IncorrectOperationException {
+          String prefix = myNamespacePrefix;
+          if (StringUtil.isEmpty(prefix)) {
+            final XmlExtension extension = getXmlExtension();
+            final XmlFile xmlFile = extension.getContainingFile(element);
+            prefix = ExtendedTagInsertHandler.getPrefixByNamespace(xmlFile, namespace);
+            if (StringUtil.isNotEmpty(prefix)) {
+              // namespace already declared
+              ExtendedTagInsertHandler.qualifyWithPrefix(prefix, element);
+              return;
+            }
+            else {
+              prefix = ExtendedTagInsertHandler.suggestPrefix(xmlFile, namespace);
+              if (!StringUtil.isEmpty(prefix)) {
+                ExtendedTagInsertHandler.qualifyWithPrefix(prefix, element);
+                PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
+              }
+            }
+          }
+          final int offset = editor.getCaretModel().getOffset();
+          final RangeMarker marker = editor.getDocument().createRangeMarker(offset, offset);
+          final XmlExtension extension = XmlExtension.getExtension(file);
+          extension.insertNamespaceDeclaration((XmlFile)file, editor, Collections.singleton(namespace), prefix, new XmlExtension.Runner<String, IncorrectOperationException>() {
+            @Override
+            public void run(final String param) throws IncorrectOperationException {
+              if (!namespace.isEmpty()) {
+                editor.getCaretModel().moveToOffset(marker.getStartOffset());
+              }
+            }
+          });
+        }
+      }, getTitle(),
+      this,
+      editor);
+  }
+
+  private String getTitle() {
+    return XmlErrorMessages.message("select.namespace.title", StringUtil.capitalize(getXmlExtension().getNamespaceAlias(getFile())));
+  }
+
+  @Override
+  public boolean startInWriteAction() {
+    return true;
+  }
+
+  @Override
+  public boolean showHint(final Editor editor) {
+    if (myToken == null) return false;
+    XmlToken token = (XmlToken)myToken.retrieve();
+    if (token == null) return false;
+    if (!XmlSettings.getInstance().SHOW_XML_ADD_IMPORT_HINTS || myNamespacePrefix.isEmpty()) {
+      return false;
+    }
+    final PsiElement element = myElement.retrieve();
+    if (element == null) return false;
+    final Set<String> namespaces = getXmlExtension().guessUnboundNamespaces(element, getFile());
+    if (!namespaces.isEmpty()) {
+      final String message = ShowAutoImportPass.getMessage(namespaces.size() > 1, namespaces.iterator().next());
+      final String title = getTitle();
+      final ImportNSAction action = new ImportNSAction(namespaces, getFile(), element, editor, title);
+      if (element instanceof XmlTag) {
+        if (VisibleHighlightingPassFactory.calculateVisibleRange(editor).contains(token.getTextRange())) {
+          HintManager.getInstance().showQuestionHint(editor, message,
+                                                     token.getTextOffset(),
+                                                     token.getTextOffset() + myNamespacePrefix.length(), action);
+          return true;        
+        }
+      } else {
+        HintManager.getInstance().showQuestionHint(editor, message,
+                                                   element.getTextOffset(),
+                                                   element.getTextRange().getEndOffset(), action);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private static boolean checkIfGivenXmlHasTheseWords(final String name, final XmlFile tldFileByUri) {
+    if (name == null || name.isEmpty()) return true;
+    final List<String> list = StringUtil.getWordsIn(name);
+    final String[] words = ArrayUtil.toStringArray(list);
+    final boolean[] wordsFound = new boolean[words.length];
+    final int[] wordsFoundCount = new int[1];
+
+    IdTableBuilding.ScanWordProcessor wordProcessor = new IdTableBuilding.ScanWordProcessor() {
+      @Override
+      public void run(final CharSequence chars, @Nullable char[] charsArray, int start, int end) {
+        if (wordsFoundCount[0] == words.length) return;
+        final int foundWordLen = end - start;
+
+        Next:
+        for (int i = 0; i < words.length; ++i) {
+          final String localName = words[i];
+          if (wordsFound[i] || localName.length() != foundWordLen) continue;
+
+          for (int j = 0; j < localName.length(); ++j) {
+            if (chars.charAt(start + j) != localName.charAt(j)) continue Next;
+          }
+
+          wordsFound[i] = true;
+          wordsFoundCount[0]++;
+          break;
+        }
+      }
+    };
+
+    final CharSequence contents = tldFileByUri.getViewProvider().getContents();
+
+    IdTableBuilding.scanWords(wordProcessor, contents, 0, contents.length());
+
+    return wordsFoundCount[0] == words.length;
+  }
+
+  public interface StringToAttributeProcessor {
+    void doSomethingWithGivenStringToProduceXmlAttributeNowPlease(@NonNls @NotNull String attrName) throws IncorrectOperationException;
+  }
+
+
+  public static void runActionOverSeveralAttributeValuesAfterLettingUserSelectTheNeededOne(@NotNull final String[] namespacesToChooseFrom,
+                                                                                           final Project project, final StringToAttributeProcessor onSelection,
+                                                                                           String title,
+                                                                                           final IntentionAction requestor,
+                                                                                           final Editor editor) throws IncorrectOperationException {
+    
+    if (namespacesToChooseFrom.length > 1 && !ApplicationManager.getApplication().isUnitTestMode()) {
+      final JList list = new JBList(namespacesToChooseFrom);
+      list.setCellRenderer(XmlNSRenderer.INSTANCE);
+      Runnable runnable = new Runnable() {
+        @Override
+        public void run() {
+          final int index = list.getSelectedIndex();
+          if (index < 0) return;
+          PsiDocumentManager.getInstance(project).commitAllDocuments();
+
+          CommandProcessor.getInstance().executeCommand(
+            project,
+            new Runnable() {
+              @Override
+              public void run() {
+                ApplicationManager.getApplication().runWriteAction(
+                  new Runnable() {
+                    @Override
+                    public void run() {
+                      try {
+                        onSelection.doSomethingWithGivenStringToProduceXmlAttributeNowPlease(namespacesToChooseFrom[index]);
+                      } catch (IncorrectOperationException ex) {
+                        throw new RuntimeException(ex);
+                      }
+                    }
+                  }
+                );
+              }
+            },
+            requestor.getText(),
+            requestor.getFamilyName()
+          );
+        }
+      };
+
+      new PopupChooserBuilder(list).
+        setTitle(title).
+        setItemChoosenCallback(runnable).
+        createPopup().
+        showInBestPositionFor(editor);
+    } else {
+      onSelection.doSomethingWithGivenStringToProduceXmlAttributeNowPlease(namespacesToChooseFrom.length == 0 ? "" : namespacesToChooseFrom[0]);
+    }
+  }
+
+  public static void processExternalUris(final MetaHandler metaHandler,
+                                         final PsiFile file,
+                                         final ExternalUriProcessor processor,
+                                         final boolean showProgress) {
+    if (!showProgress || ApplicationManager.getApplication().isUnitTestMode()) {
+      processExternalUrisImpl(metaHandler, file, processor);
+    }
+    else {
+      ProgressManager.getInstance().runProcessWithProgressSynchronously(
+        new Runnable() {
+          @Override
+          public void run() {
+            processExternalUrisImpl(metaHandler, file, processor);
+          }
+        },
+        XmlErrorMessages.message("finding.acceptable.uri"),
+        false,
+        file.getProject()
+      );
+    }
+  }
+
+  public interface MetaHandler {
+    boolean isAcceptableMetaData(PsiMetaData metadata, final String url);
+    String searchFor();
+  }
+
+  public static class TagMetaHandler implements MetaHandler {
+    private final String myName;
+    
+
+    public TagMetaHandler(final String name) {
+      myName = name;
+    }
+
+    @Override
+    public boolean isAcceptableMetaData(final PsiMetaData metaData, final String url) {
+      if (metaData instanceof XmlNSDescriptorImpl) {
+        final XmlNSDescriptorImpl nsDescriptor = (XmlNSDescriptorImpl)metaData;
+
+        final XmlElementDescriptor descriptor = nsDescriptor.getElementDescriptor(searchFor(), url);
+        return descriptor != null && !(descriptor instanceof AnyXmlElementDescriptor);
+      }
+      return false;
+    }
+
+    @Override
+    public String searchFor() {
+      return myName;
+    }
+  }
+
+  private static void processExternalUrisImpl(final MetaHandler metaHandler,
+                                              final PsiFile file,
+                                              final ExternalUriProcessor processor) {
+    final ProgressIndicator pi = ProgressManager.getInstance().getProgressIndicator();
+
+    final String searchFor = metaHandler.searchFor();
+
+    if (pi != null) pi.setText(XmlErrorMessages.message("looking.in.schemas"));
+    final ExternalResourceManager instanceEx = ExternalResourceManager.getInstance();
+    final String[] availableUrls = instanceEx.getResourceUrls(null, true);
+    int i = 0;
+
+    for (String url : availableUrls) {
+      if (pi != null) {
+        pi.setFraction((double)i / availableUrls.length);
+        pi.setText2(url);
+        ++i;
+      }
+      final XmlFile xmlFile = XmlUtil.findNamespace(file, url);
+
+      if (xmlFile != null) {
+        final boolean wordFound = checkIfGivenXmlHasTheseWords(searchFor, xmlFile);
+        if (!wordFound) continue;
+        final XmlDocument document = xmlFile.getDocument();
+        assert document != null;
+        final PsiMetaData metaData = document.getMetaData();
+
+        if (metaHandler.isAcceptableMetaData(metaData, url)) {
+          final XmlNSDescriptorImpl descriptor = metaData instanceof XmlNSDescriptorImpl ? (XmlNSDescriptorImpl)metaData:null;
+          final String defaultNamespace = descriptor != null ? descriptor.getDefaultNamespace():url;
+
+          // Skip rare stuff
+          if (!XmlUtil.XML_SCHEMA_URI2.equals(defaultNamespace) && !XmlUtil.XML_SCHEMA_URI3.equals(defaultNamespace)) {
+            processor.process(defaultNamespace, url);
+          }
+        }
+      }
+    }
+  }
+
+  public interface ExternalUriProcessor {
+    void process(@NotNull String uri,@Nullable final String url);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/HtmlUnknownTargetInspection.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/HtmlUnknownTargetInspection.java
new file mode 100644
index 0000000..c682036
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/HtmlUnknownTargetInspection.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class HtmlUnknownTargetInspection extends XmlPathReferenceInspection {
+
+  @NotNull
+  @Override
+  public String getShortName() {
+    return "HtmlUnknownTarget";
+  }
+
+  @Override
+  protected boolean isForHtml() {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportNSAction.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportNSAction.java
new file mode 100644
index 0000000..cbf1771
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportNSAction.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.codeInsight.hint.QuestionAction;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.PopupChooserBuilder;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlExtension;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author Dmitry Avdeev
+*/
+public class ImportNSAction implements QuestionAction {
+  private final Set<String> myNamespaces;
+  private final XmlFile myFile;
+  private final PsiElement myElement;
+  private final Editor myEditor;
+  private final String myTitle;
+
+  public ImportNSAction(final Set<String> namespaces, XmlFile file, @NotNull PsiElement element, Editor editor, final String title) {
+
+    myNamespaces = namespaces;
+    myFile = file;
+    myElement = element;
+    myEditor = editor;
+    myTitle = title;
+  }
+
+  public boolean execute() {
+    final Object[] objects = myNamespaces.toArray();
+    Arrays.sort(objects);
+    final JList list = new JBList(objects);
+    list.setCellRenderer(XmlNSRenderer.INSTANCE);
+    list.setSelectedIndex(0);
+    final int offset = myElement.getTextOffset();
+    final RangeMarker marker = myEditor.getDocument().createRangeMarker(offset, offset);
+    final Runnable runnable = new Runnable() {
+
+      public void run() {
+        final String namespace = (String)list.getSelectedValue();
+        if (namespace != null) {
+            final Project project = myFile.getProject();
+            new WriteCommandAction.Simple(project, myFile) {
+
+              protected void run() throws Throwable {
+                final XmlExtension extension = XmlExtension.getExtension(myFile);
+                final String prefix = extension.getNamespacePrefix(myElement);
+                extension.insertNamespaceDeclaration(myFile,
+                                                     myEditor,
+                                                     Collections.singleton(namespace),
+                                                     prefix,
+                                                     new XmlExtension.Runner<String, IncorrectOperationException>() {
+                    public void run(final String s) throws IncorrectOperationException {
+                      PsiDocumentManager.getInstance(myFile.getProject()).doPostponedOperationsAndUnblockDocument(myEditor.getDocument());
+                      PsiElement element = myFile.findElementAt(marker.getStartOffset());
+                      if (element != null) {
+                        extension.qualifyWithPrefix(s, element, myEditor.getDocument());
+                      }
+                    }
+                  }
+                );
+              }
+            }.execute();
+        }
+      }
+    };
+    if (list.getModel().getSize() == 1) {
+      runnable.run();
+    } else {
+      new PopupChooserBuilder(list).
+        setTitle(myTitle).
+        setItemChoosenCallback(runnable).
+        createPopup().
+        showInBestPositionFor(myEditor);
+    }
+
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/InsertRequiredAttributeFix.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/InsertRequiredAttributeFix.java
new file mode 100644
index 0000000..ff3b754
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/InsertRequiredAttributeFix.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.intention.HighPriorityAction;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.codeInsight.template.*;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlExtension;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: anna
+ * Date: 18-Nov-2005
+ */
+public class InsertRequiredAttributeFix implements IntentionAction, LocalQuickFix, HighPriorityAction {
+  private final XmlTag myTag;
+  private final String myAttrName;
+  private final String[] myValues;
+  @NonNls
+  private static final String NAME_TEMPLATE_VARIABLE = "name";
+
+  public InsertRequiredAttributeFix(final XmlTag tag, final String attrName,final String[] values) {
+    myTag = tag;
+    myAttrName = attrName;
+    myValues = values;
+  }
+
+  @NotNull
+  public String getText() {
+    return XmlErrorMessages.message("insert.required.attribute.quickfix.text", myAttrName);
+  }
+
+  @NotNull
+  public String getName() {
+    return getText();
+  }
+
+  @NotNull
+  public String getFamilyName() {
+    return XmlErrorMessages.message("insert.required.attribute.quickfix.family");
+  }
+
+  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+    invoke(project, null, myTag.getContainingFile());
+  }
+
+  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+    return myTag.isValid();
+  }
+
+  public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) {
+    if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
+    ASTNode treeElement = SourceTreeToPsiMap.psiElementToTree(myTag);
+
+    final XmlElementDescriptor descriptor = myTag.getDescriptor();
+    if (descriptor == null) {
+      return;
+    }
+    final XmlAttributeDescriptor attrDescriptor = descriptor.getAttributeDescriptor(myAttrName, myTag);
+    boolean indirectSyntax = XmlExtension.getExtension(myTag.getContainingFile()).isIndirectSyntax(attrDescriptor);
+
+    PsiElement anchor = SourceTreeToPsiMap.treeElementToPsi(
+      XmlChildRole.EMPTY_TAG_END_FINDER.findChild(treeElement)
+    );
+
+    final boolean anchorIsEmptyTag = anchor != null;
+
+    if (anchor == null) {
+      anchor = SourceTreeToPsiMap.treeElementToPsi(
+        XmlChildRole.START_TAG_END_FINDER.findChild(treeElement)
+      );
+    }
+
+    if (anchor == null) return;
+
+    final Template template = TemplateManager.getInstance(project).createTemplate("", "");
+    if (indirectSyntax) {
+      if (anchorIsEmptyTag) template.addTextSegment(">");
+      template.addTextSegment("<jsp:attribute name=\"" + myAttrName + "\">");
+    } else {
+      template.addTextSegment(" " + myAttrName + "=\"");
+    }
+
+    Expression expression = new Expression() {
+      TextResult result = new TextResult("");
+
+      public Result calculateResult(ExpressionContext context) {
+        return result;
+      }
+
+      public Result calculateQuickResult(ExpressionContext context) {
+        return null;
+      }
+
+      public LookupElement[] calculateLookupItems(ExpressionContext context) {
+        final LookupElement[] items = new LookupElement[myValues == null ? 0 : myValues.length];
+
+        if (myValues != null) {
+          for (int i = 0; i < items.length; i++) {
+            items[i] = LookupElementBuilder.create(myValues[i]);
+          }
+        }
+        return items;
+      }
+    };
+    template.addVariable(NAME_TEMPLATE_VARIABLE, expression, expression, true);
+    if (indirectSyntax) {
+      template.addTextSegment("</jsp:attribute>");
+      template.addEndVariable();
+      if (anchorIsEmptyTag) template.addTextSegment("</" + myTag.getName() + ">");
+    } else {
+      template.addTextSegment("\"");
+    }
+
+    final PsiElement anchor1 = anchor;
+
+    final boolean indirectSyntax1 = indirectSyntax;
+    final Runnable runnable = new Runnable() {
+      public void run() {
+        ApplicationManager.getApplication().runWriteAction(
+          new Runnable() {
+            public void run() {
+              int textOffset = anchor1.getTextOffset();
+              if (!anchorIsEmptyTag && indirectSyntax1) ++textOffset;
+              editor.getCaretModel().moveToOffset(textOffset);
+              if (anchorIsEmptyTag && indirectSyntax1) {
+                editor.getDocument().deleteString(textOffset,textOffset + 2);
+              }
+              TemplateManager.getInstance(project).startTemplate(editor, template);
+            }
+          }
+        );
+      }
+    };
+
+    if (!ApplicationManager.getApplication().isUnitTestMode()) {
+      Runnable commandRunnable = new Runnable() {
+        public void run() {
+          CommandProcessor.getInstance().executeCommand(
+            project,
+            runnable,
+            getText(),
+            getFamilyName()
+          );
+        }
+      };
+
+      ApplicationManager.getApplication().invokeLater(commandRunnable);
+    }
+    else {
+      runnable.run();
+    }
+  }
+
+  public boolean startInWriteAction() {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/RemoveAttributeIntentionFix.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/RemoveAttributeIntentionFix.java
new file mode 100644
index 0000000..4814d65
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/RemoveAttributeIntentionFix.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlAttribute;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class RemoveAttributeIntentionFix extends LocalQuickFixAndIntentionActionOnPsiElement {
+  private final String myLocalName;
+
+  public RemoveAttributeIntentionFix(final String localName, final @NotNull XmlAttribute attribute) {
+    super(attribute);
+    myLocalName = localName;
+  }
+
+  @NotNull
+  public String getText() {
+    return XmlErrorMessages.message("remove.attribute.quickfix.text", myLocalName);
+  }
+
+  @NotNull
+  public String getFamilyName() {
+    return XmlErrorMessages.message("remove.attribute.quickfix.family");
+  }
+
+  @Override
+  public void invoke(@NotNull Project project,
+                     @NotNull PsiFile file,
+                     @Nullable("is null when called from inspection") Editor editor,
+                     @NotNull PsiElement startElement,
+                     @NotNull PsiElement endElement) {
+    if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
+    PsiElement next = findNextAttribute((XmlAttribute)startElement);
+    startElement.delete();
+
+    if (next != null && editor != null) {
+      editor.getCaretModel().moveToOffset(next.getTextRange().getStartOffset());
+    }
+  }
+
+  @Nullable
+  private static PsiElement findNextAttribute(final XmlAttribute attribute) {
+    PsiElement nextSibling = attribute.getNextSibling();
+    while (nextSibling != null) {
+      if (nextSibling instanceof XmlAttribute) return nextSibling;
+      nextSibling =  nextSibling.getNextSibling();
+    }
+    return null;
+  }
+
+  public boolean startInWriteAction() {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlErrorQuickFixProvider.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlErrorQuickFixProvider.java
new file mode 100644
index 0000000..9372cb3
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlErrorQuickFixProvider.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.editor.Editor;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+public class XmlErrorQuickFixProvider implements ErrorQuickFixProvider {
+  @NonNls private static final String AMP_ENTITY = "&amp;";
+
+  public void registerErrorQuickFix(final PsiErrorElement element, final HighlightInfo highlightInfo) {
+    if (PsiTreeUtil.getParentOfType(element, XmlTag.class) != null) {
+      registerXmlErrorQuickFix(element,highlightInfo);
+    }
+  }
+
+  private static void registerXmlErrorQuickFix(final PsiErrorElement element, final HighlightInfo highlightInfo) {
+    final String text = element.getErrorDescription();
+    if (text != null && text.startsWith(XmlErrorMessages.message("unescaped.ampersand"))) {
+      QuickFixAction.registerQuickFixAction(highlightInfo, new IntentionAction() {
+        @NotNull
+        public String getText() {
+          return XmlErrorMessages.message("escape.ampersand.quickfix");
+        }
+
+        @NotNull
+        public String getFamilyName() {
+          return getText();
+        }
+
+        public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+          return true;
+        }
+
+        public void invoke(@NotNull Project project, Editor editor, PsiFile file) {
+          if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
+          final int textOffset = element.getTextOffset();
+          editor.getDocument().replaceString(textOffset,textOffset + 1,AMP_ENTITY);
+        }
+
+        public boolean startInWriteAction() {
+          return true;
+        }
+      });
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitor.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitor.java
new file mode 100644
index 0000000..96b111a
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitor.java
@@ -0,0 +1,777 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.BundleBase;
+import com.intellij.codeInsight.daemon.*;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
+import com.intellij.codeInsight.daemon.impl.HighlightVisitor;
+import com.intellij.codeInsight.daemon.impl.SeverityRegistrar;
+import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
+import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixActionRegistrarImpl;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
+import com.intellij.codeInspection.InspectionProfile;
+import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection;
+import com.intellij.codeInspection.htmlInspections.XmlEntitiesInspection;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.dtd.DTDLanguage;
+import com.intellij.lang.injection.InjectedLanguageManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.UserDataCache;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.*;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceOwner;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.templateLanguages.OuterLanguageElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.util.AnchorReference;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlTagUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * @author Mike
+ */
+public class XmlHighlightVisitor extends XmlElementVisitor implements HighlightVisitor, Validator.ValidationHost {
+  private static final Logger LOG = Logger.getInstance("com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor");
+  private static final UserDataCache<Boolean, PsiElement, Object> DO_NOT_VALIDATE =
+    new UserDataCache<Boolean, PsiElement, Object>("do not validate") {
+    @Override
+    protected Boolean compute(PsiElement parent, Object p) {
+      OuterLanguageElement element = PsiTreeUtil.getChildOfType(parent, OuterLanguageElement.class);
+
+      if (element == null) {
+        // JspOuterLanguageElement is located under XmlText
+        for (PsiElement child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+          if (child instanceof XmlText) {
+            element = PsiTreeUtil.getChildOfType(child, OuterLanguageElement.class);
+            if (element != null) {
+              break;
+            }
+          }
+        }
+      }
+      if (element == null) return false;
+      PsiFile containingFile = parent.getContainingFile();
+      return containingFile.getViewProvider().getBaseLanguage() != containingFile.getLanguage();
+    }
+  };
+  private static boolean ourDoJaxpTesting;
+
+  private static final TextAttributes NONEMPTY_TEXT_ATTRIBUTES = new TextAttributes() {
+    public boolean isEmpty() {
+      return false;
+    }
+  };
+  private HighlightInfoHolder myHolder;
+
+  public XmlHighlightVisitor() {
+  }
+
+  private void addElementsForTag(XmlTag tag,
+                                 String localizedMessage,
+                                 HighlightInfoType type,
+                                 IntentionAction quickFixAction) {
+    addElementsForTagWithManyQuickFixes(tag, localizedMessage, type, quickFixAction);
+  }
+
+  private void addElementsForTagWithManyQuickFixes(XmlTag tag,
+                                                   String localizedMessage,
+                                                   HighlightInfoType type, IntentionAction... quickFixActions) {
+    bindMessageToTag(tag, type, -1, localizedMessage, quickFixActions);
+  }
+
+  @Override public void visitXmlToken(XmlToken token) {
+    IElementType tokenType = token.getTokenType();
+    if (tokenType == XmlTokenType.XML_NAME || tokenType == XmlTokenType.XML_TAG_NAME) {
+      PsiElement element = token.getPrevSibling();
+      while(element instanceof PsiWhiteSpace) element = element.getPrevSibling();
+
+      if (element instanceof XmlToken) {
+        if (((XmlToken)element).getTokenType() == XmlTokenType.XML_START_TAG_START) {
+          PsiElement parent = element.getParent();
+
+          if (parent instanceof XmlTag && !(token.getNextSibling() instanceof OuterLanguageElement)) {
+            checkTag((XmlTag)parent);
+          }
+        }
+      } else {
+        PsiElement parent = token.getParent();
+
+        if (parent instanceof XmlAttribute && !(token.getNextSibling() instanceof OuterLanguageElement)) {
+          checkAttribute((XmlAttribute) parent);
+        }
+      }
+    } else if (tokenType == XmlTokenType.XML_DATA_CHARACTERS && token.getParent() instanceof XmlText) {
+      if (token.textContains(']') && token.textContains('>')) {
+
+        String s = token.getText();
+        String marker = "]]>";
+        int i = s.indexOf(marker);
+
+        if (i != -1 ) {                              // TODO: fix
+          XmlTag tag = PsiTreeUtil.getParentOfType(token, XmlTag.class);
+          if (tag != null && XmlExtension.getExtensionByElement(tag).shouldBeHighlightedAsTag(tag) && !skipValidation(tag)) {
+            TextRange textRange = token.getTextRange();
+            int start = textRange.getStartOffset() + i;
+            HighlightInfo info = HighlightInfo.createHighlightInfo(
+              tag instanceof HtmlTag ? HighlightInfoType.WARNING : HighlightInfoType.ERROR,
+              start, start + marker.length(),
+              XmlErrorMessages.message("cdata.end.should.not.appear.in.content.unless.to.mark.end.of.cdata.section")
+            );
+            addToResults(info);
+          }
+        }
+      }
+    }
+  }
+
+  private void checkTag(XmlTag tag) {
+    if (ourDoJaxpTesting) return;
+
+    if (!myHolder.hasErrorResults()) {
+      checkTagByDescriptor(tag);
+    }
+
+    if (!myHolder.hasErrorResults()) {
+      if (!skipValidation(tag)) {
+        final XmlElementDescriptor descriptor = tag.getDescriptor();
+
+        if (tag instanceof HtmlTag &&
+            ( descriptor instanceof AnyXmlElementDescriptor ||
+              descriptor == null
+            )
+           ) {
+          return;
+        }
+
+        checkReferences(tag);
+      }
+    }
+  }
+
+  private void bindMessageToTag(final XmlTag tag, final HighlightInfoType warning, final int messageLength, final String localizedMessage, IntentionAction... quickFixActions) {
+    XmlToken childByRole = XmlTagUtil.getStartTagNameElement(tag);
+
+    bindMessageToAstNode(childByRole, warning, 0, messageLength, localizedMessage, quickFixActions);
+    childByRole = XmlTagUtil.getEndTagNameElement(tag);
+    bindMessageToAstNode(childByRole, warning, 0, messageLength, localizedMessage, quickFixActions);
+  }
+
+
+  @Override
+  public void visitXmlProcessingInstruction(XmlProcessingInstruction processingInstruction) {
+    super .visitXmlProcessingInstruction(processingInstruction);
+    PsiElement parent = processingInstruction.getParent();
+
+    if (parent instanceof XmlProlog && processingInstruction.getText().startsWith("<?xml")) {
+      for(PsiElement e = PsiTreeUtil.prevLeaf(processingInstruction); e != null; e = PsiTreeUtil.prevLeaf(e)) {
+        if (e instanceof PsiWhiteSpace && PsiTreeUtil.prevLeaf(e) != null ||
+            e instanceof OuterLanguageElement) {
+          continue;
+        }
+        PsiElement eParent = e.getParent();
+        if (eParent instanceof PsiComment) e = eParent;
+        if (eParent instanceof XmlProcessingInstruction) break;
+  
+        addToResults(HighlightInfo.createHighlightInfo(
+          HighlightInfoType.ERROR,
+          e,
+          XmlErrorMessages.message("xml.declaration.should.precede.all.document.content")
+        ));
+      }
+    }
+  }
+
+  private void bindMessageToAstNode(final PsiElement childByRole,
+                                    final HighlightInfoType warning,
+                                    final int offset,
+                                    int length,
+                                    final String localizedMessage, IntentionAction... quickFixActions) {
+    if(childByRole != null) {
+      final TextRange textRange = childByRole.getTextRange();
+      if (length == -1) length = textRange.getLength();
+      final int startOffset = textRange.getStartOffset() + offset;
+
+      HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(
+        warning,
+        childByRole, startOffset, startOffset + length,
+        localizedMessage, HighlightInfo.htmlEscapeToolTip(localizedMessage)
+      );
+
+      if (highlightInfo == null) {
+        highlightInfo = HighlightInfo.createHighlightInfo(
+          warning,
+          new TextRange(startOffset, startOffset + length),
+          localizedMessage,
+          localizedMessage, NONEMPTY_TEXT_ATTRIBUTES
+        );
+      }
+
+      for (final IntentionAction quickFixAction : quickFixActions) {
+        if (quickFixAction == null) continue;
+        QuickFixAction.registerQuickFixAction(highlightInfo, textRange, quickFixAction);
+      }
+      addToResults(highlightInfo);
+    }
+  }
+
+  private void checkTagByDescriptor(final XmlTag tag) {
+    String name = tag.getName();
+
+    XmlElementDescriptor elementDescriptor;
+
+    final PsiElement parent = tag.getParent();
+    if (parent instanceof XmlTag) {
+      XmlTag parentTag = (XmlTag)parent;
+
+      elementDescriptor = XmlUtil.getDescriptorFromContext(tag);
+
+      final XmlElementDescriptor parentDescriptor = parentTag.getDescriptor();
+
+      if (parentDescriptor != null && elementDescriptor == null && shouldBeValidated(tag)) {
+        if (tag instanceof HtmlTag) {
+          //XmlEntitiesInspection inspection = getInspectionProfile(tag, HtmlStyleLocalInspection.SHORT_NAME);
+          //if (inspection != null /*&& isAdditionallyDeclared(inspection.getAdditionalEntries(XmlEntitiesInspection.UNKNOWN_TAG), name)*/) {
+            return;
+          //}
+        }
+
+        addElementsForTag(
+          tag,
+          XmlErrorMessages.message("element.is.not.allowed.here", name),
+          getTagProblemInfoType(tag),
+          null
+        );
+        return;
+      }
+
+      if (elementDescriptor instanceof AnyXmlElementDescriptor ||
+          elementDescriptor == null
+         ) {
+        elementDescriptor = tag.getDescriptor();
+      }
+
+      if (elementDescriptor == null) return;
+    }
+    else {
+      //root tag
+      elementDescriptor = tag.getDescriptor();
+
+     if (elementDescriptor == null) {
+       addElementsForTag(tag, XmlErrorMessages.message("element.must.be.declared", name), HighlightInfoType.WRONG_REF, null);
+       return;
+      }
+    }
+
+    checkRequiredAttributes(tag, name, elementDescriptor);
+
+    if (elementDescriptor instanceof Validator) {
+      //noinspection unchecked
+      ((Validator<XmlTag>)elementDescriptor).validate(tag,this);
+    }
+  }
+
+  private void checkRequiredAttributes(XmlTag tag, String name, XmlElementDescriptor elementDescriptor) {
+    XmlAttributeDescriptor[] attributeDescriptors = elementDescriptor.getAttributesDescriptors(tag);
+    Set<String> requiredAttributes = null;
+
+    for (XmlAttributeDescriptor attribute : attributeDescriptors) {
+      if (attribute != null && attribute.isRequired()) {
+        if (requiredAttributes == null) {
+          requiredAttributes = new HashSet<String>();
+        }
+        requiredAttributes.add(attribute.getName(tag));
+      }
+    }
+
+    if (requiredAttributes != null) {
+      for (final String attrName : requiredAttributes) {
+        if (tag.getAttributeValue(attrName) == null &&
+            !XmlExtension.getExtension(tag.getContainingFile()).isRequiredAttributeImplicitlyPresent(tag, attrName)) {
+
+          final InsertRequiredAttributeFix insertRequiredAttributeIntention = new InsertRequiredAttributeFix(
+              tag, attrName, null);
+          final String localizedMessage = XmlErrorMessages.message("element.doesnt.have.required.attribute", name, attrName);
+          final InspectionProfile profile = InspectionProjectProfileManager.getInstance(tag.getProject()).getInspectionProfile();
+          final LocalInspectionToolWrapper toolWrapper =
+            (LocalInspectionToolWrapper)profile.getInspectionTool(RequiredAttributesInspection.SHORT_NAME, tag);
+          if (toolWrapper != null) {
+            RequiredAttributesInspection inspection = (RequiredAttributesInspection)toolWrapper.getTool();
+            reportOneTagProblem(
+              tag,
+              attrName,
+              localizedMessage,
+              insertRequiredAttributeIntention,
+              HighlightDisplayKey.find(RequiredAttributesInspection.SHORT_NAME),
+              inspection,
+              XmlEntitiesInspection.NOT_REQUIRED_ATTRIBUTE
+            );
+          }
+        }
+      }
+    }
+  }
+
+  private void reportOneTagProblem(final XmlTag tag,
+                                   final String name,
+                                   final String localizedMessage,
+                                   final IntentionAction basicIntention,
+                                   final HighlightDisplayKey key,
+                                   final XmlEntitiesInspection inspection,
+                                   final int type) {
+    boolean htmlTag = false;
+
+    if (tag instanceof HtmlTag) {
+      htmlTag = true;
+      if(isAdditionallyDeclared(inspection.getAdditionalEntries(type), name)) return;
+    }
+
+    final InspectionProfile profile = InspectionProjectProfileManager.getInstance(tag.getProject()).getInspectionProfile();
+    final IntentionAction intentionAction = inspection.getIntentionAction(name, type);
+    if (htmlTag && profile.isToolEnabled(key, tag)) {
+      addElementsForTagWithManyQuickFixes(
+        tag,
+        localizedMessage,
+        isInjectedHtmlTagForWhichNoProblemsReporting((HtmlTag)tag) ?
+          HighlightInfoType.INFORMATION :
+          SeverityRegistrar.getInstance(tag.getProject()).getHighlightInfoTypeBySeverity(profile.getErrorLevel(key, tag).getSeverity()),
+        intentionAction,
+        basicIntention);
+    } else if (!htmlTag) {
+      addElementsForTag(
+        tag,
+        localizedMessage,
+        HighlightInfoType.ERROR,
+        basicIntention
+      );
+    }
+  }
+
+  private static boolean isAdditionallyDeclared(final String additional, String name) {
+    name = name.toLowerCase();
+    if (!additional.contains(name)) return false;
+
+    StringTokenizer tokenizer = new StringTokenizer(additional, ", ");
+    while (tokenizer.hasMoreTokens()) {
+      if (name.equals(tokenizer.nextToken())) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  private static HighlightInfoType getTagProblemInfoType(XmlTag tag) {
+    if (tag instanceof HtmlTag && XmlUtil.HTML_URI.equals(tag.getNamespace())) {
+      if (isInjectedHtmlTagForWhichNoProblemsReporting((HtmlTag)tag)) return HighlightInfoType.INFORMATION;
+      return HighlightInfoType.WARNING;
+    }
+    return HighlightInfoType.WRONG_REF;
+  }
+
+  private static boolean isInjectedHtmlTagForWhichNoProblemsReporting(HtmlTag tag) {
+    PsiElement context =
+      InjectedLanguageManager.getInstance(tag.getContainingFile().getProject()).getInjectionHost(tag.getContainingFile());
+    return context != null && skipValidation(context);
+  }
+
+  public static boolean skipValidation(PsiElement context) {
+    return DO_NOT_VALIDATE.get(context, null);
+  }
+
+  public static void setSkipValidation(@NotNull PsiElement element) {
+    DO_NOT_VALIDATE.put(element, Boolean.TRUE);
+  }
+
+  @Override public void visitXmlAttribute(XmlAttribute attribute) {}
+
+  private void checkAttribute(XmlAttribute attribute) {
+    XmlTag tag = attribute.getParent();
+
+    final String name = attribute.getName();
+
+    if (XmlExtension.getExtension(attribute.getContainingFile()).needWhitespaceBeforeAttribute()) {
+      PsiElement prevLeaf = PsiTreeUtil.prevLeaf(attribute);
+
+      if (!(prevLeaf instanceof PsiWhiteSpace)) {
+        TextRange textRange = attribute.getTextRange();
+        addToResults(HighlightInfo.createHighlightInfo(
+          tag instanceof HtmlTag ? HighlightInfoType.WARNING : HighlightInfoType.ERROR,
+          textRange.getStartOffset(),
+          textRange.getStartOffset(),
+          XmlErrorMessages.message("attribute.should.be.preceded.with.space")
+        ));
+      }
+    }
+
+    if (attribute.isNamespaceDeclaration()) {
+      checkReferences(attribute.getValueElement());
+      return;
+    }
+    final String namespace = attribute.getNamespace();
+
+    if (XmlUtil.XML_SCHEMA_INSTANCE_URI.equals(namespace)) {
+      checkReferences(attribute.getValueElement());
+      return;
+    }
+
+    XmlElementDescriptor elementDescriptor = tag.getDescriptor();
+    if (elementDescriptor == null ||
+        elementDescriptor instanceof AnyXmlElementDescriptor ||
+        ourDoJaxpTesting) {
+      return;
+    }
+
+    XmlAttributeDescriptor attributeDescriptor = elementDescriptor.getAttributeDescriptor(attribute);
+
+    if (attributeDescriptor == null) {
+      if (!XmlUtil.attributeFromTemplateFramework(name, tag)) {
+        final String localizedMessage = XmlErrorMessages.message("attribute.is.not.allowed.here", name);
+        final HighlightInfo highlightInfo = reportAttributeProblem(tag, name, attribute, localizedMessage);
+        if (highlightInfo != null) {
+          PsiFile file = tag.getContainingFile();
+          if (file != null) {
+            XmlExtension.getExtension(file).createAddAttributeFix(attribute, highlightInfo);
+          }
+        }
+      }
+    }
+    else {
+      checkDuplicateAttribute(tag, attribute);
+
+      if (tag instanceof HtmlTag &&
+          attribute.getValueElement() == null &&
+          !HtmlUtil.isSingleHtmlAttribute(name)
+         ) {
+        final String localizedMessage = XmlErrorMessages.message("empty.attribute.is.not.allowed", name);
+        reportAttributeProblem(tag, name, attribute, localizedMessage);
+      }
+
+      // we skip resolve of attribute references since there is separate check when taking attribute descriptors
+      PsiReference[] attrRefs = attribute.getReferences();
+      doCheckRefs(attribute, attrRefs, attribute.getNamespacePrefix().length() > 0 ? 2 : 1);
+    }
+  }
+
+  @Nullable
+  private HighlightInfo reportAttributeProblem(final XmlTag tag,
+                                               final String localName,
+                                               final XmlAttribute attribute,
+                                               final String localizedMessage) {
+
+    final RemoveAttributeIntentionFix removeAttributeIntention = new RemoveAttributeIntentionFix(localName,attribute);
+
+    if (!(tag instanceof HtmlTag)) {
+      final HighlightInfoType tagProblemInfoType = HighlightInfoType.WRONG_REF;
+
+      final ASTNode node = SourceTreeToPsiMap.psiElementToTree(attribute);
+      assert node != null;
+      final ASTNode child = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(node);
+      assert child != null;
+      final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(
+        tagProblemInfoType, child,
+        localizedMessage
+      );
+      addToResults(highlightInfo);
+
+      QuickFixAction.registerQuickFixAction(highlightInfo, removeAttributeIntention);
+
+      return highlightInfo;
+    }
+
+    return null;
+  }
+
+  private void checkDuplicateAttribute(XmlTag tag, final XmlAttribute attribute) {
+    if (skipValidation(tag)) {
+      return;
+    }
+
+    final XmlAttribute[] attributes = tag.getAttributes();
+    final PsiFile containingFile = tag.getContainingFile();
+    final XmlExtension extension = containingFile instanceof XmlFile ?
+                                   XmlExtension.getExtension(containingFile) :
+                                   XmlExtension.DEFAULT_EXTENSION;
+    for (XmlAttribute tagAttribute : attributes) {
+      ProgressManager.checkCanceled();
+      if (attribute != tagAttribute && Comparing.strEqual(attribute.getName(), tagAttribute.getName())) {
+        final String localName = attribute.getLocalName();
+
+        if (extension.canBeDuplicated(tagAttribute)) continue; // multiple import attributes are allowed in jsp directive
+
+        HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(
+          getTagProblemInfoType(tag),
+          XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(SourceTreeToPsiMap.psiElementToTree(attribute)),
+          XmlErrorMessages.message("duplicate.attribute", localName));
+        addToResults(highlightInfo);
+
+        IntentionAction intentionAction = new RemoveAttributeIntentionFix(localName, attribute);
+
+        QuickFixAction.registerQuickFixAction(highlightInfo, intentionAction);
+      }
+    }
+  }
+
+  @Override public void visitXmlDocument(final XmlDocument document) {
+    if (document.getLanguage() == DTDLanguage.INSTANCE) {
+      final PsiMetaData psiMetaData = document.getMetaData();
+      if (psiMetaData instanceof Validator) {
+        //noinspection unchecked
+        ((Validator<XmlDocument>)psiMetaData).validate(document, this);
+      }
+    }
+  }
+
+  @Override public void visitXmlTag(XmlTag tag) {
+  }
+
+  @Override public void visitXmlAttributeValue(XmlAttributeValue value) {
+    checkReferences(value);
+
+    final PsiElement parent = value.getParent();
+    if (!(parent instanceof XmlAttribute)) {
+      return;
+    }
+
+    XmlAttribute attribute = (XmlAttribute)parent;
+
+    XmlTag tag = attribute.getParent();
+
+    XmlElementDescriptor elementDescriptor = tag.getDescriptor();
+    XmlAttributeDescriptor attributeDescriptor = elementDescriptor != null ? elementDescriptor.getAttributeDescriptor(attribute):null;
+
+    if (attributeDescriptor != null && !skipValidation(value)) {
+      String error = attributeDescriptor.validateValue(value, attribute.getValue());
+
+      if (error != null) {
+        addToResults(HighlightInfo.createHighlightInfo(
+            getTagProblemInfoType(tag),
+            value,
+            error));
+      }
+    }
+  }
+
+  private void checkReferences(PsiElement value) {
+    if (value == null) return;
+
+    doCheckRefs(value, value.getReferences(), 0);
+  }
+
+  private void doCheckRefs(final PsiElement value, final PsiReference[] references, int start) {
+    for (int i = start; i < references.length; ++i) {
+      PsiReference reference = references[i];
+      ProgressManager.checkCanceled();
+      if (isUrlReference(reference)) continue;
+      if (!hasBadResolve(reference, false)) {
+        continue;
+      }
+      String description = getErrorDescription(reference);
+
+      final int startOffset = reference.getElement().getTextRange().getStartOffset();
+      final TextRange referenceRange = reference.getRangeInElement();
+
+      // logging for IDEADEV-29655
+      if (referenceRange.getStartOffset() > referenceRange.getEndOffset()) {
+        LOG.error("Reference range start offset > end offset:  " + reference +
+        ", start offset: " + referenceRange.getStartOffset() + ", end offset: " + referenceRange.getEndOffset());
+      }
+
+      HighlightInfoType type = getTagProblemInfoType(PsiTreeUtil.getParentOfType(value, XmlTag.class));
+      if (value instanceof XmlAttributeValue) {
+        PsiElement parent = value.getParent();
+        if (parent instanceof XmlAttribute) {
+          String name = ((XmlAttribute)parent).getName().toLowerCase();
+          if (type.getSeverity(null).compareTo(HighlightInfoType.WARNING.getSeverity(null)) > 0 && name.endsWith("stylename")) {
+            type = HighlightInfoType.WARNING;
+          }
+        }
+      }
+      HighlightInfo info = HighlightInfo.createHighlightInfo(
+        type,
+        startOffset + referenceRange.getStartOffset(),
+        startOffset + referenceRange.getEndOffset(),
+        description
+      );
+      addToResults(info);
+      if (reference instanceof QuickFixProvider) ((QuickFixProvider)reference).registerQuickfix(info, reference);
+      UnresolvedReferenceQuickFixProvider.registerReferenceFixes(reference, new QuickFixActionRegistrarImpl(info));
+    }
+  }
+
+  public static boolean isUrlReference(PsiReference reference) {
+    if (reference instanceof FileReferenceOwner || reference instanceof AnchorReference) {
+      return true;
+    }
+    return false;
+  }
+
+  public static String getErrorDescription(final PsiReference reference) {
+    String message;
+    if (reference instanceof EmptyResolveMessageProvider) {
+      message = ((EmptyResolveMessageProvider)reference).getUnresolvedMessagePattern();
+    }
+    else {
+      //noinspection UnresolvedPropertyKey
+      message = PsiBundle.message("cannot.resolve.symbol");
+    }
+
+    String description;
+    try {
+      description = BundleBase.format(message, reference.getCanonicalText()); // avoid double formatting
+    }
+    catch (IllegalArgumentException ex) {
+      // unresolvedMessage provided by third-party reference contains wrong format string (e.g. {}), tolerate it
+      description = message;
+    }
+    return description;
+  }
+
+  public static boolean hasBadResolve(final PsiReference reference, boolean checkSoft) {
+    if (!checkSoft && reference.isSoft()) return false;
+    if (reference instanceof PsiPolyVariantReference) {
+      return ((PsiPolyVariantReference)reference).multiResolve(false).length == 0;
+    }
+    return reference.resolve() == null;
+  }
+
+  @Override public void visitXmlDoctype(XmlDoctype xmlDoctype) {
+    if (skipValidation(xmlDoctype)) return;
+    checkReferences(xmlDoctype);
+  }
+
+  private void addToResults(final HighlightInfo info) {
+    myHolder.add(info);
+  }
+
+  public static void setDoJaxpTesting(boolean doJaxpTesting) {
+    ourDoJaxpTesting = doJaxpTesting;
+  }
+
+  public void addMessage(PsiElement context, String message, int type) {
+    if (message != null && message.length() > 0) {
+      if (context instanceof XmlTag && XmlExtension.getExtension(context.getContainingFile()).shouldBeHighlightedAsTag((XmlTag)context)) {
+        HighlightInfoType infoType = type == ERROR ? HighlightInfoType.ERROR : type == WARNING ? HighlightInfoType.WARNING : HighlightInfoType.WEAK_WARNING;
+        addElementsForTag((XmlTag)context, message, infoType, null);
+      }
+      else {
+        addToResults(HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, context, message));
+      }
+    }
+  }
+
+  public void addMessage(final PsiElement context, final String message, final ErrorType type, final IntentionAction... fixes) {
+    if (message != null && message.length() > 0) {
+      final PsiFile containingFile = context.getContainingFile();
+      final HighlightInfoType defaultInfoType = type == ErrorType.ERROR ? HighlightInfoType.ERROR : type == ErrorType.WARNING ? HighlightInfoType.WARNING : HighlightInfoType.WEAK_WARNING;
+
+      if (context instanceof XmlTag && XmlExtension.getExtension(containingFile).shouldBeHighlightedAsTag((XmlTag)context)) {
+        addElementsForTagWithManyQuickFixes((XmlTag)context, message, defaultInfoType, fixes);
+      }
+      else {
+        final PsiElement contextOfFile = InjectedLanguageManager.getInstance(containingFile.getProject()).getInjectionHost(containingFile);
+        final HighlightInfo highlightInfo;
+
+        if (contextOfFile != null) {
+          TextRange range = InjectedLanguageManager.getInstance(context.getProject()).injectedToHost(context, context.getTextRange());
+          highlightInfo = HighlightInfo.createHighlightInfo(defaultInfoType, range, message);
+        }
+        else {
+          highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, context, message);
+        }
+
+        if (fixes != null) {
+          for (final IntentionAction quickFixAction : fixes) {
+            if (quickFixAction == null) continue;
+            QuickFixAction.registerQuickFixAction(highlightInfo, quickFixAction);
+          }
+        }
+        addToResults(highlightInfo);
+      }
+    }
+  }
+
+  public boolean suitableForFile(@NotNull final PsiFile file) {
+    return file instanceof XmlFile;
+  }
+
+  public void visit(@NotNull final PsiElement element) {
+    element.accept(this);
+  }
+
+  public boolean analyze(@NotNull final PsiFile file,
+                         final boolean updateWholeFile,
+                         @NotNull HighlightInfoHolder holder,
+                         @NotNull Runnable action) {
+    myHolder = holder;
+    try {
+      action.run();
+    }
+    finally {
+      myHolder = null;
+    }
+    return true;
+  }
+
+  @NotNull
+  public HighlightVisitor clone() {
+    return new XmlHighlightVisitor();
+  }
+
+  public int order() {
+    return 1;
+  }
+
+  public static String getUnquotedValue(XmlAttributeValue value, XmlTag tag) {
+    String unquotedValue = value.getValue();
+
+    if (tag instanceof HtmlTag) {
+      unquotedValue = unquotedValue.toLowerCase();
+    }
+
+    return unquotedValue;
+  }
+
+  public static boolean shouldBeValidated(@NotNull XmlTag tag) {
+    PsiElement parent = tag.getParent();
+    if (parent instanceof XmlTag) {
+      return !skipValidation(parent) && !XmlUtil.tagFromTemplateFramework(tag);
+    }
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitorBasedInspection.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitorBasedInspection.java
new file mode 100644
index 0000000..50a9665
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitorBasedInspection.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.HighlightInfoFilter;
+import com.intellij.codeInspection.*;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.XmlRecursiveElementVisitor;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author yole
+ */
+public class XmlHighlightVisitorBasedInspection extends GlobalSimpleInspectionTool {
+  @NotNull
+  @Override
+  public HighlightDisplayLevel getDefaultLevel() {
+    return HighlightDisplayLevel.ERROR;
+  }
+
+  @Override
+  public void checkFile(@NotNull final PsiFile file,
+                        @NotNull final InspectionManager manager,
+                        @NotNull ProblemsHolder problemsHolder,
+                        @NotNull final GlobalInspectionContext globalContext,
+                        @NotNull final ProblemDescriptionsProcessor problemDescriptionsProcessor) {
+    HighlightInfoHolder myHolder = new HighlightInfoHolder(file, HighlightInfoFilter.EMPTY_ARRAY) {
+      @Override
+      public boolean add(@Nullable HighlightInfo info) {
+        if (info != null) {
+          GlobalInspectionUtil.createProblem(
+            file,
+            info,
+            new TextRange(info.startOffset, info.endOffset),
+            null,
+            manager,
+            problemDescriptionsProcessor,
+            globalContext
+          );
+        }
+        return true;
+      }
+    };
+    final XmlHighlightVisitor highlightVisitor = new XmlHighlightVisitor();
+    highlightVisitor.analyze(file, true, myHolder, new Runnable() {
+      @Override
+      public void run() {
+        file.accept(new XmlRecursiveElementVisitor() {
+          @Override
+          public void visitElement(PsiElement element) {
+            highlightVisitor.visit(element);
+            super.visitElement(element);
+          }
+        });
+      }
+    });
+
+  }
+
+  @Nls
+  @NotNull
+  @Override
+  public String getGroupDisplayName() {
+    return InspectionProfileEntry.GENERAL_GROUP_NAME;
+  }
+
+  @Nls
+  @NotNull
+  @Override
+  public String getDisplayName() {
+    return "XML highlighting";
+  }
+
+  @NotNull
+  @Override
+  public String getShortName() {
+    return "XmlHighlighting";
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlNSRenderer.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlNSRenderer.java
new file mode 100644
index 0000000..3dc1b02
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlNSRenderer.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.ui.ColoredListCellRenderer;
+import com.intellij.ui.SimpleTextAttributes;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlNSRenderer extends ColoredListCellRenderer {
+
+  public static final XmlNSRenderer INSTANCE = new XmlNSRenderer();
+
+  public XmlNSRenderer() {
+    EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
+    setFont(new Font(scheme.getEditorFontName(), Font.PLAIN, scheme.getEditorFontSize()));
+  }
+
+  protected void customizeCellRenderer(final JList list,
+                                       final Object value,
+                                       final int index,
+                                       final boolean selected,
+                                       final boolean hasFocus) {
+    append(value.toString(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+    setIcon(AllIcons.Nodes.Static);
+    setPaintFocusBorder(false);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlPathReferenceInspection.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlPathReferenceInspection.java
new file mode 100644
index 0000000..555fa15
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlPathReferenceInspection.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.codeInspection.XmlSuppressableInspectionTool;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlDoctype;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ *         Date: 9/3/12
+ */
+public class XmlPathReferenceInspection extends XmlSuppressableInspectionTool {
+
+  @NotNull
+  @Override
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    return new XmlElementVisitor() {
+      @Override
+      public void visitXmlAttributeValue(XmlAttributeValue value) {
+        checkRefs(value, holder, isOnTheFly);
+      }
+
+      @Override
+      public void visitXmlDoctype(XmlDoctype xmlDoctype) {
+        checkRefs(xmlDoctype, holder, isOnTheFly);
+      }
+
+      @Override
+      public void visitXmlTag(XmlTag tag) {
+        checkRefs(tag, holder, isOnTheFly);
+      }
+    };
+  }
+  
+  private void checkRefs(PsiElement element, ProblemsHolder holder, boolean isOnTheFly) {
+    PsiReference[] references = element.getReferences();
+    for (PsiReference reference : references) {
+      if (!XmlHighlightVisitor.isUrlReference(reference)) {
+        continue;
+      }
+      boolean isHtml = HtmlUtil.isHtmlTagContainingFile(element);
+      if (isHtml ^ isForHtml()) {
+        continue;
+      }
+      if (!isHtml && XmlHighlightVisitor.skipValidation(element)) {
+        continue;
+      }
+      if (XmlHighlightVisitor.hasBadResolve(reference, false)) {
+        holder.registerProblem(reference, ProblemsHolder.unresolvedReferenceMessage(reference),
+                               isHtml ? ProblemHighlightType.GENERIC_ERROR_OR_WARNING : ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
+      }
+    }
+  }
+
+  protected boolean isForHtml() {
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java
new file mode 100644
index 0000000..777c3ac
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.codeInspection.XmlSuppressableInspectionTool;
+import com.intellij.lang.injection.InjectedLanguageManager;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.xml.SchemaPrefixReference;
+import com.intellij.psi.templateLanguages.OuterLanguageElement;
+import com.intellij.psi.xml.*;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.util.XmlTagUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlUnboundNsPrefixInspection extends XmlSuppressableInspectionTool {
+
+  @NonNls private static final String XML = "xml";
+
+  @NotNull
+  @Override
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    return new XmlElementVisitor() {
+
+      private Boolean isXml;
+
+      private boolean isXmlFile(XmlElement element) {
+        if (isXml == null) {
+          final PsiFile file = element.getContainingFile();
+          isXml = file instanceof XmlFile && !InjectedLanguageManager.getInstance(element.getProject()).isInjectedFragment(file);
+        }
+        return isXml.booleanValue();
+      }
+
+      @Override
+      public void visitXmlToken(final XmlToken token) {
+        if (isXmlFile(token) && token.getTokenType() == XmlTokenType.XML_NAME) {
+          PsiElement element = token.getPrevSibling();
+          while(element instanceof PsiWhiteSpace) element = element.getPrevSibling();
+
+          if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_START_TAG_START) {
+            PsiElement parent = element.getParent();
+
+            if (parent instanceof XmlTag && !(token.getNextSibling() instanceof OuterLanguageElement)) {
+              XmlTag tag = (XmlTag)parent;
+              checkUnboundNamespacePrefix(tag, tag, tag.getNamespacePrefix(), token, holder, isOnTheFly);
+            }
+          }
+        }
+      }
+
+      @Override
+      public void visitXmlAttribute(final XmlAttribute attribute) {
+        if (!isXmlFile(attribute)) {
+          return;
+        }
+        final String namespace = attribute.getNamespace();
+        if (attribute.isNamespaceDeclaration() || XmlUtil.XML_SCHEMA_INSTANCE_URI.equals(namespace)) {
+          return;
+        }
+
+        XmlTag tag = attribute.getParent();
+        XmlElementDescriptor elementDescriptor = tag.getDescriptor();
+        if (elementDescriptor == null ||
+            elementDescriptor instanceof AnyXmlElementDescriptor) {
+          return;
+        }
+
+
+        final String name = attribute.getName();
+
+        checkUnboundNamespacePrefix(attribute, tag, XmlUtil.findPrefixByQualifiedName(name), null, holder, isOnTheFly);
+      }
+
+      @Override
+      public void visitXmlAttributeValue(XmlAttributeValue value) {
+        PsiReference[] references = value.getReferences();
+        for (PsiReference reference : references) {
+          if (reference instanceof SchemaPrefixReference) {
+            if (!XML.equals(((SchemaPrefixReference)reference).getNamespacePrefix()) && reference.resolve() == null) {
+              holder.registerProblem(reference, XmlErrorMessages.message("unbound.namespace",
+                                                                         ((SchemaPrefixReference)reference).getNamespacePrefix()), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
+            }
+          }
+        }
+      }
+    };
+  }
+
+  private static void checkUnboundNamespacePrefix(final XmlElement element, final XmlTag context, String namespacePrefix, final XmlToken token,
+                                                  final ProblemsHolder holder, boolean isOnTheFly) {
+
+    if (namespacePrefix.length() == 0 && (!(element instanceof XmlTag) || !(element.getParent() instanceof XmlDocument))
+      || XML.equals(namespacePrefix)) {
+      return;
+    }
+
+    final String namespaceByPrefix = context.getNamespaceByPrefix(namespacePrefix);
+    if (namespaceByPrefix.length() != 0) {
+      return;
+    }
+    PsiFile psiFile = context.getContainingFile();
+    if (!(psiFile instanceof XmlFile)) return;
+    final XmlFile containingFile = (XmlFile)psiFile;
+    if (!HighlightLevelUtil.shouldInspect(containingFile)) return;
+
+    final XmlExtension extension = XmlExtension.getExtension(containingFile);
+    if (extension.getPrefixDeclaration(context, namespacePrefix) != null) {
+      return;
+    }
+
+    final String localizedMessage = isOnTheFly ? XmlErrorMessages.message("unbound.namespace", namespacePrefix) : XmlErrorMessages.message("unbound.namespace.no.param");
+
+    if (namespacePrefix.length() == 0) {
+      final XmlTag tag = (XmlTag)element;
+      if (!XmlUtil.JSP_URI.equals(tag.getNamespace())) {
+        reportTagProblem(tag, localizedMessage, null, ProblemHighlightType.INFORMATION, 
+                         isOnTheFly ? new CreateNSDeclarationIntentionFix(context, namespacePrefix, token) : null,
+                         holder);
+      }
+      return;
+    }
+
+    final int prefixLength = namespacePrefix.length();
+    final TextRange range = new TextRange(0, prefixLength);
+    final HighlightInfoType infoType = extension.getHighlightInfoType(containingFile);
+    final ProblemHighlightType highlightType = infoType == HighlightInfoType.ERROR ? ProblemHighlightType.ERROR : ProblemHighlightType.LIKE_UNKNOWN_SYMBOL;
+    if (element instanceof XmlTag) {
+      final CreateNSDeclarationIntentionFix fix = isOnTheFly ? new CreateNSDeclarationIntentionFix(context, namespacePrefix, token) : null;
+      reportTagProblem(element, localizedMessage, range, highlightType, fix, holder);
+    } else {
+      holder.registerProblem(element, localizedMessage, highlightType, range);
+    }
+  }
+
+  private static void reportTagProblem(final XmlElement element, final String localizedMessage, final TextRange range, final ProblemHighlightType highlightType,
+                                       final CreateNSDeclarationIntentionFix fix,
+                                       final ProblemsHolder holder) {
+
+    XmlToken nameToken = XmlTagUtil.getStartTagNameElement((XmlTag)element);
+    if (nameToken != null) {
+      holder.registerProblem(nameToken, localizedMessage, highlightType, range, fix);
+    }
+    nameToken = XmlTagUtil.getEndTagNameElement((XmlTag)element);
+    if (nameToken != null) {
+      holder.registerProblem(nameToken, localizedMessage, highlightType, range, fix);
+    }
+  }
+
+
+  @NotNull
+  public HighlightDisplayLevel getDefaultLevel() {
+    return HighlightDisplayLevel.WARNING;
+  }
+
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlBundle.message("xml.inspections.group.name");
+  }
+
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("xml.inspections.unbound.prefix");
+  }
+
+  @NotNull
+  @NonNls
+  public String getShortName() {
+    return "XmlUnboundNsPrefix";
+  }
+}
+
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java
new file mode 100644
index 0000000..b5d8245
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
+import com.intellij.codeInspection.*;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.URLReference;
+import com.intellij.psi.impl.source.xml.SchemaPrefix;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.util.XmlRefCountHolder;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool {
+
+  private static final String NAMESPACE_LOCATION_IS_NEVER_USED = "Namespace location is never used";
+
+  @NotNull
+  @Override
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
+
+    return new XmlElementVisitor() {
+
+      @Override
+      public void visitXmlAttribute(XmlAttribute attribute) {
+        if (!attribute.isNamespaceDeclaration()) {
+          checkUnusedLocations(attribute, holder);
+          return;
+        }
+        XmlRefCountHolder refCountHolder = XmlRefCountHolder.getRefCountHolder(attribute);
+        if (refCountHolder == null) return;
+
+        String namespace = attribute.getValue();
+        String declaredPrefix = getDeclaredPrefix(attribute);
+        if (namespace != null && !refCountHolder.isInUse(declaredPrefix)) {
+
+          ImplicitUsageProvider[] implicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
+          for (ImplicitUsageProvider provider : implicitUsageProviders) {
+            if (provider.isImplicitUsage(attribute)) return;
+          }
+
+          XmlAttributeValue value = attribute.getValueElement();
+          assert value != null;
+          holder.registerProblem(attribute, "Namespace declaration is never used", ProblemHighlightType.LIKE_UNUSED_SYMBOL,
+                                 new RemoveNamespaceDeclarationFix(declaredPrefix, false));
+
+          XmlTag parent = attribute.getParent();
+          if (declaredPrefix.length() == 0) {
+            XmlAttribute location = getDefaultLocation(parent);
+            if (location != null) {
+              holder.registerProblem(location, NAMESPACE_LOCATION_IS_NEVER_USED, ProblemHighlightType.LIKE_UNUSED_SYMBOL,
+                                     new RemoveNamespaceDeclarationFix(declaredPrefix, true));
+            }
+          }
+          else if (!refCountHolder.isUsedNamespace(namespace)) {
+            for (PsiReference reference : getLocationReferences(namespace, parent)) {
+              if (!XmlHighlightVisitor.hasBadResolve(reference, false))
+              holder.registerProblemForReference(reference, ProblemHighlightType.LIKE_UNUSED_SYMBOL, NAMESPACE_LOCATION_IS_NEVER_USED,
+                                                 new RemoveNamespaceDeclarationFix(declaredPrefix, true));
+            }
+          }
+        }
+      }
+    };
+  }
+
+  private static void removeReferencesOrAttribute(PsiReference[] references) {
+    if (references.length == 0) {
+      return;
+    }
+    
+    XmlAttributeValue element = (XmlAttributeValue)references[0].getElement();
+    XmlAttribute attribute = (XmlAttribute)element.getParent();
+    if (element.getReferences().length == references.length) { // all refs to be removed
+      attribute.delete();
+      return;
+    }
+
+    PsiFile file = element.getContainingFile();
+    Project project = file.getProject();
+    SmartPsiElementPointer<XmlAttribute> pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(attribute);
+    for (PsiReference reference : references) {
+      RemoveNamespaceDeclarationFix.removeReferenceText(reference);
+    }
+
+    // trimming the result
+    PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
+    Document document = documentManager.getDocument(file);
+    assert document != null;
+    documentManager.commitDocument(document);
+    String trimmed = element.getValue().trim();
+    XmlAttribute pointerElement = pointer.getElement();
+    assert pointerElement != null;
+    pointerElement.setValue(trimmed);
+  }
+
+  private static void checkUnusedLocations(XmlAttribute attribute, ProblemsHolder holder) {
+    if (XmlUtil.XML_SCHEMA_INSTANCE_URI.equals(attribute.getNamespace())) {
+      XmlRefCountHolder refCountHolder = XmlRefCountHolder.getRefCountHolder(attribute);
+      if (refCountHolder == null) return;
+
+      if (XmlUtil.NO_NAMESPACE_SCHEMA_LOCATION_ATT.equals(attribute.getLocalName())) {
+        if (refCountHolder.isInUse("")) return;
+        holder.registerProblem(attribute, NAMESPACE_LOCATION_IS_NEVER_USED, ProblemHighlightType.LIKE_UNUSED_SYMBOL,
+                               new RemoveNamespaceLocationFix(""));
+      }
+      else if (XmlUtil.SCHEMA_LOCATION_ATT.equals(attribute.getLocalName())) {
+        XmlAttributeValue value = attribute.getValueElement();
+        if (value == null) return;
+        PsiReference[] references = value.getReferences();
+        for (int i = 0, referencesLength = references.length; i < referencesLength; i++) {
+          PsiReference reference = references[i];
+          if (reference instanceof URLReference) {
+            String ns = getNamespaceFromReference(reference);
+            if (ArrayUtil.indexOf(attribute.getParent().knownNamespaces(), ns) == -1 && !refCountHolder.isUsedNamespace(ns)) {
+              if (!XmlHighlightVisitor.hasBadResolve(reference, false)) {
+                holder.registerProblemForReference(reference, ProblemHighlightType.LIKE_UNUSED_SYMBOL, NAMESPACE_LOCATION_IS_NEVER_USED,
+                                                   new RemoveNamespaceLocationFix(ns));
+              }
+              for (int j = i + 1; j < referencesLength; j++) {
+                PsiReference nextRef = references[j];
+                if (nextRef instanceof URLReference) break;
+                if (!XmlHighlightVisitor.hasBadResolve(nextRef, false)) {
+                  holder.registerProblemForReference(nextRef, ProblemHighlightType.LIKE_UNUSED_SYMBOL, NAMESPACE_LOCATION_IS_NEVER_USED,
+                                                     new RemoveNamespaceLocationFix(ns));
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  private static String getDeclaredPrefix(XmlAttribute attribute) {
+    return attribute.getName().contains(":") ? attribute.getLocalName() : "";
+  }
+
+  @Nullable
+  private static XmlAttribute getDefaultLocation(XmlTag parent) {
+    return parent.getAttribute(XmlUtil.NO_NAMESPACE_SCHEMA_LOCATION_ATT, XmlUtil.XML_SCHEMA_INSTANCE_URI);
+  }
+
+  private static PsiReference[] getLocationReferences(String namespace, XmlTag tag) {
+    XmlAttribute locationAttr = tag.getAttribute(XmlUtil.SCHEMA_LOCATION_ATT, XmlUtil.XML_SCHEMA_INSTANCE_URI);
+    if (locationAttr == null) {
+      return PsiReference.EMPTY_ARRAY;
+    }
+    XmlAttributeValue value = locationAttr.getValueElement();
+    assert value != null;
+    return getLocationReferences(namespace, value);
+  }
+
+  private static PsiReference[] getLocationReferences(String namespace, XmlAttributeValue value) {
+    PsiReference[] references = value.getReferences();
+    for (int i = 0, referencesLength = references.length; i < referencesLength; i+=2) {
+      PsiReference reference = references[i];
+      if (namespace.equals(getNamespaceFromReference(reference))) {
+        if (i + 1 < referencesLength) {
+          return new PsiReference[] { references[i + 1], reference };
+        }
+        else {
+          return new PsiReference[] { reference };
+        }
+      }
+    }
+    return PsiReference.EMPTY_ARRAY;
+  }
+
+  private static String getNamespaceFromReference(PsiReference reference) {
+    return reference.getRangeInElement().substring(reference.getElement().getText());
+  }
+
+  @NotNull
+  public HighlightDisplayLevel getDefaultLevel() {
+    return HighlightDisplayLevel.WARNING;
+  }
+
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+
+  @Nls
+  @NotNull
+  @Override
+  public String getGroupDisplayName() {
+    return XmlBundle.message("xml.inspections.group.name");
+  }
+
+  @Nls
+  @NotNull
+  @Override
+  public String getDisplayName() {
+    return "Unused XML schema declaration";
+  }
+
+  @NotNull
+  @Override
+  public String getShortName() {
+    return "XmlUnusedNamespaceDeclaration";
+  }
+
+  public static class RemoveNamespaceDeclarationFix implements LocalQuickFix {
+
+    public static final String NAME = "Remove unused namespace declaration";
+
+    protected final String myPrefix;
+    private final boolean myLocationFix;
+
+    private RemoveNamespaceDeclarationFix(@Nullable String prefix, boolean locationFix) {
+      myPrefix = prefix;
+      myLocationFix = locationFix;
+    }
+
+    @NotNull
+    public String getName() {
+      return NAME;
+    }
+
+    @NotNull
+    public String getFamilyName() {
+      return XmlBundle.message("xml.inspections.group.name");
+    }
+
+    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+      doFix(project, descriptor, true);
+    }
+
+    @Nullable
+    public SmartPsiElementPointer<XmlTag> doFix(Project project, ProblemDescriptor descriptor, boolean reformat) {
+      PsiElement element = descriptor.getPsiElement();
+      if (element instanceof XmlAttributeValue) {
+        element = element.getParent();
+      }
+      else if (!(element instanceof XmlAttribute)) {
+        return null;
+      }
+      XmlAttribute attribute = (XmlAttribute)element;
+      XmlTag parent = attribute.getParent();
+
+      if (!CodeInsightUtilBase.prepareFileForWrite(parent.getContainingFile())) return null;
+
+      SmartPsiElementPointer<XmlTag> pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(parent);
+
+      doRemove(project, attribute, parent);
+
+      if (reformat) {
+        reformatStartTag(project, pointer);
+      }
+      return pointer;
+    }
+
+    public static void reformatStartTag(Project project, SmartPsiElementPointer<XmlTag> pointer) {
+      PsiDocumentManager manager = PsiDocumentManager.getInstance(project);
+      PsiFile file = pointer.getContainingFile();
+      assert file != null;
+      Document document = manager.getDocument(file);
+      assert document != null;
+      manager.commitDocument(document);
+      XmlTag tag = pointer.getElement();
+      assert tag != null;
+      XmlUtil.reformatTagStart(tag);
+    }
+
+    protected void doRemove(Project project, XmlAttribute attribute, XmlTag parent) {
+      if (!attribute.isNamespaceDeclaration()) {
+        SchemaPrefix schemaPrefix = XmlExtension.DEFAULT_EXTENSION.getPrefixDeclaration(parent, myPrefix);
+        if (schemaPrefix != null) {
+          attribute = schemaPrefix.getDeclaration();
+        }
+      }
+      String namespace = attribute.getValue();
+      String prefix = getDeclaredPrefix(attribute);
+
+      PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
+      Document document = documentManager.getDocument(attribute.getContainingFile());
+      assert document != null;
+      attribute.delete();
+      if (prefix.length() == 0) {
+        XmlAttribute locationAttr = getDefaultLocation(parent);
+        if (locationAttr != null) {
+          locationAttr.delete();
+        }
+      }
+      else {
+        documentManager.doPostponedOperationsAndUnblockDocument(document);
+        PsiReference[] references = getLocationReferences(namespace, parent);
+        removeReferencesOrAttribute(references);
+        documentManager.commitDocument(document);
+      }
+    }
+
+    public static void removeReferenceText(PsiReference ref) {
+      PsiElement element = ref.getElement();
+      PsiFile file = element.getContainingFile();
+      TextRange range = ref.getRangeInElement().shiftRight(element.getTextRange().getStartOffset());
+      PsiDocumentManager manager = PsiDocumentManager.getInstance(file.getProject());
+      Document document = manager.getDocument(file);
+      assert document != null;
+      manager.doPostponedOperationsAndUnblockDocument(document);
+      document.deleteString(range.getStartOffset(), range.getEndOffset());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      return obj instanceof RemoveNamespaceDeclarationFix &&
+             Comparing.equal(myPrefix, ((RemoveNamespaceDeclarationFix)obj).myPrefix) &&
+             (myLocationFix || ((RemoveNamespaceDeclarationFix)obj).myLocationFix);
+    }
+
+    @Override
+    public int hashCode() {
+      return myPrefix == null ? 0 : myPrefix.hashCode();
+    }
+  }
+
+  public static class RemoveNamespaceLocationFix extends RemoveNamespaceDeclarationFix {
+
+    public static final String NAME = "Remove unused namespace location";
+
+    private RemoveNamespaceLocationFix(String namespace) {
+      super(namespace, true);
+    }
+
+    @NotNull
+    @Override
+    public String getName() {
+      return NAME;
+    }
+
+    @Override
+    protected void doRemove(Project project, XmlAttribute attribute, XmlTag parent) {
+      if (myPrefix.length() == 0) {
+        attribute.delete();
+      }
+      else {
+        XmlAttributeValue value = attribute.getValueElement();
+        if (value == null) {
+          return;
+        }
+        PsiReference[] references = getLocationReferences(myPrefix, value);
+        removeReferencesOrAttribute(references);
+      }
+    }
+
+    @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
+    @Override
+    public boolean equals(Object obj) {
+      return this == obj;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java
new file mode 100644
index 0000000..59d9879
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis.encoding;
+
+import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author cdr
+*/
+public class XmlEncodingReference implements PsiReference, EmptyResolveMessageProvider, Comparable<XmlEncodingReference> {
+  private final XmlAttributeValue myValue;
+
+  private final String myCharsetName;
+  private final TextRange myRangeInElement;
+  private final int myPriority;
+
+  public XmlEncodingReference(XmlAttributeValue value, final String charsetName, final TextRange rangeInElement, int priority) {
+    myValue = value;
+    myCharsetName = charsetName;
+    myRangeInElement = rangeInElement;
+    myPriority = priority;
+  }
+
+  public PsiElement getElement() {
+    return myValue;
+  }
+
+  public TextRange getRangeInElement() {
+    return myRangeInElement;
+  }
+
+  @Nullable
+  public PsiElement resolve() {
+    return CharsetToolkit.forName(myCharsetName) == null ? null : myValue;
+    //if (ApplicationManager.getApplication().isUnitTestMode()) return myValue; // tests do not have full JDK
+    //String fqn = charset.getClass().getName();
+    //return myValue.getManager().findClass(fqn, GlobalSearchScope.allScope(myValue.getProject()));
+  }
+
+  public String getUnresolvedMessagePattern() {
+    //noinspection UnresolvedPropertyKey
+    return XmlErrorMessages.message("unknown.encoding.0");
+  }
+
+  @NotNull
+  public String getCanonicalText() {
+    return myCharsetName;
+  }
+
+  public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+    return null;
+  }
+
+  public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+    return null;
+  }
+
+  public boolean isReferenceTo(PsiElement element) {
+    return false;
+  }
+
+  @NotNull
+  public Object[] getVariants() {
+    Charset[] charsets = CharsetToolkit.getAvailableCharsets();
+    List<LookupElement> suggestions = new ArrayList<LookupElement>(charsets.length);
+    for (Charset charset : charsets) {
+      suggestions.add(LookupElementBuilder.create(charset.name()).withCaseSensitivity(false));
+    }
+    return suggestions.toArray(new LookupElement[suggestions.size()]);
+  }
+
+  public boolean isSoft() {
+    return false;
+  }
+
+  public int compareTo(XmlEncodingReference ref) {
+    return myPriority - ref.myPriority;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReferenceProvider.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReferenceProvider.java
new file mode 100644
index 0000000..ffe0b62
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReferenceProvider.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.analysis.encoding;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author cdr
+ */
+public class XmlEncodingReferenceProvider extends PsiReferenceProvider {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.encoding.XmlEncodingReferenceProvider");
+  @NonNls private static final String CHARSET_PREFIX = "charset=";
+
+  @NotNull
+  public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull final ProcessingContext context) {
+    LOG.assertTrue(element instanceof XmlAttributeValue);
+    XmlAttributeValue value = (XmlAttributeValue)element;
+
+    return new PsiReference[]{new XmlEncodingReference(value, value.getValue(), xmlAttributeValueRange(value), 0)};
+  }
+
+  protected static TextRange xmlAttributeValueRange(final XmlAttributeValue xmlAttributeValue) {
+    ASTNode valueNode = XmlChildRole.ATTRIBUTE_VALUE_VALUE_FINDER.findChild(xmlAttributeValue.getNode());
+    PsiElement toHighlight = valueNode == null ? xmlAttributeValue : valueNode.getPsi();
+    TextRange childRange = toHighlight.getTextRange();
+    TextRange range = xmlAttributeValue.getTextRange();
+    return childRange.shiftRight(-range.getStartOffset());
+  }
+
+  public static PsiReference[] extractFromContentAttribute(final XmlAttributeValue value) {
+    String text = value.getValue();
+    int start = text.indexOf(CHARSET_PREFIX);
+    if (start != -1) {
+      start += CHARSET_PREFIX.length();
+      int end = text.indexOf(';', start);
+      if (end == -1) end = text.length();
+      String charsetName = text.substring(start, end);
+      TextRange textRange = new TextRange(start, end).shiftRight(xmlAttributeValueRange(value).getStartOffset());
+      return new PsiReference[]{new XmlEncodingReference(value, charsetName, textRange, 0)};
+    }
+    return PsiReference.EMPTY_ARRAY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddXsiSchemaLocationForExtResourceAction.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddXsiSchemaLocationForExtResourceAction.java
new file mode 100644
index 0000000..7a6752a
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddXsiSchemaLocationForExtResourceAction.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.quickfix;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.daemon.impl.analysis.CreateNSDeclarationIntentionFix;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author maxim.mossienko
+ */
+public class AddXsiSchemaLocationForExtResourceAction extends BaseExtResourceAction {
+  @NonNls private static final String XMLNS_XSI_ATTR_NAME = "xmlns:xsi";
+  @NonNls private static final String XSI_SCHEMA_LOCATION_ATTR_NAME = "xsi:schemaLocation";
+  public static final String KEY = "add.xsi.schema.location.for.external.resource";
+
+  protected String getQuickFixKeyId() {
+    return KEY;
+  }
+
+  protected void doInvoke(@NotNull final PsiFile file, final int offset, @NotNull final String uri, final Editor editor) throws IncorrectOperationException {
+    final XmlTag tag = PsiTreeUtil.getParentOfType(file.findElementAt(offset), XmlTag.class);
+    if (tag == null) return;
+    final List<String> schemaLocations = new ArrayList<String>();
+
+    CreateNSDeclarationIntentionFix.processExternalUris(new CreateNSDeclarationIntentionFix.TagMetaHandler(tag.getLocalName()), file, new CreateNSDeclarationIntentionFix.ExternalUriProcessor() {
+      public void process(@NotNull final String currentUri, final String url) {
+        if (currentUri.equals(uri) && url != null) schemaLocations.add(url);
+      }
+
+    }, true);
+
+    CreateNSDeclarationIntentionFix.runActionOverSeveralAttributeValuesAfterLettingUserSelectTheNeededOne(
+      ArrayUtil.toStringArray(schemaLocations), file.getProject(), new CreateNSDeclarationIntentionFix.StringToAttributeProcessor() {
+        public void doSomethingWithGivenStringToProduceXmlAttributeNowPlease(@NotNull final String attrName) throws IncorrectOperationException {
+          doIt(file, editor, uri, tag, attrName);
+        }
+      }, XmlErrorMessages.message("select.namespace.location.title"), this, editor);
+  }
+
+  private static void doIt(final PsiFile file, final Editor editor, final String uri, final XmlTag tag, final String s) throws IncorrectOperationException {
+    if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
+    final XmlElementFactory elementFactory = XmlElementFactory.getInstance(file.getProject());
+
+    if (tag.getAttributeValue(XMLNS_XSI_ATTR_NAME) == null) {
+      tag.add(elementFactory.createXmlAttribute(XMLNS_XSI_ATTR_NAME, XmlUtil.XML_SCHEMA_INSTANCE_URI));
+    }
+
+    final XmlAttribute locationAttribute = tag.getAttribute(XSI_SCHEMA_LOCATION_ATTR_NAME);
+    final String toInsert = uri + " " + s;
+    int offset = s.length();
+
+    if (locationAttribute == null) {
+      tag.add(elementFactory.createXmlAttribute(XSI_SCHEMA_LOCATION_ATTR_NAME, toInsert));
+    } else {
+      final String newValue = locationAttribute.getValue() + "\n" + toInsert;
+      locationAttribute.setValue(newValue);
+    }
+
+    CodeStyleManager.getInstance(file.getProject()).reformat(tag);
+
+    @SuppressWarnings("ConstantConditions")
+    final TextRange range = tag.getAttribute(XSI_SCHEMA_LOCATION_ATTR_NAME).getValueElement().getTextRange();
+    final TextRange textRange = new TextRange(range.getEndOffset() - offset - 1, range.getEndOffset() - 1);
+    editor.getCaretModel().moveToOffset(textRange.getStartOffset());
+  }
+
+  @Override
+  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+    if (!(file instanceof XmlFile)) return false;
+
+    PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+    XmlAttributeValue value = PsiTreeUtil.getParentOfType(element, XmlAttributeValue.class);
+    if (value == null) return false;
+    XmlAttribute attribute = PsiTreeUtil.getParentOfType(value, XmlAttribute.class);
+    if (attribute != null && attribute.isNamespaceDeclaration()) {
+      setText(XmlBundle.message(getQuickFixKeyId()));
+      return true;
+    }
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BaseExtResourceAction.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BaseExtResourceAction.java
new file mode 100644
index 0000000..9feb95a
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BaseExtResourceAction.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.quickfix;
+
+import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.URIReferenceProvider;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.URLReference;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author mike
+ */
+abstract class BaseExtResourceAction extends BaseIntentionAction {
+
+  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+    if (!(file instanceof XmlFile)) return false;
+
+    int offset = editor.getCaretModel().getOffset();
+    String uri = findUri(file, offset);
+    if (uri == null || !isAcceptableUri(uri)) return false;
+
+    setText(XmlBundle.message(getQuickFixKeyId()));
+    return true;
+  }
+
+  protected boolean isAcceptableUri(final String uri) {
+    return true;
+  }
+
+  protected abstract String getQuickFixKeyId();
+
+  @NotNull
+  public String getFamilyName() {
+    return XmlBundle.message(getQuickFixKeyId());
+  }
+
+  public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+    int offset = editor.getCaretModel().getOffset();
+
+    PsiDocumentManager.getInstance(project).commitAllDocuments();
+
+    final String uri = findUri(file, offset);
+    if (uri == null) return;
+
+    doInvoke(file, offset, uri, editor);
+  }
+
+  protected abstract void doInvoke(final @NotNull PsiFile file, final int offset, final @NotNull String uri, final Editor editor)
+    throws IncorrectOperationException;
+
+  @Nullable
+  public static String findUri(PsiFile file, int offset) {
+    PsiReference currentRef = file.getViewProvider().findReferenceAt(offset, file.getLanguage());
+    if (currentRef == null) currentRef = file.getViewProvider().findReferenceAt(offset);
+    if (currentRef instanceof URLReference ||
+        currentRef instanceof URIReferenceProvider.DependentNSReference) {
+      return currentRef.getCanonicalText();
+    }
+    return null;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    return obj instanceof ManuallySetupExtResourceAction;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FetchExtResourceAction.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FetchExtResourceAction.java
new file mode 100644
index 0000000..9d114d2
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FetchExtResourceAction.java
@@ -0,0 +1,523 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.quickfix;
+
+import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.fileTypes.FileTypes;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.WatchedRootsProvider;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.source.xml.XmlEntityRefImpl;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.net.HttpConfigurable;
+import com.intellij.util.net.IOExceptionDialog;
+import com.intellij.util.net.NetUtils;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * @author mike
+ */
+public class FetchExtResourceAction extends BaseExtResourceAction implements WatchedRootsProvider {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.FetchDtdAction");
+  private static final @NonNls String HTML_MIME = "text/html";
+  private static final @NonNls String HTTP_PROTOCOL = "http://";
+  private static final @NonNls String HTTPS_PROTOCOL = "https://";
+  private static final @NonNls String FTP_PROTOCOL = "ftp://";
+  private static final @NonNls String EXT_RESOURCES_FOLDER = "extResources";
+
+  protected String getQuickFixKeyId() {
+    return "fetch.external.resource";
+  }
+
+  protected boolean isAcceptableUri(final String uri) {
+    return uri.startsWith(HTTP_PROTOCOL) || uri.startsWith(FTP_PROTOCOL) || uri.startsWith(HTTPS_PROTOCOL);
+  }
+
+  public static String findUrl(PsiFile file, int offset, String uri) {
+    final PsiElement currentElement = file.findElementAt(offset);
+    final XmlAttribute attribute = PsiTreeUtil.getParentOfType(currentElement, XmlAttribute.class);
+
+    if (attribute != null) {
+      final XmlTag tag = PsiTreeUtil.getParentOfType(currentElement, XmlTag.class);
+
+      if (tag != null) {
+        final String prefix = tag.getPrefixByNamespace(XmlUtil.XML_SCHEMA_INSTANCE_URI);
+        if (prefix != null) {
+          final String attrValue = tag.getAttributeValue(XmlUtil.SCHEMA_LOCATION_ATT, XmlUtil.XML_SCHEMA_INSTANCE_URI);
+          if (attrValue != null) {
+            final StringTokenizer tokenizer = new StringTokenizer(attrValue);
+
+            while (tokenizer.hasMoreElements()) {
+              if (uri.equals(tokenizer.nextToken())) {
+                if (!tokenizer.hasMoreElements()) return uri;
+                final String url = tokenizer.nextToken();
+
+                return url.startsWith(HTTP_PROTOCOL) ? url : uri;
+              }
+
+              if (!tokenizer.hasMoreElements()) return uri;
+              tokenizer.nextToken(); // skip file location
+            }
+          }
+        }
+      }
+    }
+    return uri;
+  }
+
+  @NotNull
+  public Set<String> getRootsToWatch() {
+    final File path = new File(getExternalResourcesPath());
+    if (!path.exists() && !path.mkdirs()) {
+      LOG.warn("Unable to create: " + path);
+    }
+    return Collections.singleton(path.getAbsolutePath());
+  }
+
+  static class FetchingResourceIOException extends IOException {
+    private final String url;
+
+    FetchingResourceIOException(Throwable cause, String url) {
+      initCause(cause);
+      this.url = url;
+    }
+  }
+
+  protected void doInvoke(@NotNull final PsiFile file, final int offset, @NotNull final String uri, final Editor editor)
+    throws IncorrectOperationException {
+    final String url = findUrl(file, offset, uri);
+    final Project project = file.getProject();
+
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      return;
+    }
+
+    ProgressManager.getInstance().run(new Task.Backgroundable(project, XmlBundle.message("fetching.resource.title")) {
+      @Override
+      public void run(@NotNull ProgressIndicator indicator) {
+        while (true) {
+          try {
+            HttpConfigurable.getInstance().prepareURL(url);
+            fetchDtd(project, uri, url, indicator);
+            ApplicationManager.getApplication().invokeLater(new Runnable() {
+              @Override
+              public void run() {
+                DaemonCodeAnalyzer.getInstance(project).restart(file);
+              }
+            });
+            return;
+          }
+          catch (IOException ex) {
+            LOG.info(ex);
+            @SuppressWarnings("InstanceofCatchParameter")
+            String problemUrl = ex instanceof FetchingResourceIOException ? ((FetchingResourceIOException)ex).url : url;
+            String message = XmlBundle.message("error.fetching.title");
+
+            if (!url.equals(problemUrl)) {
+              message = XmlBundle.message("error.fetching.dependent.resource.title");
+            }
+
+            if (!IOExceptionDialog.showErrorDialog(message, XmlBundle.message("error.fetching.resource", problemUrl))) {
+              break; // cancel fetching
+            }
+          }
+        }
+      }
+    });
+  }
+
+  private void fetchDtd(final Project project, final String dtdUrl, final String url, final ProgressIndicator indicator) throws IOException {
+    final String extResourcesPath = getExternalResourcesPath();
+    final File extResources = new File(extResourcesPath);
+    LOG.assertTrue(extResources.mkdirs() || extResources.exists(), extResources);
+
+    final PsiManager psiManager = PsiManager.getInstance(project);
+    ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+      public void run() {
+        @SuppressWarnings("deprecation")
+        final AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(FetchExtResourceAction.class);
+        try {
+          final String path = FileUtil.toSystemIndependentName(extResources.getAbsolutePath());
+          final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
+          LOG.assertTrue(vFile != null, path);
+        }
+        finally {
+          token.finish();
+        }
+      }
+    }, indicator.getModalityState());
+
+    final List<String> downloadedResources = new LinkedList<String>();
+    final List<String> resourceUrls = new LinkedList<String>();
+    final IOException[] nestedException = new IOException[1];
+
+    try {
+      final String resPath = fetchOneFile(indicator, url, project, extResourcesPath, null);
+      if (resPath == null) return;
+      resourceUrls.add(dtdUrl);
+      downloadedResources.add(resPath);
+
+      VirtualFile virtualFile = findFileByPath(resPath, dtdUrl, indicator);
+
+      Set<String> linksToProcess = new HashSet<String>();
+      Set<String> processedLinks = new HashSet<String>();
+      Map<String, String> baseUrls = new HashMap<String, String>();
+      VirtualFile contextFile = virtualFile;
+      linksToProcess.addAll(extractEmbeddedFileReferences(virtualFile, null, psiManager));
+
+      while (!linksToProcess.isEmpty()) {
+        String s = linksToProcess.iterator().next();
+        linksToProcess.remove(s);
+        processedLinks.add(s);
+
+        final boolean absoluteUrl = s.startsWith(HTTP_PROTOCOL);
+        String resourceUrl;
+        if (absoluteUrl) {
+          resourceUrl = s;
+        }
+        else {
+          String baseUrl = baseUrls.get(s);
+          if (baseUrl == null) baseUrl = url;
+
+          resourceUrl = baseUrl.substring(0, baseUrl.lastIndexOf('/') + 1) + s;
+        }
+
+        String resourcePath;
+
+        String refname = s.substring(s.lastIndexOf('/') + 1);
+        if (absoluteUrl) refname = Integer.toHexString(s.hashCode()) + "_" + refname;
+        try {
+          resourcePath = fetchOneFile(indicator, resourceUrl, project, extResourcesPath, refname);
+        }
+        catch (IOException e) {
+          nestedException[0] = new FetchingResourceIOException(e, resourceUrl);
+          break;
+        }
+
+        if (resourcePath == null) break;
+
+        virtualFile = findFileByPath(resourcePath, absoluteUrl ? s : null, indicator);
+        downloadedResources.add(resourcePath);
+
+        if (absoluteUrl) {
+          resourceUrls.add(s);
+        }
+
+        final List<String> newLinks = extractEmbeddedFileReferences(virtualFile, contextFile, psiManager);
+        for (String u : newLinks) {
+          baseUrls.put(u, resourceUrl);
+          if (!processedLinks.contains(u)) linksToProcess.add(u);
+        }
+      }
+    }
+    catch (IOException ex) {
+      nestedException[0] = ex;
+    }
+    if (nestedException[0] != null) {
+      cleanup(resourceUrls, downloadedResources);
+      throw nestedException[0];
+    }
+  }
+
+  private static VirtualFile findFileByPath(final String resPath, final @Nullable String dtdUrl, ProgressIndicator indicator) {
+    final Ref<VirtualFile> ref = new Ref<VirtualFile>();
+    ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+      public void run() {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          public void run() {
+            ref.set(LocalFileSystem.getInstance().refreshAndFindFileByPath(resPath.replace(File.separatorChar, '/')));
+            if (dtdUrl != null) {
+              ExternalResourceManager.getInstance().addResource(dtdUrl, resPath);
+            }
+          }
+        });
+      }
+    }, indicator.getModalityState());
+    return ref.get();
+  }
+
+  public static String getExternalResourcesPath() {
+    return PathManager.getSystemPath() + File.separator + EXT_RESOURCES_FOLDER;
+  }
+
+  private void cleanup(final List<String> resourceUrls, final List<String> downloadedResources) {
+    ApplicationManager.getApplication().invokeLater(new Runnable() {
+      public void run() {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          public void run() {
+            for (String resourcesUrl : resourceUrls) {
+              ExternalResourceManager.getInstance().removeResource(resourcesUrl);
+            }
+
+            for (String downloadedResource : downloadedResources) {
+              VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(new File(downloadedResource));
+              if (virtualFile != null) {
+                try {
+                  virtualFile.delete(this);
+                }
+                catch (IOException ignore) {
+
+                }
+              }
+            }
+          }
+        });
+      }
+    });
+  }
+
+  @Nullable
+  private static String fetchOneFile(final ProgressIndicator indicator,
+                                     final String resourceUrl,
+                                     final Project project,
+                                     String extResourcesPath,
+                                     @Nullable String refname) throws IOException {
+    SwingUtilities.invokeLater(
+      new Runnable() {
+        public void run() {
+          indicator.setText(XmlBundle.message("fetching.progress.indicator", resourceUrl));
+        }
+      }
+    );
+
+    FetchResult result = fetchData(project, resourceUrl, indicator);
+    if (result == null) return null;
+
+    if (!ApplicationManager.getApplication().isUnitTestMode() &&
+        result.contentType != null &&
+        result.contentType.contains(HTML_MIME) &&
+        new String(result.bytes).contains("<html")) {
+      ApplicationManager.getApplication().invokeLater(new Runnable() {
+        public void run() {
+          Messages.showMessageDialog(project,
+                                     XmlBundle.message("invalid.url.no.xml.file.at.location", resourceUrl),
+                                     XmlBundle.message("invalid.url.title"),
+                                     Messages.getErrorIcon());
+        }
+      }, indicator.getModalityState());
+      return null;
+    }
+
+    int slashIndex = resourceUrl.lastIndexOf('/');
+    String resPath = extResourcesPath + File.separatorChar;
+
+    if (refname != null) { // resource is known under ref.name so need to save it
+      resPath += refname;
+      int refNameSlashIndex = resPath.lastIndexOf('/');
+      if (refNameSlashIndex != -1) {
+        final File parent = new File(resPath.substring(0, refNameSlashIndex));
+        if (!parent.mkdirs() || !parent.exists()) {
+          LOG.warn("Unable to create: " + parent);
+        }
+      }
+    }
+    else {
+      resPath += Integer.toHexString(resourceUrl.hashCode()) + "_" + resourceUrl.substring(slashIndex + 1);
+    }
+
+    final int lastDoPosInResourceUrl = resourceUrl.lastIndexOf('.', slashIndex);
+    if (lastDoPosInResourceUrl == -1 ||
+        FileTypeManager.getInstance().getFileTypeByExtension(resourceUrl.substring(lastDoPosInResourceUrl + 1)) == FileTypes.UNKNOWN) {
+      // remote url does not contain file with extension
+      resPath += "." + StdFileTypes.XML.getDefaultExtension();
+    }
+
+    File res = new File(resPath);
+
+    FileOutputStream out = new FileOutputStream(res);
+    try {
+      out.write(result.bytes);
+    }
+    finally {
+      out.close();
+    }
+    return resPath;
+  }
+
+  private static List<String> extractEmbeddedFileReferences(XmlFile file, XmlFile context) {
+    final List<String> result = new LinkedList<String>();
+    if (context != null) {
+      XmlEntityRefImpl.copyEntityCaches(file, context);
+    }
+
+    XmlUtil.processXmlElements(
+      file,
+      new PsiElementProcessor() {
+        public boolean execute(@NotNull PsiElement element) {
+          if (element instanceof XmlEntityDecl) {
+            String candidateName = null;
+
+            for (PsiElement e = element.getLastChild(); e != null; e = e.getPrevSibling()) {
+              if (e instanceof XmlAttributeValue && candidateName == null) {
+                candidateName = e.getText().substring(1, e.getTextLength() - 1);
+              }
+              else if (e instanceof XmlToken &&
+                       candidateName != null &&
+                       (((XmlToken)e).getTokenType() == XmlTokenType.XML_DOCTYPE_PUBLIC ||
+                        ((XmlToken)e).getTokenType() == XmlTokenType.XML_DOCTYPE_SYSTEM
+                       )
+                ) {
+                if (!result.contains(candidateName)) {
+                  result.add(candidateName);
+                }
+                break;
+              }
+            }
+          }
+          else if (element instanceof XmlTag) {
+            final XmlTag tag = (XmlTag)element;
+            String schemaLocation = tag.getAttributeValue(XmlUtil.SCHEMA_LOCATION_ATT);
+
+            if (schemaLocation != null) {
+              final PsiReference[] references = tag.getAttribute(XmlUtil.SCHEMA_LOCATION_ATT, null).getValueElement().getReferences();
+              if (references.length > 0) {
+                final String namespace = tag.getAttributeValue("namespace");
+
+                if (namespace != null && schemaLocation.indexOf('/') == -1) {
+                  result.add(namespace.substring(0, namespace.lastIndexOf('/') + 1) + schemaLocation);
+                }
+                else {
+                  result.add(schemaLocation);
+                }
+              }
+            }
+
+            final String prefix = tag.getPrefixByNamespace(XmlUtil.XML_SCHEMA_INSTANCE_URI);
+            if (prefix != null) {
+              schemaLocation = tag.getAttributeValue("schemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI);
+
+              if (schemaLocation != null) {
+                final StringTokenizer tokenizer = new StringTokenizer(schemaLocation);
+
+                while (tokenizer.hasMoreTokens()) {
+                  tokenizer.nextToken();
+                  if (!tokenizer.hasMoreTokens()) break;
+                  String location = tokenizer.nextToken();
+
+                  if (!result.contains(location)) {
+                    result.add(location);
+                  }
+                }
+              }
+            }
+          }
+
+          return true;
+        }
+      },
+      true,
+      true
+    );
+    return result;
+  }
+
+  public static List<String> extractEmbeddedFileReferences(final VirtualFile vFile, @Nullable final VirtualFile contextVFile, final PsiManager psiManager) {
+    return ApplicationManager.getApplication().runReadAction(new Computable<List<String>>() {
+      @Override
+      public List<String> compute() {
+        PsiFile file = psiManager.findFile(vFile);
+
+        if (file instanceof XmlFile) {
+          PsiFile contextFile = contextVFile != null ? psiManager.findFile(contextVFile) : null;
+          return extractEmbeddedFileReferences((XmlFile)file, contextFile instanceof XmlFile ? (XmlFile)contextFile : null);
+        }
+
+        return Collections.emptyList();
+      }
+    });
+  }
+
+  static class FetchResult {
+    byte[] bytes;
+    String contentType;
+  }
+
+  @Nullable
+  private static FetchResult fetchData(final Project project, final String dtdUrl, ProgressIndicator indicator) throws IOException {
+
+    try {
+      URL url = new URL(dtdUrl);
+      HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
+      urlConnection.addRequestProperty("accept", "text/xml,application/xml,text/html,*/*");
+      int contentLength = urlConnection.getContentLength();
+
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      InputStream in = urlConnection.getInputStream();
+      String contentType;
+      try {
+        contentType = urlConnection.getContentType();
+        NetUtils.copyStreamContent(indicator, in, out, contentLength);
+      }
+      finally {
+        in.close();
+      }
+
+      FetchResult result = new FetchResult();
+      result.bytes = out.toByteArray();
+      result.contentType = contentType;
+
+      return result;
+    }
+    catch (MalformedURLException e) {
+      if (!ApplicationManager.getApplication().isUnitTestMode()) {
+        ApplicationManager.getApplication().invokeLater(new Runnable() {
+          public void run() {
+            Messages.showMessageDialog(project,
+                                       XmlBundle.message("invalid.url.message", dtdUrl),
+                                       XmlBundle.message("invalid.url.title"),
+                                       Messages.getErrorIcon());
+          }
+        }, indicator.getModalityState());
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IgnoreExtResourceAction.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IgnoreExtResourceAction.java
new file mode 100644
index 0000000..54d922b
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IgnoreExtResourceAction.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.quickfix;
+
+import com.intellij.javaee.ExternalResourceManagerEx;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author mike
+ */
+public class IgnoreExtResourceAction extends BaseExtResourceAction {
+  protected String getQuickFixKeyId() {
+    return "ignore.external.resource.text";
+  }
+
+  protected void doInvoke(@NotNull final PsiFile file, final int offset, @NotNull final String uri, final Editor editor) throws IncorrectOperationException {
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      public void run() {
+        ExternalResourceManagerEx.getInstanceEx().addIgnoredResource(uri);
+      }
+    });
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ManuallySetupExtResourceAction.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ManuallySetupExtResourceAction.java
new file mode 100644
index 0000000..06f9865
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ManuallySetupExtResourceAction.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.quickfix;
+
+import com.intellij.javaee.MapExternalResourceDialog;
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author mike
+ */
+public class ManuallySetupExtResourceAction extends BaseExtResourceAction {
+
+  protected String getQuickFixKeyId() {
+    return "manually.setup.external.resource";
+  }
+
+  protected void doInvoke(@NotNull final PsiFile file, final int offset, @NotNull final String uri, final Editor editor) throws IncorrectOperationException {
+    final MapExternalResourceDialog dialog = new MapExternalResourceDialog(uri, file.getProject(), file, null);
+    dialog.show();
+    if (dialog.isOK()) {
+      ApplicationManager.getApplication().runWriteAction(new Runnable() {
+        @Override
+        public void run() {
+          String location = dialog.getResourceLocation();
+          ExternalResourceManager.getInstance().addResource(dialog.getUri(), location);
+        }
+      });
+    }
+  }
+
+  public boolean startInWriteAction() {
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeBreadcrumbsPresentationProvider.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeBreadcrumbsPresentationProvider.java
new file mode 100644
index 0000000..9f524f0
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeBreadcrumbsPresentationProvider.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.tagTreeHighlighting;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.breadcrumbs.BreadcrumbsPresentationProvider;
+import com.intellij.xml.breadcrumbs.CrumbPresentation;
+import com.intellij.xml.breadcrumbs.DefaultCrumbsPresentation;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class XmlTagTreeBreadcrumbsPresentationProvider extends BreadcrumbsPresentationProvider {
+  private static boolean isMyContext(@NotNull PsiElement deepestElement) {
+    final PsiFile file = deepestElement.getContainingFile();
+    if (file == null || !XmlTagTreeHighlightingUtil.isTagTreeHighlightingActive(file)) {
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public CrumbPresentation[] getCrumbPresentations(@NotNull PsiElement[] elements) {
+    if (elements.length == 0 || !isMyContext(elements[elements.length - 1])) {
+      return null;
+    }
+
+    if (!XmlTagTreeHighlightingUtil.containsTagsWithSameName(elements)) {
+      return null;
+    }
+
+    final CrumbPresentation[] result = new CrumbPresentation[elements.length];
+    final Color[] baseColors = XmlTagTreeHighlightingUtil.getBaseColors();
+    int index = 0;
+
+    for (int i = result.length - 1; i >= 0; i--) {
+      if (elements[i] instanceof XmlTag) {
+        final Color color = baseColors[index % baseColors.length];
+        result[i] = new MyCrumbPresentation(color);
+        index++;
+      }
+    }
+    return result;
+  }
+
+  private static class MyCrumbPresentation extends DefaultCrumbsPresentation {
+    private final Color myColor;
+
+    private MyCrumbPresentation(@Nullable Color color) {
+      myColor = color;
+    }
+
+    @Override
+    public Color getBackgroundColor(boolean selected, boolean hovered, boolean light) {
+      final Color baseColor = super.getBackgroundColor(selected, hovered, light);
+      return myColor != null
+             ? XmlTagTreeHighlightingUtil.makeTransparent(myColor, baseColor, 0.1)
+             : baseColor;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingColors.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingColors.java
new file mode 100644
index 0000000..f146ea7
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingColors.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.tagTreeHighlighting;
+
+import com.intellij.application.options.editor.WebEditorOptions;
+import com.intellij.openapi.editor.colors.ColorKey;
+import com.intellij.util.ui.PlatformColors;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.*;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class XmlTagTreeHighlightingColors {
+  private static ColorKey[] ourColorKeys = null;
+
+  private static final Color[] DEFAULT_COLORS = new Color[]{Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN, PlatformColors.BLUE, Color.MAGENTA};
+
+  private XmlTagTreeHighlightingColors() {
+  }
+
+  @NotNull
+  public static ColorKey[] getColorKeys() {
+    final int levelCount = WebEditorOptions.getInstance().getTagTreeHighlightingLevelCount();
+
+    if (ourColorKeys == null || ourColorKeys.length != levelCount) {
+      ourColorKeys = new ColorKey[levelCount];
+
+      for (int i = 0; i < ourColorKeys.length; i++) {
+        ourColorKeys[i] = ColorKey.createColorKey("HTML_TAG_TREE_LEVEL" + i, DEFAULT_COLORS[i % DEFAULT_COLORS.length]);
+      }
+    }
+
+    return ourColorKeys;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingConfigurable.form b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingConfigurable.form
new file mode 100644
index 0000000..44f6766
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingConfigurable.form
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.codeInsight.daemon.impl.tagTreeHighlighting.XmlTagTreeHighlightingConfigurable">
+  <grid id="27dc6" binding="myContentPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="303" height="97"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="b5068" class="javax.swing.JCheckBox" binding="myEnableTagTreeHighlightingCheckBox">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text value="Enable HTML/XML tag tree highlighting"/>
+        </properties>
+      </component>
+      <grid id="30544" binding="myLevelsPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <component id="84b2a" class="javax.swing.JLabel">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="3" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <labelFor value="f41b2"/>
+              <text value="Levels to highlight:"/>
+            </properties>
+          </component>
+          <component id="f41b2" class="javax.swing.JSpinner" binding="myLevelsSpinner">
+            <constraints>
+              <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                <preferred-size width="50" height="-1"/>
+                <maximum-size width="50" height="-1"/>
+              </grid>
+            </constraints>
+            <properties/>
+          </component>
+          <component id="c1d38" class="javax.swing.JLabel">
+            <constraints>
+              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="3" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <labelFor value="dd25f"/>
+              <text value="Opacity:"/>
+            </properties>
+          </component>
+          <component id="dd25f" class="javax.swing.JSpinner" binding="myOpacitySpinner">
+            <constraints>
+              <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                <preferred-size width="50" height="-1"/>
+                <maximum-size width="50" height="-1"/>
+              </grid>
+            </constraints>
+            <properties/>
+          </component>
+        </children>
+      </grid>
+      <hspacer id="dd839">
+        <constraints>
+          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+      </hspacer>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingConfigurable.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingConfigurable.java
new file mode 100644
index 0000000..ace1e2b
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingConfigurable.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.tagTreeHighlighting;
+
+import com.intellij.application.options.editor.WebEditorOptions;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.TextEditor;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.UnnamedConfigurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.breadcrumbs.BreadcrumbsXmlWrapper;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class XmlTagTreeHighlightingConfigurable implements UnnamedConfigurable {
+  private JCheckBox myEnableTagTreeHighlightingCheckBox;
+  private JSpinner myLevelsSpinner;
+  private JPanel myLevelsPanel;
+  private JPanel myContentPanel;
+  private JSpinner myOpacitySpinner;
+
+  public XmlTagTreeHighlightingConfigurable() {
+    myLevelsSpinner.setModel(new SpinnerNumberModel(1, 1, 50, 1));
+    myOpacitySpinner.setModel(new SpinnerNumberModel(0.0, 0.0, 1.0, 0.05));
+
+    myEnableTagTreeHighlightingCheckBox.addActionListener(new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        final boolean enabled = myEnableTagTreeHighlightingCheckBox.isSelected();
+        UIUtil.setEnabled(myLevelsPanel, enabled, true);
+      }
+    });
+  }
+
+  @Override
+  public JComponent createComponent() {
+    return myContentPanel;
+  }
+
+  @Override
+  public boolean isModified() {
+    final WebEditorOptions options = WebEditorOptions.getInstance();
+
+    if (myEnableTagTreeHighlightingCheckBox.isSelected() != options.isTagTreeHighlightingEnabled()) {
+      return true;
+    }
+
+    if (getLevelCount() != options.getTagTreeHighlightingLevelCount()) {
+      return true;
+    }
+
+    if (getOpacity() != options.getTagTreeHighlightingOpacity()) {
+      return true;
+    }
+
+    return false;
+  }
+
+  @Override
+  public void apply() throws ConfigurationException {
+    final WebEditorOptions options = WebEditorOptions.getInstance();
+
+    options.setTagTreeHighlightingEnabled(myEnableTagTreeHighlightingCheckBox.isSelected());
+    options.setTagTreeHighlightingLevelCount(getLevelCount());
+    options.setTagTreeHighlightingOpacity(getOpacity());
+
+    clearTagTreeHighlighting();
+  }
+
+  private int getLevelCount() {
+    return ((Integer)myLevelsSpinner.getValue()).intValue();
+  }
+
+  private int getOpacity() {
+    return (int)(((Double)myOpacitySpinner.getValue()).doubleValue() * 100);
+  }
+
+  private static void clearTagTreeHighlighting() {
+    for (Project project : ProjectManager.getInstance().getOpenProjects()) {
+      for (FileEditor fileEditor : FileEditorManager.getInstance(project).getAllEditors()) {
+        if (fileEditor instanceof TextEditor) {
+          final Editor editor = ((TextEditor)fileEditor).getEditor();
+          XmlTagTreeHighlightingPass.clearHighlightingAndLineMarkers(editor, project);
+
+          final BreadcrumbsXmlWrapper breadcrumbsXmlWrapper = BreadcrumbsXmlWrapper.getBreadcrumbsComponent(editor);
+          if (breadcrumbsXmlWrapper != null) {
+            breadcrumbsXmlWrapper.queueUpdate(editor);
+          }
+        }
+      }
+    }
+  }
+
+  @Override
+  public void reset() {
+    final WebEditorOptions options = WebEditorOptions.getInstance();
+    final boolean enabled = options.isTagTreeHighlightingEnabled();
+
+    myEnableTagTreeHighlightingCheckBox.setSelected(enabled);
+    myLevelsSpinner.setValue(options.getTagTreeHighlightingLevelCount());
+    myOpacitySpinner.setValue(options.getTagTreeHighlightingOpacity() * 0.01);
+    UIUtil.setEnabled(myLevelsPanel, enabled, true);
+  }
+
+  @Override
+  public void disposeUIResources() {
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPass.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPass.java
new file mode 100644
index 0000000..9ad8d1a
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPass.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.tagTreeHighlighting;
+
+import com.intellij.application.options.editor.WebEditorOptions;
+import com.intellij.codeHighlighting.TextEditorHighlightingPass;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
+import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.ex.MarkupModelEx;
+import com.intellij.openapi.editor.impl.DocumentMarkupModel;
+import com.intellij.openapi.editor.markup.*;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.ui.Gray;
+import com.intellij.xml.breadcrumbs.BreadcrumbsInfoProvider;
+import com.intellij.xml.breadcrumbs.BreadcrumbsXmlWrapper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class XmlTagTreeHighlightingPass extends TextEditorHighlightingPass {
+  private static final Key<List<RangeHighlighter>> TAG_TREE_HIGHLIGHTERS_IN_EDITOR_KEY = Key.create("TAG_TREE_HIGHLIGHTERS_IN_EDITOR_KEY");
+
+  private static final HighlightInfoType TYPE = new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, TextAttributesKey
+    .createTextAttributesKey("TAG_TREE_HIGHLIGHTING_KEY"));
+
+  private final PsiFile myFile;
+  private final EditorEx myEditor;
+  private final BreadcrumbsInfoProvider myInfoProvider;
+
+  private final List<Pair<TextRange, TextRange>> myPairsToHighlight = new ArrayList<Pair<TextRange, TextRange>>();
+
+  public XmlTagTreeHighlightingPass(@NotNull PsiFile file, @NotNull EditorEx editor) {
+    super(file.getProject(), editor.getDocument(), true);
+    myFile = file;
+    myEditor = editor;
+    final FileViewProvider viewProvider = file.getManager().findViewProvider(file.getVirtualFile());
+    myInfoProvider = BreadcrumbsXmlWrapper.findInfoProvider(viewProvider);
+  }
+
+  @Override
+  public void doCollectInformation(@NotNull ProgressIndicator progress) {
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      return;
+    }
+
+    if (!WebEditorOptions.getInstance().isTagTreeHighlightingEnabled()) {
+      return;
+    }
+
+    final PsiElement[] elements =
+      BreadcrumbsXmlWrapper.getLinePsiElements(myEditor.getCaretModel().getOffset(), myFile.getVirtualFile(), myProject, myInfoProvider);
+
+    if (elements == null || elements.length == 0) {
+      return;
+    }
+
+    if (!XmlTagTreeHighlightingUtil.containsTagsWithSameName(elements)) {
+      return;
+    }
+
+    for (int i = elements.length - 1; i >= 0; i--) {
+      if (elements[i] instanceof XmlTag) {
+        myPairsToHighlight.add(getTagRanges((XmlTag)elements[i]));
+      }
+    }
+  }
+
+  @Nullable
+  private static Pair<TextRange, TextRange> getTagRanges(XmlTag tag) {
+    final ASTNode tagNode = tag.getNode();
+    return new Pair<TextRange, TextRange>(getStartTagRange(tagNode), getEndTagRange(tagNode));
+  }
+
+  @Nullable
+  private static TextRange getStartTagRange(ASTNode tagNode) {
+    final ASTNode startTagStart = XmlChildRole.START_TAG_START_FINDER.findChild(tagNode);
+    if (startTagStart == null) {
+      return null;
+    }
+
+    ASTNode tagName = startTagStart.getTreeNext();
+    if (tagName == null || tagName.getElementType() != XmlTokenType.XML_NAME) {
+      return null;
+    }
+
+    ASTNode next = tagName.getTreeNext();
+    if (next != null && next.getElementType() == XmlTokenType.XML_TAG_END) {
+      tagName = next;
+    }
+
+    return new TextRange(startTagStart.getStartOffset(), tagName.getTextRange().getEndOffset());
+  }
+
+  @Nullable
+  private static TextRange getEndTagRange(ASTNode tagNode) {
+    final ASTNode endTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(tagNode);
+    if (endTagStart == null) {
+      return null;
+    }
+
+    ASTNode endTagEnd = endTagStart;
+    while (endTagEnd != null && endTagEnd.getElementType() != XmlTokenType.XML_TAG_END) {
+      endTagEnd = endTagEnd.getTreeNext();
+    }
+
+    if (endTagEnd == null) {
+      return null;
+    }
+
+    return new TextRange(endTagStart.getStartOffset(), endTagEnd.getTextRange().getEndOffset());
+  }
+
+  @Override
+  public void doApplyInformationToEditor() {
+    final List<HighlightInfo> infos = getHighlights();
+    UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), infos, getColorsScheme(), getId());
+  }
+
+  public List<HighlightInfo> getHighlights() {
+    clearLineMarkers(myEditor);
+
+    final int count = myPairsToHighlight.size();
+    final List<HighlightInfo> highlightInfos = new ArrayList<HighlightInfo>(count * 2);
+    final MarkupModel markupModel = myEditor.getMarkupModel();
+
+    final Color[] baseColors = XmlTagTreeHighlightingUtil.getBaseColors();
+    final Color[] colorsForEditor = toColorsForEditor(baseColors);
+    final Color[] colorsForLineMarkers = toColorsForLineMarkers(baseColors);
+
+    final List<RangeHighlighter> newHighlighters = new ArrayList<RangeHighlighter>();
+
+    assert colorsForEditor.length > 0;
+
+    for (int i = 0; i < count && i < baseColors.length; i++) {
+      Pair<TextRange, TextRange> pair = myPairsToHighlight.get(i);
+
+      if (pair == null || (pair.first == null && pair.second == null)) {
+        continue;
+      }
+
+      Color color = colorsForEditor[i];
+
+      if (color == null) {
+        continue;
+      }
+
+      if (pair.first != null && !pair.first.isEmpty()) {
+        highlightInfos.add(createHighlightInfo(color, pair.first));
+      }
+
+      if (pair.second != null && !pair.second.isEmpty()) {
+        highlightInfos.add(createHighlightInfo(color, pair.second));
+      }
+
+      final int start = pair.first != null ? pair.first.getStartOffset() : pair.second.getStartOffset();
+      final int end = pair.second != null ? pair.second.getEndOffset() : pair.first.getEndOffset();
+
+      final Color lineMarkerColor = colorsForLineMarkers[i];
+      if (lineMarkerColor != null && start != end) {
+        final RangeHighlighter highlighter = createHighlighter(markupModel, new TextRange(start, end), lineMarkerColor);
+        newHighlighters.add(highlighter);
+      }
+    }
+
+    myEditor.putUserData(TAG_TREE_HIGHLIGHTERS_IN_EDITOR_KEY, newHighlighters);
+
+    return highlightInfos;
+  }
+
+  private static void clearLineMarkers(Editor editor) {
+    final List<RangeHighlighter> oldHighlighters = editor.getUserData(TAG_TREE_HIGHLIGHTERS_IN_EDITOR_KEY);
+
+    if (oldHighlighters != null) {
+      final MarkupModelEx markupModel = (MarkupModelEx)editor.getMarkupModel();
+
+      for (RangeHighlighter highlighter : oldHighlighters) {
+        if (markupModel.containsHighlighter(highlighter)) {
+          highlighter.dispose();
+        }
+      }
+      editor.putUserData(TAG_TREE_HIGHLIGHTERS_IN_EDITOR_KEY, null);
+    }
+  }
+
+  @NotNull
+  private static HighlightInfo createHighlightInfo(Color color, @NotNull TextRange range) {
+    return new HighlightInfo(new TextAttributes(null, color, null, null, Font.PLAIN), null, TYPE, range.getStartOffset(),
+                             range.getEndOffset(), null, null, HighlightSeverity.INFORMATION, false, null, false);
+  }
+
+  @NotNull
+  private static RangeHighlighter createHighlighter(final MarkupModel mm, final @NotNull TextRange range, final Color color) {
+    final RangeHighlighter highlighter =
+      mm.addRangeHighlighter(range.getStartOffset(), range.getEndOffset(), 0, null, HighlighterTargetArea.LINES_IN_RANGE);
+
+    highlighter.setLineMarkerRenderer(new LineMarkerRenderer() {
+      public void paint(Editor editor, Graphics g, Rectangle r) {
+        int height = r.height + editor.getLineHeight();
+        g.setColor(color);
+        g.fillRect(r.x, r.y, 2, height);
+      }
+    });
+    return highlighter;
+  }
+
+
+  private static Color[] toColorsForLineMarkers(Color[] baseColors) {
+    final Color[] colors = new Color[baseColors.length];
+    final Color tagBackground = Gray._239;
+    final double transparency = 0.4;
+    final double factor = 0.8;
+
+    for (int i = 0; i < colors.length; i++) {
+      final Color color = baseColors[i];
+
+      if (color == null) {
+        colors[i] = null;
+        continue;
+      }
+
+      int r = (int)(color.getRed() * factor);
+      int g = (int)(color.getGreen() * factor);
+      int b = (int)(color.getBlue() * factor);
+
+      r = (int)(tagBackground.getRed() * (1 - transparency) + r * transparency);
+      g = (int)(tagBackground.getGreen() * (1 - transparency) + g * transparency);
+      b = (int)(tagBackground.getBlue() * (1 - transparency) + b * transparency);
+
+      colors[i] = new Color(r, g, b);
+    }
+
+    return colors;
+  }
+
+  private Color[] toColorsForEditor(Color[] baseColors) {
+    final Color tagBackground = myEditor.getBackgroundColor();
+
+    if (tagBackground == null) {
+      return baseColors;
+    }
+
+    final Color[] resultColors = new Color[baseColors.length];
+    // todo: make configurable
+    final double transparency = WebEditorOptions.getInstance().getTagTreeHighlightingOpacity() * 0.01;
+
+    for (int i = 0; i < resultColors.length; i++) {
+      final Color color = baseColors[i];
+
+      final Color color1 = color != null
+                           ? XmlTagTreeHighlightingUtil.makeTransparent(color, tagBackground, transparency)
+                           : null;
+      resultColors[i] = color1;
+    }
+
+    return resultColors;
+  }
+
+  public static void clearHighlightingAndLineMarkers(final Editor editor, @NotNull Project project) {
+    final MarkupModel markupModel = DocumentMarkupModel.forDocument(editor.getDocument(), project, true);
+
+    for (RangeHighlighter highlighter : markupModel.getAllHighlighters()) {
+      Object tooltip = highlighter.getErrorStripeTooltip();
+
+      if (!(tooltip instanceof HighlightInfo)) {
+        continue;
+      }
+
+      if (((HighlightInfo)tooltip).type == TYPE) {
+        highlighter.dispose();
+      }
+    }
+
+    clearLineMarkers(editor);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPassFactory.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPassFactory.java
new file mode 100644
index 0000000..ca06e72
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPassFactory.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.tagTreeHighlighting;
+
+import com.intellij.codeHighlighting.Pass;
+import com.intellij.codeHighlighting.TextEditorHighlightingPass;
+import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory;
+import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class XmlTagTreeHighlightingPassFactory extends AbstractProjectComponent implements TextEditorHighlightingPassFactory {
+
+  public XmlTagTreeHighlightingPassFactory(Project project, TextEditorHighlightingPassRegistrar registrar) {
+    super(project);
+    registrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL}, null, false, -1);
+  }
+
+  public TextEditorHighlightingPass createHighlightingPass(@NotNull final PsiFile file, @NotNull final Editor editor) {
+    if (editor.isOneLineMode()) return null;
+
+    if (!XmlTagTreeHighlightingUtil.isTagTreeHighlightingActive(file)) return null;
+    if (!(editor instanceof EditorEx)) return null;
+
+    return new XmlTagTreeHighlightingPass(file, (EditorEx)editor);
+  }
+}
+
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingUtil.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingUtil.java
new file mode 100644
index 0000000..f5a388a
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingUtil.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.tagTreeHighlighting;
+
+import com.intellij.application.options.editor.WebEditorOptions;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.colors.ColorKey;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.*;
+import java.util.Set;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+class XmlTagTreeHighlightingUtil {
+  private XmlTagTreeHighlightingUtil() {
+  }
+
+  static boolean containsTagsWithSameName(PsiElement[] elements) {
+    final Set<String> names = new HashSet<String>();
+
+    for (PsiElement element : elements) {
+      if (element instanceof XmlTag) {
+        final String name = ((XmlTag)element).getName();
+        if (!names.add(name)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  static boolean isTagTreeHighlightingActive(PsiFile file) {
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      return false;
+    }
+
+    if (!hasXmlViewProvider(file)) {
+      return false;
+    }
+
+    if (!WebEditorOptions.getInstance().isTagTreeHighlightingEnabled()) {
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean hasXmlViewProvider(@NotNull PsiFile file) {
+    for (PsiFile f : file.getViewProvider().getAllFiles()) {
+      if (f instanceof XmlFile) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static Color makeTransparent(@NotNull Color color, @NotNull Color backgroundColor, double transparency) {
+    int r = makeTransparent(transparency, color.getRed(), backgroundColor.getRed());
+    int g = makeTransparent(transparency, color.getGreen(), backgroundColor.getGreen());
+    int b = makeTransparent(transparency, color.getBlue(), backgroundColor.getBlue());
+
+    return new Color(r, g, b);
+  }
+
+  private static int makeTransparent(double transparency, int channel, int backgroundChannel) {
+    final int result = (int)(backgroundChannel * (1 - transparency) + channel * transparency);
+    if (result < 0) {
+      return 0;
+    }
+    if (result > 255) {
+      return 255;
+    }
+    return result;
+  }
+
+  static Color[] getBaseColors() {
+    final ColorKey[] colorKeys = XmlTagTreeHighlightingColors.getColorKeys();
+    final Color[] colors = new Color[colorKeys.length];
+
+    final EditorColorsScheme colorsScheme = EditorColorsManager.getInstance().getGlobalScheme();
+
+    for (int i = 0; i < colors.length; i++) {
+      colors[i] = colorsScheme.getColor(colorKeys[i]);
+    }
+
+    return colors;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/DtdSelectioner.java b/xml/impl/src/com/intellij/codeInsight/editorActions/DtdSelectioner.java
new file mode 100644
index 0000000..9f884a8
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/DtdSelectioner.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttlistDecl;
+import com.intellij.psi.xml.XmlElementDecl;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.editor.Editor;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class DtdSelectioner implements ExtendWordSelectionHandler {
+  public boolean canSelect(PsiElement e) {
+    return e instanceof XmlAttlistDecl || e instanceof XmlElementDecl;
+  }
+
+  public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
+    PsiElement[] children = e.getChildren();
+
+    PsiElement first = null;
+    PsiElement last = null;
+    for (PsiElement child : children) {
+      if (child instanceof XmlToken) {
+        XmlToken token = (XmlToken)child;
+        if (token.getTokenType() == XmlTokenType.XML_TAG_END) {
+          last = token;
+          break;
+        }
+        if (token.getTokenType() == XmlTokenType.XML_ELEMENT_DECL_START ||
+            token.getTokenType() == XmlTokenType.XML_ATTLIST_DECL_START
+           ) {
+          first = token;
+        }
+      }
+    }
+
+    List<TextRange> result = new ArrayList<TextRange>(1);
+    if (first != null && last != null) {
+      final int offset = last.getTextRange().getEndOffset() + 1;
+        result.addAll(ExtendWordSelectionHandlerBase.expandToWholeLine(editorText,
+                                        new TextRange(first.getTextRange().getStartOffset(), offset < editorText.length() ? offset:editorText.length()),
+                                        false));
+    }
+
+    return result;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/EnterBetweenXmlTagsHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/EnterBetweenXmlTagsHandler.java
new file mode 100644
index 0000000..6637bef
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/EnterBetweenXmlTagsHandler.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegateAdapter;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+
+public class EnterBetweenXmlTagsHandler extends EnterHandlerDelegateAdapter {
+  public Result preprocessEnter(@NotNull final PsiFile file, @NotNull final Editor editor, @NotNull final Ref<Integer> caretOffset, @NotNull final Ref<Integer> caretAdvance,
+                                @NotNull final DataContext dataContext, final EditorActionHandler originalHandler) {
+    final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
+    
+    if (file instanceof XmlFile && isBetweenXmlTags(project, editor, file, caretOffset.get().intValue())) {
+      originalHandler.execute(editor, dataContext);
+      return Result.DefaultForceIndent;
+    }
+    return Result.Continue;
+  }
+
+  private static boolean isBetweenXmlTags(Project project, Editor editor, PsiFile file, int offset) {
+    if (offset == 0) return false;
+    CharSequence chars = editor.getDocument().getCharsSequence();
+    if (chars.charAt(offset - 1) != '>') return false;
+
+    EditorHighlighter highlighter = ((EditorEx)editor).getHighlighter();
+    HighlighterIterator iterator = highlighter.createIterator(offset - 1);
+    if (iterator.getTokenType() != XmlTokenType.XML_TAG_END) return false;
+    
+    if (isAtTheEndOfEmptyTag(project, editor, file, iterator)) {
+      return false;
+    }
+    
+    iterator.retreat();
+
+    int retrieveCount = 1;
+    while(!iterator.atEnd()) {
+      final IElementType tokenType = iterator.getTokenType();
+      if (tokenType == XmlTokenType.XML_END_TAG_START) return false;
+      if (tokenType == XmlTokenType.XML_START_TAG_START) break;
+      ++retrieveCount;
+      iterator.retreat();
+    }
+
+    for(int i = 0; i < retrieveCount; ++i) iterator.advance();
+    iterator.advance();
+    return !iterator.atEnd() && iterator.getTokenType() == XmlTokenType.XML_END_TAG_START;
+  }
+
+  private static boolean isAtTheEndOfEmptyTag(Project project, Editor editor, PsiFile file, HighlighterIterator iterator) {
+    if (iterator.getTokenType() != XmlTokenType.XML_TAG_END) {
+      return false;
+    }
+
+    PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
+    final PsiElement element = file.findElementAt(iterator.getStart());
+
+    if (element == null) {
+      return false;
+    }
+
+    final PsiElement parent = element.getParent();
+    return parent instanceof XmlTag &&
+           parent.getTextRange().getEndOffset() == iterator.getEnd();
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlQuoteHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlQuoteHandler.java
new file mode 100644
index 0000000..1c66926
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlQuoteHandler.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+
+/**
+ * @author peter
+*/
+public class HtmlQuoteHandler implements QuoteHandler {
+  private QuoteHandler myBaseQuoteHandler;
+
+  public HtmlQuoteHandler() {
+    this(new XmlQuoteHandler());
+  }
+
+  public HtmlQuoteHandler(QuoteHandler _baseHandler) {
+    myBaseQuoteHandler = _baseHandler;
+  }
+
+  public boolean isClosingQuote(HighlighterIterator iterator, int offset) {
+    if (myBaseQuoteHandler.isClosingQuote(iterator, offset)) return true;
+    return false;
+  }
+
+  public boolean isOpeningQuote(HighlighterIterator iterator, int offset) {
+    if (myBaseQuoteHandler.isOpeningQuote(iterator, offset)) return true;
+
+    return false;
+  }
+
+  public boolean hasNonClosedLiteral(Editor editor, HighlighterIterator iterator, int offset) {
+    if (myBaseQuoteHandler.hasNonClosedLiteral(editor,iterator, offset)) return true;
+
+    return false;
+  }
+
+  public boolean isInsideLiteral(HighlighterIterator iterator) {
+    if (myBaseQuoteHandler.isInsideLiteral(iterator)) return true;
+
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java b/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java
new file mode 100644
index 0000000..0bd36fb
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: mike
+ * Date: Jul 18, 2002
+ * Time: 10:30:17 PM
+ * To change template for new class use 
+ * Code Style | Class Templates options (Tools | IDE Options).
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.codeInsight.editorActions.wordSelection.AbstractWordSelectioner;
+import com.intellij.codeInsight.highlighting.BraceMatchingUtil;
+import com.intellij.ide.highlighter.HighlighterFactory;
+import com.intellij.lang.Language;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.HtmlUtil;
+
+import java.util.List;
+
+public class HtmlSelectioner extends AbstractWordSelectioner {
+
+  public boolean canSelect(PsiElement e) {
+    return canSelectElement(e);
+  }
+
+  static boolean canSelectElement(final PsiElement e) {
+    if (e instanceof XmlToken) {
+      return HtmlUtil.hasHtml(e.getContainingFile());
+    }
+    return false;
+  }
+
+  public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
+    List<TextRange> result;
+
+    if (!(e instanceof XmlToken) ||
+        XmlTokenSelectioner.shouldSelectToken((XmlToken)e) ||
+        ((XmlToken)e).getTokenType() == XmlTokenType.XML_DATA_CHARACTERS) {
+      result = super.select(e, editorText, cursorOffset, editor);
+    }
+    else {
+      result = ContainerUtil.newArrayList();
+    }
+
+    final PsiElement parent = e.getParent();
+    if (parent instanceof XmlComment) {
+      result.addAll(expandToWholeLine(editorText, parent.getTextRange(), true));
+    }
+
+    PsiFile psiFile = e.getContainingFile();
+    FileType fileType = psiFile.getVirtualFile().getFileType();
+
+    addAttributeSelection(result, e);
+    final FileViewProvider fileViewProvider = psiFile.getViewProvider();
+    for (Language lang : fileViewProvider.getLanguages()) {
+      final PsiFile langFile = fileViewProvider.getPsi(lang);
+      if (langFile != psiFile) addAttributeSelection(result, fileViewProvider.findElementAt(cursorOffset, lang));
+    }
+
+    EditorHighlighter highlighter = HighlighterFactory.createHighlighter(e.getProject(), psiFile.getVirtualFile());
+    highlighter.setText(editorText);
+
+    addTagSelection(editorText, cursorOffset, fileType, highlighter, result);
+
+    return result;
+  }
+
+  private static void addTagSelection(CharSequence editorText,
+                                      int cursorOffset,
+                                      FileType fileType,
+                                      EditorHighlighter highlighter,
+                                      List<TextRange> result) {
+    int start = cursorOffset;
+
+    while (true) {
+      if (start < 0) return;
+      HighlighterIterator i = highlighter.createIterator(start);
+      if (i.atEnd()) return;
+
+      while (true) {
+        if (i.getTokenType() == XmlTokenType.XML_START_TAG_START) break;
+        i.retreat();
+        if (i.atEnd()) return;
+      }
+
+      start = i.getStart();
+      final boolean matched = BraceMatchingUtil.matchBrace(editorText, fileType, i, true);
+
+      if (matched) {
+        final int tagEnd = i.getEnd();
+        result.add(new TextRange(start, tagEnd));
+
+        HighlighterIterator j = highlighter.createIterator(start);
+        while (!j.atEnd() && j.getTokenType() != XmlTokenType.XML_TAG_END) j.advance();
+        while (!i.atEnd() && i.getTokenType() != XmlTokenType.XML_END_TAG_START) i.retreat();
+
+        if (!i.atEnd() && !j.atEnd()) {
+          result.add(new TextRange(j.getEnd(), i.getStart()));
+        }
+        if (!j.atEnd()) {
+          result.add(new TextRange(start, j.getEnd()));
+        }
+        if (!i.atEnd()) {
+          result.add(new TextRange(i.getStart(), tagEnd));
+        }
+      }
+
+      start--;
+    }
+  }
+
+  private static void addAttributeSelection(List<TextRange> result, PsiElement e) {
+    final XmlAttribute attribute = PsiTreeUtil.getParentOfType(e, XmlAttribute.class);
+
+    if (attribute != null) {
+      result.add(attribute.getTextRange());
+      final XmlAttributeValue value = attribute.getValueElement();
+
+      if (value != null) {
+        final TextRange range = value.getTextRange();
+        result.add(range);
+        if (value.getFirstChild() != null &&
+            value.getFirstChild().getNode().getElementType() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+          result.add(new TextRange(range.getStartOffset() + 1, range.getEndOffset() - 1));
+        }
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlAutoPopupHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlAutoPopupHandler.java
new file mode 100644
index 0000000..97cbbce
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlAutoPopupHandler.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.codeInsight.AutoPopupController;
+import com.intellij.lang.Language;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Ref;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.util.XmlUtil;
+
+public class XmlAutoPopupHandler extends TypedHandlerDelegate {
+  public Result checkAutoPopup(final char charTyped, final Project project, final Editor editor, final PsiFile file) {
+    final boolean isXmlLikeFile = file.getLanguage() instanceof XMLLanguage || file.getViewProvider().getBaseLanguage() instanceof XMLLanguage;
+    boolean spaceInTag = isXmlLikeFile && charTyped == ' ';
+
+    if (spaceInTag) {
+      spaceInTag = false;
+      final PsiElement at = file.findElementAt(editor.getCaretModel().getOffset());
+
+      if (at != null) {
+        final PsiElement parent = at.getParent();
+        if (parent instanceof XmlTag) {
+          spaceInTag = true;
+        }
+      }
+    }
+
+    if ((charTyped == '<' || charTyped == '{' || charTyped == '/' || spaceInTag) && isXmlLikeFile) {
+      autoPopupXmlLookup(project, editor);
+      return Result.STOP;
+    }
+    return Result.CONTINUE;
+  }
+
+  public static void autoPopupXmlLookup(final Project project, final Editor editor){
+    AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, new Condition<PsiFile>() {
+      @Override
+      public boolean value(PsiFile file) {
+        int offset = editor.getCaretModel().getOffset();
+
+        PsiElement lastElement = InjectedLanguageUtil.findElementAtNoCommit(file, offset - 1);
+        if (lastElement instanceof PsiFile) { //the very end of an injected file
+          lastElement = file.findElementAt(offset - 1);
+        }
+        if (lastElement == null || !lastElement.isValid()) return false;
+
+        if (doCompleteIfNeeded(offset, file, lastElement)) {
+          return true;
+        }
+
+        FileViewProvider fileViewProvider = file.getViewProvider();
+        Language templateDataLanguage;
+
+        final PsiElement parent = lastElement.getParent();
+        if (fileViewProvider instanceof TemplateLanguageFileViewProvider &&
+            (templateDataLanguage = ((TemplateLanguageFileViewProvider)fileViewProvider).getTemplateDataLanguage()) != parent.getLanguage()) {
+          lastElement = fileViewProvider.findElementAt(offset - 1, templateDataLanguage);
+          if (lastElement == null || !lastElement.isValid()) return false;
+          return doCompleteIfNeeded(offset, file, lastElement);
+        }
+        return false;
+      }
+    });
+  }
+
+  private static boolean doCompleteIfNeeded(int offset, PsiFile file, PsiElement lastElement) {
+    final Ref<Boolean> isRelevantLanguage = new Ref<Boolean>();
+    final Ref<Boolean> isAnt = new Ref<Boolean>();
+    String text = lastElement.getText();
+    final int len = offset - lastElement.getTextRange().getStartOffset();
+    if (len < text.length()) {
+      text = text.substring(0, len);
+    }
+    if (text.equals("<") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) ||
+        text.equals(" ") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) ||
+        text.endsWith("${") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) && isAnt.get().booleanValue() ||
+        text.endsWith("@{") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) && isAnt.get().booleanValue() ||
+        text.endsWith("</") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt)) {
+      return true;
+    }
+
+    return false;
+  }
+
+  private static boolean isLanguageRelevant(final PsiElement element,
+                                            final PsiFile file,
+                                            final Ref<Boolean> isRelevantLanguage,
+                                            final Ref<Boolean> isAnt) {
+    Boolean isAntFile = isAnt.get();
+    if (isAntFile == null) {
+      isAntFile = XmlUtil.isAntFile(file);
+      isAnt.set(isAntFile);
+    }
+    Boolean result = isRelevantLanguage.get();
+    if (result == null) {
+      Language language = element.getLanguage();
+      PsiElement parent = element.getParent();
+      if (element instanceof PsiWhiteSpace && parent != null) {
+        language = parent.getLanguage();
+      }
+      result = language instanceof XMLLanguage || isAntFile.booleanValue();
+      isRelevantLanguage.set(result);
+    }
+    return result.booleanValue();
+  }
+
+
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlBasicWordSelectionFilter.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlBasicWordSelectionFilter.java
new file mode 100644
index 0000000..d17ddc0
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlBasicWordSelectionFilter.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlElement;
+
+/**
+ * @author yole
+ */
+public class XmlBasicWordSelectionFilter implements Condition<PsiElement> {
+  public boolean value(final PsiElement e) {
+    return !(e instanceof XmlToken) &&
+           !(e instanceof XmlElement);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlCDATAContentSelectioner.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlCDATAContentSelectioner.java
new file mode 100644
index 0000000..fe440e0
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlCDATAContentSelectioner.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.psi.impl.source.tree.CompositePsiElement;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.editor.Editor;
+
+import java.util.List;
+
+public class XmlCDATAContentSelectioner extends ExtendWordSelectionHandlerBase {
+  public boolean canSelect(PsiElement e) {
+    return e instanceof CompositePsiElement &&
+           ((CompositePsiElement)e).getElementType() == XmlElementType.XML_CDATA;
+  }
+
+  public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
+    List<TextRange> result = super.select(e, editorText, cursorOffset, editor);
+    PsiElement[] children = e.getChildren();
+
+    PsiElement first = null;
+    PsiElement last = null;
+    for (PsiElement child : children) {
+      if (child instanceof XmlToken) {
+        XmlToken token = (XmlToken)child;
+        if (token.getTokenType() == XmlTokenType.XML_CDATA_START) {
+          first = token.getNextSibling();
+        }
+        if (token.getTokenType() == XmlTokenType.XML_CDATA_END) {
+          last = token.getPrevSibling();
+          break;
+        }
+      }
+    }
+
+    if (first != null && last != null) {
+      result.addAll(expandToWholeLine(editorText,
+                                      new TextRange(first.getTextRange().getStartOffset(),
+                                                    last.getTextRange().getEndOffset()),
+                                      false));
+    }
+
+    return result;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlCopyPastePreProcessor.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlCopyPastePreProcessor.java
new file mode 100644
index 0000000..70c0429
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlCopyPastePreProcessor.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.RawText;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.tree.TreeUtil;
+import com.intellij.psi.impl.source.xml.behavior.EncodeEachSymbolPolicy;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlText;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlCopyPastePreProcessor implements CopyPastePreProcessor {
+
+  private static final EncodeEachSymbolPolicy ENCODE_EACH_SYMBOL_POLICY = new EncodeEachSymbolPolicy();
+
+  @Nullable
+  public String preprocessOnCopy(PsiFile file, int[] startOffsets, int[] endOffsets, String text) {
+    return null;
+  }
+
+  public String preprocessOnPaste(Project project, PsiFile file, Editor editor, String text, RawText rawText) {
+    final Document document = editor.getDocument();
+    PsiDocumentManager.getInstance(project).commitDocument(document);
+    int caretOffset = editor.getCaretModel().getOffset();
+    PsiElement element = PsiUtilCore.getElementAtOffset(file, caretOffset);
+
+    ASTNode node = element.getNode();
+    if (node != null) {
+      boolean hasMarkup = text.indexOf('>') >= 0 || text.indexOf('<') >= 0;
+      if (element.getTextOffset() == caretOffset &&
+          node.getElementType() == XmlElementType.XML_END_TAG_START &&
+          node.getTreePrev().getElementType() == XmlElementType.XML_TAG_END) {
+
+         return hasMarkup ? text : encode(text, element);
+      } else {
+        XmlElement parent = PsiTreeUtil.getParentOfType(element, XmlText.class, XmlAttributeValue.class);
+        if (parent != null) {
+          if (parent instanceof XmlText && hasMarkup) {
+            return text;
+          }
+
+          if (TreeUtil.findParent(node, XmlElementType.XML_CDATA) == null &&
+              TreeUtil.findParent(node, XmlElementType.XML_COMMENT) == null) {
+            return encode(text, element);
+          }
+        }
+      }
+    }
+    return text;
+  }
+
+  private static String encode(String text, PsiElement element) {
+    ASTNode astNode = ENCODE_EACH_SYMBOL_POLICY.encodeXmlTextContents(text, element);
+    return astNode.getTreeParent().getText();
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlElementSelectioner.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlElementSelectioner.java
new file mode 100644
index 0000000..a0b5121
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlElementSelectioner.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+
+class XmlElementSelectioner extends ExtendWordSelectionHandlerBase {
+  public boolean canSelect(PsiElement e) {
+    return e instanceof XmlAttribute || e instanceof XmlAttributeValue;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java
new file mode 100644
index 0000000..b3bf0c2
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.application.options.editor.WebEditorOptions;
+import com.intellij.codeInsight.highlighting.BraceMatchingUtil;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.impl.source.xml.XmlTokenImpl;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementDescriptorWithCDataContent;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+
+public class XmlGtTypedHandler extends TypedHandlerDelegate {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.TypedHandler");
+
+  public Result beforeCharTyped(final char c, final Project project, final Editor editor, final PsiFile editedFile, final FileType fileType) {
+    final WebEditorOptions webEditorOptions = WebEditorOptions.getInstance();
+    if (c == '>' && webEditorOptions != null && webEditorOptions.isAutomaticallyInsertClosingTag()
+        && (editedFile.getLanguage() instanceof XMLLanguage || editedFile.getViewProvider().getBaseLanguage() instanceof XMLLanguage)) {
+      PsiDocumentManager.getInstance(project).commitAllDocuments();
+
+      PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+      FileViewProvider provider = editedFile.getViewProvider();
+      int offset = editor.getCaretModel().getOffset();
+
+      PsiElement element, elementAtCaret = null;
+
+      if (offset < editor.getDocument().getTextLength()) {
+        elementAtCaret = element = provider.findElementAt(offset, XMLLanguage.class);
+        
+        if (!(element instanceof PsiWhiteSpace)) {
+          boolean nonAcceptableDelimiter = true;
+
+          if (element instanceof XmlToken) {
+            IElementType tokenType = ((XmlToken)element).getTokenType();
+
+            if (tokenType == XmlTokenType.XML_START_TAG_START || tokenType == XmlTokenType.XML_END_TAG_START) {
+              if (offset > 0) {
+                PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
+
+                if (previousElement instanceof XmlToken) {
+                  tokenType = ((XmlToken)previousElement).getTokenType();
+                  element = previousElement;
+                  nonAcceptableDelimiter = false;
+                }
+              }
+            } else if (tokenType == XmlTokenType.XML_NAME) {
+              if (element.getNextSibling() instanceof PsiErrorElement) {
+                nonAcceptableDelimiter = false;
+              }
+            }
+
+            if (tokenType == XmlTokenType.XML_TAG_END ||
+                tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END && element.getTextOffset() == offset - 1
+               ) {
+              editor.getCaretModel().moveToOffset(offset + 1);
+              editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+              return Result.STOP;
+            }
+          }
+          if (nonAcceptableDelimiter) return Result.CONTINUE;
+        } else {
+          // check if right after empty end
+          PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
+          if (previousElement instanceof XmlToken) {
+            final IElementType tokenType = ((XmlToken)previousElement).getTokenType();
+
+            if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END) {
+              return Result.STOP;
+            }
+          }
+        }
+
+        PsiElement parent = element.getParent();
+        if (parent instanceof XmlText) {
+          final String text = parent.getText();
+          // check /
+          final int index = offset - parent.getTextOffset() - 1;
+
+          if (index >= 0 && text.charAt(index)=='/') {
+            return Result.CONTINUE; // already seen /
+          }
+          element = parent.getPrevSibling();
+        } else if (parent instanceof XmlTag && !(element.getPrevSibling() instanceof XmlTag)) {
+          element = parent;
+        } else if (parent instanceof XmlAttributeValue) {
+          element = parent;
+        }
+      }
+      else {
+        element = provider.findElementAt(editor.getDocument().getTextLength() - 1, XMLLanguage.class);
+        if (element == null) return Result.CONTINUE;
+        element = element.getParent();
+      }
+
+      if (offset > 0 && offset <= editor.getDocument().getTextLength()) {
+        if (editor.getDocument().getCharsSequence().charAt(offset - 1) == '/') { // Some languages (e.g. GSP) allow character '/' in tag name.
+          return Result.CONTINUE;
+        }
+      }
+
+      if (element instanceof XmlAttributeValue) {
+        element = element.getParent().getParent();
+      }
+
+      while(element instanceof PsiWhiteSpace) element = element.getPrevSibling();
+      if (element instanceof XmlDocument) {   // hack for closing tags in RHTML
+        element = element.getLastChild();
+      }
+      if (element == null) return Result.CONTINUE;
+      if (!(element instanceof XmlTag)) {
+        if (element instanceof XmlTokenImpl &&
+            element.getPrevSibling() !=null &&
+            element.getPrevSibling().getText().equals("<")
+           ) {
+          // tag is started and there is another text in the end
+          editor.getDocument().insertString(offset, "</" + element.getText() + ">");
+        }
+        return Result.CONTINUE;
+      }
+
+      XmlTag tag = (XmlTag)element;
+      if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null) return Result.CONTINUE;
+      if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null) return Result.CONTINUE;
+      final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START);
+      if (startToken == null || !startToken.getText().equals("<")) return Result.CONTINUE;
+
+      String name = tag.getName();
+      if (elementAtCaret instanceof XmlToken && ((XmlToken)elementAtCaret).getTokenType() == XmlTokenType.XML_NAME) {
+        name = name.substring(0, offset - elementAtCaret.getTextOffset());
+      }
+      if (tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(name)) return Result.CONTINUE;
+      if ("".equals(name)) return Result.CONTINUE;
+
+      int tagOffset = tag.getTextRange().getStartOffset();
+
+      final XmlToken nameToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_NAME);
+      if (nameToken != null && nameToken.getTextRange().getStartOffset() > offset) return Result.CONTINUE;
+
+      HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(tagOffset);
+      if (BraceMatchingUtil.matchBrace(editor.getDocument().getCharsSequence(), editedFile.getFileType(), iterator, true,true)) {
+        PsiElement parent = tag.getParent();
+        boolean hasBalance = true;
+        
+        while(parent instanceof XmlTag && name.equals(((XmlTag)parent).getName())) {
+          ASTNode astNode = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode());
+          if (astNode == null) {
+            hasBalance = false;
+            break;
+          }
+
+          parent = parent.getParent();
+        }
+        
+        if (hasBalance) {
+          hasBalance = false;
+          for(ASTNode node=parent.getNode().getLastChildNode(); node != null; node = node.getTreePrev()) {
+            ASTNode leaf = node;
+            if (leaf.getElementType() == TokenType.ERROR_ELEMENT) {
+              ASTNode firstChild = leaf.getFirstChildNode();
+              if (firstChild != null) leaf = firstChild;
+              else {
+                PsiElement psiElement = PsiTreeUtil.nextLeaf(leaf.getPsi());
+                leaf = psiElement != null ? psiElement.getNode() : null;
+              }
+              if (leaf != null && leaf.getElementType() == TokenType.WHITE_SPACE) {
+                PsiElement psiElement = PsiTreeUtil.nextLeaf(leaf.getPsi());
+                if (psiElement != null) leaf = psiElement.getNode();
+              }
+            }
+            
+            if (leaf != null && leaf.getElementType() == XmlTokenType.XML_END_TAG_START) {
+              ASTNode treeNext = leaf.getTreeNext();
+              IElementType treeNextType;
+              if (treeNext != null && 
+                  ((treeNextType = treeNext.getElementType()) == XmlTokenType.XML_NAME ||
+                   treeNextType == XmlTokenType.XML_TAG_NAME
+                  )
+                ) {
+                if (name.equals(treeNext.getText())) {
+                  ASTNode parentEndName = parent instanceof XmlTag ?
+                                          XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode()):null;
+                  hasBalance = !(parent instanceof XmlTag) || 
+                    parentEndName != null && !parentEndName.getText().equals(name);
+                  break;
+                }
+              }
+            }
+          }
+        }
+        
+        if (hasBalance) return Result.CONTINUE; 
+      }
+
+      TextRange cdataReformatRange = null;
+      final XmlElementDescriptor descriptor = tag.getDescriptor();
+
+      if (descriptor instanceof XmlElementDescriptorWithCDataContent) {
+        final XmlElementDescriptorWithCDataContent cDataContainer = (XmlElementDescriptorWithCDataContent)descriptor;
+
+        if (cDataContainer.requiresCdataBracesInContext(tag)) {
+          int rangeStart = offset;
+          @NonNls final String cDataStart = "><![CDATA[";
+          final String inserted = cDataStart + "\n]]>";
+          editor.getDocument().insertString(offset, inserted);
+          final int newoffset = offset + cDataStart.length();
+          editor.getCaretModel().moveToOffset(newoffset);
+          offset += inserted.length();
+          cdataReformatRange = new TextRange(rangeStart, offset + 1);
+        }
+      }
+
+      editor.getDocument().insertString(offset, "</" + name + ">");
+
+      if (cdataReformatRange != null) {
+        PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
+        try {          
+          CodeStyleManager.getInstance(project).reformatText(file, cdataReformatRange.getStartOffset(), cdataReformatRange.getEndOffset());
+        }
+        catch (IncorrectOperationException e) {
+          LOG.error(e);
+        }
+      }
+      return cdataReformatRange != null ? Result.STOP : Result.CONTINUE;
+    }
+    return Result.CONTINUE;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlLineSelectioner.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlLineSelectioner.java
new file mode 100644
index 0000000..76a25de
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlLineSelectioner.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.codeInsight.editorActions.wordSelection.PlainTextLineSelectioner;
+
+import java.util.List;
+
+/**
+ * @author yole
+ */
+public class XmlLineSelectioner extends ExtendWordSelectionHandlerBase {
+  public boolean canSelect(final PsiElement e) {
+    return e instanceof XmlToken && ((XmlToken)e).getTokenType() == XmlTokenType.XML_DATA_CHARACTERS;
+  }
+
+  @Override
+  public List<TextRange> select(final PsiElement e, final CharSequence editorText, final int cursorOffset, final Editor editor) {
+    return PlainTextLineSelectioner.selectPlainTextLine(e, editorText, cursorOffset);
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlQuoteHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlQuoteHandler.java
new file mode 100644
index 0000000..1f87de2
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlQuoteHandler.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.psi.xml.XmlTokenType;
+
+/**
+ * @author peter
+*/
+public class XmlQuoteHandler implements QuoteHandler {
+  public boolean isClosingQuote(HighlighterIterator iterator, int offset) {
+    return iterator.getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;
+  }
+
+  public boolean isOpeningQuote(HighlighterIterator iterator, int offset) {
+    return iterator.getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+  }
+
+  public boolean hasNonClosedLiteral(Editor editor, HighlighterIterator iterator, int offset) {
+    return true;
+  }
+
+  public boolean isInsideLiteral(HighlighterIterator iterator) {
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java
new file mode 100644
index 0000000..8794fe0
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorModificationUtil;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.tree.TreeUtil;
+import com.intellij.psi.templateLanguages.OuterLanguageElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.xml.util.XmlUtil;
+
+public class XmlSlashTypedHandler extends TypedHandlerDelegate {
+  public Result beforeCharTyped(final char c, final Project project, final Editor editor, final PsiFile editedFile, final FileType fileType) {
+    if ((editedFile.getLanguage() instanceof XMLLanguage || editedFile.getViewProvider().getBaseLanguage() instanceof XMLLanguage) && c == '/') {
+      PsiDocumentManager.getInstance(project).commitAllDocuments();
+
+      PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+      final int offset = editor.getCaretModel().getOffset();
+      FileViewProvider provider = file.getViewProvider();
+      PsiElement element = provider.findElementAt(offset, XMLLanguage.class);
+
+      if (element instanceof XmlToken) {
+        final IElementType tokenType = ((XmlToken)element).getTokenType();
+
+        if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END &&
+            offset == element.getTextOffset()
+           ) {
+          editor.getCaretModel().moveToOffset(offset + 1);
+          editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+          return Result.STOP;
+        } else if (tokenType == XmlTokenType.XML_TAG_END &&
+                   offset == element.getTextOffset()
+                  ) {
+          final ASTNode parentNode = element.getParent().getNode();
+          final ASTNode child = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(parentNode);
+
+          if (child != null && offset + 1 == child.getTextRange().getStartOffset()) {
+            editor.getDocument().replaceString(offset + 1, parentNode.getTextRange().getEndOffset(),"");
+          }
+        }
+      }
+    }
+    return Result.CONTINUE;
+  }
+
+  public Result charTyped(final char c, final Project project, final Editor editor, final PsiFile editedFile) {
+    if ((editedFile.getLanguage() instanceof XMLLanguage || editedFile.getViewProvider().getBaseLanguage() instanceof XMLLanguage) && c == '/') {
+      PsiDocumentManager.getInstance(project).commitAllDocuments();
+
+      PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+      FileViewProvider provider = file.getViewProvider();
+      final int offset = editor.getCaretModel().getOffset();
+      PsiElement element = provider.findElementAt(offset - 1, XMLLanguage.class);
+      if (element == null) return Result.CONTINUE;
+      if (!(element.getLanguage() instanceof XMLLanguage)) return Result.CONTINUE;
+
+      ASTNode prevLeaf = element.getNode();
+      final String prevLeafText = prevLeaf != null ? prevLeaf.getText():null;
+      if (prevLeaf != null && !"/".equals(prevLeafText)) {
+        if (!"/".equals(prevLeafText.trim())) return Result.CONTINUE;
+      }
+      while((prevLeaf = TreeUtil.prevLeaf(prevLeaf)) != null && prevLeaf.getElementType() == XmlTokenType.XML_WHITE_SPACE);
+      if(prevLeaf instanceof OuterLanguageElement) {
+        element = file.getViewProvider().findElementAt(offset - 1, file.getLanguage());
+        prevLeaf = element.getNode();
+        while((prevLeaf = TreeUtil.prevLeaf(prevLeaf)) != null && prevLeaf.getElementType() == XmlTokenType.XML_WHITE_SPACE);
+      }
+      if(prevLeaf == null) return Result.CONTINUE;
+
+      XmlTag tag = PsiTreeUtil.getParentOfType(prevLeaf.getPsi(), XmlTag.class);
+      if(tag == null) { // prevLeaf maybe in one tree and element in another
+        PsiElement element2 = provider.findElementAt(prevLeaf.getStartOffset(), XMLLanguage.class);
+        tag = PsiTreeUtil.getParentOfType(element2, XmlTag.class);
+        if (tag == null) return Result.CONTINUE;
+      }
+
+      final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START);
+      if (startToken == null || !startToken.getText().equals("<")) return Result.CONTINUE;
+      if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null) return Result.CONTINUE;
+      if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null) return Result.CONTINUE;
+      if (PsiTreeUtil.getParentOfType(element, XmlAttributeValue.class) != null) return Result.CONTINUE;
+
+      EditorModificationUtil.insertStringAtCaret(editor, ">");
+      return Result.STOP;
+    }
+    return Result.CONTINUE;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagSelectioner.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagSelectioner.java
new file mode 100644
index 0000000..cc05cea
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagSelectioner.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.xml.*;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.editor.Editor;
+
+import java.util.List;
+
+public class XmlTagSelectioner extends ExtendWordSelectionHandlerBase {
+  public boolean canSelect(PsiElement e) {
+    return e instanceof XmlTag;
+  }
+
+  public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
+    List<TextRange> result = super.select(e, editorText, cursorOffset, editor);
+    PsiElement[] children = e.getChildren();
+
+    addTagContentSelection(children, result, editorText);
+
+    PsiElement prev = e.getPrevSibling();
+    while (prev instanceof PsiWhiteSpace || prev instanceof XmlText || prev instanceof XmlComment) {
+      if (prev instanceof XmlText && prev.getText().trim().length() > 0) break;
+      if (prev instanceof XmlComment) {
+        result.addAll(expandToWholeLine(editorText,
+                                        new TextRange(prev.getTextRange().getStartOffset(),
+                                                      e.getTextRange().getEndOffset()),
+                                        false));
+      }
+      prev = prev.getPrevSibling();
+    }
+
+    return result;
+  }
+
+  private static void addTagContentSelection(final PsiElement[] children, final List<TextRange> result, final CharSequence editorText) {
+    PsiElement first = null;
+    PsiElement last = null;
+    for (PsiElement child : children) {
+      if (child instanceof XmlToken) {
+        XmlToken token = (XmlToken)child;
+        if (token.getTokenType() == XmlTokenType.XML_TAG_END) {
+          first = token.getNextSibling();
+        }
+        if (token.getTokenType() == XmlTokenType.XML_END_TAG_START) {
+          last = token.getPrevSibling();
+          break;
+        }
+      }
+    }
+
+    if (first != null && last != null) {
+      result.addAll(expandToWholeLine(editorText,
+                                      new TextRange(first.getTextRange().getStartOffset(),
+                                                    last.getTextRange().getEndOffset()),
+                                      false));
+    }
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTokenSelectioner.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTokenSelectioner.java
new file mode 100644
index 0000000..c7e4b51
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTokenSelectioner.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.editor.Editor;
+
+import java.util.List;
+import java.util.ArrayList;
+
+class XmlTokenSelectioner extends ExtendWordSelectionHandlerBase {
+  public boolean canSelect(PsiElement e) {
+    return e instanceof XmlToken &&
+           !HtmlSelectioner.canSelectElement(e);
+  }
+
+  public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
+    XmlToken token = (XmlToken)e;
+
+    if (shouldSelectToken(token)) {
+      List<TextRange> ranges = super.select(e, editorText, cursorOffset, editor);
+      SelectWordUtil.addWordSelection(editor.getSettings().isCamelWords(), editorText, cursorOffset, ranges);
+      return ranges;
+    }
+    else {
+      List<TextRange> result = new ArrayList<TextRange>();
+      SelectWordUtil.addWordSelection(editor.getSettings().isCamelWords(), editorText, cursorOffset, result);
+      return result;
+    }
+  }
+
+  static boolean shouldSelectToken(final XmlToken token) {
+    return token.getTokenType() != XmlTokenType.XML_DATA_CHARACTERS &&
+          token.getTokenType() != XmlTokenType.XML_START_TAG_START &&
+          token.getTokenType() != XmlTokenType.XML_END_TAG_START &&
+          token.getTokenType() != XmlTokenType.XML_EMPTY_ELEMENT_END &&
+          token.getTokenType() != XmlTokenType.XML_TAG_END;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMover.java b/xml/impl/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMover.java
new file mode 100644
index 0000000..3ef95ed
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMover.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions.moveUpDown;
+
+import com.intellij.lang.injection.InjectedLanguageManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.impl.source.xml.TagNameReference;
+import com.intellij.psi.impl.source.xml.XmlDocumentImpl;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlText;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+class XmlMover extends LineMover {
+  //private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.actions.moveUpDown.XmlMover");
+
+  public boolean checkAvailable(@NotNull final Editor editor, @NotNull final PsiFile file, @NotNull final MoveInfo info, final boolean down) {
+    if (!(file instanceof XmlFile)) {
+      return false;
+    }
+    if (!super.checkAvailable(editor, file, info, down)) return false;
+
+    // updated moved range end to cover multiline tag start
+    final Document document = editor.getDocument();
+    int movedLineStart = document.getLineStartOffset(info.toMove.startLine);
+    final int movedLineEnd = document.getLineEndOffset(info.toMove.endLine - 1);
+
+    PsiElement movedEndElement = file.findElementAt(movedLineEnd);
+    if (movedEndElement instanceof PsiWhiteSpace) movedEndElement = PsiTreeUtil.prevLeaf(movedEndElement);
+    PsiElement movedStartElement = file.findElementAt(movedLineStart);
+    if (movedStartElement instanceof PsiWhiteSpace) movedStartElement = PsiTreeUtil.nextLeaf(movedStartElement);
+
+    if (movedEndElement == null || movedStartElement == null) return false;
+    final PsiNamedElement namedParentAtEnd = PsiTreeUtil.getParentOfType(movedEndElement, PsiNamedElement.class);
+    final PsiNamedElement namedParentAtStart = PsiTreeUtil.getParentOfType(movedStartElement, PsiNamedElement.class);
+
+    if (checkInjections(movedEndElement, movedStartElement)) return false;
+
+    XmlTag nearestTag = PsiTreeUtil.getParentOfType(movedStartElement, XmlTag.class);
+    if (nearestTag != null &&
+        ( "script".equals(nearestTag.getLocalName()) ||
+          (nearestTag instanceof HtmlTag && "script".equalsIgnoreCase(nearestTag.getLocalName()))
+        )
+      ) {
+      return false;
+    }
+
+    PsiNamedElement movedParent = null;
+
+    if (namedParentAtEnd == namedParentAtStart) movedParent = namedParentAtEnd;
+    else if (namedParentAtEnd instanceof XmlAttribute && namedParentAtStart instanceof XmlTag && namedParentAtEnd.getParent() == namedParentAtStart) {
+      movedParent = namedParentAtStart;
+    } else if (namedParentAtStart instanceof XmlAttribute && namedParentAtEnd instanceof XmlTag && namedParentAtStart.getParent() == namedParentAtEnd) {
+      movedParent = namedParentAtEnd;
+    }
+
+    if (movedParent == null) {
+      return false;
+    }
+
+    final TextRange textRange = movedParent.getTextRange();
+
+    if (movedParent instanceof XmlTag) {
+      final XmlTag tag = (XmlTag)movedParent;
+      PsiElement parent = tag.getParent();
+      if (!(parent instanceof XmlTag) && PsiTreeUtil.getChildrenOfType(parent, XmlTag.class).length < 2) {
+        // the only top-level tag
+        return info.prohibitMove();
+      }
+      final TextRange valueRange = tag.getValue().getTextRange();
+      final int valueStart = valueRange.getStartOffset();
+
+      if (movedLineStart < valueStart && valueStart + 1 < document.getTextLength()) {
+        movedLineStart = updateMovedRegionEnd(document, movedLineStart, valueStart + 1, info, down);
+      }
+      if (movedLineStart < valueStart) {
+        movedLineStart = updateMovedRegionStart(document, movedLineStart, tag.getTextRange().getStartOffset(), info, down);
+      }
+    } else if (movedParent instanceof XmlAttribute) {
+      final int endOffset = textRange.getEndOffset() + 1;
+      if (endOffset < document.getTextLength()) movedLineStart = updateMovedRegionEnd(document, movedLineStart, endOffset, info, down);
+      movedLineStart = updateMovedRegionStart(document, movedLineStart, textRange.getStartOffset(), info, down);
+    }
+
+    final TextRange moveDestinationRange = new TextRange(
+      document.getLineStartOffset(info.toMove2.startLine),
+      document.getLineStartOffset(info.toMove2.endLine) - 1
+    );
+
+    if (movedParent instanceof XmlAttribute) {
+      final XmlTag parent = ((XmlAttribute)movedParent).getParent();
+
+      if (parent != null) {
+        final TextRange valueRange = parent.getValue().getTextRange();
+
+        // Do not move attributes out of tags
+        if ( (down && moveDestinationRange.getEndOffset() >= valueRange.getStartOffset()) ||
+             (!down && moveDestinationRange.getStartOffset() <= parent.getTextRange().getStartOffset())
+          ) {
+          return info.prohibitMove();
+        }
+      }
+    }
+
+    if (down) {
+      PsiElement updatedElement = file.findElementAt(moveDestinationRange.getEndOffset());
+      if (updatedElement instanceof PsiWhiteSpace) updatedElement = PsiTreeUtil.prevLeaf(updatedElement);
+
+      if (updatedElement != null) {
+        final PsiNamedElement targetParent = PsiTreeUtil.getParentOfType(updatedElement, movedParent.getClass());
+
+        if (targetParent instanceof XmlTag) {
+          if (targetParent == movedParent) return false;
+          if (moveTags(info, (XmlTag)movedParent, (XmlTag)targetParent, down)) return true;
+
+          final XmlTag tag = (XmlTag)targetParent;
+          final int offset = tag.isEmpty() ? tag.getTextRange().getStartOffset() : tag.getValue().getTextRange().getStartOffset();
+          updatedMovedIntoEnd(document, info, offset);
+          if (tag.isEmpty()) {
+            info.toMove2 = new LineRange(targetParent);
+          }
+        } else if (targetParent instanceof XmlAttribute) {
+          updatedMovedIntoEnd(document, info, targetParent.getTextRange().getEndOffset());
+        }
+      }
+    } else {
+      PsiElement updatedElement = file.findElementAt(moveDestinationRange.getStartOffset());
+      if (updatedElement instanceof PsiWhiteSpace) updatedElement = PsiTreeUtil.nextLeaf(updatedElement);
+
+      if (updatedElement != null) {
+        final PsiNamedElement targetParent = PsiTreeUtil.getParentOfType(updatedElement, movedParent.getClass());
+
+        if (targetParent instanceof XmlTag) {
+          final XmlTag tag = (XmlTag)targetParent;
+          final TextRange tagValueRange = tag.getValue().getTextRange();
+
+          // We need to update destination range to jump over tag start
+          final XmlTag[] subtags = tag.getSubTags();
+          if ((tagValueRange.contains(movedLineStart) && subtags.length > 0 && subtags[0] == movedParent) ||
+              ( tagValueRange.getLength() == 0 && tag.getTextRange().intersects(moveDestinationRange))
+             ) {
+            final int line = document.getLineNumber(tag.getTextRange().getStartOffset());
+            final LineRange toMove2 = info.toMove2;
+            info.toMove2 = new LineRange(Math.min(line, toMove2.startLine), toMove2.endLine);
+          }
+          if (targetParent == movedParent) return false;
+          if (moveTags(info, (XmlTag)movedParent, (XmlTag)targetParent, down)) return true;
+
+        } else if (targetParent instanceof XmlAttribute) {
+          final int line = document.getLineNumber(targetParent.getTextRange().getStartOffset());
+          final LineRange toMove2 = info.toMove2;
+          info.toMove2 = new LineRange(Math.min(line, toMove2.startLine), toMove2.endLine);
+        }
+      }
+    }
+
+    if (movedParent instanceof XmlTag) {
+      // it's quite simple after all...
+      info.toMove = new LineRange(movedParent);
+    }
+    return true;
+  }
+
+  private static boolean moveTags(MoveInfo info, XmlTag moved, XmlTag target, boolean down) {
+    if (target.getParent() == moved) {
+      // we are going to jump into our own children
+      // this can mean that target computed incorrectly
+      XmlTag next = down ? PsiTreeUtil.getNextSiblingOfType(moved, XmlTag.class) :
+                           PsiTreeUtil.getPrevSiblingOfType(moved, XmlTag.class);
+      if (next == null) return info.prohibitMove();
+      info.toMove = new LineRange(moved);
+      info.toMove2 = new LineRange(next);
+      return true;
+    }
+    else if (moved.getParent() == target) {
+      return false;
+    }
+
+    LineRange targetRange = new LineRange(target);
+    if (targetRange.contains(info.toMove2)) {
+      // we are going to jump into sibling tag
+      XmlElementDescriptor descriptor = moved.getDescriptor();
+      if (descriptor == null) return false;
+      XmlNSDescriptor nsDescriptor = descriptor.getNSDescriptor();
+      if (nsDescriptor == null) return false;
+      XmlFile descriptorFile = nsDescriptor.getDescriptorFile();
+      if (descriptorFile == null || XmlDocumentImpl.isAutoGeneratedSchema(descriptorFile)) return false;
+      if (!TagNameReference.couldContain(target, moved)) {
+        info.toMove = new LineRange(moved);
+        info.toMove2 = targetRange;
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  private static boolean checkInjections(PsiElement movedEndElement, PsiElement movedStartElement) {
+    final XmlText text = PsiTreeUtil.getParentOfType(movedStartElement, XmlText.class);
+    final XmlText text2 = PsiTreeUtil.getParentOfType(movedEndElement, XmlText.class);
+
+    // Let's do not care about injections for this mover
+    if ( ( text != null && InjectedLanguageManager.getInstance(text.getProject()).getInjectedPsiFiles(text) != null) ||
+         ( text2 != null && InjectedLanguageManager.getInstance(text2.getProject()).getInjectedPsiFiles(text2) != null)) {
+      return true;
+    }
+    return false;
+  }
+
+  private static void updatedMovedIntoEnd(final Document document, @NotNull final MoveInfo info, final int offset) {
+    if (offset + 1 < document.getTextLength()) {
+      final int line = document.getLineNumber(offset + 1);
+      final LineRange toMove2 = info.toMove2;
+      if (toMove2 == null) return;
+      info.toMove2 = new LineRange(toMove2.startLine, Math.min(Math.max(line, toMove2.endLine), document.getLineCount() - 1));
+    }
+  }
+
+  private static int updateMovedRegionStart(final Document document,
+                                            int movedLineStart,
+                                            final int offset,
+                                            @NotNull final MoveInfo info,
+                                            final boolean down) {
+    final int line = document.getLineNumber(offset);
+    final LineRange toMove = info.toMove;
+    int delta = toMove.startLine - line;
+    info.toMove = new LineRange(Math.min(line, toMove.startLine), toMove.endLine);
+
+    // update moved range
+    if (delta > 0 && !down) {
+      final LineRange toMove2 = info.toMove2;
+      info.toMove2 = new LineRange(toMove2.startLine - delta, toMove2.endLine - delta);
+      movedLineStart = document.getLineStartOffset(toMove.startLine);
+    }
+    return movedLineStart;
+  }
+
+  private static int updateMovedRegionEnd(final Document document,
+                                          int movedLineStart,
+                                          final int valueStart,
+                                          @NotNull final MoveInfo info,
+                                          final boolean down) {
+    final int line = document.getLineNumber(valueStart);
+    final LineRange toMove = info.toMove;
+    int delta = line - toMove.endLine;
+    info.toMove = new LineRange(toMove.startLine, Math.max(line, toMove.endLine));
+
+    // update moved range
+    if (delta > 0 && down) {
+      final LineRange toMove2 = info.toMove2;
+      info.toMove2 = new LineRange(toMove2.startLine + delta, Math.min(toMove2.endLine + delta, document.getLineCount() - 1));
+      movedLineStart = document.getLineStartOffset(toMove.startLine);
+    }
+    return movedLineStart;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/folding/impl/XmlElementSignatureProvider.java b/xml/impl/src/com/intellij/codeInsight/folding/impl/XmlElementSignatureProvider.java
new file mode 100644
index 0000000..2d7f7e0
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/folding/impl/XmlElementSignatureProvider.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.folding.impl;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.StringTokenizer;
+
+/**
+ * @author yole
+ */
+public class XmlElementSignatureProvider extends AbstractElementSignatureProvider {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.folding.impl.XmlElementSignatureProvider");
+
+  public String getSignature(@NotNull PsiElement element) {
+    if (element instanceof XmlTag) {
+      XmlTag tag = (XmlTag)element;
+      PsiElement parent = tag.getParent();
+
+      StringBuilder buffer = new StringBuilder();
+      buffer.append("tag").append(ELEMENT_TOKENS_SEPARATOR);
+      String name = tag.getName();
+      buffer.append(name.length() == 0 ? "<unnamed>" : name);
+
+      buffer.append(ELEMENT_TOKENS_SEPARATOR);
+      buffer.append(getChildIndex(tag, parent, name, XmlTag.class));
+
+      if (parent instanceof XmlTag) {
+        String parentSignature = getSignature(parent);
+        buffer.append(";");
+        buffer.append(parentSignature);
+      }
+
+      return buffer.toString();
+    }
+    return null;
+  }
+
+  @Override
+  protected PsiElement restoreBySignatureTokens(@NotNull PsiFile file,
+                                                @NotNull PsiElement parent,
+                                                @NotNull String type,
+                                                @NotNull StringTokenizer tokenizer,
+                                                @Nullable StringBuilder processingInfoStorage)
+  {
+    if (type.equals("tag")) {
+      String name = tokenizer.nextToken();
+
+      if (parent instanceof XmlFile) {
+        parent = ((XmlFile)parent).getDocument();
+        if (parent == null) {
+          return null;
+        }
+      }
+
+      try {
+        int index = Integer.parseInt(tokenizer.nextToken());
+        PsiElement result = restoreElementInternal(parent, name, index, XmlTag.class);
+
+        if (result == null &&
+            file.getFileType() == StdFileTypes.JSP) {
+          //TODO: FoldingBuilder API, psi roots, etc?
+          if (parent instanceof XmlDocument) {
+            // html tag, not found in jsp tree
+            result = restoreElementInternal(HtmlUtil.getRealXmlDocument((XmlDocument)parent), name, index, XmlTag.class);
+          }
+          else if (name.equals("<unnamed>") && parent != null) {
+            // scriplet/declaration missed because null name
+            result = restoreElementInternal(parent, "", index, XmlTag.class);
+          }
+        }
+
+        return result;
+      }
+      catch (NumberFormatException e) {
+        LOG.error(e);
+        return null;
+      }
+    }
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java b/xml/impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java
new file mode 100644
index 0000000..7b8ab24
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.highlighting;
+
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class HtmlClosingTagErrorFilter extends HighlightErrorFilter {
+
+  public boolean shouldHighlightErrorElement(@NotNull final PsiErrorElement element) {
+    final PsiFile psiFile = element.getContainingFile();
+    if (psiFile == null || (psiFile.getViewProvider().getBaseLanguage() != HTMLLanguage.INSTANCE
+                            && HTMLLanguage.INSTANCE != element.getLanguage())) return true;
+
+    final PsiElement[] children = element.getChildren();
+    if (children.length > 0) {
+      if (children[0] instanceof XmlToken && XmlTokenType.XML_END_TAG_START == ((XmlToken)children[0]).getTokenType()) {
+        if (XmlErrorMessages.message("xml.parsing.closing.tag.matches.nothing").equals(element.getErrorDescription())) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/highlighting/XmlReadWriteAccessDetector.java b/xml/impl/src/com/intellij/codeInsight/highlighting/XmlReadWriteAccessDetector.java
new file mode 100644
index 0000000..aff0c38
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/highlighting/XmlReadWriteAccessDetector.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.highlighting;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlElementDecl;
+import com.intellij.psi.xml.XmlComment;
+
+/**
+ * @author yole
+ */
+public class XmlReadWriteAccessDetector extends ReadWriteAccessDetector {
+  public boolean isReadWriteAccessible(final PsiElement element) {
+    return element instanceof XmlAttributeValue ||
+        element instanceof XmlTag ||
+        element instanceof XmlElementDecl ||
+        element instanceof XmlComment; // e.g. <!--@elvariable name="xxx" type="yyy"-->
+  }
+
+  public boolean isDeclarationWriteAccess(final PsiElement element) {
+    return false;
+  }
+
+  public Access getReferenceAccess(final PsiElement referencedElement, final PsiReference reference) {
+    PsiElement refElement = reference.getElement();
+    return ( refElement instanceof XmlAttributeValue &&
+              (!(referencedElement instanceof XmlTag) || refElement.getParent().getParent() == referencedElement)
+            ) ||
+            refElement instanceof XmlElementDecl ||
+            refElement instanceof XmlComment   // e.g. <!--@elvariable name="xxx" type="yyy"-->
+           ? Access.Write : Access.Read;
+
+  }
+
+  public Access getExpressionAccess(final PsiElement expression) {
+    return expression instanceof XmlAttributeValue ? Access.Write : Access.Read;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/hint/TagDeclarationRangeHandler.java b/xml/impl/src/com/intellij/codeInsight/hint/TagDeclarationRangeHandler.java
new file mode 100644
index 0000000..34fe453
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/hint/TagDeclarationRangeHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.hint;
+
+import org.jetbrains.annotations.NotNull;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+
+public class TagDeclarationRangeHandler implements DeclarationRangeHandler {
+  @NotNull
+  public TextRange getDeclarationRange(@NotNull final PsiElement container) {
+    XmlTag xmlTag = (XmlTag)container;
+    int endOffset = xmlTag.getTextRange().getStartOffset();
+
+    for (PsiElement child = xmlTag.getFirstChild(); child != null; child = child.getNextSibling()) {
+      endOffset = child.getTextRange().getEndOffset();
+      if (child instanceof XmlToken) {
+        XmlToken token = (XmlToken)child;
+        IElementType tokenType = token.getTokenType();
+        if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END || tokenType == XmlTokenType.XML_TAG_END) break;
+      }
+    }
+
+    return new TextRange(xmlTag.getTextRange().getStartOffset(), endOffset);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/hint/XmlImplementationTextSelectioner.java b/xml/impl/src/com/intellij/codeInsight/hint/XmlImplementationTextSelectioner.java
new file mode 100644
index 0000000..977a0dd
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/hint/XmlImplementationTextSelectioner.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * User: anna
+ * Date: 01-Feb-2008
+ */
+package com.intellij.codeInsight.hint;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+
+public class XmlImplementationTextSelectioner implements ImplementationTextSelectioner {
+  private static final Logger LOG = Logger.getInstance("#" + XmlImplementationTextSelectioner.class.getName());
+
+  public int getTextStartOffset(@NotNull final PsiElement parent) {
+    return parent.getTextRange().getStartOffset();
+  }
+
+  public int getTextEndOffset(@NotNull PsiElement element) {
+    if (element instanceof XmlAttributeValue) {
+      final XmlTag xmlTag = PsiTreeUtil.getParentOfType(element, XmlTag.class);// for convenience
+      if (xmlTag != null) return xmlTag.getTextRange().getEndOffset();
+      LOG.assertTrue(false);
+    }
+    return element.getTextRange().getEndOffset();
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/hint/api/impls/XmlParameterInfoHandler.java b/xml/impl/src/com/intellij/codeInsight/hint/api/impls/XmlParameterInfoHandler.java
new file mode 100644
index 0000000..798a3d9
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/hint/api/impls/XmlParameterInfoHandler.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.hint.api.impls;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.MutableLookupElement;
+import com.intellij.lang.parameterInfo.*;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.Function;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class XmlParameterInfoHandler implements ParameterInfoHandler<XmlTag,XmlElementDescriptor> {
+  private static final Comparator<XmlAttributeDescriptor> COMPARATOR = new Comparator<XmlAttributeDescriptor>() {
+    public int compare(final XmlAttributeDescriptor o1, final XmlAttributeDescriptor o2) {
+      return o1.getName().compareTo(o2.getName());
+    }
+  };
+
+  public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
+    if (!(item instanceof MutableLookupElement)) return null;
+    final Object lookupItem = item.getObject();
+    if (lookupItem instanceof XmlElementDescriptor) return new Object[]{lookupItem};
+    return null;
+  }
+
+  public Object[] getParametersForDocumentation(final XmlElementDescriptor p, final ParameterInfoContext context) {
+    return getSortedDescriptors(p);
+  }
+
+  public static XmlAttributeDescriptor[] getSortedDescriptors(final XmlElementDescriptor p) {
+    final XmlAttributeDescriptor[] xmlAttributeDescriptors = p.getAttributesDescriptors(null);
+    Arrays.sort(xmlAttributeDescriptors, COMPARATOR);
+    return xmlAttributeDescriptors;
+  }
+
+  public boolean couldShowInLookup() {
+    return true;
+  }
+
+  public XmlTag findElementForParameterInfo(final CreateParameterInfoContext context) {
+    final XmlTag tag = findXmlTag(context.getFile(), context.getOffset());
+    final XmlElementDescriptor descriptor = tag != null ? tag.getDescriptor() : null;
+
+    if (descriptor == null) {
+      DaemonCodeAnalyzer.getInstance(context.getProject()).updateVisibleHighlighters(context.getEditor());
+      return null;
+    }
+
+    context.setItemsToShow(new Object[] {descriptor});
+    return tag;
+  }
+
+  public void showParameterInfo(final @NotNull XmlTag element, final CreateParameterInfoContext context) {
+    context.showHint(element, element.getTextRange().getStartOffset() + 1, this);
+  }
+
+  public XmlTag findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context) {
+    final XmlTag tag = findXmlTag(context.getFile(), context.getOffset());
+    if (tag != null) {
+      final PsiElement currentXmlTag = context.getParameterOwner();
+      if (currentXmlTag == null || currentXmlTag == tag) return tag;
+    }
+
+    return null;
+  }
+
+  public void updateParameterInfo(@NotNull final XmlTag o, final UpdateParameterInfoContext context) {
+    if (context.getParameterOwner() == null || o.equals(context.getParameterOwner())) {
+      context.setParameterOwner( o );
+    } else {
+      context.removeHint();
+    }
+  }
+
+  public String getParameterCloseChars() {
+    return null;
+  }
+
+  public boolean tracksParameterIndex() {
+    return false;
+  }
+
+  @Nullable
+  private static XmlTag findXmlTag(PsiFile file, int offset){
+    if (!(file instanceof XmlFile)) return null;
+
+    PsiElement element = file.findElementAt(offset);
+    if (element == null) return null;
+    element = element.getParent();
+
+    while (element != null) {
+      if (element instanceof XmlTag) {
+        XmlTag tag = (XmlTag)element;
+
+        final PsiElement[] children = tag.getChildren();
+
+        if (offset <= children[0].getTextRange().getStartOffset()) return null;
+
+        for (PsiElement child : children) {
+          final TextRange range = child.getTextRange();
+          if (range.getStartOffset() <= offset && range.getEndOffset() > offset) return tag;
+
+          if (child instanceof XmlToken) {
+            XmlToken token = (XmlToken)child;
+            if (token.getTokenType() == XmlTokenType.XML_TAG_END) return null;
+          }
+        }
+
+        return null;
+      }
+
+      element = element.getParent();
+    }
+
+    return null;
+  }
+
+  public void updateUI(XmlElementDescriptor o, final ParameterInfoUIContext context) {
+    updateElementDescriptor(
+      o,
+      context,
+      new Function<String, Boolean>() {
+        final XmlTag parameterOwner  = (XmlTag)context.getParameterOwner();
+
+        public Boolean fun(String s) {
+          return parameterOwner != null ? parameterOwner.getAttributeValue(s) != null:false;
+        }
+      });
+  }
+
+  public static void updateElementDescriptor(XmlElementDescriptor descriptor, ParameterInfoUIContext context,
+                                             Function<String, Boolean> attributePresentFun) {
+    final XmlAttributeDescriptor[] attributes = descriptor != null ? getSortedDescriptors(descriptor) : XmlAttributeDescriptor.EMPTY;
+
+    StringBuffer buffer = new StringBuffer();
+    int highlightStartOffset = -1;
+    int highlightEndOffset = -1;
+
+    if (attributes.length == 0) {
+      buffer.append(CodeInsightBundle.message("xml.tag.info.no.attributes"));
+    }
+    else {
+      StringBuffer text1 = new StringBuffer(" ");
+      StringBuffer text2 = new StringBuffer(" ");
+      StringBuffer text3 = new StringBuffer(" ");
+
+      for (XmlAttributeDescriptor attribute : attributes) {
+        if (Boolean.TRUE.equals(attributePresentFun.fun(attribute.getName()))) {
+          if (!(text1.toString().equals(" "))) {
+            text1.append(", ");
+          }
+          text1.append(attribute.getName());
+        }
+        else if (attribute.isRequired()) {
+          if (!(text2.toString().equals(" "))) {
+            text2.append(", ");
+          }
+          text2.append(attribute.getName());
+        }
+        else {
+          if (!(text3.toString().equals(" "))) {
+            text3.append(", ");
+          }
+          text3.append(attribute.getName());
+        }
+      }
+
+      if (!text1.toString().equals(" ") && !text2.toString().equals(" ")) {
+        text1.append(", ");
+      }
+
+      if (!text2.toString().equals(" ") && !text3.toString().equals(" ")) {
+        text2.append(", ");
+      }
+
+      if (!text1.toString().equals(" ") && !text3.toString().equals(" ") && text2.toString().equals(" ")) {
+        text1.append(", ");
+      }
+
+      buffer.append(text1);
+      highlightStartOffset = buffer.length();
+      buffer.append(text2);
+      highlightEndOffset = buffer.length();
+      buffer.append(text3);
+    }
+
+    context.setupUIComponentPresentation(buffer.toString(), highlightStartOffset, highlightEndOffset, false,
+                                         false, true, context.getDefaultParameterColor());
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/intentions/XmlChooseColorIntentionAction.java b/xml/impl/src/com/intellij/codeInsight/intentions/XmlChooseColorIntentionAction.java
new file mode 100644
index 0000000..5bfdb3b
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/intentions/XmlChooseColorIntentionAction.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.intentions;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.ui.ColorChooser;
+import com.intellij.ui.ColorUtil;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class XmlChooseColorIntentionAction extends PsiElementBaseIntentionAction {
+  public XmlChooseColorIntentionAction() {
+    setText(CodeInsightBundle.message("intention.color.chooser.dialog"));
+  }
+
+  public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
+    final PsiElement parent = element.getParent();
+    return parent instanceof XmlAttributeValue && ColorUtil.fromHex(((XmlAttributeValue)parent).getValue(), null) != null;
+  }
+
+  @NotNull
+  public String getFamilyName() {
+    return getText();
+  }
+
+  @Override
+  public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
+    if (!CodeInsightUtilBase.preparePsiElementForWrite(element)) return;
+    invokeForLiteral(editor.getComponent(), element);
+  }
+
+  private void invokeForLiteral(JComponent editorComponent, PsiElement element) {
+    final XmlAttributeValue literal = PsiTreeUtil.getParentOfType(element, XmlAttributeValue.class);
+    if (literal == null) return;
+    final String text = StringUtil.unquoteString(literal.getValue());
+    final String hexPrefix = text.startsWith("#") ? "#" : "";
+
+    Color oldColor;
+    try {
+      oldColor = Color.decode(text);
+    }
+    catch (NumberFormatException e) {
+      oldColor = Color.GRAY;
+    }
+    Color color = ColorChooser.chooseColor(editorComponent, getText(), oldColor, true);
+    if (color == null) return;
+    if (!Comparing.equal(color, oldColor)) {
+      final String newText =  hexPrefix + ColorUtil.toHex(color);
+      final PsiManager manager = literal.getManager();
+      final XmlAttribute newAttribute = XmlElementFactory.getInstance(manager.getProject()).createXmlAttribute("name", newText);
+      literal.replace(newAttribute.getValueElement());
+    }
+  }
+}
+
diff --git a/xml/impl/src/com/intellij/codeInsight/navigation/XmlMethodNavigationOffsetProvider.java b/xml/impl/src/com/intellij/codeInsight/navigation/XmlMethodNavigationOffsetProvider.java
new file mode 100644
index 0000000..136ddf8
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/navigation/XmlMethodNavigationOffsetProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.navigation;
+
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+
+import java.util.ArrayList;
+
+/**
+ * @author yole
+ */
+public class XmlMethodNavigationOffsetProvider implements MethodNavigationOffsetProvider {
+  @Override
+  public int[] getMethodNavigationOffsets(final PsiFile file, final int caretOffset) {
+    if (file instanceof XmlFile) {
+      PsiElement element = file;
+      PsiElement elementAt = file.findElementAt(caretOffset);
+      elementAt = PsiTreeUtil.getParentOfType(elementAt, XmlTag.class);
+      if (elementAt != null) element = elementAt;
+
+      ArrayList<PsiElement> array = new ArrayList<PsiElement>();
+      addNavigationElements(array, element);
+      return MethodUpDownUtil.offsetsFromElements(array);
+    }
+    return null;
+  }
+
+  private static void addNavigationElements(ArrayList<PsiElement> array, PsiElement element) {
+    PsiElement parent = element instanceof XmlFile ? element : element.getParent();
+
+    if (parent != null) {
+      PsiElement[] children = parent.getChildren();
+      for (PsiElement child : children) {
+        if (child instanceof XmlTag) {
+          array.add(child);
+        }
+      }
+    }
+    final PsiElement parentElement = element.getParent();
+    if (parentElement != null) {
+      addNavigationElements(array, parentElement);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/HtmlContextType.java b/xml/impl/src/com/intellij/codeInsight/template/HtmlContextType.java
new file mode 100644
index 0000000..5fe1dbf
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/HtmlContextType.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class HtmlContextType extends FileTypeBasedContextType {
+  public HtmlContextType() {
+    super("HTML", CodeInsightBundle.message("dialog.edit.template.checkbox.html"), StdFileTypes.HTML);
+  }
+
+  @Override
+  public boolean isInContext(@NotNull PsiFile file, int offset) {
+    return isMyLanguage(file.getLanguage()) && !XmlContextType.isEmbeddedContent(file, offset);
+  }
+
+  static boolean isMyLanguage(Language language) {
+    return language.isKindOf(HTMLLanguage.INSTANCE) || language.isKindOf(XHTMLLanguage.INSTANCE);
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/codeInsight/template/HtmlTextContextType.java b/xml/impl/src/com/intellij/codeInsight/template/HtmlTextContextType.java
new file mode 100644
index 0000000..5a61b4e
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/HtmlTextContextType.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlComment;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlText;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class HtmlTextContextType extends TemplateContextType {
+  protected HtmlTextContextType() {
+    super("HTML_TEXT", CodeInsightBundle.message("dialog.edit.template.checkbox.html.text"), HtmlContextType.class);
+  }
+
+  @Override
+  public boolean isInContext(@NotNull PsiFile file, int offset) {
+    if (!HtmlContextType.isMyLanguage(file.getLanguage())) {
+      return false;
+    }
+    PsiElement element = file.findElementAt(offset);
+    return element == null || isInContext(element);
+  }
+
+  public static boolean isInContext(@NotNull PsiElement element) {
+    if (PsiTreeUtil.getParentOfType(element, XmlComment.class) != null) {
+      return false;
+    }
+    if (PsiTreeUtil.getParentOfType(element, XmlText.class) != null) {
+      return true;
+    }
+    PsiElement parent = element.getParent();
+    if (parent instanceof PsiErrorElement) {
+      parent = parent.getParent();
+    }
+    return parent instanceof XmlDocument;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/XmlContextType.java b/xml/impl/src/com/intellij/codeInsight/template/XmlContextType.java
new file mode 100644
index 0000000..478fc00
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/XmlContextType.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.lang.Language;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiUtilBase;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class XmlContextType extends TemplateContextType {
+  public XmlContextType() {
+    super("XML", CodeInsightBundle.message("dialog.edit.template.checkbox.xml"));
+  }
+
+  @Override
+  public boolean isInContext(@NotNull PsiFile file, int offset) {
+    return file.getLanguage().isKindOf(XMLLanguage.INSTANCE) && !isEmbeddedContent(file, offset) &&
+           !HtmlContextType.isMyLanguage(PsiUtilBase.getLanguageAtOffset(file, offset)) &&
+           file.getFileType() != StdFileTypes.JSPX && file.getFileType() != StdFileTypes.JSP;
+  }
+
+  public static boolean isEmbeddedContent(@NotNull final PsiFile file, final int offset) {
+    Language languageAtOffset = PsiUtilBase.getLanguageAtOffset(file, offset);
+    return !(languageAtOffset.isKindOf(XMLLanguage.INSTANCE) || languageAtOffset instanceof XMLLanguage);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/XmlDefaultLiveTemplatesProvider.java b/xml/impl/src/com/intellij/codeInsight/template/XmlDefaultLiveTemplatesProvider.java
new file mode 100644
index 0000000..9b13138
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/XmlDefaultLiveTemplatesProvider.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template;
+
+import com.intellij.codeInsight.template.impl.DefaultLiveTemplatesProvider;
+
+/**
+ * @author yole
+ */
+public class XmlDefaultLiveTemplatesProvider implements DefaultLiveTemplatesProvider {
+  public String[] getDefaultLiveTemplateFiles() {
+    return new String[] { "/liveTemplates/html_xml", "/liveTemplates/zen_html", "/liveTemplates/zen_xsl" };
+  }
+
+  @Override
+  public String[] getHiddenLiveTemplateFiles() {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/XslTextContextType.java b/xml/impl/src/com/intellij/codeInsight/template/XslTextContextType.java
new file mode 100644
index 0000000..7f22c59
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/XslTextContextType.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class XslTextContextType extends TemplateContextType {
+  protected XslTextContextType() {
+    super("XSL_TEXT", CodeInsightBundle.message("dialog.edit.template.checkbox.xsl.text"), XmlContextType.class);
+  }
+
+  @Override
+  public boolean isInContext(@NotNull PsiFile file, int offset) {
+    if (file.getFileType() == StdFileTypes.XML && FileUtil.getExtension(file.getName()).equals("xsl")) {
+      PsiElement element = file.findElementAt(offset);
+      return element == null || HtmlTextContextType.isInContext(element);
+    }
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/ZenCodingTemplate.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/ZenCodingTemplate.java
new file mode 100644
index 0000000..29bac40
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/ZenCodingTemplate.java
@@ -0,0 +1,890 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding;
+
+import com.intellij.application.options.editor.WebEditorOptions;
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.template.*;
+import com.intellij.codeInsight.template.impl.TemplateImpl;
+import com.intellij.codeInsight.template.impl.TemplateState;
+import com.intellij.codeInsight.template.zencoding.filters.ZenCodingFilter;
+import com.intellij.codeInsight.template.zencoding.generators.XmlZenCodingGenerator;
+import com.intellij.codeInsight.template.zencoding.generators.ZenCodingGenerator;
+import com.intellij.codeInsight.template.zencoding.nodes.*;
+import com.intellij.codeInsight.template.zencoding.tokens.*;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.undo.UndoConstants;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorModificationUtil;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.ui.InputValidatorEx;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.LocalTimeCounter;
+import com.intellij.xml.XmlBundle;
+import org.apache.xerces.util.XML11Char;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class ZenCodingTemplate implements CustomLiveTemplate {
+  public static final char MARKER = '\0';
+  private static final String DELIMS = ">+*|()[]{}.#,='\" \0";
+  public static final String ATTRS = "ATTRS";
+  private static final String ID = "id";
+  private static final String CLASS = "class";
+  private static final String DEFAULT_TAG = "div";
+
+  private static int parseNonNegativeInt(@NotNull String s) {
+    try {
+      return Integer.parseInt(s);
+    }
+    catch (Throwable ignored) {
+    }
+    return -1;
+  }
+
+  private static boolean isXML11ValidQName(String str) {
+    final int colon = str.indexOf(':');
+    if (colon == 0 || colon == str.length() - 1) {
+      return false;
+    }
+    if (colon > 0) {
+      final String prefix = str.substring(0, colon);
+      final String localPart = str.substring(colon + 1);
+      return XML11Char.isXML11ValidNCName(prefix) && XML11Char.isXML11ValidNCName(localPart);
+    }
+    return XML11Char.isXML11ValidNCName(str);
+  }
+
+  private static boolean isHtml(CustomTemplateCallback callback) {
+    FileType type = callback.getFileType();
+    return type == StdFileTypes.HTML || type == StdFileTypes.XHTML;
+  }
+
+  private static void addMissingAttributes(XmlTag tag, List<Pair<String, String>> value) {
+    List<Pair<String, String>> attr2value = new ArrayList<Pair<String, String>>(value);
+    for (Iterator<Pair<String, String>> iterator = attr2value.iterator(); iterator.hasNext();) {
+      Pair<String, String> pair = iterator.next();
+      if (tag.getAttribute(pair.first) != null) {
+        iterator.remove();
+      }
+    }
+    addAttributesBefore(tag, attr2value);
+  }
+
+  private static void addAttributesBefore(XmlTag tag, List<Pair<String, String>> attr2value) {
+    XmlAttribute firstAttribute = ArrayUtil.getFirstElement(tag.getAttributes());
+    XmlElementFactory factory = XmlElementFactory.getInstance(tag.getProject());
+    for (Pair<String, String> pair : attr2value) {
+      XmlAttribute xmlAttribute = factory.createXmlAttribute(pair.first, "");
+      if (firstAttribute != null) {
+        tag.addBefore(xmlAttribute, firstAttribute);
+      }
+      else {
+        tag.add(xmlAttribute);
+      }
+    }
+  }
+
+  @Nullable
+  private static ZenCodingGenerator findApplicableDefaultGenerator(@NotNull PsiElement context, boolean wrapping) {
+    for (ZenCodingGenerator generator : ZenCodingGenerator.getInstances()) {
+      if (generator.isMyContext(context, wrapping) && generator.isAppliedByDefault(context)) {
+        return generator;
+      }
+    }
+    return null;
+  }
+
+  @NotNull
+  private static XmlFile parseXmlFileInTemplate(String templateString, CustomTemplateCallback callback, boolean createPhysicalFile) {
+    XmlFile xmlFile = (XmlFile)PsiFileFactory.getInstance(callback.getProject())
+      .createFileFromText("dummy.xml", StdFileTypes.XML, templateString, LocalTimeCounter.currentTime(), createPhysicalFile);
+    VirtualFile vFile = xmlFile.getVirtualFile();
+    if (vFile != null) {
+      vFile.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE);
+    }
+    return xmlFile;
+  }
+
+  @Nullable
+  private static ZenCodingNode parse(@NotNull String text, @NotNull CustomTemplateCallback callback, ZenCodingGenerator generator) {
+    List<ZenCodingToken> tokens = lex(text);
+    if (tokens == null) {
+      return null;
+    }
+    if (generator != null && !validate(tokens, generator)) {
+      return null;
+    }
+    MyParser parser = new MyParser(tokens, callback, generator);
+    ZenCodingNode node = parser.parse();
+    if (parser.myIndex != tokens.size() || node instanceof TextNode) {
+      return null;
+    }
+    return node;
+  }
+  
+  private static boolean validate(@NotNull List<ZenCodingToken> tokens, @NotNull ZenCodingGenerator generator) {
+    for (ZenCodingToken token : tokens) {
+      if (token instanceof TextToken && !(generator instanceof XmlZenCodingGenerator)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Nullable
+  private static List<ZenCodingToken> lex(@NotNull String text) {
+    text += MARKER;
+    final List<ZenCodingToken> result = new ArrayList<ZenCodingToken>();
+
+    boolean inQuotes = false;
+    boolean inApostrophes = false;
+    int bracesStack = 0;
+
+    StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < text.length(); i++) {
+      final char c = text.charAt(i);
+
+      if (inQuotes) {
+        builder.append(c);
+        if (c == '"') {
+          inQuotes = false;
+          result.add(new StringLiteralToken(builder.toString()));
+          builder = new StringBuilder();
+        }
+        continue;
+      }
+
+      if (inApostrophes) {
+        builder.append(c);
+        if (c == '\'') {
+          inApostrophes = false;
+          result.add(new StringLiteralToken(builder.toString()));
+          builder = new StringBuilder();
+        }
+        continue;
+      }
+
+      if (bracesStack > 0) {
+        builder.append(c);
+        if (c == '}') {
+          bracesStack--;
+          if (bracesStack == 0) {
+            result.add(new TextToken(builder.toString()));
+            builder = new StringBuilder();
+          }
+        }
+        else if (c == '{') {
+          bracesStack++;
+        }
+        continue;
+      }
+
+      if (DELIMS.indexOf(c) < 0) {
+        builder.append(c);
+      }
+      else {
+        // handle special case: ul+ template
+        if (c == '+' && (i == text.length() - 2 || text.charAt(i + 1) == ')')) {
+          builder.append(c);
+          continue;
+        }
+
+        if (builder.length() > 0) {
+          final String tokenText = builder.toString();
+          final int n = parseNonNegativeInt(tokenText);
+          if (n >= 0) {
+            result.add(new NumberToken(n));
+          }
+          else {
+            result.add(new IdentifierToken(tokenText));
+          }
+          builder = new StringBuilder();
+        }
+        if (c == '"') {
+          inQuotes = true;
+          builder.append(c);
+        }
+        else if (c == '\'') {
+          inApostrophes = true;
+          builder.append(c);
+        }
+        else if (c == '{') {
+          bracesStack = 1;
+          builder.append(c);
+        }
+        else if (c == '(') {
+          result.add(ZenCodingTokens.OPENING_R_BRACKET);
+        }
+        else if (c == ')') {
+          result.add(ZenCodingTokens.CLOSING_R_BRACKET);
+        }
+        else if (c == '[') {
+          result.add(ZenCodingTokens.OPENING_SQ_BRACKET);
+        }
+        else if (c == ']') {
+          result.add(ZenCodingTokens.CLOSING_SQ_BRACKET);
+        }
+        else if (c == '=') {
+          result.add(ZenCodingTokens.EQ);
+        }
+        else if (c == '.') {
+          result.add(ZenCodingTokens.DOT);
+        }
+        else if (c == '#') {
+          result.add(ZenCodingTokens.SHARP);
+        }
+        else if (c == ',') {
+          result.add(ZenCodingTokens.COMMA);
+        }
+        else if (c == ' ') {
+          result.add(ZenCodingTokens.SPACE);
+        }
+        else if (c == '|') {
+          result.add(ZenCodingTokens.PIPE);
+        }
+        else if (c != MARKER) {
+          result.add(new OperationToken(c));
+        }
+      }
+    }
+    if (bracesStack != 0 || inQuotes || inApostrophes) {
+      return null;
+    }
+    return result;
+  }
+
+
+  public static boolean checkTemplateKey(@NotNull String key, CustomTemplateCallback callback, ZenCodingGenerator generator) {
+    return parse(key, callback, generator) != null;
+  }
+
+  public void expand(String key, @NotNull CustomTemplateCallback callback) {
+    ZenCodingGenerator defaultGenerator = findApplicableDefaultGenerator(callback.getContext(), false);
+    assert defaultGenerator != null;
+    expand(key, callback, null, defaultGenerator);
+  }
+
+  @Nullable
+  private static ZenCodingGenerator findApplicableGenerator(ZenCodingNode node, PsiElement context, boolean wrapping) {
+    ZenCodingGenerator defaultGenerator = null;
+    List<ZenCodingGenerator> generators = ZenCodingGenerator.getInstances();
+    for (ZenCodingGenerator generator : generators) {
+      if (defaultGenerator == null && generator.isMyContext(context, wrapping) && generator.isAppliedByDefault(context)) {
+        defaultGenerator = generator;
+      }
+    }
+    while (node instanceof FilterNode) {
+      FilterNode filterNode = (FilterNode)node;
+      String suffix = filterNode.getFilter();
+      for (ZenCodingGenerator generator : generators) {
+        if (generator.isMyContext(context, wrapping)) {
+          if (suffix != null && suffix.equals(generator.getSuffix())) {
+            return generator;
+          }
+        }
+      }
+      node = filterNode.getNode();
+    }
+    return defaultGenerator;
+  }
+
+  private static List<ZenCodingFilter> getFilters(ZenCodingNode node, PsiElement context) {
+    List<ZenCodingFilter> result = new ArrayList<ZenCodingFilter>();
+
+    while (node instanceof FilterNode) {
+      FilterNode filterNode = (FilterNode)node;
+      String filterSuffix = filterNode.getFilter();
+      boolean filterFound = false;
+      for (ZenCodingFilter filter : ZenCodingFilter.getInstances()) {
+        if (filter.isMyContext(context) && filter.getSuffix().equals(filterSuffix)) {
+          filterFound = true;
+          result.add(filter);
+        }
+      }
+      assert filterFound;
+      node = filterNode.getNode();
+    }
+
+    for (ZenCodingFilter filter : ZenCodingFilter.getInstances()) {
+      if (filter.isMyContext(context) && filter.isAppliedByDefault(context)) {
+        result.add(filter);
+      }
+    }
+
+    Collections.reverse(result);
+    return result;
+  }
+
+
+  private static void expand(String key,
+                             @NotNull CustomTemplateCallback callback,
+                             String surroundedText,
+                             @NotNull ZenCodingGenerator defaultGenerator) {
+    ZenCodingNode node = parse(key, callback, defaultGenerator);
+    assert node != null;
+    if (surroundedText == null) {
+      if (node instanceof TemplateNode) {
+        if (key.equals(((TemplateNode)node).getTemplateToken().getKey()) &&
+            callback.findApplicableTemplates(key).size() > 1) {
+          callback.startTemplate();
+          return;
+        }
+      }
+      callback.deleteTemplateKey(key);
+    }
+
+    PsiElement context = callback.getContext();
+    ZenCodingGenerator generator = findApplicableGenerator(node, context, false);
+    List<ZenCodingFilter> filters = getFilters(node, context);
+
+    expand(node, generator, filters, surroundedText, callback);
+  }
+
+  private static void expand(ZenCodingNode node,
+                             ZenCodingGenerator generator,
+                             List<ZenCodingFilter> filters,
+                             String surroundedText,
+                             CustomTemplateCallback callback) {
+    if (surroundedText != null) {
+      surroundedText = surroundedText.trim();
+    }
+    List<GenerationNode> genNodes = node.expand(-1, surroundedText, callback, true);
+    LiveTemplateBuilder builder = new LiveTemplateBuilder();
+    int end = -1;
+    for (int i = 0, genNodesSize = genNodes.size(); i < genNodesSize; i++) {
+      GenerationNode genNode = genNodes.get(i);
+      TemplateImpl template = genNode.generate(callback, generator, filters, true);
+      int e = builder.insertTemplate(builder.length(), template, null);
+      if (end == -1 && end < builder.length()) {
+        end = e;
+      }
+    }
+
+    callback.startTemplate(builder.buildTemplate(), null, new TemplateEditingAdapter() {
+      private TextRange myEndVarRange;
+      private Editor myEditor;
+
+      @Override
+      public void beforeTemplateFinished(TemplateState state, Template template) {
+        int variableNumber = state.getCurrentVariableNumber();
+        if (variableNumber >= 0 && template instanceof TemplateImpl) {
+          TemplateImpl t = (TemplateImpl)template;
+          while (variableNumber < t.getVariableCount()) {
+            String varName = t.getVariableNameAt(variableNumber);
+            if (LiveTemplateBuilder.isEndVariable(varName)) {
+              myEndVarRange = state.getVariableRange(varName);
+              myEditor = state.getEditor();
+              break;
+            }
+            variableNumber++;
+          }
+        }
+      }
+
+      @Override
+      public void templateFinished(Template template, boolean brokenOff) {
+        if (brokenOff && myEndVarRange != null && myEditor != null) {
+          int offset = myEndVarRange.getStartOffset();
+          if (offset >= 0 && offset != myEditor.getCaretModel().getOffset()) {
+            myEditor.getCaretModel().moveToOffset(offset);
+            myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+          }
+        }
+      }
+    });
+  }
+
+  public void wrap(final String selection,
+                   @NotNull final CustomTemplateCallback callback
+  ) {
+    InputValidatorEx validator = new InputValidatorEx() {
+      public String getErrorText(String inputString) {
+        if (!checkTemplateKey(inputString, callback)) {
+          return XmlBundle.message("zen.coding.incorrect.abbreviation.error");
+        }
+        return null;
+      }
+
+      public boolean checkInput(String inputString) {
+        return getErrorText(inputString) == null;
+      }
+
+      public boolean canClose(String inputString) {
+        return checkInput(inputString);
+      }
+    };
+    final String abbreviation = Messages
+      .showInputDialog(callback.getProject(), XmlBundle.message("zen.coding.enter.abbreviation.dialog.label"),
+                       XmlBundle.message("zen.coding.title"), Messages.getQuestionIcon(), "", validator);
+    if (abbreviation != null) {
+      doWrap(selection, abbreviation, callback);
+    }
+  }
+
+  public static boolean checkTemplateKey(String inputString, CustomTemplateCallback callback) {
+    ZenCodingGenerator generator = findApplicableDefaultGenerator(callback.getContext(), true);
+    assert generator != null;
+    return checkTemplateKey(inputString, callback, generator);
+  }
+
+  public boolean isApplicable(PsiFile file, int offset, boolean wrapping) {
+    WebEditorOptions webEditorOptions = WebEditorOptions.getInstance();
+    if (!webEditorOptions.isZenCodingEnabled()) {
+      return false;
+    }
+    if (file == null) {
+      return false;
+    }
+    PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
+    PsiElement element = CustomTemplateCallback.getContext(file, offset);
+    return findApplicableDefaultGenerator(element, wrapping) != null;
+  }
+
+  protected static void doWrap(final String selection,
+                               final String abbreviation,
+                               final CustomTemplateCallback callback) {
+    final ZenCodingGenerator defaultGenerator = findApplicableDefaultGenerator(callback.getContext(), true);
+    assert defaultGenerator != null;
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      public void run() {
+        CommandProcessor.getInstance().executeCommand(callback.getProject(), new Runnable() {
+          public void run() {
+            callback.fixInitialState(true);
+            ZenCodingNode node = parse(abbreviation, callback, defaultGenerator);
+            assert node != null;
+            PsiElement context = callback.getContext();
+            ZenCodingGenerator generator = findApplicableGenerator(node, context, true);
+            List<ZenCodingFilter> filters = getFilters(node, context);
+
+            EditorModificationUtil.deleteSelectedText(callback.getEditor());
+            PsiDocumentManager.getInstance(callback.getProject()).commitAllDocuments();
+
+            expand(node, generator, filters, selection, callback);
+          }
+        }, CodeInsightBundle.message("insert.code.template.command"), null);
+      }
+    });
+  }
+
+  @NotNull
+  public String getTitle() {
+    return XmlBundle.message("zen.coding.title");
+  }
+
+  public char getShortcut() {
+    return (char)WebEditorOptions.getInstance().getZenCodingExpandShortcut();
+  }
+
+  protected static boolean containsAttrsVar(TemplateImpl template) {
+    for (int i = 0; i < template.getVariableCount(); i++) {
+      String varName = template.getVariableNameAt(i);
+      if (ATTRS.equals(varName)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public String computeTemplateKey(@NotNull CustomTemplateCallback callback) {
+    ZenCodingGenerator generator = findApplicableDefaultGenerator(callback.getContext(), false);
+    if (generator == null) return null;
+    return generator.computeTemplateKey(callback);
+  }
+
+  public boolean supportsWrapping() {
+    return true;
+  }
+
+  public static boolean checkFilterSuffix(@NotNull String suffix) {
+    for (ZenCodingGenerator generator : ZenCodingGenerator.getInstances()) {
+      if (suffix.equals(generator.getSuffix())) {
+        return true;
+      }
+    }
+    for (ZenCodingFilter filter : ZenCodingFilter.getInstances()) {
+      if (suffix.equals(filter.getSuffix())) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static boolean doSetTemplate(final TemplateToken token, TemplateImpl template, CustomTemplateCallback callback) {
+    token.setTemplate(template);
+    final XmlFile xmlFile = parseXmlFileInTemplate(template.getString(), callback, true);
+    token.setFile(xmlFile);
+    XmlDocument document = xmlFile.getDocument();
+    final XmlTag tag = document != null ? document.getRootTag() : null;
+    if (token.getAttribute2Value().size() > 0 && tag == null) {
+      return false;
+    }
+    if (tag != null) {
+      if (!containsAttrsVar(template) && token.getAttribute2Value().size() > 0) {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          public void run() {
+            addMissingAttributes(tag, token.getAttribute2Value());
+          }
+        });
+      }
+    }
+    return true;
+  }
+
+  private static class MyParser {
+    private final List<ZenCodingToken> myTokens;
+    private final CustomTemplateCallback myCallback;
+    private final ZenCodingGenerator myGenerator;
+    private int myIndex = 0;
+
+    private MyParser(List<ZenCodingToken> tokens, CustomTemplateCallback callback, ZenCodingGenerator generator) {
+      myTokens = tokens;
+      myCallback = callback;
+      myGenerator = generator;
+    }
+
+    @Nullable
+    private ZenCodingNode parse() {
+      ZenCodingNode add = parseAddOrMore();
+      if (add == null) {
+        return null;
+      }
+
+      ZenCodingNode result = add;
+
+      while (true) {
+        ZenCodingToken token = nextToken();
+        if (token != ZenCodingTokens.PIPE) {
+          return result;
+        }
+
+        myIndex++;
+        token = nextToken();
+        if (!(token instanceof IdentifierToken)) {
+          return null;
+        }
+
+        final String filterSuffix = ((IdentifierToken)token).getText();
+        if (!checkFilterSuffix(filterSuffix)) {
+          return null;
+        }
+
+        myIndex++;
+        result = new FilterNode(result, filterSuffix);
+      }
+    }
+
+    @Nullable
+    private ZenCodingNode parseAddOrMore() {
+      ZenCodingNode mul = parseMul();
+      if (mul == null) {
+        return null;
+      }
+      ZenCodingToken operationToken = nextToken();
+      if (!(operationToken instanceof OperationToken)) {
+        return mul;
+      }
+      char sign = ((OperationToken)operationToken).getSign();
+      if (sign == '+') {
+        myIndex++;
+        ZenCodingNode add2 = parseAddOrMore();
+        if (add2 == null) {
+          return null;
+        }
+        return new AddOperationNode(mul, add2);
+      }
+      else if (sign == '>') {
+        myIndex++;
+        ZenCodingNode more2 = parseAddOrMore();
+        if (more2 == null) {
+          return null;
+        }
+        return new MoreOperationNode(mul, more2);
+      }
+      return null;
+    }
+
+    @Nullable
+    private ZenCodingNode parseMul() {
+      ZenCodingNode exp = parseExpressionInBraces();
+      if (exp == null) {
+        return null;
+      }
+      ZenCodingToken operationToken = nextToken();
+      if (!(operationToken instanceof OperationToken)) {
+        return exp;
+      }
+      if (((OperationToken)operationToken).getSign() != '*') {
+        return exp;
+      }
+      myIndex++;
+      ZenCodingToken numberToken = nextToken();
+      if (numberToken instanceof NumberToken) {
+        myIndex++;
+        return new MulOperationNode(exp, ((NumberToken)numberToken).getNumber());
+      }
+      return new UnaryMulOperationNode(exp);
+    }
+
+    @Nullable
+    private ZenCodingNode parseExpressionInBraces() {
+      ZenCodingToken token = nextToken();
+      if (token == ZenCodingTokens.OPENING_R_BRACKET) {
+        myIndex++;
+        ZenCodingNode add = parseAddOrMore();
+        if (add == null) {
+          return null;
+        }
+        ZenCodingToken closingBrace = nextToken();
+        if (closingBrace != ZenCodingTokens.CLOSING_R_BRACKET) {
+          return null;
+        }
+        myIndex++;
+        return add;
+      }
+      else if (token instanceof TextToken) {
+        myIndex++;
+        return new TextNode((TextToken)token);
+
+      }
+
+      final ZenCodingNode templateNode = parseTemplate();
+      if (templateNode == null) {
+        return null;
+      }
+
+      token = nextToken();
+      if (token instanceof TextToken) {
+        myIndex++;
+        return new MoreOperationNode(templateNode, new TextNode((TextToken)token));
+      }
+      return templateNode;
+    }
+
+    @Nullable
+    private ZenCodingNode parseTemplate() {
+      final ZenCodingToken token = nextToken();
+      String templateKey = isHtml(myCallback) ? DEFAULT_TAG : null;
+      boolean mustHaveSelector = true;
+
+      if (token instanceof IdentifierToken) {
+        templateKey = ((IdentifierToken)token).getText();
+        mustHaveSelector = false;
+        myIndex++;
+      }
+
+      if (templateKey == null) {
+        return null;
+      }
+
+      final TemplateImpl template = myCallback.findApplicableTemplate(templateKey);
+      if (template == null && !isXML11ValidQName(templateKey)) {
+        return null;
+      }
+
+      final List<Pair<String, String>> attrList = parseSelectors();
+      if (mustHaveSelector && attrList.size() == 0) {
+        return null;
+      }
+
+      final TemplateToken templateToken = new TemplateToken(templateKey, attrList);
+
+      if (!setTemplate(templateToken, template)) {
+        return null;
+      }
+      return new TemplateNode(templateToken);
+    }
+
+    @SuppressWarnings("unchecked")
+    @NotNull
+    private List<Pair<String, String>> parseSelectors() {
+      final List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
+
+      int classAttrPosition = -1;
+      int idAttrPosition = -1;
+
+      final StringBuilder classAttrBuilder = new StringBuilder();
+      final StringBuilder idAttrBuilder = new StringBuilder();
+
+      while (true) {
+        final List<Pair<String, String>> attrList = parseSelector();
+        if (attrList == null) {
+          if (classAttrPosition != -1) {
+            result.set(classAttrPosition, new Pair<String, String>(CLASS, classAttrBuilder.toString()));
+          }
+          if (idAttrPosition != -1) {
+            result.set(idAttrPosition, new Pair<String, String>(ID, idAttrBuilder.toString()));
+          }
+          return result;
+        }
+
+        for (Pair<String, String> attr : attrList) {
+          if (CLASS.equals(attr.first)) {
+            if (classAttrBuilder.length() > 0) {
+              classAttrBuilder.append(' ');
+            }
+            classAttrBuilder.append(attr.second);
+            if (classAttrPosition == -1) {
+              classAttrPosition = result.size();
+              result.add(attr);
+            }
+          }
+          else if (ID.equals(attr.first)) {
+            if (idAttrBuilder.length() > 0) {
+              idAttrBuilder.append(' ');
+            }
+            idAttrBuilder.append(attr.second);
+            if (idAttrPosition == -1) {
+              idAttrPosition = result.size();
+              result.add(attr);
+            }
+          }
+          else {
+            result.add(attr);
+          }
+        }
+      }
+    }
+
+    @Nullable
+    private List<Pair<String, String>> parseSelector() {
+      ZenCodingToken token = nextToken();
+      if (token == ZenCodingTokens.OPENING_SQ_BRACKET) {
+        myIndex++;
+        final List<Pair<String, String>> attrList = parseAttributeList();
+        if (attrList == null || nextToken() != ZenCodingTokens.CLOSING_SQ_BRACKET) {
+          return null;
+        }
+        myIndex++;
+        return attrList;
+      }
+
+      if (token == ZenCodingTokens.DOT || token == ZenCodingTokens.SHARP) {
+        final String name = token == ZenCodingTokens.DOT ? CLASS : ID;
+        myIndex++;
+        token = nextToken();
+        final String value = getAttributeValueByToken(token);
+        myIndex++;
+        return value != null ? Collections.singletonList(new Pair<String, String>(name, value)) : null;
+      }
+
+      return null;
+    }
+
+    private boolean setTemplate(final TemplateToken token, TemplateImpl template) {
+      if (template == null) {
+        template = myGenerator.createTemplateByKey(token.getKey());
+      }
+      if (template == null) {
+        return false;
+      }
+      return doSetTemplate(token, template, myCallback);
+    }
+
+    @Nullable
+    private List<Pair<String, String>> parseAttributeList() {
+      final List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
+      while (true) {
+        final Pair<String, String> attribute = parseAttribute();
+        if (attribute == null) {
+          return result;
+        }
+        result.add(attribute);
+
+        final ZenCodingToken token = nextToken();
+        if (token != ZenCodingTokens.COMMA && token != ZenCodingTokens.SPACE) {
+          return result;
+        }
+        myIndex++;
+      }
+    }
+
+    @Nullable
+    private Pair<String, String> parseAttribute() {
+      ZenCodingToken token = nextToken();
+      if (!(token instanceof IdentifierToken)) {
+        return null;
+      }
+
+      final String name = ((IdentifierToken)token).getText();
+
+      myIndex++;
+      token = nextToken();
+      if (token != ZenCodingTokens.EQ) {
+        return new Pair<String, String>(name, "");
+      }
+
+      myIndex++;
+      final StringBuilder attrValueBuilder = new StringBuilder();
+      String value;
+      do {
+        token = nextToken();
+        value = token != null && token == ZenCodingTokens.SHARP ? token.toString() : getAttributeValueByToken(token);
+        if (value != null) {
+          attrValueBuilder.append(value);
+          myIndex++;
+        }
+      }
+      while (value != null);
+      return new Pair<String, String>(name, attrValueBuilder.toString());
+    }
+
+    @Nullable
+    private static String getAttributeValueByToken(ZenCodingToken token) {
+      if (token instanceof StringLiteralToken) {
+        final String text = ((StringLiteralToken)token).getText();
+        return text.substring(1, text.length() - 1);
+      }
+      else if (token instanceof IdentifierToken) {
+        return ((IdentifierToken)token).getText();
+      }
+      else if (token instanceof NumberToken) {
+        return Integer.toString(((NumberToken)token).getNumber());
+      }
+      return null;
+    }
+
+    @Nullable
+    private ZenCodingToken nextToken() {
+      if (myIndex < myTokens.size()) {
+        return myTokens.get(myIndex);
+      }
+      return null;
+    }
+
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/ZenCodingUtil.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/ZenCodingUtil.java
new file mode 100644
index 0000000..a72a2ed
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/ZenCodingUtil.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class ZenCodingUtil {
+  private static final char NUMBER_IN_ITERATION_PLACE_HOLDER = '$';
+  private static final String SURROUNDED_TEXT_MARKER = "$#";
+
+  private ZenCodingUtil() {
+  }
+
+  public static boolean containsSurroundedTextMarker(@NotNull String s) {
+    return s.contains(SURROUNDED_TEXT_MARKER);
+  }
+
+  public static String replaceMarkers(String s, int numberInIteration, @Nullable String surroundedText) {
+    final String by = Integer.toString(numberInIteration + 1);
+    StringBuilder builder = new StringBuilder(s.length());
+    int j = -1;
+    int i = 0;
+    int n = s.length();
+    while (i <= n) {
+      char c = i < n ? s.charAt(i) : 0;
+      if (c == NUMBER_IN_ITERATION_PLACE_HOLDER && (i == n - 1 || s.charAt(i + 1) != '#')) {
+        if (j == -1) {
+          j = i;
+        }
+      }
+      else {
+        if (j != -1) {
+          for (int k = 0, m = i - j - by.length(); k < m; k++) {
+            builder.append('0');
+          }
+          builder.append(by);
+          j = -1;
+        }
+        if (i < n) {
+          if (c == NUMBER_IN_ITERATION_PLACE_HOLDER && surroundedText != null) {
+            builder.append(surroundedText);
+            i++;
+          }
+          else {
+            builder.append(c);
+          }
+        }
+      }
+      i++;
+    }
+    return builder.toString();
+  }
+
+  public static String getValue(String value, int numberInIteration, String surroundedText) {
+    String s = replaceMarkers(value, numberInIteration, surroundedText);
+    return s.replace("\"", "&quot;");
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/CommentZenCodingFilter.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/CommentZenCodingFilter.java
new file mode 100644
index 0000000..612487f
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/CommentZenCodingFilter.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.filters;
+
+import com.intellij.codeInsight.template.zencoding.tokens.TemplateToken;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class CommentZenCodingFilter extends ZenCodingFilter {
+  private static String buildCommentString(@Nullable String classAttr, @Nullable String idAttr) {
+    StringBuilder builder = new StringBuilder();
+    if (idAttr != null) {
+      builder.append('#').append(idAttr);
+    }
+    if (classAttr != null) {
+      builder.append('.').append(classAttr);
+    }
+    return builder.toString();
+  }
+
+  @NotNull
+  @Override
+  public String filterText(@NotNull String text, @NotNull TemplateToken token) {
+    XmlDocument document = token.getFile().getDocument();
+    if (document != null) {
+      XmlTag tag = document.getRootTag();
+      if (tag != null) {
+        String classAttr = tag.getAttributeValue("class");
+        String idAttr = tag.getAttributeValue("id");
+        if (classAttr != null || idAttr != null) {
+          String commentString = buildCommentString(classAttr, idAttr);
+          return "<!-- " + commentString + " -->\n" + text + "\n<!-- /" + commentString + " -->";
+        }
+      }
+    }
+    return text;
+  }
+
+  @NotNull
+  @Override
+  public String getSuffix() {
+    return "c";
+  }
+
+  @Override
+  public boolean isMyContext(@NotNull PsiElement context) {
+    return context.getLanguage() instanceof XMLLanguage;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/EscapeZenCodingFilter.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/EscapeZenCodingFilter.java
new file mode 100644
index 0000000..8c3abe8
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/EscapeZenCodingFilter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.filters;
+
+import com.intellij.codeInsight.template.zencoding.tokens.TemplateToken;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class EscapeZenCodingFilter extends ZenCodingFilter {
+  @NotNull
+  @Override
+  public String filterText(@NotNull String s, @NotNull TemplateToken token) {
+    s = s.replace("&", "&amp;");
+    s = s.replace("<", "&lt;");
+    s = s.replace(">", "&gt;");
+    return s;
+  }
+
+  @NotNull
+  @Override
+  public String getSuffix() {
+    return "e";
+  }
+
+  @Override
+  public boolean isMyContext(@NotNull PsiElement context) {
+    return context.getLanguage() instanceof XMLLanguage;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/TrimZenCodingFilter.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/TrimZenCodingFilter.java
new file mode 100644
index 0000000..f6c26f1
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/TrimZenCodingFilter.java
@@ -0,0 +1,43 @@
+package com.intellij.codeInsight.template.zencoding.filters;
+
+import com.intellij.codeInsight.template.zencoding.nodes.GenerationNode;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.regex.Pattern;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class TrimZenCodingFilter extends ZenCodingFilter {
+  private static final Pattern PATTERN = Pattern.compile("^([\\s|\u00a0])?[\\d|#|\\-|\\*|\u2022]+\\.?\\s*");
+
+  @NotNull
+  @Override
+  public String getSuffix() {
+    return "t";
+  }
+
+  @Override
+  public boolean isMyContext(@NotNull PsiElement context) {
+    return context.getLanguage() instanceof XMLLanguage;
+  }
+
+  @NotNull
+  @Override
+  public GenerationNode filterNode(@NotNull GenerationNode node) {
+    doFilter(node);
+    return node;
+  }
+
+  private static void doFilter(GenerationNode node) {
+    final String surroundedText = node.getSurroundedText();
+    if (surroundedText != null) {
+      node.setSurroundedText(PATTERN.matcher(surroundedText).replaceAll(""));
+    }
+    for (GenerationNode child : node.getChildren()) {
+      doFilter(child);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/XslZenCodingFilter.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/XslZenCodingFilter.java
new file mode 100644
index 0000000..3a05ca2
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/XslZenCodingFilter.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.filters;
+
+import com.intellij.codeInsight.template.zencoding.generators.XmlZenCodingGenerator;
+import com.intellij.codeInsight.template.zencoding.generators.XmlZenCodingGeneratorImpl;
+import com.intellij.codeInsight.template.zencoding.nodes.GenerationNode;
+import com.intellij.codeInsight.template.zencoding.tokens.TemplateToken;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class XslZenCodingFilter extends ZenCodingFilter {
+  private final XmlZenCodingGenerator myDelegate = new XmlZenCodingGeneratorImpl();
+  @NonNls private static final String SELECT_ATTR_NAME = "select";
+
+  @NotNull
+  @Override
+  public GenerationNode filterNode(@NotNull final GenerationNode node) {
+    TemplateToken token = node.getTemplateToken();
+    if (token != null) {
+      TemplateToken xmlToken = token;
+      XmlDocument document = xmlToken.getFile().getDocument();
+      if (document != null) {
+        final XmlTag tag = document.getRootTag();
+        if (tag != null) {
+          for (Pair<String, String> pair : xmlToken.getAttribute2Value()) {
+            if (SELECT_ATTR_NAME.equals(pair.first)) {
+              return node;
+            }
+          }
+          ApplicationManager.getApplication().runWriteAction(new Runnable() {
+            @Override
+            public void run() {
+              if (isOurTag(tag, node.getChildren().size() > 0)) {
+                XmlAttribute attribute = tag.getAttribute(SELECT_ATTR_NAME);
+                if (attribute != null) {
+                  attribute.delete();
+                }
+              }
+            }
+          });
+          return node;
+        }
+      }
+    }
+    return node;
+  }
+
+  private static boolean isOurTag(XmlTag tag, boolean hasChildren) {
+    if (hasChildren) {
+      String name = tag.getLocalName();
+      return name.equals("with-param") || name.equals("variable");
+    }
+    return false;
+  }
+
+  @Override
+  public boolean isMyContext(@NotNull PsiElement context) {
+    return myDelegate.isMyContext(context, true) ||
+           myDelegate.isMyContext(context, false);
+  }
+
+  @NotNull
+  @Override
+  public String getSuffix() {
+    return "xsl";
+  }
+
+  @Override
+  public boolean isAppliedByDefault(@NotNull PsiElement context) {
+    VirtualFile vFile = context.getContainingFile().getVirtualFile();
+    return vFile != null && "xsl".equals(vFile.getExtension());
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/ZenCodingFilter.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/ZenCodingFilter.java
new file mode 100644
index 0000000..5ab6ada
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/filters/ZenCodingFilter.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.filters;
+
+import com.intellij.codeInsight.template.zencoding.nodes.GenerationNode;
+import com.intellij.codeInsight.template.zencoding.tokens.TemplateToken;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class ZenCodingFilter {
+  public static final ExtensionPointName<ZenCodingFilter> EP_NAME =
+    new ExtensionPointName<ZenCodingFilter>("com.intellij.xml.zenCodingFilter");
+
+  private static final ZenCodingFilter[] ourStandartFilters = new ZenCodingFilter[]{
+    new XslZenCodingFilter(),
+    new CommentZenCodingFilter(),
+    new EscapeZenCodingFilter(),
+    new TrimZenCodingFilter()
+  };
+
+  @NotNull
+  public String filterText(@NotNull String text, @NotNull TemplateToken token) {
+    return text;
+  }
+
+  @NotNull
+  public GenerationNode filterNode(@NotNull GenerationNode node) {
+    return node;
+  }
+
+  @NotNull
+  public abstract String getSuffix();
+
+  public abstract boolean isMyContext(@NotNull PsiElement context);
+
+  public boolean isAppliedByDefault(@NotNull PsiElement context) {
+    return false;
+  }
+
+  public static List<ZenCodingFilter> getInstances() {
+    List<ZenCodingFilter> generators = new ArrayList<ZenCodingFilter>();
+    Collections.addAll(generators, ourStandartFilters);
+    Collections.addAll(generators, EP_NAME.getExtensions());
+    return generators;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/generators/XmlZenCodingGenerator.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/generators/XmlZenCodingGenerator.java
new file mode 100644
index 0000000..07f22e5
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/generators/XmlZenCodingGenerator.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.generators;
+
+import com.intellij.codeInsight.template.impl.TemplateImpl;
+import com.intellij.codeInsight.template.zencoding.tokens.TemplateToken;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class XmlZenCodingGenerator extends ZenCodingGenerator {
+  @Override
+  public TemplateImpl generateTemplate(@NotNull TemplateToken token, boolean hasChildren, @NotNull PsiElement context) {
+    String s = toString(token, hasChildren, context);
+    TemplateImpl template = token.getTemplate().copy();
+    template.setString(s);
+    return template;
+  }
+
+  @Override
+  public TemplateImpl createTemplateByKey(@NotNull String key) {
+    StringBuilder builder = new StringBuilder("<");
+    builder.append(key).append('>');
+    if (!HtmlUtil.isSingleHtmlTag(key)) {
+      builder.append("$END$</").append(key).append('>');
+    }
+    return new TemplateImpl("", builder.toString(), "");
+  }
+
+  @NotNull
+  private String toString(@NotNull TemplateToken token, boolean hasChildren, @NotNull PsiElement context) {
+    XmlFile file = token.getFile();
+    XmlDocument document = file.getDocument();
+    if (document != null) {
+      XmlTag tag = document.getRootTag();
+      if (tag != null) {
+        return toString(tag, token.getAttribute2Value(), hasChildren, context);
+      }
+    }
+    return file.getText();
+  }
+
+  public abstract String toString(@NotNull XmlTag tag,
+                                  @NotNull List<Pair<String, String>> attribute2Value,
+                                  boolean hasChildren,
+                                  @NotNull PsiElement context);
+
+  @NotNull
+  public abstract String buildAttributesString(@NotNull List<Pair<String, String>> attribute2value,
+                                               boolean hasChildren,
+                                               int numberInIteration,
+                                               @Nullable String surroundedText);
+
+  public abstract boolean isMyContext(@NotNull PsiElement context, boolean wrapping);
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/generators/XmlZenCodingGeneratorImpl.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/generators/XmlZenCodingGeneratorImpl.java
new file mode 100644
index 0000000..b9ee262
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/generators/XmlZenCodingGeneratorImpl.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.generators;
+
+import com.intellij.codeInsight.template.HtmlTextContextType;
+import com.intellij.codeInsight.template.zencoding.ZenCodingUtil;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class XmlZenCodingGeneratorImpl extends XmlZenCodingGenerator {
+  public static final XmlZenCodingGeneratorImpl INSTANCE = new XmlZenCodingGeneratorImpl();
+
+  private static boolean isTrueXml(FileType type) {
+    return type == StdFileTypes.XHTML || type == StdFileTypes.JSPX || type == StdFileTypes.XML;
+  }
+
+  @NotNull
+  public String toString(@NotNull XmlTag tag,
+                         @NotNull List<Pair<String, String>> attribute2Value,
+                         boolean hasChildren,
+                         @NotNull PsiElement context) {
+    FileType fileType = context.getContainingFile().getFileType();
+    if (isTrueXml(fileType)) {
+      closeUnclosingTags(tag);
+    }
+    return tag.getContainingFile().getText();
+  }
+
+  @NotNull
+  public String buildAttributesString(@NotNull List<Pair<String, String>> attribute2value,
+                                      boolean hasChildren,
+                                      int numberInIteration,
+                                      @Nullable String surroundedText) {
+    StringBuilder result = new StringBuilder();
+    for (Iterator<Pair<String, String>> it = attribute2value.iterator(); it.hasNext();) {
+      Pair<String, String> pair = it.next();
+      String name = pair.first;
+      String value = ZenCodingUtil.getValue(pair.second, numberInIteration, surroundedText);
+      result.append(getAttributeString(name, value));
+      if (it.hasNext()) {
+        result.append(' ');
+      }
+    }
+    return result.toString();
+  }
+
+  public boolean isMyContext(@NotNull PsiElement context, boolean wrapping) {
+    return isMyLanguage(context.getLanguage()) && (wrapping || HtmlTextContextType.isInContext(context));
+  }
+
+  protected boolean isMyLanguage(Language language) {
+    return language instanceof XMLLanguage;
+  }
+
+  public String getSuffix() {
+    return "html";
+  }
+
+  public boolean isAppliedByDefault(@NotNull PsiElement context) {
+    return true;
+  }
+
+  private static String getAttributeString(String name, String value) {
+    return name + "=\"" + value + '"';
+  }
+
+  @SuppressWarnings({"ConstantConditions"})
+  private static void closeUnclosingTags(@NotNull XmlTag root) {
+    final List<SmartPsiElementPointer<XmlTag>> tagToClose = new ArrayList<SmartPsiElementPointer<XmlTag>>();
+    Project project = root.getProject();
+    final SmartPointerManager pointerManager = SmartPointerManager.getInstance(project);
+    root.accept(new XmlRecursiveElementVisitor() {
+      @Override
+      public void visitXmlTag(final XmlTag tag) {
+        if (!isTagClosed(tag)) {
+          tagToClose.add(pointerManager.createLazyPointer(tag));
+        }
+      }
+    });
+    PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
+    for (final SmartPsiElementPointer<XmlTag> pointer : tagToClose) {
+      final XmlTag tag = pointer.getElement();
+      if (tag != null) {
+        final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode());
+        if (child != null) {
+          final int offset = child.getTextRange().getStartOffset();
+          VirtualFile file = tag.getContainingFile().getVirtualFile();
+          if (file != null) {
+            final Document document = FileDocumentManager.getInstance().getDocument(file);
+            documentManager.doPostponedOperationsAndUnblockDocument(document);
+            ApplicationManager.getApplication().runWriteAction(new Runnable() {
+              public void run() {
+                document.replaceString(offset, tag.getTextRange().getEndOffset(), "/>");
+              }
+            });
+          }
+        }
+      }
+    }
+    documentManager.commitAllDocuments();
+  }
+
+  private static boolean isTagClosed(@NotNull XmlTag tag) {
+    ASTNode node = tag.getNode();
+    assert node != null;
+    final ASTNode emptyTagEnd = XmlChildRole.EMPTY_TAG_END_FINDER.findChild(node);
+    final ASTNode endTagEnd = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(node);
+    return emptyTagEnd != null || endTagEnd != null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/generators/ZenCodingGenerator.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/generators/ZenCodingGenerator.java
new file mode 100644
index 0000000..abd3926
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/generators/ZenCodingGenerator.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.generators;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import com.intellij.codeInsight.template.impl.TemplateImpl;
+import com.intellij.codeInsight.template.zencoding.ZenCodingTemplate;
+import com.intellij.codeInsight.template.zencoding.tokens.TemplateToken;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.impl.source.tree.LeafPsiElement;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class ZenCodingGenerator {
+  private static final ExtensionPointName<ZenCodingGenerator> EP_NAME =
+    new ExtensionPointName<ZenCodingGenerator>("com.intellij.xml.zenCodingGenerator");
+
+  public abstract TemplateImpl generateTemplate(@NotNull TemplateToken token, boolean hasChildren, @NotNull PsiElement context);
+
+  @Nullable
+  public TemplateImpl createTemplateByKey(@NotNull String key) {
+    return null;
+  }
+
+  public abstract boolean isMyContext(@NotNull PsiElement context, boolean wrapping);
+
+  @Nullable
+  public String getSuffix() {
+    return null;
+  }
+
+  public abstract boolean isAppliedByDefault(@NotNull PsiElement context);
+
+  public static List<ZenCodingGenerator> getInstances() {
+    List<ZenCodingGenerator> generators = new ArrayList<ZenCodingGenerator>();
+    Collections.addAll(generators, XmlZenCodingGeneratorImpl.INSTANCE);
+    Collections.addAll(generators, EP_NAME.getExtensions());
+    return generators;
+  }
+
+  @Nullable
+  public String computeTemplateKey(@NotNull CustomTemplateCallback callback) {
+    Editor editor = callback.getEditor();
+    PsiElement element = callback.getContext();
+    int line = editor.getCaretModel().getLogicalPosition().line;
+    int lineStart = editor.getDocument().getLineStartOffset(line);
+    int elementStart = -1;
+    do {
+      PsiElement e = element;
+      while ((e instanceof LeafPsiElement && ((LeafPsiElement)e).getElementType() == XmlTokenType.XML_DATA_CHARACTERS) ||
+             e instanceof PsiWhiteSpace || e instanceof PsiErrorElement) {
+        elementStart = e.getTextRange().getStartOffset();
+        e = e.getPrevSibling();
+      }
+      if (elementStart >= 0) {
+        int startOffset = elementStart > lineStart ? elementStart : lineStart;
+        String key = computeKey(editor, startOffset);
+        if (key != null) {
+          while (key.length() > 0 && !ZenCodingTemplate.checkTemplateKey(key, callback, this)) {
+            key = key.substring(1);
+          }
+          if (key.length() > 0) {
+            return key;
+          }
+        }
+      }
+      element = element.getParent();
+    }
+    while (element != null && elementStart > lineStart);
+    return null;
+  }
+
+  @Nullable
+  protected static String computeKey(Editor editor, int startOffset) {
+    int offset = editor.getCaretModel().getOffset();
+    String s = editor.getDocument().getCharsSequence().subSequence(startOffset, offset).toString();
+    int index = 0;
+    while (index < s.length() && Character.isWhitespace(s.charAt(index))) {
+      index++;
+    }
+    String key = s.substring(index);
+    int lastWhitespaceIndex = -1;
+    int lastQuoteIndex = -1;
+    int lastApostropheIndex = -1;
+    boolean inBrackets = false;
+    int bracesStack = 0;
+
+    for (int i = 0; i < key.length(); i++) {
+      char c = key.charAt(i);
+      if (lastQuoteIndex >= 0 || lastApostropheIndex >= 0) {
+        if (c == '"') {
+          lastQuoteIndex = -1;
+        }
+        else if (c == '\'') lastApostropheIndex = -1;
+      }
+      else if (Character.isWhitespace(c)) {
+        lastWhitespaceIndex = i;
+      }
+      else if (c == '"') {
+        lastQuoteIndex = i;
+      }
+      else if (c == '\'') {
+        lastApostropheIndex = i;
+      }
+      else if (c == '[') {
+        inBrackets = true;
+      }
+      else if (c == ']' && inBrackets) {
+        lastWhitespaceIndex = -1;
+        inBrackets = false;
+      }
+      else if (c == '{') {
+        bracesStack++;
+      }
+      else if (c == '}' && bracesStack > 0) {
+        bracesStack--;
+        if (bracesStack == 0) {
+          lastWhitespaceIndex = -1;
+        }
+      }
+    }
+    if (lastQuoteIndex >= 0 || lastApostropheIndex >= 0) {
+      int max = Math.max(lastQuoteIndex, lastApostropheIndex);
+      return max < key.length() - 1 ? key.substring(max) : null;
+    }
+    if (lastWhitespaceIndex >= 0 && lastWhitespaceIndex < key.length() - 1) {
+      return key.substring(lastWhitespaceIndex + 1);
+    }
+    return key;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/AddOperationNode.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/AddOperationNode.java
new file mode 100644
index 0000000..1894ae7
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/AddOperationNode.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.nodes;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class AddOperationNode extends ZenCodingNode {
+  private final ZenCodingNode myLeftOperand;
+  private final ZenCodingNode myRightOperand;
+
+  public AddOperationNode(ZenCodingNode leftOperand, ZenCodingNode rightOperand) {
+    myLeftOperand = leftOperand;
+    myRightOperand = rightOperand;
+  }
+
+  public ZenCodingNode getLeftOperand() {
+    return myLeftOperand;
+  }
+
+  public ZenCodingNode getRightOperand() {
+    return myRightOperand;
+  }
+
+  @NotNull
+  @Override
+  public List<GenerationNode> expand(int numberInIteration,
+                                     String surroundedText,
+                                     CustomTemplateCallback callback,
+                                     boolean insertSurroundedTextAtTheEnd) {
+    List<GenerationNode> result = new ArrayList<GenerationNode>();
+    List<GenerationNode> leftNodes = myLeftOperand.expand(numberInIteration, surroundedText, callback, false);
+    result.addAll(leftNodes);
+    result.addAll(myRightOperand.expand(numberInIteration, surroundedText, callback, insertSurroundedTextAtTheEnd));
+    return result;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/FilterNode.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/FilterNode.java
new file mode 100644
index 0000000..7ff67f1
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/FilterNode.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.nodes;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class FilterNode extends ZenCodingNode {
+  private final ZenCodingNode myNode;
+  private final String myFilter;
+
+  public FilterNode(ZenCodingNode node, String filter) {
+    myNode = node;
+    myFilter = filter;
+  }
+
+  public ZenCodingNode getNode() {
+    return myNode;
+  }
+
+  public String getFilter() {
+    return myFilter;
+  }
+
+  @NotNull
+  @Override
+  public List<GenerationNode> expand(int numberInIteration,
+                                     String surroundedText,
+                                     CustomTemplateCallback callback,
+                                     boolean insertSurroundedTextAtTheEnd) {
+    return myNode.expand(numberInIteration, surroundedText, callback, insertSurroundedTextAtTheEnd);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/GenerationNode.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/GenerationNode.java
new file mode 100644
index 0000000..a07b521
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/GenerationNode.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.nodes;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import com.intellij.codeInsight.template.LiveTemplateBuilder;
+import com.intellij.codeInsight.template.impl.TemplateImpl;
+import com.intellij.codeInsight.template.zencoding.ZenCodingTemplate;
+import com.intellij.codeInsight.template.zencoding.ZenCodingUtil;
+import com.intellij.codeInsight.template.zencoding.generators.XmlZenCodingGenerator;
+import com.intellij.codeInsight.template.zencoding.generators.XmlZenCodingGeneratorImpl;
+import com.intellij.codeInsight.template.zencoding.filters.ZenCodingFilter;
+import com.intellij.codeInsight.template.zencoding.generators.ZenCodingGenerator;
+import com.intellij.codeInsight.template.zencoding.tokens.TemplateToken;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.LocalTimeCounter;
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.HashSet;
+import com.intellij.util.containers.IntArrayList;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class GenerationNode {
+  private final TemplateToken myTemplateToken;
+  private final List<GenerationNode> myChildren;
+  private final int myNumberInIteration;
+  private String mySurroundedText;
+  private final boolean myInsertSurroundedTextAtTheEnd;
+
+  private boolean myContainsSurroundedTextMarker = false;
+
+  public GenerationNode(TemplateToken templateToken,
+                        List<GenerationNode> children,
+                        int numberInIteration,
+                        String surroundedText,
+                        boolean insertSurroundedTextAtTheEnd) {
+    myTemplateToken = templateToken;
+    myChildren = children;
+    myNumberInIteration = numberInIteration;
+    mySurroundedText = surroundedText;
+    myInsertSurroundedTextAtTheEnd = insertSurroundedTextAtTheEnd;
+  }
+
+  public List<GenerationNode> getChildren() {
+    return myChildren;
+  }
+
+  public void addChildren(Collection<GenerationNode> child) {
+    myChildren.addAll(child);
+  }
+
+  public boolean isLeaf() {
+    return myChildren.size() == 0;
+  }
+
+  private boolean isBlockTag() {
+    if (myTemplateToken != null) {
+      XmlFile xmlFile = myTemplateToken.getFile();
+      XmlDocument document = xmlFile.getDocument();
+      if (document != null) {
+        XmlTag tag = document.getRootTag();
+        if (tag != null) {
+          return HtmlUtil.isHtmlBlockTagL(tag.getName());
+        }
+      }
+    }
+    return false;
+  }
+
+  @NotNull
+  public TemplateImpl generate(@NotNull CustomTemplateCallback callback,
+                                @Nullable ZenCodingGenerator generator,
+                                @NotNull Collection<ZenCodingFilter> filters,
+                                boolean insertSurroundedText) {
+    myContainsSurroundedTextMarker = !(insertSurroundedText && myInsertSurroundedTextAtTheEnd);
+
+    GenerationNode generationNode = this;
+    for (ZenCodingFilter filter : filters) {
+      generationNode = filter.filterNode(generationNode);
+    }
+
+    if (generationNode != this) {
+      return generationNode.generate(callback, generator, Collections.<ZenCodingFilter>emptyList(), insertSurroundedText);
+    }
+
+    LiveTemplateBuilder builder = new LiveTemplateBuilder();
+    int end = -1;
+
+    boolean hasChildren = myChildren.size() > 0;
+
+    TemplateImpl parentTemplate;
+    Map<String, String> predefinedValues;
+    if (myTemplateToken instanceof TemplateToken && generator instanceof XmlZenCodingGenerator) {
+      TemplateToken xmlTemplateToken = myTemplateToken;
+      List<Pair<String, String>> attr2value = new ArrayList<Pair<String, String>>(xmlTemplateToken.getAttribute2Value());
+      parentTemplate = invokeXmlTemplate(xmlTemplateToken, callback, generator, hasChildren, attr2value);
+      predefinedValues =
+        buildPredefinedValues(attr2value, (XmlZenCodingGenerator)generator, hasChildren);
+    }
+    else {
+      parentTemplate = invokeTemplate(myTemplateToken, hasChildren, callback, generator);
+      predefinedValues = null;
+    }
+
+    String s = parentTemplate.getString();
+    for (ZenCodingFilter filter : filters) {
+      s = filter.filterText(s, myTemplateToken);
+    }
+    parentTemplate = parentTemplate.copy();
+    parentTemplate.setString(s);
+
+    final String txt = hasChildren || myContainsSurroundedTextMarker ? null : mySurroundedText;
+    parentTemplate = expandTemplate(parentTemplate, predefinedValues, txt);
+
+    int offset = builder.insertTemplate(0, parentTemplate, null);
+    int newOffset = gotoChild(callback.getProject(), builder.getText(), offset, 0, builder.length());
+    if (offset < builder.length() && newOffset != offset) {
+      end = offset;
+    }
+    offset = newOffset;
+    if (end == -1 && offset < builder.length() && myChildren.size() == 0) {
+      end = offset;
+    }
+    LiveTemplateBuilder.Marker marker = offset < builder.length() ? builder.createMarker(offset) : null;
+
+    CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(callback.getProject());
+    String tabStr;
+    if (callback.isInInjectedFragment()) {
+      tabStr = "";
+    }
+    else if (settings.useTabCharacter(callback.getFileType())) {
+      tabStr = "\t";
+    }
+    else {
+      StringBuilder tab = new StringBuilder();
+      int tabSize = settings.getTabSize(callback.getFileType());
+      while (tabSize-- > 0) {
+        tab.append(' ');
+      }
+      tabStr = tab.toString();
+    }
+
+    for (int i = 0, myChildrenSize = myChildren.size(); i < myChildrenSize; i++) {
+      GenerationNode child = myChildren.get(i);
+      TemplateImpl childTemplate = child.generate(callback, generator, filters, !myContainsSurroundedTextMarker);
+
+      boolean blockTag = child.isBlockTag();
+
+      if (blockTag && !isNewLineBefore(builder.getText(), offset)) {
+        builder.insertText(offset, "\n" + tabStr, false);
+        offset += tabStr.length() + 1;
+      }
+
+      int e = builder.insertTemplate(offset, childTemplate, null);
+      offset = marker != null ? marker.getEndOffset() : builder.length();
+
+      if (blockTag && !isNewLineAfter(builder.getText(), offset)) {
+        builder.insertText(offset, "\n" + tabStr, false);
+        offset += tabStr.length() + 1;
+      }
+
+      if (end == -1 && e < offset) {
+        end = e;
+      }
+    }
+    /*if (end != -1) {
+      builder.insertVariableSegment(end, TemplateImpl.END);
+    }*/
+    return builder.buildTemplate();
+  }
+
+  private static TemplateImpl invokeTemplate(TemplateToken token,
+                                             boolean hasChildren,
+                                             final CustomTemplateCallback callback,
+                                             @Nullable ZenCodingGenerator generator) {
+    TemplateImpl template = token.getTemplate();
+    if (generator != null) {
+      assert template != null;
+      template = generator.generateTemplate(token, hasChildren, callback.getContext());
+      removeVariablesWhichHasNoSegment(template);
+    }
+
+    return template;
+  }
+
+  private TemplateImpl invokeXmlTemplate(final TemplateToken token,
+                                                CustomTemplateCallback callback,
+                                                @Nullable ZenCodingGenerator generator,
+                                                final boolean hasChildren,
+                                                final List<Pair<String, String>> attr2value) {
+    /*assert generator == null || generator instanceof XmlZenCodingGenerator :
+      "The generator cannot process TemplateToken because it doesn't inherit XmlZenCodingGenerator";*/
+
+    TemplateImpl template = token.getTemplate();
+    assert template != null;
+
+    final XmlFile xmlFile = token.getFile();
+    XmlDocument document = xmlFile.getDocument();
+    if (document != null) {
+      final XmlTag tag = document.getRootTag();
+      if (tag != null) {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          public void run() {
+            XmlTag tag1 = hasChildren ? expandEmptyTagIfNeccessary(tag) : tag;
+            setAttributeValues(tag1, attr2value);
+            token.setFile((XmlFile)tag1.getContainingFile());
+          }
+        });
+      }
+    }
+    template =
+      (generator != null ? generator : XmlZenCodingGeneratorImpl.INSTANCE).generateTemplate(token, hasChildren, callback.getContext());
+    removeVariablesWhichHasNoSegment(template);
+    return template;
+  }
+
+  @NotNull
+  private static TemplateImpl expandTemplate(@NotNull TemplateImpl template,
+                                             Map<String, String> predefinedVarValues,
+                                             String surroundedText) {
+    LiveTemplateBuilder builder = new LiveTemplateBuilder();
+    if (predefinedVarValues == null && surroundedText == null) {
+      return template;
+    }
+    int offset = builder.insertTemplate(0, template, predefinedVarValues);
+    if (surroundedText != null) {
+      builder.insertText(offset, surroundedText, true);
+      /*if (offset < builder.length()) {
+        builder.insertVariableSegment(offset, TemplateImpl.END);
+      }*/
+    }
+    return builder.buildTemplate();
+  }
+
+  @NotNull
+  private static XmlTag expandEmptyTagIfNeccessary(@NotNull XmlTag tag) {
+    StringBuilder builder = new StringBuilder();
+    boolean flag = false;
+
+    for (PsiElement child : tag.getChildren()) {
+      if (child instanceof XmlToken && XmlTokenType.XML_EMPTY_ELEMENT_END.equals(((XmlToken)child).getTokenType())) {
+        flag = true;
+        break;
+      }
+      builder.append(child.getText());
+    }
+
+    if (flag) {
+      builder.append("></").append(tag.getName()).append('>');
+      final XmlTag tag1 = XmlElementFactory.getInstance(tag.getProject()).createTagFromText(builder.toString(), XMLLanguage.INSTANCE);
+      return tag1;
+    }
+    return tag;
+  }
+
+  private static int gotoChild(Project project, CharSequence text, int offset, int start, int end) {
+    PsiFile file = PsiFileFactory.getInstance(project)
+      .createFileFromText("dummy.xml", StdFileTypes.XML, text, LocalTimeCounter.currentTime(), false);
+
+    PsiElement element = file.findElementAt(offset);
+    if (offset < end && element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_END_TAG_START) {
+      return offset;
+    }
+
+    int newOffset = -1;
+    XmlTag tag = PsiTreeUtil.findElementOfClassAtRange(file, start, end, XmlTag.class);
+    if (tag != null) {
+      for (PsiElement child : tag.getChildren()) {
+        if (child instanceof XmlToken && ((XmlToken)child).getTokenType() == XmlTokenType.XML_END_TAG_START) {
+          newOffset = child.getTextOffset();
+        }
+      }
+    }
+
+    if (newOffset >= 0) {
+      return newOffset;
+    }
+
+    return offset;
+  }
+
+  private static void removeVariablesWhichHasNoSegment(TemplateImpl template) {
+    Set<String> segments = new HashSet<String>();
+    for (int i = 0; i < template.getSegmentsCount(); i++) {
+      segments.add(template.getSegmentName(i));
+    }
+    IntArrayList varsToRemove = new IntArrayList();
+    for (int i = 0; i < template.getVariableCount(); i++) {
+      String varName = template.getVariableNameAt(i);
+      if (!segments.contains(varName)) {
+        varsToRemove.add(i);
+      }
+    }
+    for (int i = 0; i < varsToRemove.size(); i++) {
+      template.removeVariable(varsToRemove.get(i));
+    }
+  }
+
+  @Nullable
+  private Map<String, String> buildPredefinedValues(List<Pair<String, String>> attribute2value,
+                                                    @Nullable XmlZenCodingGenerator generator,
+                                                    boolean hasChildren) {
+    if (generator == null) {
+      return Collections.emptyMap();
+    }
+
+    for (Pair<String, String> pair : attribute2value) {
+      if (ZenCodingUtil.containsSurroundedTextMarker(pair.second)) {
+        myContainsSurroundedTextMarker = true;
+        break;
+      }
+    }
+
+    String attributes = generator.buildAttributesString(attribute2value, hasChildren, myNumberInIteration, mySurroundedText);
+    attributes = attributes.length() > 0 ? ' ' + attributes : null;
+    Map<String, String> predefinedValues = null;
+    if (attributes != null) {
+      predefinedValues = new HashMap<String, String>();
+      predefinedValues.put(ZenCodingTemplate.ATTRS, attributes);
+    }
+    return predefinedValues;
+  }
+
+  private void setAttributeValues(XmlTag tag, List<Pair<String, String>> attr2value) {
+    for (Iterator<Pair<String, String>> iterator = attr2value.iterator(); iterator.hasNext();) {
+      Pair<String, String> pair = iterator.next();
+      if (tag.getAttribute(pair.first) != null) {
+        if (ZenCodingUtil.containsSurroundedTextMarker(pair.second)) {
+          myContainsSurroundedTextMarker = true;
+        }
+        tag.setAttribute(pair.first, ZenCodingUtil.getValue(pair.second, myNumberInIteration, mySurroundedText));
+        iterator.remove();
+      }
+    }
+  }
+
+  private static boolean isNewLineBefore(CharSequence text, int offset) {
+    int i = offset - 1;
+    while (i >= 0 && Character.isWhitespace(text.charAt(i))) {
+      if (text.charAt(i) == '\n') {
+        return true;
+      }
+      i--;
+    }
+    return i < 0;
+  }
+
+  private static boolean isNewLineAfter(CharSequence text, int offset) {
+    int i = offset;
+    while (i < text.length() && Character.isWhitespace(text.charAt(i))) {
+      if (text.charAt(i) == '\n') {
+        return true;
+      }
+      i++;
+    }
+    return i == text.length();
+  }
+
+  public TemplateToken getTemplateToken() {
+    return myTemplateToken;
+  }
+
+  public String getSurroundedText() {
+    return mySurroundedText;
+  }
+
+  public void setSurroundedText(String surroundedText) {
+    mySurroundedText = surroundedText;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/MoreOperationNode.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/MoreOperationNode.java
new file mode 100644
index 0000000..8e32e50
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/MoreOperationNode.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.nodes;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import com.intellij.openapi.util.text.LineTokenizer;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class MoreOperationNode extends ZenCodingNode {
+  private final ZenCodingNode myLeftOperand;
+  private final ZenCodingNode myRightOperand;
+
+  public MoreOperationNode(ZenCodingNode leftOperand, ZenCodingNode rightOperand) {
+    myLeftOperand = leftOperand;
+    myRightOperand = rightOperand;
+  }
+
+  public ZenCodingNode getLeftOperand() {
+    return myLeftOperand;
+  }
+
+  public ZenCodingNode getRightOperand() {
+    return myRightOperand;
+  }
+
+  private static void addChildrenToAllLeafs(GenerationNode root, Collection<GenerationNode> children) {
+    if (root.isLeaf()) {
+      root.addChildren(children);
+    }
+    else {
+      for (GenerationNode child : root.getChildren()) {
+        addChildrenToAllLeafs(child, children);
+      }
+    }
+  }
+
+  @NotNull
+  @Override
+  public List<GenerationNode> expand(int numberInIteration,
+                                     String surroundedText,
+                                     CustomTemplateCallback callback,
+                                     boolean insertSurroundedTextAtTheEnd) {
+    if (myLeftOperand instanceof MulOperationNode || (myLeftOperand instanceof UnaryMulOperationNode && surroundedText != null)) {
+      List<GenerationNode> result = new ArrayList<GenerationNode>();
+      if (myLeftOperand instanceof MulOperationNode) {
+        MulOperationNode mul = (MulOperationNode)myLeftOperand;
+        for (int i = 0; i < mul.getRightOperand(); i++) {
+          List<GenerationNode> parentNodes = mul.getLeftOperand().expand(i, surroundedText, callback, insertSurroundedTextAtTheEnd);
+          List<GenerationNode> innerNodes = myRightOperand.expand(i, surroundedText, callback, insertSurroundedTextAtTheEnd);
+          for (GenerationNode parentNode : parentNodes) {
+            addChildrenToAllLeafs(parentNode, innerNodes);
+          }
+          result.addAll(parentNodes);
+        }
+      }
+      else {
+        UnaryMulOperationNode unaryMul = (UnaryMulOperationNode)myLeftOperand;
+        String[] lines = LineTokenizer.tokenize(surroundedText, false);
+        for (int i = 0; i < lines.length; i++) {
+          String line = lines[i].trim();
+          List<GenerationNode> parentNodes = unaryMul.getOperand().expand(i, line, callback, insertSurroundedTextAtTheEnd);
+          List<GenerationNode> innerNodes = myRightOperand.expand(i, line, callback, insertSurroundedTextAtTheEnd);
+          for (GenerationNode parentNode : parentNodes) {
+            addChildrenToAllLeafs(parentNode, innerNodes);
+          }
+          result.addAll(parentNodes);
+        }
+      }
+      return result;
+    }
+    List<GenerationNode> leftGenNodes = myLeftOperand.expand(numberInIteration, surroundedText, callback, insertSurroundedTextAtTheEnd);
+    for (GenerationNode leftGenNode : leftGenNodes) {
+      List<GenerationNode> rightGenNodes = myRightOperand.expand(numberInIteration, surroundedText, callback, insertSurroundedTextAtTheEnd);
+      addChildrenToAllLeafs(leftGenNode, rightGenNodes);
+    }
+    return leftGenNodes;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/MulOperationNode.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/MulOperationNode.java
new file mode 100644
index 0000000..bb5b324
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/MulOperationNode.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.nodes;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class MulOperationNode extends ZenCodingNode {
+  private final ZenCodingNode myLeftOperand;
+  private final int myRightOperand;
+
+  public MulOperationNode(ZenCodingNode leftOperand, int rightOperand) {
+    myLeftOperand = leftOperand;
+    myRightOperand = rightOperand;
+  }
+
+  public ZenCodingNode getLeftOperand() {
+    return myLeftOperand;
+  }
+
+  public int getRightOperand() {
+    return myRightOperand;
+  }
+
+  @NotNull
+  @Override
+  public List<GenerationNode> expand(int numberInIteration,
+                                     String surroundedText,
+                                     CustomTemplateCallback callback,
+                                     boolean insertSurroundedTextAtTheEnd) {
+    List<GenerationNode> result = new ArrayList<GenerationNode>();
+    for (int i = 0; i < myRightOperand; i++) {
+      result.addAll(myLeftOperand.expand(i, surroundedText, callback, insertSurroundedTextAtTheEnd));
+    }
+    return result;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/TemplateNode.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/TemplateNode.java
new file mode 100644
index 0000000..7a9040d
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/TemplateNode.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.nodes;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import com.intellij.codeInsight.template.zencoding.tokens.TemplateToken;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class TemplateNode extends ZenCodingNode {
+  private final TemplateToken myTemplateToken;
+
+  public TemplateNode(TemplateToken templateToken) {
+    myTemplateToken = templateToken;
+  }
+
+  public TemplateToken getTemplateToken() {
+    return myTemplateToken;
+  }
+
+  @NotNull
+  @Override
+  public List<GenerationNode> expand(int numberInIteration,
+                                     String surroundedText,
+                                     CustomTemplateCallback callback,
+                                     boolean insertSurroundedTextAtTheEnd) {
+    GenerationNode node =
+      new GenerationNode(myTemplateToken, new ArrayList<GenerationNode>(), numberInIteration, surroundedText, insertSurroundedTextAtTheEnd);
+    return Arrays.asList(node);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/TextNode.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/TextNode.java
new file mode 100644
index 0000000..8e7eba7
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/TextNode.java
@@ -0,0 +1,48 @@
+package com.intellij.codeInsight.template.zencoding.nodes;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import com.intellij.codeInsight.template.impl.TemplateImpl;
+import com.intellij.codeInsight.template.zencoding.ZenCodingTemplate;
+import com.intellij.codeInsight.template.zencoding.ZenCodingUtil;
+import com.intellij.codeInsight.template.zencoding.tokens.TemplateToken;
+import com.intellij.codeInsight.template.zencoding.tokens.TextToken;
+import com.intellij.openapi.util.Pair;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class TextNode extends ZenCodingNode {
+  private final String myText;
+
+  public TextNode(@NotNull TextToken textToken) {
+    final String text = textToken.getText();
+    myText = text.substring(1, text.length() - 1);
+  }
+
+  public String getText() {
+    return myText;
+  }
+
+  @NotNull
+  @Override
+  public List<GenerationNode> expand(int numberInIteration,
+                                     String surroundedText,
+                                     CustomTemplateCallback callback,
+                                     boolean insertSurroundedTextAtTheEnd) {
+    final TemplateToken templateToken = new TemplateToken("", Collections.<Pair<String, String>>emptyList());
+    final boolean containsSurroundedTextMarker = ZenCodingUtil.containsSurroundedTextMarker(myText);
+
+    final String text = ZenCodingUtil.replaceMarkers(myText.replace("${nl}", "\n"), numberInIteration, surroundedText);
+    final TemplateImpl template = new TemplateImpl("", text, "");
+    ZenCodingTemplate.doSetTemplate(templateToken, template, callback);
+
+    final GenerationNode node = new GenerationNode(templateToken, new ArrayList<GenerationNode>(), numberInIteration,
+                                                   containsSurroundedTextMarker ? null : surroundedText, insertSurroundedTextAtTheEnd);
+    return Collections.singletonList(node);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/UnaryMulOperationNode.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/UnaryMulOperationNode.java
new file mode 100644
index 0000000..7efb182
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/UnaryMulOperationNode.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.nodes;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import com.intellij.openapi.util.text.LineTokenizer;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class UnaryMulOperationNode extends ZenCodingNode {
+  private final ZenCodingNode myOperand;
+
+  public UnaryMulOperationNode(ZenCodingNode operand) {
+    myOperand = operand;
+  }
+
+  public ZenCodingNode getOperand() {
+    return myOperand;
+  }
+
+  @NotNull
+  @Override
+  public List<GenerationNode> expand(int numberInIteration,
+                                     String surroundedText,
+                                     CustomTemplateCallback callback,
+                                     boolean insertSurroundedTextAtTheEnd) {
+    if (surroundedText == null) {
+      return myOperand.expand(numberInIteration, surroundedText, callback, insertSurroundedTextAtTheEnd);
+    }
+    String[] lines = LineTokenizer.tokenize(surroundedText, false);
+    List<GenerationNode> result = new ArrayList<GenerationNode>();
+    for (int i = 0; i < lines.length; i++) {
+      result.addAll(myOperand.expand(i, lines[i].trim(), callback, insertSurroundedTextAtTheEnd));
+    }
+    return result;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/ZenCodingNode.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/ZenCodingNode.java
new file mode 100644
index 0000000..f1993ad
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/nodes/ZenCodingNode.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.nodes;
+
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class ZenCodingNode {
+  @NotNull
+  public abstract List<GenerationNode> expand(int numberInIteration,
+                                              String surroundedText,
+                                              CustomTemplateCallback callback,
+                                              boolean insertSurroundedTextAtTheEnd);
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/FilterToken.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/FilterToken.java
new file mode 100644
index 0000000..739c9b6
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/FilterToken.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class FilterToken extends ZenCodingToken {
+  private final String mySuffix;
+
+  public FilterToken(String suffix) {
+    mySuffix = suffix;
+  }
+
+  public String getSuffix() {
+    return mySuffix;
+  }
+
+  @Override
+  public String toString() {
+    return "|" + mySuffix;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/IdentifierToken.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/IdentifierToken.java
new file mode 100644
index 0000000..2c42ebb
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/IdentifierToken.java
@@ -0,0 +1,23 @@
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class IdentifierToken extends ZenCodingToken {
+  private final String myText;
+
+  public IdentifierToken(@NotNull String text) {
+    myText = text;
+  }
+
+  @Override
+  public String toString() {
+    return myText;
+  }
+
+  public String getText() {
+    return myText;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/NumberToken.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/NumberToken.java
new file mode 100644
index 0000000..5d4ae7c
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/NumberToken.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class NumberToken extends ZenCodingToken {
+  private final int myNumber;
+
+  public NumberToken(int number) {
+    myNumber = number;
+  }
+
+  public int getNumber() {
+    return myNumber;
+  }
+
+  @Override
+  public String toString() {
+    return Integer.toString(myNumber);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/OperationToken.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/OperationToken.java
new file mode 100644
index 0000000..5c7c843
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/OperationToken.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class OperationToken extends ZenCodingToken {
+  private final char mySign;
+
+  public OperationToken(char sign) {
+    mySign = sign;
+  }
+
+  public char getSign() {
+    return mySign;
+  }
+
+  @Override
+  public String toString() {
+    return Character.toString(mySign);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/StringLiteralToken.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/StringLiteralToken.java
new file mode 100644
index 0000000..1c8428a
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/StringLiteralToken.java
@@ -0,0 +1,21 @@
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class StringLiteralToken extends ZenCodingToken {
+  private final String myText;
+
+  public StringLiteralToken(String text) {
+    myText = text;
+  }
+
+  @Override
+  public String toString() {
+    return myText;
+  }
+
+  public String getText() {
+    return myText;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/TemplateToken.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/TemplateToken.java
new file mode 100644
index 0000000..3bd3e5f
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/TemplateToken.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+import com.intellij.codeInsight.template.impl.TemplateImpl;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.xml.XmlFile;
+
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class TemplateToken extends ZenCodingToken {
+  private final String myKey;
+  private TemplateImpl myTemplate;
+  private final List<Pair<String, String>> myAttribute2Value;
+  private XmlFile myFile;
+
+  public TemplateToken(String key, List<Pair<String, String>> attribute2value) {
+    myKey = key;
+    myAttribute2Value = attribute2value;
+  }
+
+  public List<Pair<String, String>> getAttribute2Value() {
+    return myAttribute2Value;
+  }
+
+  public XmlFile getFile() {
+    return myFile;
+  }
+
+  public void setFile(XmlFile file) {
+    myFile = file;
+  }
+
+   public String getKey() {
+    return myKey;
+  }
+
+  public void setTemplate(TemplateImpl template) {
+    myTemplate = template;
+  }
+
+  public TemplateImpl getTemplate() {
+    return myTemplate;
+  }
+
+  public String toString() {
+    return "TEMPLATE";
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/TextToken.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/TextToken.java
new file mode 100644
index 0000000..e216302
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/TextToken.java
@@ -0,0 +1,21 @@
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class TextToken extends ZenCodingToken {
+  private final String myText;
+
+  public TextToken(String text) {
+    myText = text;
+  }
+
+  public String getText() {
+    return myText;
+  }
+
+  @Override
+  public String toString() {
+    return myText;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/ZenCodingToken.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/ZenCodingToken.java
new file mode 100644
index 0000000..b38c98e
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/ZenCodingToken.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class ZenCodingToken {
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/ZenCodingTokenImpl.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/ZenCodingTokenImpl.java
new file mode 100644
index 0000000..749279c
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/ZenCodingTokenImpl.java
@@ -0,0 +1,17 @@
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class ZenCodingTokenImpl extends ZenCodingToken {
+  private final String myString;
+
+  public ZenCodingTokenImpl(String string) {
+    myString = string;
+  }
+
+  @Override
+  public String toString() {
+    return myString;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/ZenCodingTokens.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/ZenCodingTokens.java
new file mode 100644
index 0000000..8911153
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/tokens/ZenCodingTokens.java
@@ -0,0 +1,21 @@
+package com.intellij.codeInsight.template.zencoding.tokens;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class ZenCodingTokens {
+  private ZenCodingTokens() {
+  }
+
+  public static final ZenCodingToken CLOSING_R_BRACKET = new ZenCodingTokenImpl(")");
+  public static final ZenCodingToken OPENING_R_BRACKET = new ZenCodingTokenImpl("(");
+  public static final ZenCodingToken OPENING_SQ_BRACKET = new ZenCodingTokenImpl("[");
+  public static final ZenCodingToken CLOSING_SQ_BRACKET = new ZenCodingTokenImpl("]");
+  public static final ZenCodingToken PIPE = new ZenCodingTokenImpl("|");
+  public static final ZenCodingToken MARKER = new ZenCodingTokenImpl("&");
+  public static final ZenCodingToken EQ = new ZenCodingTokenImpl("=");
+  public static final ZenCodingToken SPACE = new ZenCodingTokenImpl(" ");
+  public static final ZenCodingToken COMMA = new ZenCodingTokenImpl(",");
+  public static final ZenCodingToken DOT = new ZenCodingTokenImpl(".");
+  public static final ZenCodingToken SHARP = new ZenCodingTokenImpl("#");
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java
new file mode 100644
index 0000000..faa6174
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.CommonBundle;
+import com.intellij.codeInspection.InspectionProfile;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ModifiableModel;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+
+/**
+ * @author spleaner
+ */
+public class AddCustomTagOrAttributeIntentionAction implements LocalQuickFix {
+  private final String myName;
+  private final int myType;
+  private final String myInspectionName;
+
+  public AddCustomTagOrAttributeIntentionAction(@NotNull String shortName, String name, int type) {
+    myInspectionName = shortName;
+    myName = name;
+    myType = type;
+  }
+
+  @NotNull
+  public String getName() {
+    if (myType == XmlEntitiesInspection.UNKNOWN_TAG) {
+      return XmlBundle.message("add.custom.html.tag", myName);
+    }
+
+    if (myType == XmlEntitiesInspection.UNKNOWN_ATTRIBUTE) {
+      return XmlBundle.message("add.custom.html.attribute", myName);
+    }
+
+    if (myType == XmlEntitiesInspection.NOT_REQUIRED_ATTRIBUTE) {
+      return XmlBundle.message("add.optional.html.attribute", myName);
+    }
+
+    return getFamilyName();
+  }
+
+  @NotNull
+  public String getFamilyName() {
+    return XmlBundle.message("fix.html.family");
+  }
+
+  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+    final PsiElement element = descriptor.getPsiElement();
+    final PsiFile file = element.getContainingFile();
+
+    final InspectionProjectProfileManager profileManager = InspectionProjectProfileManager.getInstance(project);
+    final InspectionProfile inspectionProfile = profileManager.getInspectionProfile();
+    final ModifiableModel model = inspectionProfile.getModifiableModel();
+    final LocalInspectionToolWrapper wrapper = (LocalInspectionToolWrapper)model.getInspectionTool(myInspectionName, element);
+    final HtmlUnknownTagInspection inspection = (HtmlUnknownTagInspection)wrapper.getTool();
+    inspection.addCustomPropertyName(myName);
+    try {
+      model.commit();
+    }
+    catch (IOException e) {
+      Messages.showErrorDialog(project, e.getMessage(), CommonBundle.getErrorTitle());
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java
new file mode 100644
index 0000000..9b8d732
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.CommonBundle;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.InspectionProfile;
+import com.intellij.codeInspection.ModifiableModel;
+import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class AddHtmlTagOrAttributeToCustomsIntention implements IntentionAction {
+  private final String myName;
+  private final int myType;
+  private final String myInspectionName;
+
+  public AddHtmlTagOrAttributeToCustomsIntention(String shortName, String name, int type) {
+    myInspectionName = shortName;
+    myName = name;
+    myType = type;
+  }
+
+  @NotNull
+  public String getText() {
+    if (myType == XmlEntitiesInspection.UNKNOWN_TAG) {
+      return XmlBundle.message("add.custom.html.tag", myName);
+    }
+
+    if (myType == XmlEntitiesInspection.UNKNOWN_ATTRIBUTE) {
+      return XmlBundle.message("add.custom.html.attribute", myName);
+    }
+
+    if (myType == XmlEntitiesInspection.NOT_REQUIRED_ATTRIBUTE) {
+      return XmlBundle.message("add.optional.html.attribute", myName);
+    }
+
+    return getFamilyName();
+  }
+
+  @NotNull
+  public String getFamilyName() {
+    return XmlBundle.message("fix.html.family");
+  }
+
+  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+    return true;
+  }
+
+  public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+    final InspectionProjectProfileManager profileManager = InspectionProjectProfileManager.getInstance(project);
+    final InspectionProfile inspectionProfile = profileManager.getInspectionProfile();
+    final ModifiableModel model = inspectionProfile.getModifiableModel();
+    final LocalInspectionToolWrapper wrapper = (LocalInspectionToolWrapper)model.getInspectionTool(myInspectionName, file);
+    final XmlEntitiesInspection xmlEntitiesInspection = (XmlEntitiesInspection)wrapper.getTool();
+    xmlEntitiesInspection.setAdditionalEntries(myType, appendName(xmlEntitiesInspection.getAdditionalEntries(myType)));
+    try {
+      model.commit();
+    }
+    catch (IOException e) {
+      Messages.showErrorDialog(project, e.getMessage(), CommonBundle.getErrorTitle());
+    }
+  }
+
+  public boolean startInWriteAction() {
+    return false;
+  }
+
+  private String appendName(String toAppend) {
+    if (toAppend.length() > 0) {
+      toAppend += "," + myName;
+    }
+    else {
+      toAppend = myName;
+    }
+    return toAppend;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlExtraClosingTagInspection.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlExtraClosingTagInspection.java
new file mode 100644
index 0000000..923866e
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlExtraClosingTagInspection.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlTagUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class HtmlExtraClosingTagInspection extends HtmlLocalInspectionTool {
+
+  @Nls
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("html.inspection.extra.closing.tag");
+  }
+
+  @NonNls
+  @NotNull
+  public String getShortName() {
+    return "HtmlExtraClosingTag";
+  }
+
+  @NotNull
+  public HighlightDisplayLevel getDefaultLevel() {
+    return HighlightDisplayLevel.ERROR;
+  }
+
+  protected void checkTag(@NotNull final XmlTag tag, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    final XmlToken endTagName = XmlTagUtil.getEndTagNameElement(tag);
+
+    if (endTagName != null && tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(tag.getName())) {
+      holder.registerProblem(endTagName, XmlErrorMessages.message("extra.closing.tag.for.empty.element"),
+                             ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new RemoveExtraClosingTagIntentionAction());
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlLocalInspectionTool.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlLocalInspectionTool.java
new file mode 100644
index 0000000..6d44429
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlLocalInspectionTool.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.codeInspection.XmlSuppressableInspectionTool;
+import com.intellij.codeInspection.XmlInspectionGroupNames;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.templateLanguages.OuterLanguageElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public abstract class HtmlLocalInspectionTool extends XmlSuppressableInspectionTool {
+
+  @Nls
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlInspectionGroupNames.HTML_INSPECTIONS;
+  }
+
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+
+  protected void checkTag(@NotNull final XmlTag tag, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    // should be overridden
+  }
+
+  protected void checkAttribute(@NotNull final XmlAttribute attribute, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    // should be overridden
+  }
+
+  @NotNull
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    return new XmlElementVisitor() {
+      @Override public void visitXmlToken(final XmlToken token) {
+        if (token.getTokenType() == XmlTokenType.XML_NAME) {
+          PsiElement element = token.getPrevSibling();
+          while(element instanceof PsiWhiteSpace) element = element.getPrevSibling();
+
+          if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_START_TAG_START) {
+            PsiElement parent = element.getParent();
+
+            if (parent instanceof XmlTag && !(token.getNextSibling() instanceof OuterLanguageElement)) {
+              XmlTag tag = (XmlTag)parent;
+              checkTag(tag, holder, isOnTheFly);
+            }
+          }
+        }
+      }
+
+      @Override public void visitXmlAttribute(final XmlAttribute attribute) {
+        checkAttribute(attribute, holder, isOnTheFly);
+      }
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownAttributeInspection.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownAttributeInspection.java
new file mode 100644
index 0000000..9dac096
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownAttributeInspection.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class HtmlUnknownAttributeInspection extends HtmlUnknownTagInspection {
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.htmlInspections.HtmlUnknownAttributeInspection");
+  @NonNls public static final String ATTRIBUTE_SHORT_NAME = "HtmlUnknownAttribute";
+
+  public HtmlUnknownAttributeInspection() {
+    super("");
+  }
+
+  @Nls
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("html.inspections.unknown.attribute");
+  }
+
+  @NonNls
+  @NotNull
+  public String getShortName() {
+    return ATTRIBUTE_SHORT_NAME;
+  }
+
+  protected String getCheckboxTitle() {
+    return XmlBundle.message("html.inspections.unknown.tag.attribute.checkbox.title");
+  }
+
+  protected String getPanelTitle() {
+    return XmlBundle.message("html.inspections.unknown.tag.attribute.title");
+  }
+
+  @NotNull
+  protected Logger getLogger() {
+    return LOG;
+  }
+
+  protected void checkTag(@NotNull final XmlTag tag, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    // does nothing! this method should be overridden empty!
+  }
+
+  protected void checkAttribute(@NotNull final XmlAttribute attribute, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    final XmlTag tag = attribute.getParent();
+
+    if (tag instanceof HtmlTag) {
+      XmlElementDescriptor elementDescriptor = tag.getDescriptor();
+      if (elementDescriptor == null || elementDescriptor instanceof AnyXmlElementDescriptor) {
+        return;
+      }
+
+      XmlAttributeDescriptor attributeDescriptor = elementDescriptor.getAttributeDescriptor(attribute);
+
+      final String name = attribute.getName();
+
+      if (attributeDescriptor == null && !attribute.isNamespaceDeclaration()) {
+        if (!XmlUtil.attributeFromTemplateFramework(name, tag) &&
+            (!isCustomValuesEnabled() || !isCustomValue(name))) {
+          final ASTNode node = attribute.getNode();
+          assert node != null;
+          final PsiElement nameElement = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(node).getPsi();
+
+          boolean maySwitchToHtml5 = HtmlUtil.isCustomHtml5Attribute(name) && !HtmlUtil.hasNonHtml5Doctype(tag);
+          LocalQuickFix[] quickfixes = new LocalQuickFix[maySwitchToHtml5 ? 3 : 2];
+          quickfixes[0] = new AddCustomTagOrAttributeIntentionAction(getShortName(), name, XmlEntitiesInspection.UNKNOWN_ATTRIBUTE);
+          quickfixes[1] = new RemoveAttributeIntentionAction(name);
+          if (maySwitchToHtml5) {
+            quickfixes[2] = new SwitchToHtml5WithHighPriorityAction();
+          }
+
+          if (nameElement.getTextLength() > 0)
+            holder.registerProblem(nameElement, XmlErrorMessages.message("attribute.is.not.allowed.here", name),
+                                 ProblemHighlightType.GENERIC_ERROR_OR_WARNING, quickfixes);
+        }
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownTagInspection.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownTagInspection.java
new file mode 100644
index 0000000..08ab333
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownTagInspection.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.daemon.impl.analysis.CreateNSDeclarationIntentionFix;
+import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.JDOMExternalizableStringList;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.impl.source.html.dtd.HtmlElementDescriptorImpl;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.ui.FieldPanel;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlTagUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * @author spleaner
+ */
+public class HtmlUnknownTagInspection extends HtmlLocalInspectionTool {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.htmlInspections.HtmlUnknownTagInspection");
+
+  public JDOMExternalizableStringList myValues;
+  public boolean myCustomValuesEnabled = true;
+  @NonNls public static final String TAG_SHORT_NAME = "HtmlUnknownTag";
+
+  public HtmlUnknownTagInspection() {
+    this("nobr,noembed,comment,noscript,embed,script");
+  }
+
+  protected HtmlUnknownTagInspection(@NonNls @NotNull final String defaultValues) {
+    myValues = reparseProperties(defaultValues);
+  }
+
+  @Nls
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("html.inspections.unknown.tag");
+  }
+
+  @NonNls
+  @NotNull
+  public String getShortName() {
+    return TAG_SHORT_NAME;
+  }
+
+  @Nullable
+  public JComponent createOptionsPanel() {
+    final JPanel result = new JPanel(new BorderLayout());
+
+    final JPanel internalPanel = new JPanel(new BorderLayout());
+    result.add(internalPanel, BorderLayout.NORTH);
+
+    final FieldPanel additionalAttributesPanel = new FieldPanel(null, getPanelTitle(), null, null);
+    additionalAttributesPanel.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
+      protected void textChanged(DocumentEvent e) {
+        final Document document = e.getDocument();
+        try {
+          final String text = document.getText(0, document.getLength());
+          if (text != null) {
+            myValues = reparseProperties(text.trim());
+          }
+        }
+        catch (BadLocationException e1) {
+          getLogger().error(e1);
+        }
+      }
+    });
+
+    final JCheckBox checkBox = new JCheckBox(getCheckboxTitle());
+    checkBox.setSelected(myCustomValuesEnabled);
+    checkBox.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        final boolean b = checkBox.isSelected();
+        if (b != myCustomValuesEnabled) {
+          myCustomValuesEnabled = b;
+          additionalAttributesPanel.setEnabled(myCustomValuesEnabled);
+        }
+      }
+    });
+
+    internalPanel.add(checkBox, BorderLayout.NORTH);
+    internalPanel.add(additionalAttributesPanel, BorderLayout.CENTER);
+
+    additionalAttributesPanel.setPreferredSize(new Dimension(150, additionalAttributesPanel.getPreferredSize().height));
+    additionalAttributesPanel.setEnabled(myCustomValuesEnabled);
+    additionalAttributesPanel.setText(createPropertiesString());
+
+    return result;
+  }
+
+  @NotNull
+  protected Logger getLogger() {
+    return LOG;
+  }
+
+  private String createPropertiesString() {
+    final StringBuffer buffer = new StringBuffer();
+    for (final String property : myValues) {
+      if (buffer.length() == 0) {
+        buffer.append(property);
+      }
+      else {
+        buffer.append(',');
+        buffer.append(property);
+      }
+    }
+
+    return buffer.toString();
+  }
+
+  public String getAdditionalEntries() {
+    return createPropertiesString();
+  }
+
+  protected String getCheckboxTitle() {
+    return XmlBundle.message("html.inspections.unknown.tag.checkbox.title");
+  }
+
+  protected static JDOMExternalizableStringList reparseProperties(@NotNull final String properties) {
+    final JDOMExternalizableStringList result = new JDOMExternalizableStringList();
+
+    final StringTokenizer tokenizer = new StringTokenizer(properties, ",");
+    while (tokenizer.hasMoreTokens()) {
+      result.add(tokenizer.nextToken().toLowerCase().trim());
+    }
+
+    return result;
+  }
+
+  public void setAdditionalValues(@NotNull final String values) {
+    myValues = reparseProperties(values);
+  }
+
+  protected String getPanelTitle() {
+    return XmlBundle.message("html.inspections.unknown.tag.title");
+  }
+
+  protected boolean isCustomValue(@NotNull final String value) {
+    return myValues.contains(value.toLowerCase());
+  }
+
+  public void addCustomPropertyName(@NotNull final String text) {
+    final String s = text.trim().toLowerCase();
+    if (!isCustomValue(s)) {
+      myValues.add(s);
+    }
+
+    if (!isCustomValuesEnabled()) {
+      myCustomValuesEnabled = true;
+    }
+  }
+
+  public boolean isCustomValuesEnabled() {
+    return myCustomValuesEnabled;
+  }
+
+  private static boolean isAbstractDescriptor(XmlElementDescriptor descriptor) {
+    return descriptor == null || descriptor instanceof AnyXmlElementDescriptor;
+  }
+
+  // this hack is needed, because we temporarily ignore svg and mathML namespaces
+  // todo: provide schemas for svg and mathML and remove this in IDEA XI
+  private static boolean isInSpecialHtml5Namespace(XmlTag tag) {
+    final String ns = tag.getNamespace();
+    return HtmlUtil.SVG_NAMESPACE.equals(ns) || HtmlUtil.MATH_ML_NAMESPACE.endsWith(ns);
+  }
+
+  protected void checkTag(@NotNull final XmlTag tag, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    if (!(tag instanceof HtmlTag) || !XmlHighlightVisitor.shouldBeValidated(tag) || isInSpecialHtml5Namespace(tag)) {
+      return;
+    }
+
+    XmlElementDescriptor descriptorFromContext = XmlUtil.getDescriptorFromContext(tag);
+
+    PsiElement parent = tag.getParent();
+    XmlElementDescriptor parentDescriptor = parent instanceof XmlTag ? ((XmlTag)parent).getDescriptor() : null;
+
+    XmlElementDescriptor ownDescriptor = isAbstractDescriptor(descriptorFromContext)
+                                         ? tag.getDescriptor()
+                                         : descriptorFromContext;
+
+    if (isAbstractDescriptor(ownDescriptor) ||
+        (parentDescriptor instanceof HtmlElementDescriptorImpl &&
+         ownDescriptor instanceof HtmlElementDescriptorImpl &&
+         isAbstractDescriptor(descriptorFromContext))) {
+
+      final String name = tag.getName();
+
+      if (!isCustomValuesEnabled() || !isCustomValue(name)) {
+        final AddCustomTagOrAttributeIntentionAction action =
+          new AddCustomTagOrAttributeIntentionAction(getShortName(), name, XmlEntitiesInspection.UNKNOWN_TAG);
+
+        // todo: support "element is not allowed" message for html5
+        // some tags in html5 cannot be found in xhtml5.xsd if they are located in incorrect context, so they get any-element descriptor (ex. "canvas: tag)
+        final String message = isAbstractDescriptor(ownDescriptor)
+                               ? XmlErrorMessages.message("unknown.html.tag", name)
+                               : XmlErrorMessages.message("element.is.not.allowed.here", name);
+
+        final PsiElement startTagName = XmlTagUtil.getStartTagNameElement(tag);
+        assert startTagName != null;
+        final PsiElement endTagName = XmlTagUtil.getEndTagNameElement(tag);
+
+        List<LocalQuickFix> quickfixes = new ArrayList<LocalQuickFix>();
+        quickfixes.add(action);
+        if (isOnTheFly) {
+          ContainerUtil.addIfNotNull(CreateNSDeclarationIntentionFix.createFix(startTagName, ""), quickfixes);
+        }
+        if (HtmlUtil.isHtml5Tag(name) && !HtmlUtil.hasNonHtml5Doctype(tag)) {
+          quickfixes.add(new SwitchToHtml5WithHighPriorityAction());
+        }
+        ProblemHighlightType highlightType = tag.getContainingFile().getContext() == null ?
+                                             ProblemHighlightType.GENERIC_ERROR_OR_WARNING :
+                                             ProblemHighlightType.INFORMATION;
+        if (startTagName.getTextLength() > 0) {
+          holder.registerProblem(startTagName, message, highlightType, quickfixes.toArray(new LocalQuickFix[quickfixes.size()]));
+        }
+
+        if (endTagName != null) {
+          holder.registerProblem(endTagName, message, highlightType, quickfixes.toArray(new LocalQuickFix[quickfixes.size()]));
+        }
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/RemoveAttributeIntentionAction.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/RemoveAttributeIntentionAction.java
new file mode 100644
index 0000000..a4eb248
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/RemoveAttributeIntentionAction.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class RemoveAttributeIntentionAction implements LocalQuickFix {
+  private final String myLocalName;
+
+  public RemoveAttributeIntentionAction(final String localName) {
+    myLocalName = localName;
+  }
+
+  @NotNull
+  public String getName() {
+    return XmlErrorMessages.message("remove.attribute.quickfix.text", myLocalName);
+  }
+
+  @NotNull
+  public String getFamilyName() {
+    return XmlErrorMessages.message("remove.attribute.quickfix.family");
+  }
+
+  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+    PsiElement e = descriptor.getPsiElement();
+    final XmlAttribute myAttribute = PsiTreeUtil.getParentOfType(e, XmlAttribute.class);
+    if (myAttribute == null) return;
+
+    if (!CodeInsightUtilBase.prepareFileForWrite(myAttribute.getContainingFile())) {
+      return;
+    }
+
+    new WriteCommandAction(project) {
+      protected void run(final Result result) throws Throwable {
+        myAttribute.delete();
+      }
+    }.execute();
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/RemoveExtraClosingTagIntentionAction.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/RemoveExtraClosingTagIntentionAction.java
new file mode 100644
index 0000000..0610645
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/RemoveExtraClosingTagIntentionAction.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.Document;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class RemoveExtraClosingTagIntentionAction implements LocalQuickFix, IntentionAction {
+  @NotNull
+  public String getFamilyName() {
+    return XmlErrorMessages.message("remove.extra.closing.tag.quickfix");
+  }
+
+  @NotNull
+  public String getName() {
+    return XmlErrorMessages.message("remove.extra.closing.tag.quickfix");
+  }
+
+
+  @NotNull
+  public String getText() {
+    return getName();
+  }
+
+  public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
+    return true;
+  }
+
+  public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
+    final int offset = editor.getCaretModel().getOffset();
+    final PsiElement psiElement = file.findElementAt(offset);
+    if (psiElement == null || !psiElement.isValid() || !(psiElement instanceof XmlToken)) {
+      return;
+    }
+
+    if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
+    doFix(psiElement);
+  }
+
+  public boolean startInWriteAction() {
+    return true;
+  }
+
+  private static void doFix(@NotNull final PsiElement element) throws IncorrectOperationException {
+    final XmlToken endNameToken = (XmlToken)element;
+    final PsiElement tagElement = endNameToken.getParent();
+    if (!(tagElement instanceof XmlTag) && !(tagElement instanceof PsiErrorElement)) return;
+
+    if (tagElement instanceof PsiErrorElement) {
+      tagElement.delete();
+    }
+    else {
+      final ASTNode astNode = tagElement.getNode();
+      if (astNode != null) {
+        final ASTNode endTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(astNode);
+        if (endTagStart != null) {
+          final Document document = PsiDocumentManager.getInstance(element.getProject()).getDocument(tagElement.getContainingFile());
+          if (document != null) {
+            document.deleteString(endTagStart.getStartOffset(), tagElement.getLastChild().getTextRange().getEndOffset());
+          }
+        }
+      }
+    }
+  }
+
+  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+    final PsiElement element = descriptor.getPsiElement();
+    if (!element.isValid() || !(element instanceof XmlToken)) return;
+    if (!CodeInsightUtilBase.prepareFileForWrite(element.getContainingFile())) return;
+
+    new WriteCommandAction(project) {
+      protected void run(final Result result) throws Throwable {
+        doFix(element);
+      }
+    }.execute();
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/RenameTagBeginOrEndIntentionAction.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/RenameTagBeginOrEndIntentionAction.java
new file mode 100644
index 0000000..8356b78
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/RenameTagBeginOrEndIntentionAction.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.util.XmlTagUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class RenameTagBeginOrEndIntentionAction implements IntentionAction {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.htmlInspections.RenameTagBeginOrEndIntentionAction");
+
+  private final boolean myStart;
+  private final String myTargetName;
+  private final String mySourceName;
+
+  RenameTagBeginOrEndIntentionAction(@NotNull final String targetName, @NotNull final String sourceName, final boolean start) {
+    myTargetName = targetName;
+    mySourceName = sourceName;
+    myStart = start;
+  }
+
+  @NotNull
+  public String getFamilyName() {
+    return getName();
+  }
+
+  @NotNull
+  public String getText() {
+    return getName();
+  }
+
+  public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
+    return true;
+  }
+
+  public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
+    final int offset = editor.getCaretModel().getOffset();
+    PsiElement psiElement = file.findElementAt(offset);
+
+    if (psiElement == null || !psiElement.isValid()) return;
+    if (!CodeInsightUtilBase.prepareFileForWrite(psiElement.getContainingFile())) return;
+
+    if (psiElement instanceof PsiWhiteSpace) psiElement = PsiTreeUtil.prevLeaf(psiElement);
+    if (psiElement instanceof XmlToken) {
+      final IElementType tokenType = ((XmlToken)psiElement).getTokenType();
+      if (tokenType != XmlTokenType.XML_NAME) {
+        if (tokenType == XmlTokenType.XML_TAG_END) {
+          psiElement = psiElement.getPrevSibling();
+          if (psiElement == null) return;
+        }
+      }
+
+      PsiElement target = null;
+      final String text = psiElement.getText();
+      if (!myTargetName.equals(text)) {
+        target = psiElement;
+      }
+      else {
+        // we're in the other
+        PsiElement parent = psiElement.getParent();
+        if (parent instanceof PsiErrorElement) {
+          parent = parent.getParent();
+        }
+
+        if (parent instanceof XmlTag) {
+          if (myStart) {
+            target = XmlTagUtil.getStartTagNameElement((XmlTag)parent);
+          }
+          else {
+            target = XmlTagUtil.getEndTagNameElement((XmlTag)parent);
+            if (target == null) {
+              final PsiErrorElement errorElement = PsiTreeUtil.getChildOfType(parent, PsiErrorElement.class);
+              target = XmlWrongClosingTagNameInspection.findEndTagName(errorElement);
+            }
+          }
+        }
+      }
+
+      if (target != null) {
+        final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
+        if (document != null) {
+          final TextRange textRange = target.getTextRange();
+          document.replaceString(textRange.getStartOffset(), textRange.getEndOffset(), myTargetName);
+        }
+      }
+
+    }
+  }
+
+  public boolean startInWriteAction() {
+    return true;
+  }
+
+  @NotNull
+  public String getName() {
+    return myStart
+           ? XmlErrorMessages.message("rename.start.tag.name.intention", mySourceName, myTargetName)
+           : XmlErrorMessages.message("rename.end.tag.name.intention", mySourceName, myTargetName);
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/RequiredAttributesInspection.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/RequiredAttributesInspection.java
new file mode 100644
index 0000000..d4cdffe
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/RequiredAttributesInspection.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.InspectionsBundle;
+import com.intellij.codeInspection.XmlSuppressableInspectionTool;
+import com.intellij.codeInspection.XmlInspectionGroupNames;
+import com.intellij.codeInspection.ex.UnfairLocalInspectionTool;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.ui.FieldPanel;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import java.awt.*;
+
+/**
+ * User: anna
+ * Date: 18-Nov-2005
+ */
+public class RequiredAttributesInspection extends XmlSuppressableInspectionTool implements XmlEntitiesInspection, UnfairLocalInspectionTool {
+
+  public String myAdditionalRequiredHtmlAttributes = "";
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection");
+  @NonNls public static final String SHORT_NAME = "RequiredAttributes";
+
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlInspectionGroupNames.HTML_INSPECTIONS;
+  }
+
+  @NotNull
+  public String getDisplayName() {
+    return InspectionsBundle.message("inspection.required.attributes.display.name");
+  }
+
+  @NotNull
+  @NonNls
+  public String getShortName() {
+    return SHORT_NAME;
+  }
+
+  @Nullable
+  public JComponent createOptionsPanel() {
+    JPanel panel = new JPanel(new BorderLayout());
+    FieldPanel additionalAttributesPanel = new FieldPanel(InspectionsBundle.message("inspection.javadoc.html.not.required.label.text"),
+                                                          InspectionsBundle.message("inspection.javadoc.html.not.required.dialog.title"),
+                                                          null, null);
+
+    panel.add(additionalAttributesPanel, BorderLayout.NORTH);
+    additionalAttributesPanel.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
+      protected void textChanged(DocumentEvent e) {
+        final Document document = e.getDocument();
+        try {
+          final String text = document.getText(0, document.getLength());
+          if (text != null) {
+            myAdditionalRequiredHtmlAttributes = text.trim();
+          }
+        }
+        catch (BadLocationException e1) {
+          RequiredAttributesInspection.LOG.error(e1);
+        }
+      }
+    });
+    additionalAttributesPanel.setText(myAdditionalRequiredHtmlAttributes);
+    return panel;
+  }
+
+  public IntentionAction getIntentionAction(String name, int type) {
+    return new AddHtmlTagOrAttributeToCustomsIntention(getShortName(), name, type);
+  }
+
+  public String getAdditionalEntries(int type) {
+    return myAdditionalRequiredHtmlAttributes;
+  }
+
+  public void setAdditionalEntries(int type, String additionalEntries) {
+    myAdditionalRequiredHtmlAttributes = additionalEntries;
+  }
+
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5Action.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5Action.java
new file mode 100644
index 0000000..cf6bee3
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5Action.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.javaee.ExternalResourceManagerEx;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.Html5SchemaProvider;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class SwitchToHtml5Action implements LocalQuickFix, IntentionAction {
+
+  @NotNull
+  @Override
+  public String getName() {
+    return XmlErrorMessages.message("switch.to.html5.quickfix.text");
+  }
+
+  @NotNull
+  @Override
+  public String getText() {
+    return getFamilyName();
+  }
+
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return getName();
+  }
+
+  @Override
+  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+    return true;
+  }
+
+  @Override
+  public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+    applyFix(project);
+  }
+
+  @Override
+  public boolean startInWriteAction() {
+    return true;
+  }
+
+  @Override
+  public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+    applyFix(project);
+  }
+
+  private static void applyFix(Project project) {
+    ExternalResourceManagerEx.getInstanceEx().setDefaultHtmlDoctype(Html5SchemaProvider.HTML5_SCHEMA_LOCATION, project);
+    DaemonCodeAnalyzer.getInstance(project).restart();
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5WithHighPriorityAction.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5WithHighPriorityAction.java
new file mode 100644
index 0000000..7a6b2ad
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5WithHighPriorityAction.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.intention.HighPriorityAction;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class SwitchToHtml5WithHighPriorityAction extends SwitchToHtml5Action implements HighPriorityAction {
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlEntitiesInspection.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlEntitiesInspection.java
new file mode 100644
index 0000000..fdad047
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlEntitiesInspection.java
@@ -0,0 +1,18 @@
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.psi.PsiElement;
+
+/**
+ * User: anna
+ * Date: 16-Dec-2005
+ */
+public interface XmlEntitiesInspection {
+  int UNKNOWN_TAG = 1;
+  int UNKNOWN_ATTRIBUTE = 2;
+  int NOT_REQUIRED_ATTRIBUTE = 3;
+  
+  IntentionAction getIntentionAction(String name, int type);
+  String getAdditionalEntries(int type);
+  void setAdditionalEntries(int type, String additionalEntries);
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlInspectionToolProvider.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlInspectionToolProvider.java
new file mode 100644
index 0000000..287591f
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlInspectionToolProvider.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.daemon.impl.analysis.*;
+import com.intellij.codeInspection.InspectionToolProvider;
+import com.intellij.xml.util.*;
+
+/**
+ * @author yole
+ */
+public class XmlInspectionToolProvider implements InspectionToolProvider {
+  public Class[] getInspectionClasses() {
+    return new Class[] {
+      CheckTagEmptyBodyInspection.class,
+      CheckDtdReferencesInspection.class,
+      CheckEmptyTagInspection.class,
+      CheckValidXmlInScriptBodyInspection.class,
+      CheckXmlFileWithXercesValidatorInspection.class,
+      XmlDuplicatedIdInspection.class,
+      RequiredAttributesInspection.class,
+      HtmlExtraClosingTagInspection.class,
+      XmlWrongRootElementInspection.class,
+      HtmlUnknownTagInspection.class,
+      HtmlUnknownAttributeInspection.class,
+      XmlUnboundNsPrefixInspection.class,
+      XmlUnusedNamespaceInspection.class,
+      XmlHighlightVisitorBasedInspection.class,
+      XmlPathReferenceInspection.class,
+      HtmlUnknownTargetInspection.class
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongClosingTagNameInspection.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongClosingTagNameInspection.java
new file mode 100644
index 0000000..39119e0
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongClosingTagNameInspection.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.LanguageParserDefinitions;
+import com.intellij.lang.ParserDefinition;
+import com.intellij.lang.annotation.Annotation;
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.lang.annotation.Annotator;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlTagUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author spleaner
+ */
+public class XmlWrongClosingTagNameInspection implements Annotator {
+
+  public void annotate(final PsiElement psiElement, final AnnotationHolder holder) {
+    if (psiElement instanceof XmlToken) {
+      final PsiElement parent = psiElement.getParent();
+      if (parent instanceof XmlTag) {
+        final XmlTag tag = (XmlTag)parent;
+        final XmlToken start = XmlTagUtil.getStartTagNameElement(tag);
+        XmlToken endTagName = XmlTagUtil.getEndTagNameElement(tag);
+        if (endTagName != null && !(tag instanceof HtmlTag) && !tag.getName().equals(endTagName.getText())) {
+          registerProblem(holder, tag, start, endTagName);
+        }
+        else if (endTagName == null && !(tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(tag.getName()))) {
+          final PsiErrorElement errorElement = PsiTreeUtil.getChildOfType(tag, PsiErrorElement.class);
+          endTagName = findEndTagName(errorElement);
+          if (endTagName != null) {
+            registerProblem(holder, tag, start, endTagName);
+          }
+        }
+      }
+      else if (parent instanceof PsiErrorElement) {
+        if (XmlTokenType.XML_NAME == ((XmlToken)psiElement).getTokenType()) {
+          final PsiFile psiFile = psiElement.getContainingFile();
+          
+          if (psiFile != null && (HTMLLanguage.INSTANCE == psiFile.getViewProvider().getBaseLanguage() || HTMLLanguage.INSTANCE == parent.getLanguage())) {
+            final String message = XmlErrorMessages.message("xml.parsing.closing.tag.matches.nothing");
+
+            if (message.equals(((PsiErrorElement)parent).getErrorDescription()) &&
+                psiFile.getContext() == null
+               ) {
+              final Annotation annotation = holder.createWarningAnnotation(parent, message);
+              annotation.registerFix(new RemoveExtraClosingTagIntentionAction());
+            }
+          }
+        }
+      }
+    }
+  }
+
+  private static void registerProblem(@NotNull final AnnotationHolder holder,
+                                      @NotNull final XmlTag tag,
+                                      @Nullable final XmlToken start,
+                                      @NotNull final XmlToken end) {
+    PsiElement context = tag.getContainingFile().getContext();
+    if (context != null) {
+      ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(context.getLanguage());
+      if (parserDefinition != null) {
+        ASTNode contextNode = context.getNode();
+        if (contextNode != null && contextNode.getChildren(parserDefinition.getStringLiteralElements()) != null) {
+          // TODO: we should check for concatenations here
+          return;
+        }
+      }
+    }
+    final String tagName = (tag instanceof HtmlTag) ? tag.getName().toLowerCase() : tag.getName();
+    final String endTokenText = (tag instanceof HtmlTag) ? end.getText().toLowerCase() : end.getText();
+
+    final RenameTagBeginOrEndIntentionAction renameEndAction = new RenameTagBeginOrEndIntentionAction(tagName, endTokenText, false);
+    final RenameTagBeginOrEndIntentionAction renameStartAction = new RenameTagBeginOrEndIntentionAction(endTokenText, tagName, true);
+
+    if (start != null) {
+      final Annotation annotation = holder.createErrorAnnotation(start, XmlErrorMessages.message("tag.has.wrong.closing.tag.name"));
+      annotation.registerFix(renameEndAction);
+      annotation.registerFix(renameStartAction);
+    }
+
+    final Annotation annotation = holder.createErrorAnnotation(end, XmlErrorMessages.message("wrong.closing.tag.name"));
+    annotation.registerFix(new RemoveExtraClosingTagIntentionAction());
+    annotation.registerFix(renameEndAction);
+    annotation.registerFix(renameStartAction);
+  }
+
+  @Nullable
+  static XmlToken findEndTagName(@Nullable final PsiErrorElement element) {
+    if (element == null) return null;
+
+    final ASTNode astNode = element.getNode();
+    if (astNode == null) return null;
+
+    ASTNode current = astNode.getLastChildNode();
+    ASTNode prev = current;
+
+    while (current != null) {
+      final IElementType elementType = prev.getElementType();
+
+      if ((elementType == XmlElementType.XML_NAME || elementType == XmlElementType.XML_TAG_NAME) &&
+          current.getElementType() == XmlElementType.XML_END_TAG_START) {
+        return (XmlToken)prev.getPsi();
+      }
+
+      prev = current;
+      current = current.getTreePrev();
+    }
+
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongRootElementInspection.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongRootElementInspection.java
new file mode 100644
index 0000000..a1f408e
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongRootElementInspection.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.codeInspection.htmlInspections;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
+import com.intellij.codeInspection.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class XmlWrongRootElementInspection extends HtmlLocalInspectionTool {
+
+  @Nls
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlInspectionGroupNames.XML_INSPECTIONS;
+  }
+
+  @Nls
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("xml.inspection.wrong.root.element");
+  }
+
+  @NonNls
+  @NotNull
+  public String getShortName() {
+    return "XmlWrongRootElement";
+  }
+
+  @NotNull
+  public HighlightDisplayLevel getDefaultLevel() {
+    return HighlightDisplayLevel.ERROR;
+  }
+
+  protected void checkTag(@NotNull final XmlTag tag, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    if (!(tag.getParent() instanceof XmlTag)) {
+      final PsiFile psiFile = tag.getContainingFile();
+      if (!(psiFile instanceof XmlFile)) {
+        return;
+      }
+
+      XmlFile xmlFile = (XmlFile) psiFile;
+
+      final XmlDocument document = xmlFile.getDocument();
+      if (document == null) {
+        return;
+      }
+
+      XmlProlog prolog = document.getProlog();
+      if (prolog == null || XmlHighlightVisitor.skipValidation(prolog)) {
+        return;
+      }
+
+      final XmlDoctype doctype = prolog.getDoctype();
+
+      if (doctype == null) {
+        return;
+      }
+
+      XmlElement nameElement = doctype.getNameElement();
+
+      if (nameElement == null) {
+        return;
+      }
+
+      String name = tag.getName();
+      String text = nameElement.getText();
+      if (tag instanceof HtmlTag) {
+        name = name.toLowerCase();
+        text = text.toLowerCase();
+      }
+
+      if (!name.equals(text)) {
+        name = XmlUtil.findLocalNameByQualifiedName(name);
+
+        if (!name.equals(text)) {
+          if (tag instanceof HtmlTag) {
+            return; // it is legal to have html / head / body omitted
+          }
+          final LocalQuickFix localQuickFix = new MyLocalQuickFix(doctype.getNameElement().getText());
+
+          holder.registerProblem(XmlChildRole.START_TAG_NAME_FINDER.findChild(tag.getNode()).getPsi(),
+            XmlErrorMessages.message("wrong.root.element"),
+            ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, localQuickFix
+          );
+
+          final ASTNode astNode = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(tag.getNode());
+          if (astNode != null) {
+            holder.registerProblem(astNode.getPsi(),
+              XmlErrorMessages.message("wrong.root.element"),
+              ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, localQuickFix
+            );
+          }
+        }
+      }
+    }
+  }
+
+  private static class MyLocalQuickFix implements LocalQuickFix {
+    private final String myText;
+
+    public MyLocalQuickFix(String text) {
+      myText = text;
+    }
+
+    @NotNull
+    public String getName() {
+      return XmlBundle.message("change.root.element.to", myText);
+    }
+
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+
+    public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+      final XmlTag myTag = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), XmlTag.class);
+
+      if (!CodeInsightUtilBase.prepareFileForWrite(myTag.getContainingFile())) {
+        return;
+      }
+
+      new WriteCommandAction(project) {
+        protected void run(final Result result) throws Throwable {
+          myTag.setName(myText);
+        }
+      }.execute();
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/featureStatistics/XmlProductivityFeatureProvider.java b/xml/impl/src/com/intellij/featureStatistics/XmlProductivityFeatureProvider.java
new file mode 100644
index 0000000..78d4479
--- /dev/null
+++ b/xml/impl/src/com/intellij/featureStatistics/XmlProductivityFeatureProvider.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.featureStatistics;
+
+import com.intellij.codeInsight.completion.XmlCompletionContributor;
+import com.intellij.xml.XmlBundle;
+
+import java.util.Collections;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlProductivityFeatureProvider extends ProductivityFeaturesProvider {
+  public FeatureDescriptor[] getFeatureDescriptors() {
+    return new FeatureDescriptor[] { new FeatureDescriptor(XmlCompletionContributor.TAG_NAME_COMPLETION_FEATURE,
+                                                           "completion",
+                                                           "TagNameCompletion.html",
+                                                           XmlBundle.message("tag.name.completion.display.name"),
+                                                           0,
+                                                           1,
+                                                           Collections.<String>emptySet(),
+                                                           3,
+                                                           this)};
+  }
+
+  public GroupDescriptor[] getGroupDescriptors() {
+    return new GroupDescriptor[0];
+  }
+
+  public ApplicabilityFilter[] getApplicabilityFilters() {
+    return new ApplicabilityFilter[0];
+  }
+}
diff --git a/xml/impl/src/com/intellij/html/HtmlLineMarkerProvider.java b/xml/impl/src/com/intellij/html/HtmlLineMarkerProvider.java
new file mode 100644
index 0000000..a9c9a33
--- /dev/null
+++ b/xml/impl/src/com/intellij/html/HtmlLineMarkerProvider.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.html;
+
+import com.intellij.codeInsight.daemon.LineMarkerInfo;
+import com.intellij.codeInsight.daemon.LineMarkerProvider;
+import com.intellij.codeInsight.daemon.LineMarkerProviders;
+import com.intellij.lang.Language;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiWhiteSpace;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Maxim.Mossienko
+ *         Date: Oct 14, 2008
+ *         Time: 11:38:46 PM
+ */
+public class HtmlLineMarkerProvider implements LineMarkerProvider {
+  private final Map<Language, LineMarkerProvider> embeddedLanguagesLineMarkerProviders = new THashMap<Language, LineMarkerProvider>();
+
+  public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement element) {
+    if (element instanceof PsiWhiteSpace) return null;
+    final Language language = element.getLanguage();
+
+    if (!(language instanceof XMLLanguage)) {
+      final LineMarkerProvider markerProvider = getLineMarkerProviderFromLanguage(language, embeddedLanguagesLineMarkerProviders);
+
+      if (markerProvider != null) return markerProvider.getLineMarkerInfo(element);
+    }
+    return null;
+  }
+
+  private static LineMarkerProvider getLineMarkerProviderFromLanguage(final Language language,
+                                                               final Map<Language, LineMarkerProvider> embeddedLanguagesLineMarkerProviders) {
+    final LineMarkerProvider markerProvider;
+
+    if (!embeddedLanguagesLineMarkerProviders.containsKey(language)) {
+      embeddedLanguagesLineMarkerProviders.put(language, markerProvider = LineMarkerProviders.INSTANCE.forLanguage(language));
+    } else {
+      markerProvider = embeddedLanguagesLineMarkerProviders.get(language);
+    }
+    return markerProvider;
+  }
+
+  public void collectSlowLineMarkers(@NotNull final List<PsiElement> elements, @NotNull final Collection<LineMarkerInfo> result) {
+    Map<Language, LineMarkerProvider> localEmbeddedLanguagesLineMarkerProviders = null;
+    Map<LineMarkerProvider, List<PsiElement>> embeddedLineMarkersWorkItems = null;
+
+    for(PsiElement element:elements) {
+      if(element instanceof PsiWhiteSpace) continue;
+      final Language language = element.getLanguage();
+
+      if (!(language instanceof XMLLanguage)) {
+        if(localEmbeddedLanguagesLineMarkerProviders == null) {
+          localEmbeddedLanguagesLineMarkerProviders = new THashMap<Language, LineMarkerProvider>();
+        }
+
+        final LineMarkerProvider lineMarkerProvider = getLineMarkerProviderFromLanguage(language, localEmbeddedLanguagesLineMarkerProviders);
+
+        if (lineMarkerProvider != null) {
+          if (embeddedLineMarkersWorkItems == null) embeddedLineMarkersWorkItems = new THashMap<LineMarkerProvider, List<PsiElement>>();
+          List<PsiElement> elementList = embeddedLineMarkersWorkItems.get(lineMarkerProvider);
+
+          if (elementList == null) {
+            elementList = new ArrayList<PsiElement>(5);
+            embeddedLineMarkersWorkItems.put(lineMarkerProvider, elementList);
+          }
+
+          elementList.add(element);
+        }
+      }
+    }
+
+    if (embeddedLineMarkersWorkItems != null) {
+      for(Map.Entry<LineMarkerProvider, List<PsiElement>> entry:embeddedLineMarkersWorkItems.entrySet()) {
+        entry.getKey().collectSlowLineMarkers(entry.getValue(), result);
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/html/impl/Html5CustomAttributeDescriptorsProvider.java b/xml/impl/src/com/intellij/html/impl/Html5CustomAttributeDescriptorsProvider.java
new file mode 100644
index 0000000..a75e395
--- /dev/null
+++ b/xml/impl/src/com/intellij/html/impl/Html5CustomAttributeDescriptorsProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.html.impl;
+
+import com.intellij.html.index.Html5CustomAttributesIndex;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.Processor;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlAttributeDescriptorsProvider;
+import com.intellij.xml.impl.schema.AnyXmlAttributeDescriptor;
+import com.intellij.xml.util.HtmlUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class Html5CustomAttributeDescriptorsProvider implements XmlAttributeDescriptorsProvider {
+  @Override
+  public XmlAttributeDescriptor[] getAttributeDescriptors(XmlTag tag) {
+    if (tag == null || !HtmlUtil.isHtml5Context(tag)) {
+      return XmlAttributeDescriptor.EMPTY;
+    }
+    final List<String> currentAttrs = new ArrayList<String>();
+    for (XmlAttribute attribute : tag.getAttributes()) {
+      currentAttrs.add(attribute.getName());
+    }
+    final List<XmlAttributeDescriptor> result = new ArrayList<XmlAttributeDescriptor>();
+    FileBasedIndex.getInstance().processAllKeys(Html5CustomAttributesIndex.INDEX_ID, new Processor<String>() {
+      @Override
+      public boolean process(String s) {
+        boolean add = true;
+        for (String attr : currentAttrs) {
+          if (attr.startsWith(s)) {
+            add = false;
+          }
+        }
+        if (add) {
+          result.add(new AnyXmlAttributeDescriptor(s));
+        }
+        return true;
+      }
+    }, tag.getProject());
+
+    return result.toArray(new XmlAttributeDescriptor[result.size()]);
+  }
+
+  @Override
+  public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, XmlTag context) {
+    if (context != null && HtmlUtil.isHtml5Context(context) && HtmlUtil.isCustomHtml5Attribute(attributeName)) {
+      return new AnyXmlAttributeDescriptor(attributeName);
+    }
+    return null;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaElementDescriptor.java b/xml/impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaElementDescriptor.java
new file mode 100644
index 0000000..52a1920
--- /dev/null
+++ b/xml/impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaElementDescriptor.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.html.impl;
+
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.*;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.impl.schema.XmlElementDescriptorImpl;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class RelaxedHtmlFromSchemaElementDescriptor extends XmlElementDescriptorImpl {
+
+  RelaxedHtmlFromSchemaElementDescriptor(XmlTag tag) {
+    super(tag);
+  }
+
+  public XmlElementDescriptor getElementDescriptor(XmlTag childTag, XmlTag contextTag) {
+    XmlElementDescriptor elementDescriptor = super.getElementDescriptor(childTag, contextTag);
+
+    if (elementDescriptor == null) {
+      return getRelaxedDescriptor(this, childTag);
+    }
+
+    return elementDescriptor;
+  }
+
+  public XmlElementDescriptor[] getElementsDescriptors(final XmlTag context) {
+    return ArrayUtil.mergeArrays(
+      super.getElementsDescriptors(context),
+      HtmlUtil.getCustomTagDescriptors(context)
+    );
+  }
+
+  public static XmlElementDescriptor getRelaxedDescriptor(XmlElementDescriptor base, final XmlTag childTag) {
+    final String namespace = childTag.getNamespace();
+    final XmlExtension extension = XmlExtension.getExtensionByElement(childTag);
+    if(!XmlUtil.XHTML_URI.equals(namespace) && 
+       ( base.getContentType() != XmlElementDescriptor.CONTENT_TYPE_EMPTY ||
+         (extension != null && extension.isCustomTagAllowed(childTag)) // allow custom tag
+       ) ) {
+      return new AnyXmlElementDescriptor(base,childTag.getNSDescriptor(namespace,true));
+    }
+    return null;
+  }
+
+  public XmlAttributeDescriptor[] getAttributesDescriptors(final XmlTag context) {
+    return addAttrDescriptorsForFacelets(context, super.getAttributesDescriptors(context));
+  }
+
+  public static XmlAttributeDescriptor[] addAttrDescriptorsForFacelets(final XmlTag context,
+                                                                       XmlAttributeDescriptor[] descriptors) {
+    if (context == null) {
+      return descriptors;
+    }
+    for (XmlAttributeDescriptorsProvider provider: Extensions.getExtensions(XmlAttributeDescriptorsProvider.EP_NAME)) {
+      descriptors = ArrayUtil.mergeArrays(descriptors, provider.getAttributeDescriptors(context), XmlAttributeDescriptor.ARRAY_FACTORY);
+    }
+    return descriptors;
+  }
+
+  @Override
+  public XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attribute) {
+    return getAttributeDescriptor(attribute.getName(), attribute.getParent());
+  }
+
+  public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, final XmlTag context) {
+    final XmlAttributeDescriptor descriptor = super.getAttributeDescriptor(attributeName.toLowerCase(), context);
+    if (descriptor != null) return descriptor;
+
+    return getAttributeDescriptorFromFacelets(attributeName, context);
+  }
+
+  @Nullable
+  public static XmlAttributeDescriptor getAttributeDescriptorFromFacelets(final String attributeName, final XmlTag context) {
+    if (context == null) {
+      return null;
+    }
+    for (XmlAttributeDescriptorsProvider provider: Extensions.getExtensions(XmlAttributeDescriptorsProvider.EP_NAME)) {
+      final XmlAttributeDescriptor descriptor = provider.getAttributeDescriptor(attributeName, context);
+      if (descriptor != null) {
+        return descriptor;
+      }
+    }
+    return null;
+  }
+
+  public boolean allowElementsFromNamespace(final String namespace, final XmlTag context) {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaNSDescriptor.java b/xml/impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaNSDescriptor.java
new file mode 100644
index 0000000..06a9bc97
--- /dev/null
+++ b/xml/impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaNSDescriptor.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.html.impl;
+
+import com.intellij.html.RelaxedHtmlNSDescriptor;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class RelaxedHtmlFromSchemaNSDescriptor extends XmlNSDescriptorImpl implements RelaxedHtmlNSDescriptor {
+  public XmlElementDescriptor getElementDescriptor(@NotNull XmlTag tag) {
+    XmlElementDescriptor elementDescriptor = super.getElementDescriptor(tag);
+
+    String namespace;
+    if (elementDescriptor == null && 
+        !((namespace = tag.getNamespace()).equals(XmlUtil.XHTML_URI))) {
+      return new AnyXmlElementDescriptor(
+        null, 
+        XmlUtil.HTML_URI.equals(namespace) ? this : tag.getNSDescriptor(tag.getNamespace(), true)
+      );
+    }
+
+    return elementDescriptor;
+  }
+
+  protected XmlElementDescriptor createElementDescriptor(final XmlTag tag) {
+    return new RelaxedHtmlFromSchemaElementDescriptor(tag);
+  }
+
+  @NotNull
+  public XmlElementDescriptor[] getRootElementsDescriptors(@Nullable final XmlDocument doc) {
+    return ArrayUtil.mergeArrays(super.getRootElementsDescriptors(doc), HtmlUtil.getCustomTagDescriptors(doc));
+  }
+}
diff --git a/xml/impl/src/com/intellij/html/index/Html5CustomAttributesIndex.java b/xml/impl/src/com/intellij/html/index/Html5CustomAttributesIndex.java
new file mode 100644
index 0000000..152018c
--- /dev/null
+++ b/xml/impl/src/com/intellij/html/index/Html5CustomAttributesIndex.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.html.index;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.lexer.HtmlHighlightingLexer;
+import com.intellij.lexer.Lexer;
+import com.intellij.lexer.XHtmlHighlightingLexer;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.indexing.*;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class Html5CustomAttributesIndex extends ScalarIndexExtension<String> {
+  public static final ID<String, Void> INDEX_ID = ID.create("html5.custom.attributes.index");
+
+  private final DataIndexer<String, Void, FileContent> myIndexer = new DataIndexer<String, Void, FileContent>() {
+    @Override
+    @NotNull
+    public Map<String, Void> map(FileContent inputData) {
+      CharSequence input = inputData.getContentAsText();
+      Language language = ((LanguageFileType)inputData.getFileType()).getLanguage();
+      if (language == HTMLLanguage.INSTANCE || language == XHTMLLanguage.INSTANCE) {
+        final Lexer lexer = (language == HTMLLanguage.INSTANCE ? new HtmlHighlightingLexer() : new XHtmlHighlightingLexer());
+        lexer.start(input);
+        Map<String, Void> result = new HashMap<String, Void>();
+        IElementType tokenType = lexer.getTokenType();
+        while (tokenType != null) {
+          if (tokenType == XmlTokenType.XML_NAME) {
+            String xmlName = input.subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
+            if (HtmlUtil.isCustomHtml5Attribute(xmlName)) {
+              result.put(xmlName, null);
+            }
+          }
+          else if (tokenType == XmlTokenType.XML_DOCTYPE_PUBLIC || tokenType == XmlTokenType.XML_DOCTYPE_SYSTEM) {
+            // this is not an HTML5 context
+            break;
+          }
+          lexer.advance();
+          tokenType = lexer.getTokenType();
+        }
+        return result;
+      }
+      return Collections.emptyMap();
+    }
+  };
+
+  private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
+    @Override
+    public boolean acceptInput(final VirtualFile file) {
+      return (file.getFileSystem() == LocalFileSystem.getInstance() || file.getFileSystem() instanceof TempFileSystem) &&
+             file.getFileType() == StdFileTypes.HTML || file.getFileType() == StdFileTypes.XHTML;
+    }
+  };
+
+  @NotNull
+  @Override
+  public ID<String, Void> getName() {
+    return INDEX_ID;
+  }
+
+  @NotNull
+  @Override
+  public DataIndexer<String, Void, FileContent> getIndexer() {
+    return myIndexer;
+  }
+
+  @Override
+  public KeyDescriptor<String> getKeyDescriptor() {
+    return new EnumeratorStringDescriptor();
+  }
+
+  @Override
+  public FileBasedIndex.InputFilter getInputFilter() {
+    return myInputFilter;
+  }
+
+  @Override
+  public boolean dependsOnFileContent() {
+    return true;
+  }
+
+  @Override
+  public int getVersion() {
+    return 1;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/actions/CreateHtmlFileAction.java b/xml/impl/src/com/intellij/ide/actions/CreateHtmlFileAction.java
new file mode 100644
index 0000000..cbf690c
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/actions/CreateHtmlFileAction.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.actions;
+
+import com.intellij.ide.fileTemplates.FileTemplateManager;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class CreateHtmlFileAction extends CreateFileFromTemplateAction implements DumbAware {
+
+  @NonNls private static final String DEFAULT_HTML_TEMPLATE_PROPERTY = "DefaultHtmlFileTemplate";
+
+  public CreateHtmlFileAction() {
+    super(XmlBundle.message("new.html.file.action"), XmlBundle.message("new.html.file.action.description"), StdFileTypes.HTML.getIcon());
+  }
+
+  @Override
+  protected String getDefaultTemplateProperty() {
+    return DEFAULT_HTML_TEMPLATE_PROPERTY;
+  }
+
+  @Override
+  protected void buildDialog(Project project, PsiDirectory directory, CreateFileFromTemplateDialog.Builder builder) {
+    builder
+      .setTitle(XmlBundle.message("new.html.file.action"))
+      .addKind("HTML file", StdFileTypes.HTML.getIcon(), FileTemplateManager.INTERNAL_HTML5_TEMPLATE_NAME)
+      .addKind("HTML4 file", StdFileTypes.HTML.getIcon(), FileTemplateManager.INTERNAL_HTML_TEMPLATE_NAME)
+      .addKind("XHTML file", StdFileTypes.XHTML.getIcon(), FileTemplateManager.INTERNAL_XHTML_TEMPLATE_NAME);
+  }
+
+  @Override
+  protected String getActionName(PsiDirectory directory, String newName, String templateName) {
+    return XmlBundle.message("new.html.file.action");
+  }
+
+  @Override
+  public int hashCode() {
+    return 0;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    return obj instanceof CreateHtmlFileAction;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
new file mode 100644
index 0000000..7733e8d
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers;
+
+import com.intellij.ide.BrowserSettings;
+import com.intellij.ui.ListCellRendererWrapper;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.openapi.util.IconLoader;
+import com.intellij.ui.ComboboxWithBrowseButton;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.PlatformIcons;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class BrowserSelector {
+  private ComboboxWithBrowseButton myBrowserComboWithBrowse;
+  private boolean myAllowDefaultBrowser;
+
+  public BrowserSelector(boolean allowDefaultBrowser) {
+    myAllowDefaultBrowser = allowDefaultBrowser;
+    myBrowserComboWithBrowse = new ComboboxWithBrowseButton(new ComboBox());
+    myBrowserComboWithBrowse.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        final ShowSettingsUtil util = ShowSettingsUtil.getInstance();
+        util.editConfigurable(myBrowserComboWithBrowse, new BrowserSettings());
+
+        final BrowsersConfiguration.BrowserFamily selectedItem = getSelectedBrowser();
+        initBrowsersComboModel();
+        if (selectedItem != null) {
+          setSelectedBrowser(selectedItem);
+        }
+      }
+    });
+
+    final JComboBox comboBox = myBrowserComboWithBrowse.getComboBox();
+    comboBox.setRenderer(new ListCellRendererWrapper<BrowsersConfiguration.BrowserFamily>() {
+      @Override
+      public void customize(JList list,
+                            BrowsersConfiguration.BrowserFamily value,
+                            int index,
+                            boolean selected,
+                            boolean hasFocus) {
+        final Icon baseIcon = value != null ? value.getIcon() : PlatformIcons.WEB_ICON;
+        final Icon icon = myBrowserComboWithBrowse.isEnabled() ? baseIcon : IconLoader.getDisabledIcon(baseIcon);
+        setIcon(icon);
+        setText(value != null ? value.getName() : "Default");
+      }
+    });
+
+    initBrowsersComboModel();
+  }
+
+  public JComponent getMainComponent() {
+    return myBrowserComboWithBrowse;
+  }
+
+  private void initBrowsersComboModel() {
+    final List<BrowsersConfiguration.BrowserFamily> activeBrowsers = new ArrayList<BrowsersConfiguration.BrowserFamily>();
+    if (myAllowDefaultBrowser) {
+      activeBrowsers.add(null);
+    }
+    activeBrowsers.addAll(BrowsersConfiguration.getInstance().getActiveBrowsers());
+
+    myBrowserComboWithBrowse.getComboBox().setModel(new DefaultComboBoxModel(ArrayUtil.toObjectArray(activeBrowsers)));
+  }
+
+  @Nullable
+  public BrowsersConfiguration.BrowserFamily getSelectedBrowser() {
+    return (BrowsersConfiguration.BrowserFamily)myBrowserComboWithBrowse.getComboBox().getSelectedItem();
+  }
+
+  @Nullable
+  public String getSelectedBrowserFamilyName() {
+    final BrowsersConfiguration.BrowserFamily browser = getSelectedBrowser();
+    return browser != null ? browser.getName() : null;
+  }
+
+  public void setSelectedBrowser(@Nullable BrowsersConfiguration.BrowserFamily selectedItem) {
+    myBrowserComboWithBrowse.getComboBox().setSelectedItem(selectedItem);
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsProviderImpl.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsProviderImpl.java
new file mode 100644
index 0000000..e639095
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsProviderImpl.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers;
+
+import com.intellij.ide.BrowserSettingsProvider;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.options.ConfigurationException;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author spleaner
+ */
+public class BrowserSettingsProviderImpl extends BrowserSettingsProvider {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.ide.browsers.BrowserSettingsProviderImpl");
+  
+  private WebBrowsersPanel mySettingsPanel;
+  private final BrowsersConfiguration myConfiguration;
+
+  public BrowserSettingsProviderImpl(@NotNull final BrowsersConfiguration configuration) {
+    myConfiguration = configuration;
+  }
+
+  @Override
+  public void applySettingsFromWindowsRegistry() {
+    if (mySettingsPanel != null)
+      mySettingsPanel.applySettingsFromWindowsRegistry();
+  }
+
+  public JComponent createComponent() {
+    if (mySettingsPanel == null) {
+      mySettingsPanel = new WebBrowsersPanel(myConfiguration);
+    }
+
+    return mySettingsPanel;
+  }
+
+  public boolean isModified() {
+    LOG.assertTrue(mySettingsPanel != null);
+    return mySettingsPanel.isModified();
+  }
+
+  public void apply() throws ConfigurationException {
+    LOG.assertTrue(mySettingsPanel != null);
+    mySettingsPanel.apply();
+  }
+
+  public void reset() {
+    LOG.assertTrue(mySettingsPanel != null);
+    mySettingsPanel.reset();
+  }
+
+  public void disposeUIResources() {
+    mySettingsPanel.dispose();
+    mySettingsPanel = null;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSpecificSettings.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
new file mode 100644
index 0000000..2af780a
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers;
+
+import com.intellij.openapi.options.Configurable;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * @author nik
+ */
+public abstract class BrowserSpecificSettings {
+
+  public abstract Configurable createConfigurable();
+
+  @NotNull @NonNls
+  public String[] getAdditionalParameters() {
+    return ArrayUtil.EMPTY_STRING_ARRAY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java b/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java
new file mode 100644
index 0000000..4702fe6
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.BrowserUtil;
+import com.intellij.ide.browsers.chrome.ChromeSettings;
+import com.intellij.ide.browsers.firefox.FirefoxSettings;
+import com.intellij.ide.browsers.impl.DefaultUrlOpener;
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.WindowsRegistryUtil;
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
+import com.intellij.util.xmlb.XmlSerializer;
+import com.intellij.xml.XmlBundle;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author spleaner
+ */
+@State(name = "WebBrowsersConfiguration", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/browsers.xml")})
+public class BrowsersConfiguration implements PersistentStateComponent<Element> {
+  public enum BrowserFamily {
+    EXPLORER(XmlBundle.message("browsers.explorer"), "iexplore", null, null, AllIcons.Xml.Browsers.Explorer16),
+    SAFARI(XmlBundle.message("browsers.safari"), "safari", null, "Safari", AllIcons.Xml.Browsers.Safari16),
+    OPERA(XmlBundle.message("browsers.opera"), "opera", "opera", "Opera", AllIcons.Xml.Browsers.Opera16),
+    FIREFOX(XmlBundle.message("browsers.firefox"), "firefox", "firefox", "Firefox", AllIcons.Xml.Browsers.Firefox16) {
+      @Override
+      public BrowserSpecificSettings createBrowserSpecificSettings() {
+        return new FirefoxSettings();
+      }
+    },
+    CHROME(XmlBundle.message("browsers.chrome"), "chrome", "google-chrome", "Google Chrome", AllIcons.Xml.Browsers.Chrome16) {
+      @Override
+      public BrowserSpecificSettings createBrowserSpecificSettings() {
+        return new ChromeSettings();
+      }
+    };
+
+    private final String myName;
+    private final String myWindowsPath;
+    private final String myUnixPath;
+    private final String myMacPath;
+    private final Icon myIcon;
+
+    BrowserFamily(final String name,
+                  @NonNls final String windowsPath,
+                  @NonNls final String unixPath,
+                  @NonNls final String macPath,
+                  final Icon icon) {
+      myName = name;
+      myWindowsPath = windowsPath;
+      myUnixPath = unixPath;
+      myMacPath = macPath;
+      myIcon = icon;
+    }
+
+    @Nullable
+    public BrowserSpecificSettings createBrowserSpecificSettings() {
+      return null;
+    }
+
+    @Nullable
+    public String getExecutionPath() {
+      if (SystemInfo.isWindows) {
+        return myWindowsPath;
+      }
+      else if (SystemInfo.isMac) {
+        return myMacPath;
+      }
+      else if (SystemInfo.isUnix) {
+        return myUnixPath;
+      }
+
+      return null;
+    }
+
+    public String getName() {
+      return myName;
+    }
+
+    public Icon getIcon() {
+      return myIcon;
+    }
+  }
+
+  private final Map<BrowserFamily, WebBrowserSettings> myBrowserToSettingsMap = new HashMap<BrowserFamily, WebBrowserSettings>();
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public Element getState() {
+    @NonNls Element element = new Element("WebBrowsersConfiguration");
+    for (BrowserFamily browserFamily : myBrowserToSettingsMap.keySet()) {
+      final Element browser = new Element("browser");
+      browser.setAttribute("family", browserFamily.toString());
+      final WebBrowserSettings value = myBrowserToSettingsMap.get(browserFamily);
+      browser.setAttribute("path", value.getPath());
+      browser.setAttribute("active", Boolean.toString(value.isActive()));
+      final BrowserSpecificSettings specificSettings = value.getBrowserSpecificSettings();
+      if (specificSettings != null) {
+        final Element settingsElement = new Element("settings");
+        XmlSerializer.serializeInto(specificSettings, settingsElement, new SkipDefaultValuesSerializationFilters());
+        browser.addContent(settingsElement);
+      }
+      element.addContent(browser);
+    }
+
+    return element;
+  }
+
+  @SuppressWarnings({"unchecked"})
+  public void loadState(@NonNls Element element) {
+    for (@NonNls Element child : (Iterable<? extends Element>)element.getChildren("browser")) {
+      String family = child.getAttributeValue("family");
+      final String path = child.getAttributeValue("path");
+      final String active = child.getAttributeValue("active");
+      final BrowserFamily browserFamily;
+      Element settingsElement = child.getChild("settings");
+
+      try {
+        browserFamily = BrowserFamily.valueOf(family);
+        BrowserSpecificSettings specificSettings = null;
+        if (settingsElement != null) {
+          specificSettings = browserFamily.createBrowserSpecificSettings();
+          XmlSerializer.deserializeInto(specificSettings, settingsElement);
+        }
+        myBrowserToSettingsMap.put(browserFamily, new WebBrowserSettings(path, Boolean.parseBoolean(active), specificSettings));
+      }
+      catch (IllegalArgumentException e) {
+        // skip
+      }
+    }
+  }
+
+  public List<BrowserFamily> getActiveBrowsers() {
+    final List<BrowserFamily> browsers = new ArrayList<BrowserFamily>();
+    for (BrowserFamily family : BrowserFamily.values()) {
+      if (getBrowserSettings(family).isActive()) {
+        browsers.add(family);
+      }
+    }
+    return browsers;
+  }
+
+  public void updateBrowserValue(final BrowserFamily family, final String path, boolean isActive) {
+    final WebBrowserSettings settings = getBrowserSettings(family);
+    myBrowserToSettingsMap.put(family, new WebBrowserSettings(path, isActive, settings.getBrowserSpecificSettings()));
+  }
+
+  public void updateBrowserSpecificSettings(BrowserFamily family, BrowserSpecificSettings specificSettings) {
+    final WebBrowserSettings settings = getBrowserSettings(family);
+    myBrowserToSettingsMap.put(family, new WebBrowserSettings(settings.getPath(), settings.isActive(), specificSettings));
+  }
+
+  @NotNull
+  public WebBrowserSettings getBrowserSettings(@NotNull final BrowserFamily browserFamily) {
+    WebBrowserSettings result = myBrowserToSettingsMap.get(browserFamily);
+    if (result == null) {
+      final String path = browserFamily.getExecutionPath();
+      result = new WebBrowserSettings(path == null ? "" : path, path != null, null);
+      myBrowserToSettingsMap.put(browserFamily, result);
+    }
+
+    return result;
+  }
+
+  public static BrowsersConfiguration getInstance() {
+    return ServiceManager.getService(BrowsersConfiguration.class);
+  }
+
+  public static void launchBrowser(final @Nullable BrowserFamily family, @NotNull final String url) {
+    if (family == null) {
+      BrowserUtil.launchBrowser(url);
+    }
+    else {
+      for (UrlOpener urlOpener : UrlOpener.EP_NAME.getExtensions()) {
+        if (urlOpener.openUrl(family, url)) {
+          return;
+        }
+      }
+    }
+  }
+
+  public static void launchBrowser(final @NotNull BrowserFamily family, @NotNull final String url, String... parameters) {
+    launchBrowser(family, url, false, parameters);
+  }
+
+  public static void launchBrowser(final @NotNull BrowserFamily family,
+                                   @Nullable final String url,
+                                   final boolean forceOpenNewInstanceOnMac,
+                                   String... parameters) {
+    DefaultUrlOpener.launchBrowser(family, url, parameters, Conditions.<String>alwaysTrue(), forceOpenNewInstanceOnMac);
+  }
+
+  public static void launchBrowser(final @NotNull BrowserFamily family,
+                                   @NotNull final String url,
+                                   final boolean forceOpenNewInstanceOnMac,
+                                   final Condition<String> browserSpecificParametersFilter,
+                                   String... parameters) {
+    DefaultUrlOpener.launchBrowser(family, url, parameters, browserSpecificParametersFilter, forceOpenNewInstanceOnMac);
+  }
+
+  @Nullable
+  public static BrowserFamily findFamilyByName(@Nullable String name) {
+    for (BrowserFamily family : BrowserFamily.values()) {
+      if (family.getName().equals(name)) {
+        return family;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Gets data from Windows registry, may take some time to run (up to ~300ms)
+   *
+   * @return Map[BrowserFamily -> "path to .exe"]
+   */
+  @NotNull
+  public static EnumMap<BrowserFamily, String> getWindowsBrowsersEXE() {
+    EnumMap<BrowserFamily, String> map = new EnumMap<BrowserFamily, String>(BrowserFamily.class);
+    if (SystemInfo.isWindows) {
+      List<String> sections = WindowsRegistryUtil.readRegistryBranch("HKEY_LOCAL_MACHINE\\SOFTWARE\\Clients\\StartMenuInternet");
+      for (String section : sections) {
+        BrowserFamily family = getFamily(section);
+        if (family == null) {
+          continue; //We ignore "unknown" browsers like Maxthon, RockMelt, SeaMonkey, Deepnet Explorer, Avant Browser etc.
+        }
+        String pathToExe = WindowsRegistryUtil.readRegistryDefault(
+          "HKLM\\SOFTWARE\\Clients\\StartMenuInternet\\" + section + "\\shell\\open\\command");
+        if (pathToExe != null) {
+          map.put(family, pathToExe);
+        }
+      }
+    }
+    return map;
+  }
+
+  @Nullable
+  private static BrowserFamily getFamily(String registryName) {
+    registryName = registryName.toLowerCase();
+    if (registryName.contains("firefox")) {
+      return BrowserFamily.FIREFOX;
+    }
+    if (registryName.contains("iexplore")) {
+      return BrowserFamily.EXPLORER;
+    }
+    if (registryName.contains("opera")) {
+      return BrowserFamily.OPERA;
+    }
+    if (registryName.contains("safari")) {
+      return BrowserFamily.SAFARI;
+    }
+    if (registryName.contains("google")) {
+      return BrowserFamily.CHROME;
+    }
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/OpenFileInBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/OpenFileInBrowserAction.java
new file mode 100644
index 0000000..2326b1c
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/OpenFileInBrowserAction.java
@@ -0,0 +1,77 @@
+package com.intellij.ide.browsers;
+
+import com.intellij.ide.BrowserUtil;
+import com.intellij.ide.browsers.impl.WebBrowserServiceImpl;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.psi.PsiFile;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.util.HtmlUtil;
+
+import java.awt.event.InputEvent;
+
+public class OpenFileInBrowserAction extends DumbAwareAction {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.ide.browsers.OpenFileInBrowserAction");
+
+  public void update(AnActionEvent e) {
+    final DataContext dataContext = e.getDataContext();
+    final PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
+    final Presentation presentation = e.getPresentation();
+
+    if (file != null && file.getVirtualFile() != null) {
+      presentation.setVisible(true);
+
+      final WebBrowserUrlProvider browserUrlProvider = WebBrowserServiceImpl.getProvider(file);
+      final boolean isHtmlFile = HtmlUtil.isHtmlFile(file);
+      presentation.setEnabled(browserUrlProvider != null || isHtmlFile);
+      String text = getTemplatePresentation().getText();
+      String description = getTemplatePresentation().getDescription();
+
+      if (browserUrlProvider != null) {
+        final String customText = browserUrlProvider.getOpenInBrowserActionText(file);
+        if (customText != null) {
+          text = customText;
+        }
+        final String customDescription = browserUrlProvider.getOpenInBrowserActionDescription(file);
+        if (customDescription != null) {
+          description = customDescription;
+        }
+        if (isHtmlFile) {
+          description += " (hold Shift to open URL of local file)";
+        }
+      }
+
+      presentation.setText(text);
+      presentation.setDescription(description);
+      if (ActionPlaces.isPopupPlace(e.getPlace())) {
+        presentation.setVisible(presentation.isEnabled());
+      }
+    } else {
+      presentation.setVisible(false);
+      presentation.setEnabled(false);
+    }
+  }
+
+  public void actionPerformed(AnActionEvent e) {
+    final DataContext dataContext = e.getDataContext();
+    final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(dataContext);
+    LOG.assertTrue(psiFile != null);
+    try {
+      final InputEvent event = e.getInputEvent();
+      final String url = WebBrowserService.getInstance().getUrlToOpen(psiFile, event != null && event.isShiftDown());
+      if (url != null) {
+        ApplicationManager.getApplication().saveAll();
+        BrowserUtil.launchBrowser(url);
+      }
+    }
+    catch (WebBrowserUrlProvider.BrowserException e1) {
+      Messages.showErrorDialog(e1.getMessage(), XmlBundle.message("browser.error"));
+    }
+    catch (Exception e1) {
+      LOG.error(e1);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java
new file mode 100644
index 0000000..880afc2
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers;
+
+import com.intellij.execution.filters.HyperlinkWithPopupMenuInfo;
+import com.intellij.ide.BrowserUtil;
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.ide.CopyPasteManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.util.PlatformIcons;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.MouseEvent;
+
+/**
+ * @author nik
+ */
+public class OpenUrlHyperlinkInfo implements HyperlinkWithPopupMenuInfo {
+  private String myUrl;
+  private final Condition<BrowsersConfiguration.BrowserFamily> mySuitableBrowsers;
+
+  public OpenUrlHyperlinkInfo(@NotNull String url) {
+    this(url, Condition.TRUE);
+  }
+
+  public OpenUrlHyperlinkInfo(@NotNull String url, @NotNull Condition<BrowsersConfiguration.BrowserFamily> suitableBrowsers) {
+    myUrl = url;
+    mySuitableBrowsers = suitableBrowsers;
+  }
+
+  @Override
+  public ActionGroup getPopupMenuGroup(@NotNull MouseEvent event) {
+    final DefaultActionGroup group = new DefaultActionGroup();
+    for (BrowsersConfiguration.BrowserFamily family : BrowsersConfiguration.getInstance().getActiveBrowsers()) {
+      if (mySuitableBrowsers.value(family)) {
+        group.add(new OpenUrlInBrowserAction(family));
+      }
+    }
+    group.addAll(new CopyUrlToClipboardAction());
+
+    return group;
+  }
+
+  @Override
+  public void navigate(Project project) {
+    BrowserUtil.launchBrowser(myUrl);
+  }
+
+  private class CopyUrlToClipboardAction extends AnAction {
+    private CopyUrlToClipboardAction() {
+      super("Copy URL", "Copy URL to clipboard", PlatformIcons.COPY_ICON);
+    }
+
+    @Override
+    public void actionPerformed(AnActionEvent e) {
+      CopyPasteManager.getInstance().setContents(new StringSelection(myUrl));
+    }
+  }
+
+  private class OpenUrlInBrowserAction extends AnAction {
+    private final BrowsersConfiguration.BrowserFamily myFamily;
+
+    public OpenUrlInBrowserAction(@NotNull BrowsersConfiguration.BrowserFamily family) {
+      super("Open in " + family.getName(), "Open URL in " + family.getName(), family.getIcon());
+      myFamily = family;
+    }
+
+    @Override
+    public void actionPerformed(AnActionEvent e) {
+      BrowsersConfiguration.launchBrowser(myFamily, myUrl);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java
new file mode 100644
index 0000000..36ba41e
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+
+public abstract class UrlOpener {
+  public static final ExtensionPointName<UrlOpener> EP_NAME = ExtensionPointName.create("org.jetbrains.urlOpener");
+
+  public abstract boolean openUrl(BrowsersConfiguration.BrowserFamily family, String url);
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserSettings.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserSettings.java
new file mode 100644
index 0000000..e7b391d
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserSettings.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public class WebBrowserSettings {
+  private final String myPath;
+  private final boolean myActive;
+  private final BrowserSpecificSettings myBrowserSpecificSettings;
+
+  public WebBrowserSettings(String path, boolean active, BrowserSpecificSettings browserSpecificSettings) {
+    myPath = path;
+    myActive = active;
+    myBrowserSpecificSettings = browserSpecificSettings;
+  }
+
+  public String getPath() {
+    return myPath;
+  }
+
+  public boolean isActive() {
+    return myActive;
+  }
+
+  @Nullable
+  public BrowserSpecificSettings getBrowserSpecificSettings() {
+    return myBrowserSpecificSettings;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowsersPanel.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowsersPanel.java
new file mode 100644
index 0000000..e5f53e7
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowsersPanel.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.ui.IdeBorderFactory;
+import com.intellij.util.containers.HashMap;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * @author spleaner
+ */
+public class WebBrowsersPanel extends JPanel {
+  private final JPanel mySettingsPanel;
+  private Map<BrowsersConfiguration.BrowserFamily, Pair<JCheckBox, TextFieldWithBrowseButton>> myBrowserSettingsMap =
+    new HashMap<BrowsersConfiguration.BrowserFamily, Pair<JCheckBox, TextFieldWithBrowseButton>>();
+  private final BrowsersConfiguration myConfiguration;
+
+  public WebBrowsersPanel(final BrowsersConfiguration configuration) {
+    setLayout(new BorderLayout());
+
+    myConfiguration = configuration;
+
+    mySettingsPanel = new JPanel();
+    mySettingsPanel.setLayout(new BoxLayout(mySettingsPanel, BoxLayout.Y_AXIS));
+
+    add(mySettingsPanel, BorderLayout.NORTH);
+
+    createIndividualSettings(BrowsersConfiguration.BrowserFamily.FIREFOX, mySettingsPanel);
+    createIndividualSettings(BrowsersConfiguration.BrowserFamily.EXPLORER, mySettingsPanel);
+    createIndividualSettings(BrowsersConfiguration.BrowserFamily.SAFARI, mySettingsPanel);
+    createIndividualSettings(BrowsersConfiguration.BrowserFamily.CHROME, mySettingsPanel);
+    createIndividualSettings(BrowsersConfiguration.BrowserFamily.OPERA, mySettingsPanel);
+  }
+
+  private void createIndividualSettings(@NotNull final BrowsersConfiguration.BrowserFamily family, final JPanel container) {
+    final JPanel result = new JPanel();
+
+    result.setBorder(IdeBorderFactory.createTitledBorder(family.getName(), true));
+
+    result.setLayout(new BoxLayout(result, BoxLayout.Y_AXIS));
+
+    final TextFieldWithBrowseButton field = new TextFieldWithBrowseButton();
+    FileChooserDescriptor descriptor = SystemInfo.isMac
+                                       ? FileChooserDescriptorFactory.createSingleFolderDescriptor()
+                                       : FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor();
+    field.addBrowseFolderListener(IdeBundle.message("title.select.path.to.browser"), null, null, descriptor);
+
+    result.add(field);
+
+    final JPanel bottomPanel = new JPanel(new BorderLayout());
+
+    final JPanel activePanel = new JPanel();
+    activePanel.setLayout(new BoxLayout(activePanel, BoxLayout.X_AXIS));
+
+    final JCheckBox checkBox = new JCheckBox();
+    activePanel.add(checkBox);
+    final JLabel label = new JLabel(XmlBundle.message("browser.active"));
+    label.setLabelFor(checkBox);
+    activePanel.add(label);
+    bottomPanel.add(activePanel, BorderLayout.WEST);
+
+    final JButton resetButton = new JButton(XmlBundle.message("browser.default.settings"));
+    resetButton.addActionListener(new ActionListener() {
+      public void actionPerformed(final ActionEvent e) {
+        field.getTextField().setText(family.getExecutionPath());
+      }
+    });
+
+    JPanel buttonsPanel = new JPanel(new BorderLayout());
+    if (family.createBrowserSpecificSettings() != null) {
+      final JButton editSettingsButton = new JButton(XmlBundle.message("button.text.settings"));
+      editSettingsButton.addActionListener(new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+          editSettings(family);
+        }
+      });
+      buttonsPanel.add(editSettingsButton, BorderLayout.CENTER);
+    }
+    buttonsPanel.add(resetButton, BorderLayout.EAST);
+
+    bottomPanel.add(buttonsPanel, BorderLayout.EAST);
+
+    result.add(bottomPanel);
+    container.add(result);
+
+    final WebBrowserSettings settings = myConfiguration.getBrowserSettings(family);
+    field.getTextField().setText(settings.getPath());
+    checkBox.setSelected(settings.isActive());
+
+    myBrowserSettingsMap.put(family, Pair.create(checkBox, field));
+  }
+
+  private void editSettings(BrowsersConfiguration.BrowserFamily family) {
+    BrowserSpecificSettings settings = myConfiguration.getBrowserSettings(family).getBrowserSpecificSettings();
+    if (settings == null) {
+      settings = family.createBrowserSpecificSettings();
+    }
+
+    if (ShowSettingsUtil.getInstance().editConfigurable(mySettingsPanel, settings.createConfigurable())) {
+      myConfiguration.updateBrowserSpecificSettings(family, settings);
+    }
+  }
+
+  public void applySettingsFromWindowsRegistry() {
+    if (!SystemInfo.isWindows) {
+      return;
+    }
+    ApplicationManager.getApplication()
+      .executeOnPooledThread(new SwingWorker<EnumMap<BrowsersConfiguration.BrowserFamily, String>, Void>() {
+        @Override
+        protected EnumMap<BrowsersConfiguration.BrowserFamily, String> doInBackground() throws Exception {
+          return BrowsersConfiguration.getWindowsBrowsersEXE();
+        }
+
+        @Override
+        protected void done() {
+          EnumMap<BrowsersConfiguration.BrowserFamily, String> map = null;
+          try {
+            map = get();
+          }
+          catch (InterruptedException ignored) {
+          }
+          catch (ExecutionException ignored) {
+          }
+          if (myBrowserSettingsMap == null) {
+            return;//we are disposed
+          }
+          if (map != null && !map.isEmpty()) {
+            for (BrowsersConfiguration.BrowserFamily family : BrowsersConfiguration.BrowserFamily.values()) {
+              Pair<JCheckBox, TextFieldWithBrowseButton> pair = myBrowserSettingsMap.get(family);
+              String pathToExe = map.get(family);
+              if (pathToExe != null) {
+                pair.first.setSelected(true);
+                pair.second.setText(pathToExe);
+              }
+              else {
+                pair.first.setSelected(false);
+              }
+            }
+          }
+        }
+      });
+  }
+
+
+  public void dispose() {
+    myBrowserSettingsMap = null;
+  }
+
+  public boolean isModified() {
+    for (BrowsersConfiguration.BrowserFamily family : BrowsersConfiguration.BrowserFamily.values()) {
+      final WebBrowserSettings old = myConfiguration.getBrowserSettings(family);
+      final Pair<JCheckBox, TextFieldWithBrowseButton> settings = myBrowserSettingsMap.get(family);
+
+      if (old.isActive() != settings.first.isSelected() || !old.getPath().equals(settings.second.getText())) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  public void apply() {
+    for (BrowsersConfiguration.BrowserFamily family : myBrowserSettingsMap.keySet()) {
+      final Pair<JCheckBox, TextFieldWithBrowseButton> buttonPair = myBrowserSettingsMap.get(family);
+      myConfiguration.updateBrowserValue(family, buttonPair.second.getText(), buttonPair.first.isSelected());
+    }
+  }
+
+  public void reset() {
+    for (BrowsersConfiguration.BrowserFamily family : myBrowserSettingsMap.keySet()) {
+      final Pair<JCheckBox, TextFieldWithBrowseButton> buttonPair = myBrowserSettingsMap.get(family);
+      final WebBrowserSettings settings = myConfiguration.getBrowserSettings(family);
+      buttonPair.first.setSelected(settings.isActive());
+      buttonPair.second.getTextField().setText(settings.getPath());
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
new file mode 100644
index 0000000..81f9044
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers.chrome;
+
+import com.intellij.execution.configurations.ParametersList;
+import com.intellij.ide.browsers.BrowserSpecificSettings;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public class ChromeSettings extends BrowserSpecificSettings {
+  @NonNls public static final String USER_DATA_DIR_ARG = "--user-data-dir=";
+  private String myCommandLineOptions = "";
+  private String myUserDataDirectoryPath;
+  private boolean myUseCustomProfile;
+
+  public ChromeSettings() {
+  }
+
+  @Nullable
+  @Tag("user-data-dir")
+  public String getUserDataDirectoryPath() {
+    return myUserDataDirectoryPath;
+  }
+
+  @Tag("use-custom-profile")
+  public boolean isUseCustomProfile() {
+    return myUseCustomProfile;
+  }
+
+  @Tag("command-line-options")
+  public String getCommandLineOptions() {
+    return myCommandLineOptions;
+  }
+
+  public void setCommandLineOptions(String commandLineOptions) {
+    myCommandLineOptions = commandLineOptions;
+  }
+
+  public void setUserDataDirectoryPath(String userDataDirectoryPath) {
+    myUserDataDirectoryPath = userDataDirectoryPath;
+  }
+
+  public void setUseCustomProfile(boolean useCustomProfile) {
+    myUseCustomProfile = useCustomProfile;
+  }
+
+  @NotNull
+  @Override
+  public String[] getAdditionalParameters() {
+    String[] cliOptions = ParametersList.parse(myCommandLineOptions);
+    if (myUseCustomProfile && myUserDataDirectoryPath != null) {
+      return ArrayUtil.mergeArrays(cliOptions, USER_DATA_DIR_ARG + FileUtil.toSystemDependentName(myUserDataDirectoryPath));
+    }
+    else {
+      return cliOptions;
+    }
+  }
+
+  @Override
+  public ChromeSettingsConfigurable createConfigurable() {
+    return new ChromeSettingsConfigurable(this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form
new file mode 100644
index 0000000..12051d9
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.browsers.chrome.ChromeSettingsConfigurable">
+  <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="6d1fc" class="javax.swing.JCheckBox" binding="myUseCustomProfileCheckBox">
+        <constraints>
+          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text value="&amp;Use custom profile directory:"/>
+        </properties>
+      </component>
+      <vspacer id="eb956">
+        <constraints>
+          <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+        </constraints>
+      </vspacer>
+      <component id="e97dd" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myUserDataDirField">
+        <constraints>
+          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="2" use-parent-layout="false">
+            <preferred-size width="350" height="-1"/>
+          </grid>
+        </constraints>
+        <properties/>
+      </component>
+      <component id="3fc23" class="com.intellij.ui.RawCommandLineEditor" binding="myCommandLineOptionsEditor">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="2" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+      </component>
+      <component id="4b3a7" class="javax.swing.JLabel" binding="myCommandLineOptionsLabel">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text value="&amp;Command line options:"/>
+        </properties>
+      </component>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java
new file mode 100644
index 0000000..9e8b681
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers.chrome;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.ui.RawCommandLineEditor;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public class ChromeSettingsConfigurable implements Configurable {
+  private final ChromeSettings mySettings;
+  private JPanel myMainPanel;
+  private JCheckBox myUseCustomProfileCheckBox;
+  private TextFieldWithBrowseButton myUserDataDirField;
+  private JLabel myCommandLineOptionsLabel;
+  private RawCommandLineEditor myCommandLineOptionsEditor;
+  private final String myDefaultUserDirPath;
+
+  public ChromeSettingsConfigurable(@NotNull ChromeSettings settings) {
+    mySettings = settings;
+    myUserDataDirField.addBrowseFolderListener("Select User Data Directory", "Specifies the directory that user data (your \"profile\") is kept in", null,
+                                               FileChooserDescriptorFactory.createSingleFolderDescriptor());
+    myUseCustomProfileCheckBox.addActionListener(new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        myUserDataDirField.setEnabled(myUseCustomProfileCheckBox.isSelected());
+      }
+    });
+    myDefaultUserDirPath = getDefaultUserDataPath();
+    myCommandLineOptionsEditor.setDialogCaption("Chrome Command Line Options");
+    myCommandLineOptionsLabel.setLabelFor(myCommandLineOptionsEditor.getTextField());
+  }
+
+  @Override
+  public JComponent createComponent() {
+    return myMainPanel;
+  }
+
+  @Override
+  public boolean isModified() {
+    if (myUseCustomProfileCheckBox.isSelected() != mySettings.isUseCustomProfile()
+        || !myCommandLineOptionsEditor.getText().equals(mySettings.getCommandLineOptions())) {
+      return true;
+    }
+
+    String configuredPath = getConfiguredUserDataDirPath();
+    String storedPath = mySettings.getUserDataDirectoryPath();
+    if (myDefaultUserDirPath.equals(configuredPath) && storedPath == null) return false;
+    return !configuredPath.equals(storedPath);
+  }
+
+
+  private String getConfiguredUserDataDirPath() {
+    return FileUtil.toSystemIndependentName(myUserDataDirField.getText());
+  }
+
+  @Override
+  public void apply() throws ConfigurationException {
+    mySettings.setCommandLineOptions(myCommandLineOptionsEditor.getText());
+    mySettings.setUseCustomProfile(myUseCustomProfileCheckBox.isSelected());
+    mySettings.setUserDataDirectoryPath(getConfiguredUserDataDirPath());
+  }
+
+  @Override
+  public void reset() {
+    myCommandLineOptionsEditor.setText(mySettings.getCommandLineOptions());
+    myUseCustomProfileCheckBox.setSelected(mySettings.isUseCustomProfile());
+    myUserDataDirField.setEnabled(mySettings.isUseCustomProfile());
+    String path = mySettings.getUserDataDirectoryPath();
+    if (path != null) {
+      myUserDataDirField.setText(FileUtil.toSystemDependentName(path));
+    }
+    else {
+      myUserDataDirField.setText(myDefaultUserDirPath);
+    }
+  }
+
+  public void enableRecommendedOptions() {
+    if (!myUseCustomProfileCheckBox.isSelected()) {
+      myUseCustomProfileCheckBox.doClick(0);
+    }
+  }
+
+  private static String getDefaultUserDataPath() {
+    File dir = new File(PathManager.getConfigPath(), "chrome-user-data");
+    try {
+      return dir.getCanonicalPath();
+    }
+    catch (IOException e) {
+      return dir.getAbsolutePath();
+    }
+  }
+
+  @Override
+  public void disposeUIResources() {
+  }
+
+  @Nls
+  @Override
+  public String getDisplayName() {
+    return "Chrome Settings";
+  }
+
+  @Override
+  public String getHelpTopic() {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java
new file mode 100644
index 0000000..133ee83
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers.firefox;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class FirefoxProfile {
+  private final String myName;
+  private final String myPath;
+  private final boolean myDefault;
+  private final boolean myRelative;
+
+  public FirefoxProfile(String name, String path, boolean aDefault, boolean relative) {
+    myName = name;
+    myPath = path;
+    myDefault = aDefault;
+    myRelative = relative;
+  }
+
+  public String getName() {
+    return myName;
+  }
+
+  public String getPath() {
+    return myPath;
+  }
+
+  public boolean isRelative() {
+    return myRelative;
+  }
+
+  public boolean isDefault() {
+    return myDefault;
+  }
+
+  public File getProfileDirectory(File profilesIniFile) {
+    return myRelative ? new File(profilesIniFile.getParentFile(), myPath) : new File(myPath);
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java
new file mode 100644
index 0000000..618a015
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers.firefox;
+
+import com.intellij.ide.browsers.BrowserSpecificSettings;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class FirefoxSettings extends BrowserSpecificSettings {
+  private String myProfilesIniPath;
+  private String myProfile;
+
+  public FirefoxSettings() {
+  }
+
+  public FirefoxSettings(String profilesIniPath, String profile) {
+    myProfilesIniPath = profilesIniPath;
+    myProfile = profile;
+  }
+
+  @Nullable
+  @Tag("profiles-ini-path")
+  public String getProfilesIniPath() {
+    return myProfilesIniPath;
+  }
+
+  public void setProfilesIniPath(String profilesIniPath) {
+    myProfilesIniPath = profilesIniPath;
+  }
+
+  @Nullable
+  @Tag("profile")
+  public String getProfile() {
+    return myProfile;
+  }
+
+  public void setProfile(String profile) {
+    myProfile = profile;
+  }
+
+  @Override
+  public Configurable createConfigurable() {
+    return new FirefoxSettingsConfigurable(this);
+  }
+
+  @Nullable
+  public File getProfilesIniFile() {
+    if (myProfilesIniPath != null) {
+      return new File(FileUtil.toSystemDependentName(myProfilesIniPath));
+    }
+    return FirefoxUtil.getDefaultProfileIniPath();
+  }
+
+  @NotNull
+  @Override
+  public String[] getAdditionalParameters() {
+    final List<FirefoxProfile> profiles = FirefoxUtil.computeProfiles(getProfilesIniFile());
+    if (profiles.size() >= 2) {
+      final FirefoxProfile profile = FirefoxUtil.findProfileByNameOrDefault(myProfile, profiles);
+      if (profile != null && !profile.isDefault()) {
+        return new String[] {"-P", profile.getName()};
+      }
+    }
+    return ArrayUtil.EMPTY_STRING_ARRAY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form
new file mode 100644
index 0000000..bd1e753
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.browsers.firefox.FirefoxSettingsConfigurable">
+  <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <vspacer id="90b50">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+        </constraints>
+      </vspacer>
+      <grid id="735f0" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <grid id="f9834" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="852e3" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="messages/XmlBundle" key="label.text.path.to.profiles.ini"/>
+                </properties>
+              </component>
+              <hspacer id="d637d">
+                <constraints>
+                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+              </hspacer>
+            </children>
+          </grid>
+          <component id="a31a5" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myProfilesIniPathField">
+            <constraints>
+              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="2" use-parent-layout="false">
+                <preferred-size width="350" height="-1"/>
+              </grid>
+            </constraints>
+            <properties/>
+          </component>
+          <grid id="baf65" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints>
+              <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="11a5c" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <labelFor value="c6e14"/>
+                  <text resource-bundle="messages/XmlBundle" key="label.text.profile"/>
+                </properties>
+              </component>
+              <hspacer id="d3289">
+                <constraints>
+                  <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+              </hspacer>
+              <component id="c6e14" class="javax.swing.JComboBox" binding="myProfileCombobox">
+                <constraints>
+                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+              </component>
+            </children>
+          </grid>
+        </children>
+      </grid>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
new file mode 100644
index 0000000..fb92f51
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers.firefox;
+
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class FirefoxSettingsConfigurable implements Configurable {
+  private static final FileChooserDescriptor PROFILES_INI_CHOOSER_DESCRIPTOR = createProfilesIniChooserDescriptor();
+
+  private JPanel myMainPanel;
+  private JComboBox myProfileCombobox;
+  private TextFieldWithBrowseButton myProfilesIniPathField;
+  private final FirefoxSettings mySettings;
+  private String myLastProfilesIniPath;
+  private String myDefaultProfilesIniPath;
+  private String myDefaultProfile;
+
+  public FirefoxSettingsConfigurable(FirefoxSettings settings) {
+    mySettings = settings;
+    myProfilesIniPathField.addBrowseFolderListener(XmlBundle.message("chooser.title.select.profiles.ini.file"), null, null, PROFILES_INI_CHOOSER_DESCRIPTOR);
+    myProfilesIniPathField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
+      @Override
+      protected void textChanged(DocumentEvent e) {
+        updateProfilesList();
+      }
+    });
+  }
+
+  public static FileChooserDescriptor createProfilesIniChooserDescriptor() {
+    return new FileChooserDescriptor(true, false, false, false, false, false) {
+      @Override
+      public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
+        if (!file.isDirectory() && !file.getName().equals(FirefoxUtil.PROFILES_INI_FILE)) {
+          return false;
+        }
+        return super.isFileVisible(file, showHiddenFiles);
+      }
+    };
+  }
+
+  public JComponent createComponent() {
+    return myMainPanel;
+  }
+
+  public boolean isModified() {
+    return !Comparing.equal(mySettings.getProfile(), getConfiguredProfileName()) ||
+           !Comparing.equal(mySettings.getProfilesIniPath(), getConfiguredProfileIniPath());
+  }
+
+  @Nullable
+  private String getConfiguredProfileIniPath() {
+    final String path = myProfilesIniPathField.getText();
+    if (myDefaultProfilesIniPath.equals(path)) {
+      return null;
+    }
+    return FileUtil.toSystemIndependentName(path);
+  }
+
+  @Nullable
+  private String getConfiguredProfileName() {
+    final String selected = (String)myProfileCombobox.getSelectedItem();
+    if (Comparing.equal(myDefaultProfile, selected)) {
+      return null;
+    }
+    return selected;
+  }
+
+  public void apply() throws ConfigurationException {
+    mySettings.setProfile(getConfiguredProfileName());
+    mySettings.setProfilesIniPath(getConfiguredProfileIniPath());
+  }
+
+  public void reset() {
+    final File defaultFile = FirefoxUtil.getDefaultProfileIniPath();
+    myDefaultProfilesIniPath = defaultFile != null ? defaultFile.getAbsolutePath() : "";
+
+    final String path = mySettings.getProfilesIniPath();
+    myProfilesIniPathField.setText(path != null ? FileUtil.toSystemDependentName(path) : myDefaultProfilesIniPath);
+    updateProfilesList();
+    final String profileName = mySettings.getProfile();
+    myProfileCombobox.setSelectedItem(profileName != null ? profileName : myDefaultProfile);
+  }
+
+  private void updateProfilesList() {
+    final String profilesIniPath = myProfilesIniPathField.getText();
+    if (myLastProfilesIniPath != null && myLastProfilesIniPath.equals(profilesIniPath)) return;
+
+    myProfileCombobox.removeAllItems();
+    final List<FirefoxProfile> profiles = FirefoxUtil.computeProfiles(new File(profilesIniPath));
+    final FirefoxProfile defaultProfile = FirefoxUtil.getDefaultProfile(profiles);
+    myDefaultProfile = defaultProfile != null ? defaultProfile.getName() : null;
+    for (FirefoxProfile profile : profiles) {
+      myProfileCombobox.addItem(profile.getName());
+    }
+    if (!profiles.isEmpty()) {
+      myProfileCombobox.setSelectedIndex(0);
+    }
+    myLastProfilesIniPath = profilesIniPath;
+  }
+
+  public void disposeUIResources() {
+  }
+
+  @Nls
+  public String getDisplayName() {
+    return XmlBundle.message("display.name.firefox.settings");
+  }
+
+  public String getHelpTopic() {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java
new file mode 100644
index 0000000..5541052
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers.firefox;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.SystemProperties;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class FirefoxUtil {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.ide.browsers.firefox.FirefoxUtil");
+  @NonNls public static final String PROFILES_INI_FILE = "profiles.ini";
+
+  private FirefoxUtil() {
+  }
+
+  @Nullable
+  public static File getDefaultProfileIniPath() {
+    File[] roots = getProfilesDirs();
+    for (File profilesDir : roots) {
+      File profilesFile = new File(profilesDir, PROFILES_INI_FILE);
+      if (profilesFile.isFile()) {
+        return profilesFile;
+      }
+    }
+    return null;
+  }
+
+  @Nullable
+  public static File getFirefoxExtensionsDir(FirefoxSettings settings) {
+    File profilesFile = settings.getProfilesIniFile();
+    if (profilesFile != null && profilesFile.exists()) {
+      List<FirefoxProfile> profiles = computeProfiles(profilesFile);
+      FirefoxProfile profile = findProfileByNameOrDefault(settings.getProfile(), profiles);
+      if (profile != null) {
+        File profileDir = profile.getProfileDirectory(profilesFile);
+        if (profileDir.isDirectory()) {
+          return new File(profileDir, "extensions");
+        }
+      }
+    }
+    return null;
+  }
+
+  @Nullable
+  public static FirefoxProfile findProfileByNameOrDefault(@Nullable String name, List<FirefoxProfile> profiles) {
+    for (FirefoxProfile profile : profiles) {
+      if (profile.getName().equals(name)) {
+        return profile;
+      }
+    }
+    return getDefaultProfile(profiles);
+  }
+
+  @Nullable
+  public static FirefoxProfile getDefaultProfile(List<FirefoxProfile> profiles) {
+    if (profiles.isEmpty()) return null;
+
+    for (FirefoxProfile profile : profiles) {
+      if (profile.isDefault()) {
+        return profile;
+      }
+    }
+    return profiles.get(0);
+  }
+
+  @NotNull
+  public static List<FirefoxProfile> computeProfiles(File profilesFile) {
+    if (!profilesFile.isFile()) {
+      return Collections.emptyList();
+    }
+
+    try {
+      BufferedReader reader = new BufferedReader(new FileReader(profilesFile));
+      try {
+        final List<FirefoxProfile> profiles = new ArrayList<FirefoxProfile>();
+        boolean insideProfile = false;
+        String currentName = null;
+        String currentPath = null;
+        boolean isDefault = false;
+        boolean isRelative = false;
+        boolean eof = false;
+        while (!eof) {
+          @NonNls String line = reader.readLine();
+          if (line == null) {
+            eof = true;
+            line = "[]";
+          }
+          else {
+            line = line.trim();
+          }
+
+          if (line.startsWith("[") && line.endsWith("]")) {
+            if (!StringUtil.isEmpty(currentPath) && !StringUtil.isEmpty(currentName)) {
+              profiles.add(new FirefoxProfile(currentName, currentPath, isDefault, isRelative));
+            }
+            currentName = null;
+            currentPath = null;
+            isDefault = false;
+            isRelative = false;
+            insideProfile = StringUtil.startsWithIgnoreCase(line, "[Profile");
+            continue;
+          }
+
+          final int i = line.indexOf('=');
+          if (i != -1 && insideProfile) {
+            @NonNls String name = line.substring(0, i).trim();
+            @NonNls String value = line.substring(i + 1).trim();
+            if (name.equalsIgnoreCase("path")) {
+              currentPath = value;
+            }
+            else if (name.equalsIgnoreCase("name")) {
+              currentName = value;
+            }
+            else if (name.equalsIgnoreCase("default") && value.equals("1")) {
+              isDefault = true;
+            }
+            else if (name.equalsIgnoreCase("isrelative") && value.equals("1")) {
+              isRelative = true;
+            }
+          }
+        }
+        return profiles;
+      }
+      finally {
+        reader.close();
+      }
+    }
+    catch (IOException e) {
+      LOG.info(e);
+    }
+    return Collections.emptyList();
+  }
+
+  private static File[] getProfilesDirs() {
+    final String userHome = SystemProperties.getUserHome();
+    if (SystemInfo.isMac) {
+      return new File[] {
+        new File(userHome, "Library" + File.separator + "Mozilla" + File.separator + "Firefox"),
+        new File(userHome, "Library" + File.separator + "Application Support" + File.separator + "Firefox"),
+      };
+    }
+    if (SystemInfo.isUnix) {
+      return new File[] {new File(userHome, ".mozilla" + File.separator + "firefox")};
+    }
+
+    String localPath = "Mozilla" + File.separator + "Firefox";
+    return new File[] {
+      new File(System.getenv("APPDATA"), localPath),
+      new File(userHome, "AppData" + File.separator + "Roaming" + File.separator + localPath),
+      new File(userHome, "Application Data" + File.separator + localPath)
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java
new file mode 100644
index 0000000..fc50f4d
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers.impl;
+
+import com.intellij.execution.util.ExecUtil;
+import com.intellij.ide.BrowserUtil;
+import com.intellij.ide.browsers.BrowserSpecificSettings;
+import com.intellij.ide.browsers.BrowsersConfiguration;
+import com.intellij.ide.browsers.UrlOpener;
+import com.intellij.ide.browsers.WebBrowserSettings;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class DefaultUrlOpener extends UrlOpener {
+  private static final Logger LOG = Logger.getInstance(DefaultUrlOpener.class);
+
+  @Override
+  public boolean openUrl(BrowsersConfiguration.BrowserFamily family, @Nullable String url) {
+    return launchBrowser(family, url, ArrayUtil.EMPTY_STRING_ARRAY, Conditions.<String>alwaysTrue(), false);
+  }
+
+  public static boolean launchBrowser(final BrowsersConfiguration.BrowserFamily family,
+                                      @Nullable String url,
+                                      @NotNull String[] additionalParameters,
+                                      @NotNull Condition<String> browserSpecificParametersFilter,
+                                      final boolean forceOpenNewInstanceOnMac) {
+    final WebBrowserSettings settings = BrowsersConfiguration.getInstance().getBrowserSettings(family);
+    final String path = settings.getPath();
+    if (StringUtil.isEmpty(path)) {
+      Messages.showErrorDialog(XmlBundle.message("browser.path.not.specified", family.getName()), XmlBundle.message("browser.path.not.specified.title"));
+      return false;
+    }
+
+    try {
+      BrowserSpecificSettings specificSettings = settings.getBrowserSpecificSettings();
+      List<String> parameters = specificSettings == null
+                                ? (additionalParameters.length == 0 ? Collections.<String>emptyList() : new ArrayList<String>())
+                                : ContainerUtil.findAll(specificSettings.getAdditionalParameters(), browserSpecificParametersFilter);
+      Collections.addAll(parameters, additionalParameters);
+      doLaunchBrowser(path, url == null ? null : BrowserUtil.escapeUrl(url), forceOpenNewInstanceOnMac, parameters);
+      return true;
+    }
+    catch (IOException e) {
+      Messages.showErrorDialog(e.getMessage(), XmlBundle.message("browser.error"));
+      return false;
+    }
+  }
+
+  private static void doLaunchBrowser(String browserPath, @Nullable String url, boolean forceOpenNewInstanceOnMac, List<String> browserArgs)
+    throws IOException {
+    List<String> command = BrowserUtil.getOpenBrowserCommand(browserPath);
+    addArgs(command, browserArgs, url, forceOpenNewInstanceOnMac);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Launching browser: " + StringUtil.join(command, " "));
+    }
+    new ProcessBuilder(command).start();
+  }
+
+  private static void addArgs(List<String> command, List<String> browserArgs, @Nullable String url, boolean forceOpenNewInstanceOnMac) {
+    if (SystemInfo.isMac && ExecUtil.getOpenCommandPath().equals(command.get(0))) {
+      if (forceOpenNewInstanceOnMac) {
+        command.add("-n");
+      }
+      if (url != null) {
+        command.add(url);
+      }
+
+      if (!browserArgs.isEmpty()) {
+        if (BrowserUtil.isOpenCommandSupportArgs()) {
+          command.add("--args");
+          command.addAll(browserArgs);
+        }
+        else {
+          LOG.warn(
+            "'open' command doesn't allow to pass command line arguments so they will be ignored: " + StringUtil.join(browserArgs, " "));
+        }
+      }
+    }
+    else {
+      if (url != null) {
+        command.add(url);
+      }
+      command.addAll(browserArgs);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
new file mode 100644
index 0000000..4cfdc0c
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.browsers.impl;
+
+import com.intellij.ide.browsers.WebBrowserService;
+import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class WebBrowserServiceImpl extends WebBrowserService {
+  @Override
+  public boolean canOpenInBrowser(@NotNull PsiElement psiElement) {
+    final PsiFile psiFile = psiElement instanceof PsiFile ? (PsiFile)psiElement : psiElement.getContainingFile();
+    return psiFile != null && psiFile.getVirtualFile() != null &&
+           (HtmlUtil.isHtmlFile(psiFile) || getProvider(psiElement) != null);
+  }
+
+  @Override
+  @Nullable
+  public String getUrlToOpen(@NotNull PsiElement psiElement, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException {
+    final PsiFile psiFile = psiElement instanceof PsiFile ? (PsiFile)psiElement : psiElement.getContainingFile();
+    if (psiFile == null) {
+      return null;
+    }
+    VirtualFile virtualFile = psiFile.getVirtualFile();
+    if (virtualFile == null) {
+      return null;
+    }
+    if (virtualFile instanceof HttpVirtualFile) {
+      return virtualFile.getUrl();
+    }
+
+    if (!(preferLocalUrl && HtmlUtil.isHtmlFile(psiFile))) {
+      WebBrowserUrlProvider provider = getProvider(psiElement);
+      if (provider != null) {
+        try {
+          return provider.getUrl(psiElement, psiFile, virtualFile);
+        }
+        catch (WebBrowserUrlProvider.BrowserException e) {
+          if (!HtmlUtil.isHtmlFile(psiFile)) {
+            throw e;
+          }
+        }
+      }
+    }
+    return VfsUtil.toUri(virtualFile).toASCIIString();
+  }
+
+  @Nullable
+  public String getUrlToOpen(@NotNull PsiElement psiElement) {
+    try {
+      return getUrlToOpen(psiElement, false);
+    }
+    catch (WebBrowserUrlProvider.BrowserException e) {
+      return null;
+    }
+  }
+
+  @Nullable
+  public static WebBrowserUrlProvider getProvider(@Nullable PsiElement element) {
+    if (element == null) {
+      return null;
+    }
+
+    final List<WebBrowserUrlProvider> allProviders = Arrays.asList(WebBrowserUrlProvider.EP_NAME.getExtensions());
+    for (WebBrowserUrlProvider urlProvider : DumbService.getInstance(element.getProject()).filterByDumbAwareness(allProviders)) {
+      if (urlProvider.canHandleElement(element)) {
+        return urlProvider;
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/highlighter/DTDFileType.java b/xml/impl/src/com/intellij/ide/highlighter/DTDFileType.java
new file mode 100644
index 0000000..276837d
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/DTDFileType.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.highlighter;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.IdeBundle;
+import com.intellij.lang.dtd.DTDLanguage;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+public class DTDFileType extends LanguageFileType {
+  public static final DTDFileType INSTANCE = new DTDFileType();
+
+  public DTDFileType() {
+    super(DTDLanguage.INSTANCE);
+  }
+
+  @NotNull
+  public String getName() {
+    return "DTD";
+  }
+
+  @NotNull
+  public String getDescription() {
+    return IdeBundle.message("filetype.description.dtd");
+  }
+
+  @NotNull
+  public String getDefaultExtension() {
+    return "dtd";
+  }
+
+  public Icon getIcon() {
+    return AllIcons.FileTypes.Dtd;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/highlighter/DomSupportEnabled.java b/xml/impl/src/com/intellij/ide/highlighter/DomSupportEnabled.java
new file mode 100644
index 0000000..ff27af0
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/DomSupportEnabled.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.highlighter;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: zajac
+ * Date: 15.04.11
+ * Time: 14:57
+ * To change this template use File | Settings | File Templates.
+ */
+public interface DomSupportEnabled {
+}
diff --git a/xml/impl/src/com/intellij/ide/highlighter/HtmlFileHighlighter.java b/xml/impl/src/com/intellij/ide/highlighter/HtmlFileHighlighter.java
new file mode 100644
index 0000000..daff833
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/HtmlFileHighlighter.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.highlighter;
+
+import com.intellij.lexer.HtmlHighlightingLexer;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.editor.HighlighterColors;
+import com.intellij.openapi.editor.XmlHighlighterColors;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class HtmlFileHighlighter extends SyntaxHighlighterBase {
+  private static final Map<IElementType, TextAttributesKey> keys1;
+  private static final Map<IElementType, TextAttributesKey> keys2;
+
+  static {
+    keys1 = new HashMap<IElementType, TextAttributesKey>();
+    keys2 = new HashMap<IElementType, TextAttributesKey>();
+
+    keys1.put(XmlTokenType.XML_COMMENT_START, XmlHighlighterColors.HTML_COMMENT);
+    keys1.put(XmlTokenType.XML_COMMENT_END, XmlHighlighterColors.HTML_COMMENT);
+    keys1.put(XmlTokenType.XML_COMMENT_CHARACTERS, XmlHighlighterColors.HTML_COMMENT);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_COMMENT_END, XmlHighlighterColors.HTML_COMMENT);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_COMMENT_END_START, XmlHighlighterColors.HTML_COMMENT);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_COMMENT_START, XmlHighlighterColors.HTML_COMMENT);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_COMMENT_START_END, XmlHighlighterColors.HTML_COMMENT);
+
+    keys1.put(XmlTokenType.XML_START_TAG_START, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_END_TAG_START, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_TAG_END, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_EMPTY_ELEMENT_END, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_TAG_NAME, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.TAG_WHITE_SPACE, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_NAME, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_TAG_CHARACTERS, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_EQ, XmlHighlighterColors.HTML_TAG);
+
+    keys2.put(XmlTokenType.XML_TAG_NAME, XmlHighlighterColors.HTML_TAG_NAME);
+    keys2.put(XmlTokenType.XML_NAME, XmlHighlighterColors.HTML_ATTRIBUTE_NAME);
+    keys2.put(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN, XmlHighlighterColors.HTML_ATTRIBUTE_VALUE);
+    keys2.put(XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER, XmlHighlighterColors.HTML_ATTRIBUTE_VALUE);
+    keys2.put(XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER, XmlHighlighterColors.HTML_ATTRIBUTE_VALUE);
+    keys2.put(XmlTokenType.XML_EQ, XmlHighlighterColors.HTML_ATTRIBUTE_NAME);
+
+    keys1.put(XmlTokenType.XML_PI_START, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_PI_END, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_PI_TARGET, XmlHighlighterColors.HTML_TAG);
+    keys2.put(XmlTokenType.XML_PI_TARGET, XmlHighlighterColors.HTML_TAG_NAME);
+    
+    keys1.put(XmlTokenType.XML_DOCTYPE_START, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_DOCTYPE_END, XmlHighlighterColors.HTML_TAG);
+    keys1.put(XmlTokenType.XML_DOCTYPE_PUBLIC, XmlHighlighterColors.HTML_TAG);
+
+    keys2.put(XmlTokenType.XML_CHAR_ENTITY_REF, XmlHighlighterColors.HTML_ENTITY_REFERENCE);
+    keys2.put(XmlTokenType.XML_ENTITY_REF_TOKEN, XmlHighlighterColors.HTML_ENTITY_REFERENCE);
+
+    keys1.put(XmlTokenType.XML_BAD_CHARACTER, HighlighterColors.BAD_CHARACTER);
+  }
+
+  @NotNull
+  public Lexer getHighlightingLexer() {
+    return new HtmlHighlightingLexer();
+  }
+
+  @NotNull
+  public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
+    return pack(XmlHighlighterColors.HTML_CODE, pack(keys1.get(tokenType), keys2.get(tokenType)));
+  }
+
+  public static final void registerEmbeddedTokenAttributes(Map<IElementType, TextAttributesKey> _keys1,
+                                                           Map<IElementType, TextAttributesKey> _keys2) {
+    if (_keys1 != null) {
+      for (Iterator<IElementType> iterator = _keys1.keySet().iterator(); iterator.hasNext();) {
+        IElementType iElementType = iterator.next();
+        keys1.put(iElementType,_keys1.get(iElementType));
+      }
+    }
+
+    if (_keys2 != null) {
+      for (Iterator<IElementType> iterator = _keys2.keySet().iterator(); iterator.hasNext();) {
+        IElementType iElementType = iterator.next();
+        keys2.put(iElementType,_keys2.get(iElementType));
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/highlighter/HtmlFileType.java b/xml/impl/src/com/intellij/ide/highlighter/HtmlFileType.java
new file mode 100644
index 0000000..f0638e0
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/HtmlFileType.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.highlighter;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.IdeBundle;
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+
+public class HtmlFileType extends XmlLikeFileType {
+  @NonNls public static final String DOT_DEFAULT_EXTENSION = ".html";
+
+  public final static HtmlFileType INSTANCE = new HtmlFileType();
+
+  private HtmlFileType() {
+    super(HTMLLanguage.INSTANCE);
+  }
+
+  HtmlFileType(Language language) {
+    super(language);
+  }
+
+  @NotNull
+  public String getName() {
+    return "HTML";
+  }
+
+  @NotNull
+  public String getDescription() {
+    return IdeBundle.message("filetype.description.html");
+  }
+
+  @NotNull
+  public String getDefaultExtension() {
+    return "html";
+  }
+
+  public Icon getIcon() {
+    return AllIcons.FileTypes.Html;
+  }
+
+  public String getCharset(@NotNull final VirtualFile file, final byte[] content) {
+    String charset = XmlUtil.extractXmlEncodingFromProlog(content);
+    if (charset != null) return charset;
+    @NonNls String strContent;
+    try {
+      strContent = new String(content, "ISO-8859-1");
+    }
+    catch (UnsupportedEncodingException e) {
+      return null;
+    }
+    Charset c = HtmlUtil.detectCharsetFromMetaHttpEquiv(strContent);
+    return c == null ? null : c.name();
+  }
+
+  public Charset extractCharsetFromFileContent(@Nullable final Project project, @Nullable final VirtualFile file, @NotNull final String content) {
+    String name = XmlUtil.extractXmlEncodingFromProlog(content);
+    Charset charset = CharsetToolkit.forName(name);
+
+    if (charset != null) {
+      return charset;
+    }
+    return HtmlUtil.detectCharsetFromMetaHttpEquiv(content);
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/highlighter/HtmlHighlighterFactory.java b/xml/impl/src/com/intellij/ide/highlighter/HtmlHighlighterFactory.java
new file mode 100644
index 0000000..67a3616
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/HtmlHighlighterFactory.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.ide.highlighter;
+
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+
+public class HtmlHighlighterFactory {
+  public static EditorHighlighter createHTMLHighlighter(EditorColorsScheme settings){
+    SyntaxHighlighter highlighter = new HtmlFileHighlighter();
+    return HighlighterFactory.createHighlighter(highlighter, settings);
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/highlighter/XHtmlFileType.java b/xml/impl/src/com/intellij/ide/highlighter/XHtmlFileType.java
new file mode 100644
index 0000000..9d282e2
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/XHtmlFileType.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.highlighter;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.IdeBundle;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+public class XHtmlFileType extends HtmlFileType {
+  public static final XHtmlFileType INSTANCE = new XHtmlFileType();
+
+  private XHtmlFileType() {
+    super(XHTMLLanguage.INSTANCE);
+  }
+
+  @NotNull
+  public String getName() {
+    return "XHTML";
+  }
+
+  @NotNull
+  public String getDescription() {
+    return IdeBundle.message("filetype.description.xhtml");
+  }
+
+  @NotNull
+  public String getDefaultExtension() {
+    return "xhtml";
+  }
+
+  public Icon getIcon() {
+    return AllIcons.FileTypes.Xhtml;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/highlighter/XmlFileHighlighter.java b/xml/impl/src/com/intellij/ide/highlighter/XmlFileHighlighter.java
new file mode 100644
index 0000000..4b68ad9
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/XmlFileHighlighter.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.highlighter;
+
+import com.intellij.lexer.DtdLexer;
+import com.intellij.lexer.Lexer;
+import com.intellij.lexer.XHtmlHighlightingLexer;
+import com.intellij.lexer.XmlHighlightingLexer;
+import com.intellij.openapi.editor.HighlighterColors;
+import com.intellij.openapi.editor.XmlHighlighterColors;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class XmlFileHighlighter extends SyntaxHighlighterBase {
+  private static final Map<IElementType, TextAttributesKey> keys1;
+  private static final Map<IElementType, TextAttributesKey> keys2;
+
+  static {
+    keys1 = new HashMap<IElementType, TextAttributesKey>();
+    keys2 = new HashMap<IElementType, TextAttributesKey>();
+
+    keys1.put(XmlTokenType.XML_DATA_CHARACTERS, XmlHighlighterColors.XML_TAG_DATA);
+
+    keys1.put(XmlTokenType.XML_COMMENT_START, XmlHighlighterColors.XML_COMMENT);
+    keys1.put(XmlTokenType.XML_COMMENT_END, XmlHighlighterColors.XML_COMMENT);
+    keys1.put(XmlTokenType.XML_COMMENT_CHARACTERS, XmlHighlighterColors.XML_COMMENT);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_COMMENT_END, XmlHighlighterColors.XML_COMMENT);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_COMMENT_END_START, XmlHighlighterColors.XML_COMMENT);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_COMMENT_START, XmlHighlighterColors.XML_COMMENT);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_COMMENT_START_END, XmlHighlighterColors.XML_COMMENT);
+
+    keys1.put(XmlTokenType.XML_START_TAG_START, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_END_TAG_START, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_TAG_END, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_EMPTY_ELEMENT_END, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_TAG_NAME, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.TAG_WHITE_SPACE, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_NAME, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_IGNORE, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_CONDITIONAL_INCLUDE, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_EQ, XmlHighlighterColors.XML_TAG);
+    keys1.put(XmlTokenType.XML_TAG_CHARACTERS, XmlHighlighterColors.XML_TAG);
+
+    keys2.put(XmlTokenType.XML_TAG_NAME, XmlHighlighterColors.XML_TAG_NAME);
+    keys2.put(XmlTokenType.XML_CONDITIONAL_INCLUDE, XmlHighlighterColors.XML_TAG_NAME);
+    keys2.put(XmlTokenType.XML_CONDITIONAL_INCLUDE, XmlHighlighterColors.XML_TAG_NAME);
+    keys2.put(XmlTokenType.XML_NAME, XmlHighlighterColors.XML_ATTRIBUTE_NAME);
+    keys2.put(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN, XmlHighlighterColors.XML_ATTRIBUTE_VALUE);
+    keys2.put(XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER, XmlHighlighterColors.XML_ATTRIBUTE_VALUE);
+    keys2.put(XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER, XmlHighlighterColors.XML_ATTRIBUTE_VALUE);
+    keys2.put(XmlTokenType.XML_EQ, XmlHighlighterColors.XML_ATTRIBUTE_NAME);
+    keys2.put(XmlTokenType.XML_TAG_CHARACTERS, XmlHighlighterColors.XML_ATTRIBUTE_VALUE);
+
+    keys1.put(XmlTokenType.XML_BAD_CHARACTER, HighlighterColors.BAD_CHARACTER);
+
+    keys1.put(XmlTokenType.XML_DECL_START, XmlHighlighterColors.XML_TAG);
+    keys2.put(XmlTokenType.XML_DECL_START, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_CONDITIONAL_SECTION_START, XmlHighlighterColors.XML_PROLOGUE);
+    keys2.put(XmlTokenType.XML_CONDITIONAL_SECTION_START, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_CONDITIONAL_SECTION_END, XmlHighlighterColors.XML_PROLOGUE);
+    keys2.put(XmlTokenType.XML_CONDITIONAL_SECTION_END, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_DECL_END, XmlHighlighterColors.XML_PROLOGUE);
+    keys2.put(XmlTokenType.XML_DECL_END, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_PI_START, XmlHighlighterColors.XML_PROLOGUE);
+    keys1.put(XmlTokenType.XML_PI_END, XmlHighlighterColors.XML_PROLOGUE); 
+    keys1.put(XmlTokenType.XML_DOCTYPE_END, XmlHighlighterColors.XML_PROLOGUE);
+    keys2.put(XmlTokenType.XML_DOCTYPE_END, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_DOCTYPE_START, XmlHighlighterColors.XML_TAG);
+    keys2.put(XmlTokenType.XML_DOCTYPE_START, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_DOCTYPE_SYSTEM, XmlHighlighterColors.XML_TAG);
+    keys2.put(XmlTokenType.XML_DOCTYPE_SYSTEM, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_DOCTYPE_PUBLIC, XmlHighlighterColors.XML_TAG);
+    keys2.put(XmlTokenType.XML_DOCTYPE_PUBLIC, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_DOCTYPE_PUBLIC, XmlHighlighterColors.XML_TAG);
+    keys2.put(XmlTokenType.XML_DOCTYPE_PUBLIC, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_ATTLIST_DECL_START, XmlHighlighterColors.XML_TAG);
+    keys2.put(XmlTokenType.XML_ATTLIST_DECL_START, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_ELEMENT_DECL_START, XmlHighlighterColors.XML_TAG);
+    keys2.put(XmlTokenType.XML_ELEMENT_DECL_START, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys1.put(XmlTokenType.XML_ENTITY_DECL_START, XmlHighlighterColors.XML_TAG);
+    keys2.put(XmlTokenType.XML_ENTITY_DECL_START, XmlHighlighterColors.XML_TAG_NAME);
+
+    keys2.put(XmlTokenType.XML_CHAR_ENTITY_REF, XmlHighlighterColors.XML_ENTITY_REFERENCE);
+    keys2.put(XmlTokenType.XML_ENTITY_REF_TOKEN, XmlHighlighterColors.XML_ENTITY_REFERENCE);
+  }
+
+  private boolean myIsDtd;
+  private boolean myIsXHtml;
+
+  public XmlFileHighlighter() {
+    this(false);
+  }
+
+  public XmlFileHighlighter(boolean dtd) {
+    myIsDtd = dtd;
+  }
+
+  public XmlFileHighlighter(boolean dtd, boolean xhtml) {
+    myIsDtd = dtd;
+    myIsXHtml = xhtml;
+  }
+
+  @NotNull
+  public Lexer getHighlightingLexer() {
+    if (myIsDtd) {
+      return new DtdLexer(true);
+    } else if (myIsXHtml) {
+      return new XHtmlHighlightingLexer();
+    } else {
+      return new XmlHighlightingLexer();
+    }
+  }
+
+  @NotNull
+  public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
+    return pack(keys1.get(tokenType), keys2.get(tokenType));
+  }
+
+  public static final void registerEmbeddedTokenAttributes(Map<IElementType, TextAttributesKey> _keys1,
+                                                           Map<IElementType, TextAttributesKey> _keys2) {
+    if (_keys1!=null) {
+      for (Iterator<IElementType> iterator = _keys1.keySet().iterator(); iterator.hasNext();) {
+        IElementType iElementType = iterator.next();
+        keys1.put(iElementType,_keys1.get(iElementType));
+      }
+    }
+
+    if (_keys2!=null) {
+      for (Iterator<IElementType> iterator = _keys2.keySet().iterator(); iterator.hasNext();) {
+        IElementType iElementType = iterator.next();
+        keys2.put(iElementType,_keys2.get(iElementType));
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/highlighter/XmlFileType.java b/xml/impl/src/com/intellij/ide/highlighter/XmlFileType.java
new file mode 100644
index 0000000..7c0447d
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/XmlFileType.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.highlighter;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.IdeBundle;
+import com.intellij.lang.xml.XMLLanguage;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+public class XmlFileType extends XmlLikeFileType implements DomSupportEnabled {
+  public static final XmlFileType INSTANCE = new XmlFileType();
+  @NonNls public static final String DEFAULT_EXTENSION = "xml";
+  @NonNls public static final String DOT_DEFAULT_EXTENSION = "."+DEFAULT_EXTENSION;
+
+  private XmlFileType() {
+    super(XMLLanguage.INSTANCE);
+  }
+
+  @NotNull
+  public String getName() {
+    return "XML";
+  }
+
+  @NotNull
+  public String getDescription() {
+    return IdeBundle.message("filetype.description.xml");
+  }
+
+  @NotNull
+  public String getDefaultExtension() {
+    return DEFAULT_EXTENSION;
+  }
+
+  public Icon getIcon() {
+    return AllIcons.FileTypes.Xml;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/highlighter/XmlHighlighterFactory.java b/xml/impl/src/com/intellij/ide/highlighter/XmlHighlighterFactory.java
new file mode 100644
index 0000000..5e9faf4
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/XmlHighlighterFactory.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.ide.highlighter;
+
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+
+public class XmlHighlighterFactory {
+  public static EditorHighlighter createXMLHighlighter(EditorColorsScheme settings){
+    return HighlighterFactory.createHighlighter(new XmlFileHighlighter(), settings);
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/highlighter/XmlLikeFileType.java b/xml/impl/src/com/intellij/ide/highlighter/XmlLikeFileType.java
new file mode 100644
index 0000000..5ac4888
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/highlighter/XmlLikeFileType.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.highlighter;
+
+import com.intellij.lang.Language;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.nio.charset.Charset;
+
+public abstract class XmlLikeFileType extends LanguageFileType {
+  public XmlLikeFileType(Language language) {
+    super(language);
+  }
+  public String getCharset(@NotNull VirtualFile file, final byte[] content) {
+    String charset = XmlUtil.extractXmlEncodingFromProlog(content);
+    return charset == null ? CharsetToolkit.UTF8 : charset;
+  }
+
+  public Charset extractCharsetFromFileContent(final Project project, @Nullable final VirtualFile file, @NotNull final String content) {
+    String name = XmlUtil.extractXmlEncodingFromProlog(content);
+    Charset charset = CharsetToolkit.forName(name);
+    return charset == null ? CharsetToolkit.UTF8_CHARSET : charset;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/structureView/impl/xml/AbstractXmlTagTreeElement.java b/xml/impl/src/com/intellij/ide/structureView/impl/xml/AbstractXmlTagTreeElement.java
new file mode 100644
index 0000000..fde4906
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/structureView/impl/xml/AbstractXmlTagTreeElement.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.structureView.impl.xml;
+
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.xml.XmlStructureViewElementProvider;
+import com.intellij.ide.structureView.impl.common.PsiTreeElementBase;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+
+import java.util.Collection;
+
+public abstract class AbstractXmlTagTreeElement<T extends XmlElement> extends PsiTreeElementBase<T> {
+  protected AbstractXmlTagTreeElement(final T psiElement) {
+    super(psiElement);
+  }
+
+  protected static Collection<StructureViewTreeElement> getStructureViewTreeElements(XmlTag[] subTags) {
+    final XmlStructureViewElementProvider[] providers =
+      (XmlStructureViewElementProvider[])Extensions.getExtensions(XmlStructureViewElementProvider.EXTENSION_POINT_NAME);
+
+    return ContainerUtil.map2List(subTags, new Function<XmlTag, StructureViewTreeElement>() {
+      public StructureViewTreeElement fun(final XmlTag xmlTag) {
+        for (final XmlStructureViewElementProvider provider : providers) {
+          final StructureViewTreeElement element = provider.createCustomXmlTagTreeElement(xmlTag);
+          if (element != null) {
+            return element;
+          }
+        }
+        return new XmlTagTreeElement(xmlTag);
+      }
+    });
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/structureView/impl/xml/DtdFileTreeElement.java b/xml/impl/src/com/intellij/ide/structureView/impl/xml/DtdFileTreeElement.java
new file mode 100644
index 0000000..9947657
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/structureView/impl/xml/DtdFileTreeElement.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.structureView.impl.xml;
+
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.impl.common.PsiTreeElementBase;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.xml.*;
+import com.intellij.util.PlatformIcons;
+import com.intellij.xml.impl.dtd.XmlElementDescriptorImpl;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.*;
+
+public class DtdFileTreeElement extends PsiTreeElementBase<XmlFile> {
+  public DtdFileTreeElement(XmlFile file) {
+    super(file);
+  }
+
+  @NotNull
+  public Collection<StructureViewTreeElement> getChildrenBase() {
+    return collectElements(getElement().getDocument());
+  }
+
+  static List<StructureViewTreeElement> collectElements(final XmlElement element) {
+    final List<StructureViewTreeElement> elements = new ArrayList<StructureViewTreeElement>();
+
+    XmlUtil.processXmlElements(element, new PsiElementProcessor() {
+      public boolean execute(@NotNull final PsiElement element) {
+        if (element instanceof XmlElementDecl ||
+            element instanceof XmlEntityDecl) {
+          elements.add(new DtdTreeElement((PsiNamedElement)element));
+        }
+        return true;
+      }
+    }, false);
+    return elements;
+  }
+
+  public String getPresentableText() {
+    return getElement().getName();
+  }
+
+  private static class DtdTreeElement extends PsiTreeElementBase<PsiNamedElement> {
+    @NonNls private static final String IMPLIED = "implied";
+    @NonNls private static final String REQUIRED = "required";
+    @NonNls private static final String FIXED = "fixed";
+    @NonNls private static final String ID = "id";
+    @NonNls private static final String IDREF = "idref";
+    @NonNls private static final String ENUM = "enum";
+
+    public DtdTreeElement(final PsiNamedElement element) {
+      super(element);
+    }
+
+    @NotNull
+    public Collection<StructureViewTreeElement> getChildrenBase() {
+      return Collections.emptyList();
+    }
+
+    public String getPresentableText() {
+      final PsiNamedElement namedElement = getElement();
+      return namedElement != null ? namedElement.getName():"";
+    }
+
+    public Icon getIcon(final boolean open) {
+      return PlatformIcons.XML_TAG_ICON;
+    }
+
+    public String getLocationString() {
+      final XmlElement owner = (XmlElement)getElement();
+
+      final XmlAttlistDecl[] attLists= owner instanceof XmlElementDecl ? XmlElementDescriptorImpl.getCachedAttDecls(owner): XmlAttlistDecl.EMPTY_ARRAY;
+
+      if (attLists.length > 0) {
+        Map<String,XmlAttributeDecl> attrMap = null;
+
+        final String name = getElement().getName();
+        for(XmlAttlistDecl a:attLists) {
+          final String aname = a.getName();
+          if (!Comparing.equal(aname, name)) continue;
+          if (attrMap == null) attrMap = new LinkedHashMap<String, XmlAttributeDecl>();
+
+          for(XmlAttributeDecl d : a.getAttributeDecls()) {
+            attrMap.put(d.getName(), d);
+          }
+        }
+
+        StringBuilder b = null;
+        if (attrMap != null) {
+          for(Map.Entry<String,XmlAttributeDecl> e:attrMap.entrySet()) {
+            if (b == null) b = new StringBuilder();
+            else b.append(", ");
+            b.append(e.getKey());
+            final XmlAttributeDecl attributeDecl = e.getValue();
+            String type = null;
+
+            if (attributeDecl.isIdAttribute()) {
+              type = ID;
+            } else if (attributeDecl.isIdRefAttribute()) {
+              type = IDREF;
+            } else if (attributeDecl.isEnumerated()) {
+              type = ENUM;
+            }
+
+            if (attributeDecl.isAttributeFixed()) {
+              if (type == null) type = FIXED;
+              else type += " " + FIXED;
+            } else if (attributeDecl.isAttributeRequired()) {
+              if (type == null) type = REQUIRED;
+              else type += " " + REQUIRED;
+            } else if (attributeDecl.isAttributeImplied()) {
+              if (type == null) type = IMPLIED;
+              else type += " " + IMPLIED;
+            }
+
+            if (type != null) b.append(':').append(type);
+            final XmlAttributeValue value = attributeDecl.getDefaultValue();
+
+            if (value != null) b.append("=").append(value);
+          }
+        }
+
+        if (b != null) return b.toString();
+     }
+     return super.getLocationString();
+    }
+
+    public String toString() {
+      final String s = getLocationString();
+      final String name = getElement().getName();
+      if (s == null || s.length() == 0) return name;
+      return name + " (" + s + ")";
+    }
+  }
+
+
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlFileTreeElement.java b/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlFileTreeElement.java
new file mode 100644
index 0000000..e1cd6a2
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlFileTreeElement.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.structureView.impl.xml;
+
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.*;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class XmlFileTreeElement extends AbstractXmlTagTreeElement<XmlFile> {
+  public XmlFileTreeElement(XmlFile file) {
+    super(file);
+  }
+
+  @NotNull
+  public Collection<StructureViewTreeElement> getChildrenBase() {
+    final XmlDocument document = getElement().getDocument();
+    List<XmlTag> rootTags = new ArrayList<XmlTag>();
+    if (document != null) {
+      for (PsiElement element : document.getChildren())
+        if (element instanceof XmlTag) rootTags.add((XmlTag)element);
+    }
+
+    Collection<StructureViewTreeElement> structureViewTreeElements =
+      getStructureViewTreeElements(rootTags.toArray(new XmlTag[rootTags.size()]));
+
+    Collection<StructureViewTreeElement> dtdStructureViewTreeElements = null;
+    final XmlProlog prolog = document != null ? document.getProlog():null;
+    if (prolog != null) {
+      final XmlDoctype doctype = prolog.getDoctype();
+
+      if (doctype != null) {
+        final XmlMarkupDecl xmlMarkupDecl = doctype.getMarkupDecl();
+        if (xmlMarkupDecl != null) {
+          dtdStructureViewTreeElements = DtdFileTreeElement.collectElements(xmlMarkupDecl);
+        }
+      }
+    }
+
+    if (dtdStructureViewTreeElements != null) {
+      final ArrayList<StructureViewTreeElement> result = new ArrayList<StructureViewTreeElement>(
+        dtdStructureViewTreeElements.size() + structureViewTreeElements.size()
+      );
+
+      result.addAll(dtdStructureViewTreeElements);
+      result.addAll(structureViewTreeElements);
+      structureViewTreeElements = result;
+    }
+    return structureViewTreeElements;
+  }
+
+  public String getPresentableText() {
+    return getElement().getName();
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlStructureViewTreeModel.java b/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlStructureViewTreeModel.java
new file mode 100644
index 0000000..71212d1
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlStructureViewTreeModel.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.structureView.impl.xml;
+
+import com.intellij.ide.structureView.StructureViewExtension;
+import com.intellij.ide.structureView.StructureViewFactoryEx;
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.TextEditorBasedStructureViewModel;
+import com.intellij.ide.util.treeView.smartTree.Sorter;
+import com.intellij.lang.dtd.DTDLanguage;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.*;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class XmlStructureViewTreeModel extends TextEditorBasedStructureViewModel{
+  private final XmlFile myFile;
+  private static final Class[] myClasses = new Class[]{XmlTag.class, XmlFile.class, XmlEntityDecl.class, XmlElementDecl.class, XmlAttlistDecl.class, XmlConditionalSection.class};
+  private static final Sorter[] mySorters = {Sorter.ALPHA_SORTER};
+
+  public XmlStructureViewTreeModel(XmlFile file) {
+    super(file);
+    myFile = file;
+  }
+
+  @NotNull
+  public StructureViewTreeElement getRoot() {
+    if (myFile.getLanguage() == DTDLanguage.INSTANCE) return new DtdFileTreeElement(myFile);
+    return new XmlFileTreeElement(myFile);
+  }
+
+  public boolean shouldEnterElement(final Object element) {
+    return element instanceof XmlTag && ((XmlTag)element).getSubTags().length > 0;
+  }
+
+  protected PsiFile getPsiFile() {
+    return myFile;
+  }
+
+  @NotNull
+  protected Class[] getSuitableClasses() {
+    return myClasses;
+  }
+
+  public Object getCurrentEditorElement() {
+    final Object editorElement = super.getCurrentEditorElement();
+    if (editorElement instanceof XmlTag) {
+      final Collection<StructureViewExtension> structureViewExtensions =
+          StructureViewFactoryEx.getInstanceEx(myFile.getProject()).getAllExtensions(XmlTag.class);
+      for(StructureViewExtension extension:structureViewExtensions) {
+        final Object element = extension.getCurrentEditorElement(getEditor(), (PsiElement)editorElement);
+        if (element != null) return element;
+      }
+    }
+    return editorElement;
+  }
+
+  @NotNull
+  public Sorter[] getSorters() {
+    return mySorters;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlTagTreeElement.java b/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlTagTreeElement.java
new file mode 100644
index 0000000..86a6350
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlTagTreeElement.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.structureView.impl.xml;
+
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+public class XmlTagTreeElement extends AbstractXmlTagTreeElement<XmlTag>{
+  @NonNls private static final String ID_ATTR_NAME = "id";
+  @NonNls private static final String NAME_ATTR_NAME = "name";
+
+  public XmlTagTreeElement(XmlTag tag) {
+    super(tag);
+  }
+
+ @NotNull
+ public Collection<StructureViewTreeElement> getChildrenBase() {
+    return getStructureViewTreeElements(getElement().getSubTags());
+  }
+
+  public String getPresentableText() {
+    final XmlTag element = getElement();
+    String id = element.getAttributeValue(ID_ATTR_NAME);
+    if (id == null) id = element.getAttributeValue(NAME_ATTR_NAME);
+    id = toCanonicalForm(id);
+
+    if (id != null) return id + ":" + element.getLocalName();
+    return element.getName();
+  }
+
+  public String getLocationString() {
+    final StringBuffer buffer = new StringBuffer();
+    final XmlTag element = getElement();
+    final XmlAttribute[] attributes = element.getAttributes();
+
+    String id = element.getAttributeValue(ID_ATTR_NAME);
+    String usedAttrName = null;
+
+    if (id == null) {
+      id = element.getAttributeValue(NAME_ATTR_NAME);
+      if (id != null) usedAttrName = NAME_ATTR_NAME;
+    }
+    else {
+      usedAttrName = ID_ATTR_NAME;
+    }
+
+    id = toCanonicalForm(id);
+
+    for (XmlAttribute attribute : attributes) {
+      if (buffer.length() != 0) {
+        buffer.append(" ");
+      }
+
+      final String name = attribute.getName();
+      if (usedAttrName != null &&
+          id != null &&
+          usedAttrName.equals(name)
+        ) {
+        continue; // we output this name in name
+      }
+
+      buffer.append(name);
+      buffer.append("=");
+      buffer.append("\"");
+      buffer.append(attribute.getValue());
+      buffer.append("\"");
+    }
+    return buffer.toString();
+  }
+
+  @Nullable
+  protected static String toCanonicalForm(@Nullable String id) {
+    if (id != null) {
+      id = id.trim();
+      if (id.length() == 0) id = null;
+    }
+    return id;
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/util/treeView/XmlDoctypeNodeDescriptor.java b/xml/impl/src/com/intellij/ide/util/treeView/XmlDoctypeNodeDescriptor.java
new file mode 100644
index 0000000..ea771e3
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/util/treeView/XmlDoctypeNodeDescriptor.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.util.treeView;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+
+/**
+ * @author Mike
+ */
+public class XmlDoctypeNodeDescriptor  extends SmartElementDescriptor {
+  public XmlDoctypeNodeDescriptor(Project project, NodeDescriptor parentDescriptor, PsiElement element) {
+    super(project, parentDescriptor, element);
+    //noinspection HardCodedStringLiteral
+    myName = "DOCTYPE";
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/DefaultHtmlDoctypeInitialConfigurator.java b/xml/impl/src/com/intellij/javaee/DefaultHtmlDoctypeInitialConfigurator.java
new file mode 100644
index 0000000..772dd19
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/DefaultHtmlDoctypeInitialConfigurator.java
@@ -0,0 +1,20 @@
+package com.intellij.javaee;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.xml.Html5SchemaProvider;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class DefaultHtmlDoctypeInitialConfigurator {
+
+  public DefaultHtmlDoctypeInitialConfigurator(ProjectManager projectManager,
+                                               PropertiesComponent propertiesComponent) {
+    if (!propertiesComponent.getBoolean("DefaultHtmlDoctype.MigrateToHtml5", false)) {
+      propertiesComponent.setValue("DefaultHtmlDoctype.MigrateToHtml5", Boolean.TRUE.toString());
+      ExternalResourceManagerEx.getInstanceEx()
+        .setDefaultHtmlDoctype(Html5SchemaProvider.HTML5_SCHEMA_LOCATION, projectManager.getDefaultProject());
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/EditLocationDialog.java b/xml/impl/src/com/intellij/javaee/EditLocationDialog.java
new file mode 100644
index 0000000..443e0d6
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/EditLocationDialog.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.FixedSizeButton;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.xml.XmlBundle;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+public class EditLocationDialog extends DialogWrapper {
+
+  private JTextField myTfUrl;
+  private JTextField myTfPath;
+  private FixedSizeButton myBtnBrowseLocalPath;
+  private final Project myProject;
+  private final boolean myShowPath;
+
+  private final String myTitle;
+  private final String myName;
+  private final String myLocation;
+  private boolean myTfShared = true;
+
+  public EditLocationDialog(Project project, boolean showPath) {
+    super(project, true);
+    myProject = project;
+    myShowPath = showPath;
+    myTitle = XmlBundle.message("dialog.title.external.resource");
+    myName = XmlBundle.message("label.edit.external.resource.uri");
+    myLocation = XmlBundle.message("label.edit.external.resource.path");
+    init();
+  }
+
+  public EditLocationDialog(Project project, boolean showPath, String title, String name, String location) {
+    super(project, true);
+    myProject = project;
+    myShowPath = showPath;
+    myTitle = title;
+    myName = name;
+    myLocation = location;
+    init();
+  }
+
+  protected JComponent createCenterPanel() {
+    JPanel panel = new JPanel(new GridBagLayout());
+
+    panel.add(
+        new JLabel(myName),
+        new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 3, 5), 0, 0)
+    );
+    panel.add(
+        myTfUrl,
+        new GridBagConstraints(0, 1, 2, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 5, 5), 0, 0)
+    );
+
+    myTfUrl.setPreferredSize(new Dimension(350, myTfUrl.getPreferredSize().height));
+
+  if (myShowPath) {
+      panel.add(
+          new JLabel(myLocation),
+          new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 3, 5), 0, 0)
+      );
+      panel.add(
+          myTfPath,
+          new GridBagConstraints(0, 3, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 10, 0), 0, 0)
+      );
+      panel.add(
+          myBtnBrowseLocalPath,
+          new GridBagConstraints(1, 3, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 10, 5), 0, 0)
+      );
+
+      //
+    TextFieldWithBrowseButton.MyDoClickAction.addTo(myBtnBrowseLocalPath, myTfPath);
+    myBtnBrowseLocalPath.addActionListener(
+          new ActionListener() {
+            public void actionPerformed(ActionEvent ignored) {
+              FileChooserDescriptor descriptor = getChooserDescriptor();
+              VirtualFile file = FileChooser.chooseFile(descriptor, myProject, null);
+              if (file != null) {
+                myTfPath.setText(file.getPath().replace('/', File.separatorChar));
+              }
+            }
+          }
+      );
+    }
+
+    //
+
+    return panel;
+  }
+
+  public JComponent getPreferredFocusedComponent() {
+    return myTfUrl;
+  }
+
+  public NameLocationPair getPair() {
+    String path = myTfPath.getText().trim();
+    String url = myTfUrl.getText().trim();
+    return new NameLocationPair(url, path, myTfShared);
+  }
+
+  protected FileChooserDescriptor getChooserDescriptor(){
+    return new FileChooserDescriptor(true, false, false, false, true, false);
+  }
+
+  protected void init() {
+    setTitle(myTitle);
+    myTfUrl = new JTextField();
+    myTfPath = new JTextField();
+    myBtnBrowseLocalPath = new FixedSizeButton(myTfPath);
+    super.init();
+  }
+
+  /**
+   * Initializes editor with the passed data.
+   */
+  public void init(NameLocationPair origin) {
+    myTfUrl.setText(origin.myName);
+    myTfPath.setText(origin.myLocation);
+    myTfShared = origin.myShared;
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourceConfigurable.java b/xml/impl/src/com/intellij/javaee/ExternalResourceConfigurable.java
new file mode 100644
index 0000000..086f8fe
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/ExternalResourceConfigurable.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.options.BaseConfigurable;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.JarFileSystem;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.AddEditRemovePanel;
+import com.intellij.ui.table.JBTable;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumn;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ExternalResourceConfigurable extends BaseConfigurable
+  implements Configurable.NoScroll {
+  private JPanel myPanel;
+  private List<NameLocationPair> myPairs;
+  private List<String> myIgnoredUrls;
+  private String myDefaultHtmlDoctype;
+  private AddEditRemovePanel<NameLocationPair> myExtPanel;
+  private AddEditRemovePanel<String> myIgnorePanel;
+  private HtmlLanguageLevelForm myHtmlLanguageLevelForm;
+  @Nullable private final Project myProject;
+  private final List<NameLocationPair> myNewPairs;
+
+  @SuppressWarnings("UnusedDeclaration")
+  public ExternalResourceConfigurable(@Nullable Project project) {
+    this(project, Collections.<NameLocationPair>emptyList());
+  }
+
+  public ExternalResourceConfigurable(@Nullable Project project, List<NameLocationPair> newResources) {
+    myProject = project;
+    myNewPairs = newResources;
+  }
+
+  public String getDisplayName() {
+    return XmlBundle.message("display.name.edit.external.resource");
+  }
+
+  public JComponent createComponent() {
+    myPanel = new JPanel(new GridBagLayout()) {
+      public Dimension getPreferredSize() {
+        return new Dimension(-1, 400);
+      }
+    };
+
+    myExtPanel = new AddEditRemovePanel<NameLocationPair>(new ExtUrlsTableModel(), myPairs, XmlBundle.message("label.edit.external.resource.configure.external.resources")) {
+      protected NameLocationPair addItem() {
+        return addExtLocation();
+      }
+
+      protected boolean removeItem(NameLocationPair o) {
+        setModified(true);
+        return true;
+      }
+
+      protected NameLocationPair editItem(NameLocationPair o) {
+        return editExtLocation(o);
+      }
+    };
+
+    myExtPanel.setRenderer(1, new PathRenderer());
+
+    JTable table = myExtPanel.getTable();
+    if (myProject != null) {
+      TableColumn column = table.getColumn(table.getColumnName(2));
+      column.setMaxWidth(50);
+      column.setCellEditor(JBTable.createBooleanEditor());
+    }
+
+    table.getModel().addTableModelListener(new TableModelListener() {
+      public void tableChanged(TableModelEvent e) {
+        setModified(true);
+      }
+    });
+    myIgnorePanel = new AddEditRemovePanel<String>(new IgnoredUrlsModel(), myIgnoredUrls, XmlBundle.message("label.edit.external.resource.configure.ignored.resources")) {
+      protected String addItem() {
+        return addIgnoreLocation();
+      }
+
+      protected boolean removeItem(String o) {
+        setModified(true);
+        return true;
+      }
+
+      protected String editItem(String o) {
+        return editIgnoreLocation(o);
+      }
+    };
+    if (myProject != null) {
+      myHtmlLanguageLevelForm = new HtmlLanguageLevelForm(myProject);
+      myHtmlLanguageLevelForm.addListener(new HtmlLanguageLevelForm.MyListener() {
+        @Override
+        public void doctypeChanged() {
+          if (!myHtmlLanguageLevelForm.getDoctype().equals(myDefaultHtmlDoctype)) {
+            setModified(true);
+          }
+        }
+      });
+    }
+
+    myPanel.add(myExtPanel,
+                new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
+    myPanel.add(myIgnorePanel,
+                new GridBagConstraints(0, 1, 1, 1, 1, 1, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
+    if (myProject != null) {
+      myPanel.add(myHtmlLanguageLevelForm.getContentPanel(),
+                  new GridBagConstraints(0, 2, 1, 1, 1, 0, GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0),
+                                         0, 0));
+    }
+
+    myExtPanel.setData(myPairs);
+    myIgnorePanel.setData(myIgnoredUrls);
+
+    myExtPanel.getEmptyText().setText(XmlBundle.message("no.external.resources"));
+    myIgnorePanel.getEmptyText().setText(XmlBundle.message("no.ignored.resources"));
+
+    return myPanel;
+  }
+
+  public void apply() {
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      public void run() {
+        ExternalResourceManagerEx manager = ExternalResourceManagerEx.getInstanceEx();
+
+        if (myProject == null) {
+          manager.clearAllResources();
+        }
+        else {
+          manager.clearAllResources(myProject);
+        }
+        for (Object myPair : myPairs) {
+          NameLocationPair pair = (NameLocationPair)myPair;
+          String s = FileUtil.toSystemIndependentName(pair.myLocation);
+          if (myProject == null || pair.myShared) {
+            manager.addResource(pair.myName, s);
+          }
+          else {
+            manager.addResource(pair.myName, s, myProject);
+          }
+        }
+
+        for (Object myIgnoredUrl : myIgnoredUrls) {
+          String url = (String)myIgnoredUrl;
+          manager.addIgnoredResource(url);
+        }
+        if (myProject != null) {
+          manager.setDefaultHtmlDoctype(myHtmlLanguageLevelForm.getDoctype(), myProject);
+        }
+      }
+    });
+
+    setModified(false);
+  }
+
+  public void reset() {
+
+    myPairs = new ArrayList<NameLocationPair>(myNewPairs);
+    ExternalResourceManagerEx manager = ExternalResourceManagerEx.getInstanceEx();
+
+    String[] urls = manager.getAvailableUrls();
+    for (String url : urls) {
+      String loc = myProject == null ? manager.getResourceLocation(url, (String)null) : manager.getResourceLocation(url, myProject);
+      myPairs.add(new NameLocationPair(url, FileUtil.toSystemDependentName(loc), true));
+    }
+    if (myProject != null) {
+      urls = manager.getAvailableUrls(myProject);
+      for (String url : urls) {
+        String loc = manager.getResourceLocation(url, myProject);
+        myPairs.add(new NameLocationPair(url, FileUtil.toSystemDependentName(loc), false));
+      }
+    }
+
+    Collections.sort(myPairs);
+
+    myIgnoredUrls = new ArrayList<String>();
+    final String[] ignoredResources = manager.getIgnoredResources();
+    ContainerUtil.addAll(myIgnoredUrls, ignoredResources);
+
+    Collections.sort(myIgnoredUrls);
+
+    if (myExtPanel != null) {
+      myExtPanel.setData(myPairs);
+      myIgnorePanel.setData(myIgnoredUrls);
+      if (!myNewPairs.isEmpty()) {
+        ListSelectionModel selectionModel = myExtPanel.getTable().getSelectionModel();
+        selectionModel.clearSelection();
+        for (NameLocationPair newPair : myNewPairs) {
+          int index = myPairs.indexOf(newPair);
+          selectionModel.addSelectionInterval(index, index);
+        }
+      }
+     }
+
+    if (myProject != null) {
+      myDefaultHtmlDoctype = manager.getDefaultHtmlDoctype(myProject);
+      myHtmlLanguageLevelForm.resetFromDoctype(myDefaultHtmlDoctype);
+    }
+
+    setModified(!myNewPairs.isEmpty());
+  }
+
+  public void disposeUIResources() {
+    myPanel = null;
+    myExtPanel = null;
+    myIgnorePanel = null;
+    myHtmlLanguageLevelForm = null;
+  }
+
+  public String getHelpTopic() {
+    return "preferences.externalResources";
+  }
+
+  @Nullable
+  private NameLocationPair addExtLocation() {
+    MapExternalResourceDialog dialog = new MapExternalResourceDialog(null, myProject, null, null);
+    dialog.show();
+    if (!dialog.isOK()) return null;
+    setModified(true);
+    return new NameLocationPair(dialog.getUri(), dialog.getResourceLocation(), false);
+  }
+
+  @Nullable
+  private NameLocationPair editExtLocation(Object o) {
+    NameLocationPair pair = (NameLocationPair)o;
+    MapExternalResourceDialog dialog = new MapExternalResourceDialog(pair.getName(), myProject, null, pair.getLocation());
+    dialog.show();
+    if (!dialog.isOK()) {
+      return null;
+    }
+    setModified(true);
+    return new NameLocationPair(dialog.getUri(), dialog.getResourceLocation(), pair.myShared);
+  }
+
+  @Nullable
+  private String addIgnoreLocation() {
+    EditLocationDialog dialog = new EditLocationDialog(null, false);
+    dialog.show();
+    if (!dialog.isOK()) return null;
+    setModified(true);
+    return dialog.getPair().myName;
+  }
+
+  @Nullable
+  private String editIgnoreLocation(Object o) {
+    EditLocationDialog dialog = new EditLocationDialog(null, false);
+    dialog.init(new NameLocationPair(o.toString(), null, false));
+    dialog.show();
+    if (!dialog.isOK()) return null;
+    setModified(true);
+    return dialog.getPair().myName;
+  }
+
+  private static class PathRenderer extends DefaultTableCellRenderer {
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+      final Component rendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+      if (value != null) {
+        String loc = value.toString().replace('\\', '/');
+        final int jarDelimIndex = loc.indexOf(JarFileSystem.JAR_SEPARATOR);
+        final VirtualFile path;
+
+        if (jarDelimIndex != -1) {
+          path = JarFileSystem.getInstance().findFileByPath(loc);
+        } else {
+          path = LocalFileSystem.getInstance().findFileByPath(loc);
+        }
+
+        setForeground(path != null ? isSelected ? UIUtil.getTableSelectionForeground() : Color.black : new Color(210, 0, 0));
+      }
+      return rendererComponent;
+    }
+  }
+
+  private static class IgnoredUrlsModel extends AddEditRemovePanel.TableModel<String> {
+    private final String[] myNames = {XmlBundle.message("column.name.edit.external.resource.uri")};
+
+    public int getColumnCount() {
+      return myNames.length;
+    }
+
+    public Object getField(String o, int columnIndex) {
+      return o;
+    }
+
+    public Class getColumnClass(int columnIndex) {
+      return String.class;
+    }
+
+    public boolean isEditable(int column) {
+      return false;
+    }
+
+    public void setValue(Object aValue, String data, int columnIndex) {
+
+    }
+
+    public String getColumnName(int column) {
+      return myNames[column];
+    }
+  }
+
+  private class ExtUrlsTableModel extends AddEditRemovePanel.TableModel<NameLocationPair> {
+    final String[] myNames;
+
+    {
+      List<String> names = new ArrayList<String>();
+      names.add(XmlBundle.message("column.name.edit.external.resource.uri"));
+      names.add(XmlBundle.message("column.name.edit.external.resource.location"));
+      if (myProject != null) {
+        names.add("Project");
+      }
+      myNames = ArrayUtil.toStringArray(names);
+    }
+
+    public int getColumnCount() {
+      return myNames.length;
+    }
+
+    public Object getField(NameLocationPair pair, int columnIndex) {
+      switch (columnIndex) {
+        case 0:
+          return pair.myName;
+        case 1:
+          return pair.myLocation;
+        case 2:
+          return !pair.myShared;
+      }
+
+      return "";
+    }
+
+    public Class getColumnClass(int columnIndex) {
+      return columnIndex == 2 ? Boolean.class : String.class;
+    }
+
+    public boolean isEditable(int column) {
+      return column == 2;
+    }
+
+    public void setValue(Object aValue, NameLocationPair data, int columnIndex) {
+      data.myShared = !((Boolean)aValue).booleanValue();
+    }
+
+    public String getColumnName(int column) {
+      return myNames[column];
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourceListener.java b/xml/impl/src/com/intellij/javaee/ExternalResourceListener.java
new file mode 100644
index 0000000..0bca97c
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/ExternalResourceListener.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+/**
+ * @author mike
+ */
+public interface ExternalResourceListener {
+  void externalResourceChanged();
+}
diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java
new file mode 100644
index 0000000..00e93a4
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * author: lesya
+ */
+public abstract class ExternalResourceManagerEx extends ExternalResourceManager {
+  public static ExternalResourceManagerEx getInstanceEx(){
+    return (ExternalResourceManagerEx)getInstance();
+  }
+
+  public abstract void removeResource(String url, @NotNull Project project);
+
+  public abstract void addResource(@NonNls String url, @NonNls String location, @NotNull Project project);
+
+  public abstract String[] getAvailableUrls();
+  public abstract String[] getAvailableUrls(Project project);
+
+  public abstract void clearAllResources();
+  public abstract void clearAllResources(Project project);
+
+  public abstract void addIgnoredResource(String url);
+  public abstract void removeIgnoredResource(String url);
+
+  public abstract boolean isIgnoredResource(String url);
+
+  public abstract String[] getIgnoredResources();
+
+  public abstract void addExternalResourceListener(ExternalResourceListener listener);
+
+  public abstract void removeExternalResourceListener(ExternalResourceListener listener);
+
+  @Nullable
+  public abstract String getUserResourse(Project project, String url, String version);
+  @Nullable
+  public abstract String getStdResource(String url, String version);
+
+  @NotNull
+  public abstract String getDefaultHtmlDoctype(@NotNull Project project);
+
+  public abstract void setDefaultHtmlDoctype(@NotNull String defaultHtmlDoctype, @NotNull Project project);
+
+  public abstract String getCatalogPropertiesFile();
+  public abstract void setCatalogPropertiesFile(@Nullable String filePath);
+
+  public abstract long getModificationCount(@NotNull Project project);
+}
diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java
new file mode 100644
index 0000000..9e53742
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java
@@ -0,0 +1,585 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.application.options.PathMacrosImpl;
+import com.intellij.application.options.ReplacePathToMacroMap;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.HashMap;
+import com.intellij.xml.Html5SchemaProvider;
+import com.intellij.xml.XmlSchemaProvider;
+import com.intellij.xml.util.XmlUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
+
+import java.io.File;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * @author mike
+ */
+@State(name = "ExternalResourceManagerImpl",
+       storages = {@Storage( file = StoragePathMacros.APP_CONFIG + "/other.xml")})
+public class ExternalResourceManagerImpl extends ExternalResourceManagerEx implements JDOMExternalizable {
+  static final Logger LOG = Logger.getInstance("#com.intellij.j2ee.openapi.impl.ExternalResourceManagerImpl");
+
+  @NonNls public static final String J2EE_1_3 = "http://java.sun.com/dtd/";
+  @NonNls public static final String J2EE_1_2 = "http://java.sun.com/j2ee/dtds/";
+  @NonNls public static final String J2EE_NS = "http://java.sun.com/xml/ns/j2ee/";
+  @NonNls public static final String JAVAEE_NS = "http://java.sun.com/xml/ns/javaee/";
+  private static final String CATALOG_PROPERTIES_ELEMENT = "CATALOG_PROPERTIES";
+
+
+  private final Map<String, Map<String, String>> myResources = new HashMap<String, Map<String, String>>();
+  private final Set<String> myResourceLocations = new HashSet<String>();
+
+  private final Set<String> myIgnoredResources = new HashSet<String>();
+
+  private final AtomicNotNullLazyValue<Map<String, Map<String, Resource>>> myStdResources = new AtomicNotNullLazyValue<Map<String, Map<String, Resource>>>() {
+        
+    @NotNull
+    @Override
+    protected Map<String, Map<String, Resource>> compute() {
+      return computeStdResources();
+    }
+  };
+
+  private String myDefaultHtmlDoctype = HTML5_DOCTYPE_ELEMENT;
+
+  private String myCatalogPropertiesFile;
+  private XMLCatalogManager myCatalogManager;
+  private static final String HTML5_DOCTYPE_ELEMENT = "HTML5";
+
+  protected Map<String, Map<String, Resource>> computeStdResources() {
+    ResourceRegistrarImpl registrar = new ResourceRegistrarImpl();
+    for (StandardResourceProvider provider : Extensions.getExtensions(StandardResourceProvider.EP_NAME)) {
+      provider.registerResources(registrar);
+    }
+    StandardResourceEP[] extensions = Extensions.getExtensions(StandardResourceEP.EP_NAME);
+    for (StandardResourceEP extension : extensions) {
+      registrar.addStdResource(extension.url, extension.version, extension.resourcePath, null, extension.getLoaderForClass());
+    }
+
+    myIgnoredResources.addAll(registrar.getIgnored());
+    return registrar.getResources();
+  }
+
+  private final List<ExternalResourceListener> myListeners = new ArrayList<ExternalResourceListener>();
+  private long myModificationCount = 0;
+  private final PathMacrosImpl myPathMacros;
+  @NonNls private static final String RESOURCE_ELEMENT = "resource";
+  @NonNls private static final String URL_ATTR = "url";
+  @NonNls private static final String LOCATION_ATTR = "location";
+  @NonNls private static final String IGNORED_RESOURCE_ELEMENT = "ignored-resource";
+  @NonNls private static final String HTML_DEFAULT_DOCTYPE_ELEMENT = "default-html-doctype";
+  private static final String DEFAULT_VERSION = null;
+  @NonNls public static final String STANDARD_SCHEMAS = "/standardSchemas/";
+
+  public ExternalResourceManagerImpl(PathMacrosImpl pathMacros) {
+    myPathMacros = pathMacros;
+  }
+
+  public static boolean isStandardResource(VirtualFile file) {
+    VirtualFile parent = file.getParent();
+    return parent != null && parent.getName().equals("standardSchemas");
+  }
+
+  public boolean isUserResource(VirtualFile file) {
+    return myResourceLocations.contains(file.getUrl());
+  }
+
+  @Nullable
+  static <T> Map<String, T> getMap(@NotNull final Map<String, Map<String, T>> resources,
+                                    @Nullable final String version,
+                                    final boolean create) {
+    Map<String, T> map = resources.get(version);
+    if (map == null) {
+      if (create) {
+        map = ContainerUtil.newHashMap();
+        resources.put(version, map);
+      }
+      else if (version == null || !version.equals(DEFAULT_VERSION)) {
+        map = resources.get(DEFAULT_VERSION);
+      }
+    }
+
+    return map;
+  }
+
+  public String getResourceLocation(String url) {
+    return getResourceLocation(url, DEFAULT_VERSION);
+  }
+
+  public String getResourceLocation(@NonNls String url, String version) {
+    String result = getUserResource(url, version);
+    if (result == null) {
+      XMLCatalogManager manager = getCatalogManager();
+      if (manager != null) {
+        result = manager.resolve(url);
+      }
+    }
+    if (result == null) {
+      result = getStdResource(url, version);
+    }
+    if (result == null) {
+      result = url;
+    }
+    return result;
+  }
+
+  @Override
+  @Nullable
+  public String getUserResourse(Project project, String url, String version) {
+    String resourse = getProjectResources(project).getUserResource(url, version);
+    return resourse == null ? getUserResource(url, version) : resourse;
+  }
+
+  @Override
+  @Nullable
+  public String getStdResource(String url, String version) {
+    Map<String, Resource> map = getMap(myStdResources.getValue(), version, false);
+    if (map != null) {
+      Resource resource = map.get(url);
+      return resource == null ? null : resource.getResourceUrl();
+    }
+    else {
+      return null;
+    }
+  }
+
+  @Nullable
+  private String getUserResource(String url, String version) {
+    Map<String, String> map = getMap(myResources, version, false);
+    return map != null ? map.get(url) : null;
+  }
+
+  public String getResourceLocation(@NonNls String url, @NotNull Project project) {
+    String location = getProjectResources(project).getResourceLocation(url);
+    return location == null || location.equals(url) ? getResourceLocation(url) : location;
+  }
+
+  public String getResourceLocation(@NonNls String url, String version, @NotNull Project project) {
+    String location = getProjectResources(project).getResourceLocation(url, version);
+    return location == null || location.equals(url) ? getResourceLocation(url, version) : location;
+  }
+
+  @Nullable
+  public PsiFile getResourceLocation(@NotNull @NonNls final String url, @NotNull final PsiFile baseFile, final String version) {
+    final XmlFile schema = XmlSchemaProvider.findSchema(url, baseFile);
+    if (schema != null) {
+      return schema;
+    }
+    final String location = getResourceLocation(url, version, baseFile.getProject());
+    return XmlUtil.findXmlFile(baseFile, location);
+  }
+
+  public String[] getResourceUrls(FileType fileType, final boolean includeStandard) {
+    return getResourceUrls(fileType, DEFAULT_VERSION, includeStandard);
+  }
+
+  public String[] getResourceUrls(@Nullable final FileType fileType, @NonNls final String version, final boolean includeStandard) {
+    final List<String> result = new LinkedList<String>();
+    addResourcesFromMap(result, version, myResources);
+
+    if (includeStandard) {
+      addResourcesFromMap(result, version, myStdResources.getValue());
+    }
+
+    return ArrayUtil.toStringArray(result);
+  }
+
+  private static <T> void addResourcesFromMap(final List<String> result,
+                                          String version,
+                                          Map<String, Map<String, T>> resourcesMap) {
+    Map<String, T> resources = getMap(resourcesMap, version, false);
+    if (resources == null) return;
+    result.addAll(resources.keySet());
+  }
+
+  @TestOnly
+  public static void addTestResource(final String url, final String location, Disposable parentDisposable) {
+    final ExternalResourceManagerImpl instance = (ExternalResourceManagerImpl)getInstance();
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      public void run() {
+        instance.addResource(url, location);
+      }
+    });
+    Disposer.register(parentDisposable, new Disposable() {
+      @Override
+      public void dispose() {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          public void run() {
+            instance.removeResource(url);
+          }
+        });
+      }
+    });
+  }
+  public void addResource(String url, String location) {
+    addResource(url, DEFAULT_VERSION, location);
+  }
+
+  public void addResource(@NonNls String url, @NonNls String version, @NonNls String location) {
+    ApplicationManager.getApplication().assertWriteAccessAllowed();
+    addSilently(url, version, location);
+    fireExternalResourceChanged();
+  }
+
+  private void addSilently(String url, String version, String location) {
+    final Map<String, String> map = getMap(myResources, version, true);
+    assert map != null;
+    map.put(url, location);
+    myResourceLocations.add(location);
+    myModificationCount++;
+  }
+
+  public void removeResource(String url) {
+    removeResource(url, DEFAULT_VERSION);
+  }
+
+  public void removeResource(String url, String version) {
+    ApplicationManager.getApplication().assertWriteAccessAllowed();
+    Map<String, String> map = getMap(myResources, version, false);
+    if (map != null) {
+      String location = map.remove(url);
+      if (location != null) {
+        myResourceLocations.remove(location);
+      }
+      myModificationCount++;
+      fireExternalResourceChanged();
+    }
+  }
+
+  @Override
+  public void removeResource(String url, @NotNull Project project) {
+    getProjectResources(project).removeResource(url);
+  }
+
+  @Override
+  public void addResource(@NonNls String url, @NonNls String location, @NotNull Project project) {
+    getProjectResources(project).addResource(url, location);
+  }
+
+  public String[] getAvailableUrls() {
+    Set<String> urls = new HashSet<String>();
+    for (Map<String, String> map : myResources.values()) {
+      urls.addAll(map.keySet());
+    }
+    return ArrayUtil.toStringArray(urls);
+  }
+
+  @Override
+  public String[] getAvailableUrls(Project project) {
+    return getProjectResources(project).getAvailableUrls();
+  }
+
+  public void clearAllResources() {
+    myResources.clear();
+    myIgnoredResources.clear();
+  }
+
+  public void clearAllResources(Project project) {
+    ApplicationManager.getApplication().assertWriteAccessAllowed();
+    clearAllResources();
+    getProjectResources(project).clearAllResources();
+    myModificationCount++;
+    fireExternalResourceChanged();
+  }
+
+  public void addIgnoredResource(String url) {
+    ApplicationManager.getApplication().assertWriteAccessAllowed();
+    addIgnoredSilently(url);
+    fireExternalResourceChanged();
+  }
+
+  private void addIgnoredSilently(String url) {
+    myIgnoredResources.add(url);
+    myModificationCount++;
+  }
+
+  public void removeIgnoredResource(String url) {
+    ApplicationManager.getApplication().assertWriteAccessAllowed();
+    if (myIgnoredResources.remove(url)) {
+      myModificationCount++;
+      fireExternalResourceChanged();
+    }
+  }
+
+  public boolean isIgnoredResource(String url) {
+    myStdResources.getValue();  // ensure ignored resources are loaded
+    return myIgnoredResources.contains(url) || isImplicitNamespaceDescriptor(url);
+  }
+
+  private static boolean isImplicitNamespaceDescriptor(String url) {
+    for (ImplicitNamespaceDescriptorProvider namespaceDescriptorProvider : Extensions
+      .getExtensions(ImplicitNamespaceDescriptorProvider.EP_NAME)) {
+      if (namespaceDescriptorProvider.getNamespaceDescriptor(null, url, null) != null) return true;
+    }
+    return false;
+  }
+
+  public String[] getIgnoredResources() {
+    myStdResources.getValue();  // ensure ignored resources are loaded
+    return ArrayUtil.toStringArray(myIgnoredResources);
+  }
+
+  public long getModificationCount() {
+    return myModificationCount;
+  }
+
+  @Override
+  public long getModificationCount(@NotNull Project project) {
+    return getProjectResources(project).getModificationCount();
+  }
+
+  public void readExternal(Element element) throws InvalidDataException {
+    final ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap();
+    myPathMacros.addMacroExpands(macroExpands);
+    macroExpands.substitute(element, SystemInfo.isFileSystemCaseSensitive);
+
+    myModificationCount++;
+    for (final Object o1 : element.getChildren(RESOURCE_ELEMENT)) {
+      Element e = (Element)o1;
+      addSilently(e.getAttributeValue(URL_ATTR), DEFAULT_VERSION, e.getAttributeValue(LOCATION_ATTR).replace('/', File.separatorChar));
+    }
+
+    for (final Object o : element.getChildren(IGNORED_RESOURCE_ELEMENT)) {
+      Element e = (Element)o;
+      addIgnoredSilently(e.getAttributeValue(URL_ATTR));
+    }
+
+    Element child = element.getChild(HTML_DEFAULT_DOCTYPE_ELEMENT);
+    if (child != null) {
+      String text = child.getText();
+      if (FileUtil.toSystemIndependentName(text).endsWith("idea.jar!/resources/html5-schema/html5.rnc")) {
+        text = HTML5_DOCTYPE_ELEMENT;
+      }
+      myDefaultHtmlDoctype = text;
+    }
+    Element catalogElement = element.getChild(CATALOG_PROPERTIES_ELEMENT);
+    if (catalogElement != null) {
+      myCatalogPropertiesFile = catalogElement.getTextTrim();
+    }
+  }
+
+  public void writeExternal(Element element) throws WriteExternalException {
+    final String[] urls = getAvailableUrls();
+    for (String url : urls) {
+      if (url == null) continue;
+      String location = getResourceLocation(url);
+      if (location == null) continue;
+      final Element e = new Element(RESOURCE_ELEMENT);
+
+      e.setAttribute(URL_ATTR, url);
+      e.setAttribute(LOCATION_ATTR, location.replace(File.separatorChar, '/'));
+      element.addContent(e);
+    }
+
+    final String[] ignoredResources = getIgnoredResources();
+    for (String ignoredResource : ignoredResources) {
+      final Element e = new Element(IGNORED_RESOURCE_ELEMENT);
+
+      e.setAttribute(URL_ATTR, ignoredResource);
+      element.addContent(e);
+    }
+
+    if (myDefaultHtmlDoctype != null && !HTML5_DOCTYPE_ELEMENT.equals(myDefaultHtmlDoctype)) {
+      final Element e = new Element(HTML_DEFAULT_DOCTYPE_ELEMENT);
+      e.setText(myDefaultHtmlDoctype);
+      element.addContent(e);
+    }
+    if (myCatalogPropertiesFile != null) {
+      Element properties = new Element(CATALOG_PROPERTIES_ELEMENT);
+      properties.setText(myCatalogPropertiesFile);
+      element.addContent(properties);
+    }
+    final ReplacePathToMacroMap macroReplacements = new ReplacePathToMacroMap();
+    PathMacrosImpl.getInstanceEx().addMacroReplacements(macroReplacements);
+    macroReplacements.substitute(element, SystemInfo.isFileSystemCaseSensitive);
+  }
+
+  public void addExternalResourceListener(ExternalResourceListener listener) {
+    myListeners.add(listener);
+  }
+
+  public void removeExternalResourceListener(ExternalResourceListener listener) {
+    myListeners.remove(listener);
+  }
+
+  private void fireExternalResourceChanged() {
+    for (ExternalResourceListener listener : myListeners.toArray(new ExternalResourceListener[myListeners.size()])) {
+      listener.externalResourceChanged();
+    }
+  }
+
+  Collection<Map<String, Resource>> getStandardResources() {
+    return myStdResources.getValue().values();
+  }
+
+
+  private static final NotNullLazyKey<ProjectResources, Project> INSTANCE_CACHE = ServiceManager.createLazyKey(ProjectResources.class);
+
+  private static ExternalResourceManagerImpl getProjectResources(Project project) {
+    return INSTANCE_CACHE.getValue(project);
+  }
+
+  @Override
+  @NotNull
+  public String getDefaultHtmlDoctype(@NotNull Project project) {
+    final String doctype = getProjectResources(project).myDefaultHtmlDoctype;
+    if (XmlUtil.XHTML_URI.equals(doctype)) {
+      return XmlUtil.XHTML4_SCHEMA_LOCATION;
+    }
+    else if (HTML5_DOCTYPE_ELEMENT.equals(doctype)) {
+      return Html5SchemaProvider.HTML5_SCHEMA_LOCATION;
+    }
+    else {
+      return doctype;
+    }
+  }
+
+  @Override
+  public void setDefaultHtmlDoctype(@NotNull String defaultHtmlDoctype, @NotNull Project project) {
+    getProjectResources(project).setDefaultHtmlDoctype(defaultHtmlDoctype);
+  }
+
+  @Override
+  public String getCatalogPropertiesFile() {
+    return myCatalogPropertiesFile;
+  }
+
+  @Override
+  public void setCatalogPropertiesFile(String filePath) {
+    myCatalogManager = null;
+    myCatalogPropertiesFile = filePath;
+    myModificationCount++;
+  }
+
+  @Nullable
+  private XMLCatalogManager getCatalogManager() {
+    if (myCatalogManager == null && myCatalogPropertiesFile != null) {
+      myCatalogManager = new XMLCatalogManager(myCatalogPropertiesFile);
+    }
+    return myCatalogManager;
+  }
+
+  private void setDefaultHtmlDoctype(String defaultHtmlDoctype) {
+    myModificationCount++;
+
+    if (Html5SchemaProvider.HTML5_SCHEMA_LOCATION.equals(defaultHtmlDoctype)) {
+      myDefaultHtmlDoctype = HTML5_DOCTYPE_ELEMENT;
+    }
+    else {
+      myDefaultHtmlDoctype = defaultHtmlDoctype;
+    }
+    fireExternalResourceChanged();
+  }
+
+  @TestOnly
+  public static void registerResourceTemporarily(final String url, final String location, Disposable disposable) {
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      public void run() {
+        getInstance().addResource(url, location);
+      }
+    });
+
+    Disposer.register(disposable, new Disposable() {
+      @Override
+      public void dispose() {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          public void run() {
+            getInstance().removeResource(url);
+          }
+        });
+      }
+    });
+  }
+
+  static class Resource {
+    String file;
+    ClassLoader classLoader;
+    Class clazz;
+
+    @Nullable
+    String getResourceUrl() {
+
+      if (classLoader == null && clazz == null) return file;
+
+      final URL resource = clazz == null ? classLoader.getResource(file) : clazz.getResource(file);
+      classLoader = null;
+      clazz = null;
+      if (resource == null) {
+        String message = "Cannot find standard resource. filename:" + file + " class=" + classLoader;
+        if (ApplicationManager.getApplication().isUnitTestMode()) {
+          LOG.error(message);
+        }
+        else {
+          LOG.warn(message);
+        }
+
+        return null;
+      }
+
+      String path = FileUtil.unquote(resource.toString());
+      // this is done by FileUtil for windows
+      path = path.replace('\\','/');
+      file = path;
+      return path;
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      Resource resource = (Resource)o;
+
+      if (classLoader != resource.classLoader) return false;
+      if (clazz != resource.clazz) return false;
+      if (file != null ? !file.equals(resource.file) : resource.file != null) return false;
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return file.hashCode();
+    }
+
+    @Override
+    public String toString() {
+      return file + " for " + classLoader;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java b/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java
new file mode 100644
index 0000000..40fb2a7
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.codeInsight.daemon.impl.quickfix.FetchExtResourceAction;
+import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.indexing.IndexableSetContributor;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class ExternalResourcesRootsProvider extends IndexableSetContributor {
+
+  private final NotNullLazyValue<Set<String>> myStandardResources = new NotNullLazyValue<Set<String>>() {
+    @NotNull
+    @Override
+    protected Set<String> compute() {
+      ExternalResourceManagerImpl manager = (ExternalResourceManagerImpl)ExternalResourceManager.getInstance();
+      Collection<Map<String,ExternalResourceManagerImpl.Resource>> resources = manager.getStandardResources();
+      Set<ExternalResourceManagerImpl.Resource> dirs = new HashSet<ExternalResourceManagerImpl.Resource>();
+      Set<String> set = new HashSet<String>();
+      for (Map<String, ExternalResourceManagerImpl.Resource> map : resources) {
+        for (ExternalResourceManagerImpl.Resource resource : map.values()) {
+          ExternalResourceManagerImpl.Resource dir = new ExternalResourceManagerImpl.Resource();
+          int i = resource.file.lastIndexOf('/');
+          dir.file = i > 0 ? resource.file.substring(0, i) : resource.file;
+          dir.classLoader = resource.classLoader;
+          dir.clazz = resource.clazz;
+          if (dirs.add(dir)) {
+            String url = resource.getResourceUrl();
+            if (url != null) {
+              set.add(url.substring(0, url.lastIndexOf('/')));
+            }
+          }
+        }
+      }
+      return set;
+    }
+  };
+
+  public Set<VirtualFile> getAdditionalRootsToIndex() {
+
+    HashSet<VirtualFile> roots = new HashSet<VirtualFile>();
+    for (String url : myStandardResources.getValue()) {
+      VirtualFile file = VfsUtil.findRelativeFile(url, null);
+      if (file != null) {
+        roots.add(file);
+      }
+    }
+
+    String path = FetchExtResourceAction.getExternalResourcesPath();
+    VirtualFile extResources = LocalFileSystem.getInstance().findFileByPath(path);
+    ContainerUtil.addIfNotNull(extResources, roots);
+    
+    return roots;
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/HtmlLanguageLevelForm.form b/xml/impl/src/com/intellij/javaee/HtmlLanguageLevelForm.form
new file mode 100644
index 0000000..60ecb1c
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/HtmlLanguageLevelForm.form
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.javaee.HtmlLanguageLevelForm">
+  <grid id="27dc6" binding="myContentPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="326" height="138"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <grid id="adc9b" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <clientProperties>
+          <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
+        </clientProperties>
+        <border type="none" title="Default HTML language level"/>
+        <children>
+          <component id="aad8c" class="javax.swing.JRadioButton" binding="myHtml4RadioButton">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="HTML 4 (&quot;http://www.w3.org/TR/html4/loose.dtd&quot;)"/>
+            </properties>
+          </component>
+          <component id="bb372" class="javax.swing.JRadioButton" binding="myHtml5RadioButton">
+            <constraints>
+              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="HTML 5"/>
+            </properties>
+          </component>
+          <grid id="6ae8e" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints>
+              <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="192c4" class="javax.swing.JRadioButton" binding="myOtherRadioButton" default-binding="true">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="Other doctype:"/>
+                </properties>
+              </component>
+              <grid id="88e81" binding="myOtherDoctypeWrapper" layout-manager="BorderLayout" hgap="0" vgap="0">
+                <constraints>
+                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+                <border type="none"/>
+                <children/>
+              </grid>
+            </children>
+          </grid>
+        </children>
+      </grid>
+    </children>
+  </grid>
+  <buttonGroups>
+    <group name="buttonGroup1">
+      <member id="aad8c"/>
+      <member id="bb372"/>
+      <member id="192c4"/>
+    </group>
+  </buttonGroups>
+</form>
diff --git a/xml/impl/src/com/intellij/javaee/HtmlLanguageLevelForm.java b/xml/impl/src/com/intellij/javaee/HtmlLanguageLevelForm.java
new file mode 100644
index 0000000..5f31930
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/HtmlLanguageLevelForm.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.TextFieldWithAutoCompletion;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.Html5SchemaProvider;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class HtmlLanguageLevelForm {
+  private JRadioButton myHtml4RadioButton;
+  private JRadioButton myHtml5RadioButton;
+  private JRadioButton myOtherRadioButton;
+  private JPanel myContentPanel;
+  private JPanel myOtherDoctypeWrapper;
+  private final TextFieldWithAutoCompletion myDoctypeTextField;
+  private final List<MyListener> myListeners = new ArrayList<MyListener>();
+
+  public HtmlLanguageLevelForm(Project project) {
+    final String[] urls = ExternalResourceManager.getInstance().getResourceUrls(null, true);
+    myDoctypeTextField = TextFieldWithAutoCompletion.create(project, Arrays.asList(urls), null, true, null);
+    myOtherDoctypeWrapper.add(myDoctypeTextField);
+    ActionListener listener = new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        myDoctypeTextField.setEnabled(myOtherRadioButton.isSelected());
+        fireDoctypeChanged();
+      }
+    };
+    myHtml4RadioButton.addActionListener(listener);
+    myHtml5RadioButton.addActionListener(listener);
+    myOtherRadioButton.addActionListener(listener);
+    myDoctypeTextField.addDocumentListener(new DocumentAdapter() {
+      @Override
+      public void documentChanged(DocumentEvent e) {
+        fireDoctypeChanged();
+      }
+    });
+  }
+
+  public JPanel getContentPanel() {
+    return myContentPanel;
+  }
+
+  @NotNull
+  public String getDoctype() {
+    if (myHtml4RadioButton.isSelected()) {
+      return XmlUtil.XHTML_URI;
+    }
+    if (myHtml5RadioButton.isSelected()) {
+      return Html5SchemaProvider.HTML5_SCHEMA_LOCATION;
+    }
+    return myDoctypeTextField.getText();
+  }
+
+  public void resetFromDoctype(final String doctype) {
+    if (doctype == null || doctype.isEmpty() || doctype.equals(XmlUtil.XHTML4_SCHEMA_LOCATION)) {
+      myHtml4RadioButton.setSelected(true);
+      myDoctypeTextField.setEnabled(false);
+    }
+    else if (doctype.equals(Html5SchemaProvider.HTML5_SCHEMA_LOCATION)) {
+      myHtml5RadioButton.setSelected(true);
+      myDoctypeTextField.setEnabled(false);
+    }
+    else {
+      myOtherRadioButton.setSelected(true);
+      myDoctypeTextField.setEnabled(true);
+      UIUtil.invokeLaterIfNeeded(new Runnable() {
+        @Override
+        public void run() {
+          try {
+            myDoctypeTextField.setText(doctype);
+          }
+          catch (Exception e) {
+            throw new RuntimeException(e);
+          }
+        }
+      });
+    }
+  }
+
+  public void addListener(@NotNull MyListener listener) {
+    myListeners.add(listener);
+  }
+
+  public void removeListener(@NotNull MyListener listener) {
+    myListeners.remove(listener);
+  }
+
+  private void fireDoctypeChanged() {
+    for (MyListener listener : myListeners) {
+      listener.doctypeChanged();
+    }
+  }
+
+  public interface MyListener {
+    void doctypeChanged();
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/ImplicitNamespaceDescriptorProvider.java b/xml/impl/src/com/intellij/javaee/ImplicitNamespaceDescriptorProvider.java
new file mode 100644
index 0000000..d3f0a34
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/ImplicitNamespaceDescriptorProvider.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.module.Module;
+import com.intellij.psi.PsiFile;
+import com.intellij.xml.XmlNSDescriptor;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public interface ImplicitNamespaceDescriptorProvider {
+  @NonNls ExtensionPointName<ImplicitNamespaceDescriptorProvider> EP_NAME = ExtensionPointName.create("com.intellij.xml.implicitNamespaceDescriptorProvider");
+
+  @Nullable
+  XmlNSDescriptor getNamespaceDescriptor(@Nullable Module module, @NotNull final String ns, @Nullable PsiFile file);
+}
diff --git a/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java
new file mode 100644
index 0000000..d9755ad
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class InternalResourceProvider implements StandardResourceProvider{
+
+  public void registerResources(ResourceRegistrar registrar) {
+    ResourceRegistrarImpl impl = (ResourceRegistrarImpl)registrar;
+    
+    impl.addInternalResource(XmlUtil.XSLT_URI,"xslt-1_0.xsd");
+    impl.addInternalResource(XmlUtil.XSLT_URI,"2.0", "xslt-2_0.xsd");
+    impl.addInternalResource(XmlUtil.XINCLUDE_URI,"xinclude.xsd");
+    impl.addInternalResource(XmlUtil.XML_SCHEMA_URI, "XMLSchema.xsd");
+    impl.addInternalResource(XmlUtil.XML_SCHEMA_URI + ".xsd", "XMLSchema.xsd");
+    impl.addInternalResource("http://www.w3.org/2001/XMLSchema.dtd", "XMLSchema.dtd");
+    impl.addInternalResource(XmlUtil.XML_SCHEMA_INSTANCE_URI, "XMLSchema-instance.xsd");
+    impl.addInternalResource("http://www.w3.org/2001/xml.xsd","xml.xsd");
+    impl.addInternalResource(XmlUtil.XML_NAMESPACE_URI,"xml.xsd");
+    impl.addInternalResource(XmlUtil.XHTML_URI,"xhtml1-transitional.xsd");
+    impl.addInternalResource("http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd","xhtml1-strict.xsd");
+
+    impl.addInternalResource("http://www.w3.org/TR/html4/strict.dtd","xhtml1-strict.dtd");
+    impl.addInternalResource(XmlUtil.HTML4_LOOSE_URI,"xhtml1-transitional.dtd");
+    impl.addInternalResource("http://www.w3.org/TR/html4/frameset.dtd","xhtml1-frameset.dtd");
+    impl.addInternalResource("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd","xhtml1-strict.dtd");
+    impl.addInternalResource("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd","xhtml1-transitional.dtd");
+    impl.addInternalResource("http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd","xhtml1-frameset.dtd");
+    impl.addInternalResource("http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd","xhtml11/xhtml11.dtd");
+
+    impl.addInternalResource("urn:oasis:names:tc:entity:xmlns:xml:catalog", "catalog.xsd");
+
+    // Plugins DTDs // stathik
+    impl.addInternalResource("http://plugins.intellij.net/plugin.dtd", "plugin.dtd");
+    impl.addInternalResource("http://plugins.intellij.net/plugin-repository.dtd", "plugin-repository.dtd");
+
+    // mobile
+    impl.addInternalResource("http://www.wapforum.org/DTD/xhtml-mobile10.dtd", "xhtml-mobile/xhtml-mobile10.dtd");
+    impl.addInternalResource("http://www.wapforum.org/DTD/xhtml-mobile10-flat.dtd", "xhtml-mobile/xhtml-mobile10-flat.dtd");
+    impl.addInternalResource("http://www.wapforum.org/DTD/xhtml-mobile12.dtd", "xhtml-mobile/xhtml-mobile12.dtd");
+
+    impl.addInternalResource("http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd", "xhtml-mobile/xhtml-mobile12.dtd");
+
+    // svg and mathML
+    impl.addIgnoredResource(HtmlUtil.MATH_ML_NAMESPACE);
+    impl.addIgnoredResource(HtmlUtil.SVG_NAMESPACE);
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/MapExternalResourceDialog.form b/xml/impl/src/com/intellij/javaee/MapExternalResourceDialog.form
new file mode 100644
index 0000000..49c27b2
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/MapExternalResourceDialog.form
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.javaee.MapExternalResourceDialog">
+  <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="95c44" class="com.intellij.ui.components.JBLabel">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <labelFor value="3a92c"/>
+          <text value="&amp;URI:"/>
+        </properties>
+      </component>
+      <component id="3a92c" class="javax.swing.JTextField" binding="myUri">
+        <constraints>
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+            <preferred-size width="150" height="-1"/>
+          </grid>
+        </constraints>
+        <properties/>
+      </component>
+      <grid id="2057d" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <tabbedpane id="c9457" class="com.intellij.ui.components.JBTabbedPane" binding="myTabs">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <grid id="39983" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                <margin top="0" left="0" bottom="0" right="0"/>
+                <constraints>
+                  <tabbedpane title="Schemas"/>
+                </constraints>
+                <properties/>
+                <border type="none"/>
+                <children>
+                  <scrollpane id="ec831" class="com.intellij.ui.components.JBScrollPane">
+                    <constraints>
+                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties/>
+                    <border type="none"/>
+                    <children>
+                      <component id="a85b4" class="com.intellij.ui.treeStructure.Tree" binding="mySchemasTree">
+                        <constraints/>
+                        <properties/>
+                      </component>
+                    </children>
+                  </scrollpane>
+                </children>
+              </grid>
+              <grid id="d3553" binding="myExplorerPanel" custom-create="true" layout-manager="BorderLayout" hgap="0" vgap="0">
+                <constraints>
+                  <tabbedpane title="Explorer"/>
+                </constraints>
+                <properties/>
+                <border type="none"/>
+                <children/>
+              </grid>
+            </children>
+          </tabbedpane>
+        </children>
+      </grid>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/javaee/MapExternalResourceDialog.java b/xml/impl/src/com/intellij/javaee/MapExternalResourceDialog.java
new file mode 100644
index 0000000..eae3953
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/MapExternalResourceDialog.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.colors.EditorFontType;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.FileSystemTree;
+import com.intellij.openapi.fileChooser.ex.FileSystemTreeImpl;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.components.JBPanel;
+import com.intellij.ui.components.JBTabbedPane;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.tree.TreeUtil;
+import com.intellij.xml.config.ConfigFileSearcher;
+import com.intellij.xml.config.ConfigFilesTreeBuilder;
+import com.intellij.xml.index.IndexedRelevantResource;
+import com.intellij.xml.index.XmlNamespaceIndex;
+import com.intellij.xml.index.XsdNamespaceBuilder;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Dmitry Avdeev
+ *         Date: 7/17/12
+ */
+public class MapExternalResourceDialog extends DialogWrapper {
+
+  private static final String MAP_EXTERNAL_RESOURCE_SELECTED_TAB = "map.external.resource.selected.tab";
+  private JTextField myUri;
+  private JPanel myMainPanel;
+  private JTree mySchemasTree;
+  private JPanel myExplorerPanel;
+  private JBTabbedPane myTabs;
+  private final FileSystemTreeImpl myExplorer;
+  private String myLocation;
+
+  public MapExternalResourceDialog(String uri, @NotNull Project project, @Nullable PsiFile file, @Nullable String location) {
+    super(project);
+    setTitle("Map External Resource");
+    myUri.setText(uri);
+
+    DefaultMutableTreeNode root = new DefaultMutableTreeNode();
+    mySchemasTree.setModel(new DefaultTreeModel(root));
+    ConfigFileSearcher searcher = new ConfigFileSearcher(file == null ? null : ModuleUtilCore.findModuleForPsiElement(file), project) {
+      @Override
+      public Set<PsiFile> search(@Nullable Module module, @NotNull Project project) {
+        List<IndexedRelevantResource<String, XsdNamespaceBuilder>> resources = XmlNamespaceIndex.getAllResources(module, project, null);
+
+        HashSet<PsiFile> files = new HashSet<PsiFile>();
+        PsiManager psiManager = PsiManager.getInstance(project);
+        for (IndexedRelevantResource<String, XsdNamespaceBuilder> resource : resources) {
+          VirtualFile file = resource.getFile();
+          PsiFile psiFile = psiManager.findFile(file);
+          ContainerUtil.addIfNotNull(files, psiFile);
+        }
+        return files;
+      }
+    };
+    searcher.search();
+    new ConfigFilesTreeBuilder(mySchemasTree).buildTree(searcher, root);
+    TreeUtil.expandAll(mySchemasTree);
+    mySchemasTree.setRootVisible(false);
+    mySchemasTree.setShowsRootHandles(true);
+
+    ColoredTreeCellRenderer renderer = new ColoredTreeCellRenderer() {
+      @Override
+      public void customizeCellRenderer(JTree tree,
+                                        Object value,
+                                        boolean selected,
+                                        boolean expanded,
+                                        boolean leaf,
+                                        int row,
+                                        boolean hasFocus) {
+        ConfigFilesTreeBuilder.renderNode(value, expanded, this);
+      }
+    };
+    renderer.setFont(EditorColorsManager.getInstance().getGlobalScheme().getFont(EditorFontType.PLAIN));
+
+    mySchemasTree.setCellRenderer(renderer);
+    MouseAdapter mouseAdapter = new MouseAdapter() {
+      @Override
+      public void mouseClicked(MouseEvent e) {
+        if (e.getClickCount() > 1 && isOKActionEnabled()) {
+          doOKAction();
+        }
+      }
+    };
+    mySchemasTree.addMouseListener(mouseAdapter);
+
+    myUri.getDocument().addDocumentListener(new DocumentAdapter() {
+      @Override
+      protected void textChanged(DocumentEvent e) {
+        validateInput();
+      }
+    });
+    mySchemasTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
+      @Override
+      public void valueChanged(TreeSelectionEvent e) {
+        validateInput();
+      }
+    });
+
+    myExplorer = new FileSystemTreeImpl(project, new FileChooserDescriptor(true, false, false, false, true, false));
+
+    myExplorer.addListener(new FileSystemTree.Listener() {
+      @Override
+      public void selectionChanged(List<VirtualFile> selection) {
+        validateInput();
+      }
+    }, myExplorer);
+    myExplorer.getTree().addMouseListener(mouseAdapter);
+
+    myExplorerPanel.add(ScrollPaneFactory.createScrollPane(myExplorer.getTree()), BorderLayout.CENTER);
+
+    AnAction actionGroup = ActionManager.getInstance().getAction("FileChooserToolbar");
+    ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, (ActionGroup)actionGroup, true);
+    toolbar.setTargetComponent(myExplorerPanel);
+    myExplorerPanel.add(toolbar.getComponent(), BorderLayout.NORTH);
+
+    PsiFile schema = null;
+    if (file != null) {
+      schema = XmlUtil.findNamespaceByLocation(file, uri);
+    }
+    else if (location != null) {
+      VirtualFile virtualFile = VfsUtil.findRelativeFile(location, null);
+      if (virtualFile != null) {
+        schema = PsiManager.getInstance(project).findFile(virtualFile);
+      }
+    }
+
+    if (schema != null) {
+      DefaultMutableTreeNode node = TreeUtil.findNodeWithObject(root, schema);
+      if (node != null) {
+        TreeUtil.selectNode(mySchemasTree, node);
+      }
+      myExplorer.select(schema.getVirtualFile(), null);
+    }
+
+    int index = PropertiesComponent.getInstance().getOrInitInt(MAP_EXTERNAL_RESOURCE_SELECTED_TAB, 0);
+    myTabs.setSelectedIndex(index);
+    myTabs.getModel().addChangeListener(new ChangeListener() {
+      @Override
+      public void stateChanged(ChangeEvent e) {
+        PropertiesComponent.getInstance().setValue(MAP_EXTERNAL_RESOURCE_SELECTED_TAB, Integer.toString(myTabs.getSelectedIndex()));
+      }
+    });
+    init();
+  }
+
+  @Override
+  protected void processDoNotAskOnOk(int exitCode) {
+    super.processDoNotAskOnOk(exitCode);
+    // store it since explorer will be disposed
+    myLocation = getResourceLocation();
+  }
+
+  private void validateInput() {
+    setOKActionEnabled(!StringUtil.isEmpty(myUri.getText()) && getResourceLocation() != null);
+  }
+
+  @Override
+  protected JComponent createCenterPanel() {
+    return myMainPanel;
+  }
+
+  @Override
+  public JComponent getPreferredFocusedComponent() {
+    return StringUtil.isEmpty(myUri.getText()) ? myUri : mySchemasTree;
+  }
+
+  public String getUri() {
+    return myUri.getText();
+  }
+
+  @Nullable
+  public String getResourceLocation() {
+    if (myLocation != null) return myLocation;
+
+    if (myTabs.getSelectedIndex() == 0) {
+      TreePath path = mySchemasTree.getSelectionPath();
+      if (path == null) return null;
+      Object object = ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+      if (!(object instanceof PsiFile)) return null;
+      return FileUtil.toSystemIndependentName(((PsiFile)object).getVirtualFile().getPath());
+    }
+    else {
+      VirtualFile file = myExplorer.getSelectedFile();
+      return file == null ? null : FileUtil.toSystemIndependentName(file.getPath());
+    }
+  }
+
+  private void createUIComponents() {
+    myExplorerPanel = new JBPanel(new BorderLayout()) {
+      @Override
+      public void calcData(DataKey key, DataSink sink) {
+        if (key == PlatformDataKeys.VIRTUAL_FILE_ARRAY) {
+          sink.put(PlatformDataKeys.VIRTUAL_FILE_ARRAY, myExplorer.getSelectedFiles());
+        }
+        else if (key == FileSystemTree.DATA_KEY) {
+          sink.put(FileSystemTree.DATA_KEY, myExplorer);
+        }
+      }
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/NameLocationPair.java b/xml/impl/src/com/intellij/javaee/NameLocationPair.java
new file mode 100644
index 0000000..724d2a5
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/NameLocationPair.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+/**
+* @author Dmitry Avdeev
+*         Date: 7/18/12
+*/
+public class NameLocationPair implements Comparable {
+  String myName;
+  String myLocation;
+  boolean myShared;
+
+  public NameLocationPair(String name, String location, boolean shared) {
+    myName = name;
+    myLocation = location;
+    myShared = shared;
+  }
+
+  public int compareTo(Object o) {
+    return myName.compareTo(((NameLocationPair)o).myName);
+  }
+
+  public boolean equals(Object obj) {
+    if (! (obj instanceof NameLocationPair)) return false;
+    return compareTo(obj) == 0;
+  }
+
+  public int hashCode() {
+    return myName.hashCode();
+  }
+
+  public String getName() {
+    return myName;
+  }
+
+  public String getLocation(){
+    return myLocation;
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/ProjectResources.java b/xml/impl/src/com/intellij/javaee/ProjectResources.java
new file mode 100644
index 0000000..7bf3a03
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/ProjectResources.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.application.options.PathMacrosImpl;
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
+import com.intellij.openapi.components.StoragePathMacros;
+import com.intellij.openapi.util.JDOMExternalizableAdapter;
+import org.jdom.Element;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+* @author Dmitry Avdeev
+*/
+@State(name = "ProjectResources", storages = {@Storage( file = StoragePathMacros.PROJECT_FILE)})
+public class ProjectResources extends ExternalResourceManagerImpl implements PersistentStateComponent<Element> {
+
+  private final JDOMExternalizableAdapter myAdapter;
+
+  public ProjectResources(PathMacrosImpl pathMacros) {
+    super(pathMacros);
+    myAdapter = new JDOMExternalizableAdapter(this, "ProjectResources");
+  }
+
+  @Override
+  protected Map<String, Map<String, Resource>> computeStdResources() {
+    return Collections.emptyMap();   
+  }
+
+  public Element getState() {
+    return myAdapter.getState();
+  }
+
+  public void loadState(Element state) {
+    myAdapter.loadState(state);
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/PsiExternalResourceNotifier.java b/xml/impl/src/com/intellij/javaee/PsiExternalResourceNotifier.java
new file mode 100644
index 0000000..30fa2e2
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/PsiExternalResourceNotifier.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.Disposable;
+import com.intellij.psi.impl.PsiManagerEx;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class PsiExternalResourceNotifier extends AbstractProjectComponent {
+  private final PsiManagerEx myPsiManager;
+  private final ExternalResourceManagerEx myExternalResourceManager;
+  private final DaemonCodeAnalyzer myDaemonCodeAnalyzer;
+
+  public PsiExternalResourceNotifier(PsiManagerEx psiManager, ExternalResourceManager externalResourceManager,
+                                     final DaemonCodeAnalyzer daemonCodeAnalyzer, Project project) {
+    super(project);
+    myPsiManager = psiManager;
+    myExternalResourceManager = (ExternalResourceManagerEx)externalResourceManager;
+    myDaemonCodeAnalyzer = daemonCodeAnalyzer;
+    final ExternalResourceListener myExternalResourceListener = new MyExternalResourceListener();
+    myExternalResourceManager.addExternalResourceListener(myExternalResourceListener);
+    Disposer.register(project, new Disposable() {
+      public void dispose() {
+        myExternalResourceManager.removeExternalResourceListener(myExternalResourceListener);
+      }
+    });
+  }
+
+  @NotNull
+  public String getComponentName() {
+    return "PsiExternalResourceNotifier";
+  }
+
+  private class MyExternalResourceListener implements ExternalResourceListener {
+    public void externalResourceChanged() {
+      myPsiManager.beforeChange(true);
+      myDaemonCodeAnalyzer.restart();
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/ResourceRegistrarImpl.java b/xml/impl/src/com/intellij/javaee/ResourceRegistrarImpl.java
new file mode 100644
index 0000000..a13d933
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/ResourceRegistrarImpl.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.javaee;
+
+import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class ResourceRegistrarImpl implements ResourceRegistrar {
+
+  private final Map<String, Map<String, ExternalResourceManagerImpl.Resource>> myResources = new HashMap<String, Map<String, ExternalResourceManagerImpl.Resource>>();
+  private final List<String> myIgnored = new ArrayList<String>();
+
+  public void addStdResource(@NonNls String resource, @NonNls String fileName) {
+    addStdResource(resource, null, fileName, getClass());
+  }
+
+  public void addStdResource(@NonNls String resource, @NonNls String fileName, Class klass) {
+    addStdResource(resource, null, fileName, klass);
+  }
+
+  public void addStdResource(@NonNls String resource, @NonNls String version, @NonNls String fileName, @Nullable Class klass, @Nullable ClassLoader classLoader) {
+    final Map<String, ExternalResourceManagerImpl.Resource> map = ExternalResourceManagerImpl.getMap(myResources, version, true);
+    assert map != null;
+    ExternalResourceManagerImpl.Resource res = new ExternalResourceManagerImpl.Resource();
+    res.file = fileName;
+    res.classLoader = classLoader;
+    res.clazz = klass;
+    map.put(resource, res);
+  }
+
+  public void addStdResource(@NonNls String resource, @Nullable @NonNls String version, @NonNls String fileName, Class klass) {
+    addStdResource(resource, version, fileName, klass, null);
+  }
+
+  public void addIgnoredResource(@NonNls String url) {
+    myIgnored.add(url);
+  }
+
+  public void addInternalResource(@NonNls String resource, @NonNls String fileName) {
+    addInternalResource(resource, null, fileName, getClass());
+  }
+
+  public void addInternalResource(@NonNls String resource, @NonNls String fileName, Class clazz) {
+    addInternalResource(resource, null, fileName, clazz);
+  }
+
+  public void addInternalResource(@NonNls String resource, @NonNls String version, @NonNls String fileName) {
+    addInternalResource(resource, version, fileName, getClass());
+  }
+
+  public void addInternalResource(@NonNls String resource, @Nullable @NonNls String version, @NonNls String fileName, @Nullable Class clazz) {
+    addStdResource(resource, version, ExternalResourceManagerImpl.STANDARD_SCHEMAS + fileName, clazz);
+  }
+
+  public Map<String, Map<String, ExternalResourceManagerImpl.Resource>> getResources() {
+    return myResources;
+  }
+
+  public List<String> getIgnored() {
+    return myIgnored;
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.form b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.form
new file mode 100644
index 0000000..660dca5
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.form
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.javaee.XMLCatalogConfigurable">
+  <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="500" height="46"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="5b144" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text value="Catalog property file:"/>
+        </properties>
+      </component>
+      <component id="b541d" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myPropertyFile">
+        <constraints>
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+      </component>
+      <vspacer id="fd213">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+        </constraints>
+      </vspacer>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java
new file mode 100644
index 0000000..614636b
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.options.BaseConfigurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.Nls;
+
+import javax.swing.*;
+
+/**
+ * @author Dmitry Avdeev
+ *         Date: 7/20/12
+ */
+public class XMLCatalogConfigurable extends BaseConfigurable {
+
+  private TextFieldWithBrowseButton myPropertyFile;
+  private JPanel myPanel;
+
+  public XMLCatalogConfigurable() {
+    myPropertyFile.addBrowseFolderListener("XML Catalog Properties File", null, null,
+                                           new FileChooserDescriptor(true, false, false, false, false, false));
+  }
+
+  @Nls
+  @Override
+  public String getDisplayName() {
+    return "XML Catalog";
+  }
+
+  @Override
+  public String getHelpTopic() {
+    return "XML.Catalog.Dialog";
+  }
+
+  @Override
+  public JComponent createComponent() {
+    return myPanel;
+  }
+
+  @Override
+  public JComponent getPreferredFocusedComponent() {
+    return myPropertyFile.getTextField();
+  }
+
+  @Override
+  public void apply() throws ConfigurationException {
+    ExternalResourceManagerEx.getInstanceEx().setCatalogPropertiesFile(myPropertyFile.getText());
+  }
+
+  @Override
+  public void reset() {
+    myPropertyFile.setText(ExternalResourceManagerEx.getInstanceEx().getCatalogPropertiesFile());
+  }
+
+  @Override
+  public boolean isModified() {
+    return !StringUtil.notNullize(ExternalResourceManagerEx.getInstanceEx().getCatalogPropertiesFile()).equals(myPropertyFile.getText());
+  }
+
+  @Override
+  public void disposeUIResources() {
+
+  }
+}
diff --git a/xml/impl/src/com/intellij/javaee/XMLCatalogManager.java b/xml/impl/src/com/intellij/javaee/XMLCatalogManager.java
new file mode 100644
index 0000000..c9eacea
--- /dev/null
+++ b/xml/impl/src/com/intellij/javaee/XMLCatalogManager.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.javaee;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import org.apache.xml.resolver.Catalog;
+import org.apache.xml.resolver.CatalogManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.lang.reflect.Field;
+import java.util.PropertyResourceBundle;
+
+/**
+ * @author Dmitry Avdeev
+ *         Date: 7/20/12
+ */
+public class XMLCatalogManager {
+
+  private final static Logger LOG = Logger.getInstance(XMLCatalogManager.class);
+
+  private static Field ourResources;
+  private static Field ourPropertyFileUri;
+
+  static {
+    try {
+      ourResources = CatalogManager.class.getDeclaredField("resources");
+      ourResources.setAccessible(true);
+      ourPropertyFileUri = CatalogManager.class.getDeclaredField("propertyFileURI");
+      ourPropertyFileUri.setAccessible(true);
+    }
+    catch (NoSuchFieldException e) {
+      LOG.error(e);
+    }
+  }
+
+  private final CatalogManager myManager = new CatalogManager();
+
+  public XMLCatalogManager(@NotNull String propertiesFilePath) {
+
+    File file = new File(propertiesFilePath);
+    try {
+      String s = FileUtil.loadFile(file);
+      PropertyResourceBundle bundle = new PropertyResourceBundle(new StringReader(s));
+      ourResources.set(myManager, bundle);
+      ourPropertyFileUri.set(myManager, file.toURI().toURL());
+    }
+    catch (IllegalAccessException e) {
+      LOG.error(e);
+    }
+    catch (IOException e) {
+      LOG.warn(e);
+    }
+  }
+
+  @Nullable
+  public String resolve(String uri) {
+    try {
+      Catalog catalog = myManager.getCatalog();
+      if (catalog == null) return null;
+      String resolved = catalog.resolveSystem(uri);
+      return resolved == null ? catalog.resolvePublic(uri, null) : resolved;
+    }
+    catch (IOException e) {
+      LOG.warn(e);
+      return null;
+    }
+  }
+
+  @TestOnly
+  public CatalogManager getManager() {
+    return myManager;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/HtmlInlineScriptTokenTypesProvider.java b/xml/impl/src/com/intellij/lang/HtmlInlineScriptTokenTypesProvider.java
new file mode 100644
index 0000000..b72c2e7
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/HtmlInlineScriptTokenTypesProvider.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang;
+
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.psi.tree.IElementType;
+
+public interface HtmlInlineScriptTokenTypesProvider {
+  IElementType getElementType();
+
+  FileType getFileType();
+}
diff --git a/xml/impl/src/com/intellij/lang/HtmlScriptContentProvider.java b/xml/impl/src/com/intellij/lang/HtmlScriptContentProvider.java
new file mode 100644
index 0000000..92bf644
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/HtmlScriptContentProvider.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang;
+
+import com.intellij.lexer.Lexer;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.Nullable;
+
+public interface HtmlScriptContentProvider {
+  /**
+   * @return instance of the <code>com.intellij.psi.tree.IElementType</code> to use in html script tag
+   */
+  IElementType getScriptElementType();
+
+  /**
+   * @return highlighting lexer to use in html script tag
+   */
+  @Nullable
+  Lexer getHighlightingLexer();
+}
diff --git a/xml/impl/src/com/intellij/lang/LanguageHtmlInlineScriptTokenTypesProvider.java b/xml/impl/src/com/intellij/lang/LanguageHtmlInlineScriptTokenTypesProvider.java
new file mode 100644
index 0000000..8b8c557
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/LanguageHtmlInlineScriptTokenTypesProvider.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang;
+
+import org.jetbrains.annotations.Nullable;
+
+public class LanguageHtmlInlineScriptTokenTypesProvider extends LanguageExtension<HtmlInlineScriptTokenTypesProvider> {
+  public final static LanguageHtmlInlineScriptTokenTypesProvider INSTANCE = new LanguageHtmlInlineScriptTokenTypesProvider();
+
+  public LanguageHtmlInlineScriptTokenTypesProvider() {
+    super("com.intellij.html.inlineScriptTokenTypesProvider");
+  }
+
+  @Nullable
+  public static HtmlInlineScriptTokenTypesProvider getInlineScriptProvider(@Nullable Language language) {
+    return language == null ? null : INSTANCE.forLanguage(language);
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/LanguageHtmlScriptContentProvider.java b/xml/impl/src/com/intellij/lang/LanguageHtmlScriptContentProvider.java
new file mode 100644
index 0000000..7767649
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/LanguageHtmlScriptContentProvider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang;
+
+import org.jetbrains.annotations.NotNull;
+
+public class LanguageHtmlScriptContentProvider extends LanguageExtension<HtmlScriptContentProvider> {
+  public final static LanguageHtmlScriptContentProvider INSTANCE = new LanguageHtmlScriptContentProvider();
+
+  public LanguageHtmlScriptContentProvider() {
+    super("com.intellij.html.scriptContentProvider");
+  }
+
+  public static HtmlScriptContentProvider getScriptContentProvider(@NotNull Language language) {
+    return INSTANCE.forLanguage(language);
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/dtd/DTDLanguage.java b/xml/impl/src/com/intellij/lang/dtd/DTDLanguage.java
new file mode 100644
index 0000000..29ce449
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/dtd/DTDLanguage.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.dtd;
+
+import com.intellij.ide.highlighter.XmlFileHighlighter;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.fileTypes.SingleLazyInstanceSyntaxHighlighterFactory;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class DTDLanguage extends XMLLanguage {
+
+  public static final DTDLanguage INSTANCE = new DTDLanguage();
+
+  protected DTDLanguage() {
+    super(XMLLanguage.INSTANCE, "DTD", "text/dtd", "text/x-dtd");
+    SyntaxHighlighterFactory.LANGUAGE_FACTORY.addExplicitExtension(this, new SingleLazyInstanceSyntaxHighlighterFactory() {
+      @NotNull
+      protected SyntaxHighlighter createHighlighter() {
+        return new XmlFileHighlighter(true);
+      }
+    });
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/dtd/DTDParserDefinition.java b/xml/impl/src/com/intellij/lang/dtd/DTDParserDefinition.java
new file mode 100644
index 0000000..541aa16
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/dtd/DTDParserDefinition.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.dtd;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.LanguageUtil;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.PsiParser;
+import com.intellij.lang.xml.XMLParserDefinition;
+import com.intellij.lexer.DtdLexer;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.parsing.xml.DtdParsing;
+import com.intellij.psi.impl.source.xml.XmlFileImpl;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.IFileElementType;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlEntityDecl;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class DTDParserDefinition extends XMLParserDefinition {
+  public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
+    return LanguageUtil.canStickTokensTogetherByLexer(left, right, new DtdLexer(false));
+  }
+
+  public PsiFile createFile(FileViewProvider viewProvider) {
+    return new XmlFileImpl(viewProvider, XmlElementType.DTD_FILE);
+  }
+
+  @NotNull
+  @Override
+  public PsiParser createParser(Project project) {
+    return new PsiParser() {
+      @NotNull
+      @Override
+      public ASTNode parse(IElementType root, PsiBuilder builder) {
+        return new DtdParsing(root, XmlEntityDecl.EntityContextType.GENERIC_XML, builder).parse();
+      }
+    };
+  }
+
+  @Override
+  public IFileElementType getFileNodeType() {
+    return XmlElementType.DTD_FILE;
+  }
+
+  @NotNull
+  @Override
+  public Lexer createLexer(Project project) {
+    return new DtdLexer(false);
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/dtd/DtdStructureViewBuilderFactory.java b/xml/impl/src/com/intellij/lang/dtd/DtdStructureViewBuilderFactory.java
new file mode 100644
index 0000000..f88cafe
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/dtd/DtdStructureViewBuilderFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.dtd;
+
+import com.intellij.ide.structureView.StructureViewBuilder;
+import com.intellij.ide.structureView.StructureViewModel;
+import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
+import com.intellij.ide.structureView.impl.xml.XmlStructureViewTreeModel;
+import com.intellij.lang.PsiStructureViewFactory;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import org.jetbrains.annotations.NotNull;
+
+public class DtdStructureViewBuilderFactory implements PsiStructureViewFactory {
+  @NotNull
+  public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) {
+    return new TreeBasedStructureViewBuilder() {
+      @NotNull
+      public StructureViewModel createStructureViewModel() {
+        return new XmlStructureViewTreeModel((XmlFile)psiFile);
+      }
+    };
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/lang/html/HTMLLanguage.java b/xml/impl/src/com/intellij/lang/html/HTMLLanguage.java
new file mode 100644
index 0000000..4c4cbca
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/HTMLLanguage.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.html;
+
+import com.intellij.ide.highlighter.HtmlFileHighlighter;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.fileTypes.SingleLazyInstanceSyntaxHighlighterFactory;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
+import com.intellij.psi.impl.source.xml.XmlPsiPolicy;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class HTMLLanguage extends XMLLanguage {
+
+  public static final HTMLLanguage INSTANCE = new HTMLLanguage();
+
+  private HTMLLanguage() {
+    super(XMLLanguage.INSTANCE, "HTML", "text/html", "text/htmlh");
+    SyntaxHighlighterFactory.LANGUAGE_FACTORY.addExplicitExtension(this, new SingleLazyInstanceSyntaxHighlighterFactory() {
+      @NotNull
+      protected SyntaxHighlighter createHighlighter() {
+        return new HtmlFileHighlighter();
+      }
+    });
+
+  }
+
+  public XmlPsiPolicy getPsiPolicy() {
+    return ENCODE_EACH_SYMBOL_POLICY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/html/HTMLParser.java b/xml/impl/src/com/intellij/lang/html/HTMLParser.java
new file mode 100644
index 0000000..e4f89c6
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/HTMLParser.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.html;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.PsiParser;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+
+public class HTMLParser implements PsiParser {
+
+  @NotNull
+  public ASTNode parse(final IElementType root, final PsiBuilder builder) {
+    builder.enforceCommentTokens(TokenSet.EMPTY);
+    final PsiBuilder.Marker file = builder.mark();
+    new HtmlParsing(builder).parseDocument();
+    file.done(root);
+    return builder.getTreeBuilt();
+  }
+
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/lang/html/HTMLParserDefinition.java b/xml/impl/src/com/intellij/lang/html/HTMLParserDefinition.java
new file mode 100644
index 0000000..13b0dcc
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/HTMLParserDefinition.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.html;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.ParserDefinition;
+import com.intellij.lang.PsiParser;
+import com.intellij.lang.xml.XMLParserDefinition;
+import com.intellij.lexer.HtmlLexer;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.html.HtmlFileImpl;
+import com.intellij.psi.tree.IFileElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class HTMLParserDefinition implements ParserDefinition {
+  @NotNull
+  public Lexer createLexer(Project project) {
+    return new HtmlLexer();
+  }
+
+  public IFileElementType getFileNodeType() {
+    return XmlElementType.HTML_FILE;
+  }
+
+  @NotNull
+  public TokenSet getWhitespaceTokens() {
+    return XmlTokenType.WHITESPACES;
+  }
+
+  @NotNull
+  public TokenSet getCommentTokens() {
+    return XmlTokenType.COMMENTS;
+  }
+
+  @NotNull
+  public TokenSet getStringLiteralElements() {
+    return TokenSet.EMPTY;
+  }
+
+  @NotNull
+  public PsiParser createParser(final Project project) {
+    return new HTMLParser();
+  }
+
+  @NotNull
+  public PsiElement createElement(ASTNode node) {
+    return PsiUtilCore.NULL_PSI_ELEMENT;
+  }
+
+  public PsiFile createFile(FileViewProvider viewProvider) {
+    return new HtmlFileImpl(viewProvider);
+  }
+
+  public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
+    final Lexer lexer = createLexer(left.getPsi().getProject());
+    return XMLParserDefinition.canStickTokensTogetherByLexerInXml(left, right, lexer, 0);
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/html/HtmlFormattingModelBuilder.java b/xml/impl/src/com/intellij/lang/html/HtmlFormattingModelBuilder.java
new file mode 100644
index 0000000..1b004ec
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/HtmlFormattingModelBuilder.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.html;
+
+import com.intellij.formatting.FormattingModel;
+import com.intellij.formatting.FormattingModelBuilder;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.formatter.FormattingDocumentModelImpl;
+import com.intellij.psi.formatter.xml.HtmlPolicy;
+import com.intellij.psi.formatter.xml.XmlBlock;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.lang.xml.XmlFormattingModel;
+import org.jetbrains.annotations.NotNull;
+
+public class HtmlFormattingModelBuilder implements FormattingModelBuilder {
+  @NotNull
+    public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) {
+    final PsiFile psiFile = element.getContainingFile();
+    final FormattingDocumentModelImpl documentModel = FormattingDocumentModelImpl.createOn(psiFile);
+    return new XmlFormattingModel(psiFile,
+                                                           new XmlBlock(SourceTreeToPsiMap.psiElementToTree(psiFile),
+                                                                        null, null, new HtmlPolicy(settings, documentModel), null, null, false),
+                                                           documentModel);
+  }
+
+  public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/lang/html/HtmlParsing.java b/xml/impl/src/com/intellij/lang/html/HtmlParsing.java
new file mode 100644
index 0000000..e500762
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/HtmlParsing.java
@@ -0,0 +1,618 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.html;
+
+import com.intellij.codeInsight.completion.CompletionUtil;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.psi.impl.source.codeStyle.IndentHelperImpl;
+import com.intellij.psi.tree.CustomParsingType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.ILazyParseableElementType;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.containers.Stack;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class HtmlParsing {
+  @NonNls private static final String TR_TAG = "tr";
+  @NonNls private static final String TD_TAG = "td";
+  @NonNls private static final String DD_TAG = "dd";
+  @NonNls private static final String DT_TAG = "dt";
+  @NonNls private static final String TABLE_TAG = "table";
+
+  private final PsiBuilder myBuilder;
+  private final Stack<String> myTagNamesStack = new Stack<String>();
+  private final Stack<PsiBuilder.Marker> myTagMarkersStack = new Stack<PsiBuilder.Marker>();
+  @NonNls private static final String COMPLETION_NAME = CompletionUtil.DUMMY_IDENTIFIER_TRIMMED.toLowerCase();
+
+  public HtmlParsing(final PsiBuilder builder) {
+    myBuilder = builder;
+  }
+
+  public void parseDocument() {
+    final PsiBuilder.Marker document = mark();
+
+    while (token() == XmlTokenType.XML_COMMENT_START) {
+      parseComment();
+    }
+
+    parseProlog();
+
+    PsiBuilder.Marker error = null;
+    while (!eof()) {
+      final IElementType tt = token();
+      if (tt == XmlTokenType.XML_START_TAG_START) {
+        error = flushError(error);
+        parseTag("");
+        myTagMarkersStack.clear();
+        myTagNamesStack.clear();
+      }
+      else if (tt == XmlTokenType.XML_COMMENT_START) {
+        error = flushError(error);
+        parseComment();
+      }
+      else if (tt == XmlTokenType.XML_PI_START) {
+        error = flushError(error);
+        parseProcessingInstruction();
+      }
+      else if (tt == XmlTokenType.XML_REAL_WHITE_SPACE || tt == XmlTokenType.XML_CHAR_ENTITY_REF || tt == XmlTokenType.XML_DATA_CHARACTERS) {
+        error = flushError(error);
+        advance();
+      } else if (tt == XmlTokenType.XML_END_TAG_START) {
+        final PsiBuilder.Marker tagEndError = myBuilder.mark();
+
+        advance();
+        if (token() == XmlTokenType.XML_NAME) {
+          advance();
+          if (token() == XmlTokenType.XML_TAG_END) {
+            advance();
+          }
+        }
+
+        tagEndError.error(XmlErrorMessages.message("xml.parsing.closing.tag.matches.nothing"));
+      }
+      else {
+        if (error == null) error = mark();
+        advance();
+      }
+    }
+
+    if (error != null) {
+      error.error(XmlErrorMessages.message("top.level.element.is.not.completed"));
+      error = null;
+    }
+
+    document.done(XmlElementType.HTML_DOCUMENT);
+  }
+
+  @Nullable
+  private static PsiBuilder.Marker flushError(PsiBuilder.Marker error) {
+    if (error != null) {
+      error.error(XmlErrorMessages.message("xml.parsing.unexpected.tokens"));
+      error = null;
+    }
+    return error;
+  }
+
+  private void parseDoctype() {
+    assert token() == XmlTokenType.XML_DOCTYPE_START : "Doctype start expected";
+    final PsiBuilder.Marker doctype = mark();
+    advance();
+
+    while (token() != XmlTokenType.XML_DOCTYPE_END && !eof()) advance();
+    if (eof()) {
+      error(XmlErrorMessages.message("xml.parsing.unexpected.end.of.file"));
+    }
+    else {
+      advance();
+    }
+
+    doctype.done(XmlElementType.XML_DOCTYPE);
+  }
+
+  private static boolean ddordt(String name) {
+    return DT_TAG.equals(name) || DD_TAG.equals(name);
+  }
+
+  private boolean parseTag(String parentName) {
+    assert token() == XmlTokenType.XML_START_TAG_START : "Tag start expected";
+    final PsiBuilder.Marker tag = mark();
+    myTagMarkersStack.push(tag);
+
+    // Start tag header
+    advance();
+    final String originalTagName;
+    if (token() != XmlTokenType.XML_NAME) {
+      error(XmlErrorMessages.message("xml.parsing.tag.name.expected"));
+      originalTagName = "";
+    }
+    else {
+      originalTagName = myBuilder.getTokenText();
+      advance();
+    }
+
+    String tagName = originalTagName.toLowerCase();
+    if ((ddordt(tagName) && ddordt(parentName)) ||
+        (tagName.equals(parentName) && HtmlUtil.isOptionalEndForHtmlTagL(tagName)) ||
+        myTagMarkersStack.size() > MAGIC_FRAME_COUNT // no chance for evil guys wanting us to have stack overflow
+       ) {
+      tag.rollbackTo();
+      myTagMarkersStack.pop();
+      return false;
+    }
+
+    myTagNamesStack.push(tagName);
+
+    boolean freeMakerTag = tagName.length() > 0 && '#' == tagName.charAt(0);
+
+    do {
+      final IElementType tt = token();
+      if (freeMakerTag) {
+        if (tt == XmlTokenType.XML_EMPTY_ELEMENT_END ||
+            tt == XmlTokenType.XML_TAG_END ||
+            tt == XmlTokenType.XML_END_TAG_START ||
+            tt == XmlTokenType.XML_START_TAG_START) break;
+        advance();
+      }
+      else {
+        if (tt == XmlTokenType.XML_NAME) {
+          parseAttribute();
+        }
+        else if (tt == XmlTokenType.XML_CHAR_ENTITY_REF || tt == XmlTokenType.XML_ENTITY_REF_TOKEN) {
+          parseReference();
+        }
+        else {
+          break;
+        }
+      }
+    }
+    while (!eof());
+
+    if (token() == XmlTokenType.XML_EMPTY_ELEMENT_END) {
+      advance();
+      tag.done(XmlElementType.HTML_TAG);
+      return true;
+    }
+
+    if (token() == XmlTokenType.XML_TAG_END) {
+      advance();
+    }
+    else {
+      error(XmlErrorMessages.message("tag.start.is.not.closed"));
+      tag.done(XmlElementType.HTML_TAG);
+      return true;
+    }
+
+    if (HtmlUtil.isSingleHtmlTagL(tagName)) {
+      final PsiBuilder.Marker footer = mark();
+      if (token() == XmlTokenType.XML_END_TAG_START) {
+        advance();
+        if (token() == XmlTokenType.XML_NAME) {
+          if (tagName.equalsIgnoreCase(myBuilder.getTokenText())) {
+            advance();
+            footer.drop();
+            if (token() == XmlTokenType.XML_TAG_END) {
+              advance();
+            }
+            tag.done(XmlElementType.HTML_TAG);
+            return true;
+          }
+        }
+      }
+
+      footer.rollbackTo();
+      tag.done(XmlElementType.HTML_TAG);
+      return true;
+    }
+
+    // Done header, start content
+
+    boolean isInlineTagContainer = HtmlUtil.isInlineTagContainerL(tagName);
+    boolean isOptionalTagEnd = HtmlUtil.isOptionalEndForHtmlTagL(tagName);
+
+    PsiBuilder.Marker firstBlockChild = null;
+
+    PsiBuilder.Marker xmlText = null;
+    while (!eof()) {
+      final IElementType tt = token();
+      if (tt == XmlTokenType.XML_START_TAG_START) {
+        xmlText = terminateText(xmlText);
+        if (!parseTag(tagName)) {
+          tag.done(XmlElementType.HTML_TAG);
+          return true;
+        }
+
+        PsiBuilder.Marker childMarker = myTagMarkersStack.pop();
+        String childName = myTagNamesStack.pop();
+
+        if (isOptionalTagEnd) {
+          boolean foundMatch = childTerminatesParentInStack(childName, true);
+          if (foundMatch) {
+            myTagMarkersStack.pop();
+            myTagNamesStack.pop();
+
+            myTagMarkersStack.push(childMarker);
+            myTagNamesStack.push(childName);
+
+            tag.doneBefore(XmlElementType.HTML_TAG, childMarker);
+            return true;
+          }
+        }
+
+
+        if (isInlineTagContainer && HtmlUtil.isHtmlBlockTagL(childName) && isOptionalTagEnd && !HtmlUtil.isPossiblyInlineTag(childName)) {
+          tag.doneBefore(XmlElementType.HTML_TAG, childMarker);
+          return true;
+        }
+        else if (isOptionalTagEnd && firstBlockChild == null && HtmlUtil.isHtmlBlockTagL(childName) && !HtmlUtil.isHtmlBlockTagL(tagName) && canTerminate(childName, tagName)) {
+          firstBlockChild = childMarker;
+        }
+      }
+      else if (tt == XmlTokenType.XML_PI_START) {
+        xmlText = terminateText(xmlText);
+        parseProcessingInstruction();
+      }
+      else if (tt == XmlTokenType.XML_ENTITY_REF_TOKEN) {
+        xmlText = terminateText(xmlText);
+        parseReference();
+      }
+      else if (tt == XmlTokenType.XML_CHAR_ENTITY_REF) {
+        xmlText = startText(xmlText);
+        parseReference();
+      }
+      else if (tt == XmlTokenType.XML_CDATA_START) {
+        xmlText = startText(xmlText);
+        parseCData();
+      }
+      else if (tt == XmlTokenType.XML_COMMENT_START) {
+        xmlText = startText(xmlText);
+        parseComment();
+      }
+      else if (tt == XmlTokenType.XML_BAD_CHARACTER) {
+        xmlText = startText(xmlText);
+        final PsiBuilder.Marker error = mark();
+        advance();
+        error.error(XmlErrorMessages.message("unescaped.ampersand.or.nonterminated.character.entity.reference"));
+      }
+      else if (tt instanceof CustomParsingType || tt instanceof ILazyParseableElementType) {
+        xmlText = terminateText(xmlText);
+        advance();
+      }
+      else if (token() == XmlTokenType.XML_END_TAG_START) {
+        xmlText = terminateText(xmlText);
+        final PsiBuilder.Marker footer = mark();
+        advance();
+
+        if (token() == XmlTokenType.XML_NAME) {
+          String endName = myBuilder.getTokenText().toLowerCase();
+          if (!tagName.equals(endName) && !endName.endsWith(COMPLETION_NAME)) {
+            final boolean hasChancesToMatch = HtmlUtil.isOptionalEndForHtmlTagL(endName) ? childTerminatesParentInStack(endName, false) : myTagNamesStack.contains(endName);
+            if (hasChancesToMatch) {
+              footer.rollbackTo();
+              if (isOptionalTagEnd) {
+                if (firstBlockChild != null) {
+                  tag.doneBefore(XmlElementType.HTML_TAG, firstBlockChild);
+                }
+                else {
+                  tag.done(XmlElementType.HTML_TAG);
+                }
+              }
+              else {
+                error(XmlErrorMessages.message("named.element.is.not.closed", originalTagName));
+                tag.done(XmlElementType.HTML_TAG);
+              }
+              return true;
+            }
+            else {
+              advance();
+              if (token() == XmlTokenType.XML_TAG_END) advance();
+              footer.error(XmlErrorMessages.message("xml.parsing.closing.tag.matches.nothing"));
+              continue;
+            }
+          }
+
+          advance();
+
+          while (token() != XmlTokenType.XML_TAG_END && token() != XmlTokenType.XML_START_TAG_START && token() != XmlTokenType.XML_END_TAG_START && !eof()) {
+            error(XmlErrorMessages.message("xml.parsing.unexpected.token"));
+            advance();
+          }
+        }
+        else {
+          error(XmlErrorMessages.message("xml.parsing.closing.tag.name.missing"));
+        }
+        footer.drop();
+
+        if (token() == XmlTokenType.XML_TAG_END) {
+          advance();
+        }
+        else {
+          error(XmlErrorMessages.message("xml.parsing.closing.tag.is.not.done"));
+        }
+
+        tag.done(XmlElementType.HTML_TAG);
+        return true;
+      }
+      else {
+        xmlText = startText(xmlText);
+        advance();
+      }
+    }
+
+    xmlText = terminateText(xmlText);
+
+    if (isOptionalTagEnd || "body".equalsIgnoreCase(tagName) || "html".equalsIgnoreCase(tagName)) {
+      if (firstBlockChild != null) {
+        tag.doneBefore(XmlElementType.HTML_TAG, firstBlockChild);
+      }
+      else {
+        tag.done(XmlElementType.HTML_TAG);
+      }
+    }
+    else {
+      error(XmlErrorMessages.message("named.element.is.not.closed", originalTagName));
+      tag.done(XmlElementType.HTML_TAG);
+    }
+
+    return true;
+  }
+
+  private static boolean canTerminate(final String childTagName,final String tagName) {
+    // TODO: make hash
+    return !(tagName.equalsIgnoreCase(TR_TAG) && childTagName.equalsIgnoreCase(TD_TAG)) ||
+           (tagName.equalsIgnoreCase(TABLE_TAG) && childTagName.equalsIgnoreCase(TR_TAG));
+  }
+
+  private boolean childTerminatesParentInStack(final String childName, final boolean terminateOnNonOptionalTag) {
+    boolean isTD = TD_TAG.equals(childName);
+    boolean isTR = TR_TAG.equals(childName);
+
+    for (int i = myTagNamesStack.size() - 1; i >= 0; i--) {
+      String parentName = myTagNamesStack.get(i);
+      if (terminateOnNonOptionalTag && !HtmlUtil.isOptionalEndForHtmlTagL(parentName)) return false;
+      if (isTD && (TR_TAG.equals(parentName) || TABLE_TAG.equals(parentName)) ||
+          isTR && TABLE_TAG.equals(parentName)) {
+        return false;
+      }
+
+      if (childName.equals(parentName)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+
+  @NotNull
+  private PsiBuilder.Marker startText(@Nullable PsiBuilder.Marker xmlText) {
+    if (xmlText == null) {
+      xmlText = mark();
+      assert xmlText != null;
+    }
+    return xmlText;
+  }
+
+  protected final PsiBuilder.Marker mark() {
+    return myBuilder.mark();
+  }
+
+  @Nullable
+  private static PsiBuilder.Marker terminateText(@Nullable PsiBuilder.Marker xmlText) {
+    if (xmlText != null) {
+      xmlText.done(XmlElementType.XML_TEXT);
+      xmlText = null;
+    }
+    return xmlText;
+  }
+
+  private void parseCData() {
+    assert token() == XmlTokenType.XML_CDATA_START;
+    final PsiBuilder.Marker cdata = mark();
+    while (token() != XmlTokenType.XML_CDATA_END && !eof()) {
+      advance();
+    }
+
+    if (!eof()) {
+      advance();
+    }
+
+    cdata.done(XmlElementType.XML_CDATA);
+  }
+
+  protected void parseComment() {
+    final PsiBuilder.Marker comment = mark();
+    advance();
+    while (true) {
+      final IElementType tt = token();
+      if (tt == XmlTokenType.XML_COMMENT_CHARACTERS || tt == XmlTokenType.XML_CHAR_ENTITY_REF || tt == XmlTokenType.XML_CONDITIONAL_COMMENT_START
+        || tt == XmlTokenType.XML_CONDITIONAL_COMMENT_START_END || tt == XmlTokenType.XML_CONDITIONAL_COMMENT_END_START
+        || tt == XmlTokenType.XML_CONDITIONAL_COMMENT_END) {
+        advance();
+        continue;
+      }
+      else if (tt == XmlTokenType.XML_BAD_CHARACTER) {
+        final PsiBuilder.Marker error = mark();
+        advance();
+        error.error(XmlErrorMessages.message("xml.parsing.bad.character"));
+        continue;
+      }
+      if (tt == XmlTokenType.XML_COMMENT_END) {
+        advance();
+      }
+      break;
+    }
+    comment.done(XmlElementType.XML_COMMENT);
+  }
+
+  private void parseReference() {
+    if (token() == XmlTokenType.XML_CHAR_ENTITY_REF) {
+      advance();
+    }
+    else if (token() == XmlTokenType.XML_ENTITY_REF_TOKEN) {
+      final PsiBuilder.Marker ref = mark();
+      advance();
+      ref.done(XmlElementType.XML_ENTITY_REF);
+    }
+    else {
+      assert false : "Unexpected token";
+    }
+  }
+
+  private void parseAttribute() {
+    assert token() == XmlTokenType.XML_NAME;
+    final PsiBuilder.Marker att = mark();
+    advance();
+    if (token() == XmlTokenType.XML_EQ) {
+      advance();
+      parseAttributeValue();
+      att.done(XmlElementType.XML_ATTRIBUTE);
+    }
+    else {
+      att.done(XmlElementType.XML_ATTRIBUTE);
+    }
+  }
+
+  private void parseAttributeValue() {
+    final PsiBuilder.Marker attValue = mark();
+    if (token() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+      while (true) {
+        final IElementType tt = token();
+        if (tt == null || tt == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER || tt == XmlTokenType.XML_END_TAG_START || tt == XmlTokenType
+          .XML_EMPTY_ELEMENT_END ||
+            tt == XmlTokenType.XML_START_TAG_START) {
+          break;
+        }
+
+        if (tt == XmlTokenType.XML_BAD_CHARACTER) {
+          final PsiBuilder.Marker error = mark();
+          advance();
+          error.error(XmlErrorMessages.message("unescaped.ampersand.or.nonterminated.character.entity.reference"));
+        }
+        else if (tt == XmlTokenType.XML_ENTITY_REF_TOKEN) {
+          parseReference();
+        }
+        else {
+          advance();
+        }
+      }
+
+      if (token() == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER) {
+        advance();
+      }
+      else {
+        error(XmlErrorMessages.message("xml.parsing.unclosed.attribute.value"));
+      }
+    }
+    else {
+      if (token() != XmlTokenType.XML_TAG_END && token() != XmlTokenType.XML_EMPTY_ELEMENT_END) {
+        advance(); // Single token att value
+      }
+    }
+
+    attValue.done(XmlElementType.XML_ATTRIBUTE_VALUE);
+  }
+
+  private void parseProlog() {
+    while (true) {
+      final IElementType tt = token();
+      if (tt == XmlTokenType.XML_COMMENT_START) {
+        parseComment();
+      }
+      else if (tt == XmlTokenType.XML_REAL_WHITE_SPACE) {
+        advance();
+      }
+      else {
+        break;
+      }
+    }
+
+    final PsiBuilder.Marker prolog = mark();
+    while (true) {
+      final IElementType tt = token();
+      if (tt == XmlTokenType.XML_PI_START) {
+        parseProcessingInstruction();
+      }
+      else if (tt == XmlTokenType.XML_DOCTYPE_START) {
+        parseDoctype();
+      }
+      else if (tt == XmlTokenType.XML_COMMENT_START) {
+        parseComment();
+      }
+      else if (tt == XmlTokenType.XML_REAL_WHITE_SPACE) {
+        advance();
+      }
+      else {
+        break;
+      }
+    }
+    prolog.done(XmlElementType.XML_PROLOG);
+  }
+
+  private void parseProcessingInstruction() {
+    assert token() == XmlTokenType.XML_PI_START;
+    final PsiBuilder.Marker pi = mark();
+    advance();
+    if (token() == XmlTokenType.XML_NAME || token() == XmlTokenType.XML_PI_TARGET) {
+      advance();
+    }
+
+    while (token() == XmlTokenType.XML_NAME) {
+      advance();
+      if (token() == XmlTokenType.XML_EQ) {
+        advance();
+      }
+      else {
+        error(XmlErrorMessages.message("expected.attribute.eq.sign"));
+      }
+      parseAttributeValue();
+    }
+
+    if (token() == XmlTokenType.XML_PI_END) {
+      advance();
+    }
+    else {
+      error(XmlErrorMessages.message("xml.parsing.unterminated.processing.instruction"));
+    }
+
+    pi.done(XmlElementType.XML_PROCESSING_INSTRUCTION);
+  }
+
+  protected final IElementType token() {
+    return myBuilder.getTokenType();
+  }
+
+  protected final boolean eof() {
+    return myBuilder.eof();
+  }
+
+  protected final void advance() {
+    myBuilder.advanceLexer();
+  }
+
+  private void error(final String message) {
+    myBuilder.error(message);
+  }
+
+  private static final int MAGIC_FRAME_COUNT = IndentHelperImpl.TOO_BIG_WALK_THRESHOLD + (int)(Math.pow(Math.E, Math.PI) * Math.sin(Math.random()));
+}
diff --git a/xml/impl/src/com/intellij/lang/html/HtmlStructureViewBuilderProvider.java b/xml/impl/src/com/intellij/lang/html/HtmlStructureViewBuilderProvider.java
new file mode 100644
index 0000000..19a063d
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/HtmlStructureViewBuilderProvider.java
@@ -0,0 +1,56 @@
+package com.intellij.lang.html;
+
+import com.intellij.ide.highlighter.HtmlFileType;
+import com.intellij.ide.structureView.StructureViewBuilder;
+import com.intellij.ide.structureView.StructureViewModel;
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
+import com.intellij.ide.structureView.impl.xml.XmlStructureViewTreeModel;
+import com.intellij.ide.structureView.xml.XmlStructureViewBuilderProvider;
+import com.intellij.ide.util.treeView.smartTree.Sorter;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class HtmlStructureViewBuilderProvider implements XmlStructureViewBuilderProvider {
+  @Nullable
+  public StructureViewBuilder createStructureViewBuilder(@NotNull final XmlFile file) {
+    if (file.getViewProvider().getVirtualFile().getFileType() != HtmlFileType.INSTANCE) return null;
+
+    return new TreeBasedStructureViewBuilder() {
+      public boolean isRootNodeShown() {
+        return false;
+      }
+
+      @NotNull
+      public StructureViewModel createStructureViewModel() {
+        return new XmlStructureViewTreeModel(file) {
+          @NotNull
+          public Sorter[] getSorters() {
+            return Sorter.EMPTY_ARRAY;
+          }
+
+          @NotNull
+          public StructureViewTreeElement getRoot() {
+            final XmlDocument document = ((XmlFile)getPsiFile()).getDocument();
+            final XmlTag rootTag = document == null ? null : document.getRootTag();
+
+            if (rootTag != null && "html".equalsIgnoreCase(rootTag.getLocalName())) {
+              final XmlTag[] subTags = rootTag.getSubTags();
+              if (subTags.length == 1 &&
+                  ("head".equalsIgnoreCase(subTags[0].getLocalName()) || "body".equalsIgnoreCase(subTags[0].getLocalName()))) {
+                return new HtmlStructureViewElementProvider.HtmlTagTreeElement(subTags[0]);
+              }
+
+              return new HtmlStructureViewElementProvider.HtmlTagTreeElement(rootTag);
+            }
+
+            return super.getRoot();
+          }
+        };
+      }
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/html/HtmlStructureViewElementProvider.java b/xml/impl/src/com/intellij/lang/html/HtmlStructureViewElementProvider.java
new file mode 100644
index 0000000..4be0765
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/HtmlStructureViewElementProvider.java
@@ -0,0 +1,102 @@
+package com.intellij.lang.html;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.ide.highlighter.HtmlFileType;
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.impl.xml.XmlTagTreeElement;
+import com.intellij.ide.structureView.xml.XmlStructureViewElementProvider;
+import com.intellij.navigation.LocationPresentation;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+
+public class HtmlStructureViewElementProvider implements XmlStructureViewElementProvider {
+
+  private static int MAX_TEXT_LENGTH = 50;
+
+  @Nullable
+  public StructureViewTreeElement createCustomXmlTagTreeElement(@NotNull final XmlTag tag) {
+    if (tag.getContainingFile().getViewProvider().getVirtualFile().getFileType() != HtmlFileType.INSTANCE) return null;
+
+    return new HtmlTagTreeElement(tag);
+  }
+
+  static class HtmlTagTreeElement extends XmlTagTreeElement implements LocationPresentation {
+    public HtmlTagTreeElement(final XmlTag tag) {
+      super(tag);
+    }
+
+    public String getPresentableText() {
+      final XmlTag tag = getElement();
+      if (tag == null) return IdeBundle.message("node.structureview.invalid");
+
+      final String id = toCanonicalForm(tag.getAttributeValue("id"));
+
+      final String classValue = tag.getAttributeValue("class");
+      final List<String> classValues = classValue != null ? StringUtil.split(classValue, " ") : Collections.<String>emptyList();
+
+      final StringBuilder text = new StringBuilder(tag.getLocalName());
+
+      if (id != null) {
+        text.append("#").append(id);
+      }
+
+      if (!classValues.isEmpty()) {
+        text.append('.').append(StringUtil.join(classValues, "."));
+      }
+
+      return text.toString();
+    }
+
+    public String getLocationString() {
+      final XmlTag tag = getElement();
+      if (tag == null) return null;
+
+      final String text = normalizeSpaces(tag.getValue().getTrimmedText());
+      return text.isEmpty() ? null : shortenTextIfLong(text);
+    }
+
+    private static String normalizeSpaces(final String text) {
+      final StringBuilder buf = new StringBuilder();
+
+      for (char ch : text.toCharArray()) {
+        if (ch <= ' ' || Character.isSpaceChar(ch)) {
+          if (buf.length() == 0 || buf.charAt(buf.length() - 1) != ' ') {
+            buf.append(' ');
+          }
+        }
+        else {
+          buf.append(ch);
+        }
+      }
+
+      return buf.toString();
+    }
+
+    private static String shortenTextIfLong(final String text) {
+      if (text.length() <= MAX_TEXT_LENGTH) return text;
+
+      int index;
+      for (index = MAX_TEXT_LENGTH; index > MAX_TEXT_LENGTH - 20; index--) {
+        if (!Character.isLetter(text.charAt(index))) {
+          break;
+        }
+      }
+
+      final int endIndex = Character.isLetter(index) ? MAX_TEXT_LENGTH : index;
+      return text.substring(0, endIndex) + "...";
+    }
+
+    public String getLocationPrefix() {
+      return "  ";
+    }
+
+    public String getLocationSuffix() {
+      return "";
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xhtml/XHTMLLanguage.java b/xml/impl/src/com/intellij/lang/xhtml/XHTMLLanguage.java
new file mode 100644
index 0000000..52bb56d
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xhtml/XHTMLLanguage.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xhtml;
+
+import com.intellij.ide.highlighter.XmlFileHighlighter;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.fileTypes.SingleLazyInstanceSyntaxHighlighterFactory;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
+import com.intellij.psi.impl.source.xml.XmlPsiPolicy;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class XHTMLLanguage extends XMLLanguage {
+
+  public static final XHTMLLanguage INSTANCE = new XHTMLLanguage();
+
+  private XHTMLLanguage() {
+    super(XMLLanguage.INSTANCE, "XHTML", "text/xhtml", "application/xhtml+xml");
+    SyntaxHighlighterFactory.LANGUAGE_FACTORY.addExplicitExtension(this, new SingleLazyInstanceSyntaxHighlighterFactory() {
+      @NotNull
+      protected SyntaxHighlighter createHighlighter() {
+        return new XmlFileHighlighter(false, true);
+      }
+    });
+  }
+
+  public XmlPsiPolicy getPsiPolicy() {
+    return ENCODE_EACH_SYMBOL_POLICY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xhtml/XHTMLParserDefinition.java b/xml/impl/src/com/intellij/lang/xhtml/XHTMLParserDefinition.java
new file mode 100644
index 0000000..93b34c0
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xhtml/XHTMLParserDefinition.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xhtml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.xml.XMLParserDefinition;
+import com.intellij.lexer.Lexer;
+import com.intellij.lexer.XHtmlLexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.xml.XmlFileImpl;
+import com.intellij.psi.xml.XmlElementType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class XHTMLParserDefinition extends XMLParserDefinition {
+
+  @NotNull
+  public Lexer createLexer(Project project) {
+    return new XHtmlLexer();
+  }
+
+  public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
+    final Lexer lexer = createLexer(left.getPsi().getProject());
+    return canStickTokensTogetherByLexerInXml(left, right, lexer, 0);
+  }
+
+  public PsiFile createFile(FileViewProvider viewProvider) {
+    return new XmlFileImpl(viewProvider, XmlElementType.XHTML_FILE);
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/lang/xhtml/XhtmlFormattingModelBuilder.java b/xml/impl/src/com/intellij/lang/xhtml/XhtmlFormattingModelBuilder.java
new file mode 100644
index 0000000..769f7cc
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xhtml/XhtmlFormattingModelBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.xhtml;
+
+import com.intellij.formatting.FormattingModel;
+import com.intellij.formatting.FormattingModelBuilder;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.formatter.FormattingDocumentModelImpl;
+import com.intellij.psi.formatter.xml.HtmlPolicy;
+import com.intellij.psi.formatter.xml.XmlBlock;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.lang.xml.XmlFormattingModel;
+import org.jetbrains.annotations.NotNull;
+
+public class XhtmlFormattingModelBuilder implements FormattingModelBuilder {
+  @NotNull
+    public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) {
+    final PsiFile psiFile = element.getContainingFile();
+    final FormattingDocumentModelImpl documentModel = FormattingDocumentModelImpl.createOn(psiFile);
+    return new XmlFormattingModel(psiFile,
+                                                            new XmlBlock(SourceTreeToPsiMap.psiElementToTree(psiFile),
+                                                                         null, null,
+                                                                         new HtmlPolicy(settings, documentModel), null, null, false),
+                                                            documentModel);
+  }
+
+  public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/lang/xml/XMLExternalAnnotator.java b/xml/impl/src/com/intellij/lang/xml/XMLExternalAnnotator.java
new file mode 100644
index 0000000..75a8da5
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XMLExternalAnnotator.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.codeInsight.daemon.Validator;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.lang.annotation.Annotation;
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.lang.annotation.ExternalAnnotator;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.util.XmlTagUtil;
+
+/**
+ * @author ven
+ */
+public class XMLExternalAnnotator extends ExternalAnnotator {
+
+  public void annotate(PsiFile file, AnnotationHolder holder) {
+    if (!(file instanceof XmlFile)) return;
+    final XmlDocument document = ((XmlFile)file).getDocument();
+    if (document == null) return;
+    XmlTag rootTag = document.getRootTag();
+    XmlNSDescriptor nsDescriptor = rootTag == null ? null : rootTag.getNSDescriptor(rootTag.getNamespace(), false);
+
+    if (nsDescriptor instanceof Validator) {
+        //noinspection unchecked
+        ((Validator<XmlDocument>)nsDescriptor).validate(document, new MyHost(holder));
+    }
+  }
+
+  private static final Validator.ValidationHost.ErrorType[] types = Validator.ValidationHost.ErrorType.values();
+
+  private static void appendFixes(final Annotation annotation, final IntentionAction... actions) {
+    if (actions != null) {
+      for(IntentionAction action:actions) annotation.registerFix(action);
+    }
+  }
+
+  private static class MyHost implements Validator.ValidationHost {
+
+    private final AnnotationHolder myHolder;
+
+    public MyHost(AnnotationHolder holder) {
+
+      myHolder = holder;
+    }
+
+    public void addMessage(PsiElement context, String message, int type) {
+      addMessage(context, message, types[type]);
+    }
+
+    public void addMessage(final PsiElement context, final String message, final ErrorType type, final IntentionAction... fixes) {
+      if (message != null && message.length() > 0) {
+        if (context instanceof XmlTag) {
+          addMessagesForTag((XmlTag)context, message, type, fixes);
+        }
+        else {
+          if (type == Validator.ValidationHost.ErrorType.ERROR) {
+            appendFixes(myHolder.createErrorAnnotation(context, message), fixes);
+          } else {
+            appendFixes(myHolder.createWarningAnnotation(context, message), fixes);
+          }
+        }
+      }
+    }
+
+    private void addMessagesForTag(XmlTag tag, String message, ErrorType type, IntentionAction... actions) {
+      XmlToken childByRole = XmlTagUtil.getStartTagNameElement(tag);
+
+      addMessagesForTreeChild(childByRole, type, message, actions);
+
+      childByRole = XmlTagUtil.getEndTagNameElement(tag);
+      addMessagesForTreeChild(childByRole, type, message, actions);
+    }
+
+    private void addMessagesForTreeChild(final XmlToken childByRole, final ErrorType type, final String message, IntentionAction... actions) {
+      if (childByRole != null) {
+        Annotation annotation;
+        if (type == ErrorType.ERROR) {
+          annotation = myHolder.createErrorAnnotation(childByRole, message);
+        }
+        else {
+          annotation = myHolder.createWarningAnnotation(childByRole, message);
+        }
+
+        appendFixes(annotation, actions);
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XMLLanguage.java b/xml/impl/src/com/intellij/lang/xml/XMLLanguage.java
new file mode 100644
index 0000000..872cc75
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XMLLanguage.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.ide.highlighter.XmlFileHighlighter;
+import com.intellij.lang.CompositeLanguage;
+import com.intellij.lang.Language;
+import com.intellij.openapi.fileTypes.SingleLazyInstanceSyntaxHighlighterFactory;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
+import com.intellij.psi.impl.source.xml.XmlPsiPolicy;
+import com.intellij.psi.impl.source.xml.behavior.CDATAOnAnyEncodedPolicy;
+import com.intellij.psi.impl.source.xml.behavior.EncodeEachSymbolPolicy;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class XMLLanguage extends CompositeLanguage {
+
+  public final static XMLLanguage INSTANCE = new XMLLanguage();
+
+  protected static final CDATAOnAnyEncodedPolicy CDATA_ON_ANY_ENCODED_POLICY = new CDATAOnAnyEncodedPolicy();
+  protected static final EncodeEachSymbolPolicy ENCODE_EACH_SYMBOL_POLICY = new EncodeEachSymbolPolicy();
+
+  private XMLLanguage() {
+    super("XML", "text/xml");
+
+    SyntaxHighlighterFactory.LANGUAGE_FACTORY.addExplicitExtension(this, new SingleLazyInstanceSyntaxHighlighterFactory() {
+      @NotNull
+      protected SyntaxHighlighter createHighlighter() {
+        return new XmlFileHighlighter();
+      }
+    });
+  }
+
+  @Deprecated
+  protected XMLLanguage(@NonNls String name, @NonNls String... mime) {
+    super(name, mime);
+  }
+
+  protected XMLLanguage(Language baseLanguage, @NonNls String name, @NonNls String... mime) {
+    super(baseLanguage, name, mime);
+  }
+
+
+  public XmlPsiPolicy getPsiPolicy() {
+    return CDATA_ON_ANY_ENCODED_POLICY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XMLParserDefinition.java b/xml/impl/src/com/intellij/lang/xml/XMLParserDefinition.java
new file mode 100644
index 0000000..a25df77
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XMLParserDefinition.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.ParserDefinition;
+import com.intellij.lang.PsiParser;
+import com.intellij.lexer.Lexer;
+import com.intellij.lexer.XmlLexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.parsing.xml.XmlParser;
+import com.intellij.psi.impl.source.xml.XmlFileImpl;
+import com.intellij.psi.tree.IFileElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class XMLParserDefinition implements ParserDefinition {
+  @NotNull
+  public Lexer createLexer(Project project) {
+    return new XmlLexer();
+  }
+
+  public IFileElementType getFileNodeType() {
+    return XmlElementType.XML_FILE;
+  }
+
+  @NotNull
+  public TokenSet getWhitespaceTokens() {
+    return XmlTokenType.WHITESPACES;
+  }
+
+  @NotNull
+  public TokenSet getCommentTokens() {
+    return XmlTokenType.COMMENTS;
+  }
+
+  @NotNull
+  public TokenSet getStringLiteralElements() {
+    return TokenSet.EMPTY;
+  }
+
+  @NotNull
+  public PsiParser createParser(final Project project) {
+    return new XmlParser();
+  }
+
+  @NotNull
+  public PsiElement createElement(ASTNode node) {
+    return PsiUtilCore.NULL_PSI_ELEMENT;
+  }
+
+  public PsiFile createFile(FileViewProvider viewProvider) {
+    return new XmlFileImpl(viewProvider, XmlElementType.XML_FILE);
+  }
+
+  public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
+    final Lexer lexer = createLexer(left.getPsi().getProject());
+    return canStickTokensTogetherByLexerInXml(left, right, lexer, 0);
+  }
+
+  public static SpaceRequirements canStickTokensTogetherByLexerInXml(final ASTNode left,
+                                                                                      final ASTNode right,
+                                                                                      final Lexer lexer,
+                                                                                      int state) {
+    if (left.getElementType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN ||
+        right.getElementType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) {
+      return SpaceRequirements.MUST_NOT;
+    }
+    if (left.getElementType() == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER && right.getElementType() == XmlTokenType.XML_NAME) {
+      return SpaceRequirements.MUST;
+    }
+    if (left.getElementType() == XmlTokenType.XML_NAME && right.getElementType() == XmlTokenType.XML_NAME) {
+      return SpaceRequirements.MUST;
+    }
+    return SpaceRequirements.MAY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlASTFactory.java b/xml/impl/src/com/intellij/lang/xml/XmlASTFactory.java
new file mode 100644
index 0000000..4b49994
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlASTFactory.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.lang.ASTFactory;
+import com.intellij.lang.impl.PsiBuilderImpl;
+import com.intellij.psi.impl.source.html.HtmlDocumentImpl;
+import com.intellij.psi.impl.source.html.HtmlTagImpl;
+import com.intellij.psi.impl.source.tree.*;
+import com.intellij.psi.impl.source.xml.*;
+import com.intellij.psi.templateLanguages.TemplateDataElementType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.ILazyParseableElementType;
+import com.intellij.psi.tree.xml.IXmlLeafElementType;
+import static com.intellij.psi.xml.XmlElementType.*;
+import static com.intellij.psi.xml.XmlElementType.XML_ELEMENT_CONTENT_GROUP;
+
+public class XmlASTFactory extends ASTFactory {
+  public CompositeElement createComposite(final IElementType type) {
+    if (type == XML_TAG) {
+      return new XmlTagImpl();
+    }
+    else if (type == XML_CONDITIONAL_SECTION) {
+      return new XmlConditionalSectionImpl();
+    }
+    else if (type == HTML_TAG) {
+      return new HtmlTagImpl();
+    }
+    else if (type == XML_TEXT) {
+      return new XmlTextImpl();
+    }
+    else if (type == XML_PROCESSING_INSTRUCTION) {
+      return new XmlProcessingInstructionImpl();
+    }
+    else if (type == XML_DOCUMENT) {
+      return new XmlDocumentImpl();
+    }
+    else if (type == HTML_DOCUMENT) {
+      return new HtmlDocumentImpl();
+    }
+    else if (type == XML_PROLOG) {
+      return new XmlPrologImpl();
+    }
+    else if (type == XML_DECL) {
+      return new XmlDeclImpl();
+    }
+    else if (type == XML_ATTRIBUTE) {
+      return new XmlAttributeImpl();
+    }
+    else if (type == XML_ATTRIBUTE_VALUE) {
+      return new XmlAttributeValueImpl();
+    }
+    else if (type == XML_COMMENT) {
+      return new XmlCommentImpl();
+    }
+    else if (type == XML_DOCTYPE) {
+      return new XmlDoctypeImpl();
+    }
+    else if (type == XML_MARKUP_DECL) {
+      return new XmlMarkupDeclImpl();
+    }
+    else if (type == XML_ELEMENT_DECL) {
+      return new XmlElementDeclImpl();
+    }
+    else if (type == XML_ENTITY_DECL) {
+      return new XmlEntityDeclImpl();
+    }
+    else if (type == XML_ATTLIST_DECL) {
+      return new XmlAttlistDeclImpl();
+    }
+    else if (type == XML_ATTRIBUTE_DECL) {
+      return new XmlAttributeDeclImpl();
+    }
+    else if (type == XML_NOTATION_DECL) {
+      return new XmlNotationDeclImpl();
+    }
+    else if (type == XML_ELEMENT_CONTENT_SPEC) {
+      return new XmlElementContentSpecImpl();
+    }
+    else if (type == XML_ELEMENT_CONTENT_GROUP) {
+      return new XmlElementContentGroupImpl();
+    }
+    else if (type == XML_ENTITY_REF) {
+      return new XmlEntityRefImpl();
+    }
+    else if (type == XML_ENUMERATED_TYPE) {
+      return new XmlEnumeratedTypeImpl();
+    }
+    else if (type == XML_CDATA) {
+      return new CompositePsiElement(XML_CDATA) {};
+    }
+    else if (type instanceof TemplateDataElementType) {
+      return new XmlFileElement(type, null);
+    }
+
+    return null;
+  }
+
+  @Override
+  public LazyParseableElement createLazy(ILazyParseableElementType type, CharSequence text) {
+    if (type == XML_FILE) {
+      return new XmlFileElement(type, text);
+    }
+    else if (type == DTD_FILE) {
+      return new XmlFileElement(type, text);
+    }
+    else if (type == XHTML_FILE) {
+      return new XmlFileElement(type, text);
+    }
+    else if (type == HTML_FILE) {
+      return new HtmlFileElement(text);
+    }
+    else if (type instanceof TemplateDataElementType) {
+      return new XmlFileElement(type, text);
+    }
+    return null;
+  }
+
+  public LeafElement createLeaf(final IElementType type, CharSequence text) {
+    if (type instanceof IXmlLeafElementType) {
+      if (type == XML_REAL_WHITE_SPACE) {
+        return new PsiWhiteSpaceImpl(text);
+      }
+      return new XmlTokenImpl(type, text);
+    }
+
+    return null;
+  }
+
+  static {
+    PsiBuilderImpl.registerWhitespaceToken(XML_REAL_WHITE_SPACE);    
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlAttributeValueRenameValidator.java b/xml/impl/src/com/intellij/lang/xml/XmlAttributeValueRenameValidator.java
new file mode 100644
index 0000000..b0618e7
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlAttributeValueRenameValidator.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.patterns.ElementPattern;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.refactoring.rename.RenameInputValidator;
+import com.intellij.util.ProcessingContext;
+
+import static com.intellij.patterns.PlatformPatterns.psiElement;
+
+public class XmlAttributeValueRenameValidator implements RenameInputValidator {
+  @Override
+  public ElementPattern<? extends PsiElement> getPattern() {
+    return psiElement(XmlAttributeValue.class);
+  }
+
+  public boolean isInputValid(final String newName, final PsiElement element, final ProcessingContext context) {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlCommenter.java b/xml/impl/src/com/intellij/lang/xml/XmlCommenter.java
new file mode 100644
index 0000000..4701036
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlCommenter.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.lang.Commenter;
+
+/**
+ * @author max
+ */
+public class XmlCommenter implements Commenter {
+
+  public String getLineCommentPrefix() {
+    return null;
+  }
+
+  public String getBlockCommentPrefix() {
+    return "<!--";
+  }
+
+  public String getBlockCommentSuffix() {
+    return "-->";
+  }
+
+  public String getCommentedBlockCommentPrefix() {
+    return "&lt;!&ndash;";
+  }
+
+  public String getCommentedBlockCommentSuffix() {
+    return "&ndash;&gt;";
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlElementRenameValidator.java b/xml/impl/src/com/intellij/lang/xml/XmlElementRenameValidator.java
new file mode 100644
index 0000000..3324366
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlElementRenameValidator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.patterns.ElementPattern;
+import com.intellij.patterns.PlatformPatterns;
+import com.intellij.patterns.XmlPatterns;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttributeDecl;
+import com.intellij.psi.xml.XmlElementDecl;
+import com.intellij.refactoring.rename.RenameInputValidator;
+import com.intellij.util.ProcessingContext;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+
+import static com.intellij.patterns.PlatformPatterns.psiElement;
+import static com.intellij.patterns.StandardPatterns.or;
+
+public class XmlElementRenameValidator implements RenameInputValidator {
+  @Override
+  public ElementPattern<? extends PsiElement> getPattern() {
+    return or(
+      XmlPatterns.xmlTag().withMetaData(
+        or(PlatformPatterns.instanceOf(XmlElementDescriptor.class),
+           PlatformPatterns.instanceOf(XmlAttributeDescriptor.class))
+      ),
+      psiElement(XmlElementDecl.class),
+      psiElement(XmlAttributeDecl.class),
+      XmlPatterns.xmlTag().withDescriptor(
+        or(PlatformPatterns.instanceOf(XmlElementDescriptor.class),
+           PlatformPatterns.instanceOf(XmlAttributeDescriptor.class))
+      )
+    );
+  }
+
+  public boolean isInputValid(final String newName, final PsiElement element, final ProcessingContext context) {
+    return newName.trim().matches("([\\d\\w\\_\\.\\-]+:)?[\\d\\w\\_\\.\\-]+");
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlEnclosingTagUnwrapper.java b/xml/impl/src/com/intellij/lang/xml/XmlEnclosingTagUnwrapper.java
new file mode 100644
index 0000000..825f168
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlEnclosingTagUnwrapper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.codeInsight.unwrap.Unwrapper;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlBundle;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.lang.ASTNode;
+
+import java.util.Set;
+import java.util.List;
+import java.util.Collections;
+
+public class XmlEnclosingTagUnwrapper implements Unwrapper {
+  public boolean isApplicableTo(PsiElement e) {
+    return true;
+  }
+
+  public void collectElementsToIgnore(PsiElement element, Set<PsiElement> result) {
+  }
+
+  public String getDescription(PsiElement e) {
+    return XmlBundle.message("unwrap.enclosing.tag.name.action.name", ((XmlTag)e).getName());
+  }
+
+  public PsiElement collectAffectedElements(PsiElement e, List<PsiElement> toExtract) {
+    return e;
+  }
+
+  public List<PsiElement> unwrap(Editor editor, PsiElement element) throws IncorrectOperationException {
+    final TextRange range = element.getTextRange();
+    final ASTNode startTagNameEnd = XmlChildRole.START_TAG_END_FINDER.findChild(element.getNode());
+    final ASTNode endTagNameStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(element.getNode());
+
+    if (endTagNameStart != null) {
+      editor.getDocument().replaceString(endTagNameStart.getTextRange().getStartOffset(), range.getEndOffset(), "");
+      editor.getDocument().replaceString(range.getStartOffset(), startTagNameEnd.getTextRange().getEndOffset(), "");
+    }
+    else {
+      editor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), "");
+    }
+    return Collections.emptyList();
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlFindUsagesProvider.java b/xml/impl/src/com/intellij/lang/xml/XmlFindUsagesProvider.java
new file mode 100644
index 0000000..c9154bd
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlFindUsagesProvider.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.find.impl.HelpID;
+import com.intellij.lang.LangBundle;
+import com.intellij.lang.cacheBuilder.WordsScanner;
+import com.intellij.lang.findUsages.FindUsagesProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.xml.*;
+import com.intellij.usageView.UsageViewBundle;
+import com.intellij.usageView.UsageViewUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ven
+ */
+public class XmlFindUsagesProvider implements FindUsagesProvider {
+
+  public boolean canFindUsagesFor(@NotNull PsiElement element) {
+    return element instanceof XmlElementDecl ||
+           element instanceof XmlAttributeDecl ||
+           element instanceof XmlEntityDecl ||
+           element instanceof XmlTag ||
+           element instanceof XmlAttributeValue ||
+           element instanceof PsiFile ||
+           element instanceof XmlComment;
+  }
+
+  @NotNull
+  public String getType(@NotNull PsiElement element) {
+    if (element instanceof XmlTag) {
+      final PsiMetaData metaData = ((XmlTag)element).getMetaData();
+      if (metaData != null && metaData.getDeclaration() instanceof XmlTag) {
+        return ((XmlTag)metaData.getDeclaration()).getName();
+      }
+      return LangBundle.message("xml.terms.xml.tag");
+    }
+    if (element instanceof XmlElementDecl) {
+      return LangBundle.message("xml.terms.tag");
+    }
+    else if (element instanceof XmlAttributeDecl) {
+      return LangBundle.message("xml.terms.attribute");
+    }
+    else if (element instanceof XmlAttributeValue) {
+      return LangBundle.message("xml.terms.attribute.value");
+    }
+    else if (element instanceof XmlEntityDecl) {
+      return LangBundle.message("xml.terms.entity");
+    }
+    else if (element instanceof XmlAttribute) {
+      return LangBundle.message("xml.terms.attribute");
+    } else if (element instanceof XmlComment) {
+      return LangBundle.message("xml.terms.variable");
+    }
+    throw new IllegalArgumentException("Cannot get type for " + element);
+  }
+
+  public String getHelpId(@NotNull PsiElement element) {
+    return HelpID.FIND_OTHER_USAGES;
+  }
+
+  @NotNull
+  public String getDescriptiveName(@NotNull PsiElement element) {
+    if (element instanceof XmlTag) {
+      return ((XmlTag)element).getName();
+    }
+
+    if (element instanceof XmlAttributeValue) {
+      return ((XmlAttributeValue)element).getValue();
+    }
+
+    if (element instanceof PsiNamedElement) {
+      return ((PsiNamedElement)element).getName();
+    } else {
+      return element.getText();
+    }
+  }
+
+  @NotNull
+  public String getNodeText(@NotNull PsiElement element, boolean useFullName) {
+    if (element instanceof XmlTag) {
+      final XmlTag xmlTag = (XmlTag)element;
+      final PsiMetaData metaData = xmlTag.getMetaData();
+      final String name = metaData != null ? UsageViewUtil.getMetaDataName(metaData) : xmlTag.getName();
+      return UsageViewBundle.message("usage.target.xml.tag.of.file", metaData == null ? "<" + name + ">" : name, xmlTag.getContainingFile().getName());
+    }
+    else if (element instanceof XmlAttributeValue) {
+      return ((XmlAttributeValue)element).getValue();
+    }
+    if (element instanceof PsiNamedElement) {
+      return ((PsiNamedElement)element).getName();
+    } else {
+      return element.getText();
+    }
+  }
+
+  public WordsScanner getWordsScanner() {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java b/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java
new file mode 100644
index 0000000..1fc9b15
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.application.options.editor.XmlFoldingSettings;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.lang.folding.FoldingBuilder;
+import com.intellij.lang.folding.FoldingDescriptor;
+import com.intellij.lang.folding.LanguageFolding;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.impl.source.html.HtmlFileImpl;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.*;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.XmlTagUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class XmlFoldingBuilder implements FoldingBuilder, DumbAware {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.lang.xml.XmlFoldingBuilder");
+  private static final TokenSet XML_ATTRIBUTE_SET = TokenSet.create(XmlElementType.XML_ATTRIBUTE);
+  private static final int MIN_TEXT_RANGE_LENGTH = 3;
+  private static final String STYLE_ATTRIBUTE = "style";
+
+  @NotNull
+  public FoldingDescriptor[] buildFoldRegions(@NotNull ASTNode node, @NotNull Document document) {
+    final PsiElement psiElement = node.getPsi();
+    XmlDocument xmlDocument = null;
+    
+    if (psiElement instanceof XmlFile) { 
+      XmlFile file = (XmlFile)psiElement;
+      xmlDocument = file.getDocument();
+    }
+    else if (psiElement instanceof XmlDocument) {
+      xmlDocument = (XmlDocument)psiElement;
+    }
+    
+    XmlElement rootTag = xmlDocument == null ? null : xmlDocument.getRootTag();
+    if (rootTag == null) {
+      rootTag = xmlDocument;
+    }
+    List<FoldingDescriptor> foldings = null;
+
+    if (rootTag != null) {
+      foldings = new ArrayList<FoldingDescriptor>();
+
+      doAddForChildren(xmlDocument, foldings, document);
+    }
+
+    return foldings != null ? foldings.toArray(new FoldingDescriptor[foldings.size()]):FoldingDescriptor.EMPTY;
+  }
+
+  protected void addElementsToFold(List<FoldingDescriptor> foldings, XmlElement tag, Document document) {
+    addToFold(foldings, tag, document);
+    doAddForChildren(tag, foldings, document);
+  }
+
+  protected void doAddForChildren(final XmlElement tag, final List<FoldingDescriptor> foldings, final Document document) {
+    final PsiElement[] children = tag.getChildren();
+
+    for (PsiElement child : children) {
+      ProgressManager.checkCanceled();
+
+      if (child instanceof XmlTag || child instanceof XmlConditionalSection) {
+        addElementsToFold(foldings, (XmlElement)child, document);
+      }
+      else if (child instanceof XmlComment) {
+        addToFold(foldings, child, document);
+      }
+      else if (child instanceof XmlText || child instanceof XmlProlog) {
+        final PsiElement[] grandChildren = child.getChildren();
+
+        for (PsiElement grandChild : grandChildren) {
+          ProgressManager.checkCanceled();
+
+          if (grandChild instanceof XmlComment) {
+            addToFold(foldings, grandChild, document);
+          }
+        }
+      }
+      else if(child instanceof XmlAttribute && isAttributeShouldBeFolded((XmlAttribute)child)) {
+        addToFold(foldings, child, document);
+      }
+      else {
+        final Language language = child.getLanguage();
+        if (!(language instanceof XMLLanguage) && language != Language.ANY) {
+          final FoldingBuilder foldingBuilder = LanguageFolding.INSTANCE.forLanguage(language);
+
+          if (foldingBuilder != null) {
+            final FoldingDescriptor[] foldingDescriptors = foldingBuilder.buildFoldRegions(child.getNode(), document);
+
+            ContainerUtil.addAll(foldings, foldingDescriptors);
+          }
+        }
+      }
+    }
+  }
+
+  @Nullable
+  public TextRange getRangeToFold(PsiElement element) {
+    if (element instanceof XmlTag) {
+      final ASTNode tagNode = element.getNode();
+      XmlToken tagNameElement = XmlTagUtil.getStartTagNameElement((XmlTag)element);
+      if (tagNameElement == null) return null;
+
+      int nameEnd = tagNameElement.getTextRange().getEndOffset();
+      int end = tagNode.getLastChildNode().getTextRange().getEndOffset() - 1;  // last child node can be another tag in unbalanced tree
+      ASTNode[] attributes = tagNode.getChildren(XML_ATTRIBUTE_SET);
+
+      if (attributes.length > 0) {
+        ASTNode lastAttribute = attributes[attributes.length - 1];
+        ASTNode lastAttributeBeforeCR = null;
+
+        for (ASTNode child = tagNode.getFirstChildNode(); child != lastAttribute.getTreeNext(); child = child.getTreeNext()) {
+          if (child.getElementType() == XmlElementType.XML_ATTRIBUTE) {
+            lastAttributeBeforeCR = child;
+          } else if (child.getPsi() instanceof PsiWhiteSpace) {
+            if (child.textContains('\n')) break;
+          }
+        }
+
+        if (lastAttributeBeforeCR != null) {
+          int attributeEnd = lastAttributeBeforeCR.getTextRange().getEndOffset();
+          return new TextRange(attributeEnd, end);
+        }
+      }
+
+      return new TextRange(nameEnd, end);
+    } else if (element instanceof XmlComment) {
+      final XmlComment xmlComment = (XmlComment)element;
+      final TextRange textRange = element.getTextRange();
+      int commentStartOffset = getCommentStartOffset(xmlComment);
+      int commentEndOffset = getCommentStartEnd(xmlComment);
+
+      if (textRange.getEndOffset() - textRange.getStartOffset() > commentStartOffset + commentEndOffset) {
+        return new TextRange(textRange.getStartOffset() + commentStartOffset, textRange.getEndOffset() - commentEndOffset);
+      }
+      else {
+        return null;
+      }
+    }
+    else if (element instanceof XmlConditionalSection) {
+      final XmlConditionalSection conditionalSection = (XmlConditionalSection)element;
+      final TextRange textRange = element.getTextRange();
+      final PsiElement bodyStart = conditionalSection.getBodyStart();
+      int startOffset = bodyStart != null ? bodyStart.getStartOffsetInParent() : MIN_TEXT_RANGE_LENGTH;
+      int endOffset = MIN_TEXT_RANGE_LENGTH;
+
+      if (textRange.getEndOffset() - textRange.getStartOffset() > startOffset + endOffset) {
+        return new TextRange(textRange.getStartOffset() + startOffset, textRange.getEndOffset() - endOffset);
+      }
+      else {
+        return null;
+      }
+    }
+    else if (element instanceof XmlAttribute) {
+      final XmlAttributeValue valueElement = ((XmlAttribute)element).getValueElement();
+      return valueElement != null ? valueElement.getValueTextRange() : null;
+    }
+    else {
+      return null;
+    }
+  }
+
+  protected int getCommentStartOffset(final XmlComment element) {
+    return 4;
+  }
+
+  protected int getCommentStartEnd(final XmlComment element) {
+    return MIN_TEXT_RANGE_LENGTH;
+  }
+
+  protected boolean addToFold(List<FoldingDescriptor> foldings, PsiElement elementToFold, Document document) {
+    LOG.assertTrue(elementToFold.isValid());
+    TextRange range = getRangeToFold(elementToFold);
+    if (range == null) return false;
+
+    if(range.getStartOffset() >= 0 &&
+       range.getEndOffset() <= elementToFold.getContainingFile().getTextRange().getEndOffset() &&
+       range.getEndOffset() <= document.getTextLength() // psi and document maybe not in sync after error
+      ) {
+
+      int startLine = document.getLineNumber(range.getStartOffset());
+      int endLine = document.getLineNumber(range.getEndOffset() - 1);
+      if (startLine < endLine || elementToFold instanceof XmlAttribute) {
+        if (range.getStartOffset() + MIN_TEXT_RANGE_LENGTH < range.getEndOffset()) {
+          foldings.add(new FoldingDescriptor(elementToFold.getNode(), range));
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  public String getPlaceholderText(@NotNull ASTNode node) {
+    final PsiElement psi = node.getPsi();
+    if (psi instanceof XmlTag ||
+        psi instanceof XmlComment ||
+        psi instanceof XmlAttribute ||
+        psi instanceof XmlConditionalSection
+       ) return "...";
+    return null;
+  }
+
+  public boolean isCollapsedByDefault(@NotNull ASTNode node) {
+    final PsiElement psi = node.getPsi();
+    final XmlFoldingSettings foldingSettings = XmlFoldingSettings.getInstance();
+    return (psi instanceof XmlTag && foldingSettings.isCollapseXmlTags())
+           || (psi instanceof XmlAttribute && foldingSettings.isCollapseHtmlStyleAttribute());
+  }
+
+  private static boolean isAttributeShouldBeFolded(XmlAttribute child) {
+    return child.getContainingFile() instanceof HtmlFileImpl &&
+      STYLE_ATTRIBUTE.equalsIgnoreCase(((XmlAttribute)child).getName());
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlFormattingModel.java b/xml/impl/src/com/intellij/lang/xml/XmlFormattingModel.java
new file mode 100644
index 0000000..522a645
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlFormattingModel.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.formatting.Block;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.formatter.FormatterUtil;
+import com.intellij.psi.formatter.FormattingDocumentModelImpl;
+import com.intellij.psi.formatter.PsiBasedFormattingModel;
+import com.intellij.psi.impl.source.tree.TreeUtil;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlElementType;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+public class XmlFormattingModel extends PsiBasedFormattingModel {
+  private static final Logger LOG =
+      Logger.getInstance("#com.intellij.psi.impl.source.codeStyle.PsiBasedFormatterModelWithShiftIndentInside");
+
+  private final Project myProject;
+
+  public XmlFormattingModel(final PsiFile file,
+                                                     final Block rootBlock,
+                                                     final FormattingDocumentModelImpl documentModel) {
+    super(file, rootBlock, documentModel);
+    myProject = file.getProject();
+  }
+
+  public TextRange shiftIndentInsideRange(TextRange textRange, int shift) {
+    return shiftIndentInsideWithPsi(textRange, shift);
+  }
+
+  public void commitChanges() {
+  }
+
+
+  private TextRange shiftIndentInsideWithPsi(final TextRange textRange, final int shift) {
+    final int offset = textRange.getStartOffset();
+
+    ASTNode leafElement = findElementAt(offset);
+    while (leafElement != null && !leafElement.getTextRange().equals(textRange)) {
+      leafElement = leafElement.getTreeParent();
+    }
+
+    return textRange;
+  }
+
+  protected String replaceWithPsiInLeaf(final TextRange textRange, String whiteSpace, ASTNode leafElement) {
+     if (!myCanModifyAllWhiteSpaces) {
+       if (leafElement.getElementType() == TokenType.WHITE_SPACE) return null;
+       LOG.assertTrue(leafElement.getPsi().isValid());
+       ASTNode prevNode = TreeUtil.prevLeaf(leafElement);
+
+       if (prevNode != null) {
+         IElementType type = prevNode.getElementType();
+         if(type == TokenType.WHITE_SPACE) {
+           final String text = prevNode.getText();
+
+           final @NonNls String cdataStartMarker = "<![CDATA[";
+           final int cdataPos = text.indexOf(cdataStartMarker);
+           if (cdataPos != -1 && whiteSpace.indexOf(cdataStartMarker) == -1) {
+             whiteSpace = mergeWsWithCdataMarker(whiteSpace, text, cdataPos);
+             if (whiteSpace == null) return null;
+           }
+
+           prevNode = TreeUtil.prevLeaf(prevNode);
+           type = prevNode != null ? prevNode.getElementType():null;
+         }
+
+         final @NonNls String cdataEndMarker = "]]>";
+         if(type == XmlElementType.XML_CDATA_END && whiteSpace.indexOf(cdataEndMarker) == -1) {
+           final ASTNode at = findElementAt(prevNode.getStartOffset());
+
+           if (at != null && at.getPsi() instanceof PsiWhiteSpace) {
+             final String s = at.getText();
+             final int cdataEndPos = s.indexOf(cdataEndMarker);
+             whiteSpace = mergeWsWithCdataMarker(whiteSpace, s, cdataEndPos);
+             leafElement = at;
+           } else {
+             whiteSpace = null;
+           }
+           if (whiteSpace == null) return null;
+         }
+       }
+     }
+     FormatterUtil.replaceWhiteSpace(whiteSpace, leafElement, TokenType.WHITE_SPACE, textRange);
+     return whiteSpace;
+   }
+
+   @Nullable
+   private static String mergeWsWithCdataMarker(String whiteSpace, final String s, final int cdataPos) {
+     final int firstCrInGeneratedWs = whiteSpace.indexOf('\n');
+     final int secondCrInGeneratedWs = firstCrInGeneratedWs != -1 ? whiteSpace.indexOf('\n', firstCrInGeneratedWs + 1):-1;
+     final int firstCrInPreviousWs = s.indexOf('\n');
+     final int secondCrInPreviousWs = firstCrInPreviousWs != -1 ? s.indexOf('\n', firstCrInPreviousWs + 1):-1;
+
+     boolean knowHowToModifyCData = false;
+
+     if (secondCrInPreviousWs != -1 && secondCrInGeneratedWs != -1 && cdataPos > firstCrInPreviousWs && cdataPos < secondCrInPreviousWs ) {
+       whiteSpace = whiteSpace.substring(0, secondCrInGeneratedWs) + s.substring(firstCrInPreviousWs + 1, secondCrInPreviousWs) + whiteSpace.substring(secondCrInGeneratedWs);
+       knowHowToModifyCData = true;
+     }
+     if (!knowHowToModifyCData) whiteSpace = null;
+     return whiteSpace;
+   }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlFormattingModelBuilder.java b/xml/impl/src/com/intellij/lang/xml/XmlFormattingModelBuilder.java
new file mode 100644
index 0000000..d87bdf4
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlFormattingModelBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.formatting.FormattingModel;
+import com.intellij.formatting.FormattingModelBuilder;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.formatter.FormattingDocumentModelImpl;
+import com.intellij.psi.formatter.xml.XmlBlock;
+import com.intellij.psi.formatter.xml.XmlPolicy;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.impl.source.tree.TreeUtil;
+import org.jetbrains.annotations.NotNull;
+
+public class XmlFormattingModelBuilder implements FormattingModelBuilder {
+  
+  @NotNull
+  public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) {
+    final ASTNode root = TreeUtil.getFileElement((TreeElement)SourceTreeToPsiMap.psiElementToTree(element));
+    final FormattingDocumentModelImpl documentModel = FormattingDocumentModelImpl.createOn(element.getContainingFile());
+    return new XmlFormattingModel(element.getContainingFile(),
+                                                           new XmlBlock(root, null, null, new XmlPolicy(settings, documentModel), null, null, false),
+                                                           documentModel);
+  }
+
+  public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlLiteralEscaper.java b/xml/impl/src/com/intellij/lang/xml/XmlLiteralEscaper.java
new file mode 100644
index 0000000..74df4c2
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlLiteralEscaper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.LiteralEscaper;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlToken;
+
+/**
+ * @author Gregory.Shrago
+ */
+public class XmlLiteralEscaper implements LiteralEscaper {
+  public String getEscapedText(PsiElement context, String originalText) {
+    if (context instanceof XmlToken) {
+      context = context.getParent();
+    }
+
+    ASTNode contextNode = context != null ? context.getNode():null;
+    if (contextNode != null && contextNode.getElementType() == XmlElementType.XML_CDATA) {
+      return originalText;
+    }
+    return escapeText(originalText);
+  }
+
+  public String escapeText(String originalText) {
+    return StringUtil.escapeXml(originalText);
+  }
+
+  public String unescapeText(String originalText) {
+    return StringUtil.unescapeXml(originalText);
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlStructureViewBuilderFactory.java b/xml/impl/src/com/intellij/lang/xml/XmlStructureViewBuilderFactory.java
new file mode 100644
index 0000000..2282b17
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlStructureViewBuilderFactory.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.ide.structureView.StructureViewBuilder;
+import com.intellij.ide.structureView.StructureViewModel;
+import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
+import com.intellij.ide.structureView.impl.xml.XmlStructureViewTreeModel;
+import com.intellij.ide.structureView.xml.XmlStructureViewBuilderProvider;
+import com.intellij.lang.Language;
+import com.intellij.lang.LanguageStructureViewBuilder;
+import com.intellij.lang.PsiStructureViewFactory;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class XmlStructureViewBuilderFactory implements PsiStructureViewFactory {
+  @Nullable
+  public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) {
+    if (!(psiFile instanceof XmlFile)) {
+      return null;
+    }
+    StructureViewBuilder builder = getStructureViewBuilderForExtensions(psiFile);
+    if (builder != null) {
+      return builder;
+    }
+
+    for (XmlStructureViewBuilderProvider xmlStructureViewBuilderProvider : getStructureViewBuilderProviders()) {
+      final StructureViewBuilder structureViewBuilder = xmlStructureViewBuilderProvider.createStructureViewBuilder((XmlFile)psiFile);
+      if (structureViewBuilder != null) {
+        return structureViewBuilder;
+      }
+    }
+
+    return new TreeBasedStructureViewBuilder() {
+      @NotNull
+      public StructureViewModel createStructureViewModel() {
+        return new XmlStructureViewTreeModel((XmlFile)psiFile);
+      }
+    };
+  }
+
+  private static XmlStructureViewBuilderProvider[] getStructureViewBuilderProviders() {
+    return (XmlStructureViewBuilderProvider[])Extensions.getExtensions(XmlStructureViewBuilderProvider.EXTENSION_POINT_NAME);
+  }
+
+  @Nullable
+  private static StructureViewBuilder getStructureViewBuilderForExtensions(final PsiFile psiFile) {
+    for (Language language : XMLLanguage.INSTANCE.getLanguageExtensionsForFile(psiFile)) {
+      PsiStructureViewFactory factory = LanguageStructureViewBuilder.INSTANCE.forLanguage(language);
+      if (factory == null) continue;
+      final StructureViewBuilder builder = factory.getStructureViewBuilder(psiFile);
+      if (builder != null) {
+        return builder;
+      }
+    }
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlSurroundDescriptor.java b/xml/impl/src/com/intellij/lang/xml/XmlSurroundDescriptor.java
new file mode 100644
index 0000000..f0683d3
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlSurroundDescriptor.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.codeInsight.template.HtmlContextType;
+import com.intellij.codeInsight.template.XmlContextType;
+import com.intellij.codeInsight.template.impl.TemplateContext;
+import com.intellij.codeInsight.template.impl.TemplateImpl;
+import com.intellij.lang.surroundWith.SurroundDescriptor;
+import com.intellij.lang.surroundWith.Surrounder;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiUtilBase;
+import com.intellij.psi.xml.XmlTagChild;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author ven
+ */
+public class XmlSurroundDescriptor implements SurroundDescriptor {
+  @NotNull public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) {
+    final Pair<XmlTagChild, XmlTagChild> childrenInRange = XmlUtil.findTagChildrenInRange(file, startOffset, endOffset);
+    if (childrenInRange == null) {
+      final PsiElement elementAt = file.findElementAt(startOffset);
+      if (elementAt instanceof XmlToken &&
+          ((XmlToken)elementAt).getTokenType() == XmlTokenType.XML_DATA_CHARACTERS) {
+        return new PsiElement[] {elementAt};
+      }
+      return PsiElement.EMPTY_ARRAY;
+    }
+    List<PsiElement> result = new ArrayList<PsiElement>();
+    PsiElement first = childrenInRange.getFirst();
+    PsiElement last = childrenInRange.getSecond();
+    while(true) {
+      result.add(first);
+      if (first == last) break;
+      first = first.getNextSibling();
+    }
+
+    return PsiUtilBase.toPsiElementArray(result);
+  }
+
+  @NotNull public Surrounder[] getSurrounders() {
+    return new Surrounder[0]; //everything is in live templates now
+  }
+
+  @Override
+  public boolean isExclusive() {
+    return false;
+  }
+
+  protected boolean isEnabled(final TemplateImpl template) {
+    final TemplateContext context = template.getTemplateContext();
+    return context.isEnabled(new XmlContextType()) || context.isEnabled(new HtmlContextType());
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlUnwrapDescriptor.java b/xml/impl/src/com/intellij/lang/xml/XmlUnwrapDescriptor.java
new file mode 100644
index 0000000..deb5187
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlUnwrapDescriptor.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.codeInsight.unwrap.LanguageUnwrappers;
+import com.intellij.codeInsight.unwrap.UnwrapDescriptor;
+import com.intellij.codeInsight.unwrap.Unwrapper;
+import com.intellij.lang.Language;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class XmlUnwrapDescriptor implements UnwrapDescriptor {
+  public List<Pair<PsiElement, Unwrapper>> collectUnwrappers(Project project, Editor editor, PsiFile file) {
+    int offset = editor.getCaretModel().getOffset();
+
+    PsiElement e1 = file.findElementAt(offset);
+    if (e1 != null) {
+      Language language = e1.getParent().getLanguage();
+      if (language != file.getLanguage()) {
+        UnwrapDescriptor unwrapDescriptor = LanguageUnwrappers.INSTANCE.forLanguage(language);
+        if (unwrapDescriptor != null && !(unwrapDescriptor instanceof XmlUnwrapDescriptor)) {
+          return unwrapDescriptor.collectUnwrappers(project, editor, file);
+        }
+      }
+    }
+
+    List<Pair<PsiElement, Unwrapper>> result = new ArrayList<Pair<PsiElement, Unwrapper>>();
+
+    FileViewProvider viewProvider = file.getViewProvider();
+
+    for (Language language : viewProvider.getLanguages()) {
+      UnwrapDescriptor unwrapDescriptor = LanguageUnwrappers.INSTANCE.forLanguage(language);
+      if (unwrapDescriptor instanceof XmlUnwrapDescriptor) {
+        PsiElement e = viewProvider.findElementAt(offset, language);
+
+        PsiElement tag = PsiTreeUtil.getParentOfType(e, XmlTag.class);
+        while (tag != null) {
+          if (XmlChildRole.START_TAG_NAME_FINDER.findChild(tag.getNode()) != null) { // Exclude implicit tags suck as 'jsp:root'
+            result.add(new Pair<PsiElement, Unwrapper>(tag, new XmlEnclosingTagUnwrapper()));
+          }
+          tag = PsiTreeUtil.getParentOfType(tag, XmlTag.class);
+        }
+      }
+    }
+
+    Collections.sort(result, new Comparator<Pair<PsiElement, Unwrapper>>() {
+      @Override
+      public int compare(Pair<PsiElement, Unwrapper> o1, Pair<PsiElement, Unwrapper> o2) {
+        return o2.first.getTextOffset() - o1.first.getTextOffset();
+      }
+    });
+
+    return result;
+  }
+
+  public boolean showOptionsDialog() {
+    return true;
+  }
+
+  public boolean shouldTryToRestoreCaretPosition() {
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlWhiteSpaceFormattingStrategy.java b/xml/impl/src/com/intellij/lang/xml/XmlWhiteSpaceFormattingStrategy.java
new file mode 100644
index 0000000..10cab62
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlWhiteSpaceFormattingStrategy.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.lang.ASTFactory;
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.formatter.WhiteSpaceFormattingStrategyAdapter;
+import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
+import com.intellij.psi.impl.source.tree.Factory;
+import com.intellij.psi.impl.source.tree.LeafElement;
+import com.intellij.psi.impl.source.tree.SharedImplUtil;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlText;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.CharTable;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Denis Zhdanov
+ * @since 12/6/11 4:51 PM
+ */
+public class XmlWhiteSpaceFormattingStrategy extends WhiteSpaceFormattingStrategyAdapter {
+
+  private static void addWhitespaceToTagBody(final ASTNode treePrev, final LeafElement whiteSpaceElement) {
+    final CharTable charTable = SharedImplUtil.findCharTableByTree(treePrev);
+    final ASTNode treeParent = treePrev.getTreeParent();
+
+    final boolean before;
+    final XmlText xmlText;
+    if(treePrev.getElementType() == XmlElementType.XML_TEXT) {
+      xmlText = (XmlText)treePrev.getPsi();
+      before = true;
+    }
+    else if(treePrev.getTreePrev().getElementType() == XmlElementType.XML_TEXT){
+      xmlText = (XmlText)treePrev.getTreePrev().getPsi();
+      before = false;
+    }
+    else{
+      xmlText = (XmlText)Factory.createCompositeElement(XmlElementType.XML_TEXT, charTable, treeParent.getPsi().getManager());
+      CodeEditUtil.setNodeGenerated(xmlText.getNode(), true);
+      treeParent.addChild(xmlText.getNode(), treePrev);
+      before = true;
+    }
+    final ASTNode node = xmlText.getNode();
+    assert node != null;
+    final TreeElement anchorInText = (TreeElement) (before ? node.getFirstChildNode() : node.getLastChildNode());
+    if (anchorInText == null) node.addChild(whiteSpaceElement);
+    else if (anchorInText.getElementType() != XmlTokenType.XML_WHITE_SPACE) node.addChild(whiteSpaceElement, before ? anchorInText : null);
+    else {
+      final String text = before ? whiteSpaceElement.getText() + anchorInText.getText() : anchorInText.getText() +
+                                                                                          whiteSpaceElement.getText();
+      node.replaceChild(anchorInText, ASTFactory.whitespace(text));
+    }
+  }
+
+  protected boolean isInsideTagBody(@NotNull ASTNode place) {
+    final ASTNode treeParent = place.getTreeParent();
+    if(treeParent.getElementType() != XmlElementType.XML_TAG
+       && treeParent.getElementType() != XmlElementType.HTML_TAG) return false;
+    while(place != null){
+      if(place.getElementType() == XmlTokenType.XML_TAG_END) return true;
+      place = place.getTreePrev();
+    }
+    return false;
+  }
+
+  public boolean addWhitespace(@NotNull final ASTNode treePrev, @NotNull final LeafElement whiteSpaceElement) {
+    if (isInsideTagBody(treePrev)) {
+      addWhitespaceToTagBody(treePrev, whiteSpaceElement);
+      return true;
+    }
+
+    return false;
+  }
+
+  public boolean containsWhitespacesOnly(@NotNull final ASTNode node) {
+    return (node.getElementType() == XmlTokenType.XML_DATA_CHARACTERS) &&
+           node.getText().trim().length() == 0;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlWordCompletionFilter.java b/xml/impl/src/com/intellij/lang/xml/XmlWordCompletionFilter.java
new file mode 100644
index 0000000..3fbd001
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/xml/XmlWordCompletionFilter.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang.xml;
+
+import com.intellij.codeInsight.completion.CompletionProcess;
+import com.intellij.codeInsight.completion.CompletionService;
+import com.intellij.lang.DefaultWordCompletionFilter;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+
+public class XmlWordCompletionFilter extends DefaultWordCompletionFilter {
+  private final static TokenSet ENABLED_TOKENS = TokenSet.create(XmlElementType.XML_CDATA,
+                                                                 XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN,
+                                                                 XmlTokenType.XML_DATA_CHARACTERS);
+  public boolean isWordCompletionEnabledIn(final IElementType element) {
+    return super.isWordCompletionEnabledIn(element) || ENABLED_TOKENS.contains(element);
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/lexer/BaseHtmlLexer.java b/xml/impl/src/com/intellij/lexer/BaseHtmlLexer.java
new file mode 100644
index 0000000..a357699
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/BaseHtmlLexer.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lexer;
+
+import com.intellij.codeInsight.completion.CompletionUtil;
+import com.intellij.lang.HtmlScriptContentProvider;
+import com.intellij.lang.Language;
+import com.intellij.lang.LanguageHtmlScriptContentProvider;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.impl.source.tree.TreeUtil;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.text.CharArrayUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.HashMap;
+
+/**
+ * @author Maxim.Mossienko
+ */
+abstract class BaseHtmlLexer extends DelegateLexer {
+  protected static final int BASE_STATE_MASK = 0x3F;
+  private static final int SEEN_STYLE = 0x40;
+  private static final int SEEN_TAG = 0x80;
+  private static final int SEEN_SCRIPT = 0x100;
+  private static final int SEEN_ATTRIBUTE = 0x200;
+  private static final int SEEN_CONTENT_TYPE = 0x400;
+  protected static final int BASE_STATE_SHIFT = 11;
+  @Nullable
+  protected static Language ourDefaultLanguage = Language.findLanguageByID("JavaScript");
+
+  private boolean seenTag;
+  private boolean seenAttribute;
+  private boolean seenStyle;
+  private boolean seenScript;
+
+  @Nullable
+  protected String scriptType = null;
+
+  private final boolean caseInsensitive;
+  private boolean seenContentType;
+  private CharSequence cachedBufferSequence;
+  private Lexer lexerOfCacheBufferSequence;
+
+  static final TokenSet TOKENS_TO_MERGE = TokenSet.create(XmlTokenType.XML_COMMENT_CHARACTERS, XmlTokenType.XML_WHITE_SPACE, XmlTokenType.XML_REAL_WHITE_SPACE,
+                                                          XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN, XmlTokenType.XML_DATA_CHARACTERS,
+                                                          XmlTokenType.XML_TAG_CHARACTERS);
+
+  public interface TokenHandler {
+    void handleElement(Lexer lexer);
+  }
+
+  public class XmlNameHandler implements TokenHandler {
+    @NonNls private static final String TOKEN_SCRIPT = "script";
+    @NonNls private static final String TOKEN_STYLE = "style";
+    @NonNls private static final String TOKEN_ON = "on";
+
+    public void handleElement(Lexer lexer) {
+      final CharSequence buffer;
+      if (lexerOfCacheBufferSequence == lexer) {
+        buffer = cachedBufferSequence;
+      } else {
+        cachedBufferSequence = lexer.getBufferSequence();
+        buffer = cachedBufferSequence;
+        lexerOfCacheBufferSequence = lexer;
+      }
+      final char firstCh = buffer.charAt(lexer.getTokenStart());
+
+      if (seenScript && !seenTag) {
+        seenContentType = false;
+
+        if (((firstCh == 'l' || firstCh == 't') || (caseInsensitive && (firstCh == 'L' || firstCh == 'T')))) {
+          @NonNls String name = TreeUtil.getTokenText(lexer);
+          if (caseInsensitive) name = name.toLowerCase();
+
+          if ("language".equals(name) || "type".equals(name)) {
+            seenContentType = true;
+          }
+        }
+
+        return;
+      }
+
+      if (firstCh !='o' && firstCh !='s' &&
+          (!caseInsensitive || (firstCh !='S' && firstCh !='O') )
+          ) {
+        return; // optimization
+      }
+
+      String name = TreeUtil.getTokenText(lexer);
+      if (caseInsensitive) name = name.toLowerCase();
+
+      final boolean style = name.equals(TOKEN_STYLE);
+      final int state = getState() & BASE_STATE_MASK;
+      final boolean script = name.equals(TOKEN_SCRIPT) ||
+                       ((name.startsWith(TOKEN_ON) && name.indexOf(':') == -1 && !isHtmlTagState(state)));
+
+      if (style || script) {
+        // encountered tag name in end of tag
+        if (seenTag) {
+          if (isHtmlTagState(state)) {
+            seenTag = false;
+          }
+          return;
+        }
+
+        seenStyle = style;
+        seenScript = script;
+
+        if (!isHtmlTagState(state)) {
+          seenAttribute=true;
+        }
+      }
+    }
+  }
+
+  class XmlAttributeValueEndHandler implements TokenHandler {
+    public void handleElement(Lexer lexer) {
+      if (seenAttribute) {
+        seenStyle = false;
+        seenScript = false;
+        seenAttribute = false;
+      }
+      seenContentType = false;
+    }
+  }
+
+  class XmlAttributeValueHandler implements TokenHandler {
+    public void handleElement(Lexer lexer) {
+      if (seenContentType) {
+        if(!seenScript || seenAttribute) {
+          return; // something invalid
+        }
+
+        @NonNls String mimeType = TreeUtil.getTokenText(lexer);
+        if (caseInsensitive) mimeType = mimeType.toLowerCase();
+        if (supportMimeType(mimeType)) {
+          scriptType = mimeType;
+        }
+        else {
+          seenScript = false;
+          seenTag = true;    // will be switched of on tag name in end
+        }
+      }
+    }
+  }
+
+  private boolean supportMimeType(String mimeType) {
+    return findScriptContentProvider(mimeType) != null;
+  }
+
+  @Nullable
+  protected IElementType getCurrentScriptElementType() {
+    HtmlScriptContentProvider scriptContentProvider = findScriptContentProvider(scriptType);
+    return scriptContentProvider == null ? null : scriptContentProvider.getScriptElementType();
+  }
+
+  @Nullable
+  protected static HtmlScriptContentProvider findScriptContentProvider(@Nullable String mimeType) {
+    if (StringUtil.isEmpty(mimeType)) {
+      return ourDefaultLanguage != null ? LanguageHtmlScriptContentProvider.getScriptContentProvider(ourDefaultLanguage) : null;
+    }
+    Collection<Language> instancesByMimeType = Language.findInstancesByMimeType(mimeType != null ? mimeType.trim() : null);
+    for (Language language : instancesByMimeType) {
+      HtmlScriptContentProvider scriptContentProvider = LanguageHtmlScriptContentProvider.getScriptContentProvider(language);
+      if (scriptContentProvider != null) {
+        return scriptContentProvider;
+      }
+    }
+    return null;
+  }
+
+  class XmlTagClosedHandler implements TokenHandler {
+    public void handleElement(Lexer lexer) {
+      if (seenAttribute) {
+        seenScript=false;
+        seenStyle=false;
+
+        seenAttribute=false;
+      } else {
+        if (seenStyle || seenScript) {
+          seenTag=true;
+        }
+      }
+    }
+  }
+
+  class XmlTagEndHandler implements TokenHandler {
+    public void handleElement(Lexer lexer) {
+      seenStyle=false;
+      seenScript=false;
+      seenAttribute=false;
+      seenContentType=false;
+      scriptType = null;
+    }
+  }
+
+  private final HashMap<IElementType,TokenHandler> tokenHandlers = new HashMap<IElementType, TokenHandler>();
+
+  protected BaseHtmlLexer(Lexer _baseLexer, boolean _caseInsensitive)  {
+    super(_baseLexer);
+    caseInsensitive = _caseInsensitive;
+
+    XmlNameHandler value = new XmlNameHandler();
+    tokenHandlers.put(XmlTokenType.XML_NAME,value);
+    tokenHandlers.put(XmlTokenType.XML_TAG_NAME,value);
+    tokenHandlers.put(XmlTokenType.XML_TAG_END,new XmlTagClosedHandler());
+    tokenHandlers.put(XmlTokenType.XML_END_TAG_START,new XmlTagEndHandler());
+    tokenHandlers.put(XmlTokenType.XML_EMPTY_ELEMENT_END,new XmlTagEndHandler());
+    tokenHandlers.put(XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER,new XmlAttributeValueEndHandler());
+    tokenHandlers.put(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN,new XmlAttributeValueHandler());
+  }
+
+  protected void registerHandler(IElementType elementType, TokenHandler value) {
+    final TokenHandler tokenHandler = tokenHandlers.get(elementType);
+
+    if (tokenHandler != null) {
+      final TokenHandler newHandler = value;
+      value = new TokenHandler() {
+        public void handleElement(final Lexer lexer) {
+          tokenHandler.handleElement(lexer);
+          newHandler.handleElement(lexer);
+        }
+      };
+    }
+
+    tokenHandlers.put(elementType,value);
+  }
+
+  public void start(final CharSequence buffer, final int startOffset, final int endOffset, final int initialState) {
+    initState(initialState);
+    super.start(buffer, startOffset, endOffset, initialState & BASE_STATE_MASK);
+  }
+
+  private void initState(final int initialState) {
+    seenScript = (initialState & SEEN_SCRIPT)!=0;
+    seenStyle = (initialState & SEEN_STYLE)!=0;
+    seenTag = (initialState & SEEN_TAG)!=0;
+    seenAttribute = (initialState & SEEN_ATTRIBUTE)!=0;
+    seenContentType = (initialState & SEEN_CONTENT_TYPE) != 0;
+    lexerOfCacheBufferSequence = null;
+    cachedBufferSequence = null;
+  }
+
+  protected int skipToTheEndOfTheEmbeddment() {
+    Lexer base = getDelegate();
+    int tokenEnd = base.getTokenEnd();
+    int lastState = 0;
+    int lastStart = 0;
+
+    final CharSequence buf = base.getBufferSequence();
+    final char[] bufArray = CharArrayUtil.fromSequenceWithoutCopying(buf);
+
+    if (seenTag) {
+      FoundEnd:
+      while(true) {
+        FoundEndOfTag:
+        while(base.getTokenType() != XmlTokenType.XML_END_TAG_START) {
+          if (base.getTokenType() == XmlTokenType.XML_COMMENT_CHARACTERS) {
+            // we should terminate on first occurence of </
+            final int end = base.getTokenEnd();
+
+            for(int i = base.getTokenStart(); i < end; ++i) {
+              if ((bufArray != null ? bufArray[i ]:buf.charAt(i)) == '<' &&
+                  i + 1 < end &&
+                  (bufArray != null ? bufArray[i+1]:buf.charAt(i+1)) == '/') {
+                tokenEnd = i;
+                lastStart = i - 1;
+                lastState = 0;
+
+                break FoundEndOfTag;
+              }
+            }
+          }
+
+          lastState = base.getState();
+          tokenEnd = base.getTokenEnd();
+          lastStart = base.getTokenStart();
+          if (tokenEnd == getBufferEnd()) break FoundEnd;
+          base.advance();
+        }
+
+        // check if next is script
+        if (base.getTokenType() != XmlTokenType.XML_END_TAG_START) { // we are inside comment
+          base.start(buf,lastStart+1,getBufferEnd(),lastState);
+          base.getTokenType();
+          base.advance();
+        } else {
+          base.advance();
+        }
+
+        while(XmlTokenType.WHITESPACES.contains(base.getTokenType())) {
+          base.advance();
+        }
+
+        if (base.getTokenType() == XmlTokenType.XML_NAME) {
+          String name = TreeUtil.getTokenText(base);
+          if (caseInsensitive) name = name.toLowerCase();
+
+          if((hasSeenScript() && XmlNameHandler.TOKEN_SCRIPT.equals(name)) ||
+             (hasSeenStyle() && XmlNameHandler.TOKEN_STYLE.equals(name)) ||
+             CompletionUtil.DUMMY_IDENTIFIER_TRIMMED.equalsIgnoreCase(name)) {
+            break; // really found end
+          }
+        }
+      }
+
+      base.start(buf,lastStart,getBufferEnd(),lastState);
+      base.getTokenType();
+    } else if (seenAttribute) {
+      while(true) {
+        if (!isValidAttributeValueTokenType(base.getTokenType())) break;
+
+        tokenEnd = base.getTokenEnd();
+        lastState = base.getState();
+        lastStart = base.getTokenStart();
+
+        if (tokenEnd == getBufferEnd()) break;
+        base.advance();
+      }
+
+      base.start(buf,lastStart,getBufferEnd(),lastState);
+      base.getTokenType();
+    }
+    return tokenEnd;
+  }
+
+  protected boolean isValidAttributeValueTokenType(final IElementType tokenType) {
+    return tokenType == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN ||
+           tokenType == XmlTokenType.XML_ENTITY_REF_TOKEN ||
+            tokenType == XmlTokenType.XML_CHAR_ENTITY_REF;
+  }
+
+  public void advance() {
+    super.advance();
+    IElementType type = getDelegate().getTokenType();
+    TokenHandler tokenHandler = tokenHandlers.get(type);
+    if (tokenHandler!=null) tokenHandler.handleElement(this);
+  }
+
+
+  public int getState() {
+    int state = super.getState();
+
+    state |= ((seenScript)?SEEN_SCRIPT:0);
+    state |= ((seenTag)?SEEN_TAG:0);
+    state |= ((seenStyle)?SEEN_STYLE:0);
+    state |= ((seenAttribute)?SEEN_ATTRIBUTE:0);
+    state |= ((seenContentType)?SEEN_CONTENT_TYPE:0);
+
+    return state;
+  }
+
+  protected final boolean hasSeenStyle() {
+    return seenStyle;
+  }
+
+  protected final boolean hasSeenAttribute() {
+    return seenAttribute;
+  }
+
+  protected final boolean hasSeenTag() {
+    return seenTag;
+  }
+
+  protected boolean hasSeenScript() {
+    return seenScript;
+  }
+
+  protected abstract boolean isHtmlTagState(int state);
+}
diff --git a/xml/impl/src/com/intellij/lexer/DtdLexer.java b/xml/impl/src/com/intellij/lexer/DtdLexer.java
new file mode 100644
index 0000000..e7f14f0
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/DtdLexer.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lexer;
+
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlTokenType;
+
+/**
+ * @author ik
+ */
+public class DtdLexer extends MergingLexerAdapter {
+  private final static TokenSet TOKENS_TO_MERGE =
+    TokenSet.create(XmlTokenType.XML_DATA_CHARACTERS, XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN, XmlTokenType.XML_PI_TARGET);
+
+  public DtdLexer(boolean highlightingMode) {
+    super(new FlexAdapter(new _DtdLexer(highlightingMode)), TOKENS_TO_MERGE);
+  }
+}
diff --git a/xml/impl/src/com/intellij/lexer/HtmlEmbeddedTokenTypesProvider.java b/xml/impl/src/com/intellij/lexer/HtmlEmbeddedTokenTypesProvider.java
new file mode 100644
index 0000000..60a8d03
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/HtmlEmbeddedTokenTypesProvider.java
@@ -0,0 +1,17 @@
+package com.intellij.lexer;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.tree.IElementType;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public interface HtmlEmbeddedTokenTypesProvider {
+
+  ExtensionPointName<HtmlEmbeddedTokenTypesProvider> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.html.embeddedTokenTypesProvider");
+
+  /** style or script */
+  String getName();
+  IElementType getElementType();
+  IElementType getInlineElementType();
+}
diff --git a/xml/impl/src/com/intellij/lexer/HtmlHighlightingLexer.java b/xml/impl/src/com/intellij/lexer/HtmlHighlightingLexer.java
new file mode 100644
index 0000000..17d95dd
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/HtmlHighlightingLexer.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lexer;
+
+import com.intellij.lang.HtmlInlineScriptTokenTypesProvider;
+import com.intellij.lang.HtmlScriptContentProvider;
+import com.intellij.lang.Language;
+import com.intellij.lang.LanguageHtmlInlineScriptTokenTypesProvider;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.Nullable;
+
+public class HtmlHighlightingLexer extends BaseHtmlLexer {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.lexer.HtmlHighlightingLexer");
+
+  private static final int EMBEDDED_LEXER_ON = 0x1 << BASE_STATE_SHIFT;
+  private static final int EMBEDDED_LEXER_STATE_SHIFT = BASE_STATE_SHIFT + 1;
+
+  private Lexer embeddedLexer;
+  private Lexer styleLexer;
+  private Lexer scriptLexer;
+  protected Lexer elLexer;
+  private boolean hasNoEmbeddments;
+  private final static FileType ourStyleFileType = FileTypeManager.getInstance().getStdFileType("CSS");
+  private static FileType ourInlineScriptFileType = null;
+
+  static {
+    // At the moment only JS.
+    HtmlInlineScriptTokenTypesProvider provider =
+      LanguageHtmlInlineScriptTokenTypesProvider.getInlineScriptProvider(Language.findLanguageByID("JavaScript"));
+    ourInlineScriptFileType = provider != null ? provider.getFileType() : null;
+  }
+
+  public class XmlEmbeddmentHandler implements TokenHandler {
+    public void handleElement(Lexer lexer) {
+      if (!hasSeenStyle() && !hasSeenScript() || hasNoEmbeddments) return;
+      final IElementType tokenType = lexer.getTokenType();
+
+      if ((tokenType==XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN && hasSeenAttribute()) ||
+          (tokenType==XmlTokenType.XML_DATA_CHARACTERS && hasSeenTag()) ||
+          tokenType==XmlTokenType.XML_COMMENT_CHARACTERS && hasSeenTag()
+          ) {
+        setEmbeddedLexer();
+
+        if (embeddedLexer!=null) {
+          embeddedLexer.start(
+            getBufferSequence(),
+            HtmlHighlightingLexer.super.getTokenStart(),
+            skipToTheEndOfTheEmbeddment(),
+            embeddedLexer instanceof EmbedmentLexer ? ((EmbedmentLexer)embeddedLexer).getEmbeddedInitialState(tokenType) : 0
+          );
+
+          if (embeddedLexer.getTokenType() == null) {
+            // no content for embeddment
+            embeddedLexer = null;
+          }
+        }
+      }
+    }
+  }
+
+  public class ElEmbeddmentHandler implements TokenHandler {
+    public void handleElement(Lexer lexer) {
+      setEmbeddedLexer();
+      if (embeddedLexer != null) {
+        embeddedLexer.start(getBufferSequence(), HtmlHighlightingLexer.super.getTokenStart(), HtmlHighlightingLexer.super.getTokenEnd());
+      }
+    }
+  }
+
+  public HtmlHighlightingLexer() {
+    this(new MergingLexerAdapter(new FlexAdapter(new _HtmlLexer()),TOKENS_TO_MERGE),true);
+  }
+
+  protected HtmlHighlightingLexer(Lexer lexer, boolean caseInsensitive) {
+    super(lexer,caseInsensitive);
+
+    XmlEmbeddmentHandler value = new XmlEmbeddmentHandler();
+    registerHandler(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN,value);
+    registerHandler(XmlTokenType.XML_DATA_CHARACTERS,value);
+    registerHandler(XmlTokenType.XML_COMMENT_CHARACTERS,value);
+  }
+
+  public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
+    super.start(buffer, startOffset, endOffset, initialState);
+
+    if ((initialState & EMBEDDED_LEXER_ON)!=0) {
+      int state = initialState >> EMBEDDED_LEXER_STATE_SHIFT;
+      setEmbeddedLexer();
+      LOG.assertTrue(embeddedLexer!=null);
+      embeddedLexer.start(buffer,startOffset,skipToTheEndOfTheEmbeddment(),state);
+    } else {
+      embeddedLexer = null;
+    }
+  }
+
+  private void setEmbeddedLexer() {
+    Lexer newLexer = null;
+    if (hasSeenStyle()) {
+      if (styleLexer==null) {
+        styleLexer = (ourStyleFileType!=null)? SyntaxHighlighterFactory.getSyntaxHighlighter(ourStyleFileType, null, null).getHighlightingLexer():null;
+      }
+
+      newLexer = styleLexer;
+    } else if (hasSeenScript()) {
+      if (scriptLexer == null) {
+        if (hasSeenTag()) {
+          HtmlScriptContentProvider provider = findScriptContentProvider(scriptType);
+          scriptLexer = provider != null ? provider.getHighlightingLexer() : null;
+        }
+        else if (hasSeenAttribute()) {
+          SyntaxHighlighter syntaxHighlighter =
+            (ourInlineScriptFileType != null) ? SyntaxHighlighterFactory.getSyntaxHighlighter(ourInlineScriptFileType, null, null) : null;
+          scriptLexer = syntaxHighlighter != null ? syntaxHighlighter.getHighlightingLexer() : null;
+        }
+      }
+      newLexer = scriptLexer;
+    }
+    else {
+      newLexer = createELLexer(newLexer);
+    }
+
+    if (newLexer!=null) {
+      embeddedLexer = newLexer;
+    }
+  }
+
+  @Nullable
+  protected Lexer createELLexer(Lexer newLexer) {
+    return newLexer;
+  }
+
+  public void advance() {
+    if (embeddedLexer!=null) {
+      embeddedLexer.advance();
+      if (embeddedLexer.getTokenType()==null) {
+        embeddedLexer=null;
+      }
+    }
+
+    if (embeddedLexer==null) {
+      super.advance();
+    }
+  }
+
+  public IElementType getTokenType() {
+    if (embeddedLexer!=null) {
+      return embeddedLexer.getTokenType();
+    } else {
+      IElementType tokenType = super.getTokenType();
+
+      // TODO: fix no DOCTYPE highlighting
+      if (tokenType == null) return tokenType;
+
+      if (tokenType==XmlTokenType.XML_NAME) {
+        // we need to convert single xml_name for tag name and attribute name into to separate
+        // lex types for the highlighting!
+        final int state = getState() & BASE_STATE_MASK;
+
+        if (isHtmlTagState(state)) {
+          tokenType = XmlTokenType.XML_TAG_NAME;
+        }
+      }
+      else if (tokenType == XmlTokenType.XML_WHITE_SPACE || tokenType == XmlTokenType.XML_REAL_WHITE_SPACE) {
+        if (hasSeenTag() && (hasSeenStyle() || hasSeenScript())) {
+          tokenType = XmlTokenType.XML_WHITE_SPACE;
+        } else {
+          tokenType = (getState()!=0)?XmlTokenType.TAG_WHITE_SPACE:XmlTokenType.XML_REAL_WHITE_SPACE;
+        }
+      } else if (tokenType == XmlTokenType.XML_CHAR_ENTITY_REF ||
+               tokenType == XmlTokenType.XML_ENTITY_REF_TOKEN
+              ) {
+        // we need to convert char entity ref & entity ref in comments as comment chars
+        final int state = getState() & BASE_STATE_MASK;
+        if (state == _HtmlLexer.COMMENT) return XmlTokenType.XML_COMMENT_CHARACTERS;
+      }
+      return tokenType;
+    }
+  }
+
+  public int getTokenStart() {
+    if (embeddedLexer!=null) {
+      return embeddedLexer.getTokenStart();
+    } else {
+      return super.getTokenStart();
+    }
+  }
+
+  public int getTokenEnd() {
+    if (embeddedLexer!=null) {
+      return embeddedLexer.getTokenEnd();
+    } else {
+      return super.getTokenEnd();
+    }
+  }
+
+  public int getState() {
+    int state = super.getState();
+
+    state |= ((embeddedLexer!=null)?EMBEDDED_LEXER_ON:0);
+    if (embeddedLexer!=null) state |= (embeddedLexer.getState() << EMBEDDED_LEXER_STATE_SHIFT);
+
+    return state;
+  }
+
+  protected boolean isHtmlTagState(int state) {
+    return state == _HtmlLexer.START_TAG_NAME || state == _HtmlLexer.END_TAG_NAME ||
+           state  == _HtmlLexer.START_TAG_NAME2 || state == _HtmlLexer.END_TAG_NAME2;
+  }
+
+  public void setHasNoEmbeddments(boolean hasNoEmbeddments) {
+    this.hasNoEmbeddments = hasNoEmbeddments;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lexer/HtmlLexer.java b/xml/impl/src/com/intellij/lexer/HtmlLexer.java
new file mode 100644
index 0000000..90b0e9a
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/HtmlLexer.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lexer;
+
+import com.intellij.lang.HtmlInlineScriptTokenTypesProvider;
+import com.intellij.lang.Language;
+import com.intellij.lang.LanguageHtmlInlineScriptTokenTypesProvider;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class HtmlLexer extends BaseHtmlLexer {
+  private static IElementType ourStyleElementType;
+  private static IElementType ourInlineStyleElementType;
+  private static IElementType ourInlineScriptElementType;
+
+  static {
+    HtmlEmbeddedTokenTypesProvider[] extensions = Extensions.getExtensions(HtmlEmbeddedTokenTypesProvider.EXTENSION_POINT_NAME);
+    for (HtmlEmbeddedTokenTypesProvider extension : extensions) {
+      if ("style".equals(extension.getName())) {
+        ourStyleElementType = extension.getElementType();
+        ourInlineStyleElementType = extension.getInlineElementType();
+      }
+    }
+    // At the moment only JS.
+    HtmlInlineScriptTokenTypesProvider provider =
+      LanguageHtmlInlineScriptTokenTypesProvider.getInlineScriptProvider(ourDefaultLanguage);
+    ourInlineScriptElementType = provider != null ? provider.getElementType() : null;
+  }
+
+  private IElementType myTokenType;
+  private int myTokenStart;
+  private int myTokenEnd;
+
+  @Override
+  public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
+    myTokenType = null;
+    super.start(buffer, startOffset, endOffset, initialState);
+  }
+
+  public void advance() {
+    myTokenType = null;
+    super.advance();
+  }
+
+  public IElementType getTokenType() {
+    if (myTokenType!=null) return myTokenType;
+    IElementType tokenType = super.getTokenType();
+
+    myTokenStart = super.getTokenStart();
+    myTokenEnd = super.getTokenEnd();
+
+    if (hasSeenStyle()) {
+      if (hasSeenTag() && ourStyleElementType!=null && isStartOfEmbeddmentTagContent(tokenType)) {
+        myTokenEnd = skipToTheEndOfTheEmbeddment();
+        tokenType = ourStyleElementType;
+      } else if (ourInlineStyleElementType!=null && isStartOfEmbeddmentAttributeValue(tokenType) && hasSeenAttribute()) {
+        tokenType = ourInlineStyleElementType;
+      }
+    } else if (hasSeenScript()) {
+      IElementType currentScriptElementType = getCurrentScriptElementType();
+      if (hasSeenTag() && currentScriptElementType != null && isStartOfEmbeddmentTagContent(tokenType)) {
+        myTokenEnd = skipToTheEndOfTheEmbeddment();
+        tokenType = currentScriptElementType;
+      } else if (hasSeenAttribute() && isStartOfEmbeddmentAttributeValue(tokenType) && ourInlineScriptElementType!=null) {
+        myTokenEnd = skipToTheEndOfTheEmbeddment();
+        tokenType = ourInlineScriptElementType;
+      }
+    }
+
+    return myTokenType = tokenType;
+  }
+
+  private static boolean isStartOfEmbeddmentAttributeValue(final IElementType tokenType) {
+    return tokenType == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+  }
+
+  private static boolean isStartOfEmbeddmentTagContent(final IElementType tokenType) {
+    return (tokenType == XmlTokenType.XML_DATA_CHARACTERS ||
+            tokenType == XmlTokenType.XML_CDATA_START ||
+            tokenType == XmlTokenType.XML_COMMENT_START ||
+            tokenType == XmlTokenType.XML_REAL_WHITE_SPACE || tokenType == TokenType.WHITE_SPACE
+    );
+  }
+
+  public HtmlLexer() {
+    this(new MergingLexerAdapter(new FlexAdapter(new _HtmlLexer()), TOKENS_TO_MERGE),true);
+  }
+
+  protected HtmlLexer(Lexer _baseLexer, boolean _caseInsensitive) {
+    super(_baseLexer,_caseInsensitive);
+  }
+
+  protected boolean isHtmlTagState(int state) {
+    return state == _HtmlLexer.START_TAG_NAME || state == _HtmlLexer.END_TAG_NAME;
+  }
+
+  public int getTokenStart() {
+    if (myTokenType!=null) {
+      return myTokenStart;
+    }
+    return super.getTokenStart();
+  }
+
+  public int getTokenEnd() {
+    if (myTokenType!=null) {
+      return myTokenEnd;
+    }
+    return super.getTokenEnd();
+  }
+}
diff --git a/xml/impl/src/com/intellij/lexer/XHtmlHighlightingLexer.java b/xml/impl/src/com/intellij/lexer/XHtmlHighlightingLexer.java
new file mode 100644
index 0000000..5f89e20
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/XHtmlHighlightingLexer.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lexer;
+
+public class XHtmlHighlightingLexer extends HtmlHighlightingLexer {
+  public XHtmlHighlightingLexer() {
+    this(new XmlLexer(true));
+  }
+
+  public XHtmlHighlightingLexer(Lexer baseLexer) {
+    super(baseLexer,false);
+  }
+
+  protected boolean isHtmlTagState(int state) {
+    return state == __XmlLexer.TAG || state == __XmlLexer.END_TAG;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/lexer/XHtmlLexer.java b/xml/impl/src/com/intellij/lexer/XHtmlLexer.java
new file mode 100644
index 0000000..784198c
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/XHtmlLexer.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lexer;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class XHtmlLexer extends HtmlLexer {
+  public XHtmlLexer(Lexer baseLexer) {
+    super(baseLexer, false);
+  }
+
+  public XHtmlLexer() {
+    this(new XmlLexer(true));
+  }
+
+  protected boolean isHtmlTagState(int state) {
+    return state == __XmlLexer.TAG || state == __XmlLexer.END_TAG;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lexer/XmlHighlightingLexer.java b/xml/impl/src/com/intellij/lexer/XmlHighlightingLexer.java
new file mode 100644
index 0000000..e485774
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/XmlHighlightingLexer.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lexer;
+
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+
+/**
+ * @author mike
+ */
+public class XmlHighlightingLexer extends DelegateLexer {
+  public XmlHighlightingLexer() {
+    super(new XmlLexer());
+  }
+
+  public IElementType getTokenType() {
+    IElementType tokenType = getDelegate().getTokenType();
+
+    if (tokenType == null) return tokenType;
+
+    int state = getState() & 0xF;
+
+    tokenType = fixWrongTokenTypes(tokenType, state);
+    if (tokenType != XmlTokenType.XML_COMMENT_CHARACTERS &&
+      tokenType != XmlTokenType.XML_COMMENT_END &&
+      tokenType != XmlTokenType.XML_COMMENT_START &&
+      tokenType != XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+
+      // TODO: do not know when this happens!
+      switch (state) {
+        case __XmlLexer.DOCTYPE:
+          tokenType = XmlTokenType.XML_DECL_START;
+          break;
+      }
+    }
+
+    return tokenType;
+  }
+
+  static IElementType fixWrongTokenTypes(IElementType tokenType, final int state) {
+    if (tokenType == XmlTokenType.XML_NAME) {
+      if (state == __XmlLexer.TAG || state == __XmlLexer.END_TAG) {
+        // translate XML names for tags into XmlTagName
+        tokenType = XmlTokenType.XML_TAG_NAME;
+      }
+    } else if (tokenType == XmlTokenType.XML_WHITE_SPACE) {
+      switch (state) {
+        case __XmlLexer.ATTR_LIST:
+        case __XmlLexer.ATTR:
+          tokenType = XmlTokenType.TAG_WHITE_SPACE; break;
+        default:
+          tokenType = XmlTokenType.XML_REAL_WHITE_SPACE; break;
+      }
+    } else if (tokenType == XmlTokenType.XML_CHAR_ENTITY_REF ||
+               tokenType == XmlTokenType.XML_ENTITY_REF_TOKEN
+              ) {
+      if (state == __XmlLexer.COMMENT) return XmlTokenType.XML_COMMENT_CHARACTERS;
+    }
+    return tokenType;
+  }
+}
diff --git a/xml/impl/src/com/intellij/lexer/XmlLexer.java b/xml/impl/src/com/intellij/lexer/XmlLexer.java
new file mode 100644
index 0000000..c215e77
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/XmlLexer.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lexer;
+
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlTokenType;
+
+import java.io.Reader;
+
+public class XmlLexer extends MergingLexerAdapter {
+  private final static TokenSet TOKENS_TO_MERGE = TokenSet.create(XmlTokenType.XML_DATA_CHARACTERS,
+                                                                  XmlTokenType.XML_TAG_CHARACTERS,
+                                                                  XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN,
+                                                                  XmlTokenType.XML_PI_TARGET,
+                                                                  XmlTokenType.XML_COMMENT_CHARACTERS);
+
+  public XmlLexer() {
+    this(false);
+  }
+
+  public XmlLexer(final boolean conditionalCommentsSupport) {
+    this(new _XmlLexer(new __XmlLexer((Reader)null), conditionalCommentsSupport));
+  }
+
+  public XmlLexer(Lexer baseLexer) {
+    super(baseLexer, TOKENS_TO_MERGE);
+  }
+}
diff --git a/xml/impl/src/com/intellij/lexer/_DtdLexer.flex b/xml/impl/src/com/intellij/lexer/_DtdLexer.flex
new file mode 100644
index 0000000..0869996
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/_DtdLexer.flex
@@ -0,0 +1,167 @@
+ /* It's an automatically generated code. Do not modify it. */
+package com.intellij.lexer;
+
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.*;
+import com.intellij.psi.xml.*;
+
+%%
+
+%{
+   private boolean isHighlightModeOn = false;
+
+   public _DtdLexer(boolean highlightModeOn) {
+     this((java.io.Reader)null);
+     isHighlightModeOn = highlightModeOn;
+   }
+%}
+
+%unicode
+%class _DtdLexer
+%public
+%implements FlexLexer
+%function advance
+%type IElementType
+%eof{  return;
+%eof}
+
+%state DECL
+%state DECL_ATTR
+%state DECL_ATTR_VALUE_DQ
+%state DECL_ATTR_VALUE_SQ
+%state TAG_NAME
+%state TAG_ATTRIBUTES
+%state COMMENT
+%state ATTRIBUTE_VALUE_START
+%state ATTRIBUTE_VALUE_DQ
+%state ATTRIBUTE_VALUE_SQ
+%state PROCESSING_INSTRUCTION
+%state DOCTYPE_MARKUP_STARTED
+
+%state DOCTYPE
+%state DOCTYPE_EXTERNAL_ID
+%state DOCTYPE_MARKUP
+%state DOCTYPE_MARKUP_DQ
+%state DOCTYPE_MARKUP_SQ
+%state CDATA
+%state CONDITIONAL
+%state DOCTYPE_COMMENT
+
+ALPHA=[:letter:]
+DIGIT=[0-9]
+WS=[\ \n\r\t\f]
+S={WS}+
+
+TAG_NAME=({ALPHA}|"_"|":")({ALPHA}|{DIGIT}|"_"|":"|"."|"-")*
+NAME=({ALPHA}|"_"|":")({ALPHA}|{DIGIT}|"_"|":"|"."|"-")*
+NMTOKEN=({ALPHA}|{DIGIT}|"_"|":"|"."|"-")+
+
+%%
+"<![CDATA[" {yybegin(CDATA); return XmlTokenType.XML_CDATA_START; }
+<CDATA> "]]>"  {yybegin(YYINITIAL); return XmlTokenType.XML_CDATA_END; }
+<CDATA> [^] {return XmlTokenType.XML_DATA_CHARACTERS; }
+<CDATA> "<!--" { return XmlTokenType.XML_DATA_CHARACTERS; }
+
+"<![" {yybegin(CONDITIONAL); return XmlTokenType.XML_CONDITIONAL_SECTION_START; }
+
+<CONDITIONAL> "INCLUDE" { return XmlTokenType.XML_CONDITIONAL_INCLUDE; }
+<CONDITIONAL> "IGNORE" { return XmlTokenType.XML_CONDITIONAL_IGNORE; }
+"]]>" { yybegin(YYINITIAL); return XmlTokenType.XML_CONDITIONAL_SECTION_END; }
+
+"&"{NAME}";" { return XmlTokenType.XML_ENTITY_REF_TOKEN; }
+"%"{NAME}";" { return XmlTokenType.XML_ENTITY_REF_TOKEN; }
+
+"&#"{DIGIT}+";" { return XmlTokenType.XML_CHAR_ENTITY_REF; }
+"&#x"({DIGIT}|[a-fA-F])+";" { return XmlTokenType.XML_CHAR_ENTITY_REF; }
+
+<YYINITIAL> "<?xml " { yybegin(DECL); return XmlTokenType.XML_DECL_START; }
+
+<DECL> {NAME} { yybegin(DECL_ATTR); return XmlTokenType.XML_NAME; }
+<DECL_ATTR> "=" { return XmlTokenType.XML_EQ;}
+<DECL_ATTR> "'" { yybegin(DECL_ATTR_VALUE_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;}
+<DECL_ATTR> "\"" { yybegin(DECL_ATTR_VALUE_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;}
+<DECL_ATTR_VALUE_DQ> [^\"]* { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+<DECL_ATTR_VALUE_SQ> [^']* { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+<DECL_ATTR_VALUE_DQ> "\"" { yybegin(DECL); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;}
+<DECL_ATTR_VALUE_SQ> "'" { yybegin(DECL); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;}
+<DECL> "?>" { yybegin(YYINITIAL); return XmlTokenType.XML_DECL_END;}
+<DECL> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_BAD_CHARACTER;}
+
+<YYINITIAL> "<!DOCTYPE" { yybegin(DOCTYPE); return XmlTokenType.XML_DOCTYPE_START; }
+<DOCTYPE> "SYSTEM" { yybegin(DOCTYPE_EXTERNAL_ID); return XmlTokenType.XML_DOCTYPE_SYSTEM; }
+<DOCTYPE> "PUBLIC" { yybegin(DOCTYPE_EXTERNAL_ID); return XmlTokenType.XML_DOCTYPE_PUBLIC; }
+<DOCTYPE> {NAME} { return XmlTokenType.XML_NAME; }
+<DOCTYPE_EXTERNAL_ID> "\""[^\"]*"\"" { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+<DOCTYPE_EXTERNAL_ID> "'"[^']*"'" { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+<DOCTYPE, DOCTYPE_EXTERNAL_ID,CONDITIONAL> "[" { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_MARKUP_START;}
+<DOCTYPE_MARKUP, YYINITIAL> "<!ELEMENT" { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_ELEMENT_DECL_START;}
+<DOCTYPE_MARKUP, YYINITIAL> "<!NOTATION" { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_NOTATION_DECL_START;}
+<DOCTYPE_MARKUP, YYINITIAL> "<!ATTLIST" { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_ATTLIST_DECL_START;}
+<DOCTYPE_MARKUP, YYINITIAL> "<!ENTITY" { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_ENTITY_DECL_START;}
+<DOCTYPE_MARKUP> "SYSTEM" { return XmlTokenType.XML_DOCTYPE_SYSTEM; }
+<DOCTYPE_MARKUP> "PUBLIC" { return XmlTokenType.XML_DOCTYPE_PUBLIC; }
+<DOCTYPE_MARKUP> "#PCDATA" { return XmlTokenType.XML_PCDATA;}
+<DOCTYPE_MARKUP> "EMPTY" { return XmlTokenType.XML_CONTENT_EMPTY;}
+<DOCTYPE_MARKUP> "ANY" { return XmlTokenType.XML_CONTENT_ANY;}
+<DOCTYPE_MARKUP> "(" { return XmlTokenType.XML_LEFT_PAREN;}
+<DOCTYPE_MARKUP> ")" { return XmlTokenType.XML_RIGHT_PAREN;}
+<DOCTYPE_MARKUP> "?" { return XmlTokenType.XML_QUESTION;}
+<DOCTYPE_MARKUP> "+" { return XmlTokenType.XML_PLUS;}
+<DOCTYPE_MARKUP> "*" { return XmlTokenType.XML_STAR;}
+<DOCTYPE_MARKUP> "%" { return XmlTokenType.XML_PERCENT;}
+<DOCTYPE_MARKUP> "--" ([^\-]|(\-[^\-]))* "--" { yybegin(DOCTYPE_MARKUP_STARTED); yypushback(yylength()); }
+<DOCTYPE_MARKUP_STARTED> "--" { yybegin(DOCTYPE_COMMENT); return XmlTokenType.XML_COMMENT_START;}
+<DOCTYPE_COMMENT> ([^\-]|(\-[^\-]))* { return XmlTokenType.XML_COMMENT_CHARACTERS; }
+<DOCTYPE_COMMENT> "--" { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_COMMENT_END;}
+<DOCTYPE_MARKUP> \| { return XmlTokenType.XML_BAR;}
+<DOCTYPE_MARKUP> "," { return XmlTokenType.XML_COMMA;}
+<DOCTYPE_MARKUP> "&" { return XmlTokenType.XML_AMP;}
+<DOCTYPE_MARKUP> ";" { return XmlTokenType.XML_SEMI;}
+<DOCTYPE_MARKUP> "#IMPLIED" { return XmlTokenType.XML_ATT_IMPLIED;}
+<DOCTYPE_MARKUP> "#REQUIRED" { return XmlTokenType.XML_ATT_REQUIRED;}
+<DOCTYPE_MARKUP> "#FIXED" { return XmlTokenType.XML_ATT_FIXED;}
+<DOCTYPE_MARKUP> {NMTOKEN} { return XmlTokenType.XML_NAME;}
+<DOCTYPE_MARKUP> ">" { return XmlTokenType.XML_TAG_END;}
+<DOCTYPE_MARKUP> "]" { yybegin(DOCTYPE); return XmlTokenType.XML_MARKUP_END;}
+<DOCTYPE_MARKUP> "\"" { yybegin(DOCTYPE_MARKUP_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER; }
+<DOCTYPE_MARKUP> "'" { yybegin(DOCTYPE_MARKUP_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER; }
+<DOCTYPE_MARKUP_DQ> "\"" { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER; }
+<DOCTYPE_MARKUP_SQ> "'" { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER; }
+<DOCTYPE_MARKUP_DQ> [^\"]+ { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN; }
+<DOCTYPE_MARKUP_SQ> [^']+ { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN; }
+<DOCTYPE,DOCTYPE_EXTERNAL_ID> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_DOCTYPE_END; }
+
+<YYINITIAL> "<?" { yybegin(PROCESSING_INSTRUCTION); return XmlTokenType.XML_PI_START; }
+<PROCESSING_INSTRUCTION> "?>" { yybegin(YYINITIAL); return XmlTokenType.XML_PI_END; }
+<PROCESSING_INSTRUCTION> [^] { return XmlTokenType.XML_PI_TARGET; }
+
+<YYINITIAL,TAG_NAME,TAG_ATTRIBUTES,ATTRIBUTE_VALUE_START,ATTRIBUTE_VALUE_DQ,ATTRIBUTE_VALUE_SQ>"<" { yybegin(TAG_NAME); return XmlTokenType.XML_START_TAG_START; }
+<YYINITIAL,TAG_NAME,TAG_ATTRIBUTES,ATTRIBUTE_VALUE_START,ATTRIBUTE_VALUE_DQ,ATTRIBUTE_VALUE_SQ>"</" { yybegin(TAG_NAME); return XmlTokenType.XML_END_TAG_START; }
+
+
+<TAG_NAME> {TAG_NAME} { yybegin(TAG_ATTRIBUTES); return isHighlightModeOn ? XmlTokenType.XML_TAG_NAME:XmlTokenType.XML_NAME; }
+
+<TAG_ATTRIBUTES> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_TAG_END; }
+<TAG_ATTRIBUTES> "/>" { yybegin(YYINITIAL); return XmlTokenType.XML_EMPTY_ELEMENT_END; }
+<TAG_ATTRIBUTES> {NAME} { return XmlTokenType.XML_NAME; }
+<TAG_ATTRIBUTES> "=" { yybegin(ATTRIBUTE_VALUE_START); return XmlTokenType.XML_EQ; }
+
+<ATTRIBUTE_VALUE_START> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_TAG_END; }
+<ATTRIBUTE_VALUE_START> "/>" { yybegin(YYINITIAL); return XmlTokenType.XML_EMPTY_ELEMENT_END; }
+<ATTRIBUTE_VALUE_START> "\"" { yybegin(ATTRIBUTE_VALUE_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER; }
+<ATTRIBUTE_VALUE_START> "'" { yybegin(ATTRIBUTE_VALUE_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER; }
+<ATTRIBUTE_VALUE_DQ> "\"" { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER; }
+<ATTRIBUTE_VALUE_SQ> "'" { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER; }
+<ATTRIBUTE_VALUE_DQ> [^\"] { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN; }
+<ATTRIBUTE_VALUE_SQ> [^'] { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN; }
+
+"<!--" { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_START; }
+<COMMENT> "-->" { yybegin(YYINITIAL); return XmlTokenType.XML_COMMENT_END; }
+<COMMENT> ([^\-]|(-[^\-]))* { return XmlTokenType.XML_COMMENT_CHARACTERS; }
+
+<YYINITIAL,DECL,DECL_ATTR,TAG_NAME,TAG_ATTRIBUTES,COMMENT,ATTRIBUTE_VALUE_START,
+ DOCTYPE,DOCTYPE_EXTERNAL_ID,DOCTYPE_MARKUP,CONDITIONAL>{S} { return XmlTokenType.XML_WHITE_SPACE; }
+
+<YYINITIAL> [^<&] { return XmlTokenType.XML_DATA_CHARACTERS; }
+
+[^] { return XmlTokenType.XML_BAD_CHARACTER; }
diff --git a/xml/impl/src/com/intellij/lexer/_DtdLexer.java b/xml/impl/src/com/intellij/lexer/_DtdLexer.java
new file mode 100644
index 0000000..a9308ed
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/_DtdLexer.java
@@ -0,0 +1,1143 @@
+/* The following code was generated by JFlex 1.4.3 on 7/31/12 2:32 PM */
+
+ /* It's an automatically generated code. Do not modify it. */
+package com.intellij.lexer;
+
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.*;
+import com.intellij.psi.xml.*;
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4.3
+ * on 7/31/12 2:32 PM from the specification file
+ * <tt>C:/Idea.Sources/Trunk/tools/lexer/../../community/xml/impl/src/com/intellij/lexer/_DtdLexer.flex</tt>
+ */
+public class _DtdLexer implements FlexLexer {
+  /** initial size of the lookahead buffer */
+  private static final int ZZ_BUFFERSIZE = 16384;
+
+  /** lexical states */
+  public static final int PROCESSING_INSTRUCTION = 22;
+  public static final int DECL_ATTR_VALUE_DQ = 6;
+  public static final int DECL_ATTR = 4;
+  public static final int ATTRIBUTE_VALUE_START = 16;
+  public static final int DECL_ATTR_VALUE_SQ = 8;
+  public static final int ATTRIBUTE_VALUE_DQ = 18;
+  public static final int CONDITIONAL = 38;
+  public static final int DECL = 2;
+  public static final int DOCTYPE_MARKUP_STARTED = 24;
+  public static final int ATTRIBUTE_VALUE_SQ = 20;
+  public static final int DOCTYPE_EXTERNAL_ID = 28;
+  public static final int CDATA = 36;
+  public static final int COMMENT = 14;
+  public static final int TAG_NAME = 10;
+  public static final int DOCTYPE_MARKUP = 30;
+  public static final int DOCTYPE_COMMENT = 40;
+  public static final int DOCTYPE_MARKUP_DQ = 32;
+  public static final int YYINITIAL = 0;
+  public static final int TAG_ATTRIBUTES = 12;
+  public static final int DOCTYPE_MARKUP_SQ = 34;
+  public static final int DOCTYPE = 26;
+
+  /**
+   * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
+   * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
+   *                  at the beginning of a line
+   * l is of the form l = 2*k, k a non negative integer
+   */
+  private static final int ZZ_LEXSTATE[] = { 
+     0,  0,  1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7,  7, 
+     8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 
+    16, 16, 17, 17, 18, 18, 19, 19, 20, 20
+  };
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final String ZZ_CMAP_PACKED = 
+    "\11\0\2\3\1\0\2\3\22\0\1\40\1\7\1\43\1\32\1\0"+
+    "\1\31\1\27\1\42\1\51\1\52\1\54\1\53\1\56\1\5\1\4"+
+    "\1\62\12\2\1\1\1\30\1\6\1\41\1\16\1\35\1\0\1\13"+
+    "\1\50\1\11\1\12\1\23\1\60\1\24\1\1\1\17\2\1\1\21"+
+    "\1\47\1\20\1\25\1\45\1\57\1\26\1\46\1\14\1\22\2\1"+
+    "\1\61\1\44\1\1\1\10\1\0\1\15\1\0\1\1\1\0\6\34"+
+    "\5\1\1\37\1\36\12\1\1\33\2\1\1\0\1\55\55\0\1\1"+
+    "\12\0\1\1\4\0\1\1\5\0\27\1\1\0\37\1\1\0\u01ca\1"+
+    "\4\0\14\1\16\0\5\1\7\0\1\1\1\0\1\1\201\0\5\1"+
+    "\1\0\2\1\2\0\4\1\10\0\1\1\1\0\3\1\1\0\1\1"+
+    "\1\0\24\1\1\0\123\1\1\0\213\1\10\0\236\1\11\0\46\1"+
+    "\2\0\1\1\7\0\47\1\110\0\33\1\5\0\3\1\55\0\53\1"+
+    "\43\0\2\1\1\0\143\1\1\0\1\1\17\0\2\1\7\0\2\1"+
+    "\12\0\3\1\2\0\1\1\20\0\1\1\1\0\36\1\35\0\131\1"+
+    "\13\0\1\1\30\0\41\1\11\0\2\1\4\0\1\1\5\0\26\1"+
+    "\4\0\1\1\11\0\1\1\3\0\1\1\27\0\31\1\253\0\66\1"+
+    "\3\0\1\1\22\0\1\1\7\0\12\1\17\0\7\1\1\0\7\1"+
+    "\5\0\10\1\2\0\2\1\2\0\26\1\1\0\7\1\1\0\1\1"+
+    "\3\0\4\1\3\0\1\1\20\0\1\1\15\0\2\1\1\0\3\1"+
+    "\16\0\2\1\23\0\6\1\4\0\2\1\2\0\26\1\1\0\7\1"+
+    "\1\0\2\1\1\0\2\1\1\0\2\1\37\0\4\1\1\0\1\1"+
+    "\23\0\3\1\20\0\11\1\1\0\3\1\1\0\26\1\1\0\7\1"+
+    "\1\0\2\1\1\0\5\1\3\0\1\1\22\0\1\1\17\0\2\1"+
+    "\43\0\10\1\2\0\2\1\2\0\26\1\1\0\7\1\1\0\2\1"+
+    "\1\0\5\1\3\0\1\1\36\0\2\1\1\0\3\1\17\0\1\1"+
+    "\21\0\1\1\1\0\6\1\3\0\3\1\1\0\4\1\3\0\2\1"+
+    "\1\0\1\1\1\0\2\1\3\0\2\1\3\0\3\1\3\0\14\1"+
+    "\26\0\1\1\64\0\10\1\1\0\3\1\1\0\27\1\1\0\12\1"+
+    "\1\0\5\1\3\0\1\1\32\0\2\1\6\0\2\1\43\0\10\1"+
+    "\1\0\3\1\1\0\27\1\1\0\12\1\1\0\5\1\3\0\1\1"+
+    "\40\0\1\1\1\0\2\1\17\0\2\1\22\0\10\1\1\0\3\1"+
+    "\1\0\51\1\2\0\1\1\20\0\1\1\21\0\2\1\30\0\6\1"+
+    "\5\0\22\1\3\0\30\1\1\0\11\1\1\0\1\1\2\0\7\1"+
+    "\72\0\60\1\1\0\2\1\14\0\7\1\72\0\2\1\1\0\1\1"+
+    "\2\0\2\1\1\0\1\1\2\0\1\1\6\0\4\1\1\0\7\1"+
+    "\1\0\3\1\1\0\1\1\1\0\1\1\2\0\2\1\1\0\4\1"+
+    "\1\0\2\1\11\0\1\1\2\0\5\1\1\0\1\1\25\0\2\1"+
+    "\42\0\1\1\77\0\10\1\1\0\44\1\33\0\5\1\163\0\53\1"+
+    "\24\0\1\1\20\0\6\1\4\0\4\1\3\0\1\1\3\0\2\1"+
+    "\7\0\3\1\4\0\15\1\14\0\1\1\21\0\46\1\12\0\53\1"+
+    "\1\0\1\1\3\0\u0149\1\1\0\4\1\2\0\7\1\1\0\1\1"+
+    "\1\0\4\1\2\0\51\1\1\0\4\1\2\0\41\1\1\0\4\1"+
+    "\2\0\7\1\1\0\1\1\1\0\4\1\2\0\17\1\1\0\71\1"+
+    "\1\0\4\1\2\0\103\1\45\0\20\1\20\0\125\1\14\0\u026c\1"+
+    "\2\0\21\1\1\0\32\1\5\0\113\1\25\0\15\1\1\0\4\1"+
+    "\16\0\22\1\16\0\22\1\16\0\15\1\1\0\3\1\17\0\64\1"+
+    "\43\0\1\1\4\0\1\1\103\0\130\1\10\0\51\1\1\0\1\1"+
+    "\5\0\106\1\12\0\35\1\63\0\36\1\2\0\5\1\13\0\54\1"+
+    "\25\0\7\1\70\0\27\1\11\0\65\1\122\0\1\1\135\0\57\1"+
+    "\21\0\7\1\67\0\36\1\15\0\2\1\20\0\46\1\32\0\44\1"+
+    "\51\0\3\1\12\0\44\1\153\0\4\1\1\0\4\1\16\0\300\1"+
+    "\100\0\u0116\1\2\0\6\1\2\0\46\1\2\0\6\1\2\0\10\1"+
+    "\1\0\1\1\1\0\1\1\1\0\1\1\1\0\37\1\2\0\65\1"+
+    "\1\0\7\1\1\0\1\1\3\0\3\1\1\0\7\1\3\0\4\1"+
+    "\2\0\6\1\4\0\15\1\5\0\3\1\1\0\7\1\164\0\1\1"+
+    "\15\0\1\1\20\0\15\1\145\0\1\1\4\0\1\1\2\0\12\1"+
+    "\1\0\1\1\3\0\5\1\6\0\1\1\1\0\1\1\1\0\1\1"+
+    "\1\0\4\1\1\0\13\1\2\0\4\1\5\0\5\1\4\0\1\1"+
+    "\64\0\2\1\u0a7b\0\57\1\1\0\57\1\1\0\205\1\6\0\4\1"+
+    "\21\0\46\1\12\0\66\1\11\0\1\1\20\0\27\1\11\0\7\1"+
+    "\1\0\7\1\1\0\7\1\1\0\7\1\1\0\7\1\1\0\7\1"+
+    "\1\0\7\1\1\0\7\1\120\0\1\1\u01d5\0\2\1\52\0\5\1"+
+    "\5\0\2\1\4\0\126\1\6\0\3\1\1\0\132\1\1\0\4\1"+
+    "\5\0\51\1\3\0\136\1\21\0\33\1\65\0\20\1\u0200\0\u19b6\1"+
+    "\112\0\u51cc\1\64\0\u048d\1\103\0\56\1\2\0\u010d\1\3\0\20\1"+
+    "\12\0\2\1\24\0\57\1\20\0\31\1\10\0\106\1\61\0\11\1"+
+    "\2\0\147\1\2\0\4\1\1\0\2\1\16\0\12\1\120\0\10\1"+
+    "\1\0\3\1\1\0\4\1\1\0\27\1\35\0\64\1\16\0\62\1"+
+    "\76\0\6\1\3\0\1\1\16\0\34\1\12\0\27\1\31\0\35\1"+
+    "\7\0\57\1\34\0\1\1\60\0\51\1\27\0\3\1\1\0\10\1"+
+    "\24\0\27\1\3\0\1\1\5\0\60\1\1\0\1\1\3\0\2\1"+
+    "\2\0\5\1\2\0\1\1\1\0\1\1\30\0\3\1\43\0\6\1"+
+    "\2\0\6\1\2\0\6\1\11\0\7\1\1\0\7\1\221\0\43\1"+
+    "\35\0\u2ba4\1\14\0\27\1\4\0\61\1\u2104\0\u012e\1\2\0\76\1"+
+    "\2\0\152\1\46\0\7\1\14\0\5\1\5\0\1\1\1\0\12\1"+
+    "\1\0\15\1\1\0\5\1\1\0\1\1\1\0\2\1\1\0\2\1"+
+    "\1\0\154\1\41\0\u016b\1\22\0\100\1\2\0\66\1\50\0\14\1"+
+    "\164\0\5\1\1\0\207\1\44\0\32\1\6\0\32\1\13\0\131\1"+
+    "\3\0\6\1\2\0\6\1\2\0\6\1\2\0\3\1\43\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+  /** 
+   * Translates DFA states to action switch labels.
+   */
+  private static final int [] ZZ_ACTION = zzUnpackAction();
+
+  private static final String ZZ_ACTION_PACKED_0 =
+    "\3\0\2\1\2\0\1\2\14\0\1\2\1\3\1\4"+
+    "\1\5\1\3\1\6\1\3\1\6\1\7\2\6\1\10"+
+    "\2\6\1\11\1\12\1\13\5\1\1\14\5\1\1\15"+
+    "\1\5\1\16\1\17\1\20\1\6\1\2\1\6\4\2"+
+    "\1\21\1\22\4\1\1\23\6\24\1\6\1\25\1\26"+
+    "\2\16\2\6\1\16\1\6\1\16\1\27\1\30\1\16"+
+    "\1\31\1\32\1\33\1\6\1\34\1\35\1\36\2\16"+
+    "\1\37\1\40\1\41\1\42\1\43\1\44\1\45\3\3"+
+    "\2\6\1\0\1\46\1\47\4\0\1\50\10\1\1\51"+
+    "\2\0\4\2\1\52\1\53\2\16\2\0\1\16\1\0"+
+    "\2\16\4\0\2\16\4\0\1\54\1\0\1\55\5\0"+
+    "\1\56\1\57\2\0\1\55\1\56\1\57\2\1\1\55"+
+    "\1\56\1\57\2\1\1\60\1\0\1\55\1\56\1\0"+
+    "\1\57\2\2\2\16\1\0\1\16\1\61\1\16\4\0"+
+    "\2\16\1\0\1\62\2\0\1\63\7\0\1\64\1\0"+
+    "\1\1\1\64\2\1\1\64\1\1\1\2\1\64\1\2"+
+    "\2\16\1\0\1\65\1\16\4\0\2\16\11\0\2\1"+
+    "\1\2\2\16\1\65\1\66\4\0\2\16\10\0\1\67"+
+    "\2\1\1\2\1\70\1\71\3\0\1\72\1\73\1\74"+
+    "\1\0\1\75\6\0\2\1\1\2\2\0\1\76\1\77"+
+    "\4\0\1\100\1\0\2\1\1\2\1\101\1\0\1\102"+
+    "\1\103\1\104\1\0\1\105\3\102\1\106\1\107";
+
+  private static int [] zzUnpackAction() {
+    int [] result = new int[304];
+    int offset = 0;
+    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAction(String packed, int offset, int [] result) {
+    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++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
+
+  private static final String ZZ_ROWMAP_PACKED_0 =
+    "\0\0\0\63\0\146\0\231\0\314\0\377\0\u0132\0\u0165"+
+    "\0\u0198\0\u01cb\0\u01fe\0\u0231\0\u0264\0\u0297\0\u02ca\0\u02fd"+
+    "\0\u0330\0\u0363\0\u0396\0\u03c9\0\u03fc\0\u042f\0\u0462\0\u0495"+
+    "\0\u04c8\0\u04fb\0\u052e\0\u042f\0\u0561\0\u0594\0\u04c8\0\u042f"+
+    "\0\u052e\0\u05c7\0\u042f\0\u042f\0\u042f\0\u05fa\0\u062d\0\u0660"+
+    "\0\u0693\0\u06c6\0\u042f\0\u06f9\0\u072c\0\u075f\0\u0792\0\u07c5"+
+    "\0\u07f8\0\u082b\0\u085e\0\u042f\0\u042f\0\u0891\0\u08c4\0\u08f7"+
+    "\0\u092a\0\u095d\0\u0990\0\u09c3\0\u042f\0\u042f\0\u042f\0\u04c8"+
+    "\0\u04fb\0\u052e\0\u042f\0\u042f\0\u0594\0\u04c8\0\u04fb\0\u052e"+
+    "\0\u09f6\0\u0a29\0\u042f\0\u042f\0\u0a5c\0\u0a8f\0\u0ac2\0\u0af5"+
+    "\0\u0b28\0\u0b5b\0\u0b8e\0\u04c8\0\u042f\0\u0bc1\0\u04fb\0\u042f"+
+    "\0\u052e\0\u0bf4\0\u042f\0\u042f\0\u042f\0\u0c27\0\u0c5a\0\u042f"+
+    "\0\u042f\0\u042f\0\u042f\0\u042f\0\u042f\0\u042f\0\u0c8d\0\u0cc0"+
+    "\0\u04fb\0\u0cf3\0\u0d26\0\u0d59\0\u0d8c\0\u042f\0\u0dbf\0\u0df2"+
+    "\0\u0e25\0\u0e58\0\u042f\0\u0e8b\0\u0ebe\0\u0ef1\0\u0f24\0\u0f57"+
+    "\0\u0f8a\0\u0fbd\0\u0ff0\0\u042f\0\u1023\0\u1056\0\u1089\0\u10bc"+
+    "\0\u10ef\0\u1122\0\u042f\0\u042f\0\u1155\0\u1188\0\u0ac2\0\u0af5"+
+    "\0\u11bb\0\u11ee\0\u1221\0\u1254\0\u1287\0\u12ba\0\u12ed\0\u1320"+
+    "\0\u1353\0\u1386\0\u13b9\0\u13ec\0\u141f\0\u1452\0\u042f\0\u1485"+
+    "\0\u14b8\0\u14eb\0\u151e\0\u1551\0\u1584\0\u15b7\0\u042f\0\u042f"+
+    "\0\u15ea\0\u161d\0\u1650\0\u05fa\0\u05fa\0\u1683\0\u16b6\0\u16e9"+
+    "\0\u06f9\0\u06f9\0\u171c\0\u174f\0\u042f\0\u1782\0\u17b5\0\u08c4"+
+    "\0\u17e8\0\u08c4\0\u181b\0\u184e\0\u1881\0\u18b4\0\u18e7\0\u191a"+
+    "\0\u085e\0\u194d\0\u1980\0\u19b3\0\u19e6\0\u1a19\0\u1a4c\0\u1a7f"+
+    "\0\u1ab2\0\u042f\0\u1ae5\0\u1b18\0\u042f\0\u1b4b\0\u1b7e\0\u1bb1"+
+    "\0\u1be4\0\u1c17\0\u1c4a\0\u1c7d\0\u042f\0\u1cb0\0\u1ce3\0\u05fa"+
+    "\0\u1d16\0\u1d49\0\u06f9\0\u1d7c\0\u1daf\0\u08c4\0\u1de2\0\u1e15"+
+    "\0\u1e48\0\u1e7b\0\u085e\0\u1eae\0\u1ee1\0\u1f14\0\u1f47\0\u1f7a"+
+    "\0\u1fad\0\u1fe0\0\u2013\0\u2046\0\u2079\0\u20ac\0\u20df\0\u2112"+
+    "\0\u2145\0\u2178\0\u21ab\0\u21de\0\u2211\0\u2244\0\u2277\0\u22aa"+
+    "\0\u042f\0\u085e\0\u22dd\0\u2310\0\u2343\0\u2376\0\u23a9\0\u23dc"+
+    "\0\u240f\0\u2442\0\u2475\0\u24a8\0\u24db\0\u250e\0\u2541\0\u2574"+
+    "\0\u042f\0\u25a7\0\u25da\0\u260d\0\u085e\0\u085e\0\u2640\0\u2673"+
+    "\0\u26a6\0\u042f\0\u085e\0\u085e\0\u26d9\0\u042f\0\u270c\0\u273f"+
+    "\0\u2772\0\u27a5\0\u27d8\0\u280b\0\u283e\0\u2871\0\u28a4\0\u28d7"+
+    "\0\u290a\0\u042f\0\u042f\0\u293d\0\u2970\0\u29a3\0\u29d6\0\u042f"+
+    "\0\u2a09\0\u2a3c\0\u2a6f\0\u2aa2\0\u042f\0\u2ad5\0\u042f\0\u042f"+
+    "\0\u042f\0\u2b08\0\u042f\0\u05fa\0\u06f9\0\u08c4\0\u042f\0\u042f";
+
+  private static int [] zzUnpackRowMap() {
+    int [] result = new int[304];
+    int offset = 0;
+    offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackRowMap(String packed, int offset, int [] result) {
+    int i = 0;  /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int high = packed.charAt(i++) << 16;
+      result[j++] = high | packed.charAt(i++);
+    }
+    return j;
+  }
+
+  /** 
+   * The transition table of the DFA
+   */
+  private static final int [] ZZ_TRANS = zzUnpackTrans();
+
+  private static final String ZZ_TRANS_PACKED_0 =
+    "\3\26\1\27\2\26\1\30\6\26\1\31\11\26\1\32"+
+    "\1\26\1\33\6\26\1\27\22\26\1\34\1\35\1\34"+
+    "\1\27\2\34\1\36\2\34\4\35\1\37\1\40\10\35"+
+    "\1\32\1\34\1\41\1\34\2\35\1\42\2\35\1\27"+
+    "\3\34\5\35\6\34\3\35\4\34\1\27\2\34\1\36"+
+    "\6\34\1\37\11\34\1\32\1\34\1\41\6\34\1\27"+
+    "\1\43\1\44\1\45\17\34\6\46\1\47\6\46\1\50"+
+    "\11\46\1\51\1\46\1\52\11\46\1\53\17\46\6\54"+
+    "\1\55\6\54\1\56\11\54\1\57\1\54\1\60\10\54"+
+    "\1\53\20\54\1\34\1\61\1\34\1\27\2\34\1\62"+
+    "\2\34\4\61\1\37\1\34\10\61\1\32\1\34\1\41"+
+    "\1\34\2\61\1\34\2\61\1\27\3\34\5\61\6\34"+
+    "\3\61\2\34\1\63\1\34\1\27\2\34\1\62\2\34"+
+    "\4\63\1\37\1\64\10\63\1\32\1\34\1\41\1\34"+
+    "\2\63\1\34\2\63\1\27\1\65\2\34\5\63\6\34"+
+    "\3\63\1\66\5\67\1\70\1\71\6\67\1\72\11\67"+
+    "\1\73\1\67\1\74\31\67\3\34\1\27\2\34\1\62"+
+    "\6\34\1\37\1\64\10\34\1\32\1\34\1\41\6\34"+
+    "\1\27\1\34\1\75\1\76\16\34\1\66\6\77\1\62"+
+    "\6\77\1\100\11\77\1\101\1\77\1\102\11\77\1\103"+
+    "\25\77\1\62\6\77\1\100\11\77\1\101\1\77\1\102"+
+    "\10\77\1\103\20\77\6\104\1\105\6\104\1\106\11\104"+
+    "\1\107\1\104\1\110\3\104\1\111\25\104\5\34\1\112"+
+    "\1\36\6\34\1\37\11\34\1\32\1\34\1\41\32\34"+
+    "\1\63\1\34\1\27\2\34\1\36\1\34\1\113\4\63"+
+    "\1\37\1\114\10\63\1\32\1\34\1\41\1\34\2\63"+
+    "\1\34\2\63\1\27\3\34\1\63\1\115\1\116\2\63"+
+    "\6\34\3\63\4\34\1\27\2\34\1\36\1\34\1\113"+
+    "\4\34\1\37\1\114\10\34\1\32\1\34\1\41\6\34"+
+    "\1\27\1\34\1\117\1\120\20\34\2\63\1\27\1\63"+
+    "\1\121\1\122\2\34\2\63\1\123\1\63\1\124\1\125"+
+    "\4\63\1\126\3\63\1\127\1\130\1\131\1\132\2\63"+
+    "\1\133\2\63\1\27\1\34\1\134\1\135\1\63\1\136"+
+    "\1\137\2\63\1\140\1\141\1\142\1\143\1\144\1\145"+
+    "\3\63\1\34\6\46\1\47\6\46\1\50\11\46\1\51"+
+    "\1\46\1\52\11\46\1\146\17\46\6\54\1\55\6\54"+
+    "\1\56\11\54\1\57\1\54\1\60\10\54\1\146\20\54"+
+    "\6\26\1\147\6\26\1\150\11\26\1\151\1\26\1\33"+
+    "\31\26\3\34\1\27\2\34\1\36\1\34\1\113\4\34"+
+    "\1\37\1\34\1\152\7\34\1\32\1\34\1\41\6\34"+
+    "\1\27\22\34\5\67\1\153\1\71\6\67\1\72\11\67"+
+    "\1\73\1\67\1\74\31\67\66\0\1\27\34\0\1\27"+
+    "\31\0\1\154\25\0\1\155\24\0\1\156\15\0\1\157"+
+    "\46\0\1\160\7\0\4\160\2\0\10\160\3\0\1\161"+
+    "\2\160\1\0\2\160\4\0\5\160\6\0\3\160\2\0"+
+    "\1\160\7\0\4\160\2\0\10\160\4\0\2\160\1\0"+
+    "\2\160\4\0\5\160\6\0\3\160\2\0\2\35\1\0"+
+    "\2\35\3\0\4\35\2\0\10\35\4\0\2\35\1\0"+
+    "\2\35\4\0\5\35\6\0\3\35\10\0\1\162\71\0"+
+    "\1\163\44\0\43\46\1\0\26\46\1\164\33\46\1\0"+
+    "\34\46\1\165\25\46\1\0\20\46\1\166\7\46\4\166"+
+    "\2\46\10\166\3\46\1\167\2\166\1\46\2\166\3\46"+
+    "\1\0\5\166\6\46\3\166\2\46\1\166\7\46\4\166"+
+    "\2\46\10\166\4\46\2\166\1\46\2\166\3\46\1\0"+
+    "\5\166\6\46\3\166\1\46\42\54\1\0\27\54\1\170"+
+    "\32\54\1\0\35\54\1\171\24\54\1\0\21\54\1\172"+
+    "\7\54\4\172\2\54\10\172\3\54\1\173\2\172\1\54"+
+    "\2\172\2\54\1\0\1\54\5\172\6\54\3\172\2\54"+
+    "\1\172\7\54\4\172\2\54\10\172\4\54\2\172\1\54"+
+    "\2\172\2\54\1\0\1\54\5\172\6\54\3\172\1\54"+
+    "\1\0\2\61\1\0\2\61\3\0\4\61\2\0\10\61"+
+    "\4\0\2\61\1\0\2\61\4\0\5\61\6\0\3\61"+
+    "\10\0\1\162\52\0\1\156\1\0\2\63\1\0\2\63"+
+    "\3\0\4\63\2\0\10\63\4\0\2\63\1\0\2\63"+
+    "\4\0\5\63\6\0\3\63\17\0\1\174\44\0\5\67"+
+    "\1\175\62\67\1\176\62\67\1\175\1\67\1\177\60\67"+
+    "\1\175\7\67\1\200\46\67\1\201\3\67\1\175\3\67"+
+    "\4\201\2\67\10\201\3\67\1\202\2\201\1\67\2\201"+
+    "\4\67\5\201\6\67\3\201\2\67\1\201\3\67\1\175"+
+    "\3\67\4\201\2\67\10\201\4\67\2\201\1\67\2\201"+
+    "\4\67\5\201\6\67\3\201\1\67\16\0\1\203\51\0"+
+    "\1\204\56\0\2\63\1\0\2\63\3\0\4\63\2\0"+
+    "\3\63\1\205\4\63\4\0\2\63\1\0\2\63\4\0"+
+    "\5\63\6\0\3\63\2\0\2\63\1\0\2\63\3\0"+
+    "\4\63\2\0\10\63\4\0\2\63\1\0\2\63\4\0"+
+    "\1\206\4\63\6\0\3\63\1\0\42\207\1\77\20\207"+
+    "\43\210\1\77\17\210\1\0\2\63\1\0\1\63\1\211"+
+    "\3\0\4\63\2\0\10\63\4\0\2\63\1\0\2\63"+
+    "\4\0\5\63\6\0\3\63\10\0\1\212\54\0\2\63"+
+    "\1\0\2\63\3\0\4\63\2\0\1\63\1\213\6\63"+
+    "\4\0\2\63\1\0\2\63\4\0\5\63\6\0\3\63"+
+    "\2\0\2\63\1\0\2\63\3\0\4\63\2\0\10\63"+
+    "\4\0\2\63\1\0\2\63\4\0\3\63\1\214\1\63"+
+    "\6\0\3\63\20\0\1\215\6\0\1\216\16\0\1\217"+
+    "\12\0\1\220\3\0\2\63\1\0\2\63\3\0\4\63"+
+    "\2\0\3\63\1\221\4\63\4\0\2\63\1\0\2\63"+
+    "\4\0\5\63\6\0\3\63\2\0\2\63\1\0\2\63"+
+    "\3\0\4\63\2\0\10\63\4\0\2\63\1\0\2\63"+
+    "\4\0\1\222\4\63\6\0\3\63\10\0\1\223\70\0"+
+    "\1\224\65\0\1\225\3\0\1\226\36\0\5\67\1\227"+
+    "\55\67\5\0\1\230\2\0\1\231\1\0\1\232\1\233"+
+    "\4\0\1\234\2\0\1\235\72\0\1\236\45\0\1\237"+
+    "\45\0\2\160\1\0\2\160\3\0\4\160\2\0\10\160"+
+    "\1\0\1\240\2\0\2\160\1\0\2\160\4\0\5\160"+
+    "\6\0\3\160\3\0\1\241\30\0\1\242\34\0\1\230"+
+    "\2\0\1\231\52\0\10\46\1\243\32\46\1\0\35\46"+
+    "\1\244\24\46\1\0\20\46\2\166\1\46\2\166\3\46"+
+    "\4\166\2\46\10\166\1\46\1\245\2\46\2\166\1\46"+
+    "\2\166\3\46\1\0\5\166\6\46\3\166\3\46\1\246"+
+    "\30\46\1\247\7\46\1\0\17\46\10\54\1\250\31\54"+
+    "\1\0\36\54\1\251\23\54\1\0\21\54\2\172\1\54"+
+    "\2\172\3\54\4\172\2\54\10\172\1\54\1\252\2\54"+
+    "\2\172\1\54\2\172\2\54\1\0\1\54\5\172\6\54"+
+    "\3\172\3\54\1\253\30\54\1\254\6\54\1\0\20\54"+
+    "\5\67\1\0\55\67\16\0\1\255\44\0\5\67\1\256"+
+    "\2\67\1\257\57\67\1\175\10\67\1\260\45\67\2\201"+
+    "\1\67\1\201\1\261\3\67\4\201\2\67\10\201\1\67"+
+    "\1\262\2\67\2\201\1\67\2\201\4\67\5\201\6\67"+
+    "\3\201\3\67\1\263\2\67\1\175\25\67\1\264\27\67"+
+    "\1\0\2\63\1\0\2\63\3\0\4\63\2\0\10\63"+
+    "\4\0\2\63\1\0\2\63\4\0\4\63\1\265\6\0"+
+    "\3\63\2\0\2\63\1\0\2\63\3\0\4\63\2\0"+
+    "\10\63\4\0\2\63\1\0\2\63\4\0\2\63\1\266"+
+    "\2\63\6\0\3\63\1\0\1\267\2\211\1\267\1\211"+
+    "\1\270\3\267\4\211\2\267\10\211\4\267\2\211\1\267"+
+    "\2\211\4\267\5\211\6\267\3\211\1\267\5\0\1\230"+
+    "\2\0\1\231\2\0\1\233\4\0\1\234\2\0\1\235"+
+    "\40\0\2\63\1\0\2\63\3\0\4\63\2\0\10\63"+
+    "\4\0\2\63\1\0\2\63\4\0\1\271\4\63\6\0"+
+    "\3\63\2\0\2\63\1\0\2\63\3\0\4\63\2\0"+
+    "\10\63\4\0\2\63\1\0\2\63\4\0\1\63\1\272"+
+    "\3\63\6\0\3\63\50\0\1\273\36\0\1\274\50\0"+
+    "\1\275\70\0\1\276\44\0\2\63\1\0\2\63\3\0"+
+    "\4\63\2\0\10\63\4\0\2\63\1\0\2\63\4\0"+
+    "\4\63\1\277\6\0\3\63\2\0\2\63\1\0\2\63"+
+    "\3\0\4\63\2\0\10\63\4\0\2\63\1\0\2\63"+
+    "\4\0\2\63\1\300\2\63\6\0\3\63\6\0\1\301"+
+    "\2\0\1\231\70\0\1\302\55\0\1\303\71\0\1\304"+
+    "\47\0\1\305\66\0\1\306\76\0\1\307\51\0\1\310"+
+    "\73\0\1\311\55\0\1\312\1\313\77\0\1\314\26\0"+
+    "\1\241\25\0\1\315\34\0\1\316\6\0\3\316\7\0"+
+    "\1\316\10\0\1\316\13\0\1\316\7\0\1\316\2\0"+
+    "\11\46\1\317\31\46\1\0\21\46\1\246\25\46\1\320"+
+    "\12\46\1\0\21\46\1\321\6\46\3\321\7\46\1\321"+
+    "\10\46\1\321\6\46\1\0\4\46\1\321\7\46\1\321"+
+    "\2\46\11\54\1\322\30\54\1\0\22\54\1\253\25\54"+
+    "\1\323\11\54\1\0\22\54\1\324\6\54\3\324\7\54"+
+    "\1\324\10\54\1\324\5\54\1\0\5\54\1\324\7\54"+
+    "\1\324\2\54\5\67\1\305\62\67\1\175\3\67\1\325"+
+    "\52\67\2\201\1\67\1\201\1\160\3\67\4\201\2\67"+
+    "\10\201\1\67\1\262\2\67\2\201\1\67\2\201\4\67"+
+    "\5\201\6\67\3\201\3\67\1\263\2\67\1\175\22\67"+
+    "\1\326\34\67\1\327\2\67\1\175\3\67\3\327\7\67"+
+    "\1\327\10\67\1\327\13\67\1\327\7\67\1\327\2\67"+
+    "\1\0\2\63\1\0\2\63\3\0\4\63\2\0\2\63"+
+    "\1\330\5\63\4\0\2\63\1\0\2\63\4\0\5\63"+
+    "\6\0\3\63\2\0\2\63\1\0\2\63\3\0\3\63"+
+    "\1\331\2\0\10\63\4\0\2\63\1\0\2\63\4\0"+
+    "\5\63\6\0\3\63\1\0\5\267\1\332\56\267\2\211"+
+    "\1\267\1\211\1\333\3\267\4\211\2\267\10\211\4\267"+
+    "\2\211\1\267\2\211\4\267\5\211\6\267\3\211\1\267"+
+    "\1\0\2\63\1\0\2\63\3\0\3\63\1\334\2\0"+
+    "\10\63\4\0\2\63\1\0\2\63\4\0\5\63\6\0"+
+    "\3\63\46\0\1\335\74\0\1\336\15\0\1\337\131\0"+
+    "\1\340\2\0\2\63\1\0\2\63\3\0\4\63\2\0"+
+    "\2\63\1\341\5\63\4\0\2\63\1\0\2\63\4\0"+
+    "\5\63\6\0\3\63\2\0\2\63\1\0\2\63\3\0"+
+    "\3\63\1\342\2\0\10\63\4\0\2\63\1\0\2\63"+
+    "\4\0\5\63\6\0\3\63\6\0\1\26\76\0\1\343"+
+    "\66\0\1\344\47\0\1\345\61\0\1\346\65\0\1\347"+
+    "\62\0\1\350\62\0\1\351\71\0\1\352\76\0\1\353"+
+    "\25\0\1\316\6\0\3\316\7\0\1\316\4\0\1\315"+
+    "\3\0\1\316\13\0\1\316\7\0\1\316\2\0\12\46"+
+    "\1\354\30\46\1\0\21\46\1\321\6\46\3\321\7\46"+
+    "\1\321\4\46\1\320\3\46\1\321\6\46\1\0\4\46"+
+    "\1\321\7\46\1\321\2\46\12\54\1\355\27\54\1\0"+
+    "\22\54\1\324\6\54\3\324\7\54\1\324\4\54\1\323"+
+    "\3\54\1\324\5\54\1\0\5\54\1\324\7\54\1\324"+
+    "\2\54\5\67\1\175\4\67\1\356\52\67\1\327\2\67"+
+    "\1\175\3\67\3\327\7\67\1\327\4\67\1\326\3\67"+
+    "\1\327\13\67\1\327\7\67\1\327\2\67\1\0\2\63"+
+    "\1\0\2\63\3\0\4\63\2\0\1\357\7\63\4\0"+
+    "\2\63\1\0\2\63\4\0\5\63\6\0\3\63\2\0"+
+    "\2\63\1\0\2\63\3\0\4\63\2\0\4\63\1\360"+
+    "\3\63\4\0\2\63\1\0\2\63\4\0\5\63\6\0"+
+    "\3\63\1\0\5\267\1\361\55\267\1\0\2\63\1\0"+
+    "\2\63\3\0\4\63\2\0\10\63\4\0\2\63\1\0"+
+    "\2\63\4\0\1\362\4\63\6\0\3\63\22\0\1\363"+
+    "\63\0\1\364\53\0\1\365\72\0\1\366\40\0\2\63"+
+    "\1\0\2\63\3\0\4\63\2\0\1\367\7\63\4\0"+
+    "\2\63\1\0\2\63\4\0\5\63\6\0\3\63\2\0"+
+    "\2\63\1\0\2\63\3\0\4\63\2\0\4\63\1\370"+
+    "\3\63\4\0\2\63\1\0\2\63\4\0\5\63\6\0"+
+    "\3\63\23\0\1\371\66\0\1\372\47\0\1\373\63\0"+
+    "\1\374\67\0\1\375\54\0\1\376\66\0\1\377\112\0"+
+    "\1\u0100\53\0\1\u0101\22\0\13\46\1\u0102\27\46\1\0"+
+    "\17\46\13\54\1\u0103\26\54\1\0\20\54\5\67\1\175"+
+    "\5\67\1\u0104\47\67\1\0\2\63\1\0\2\63\3\0"+
+    "\1\u0105\3\63\2\0\10\63\4\0\2\63\1\0\2\63"+
+    "\4\0\5\63\6\0\3\63\2\0\2\63\1\0\2\63"+
+    "\3\0\4\63\2\0\10\63\4\0\2\63\1\0\2\63"+
+    "\4\0\3\63\1\u0106\1\63\6\0\3\63\20\0\1\u0107"+
+    "\62\0\1\u0108\57\0\1\u0109\60\0\1\u010a\51\0\2\63"+
+    "\1\0\2\63\3\0\1\u010b\3\63\2\0\10\63\4\0"+
+    "\2\63\1\0\2\63\4\0\5\63\6\0\3\63\2\0"+
+    "\2\63\1\0\2\63\3\0\4\63\2\0\10\63\4\0"+
+    "\2\63\1\0\2\63\4\0\3\63\1\u010c\1\63\6\0"+
+    "\3\63\13\0\1\u010d\73\0\1\u010e\53\0\1\u010f\112\0"+
+    "\1\u0110\35\0\1\u0111\57\0\1\u0112\62\0\1\u0113\71\0"+
+    "\1\u0114\37\0\14\46\1\u0115\26\46\1\0\17\46\14\54"+
+    "\1\u0116\25\54\1\0\20\54\5\67\1\175\6\67\1\u0117"+
+    "\46\67\23\0\1\u0118\65\0\1\u0119\47\0\1\u011a\72\0"+
+    "\1\u011b\52\0\1\u011c\114\0\1\u011d\63\0\1\u011e\33\0"+
+    "\1\u011f\107\0\1\u0120\36\0\1\u0121\42\0\13\46\1\u0122"+
+    "\27\46\1\0\17\46\13\54\1\u0123\26\54\1\0\20\54"+
+    "\5\67\1\175\5\67\1\u0124\47\67\12\0\1\u0125\73\0"+
+    "\1\u0126\47\0\1\u0127\75\0\1\u0128\53\0\1\u0129\73\0"+
+    "\1\u012a\51\0\1\u012b\46\0\10\46\1\u012c\32\46\1\0"+
+    "\17\46\10\54\1\u012d\31\54\1\0\20\54\5\67\1\175"+
+    "\2\67\1\u012e\52\67\12\0\1\u012f\70\0\1\u0130\42\0";
+
+  private static int [] zzUnpackTrans() {
+    int [] result = new int[11067];
+    int offset = 0;
+    offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackTrans(String packed, int offset, int [] result) {
+    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 result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /* error codes */
+  private static final int ZZ_UNKNOWN_ERROR = 0;
+  private static final int ZZ_NO_MATCH = 1;
+  private static final int ZZ_PUSHBACK_2BIG = 2;
+  private static final char[] EMPTY_BUFFER = new char[0];
+  private static final int YYEOF = -1;
+  private static java.io.Reader zzReader = null; // Fake
+
+  /* error messages for the codes above */
+  private static final String ZZ_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /**
+   * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+  private static final String ZZ_ATTRIBUTE_PACKED_0 =
+    "\3\0\2\1\2\0\1\1\14\0\1\1\1\11\5\1"+
+    "\1\11\3\1\1\11\2\1\3\11\5\1\1\11\10\1"+
+    "\2\11\7\1\3\11\3\1\2\11\6\1\2\11\10\1"+
+    "\1\11\2\1\1\11\2\1\3\11\2\1\7\11\5\1"+
+    "\1\0\1\1\1\11\4\0\1\11\10\1\1\11\2\0"+
+    "\4\1\2\11\2\1\2\0\1\1\1\0\2\1\4\0"+
+    "\2\1\4\0\1\11\1\0\1\1\5\0\2\11\2\0"+
+    "\12\1\1\11\1\0\2\1\1\0\5\1\1\0\3\1"+
+    "\4\0\2\1\1\0\1\11\2\0\1\11\7\0\1\11"+
+    "\1\0\13\1\1\0\2\1\4\0\2\1\11\0\5\1"+
+    "\1\11\1\1\4\0\2\1\10\0\1\11\5\1\3\0"+
+    "\1\11\2\1\1\0\1\11\6\0\3\1\2\0\2\11"+
+    "\4\0\1\11\1\0\3\1\1\11\1\0\3\11\1\0"+
+    "\1\11\3\1\2\11";
+
+  private static int [] zzUnpackAttribute() {
+    int [] result = new int[304];
+    int offset = 0;
+    offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAttribute(String packed, int offset, int [] result) {
+    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++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+  /** the current state of the DFA */
+  private int zzState;
+
+  /** the current lexical state */
+  private int zzLexicalState = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private CharSequence zzBuffer = "";
+
+  /** this buffer may contains the current text array to be matched when it is cheap to acquire it */
+  private char[] zzBufferArray;
+
+  /** the textposition at the last accepting state */
+  private int zzMarkedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int zzPushbackPos;
+
+  /** the current text position in the buffer */
+  private int zzCurrentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int zzStartRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int zzEndRead;
+
+  /**
+   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean zzAtBOL = true;
+
+  /** zzAtEOF == true <=> the scanner is at the EOF */
+  private boolean zzAtEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean zzEOFDone;
+
+  /* user code: */
+   private boolean isHighlightModeOn = false;
+
+   public _DtdLexer(boolean highlightModeOn) {
+     this((java.io.Reader)null);
+     isHighlightModeOn = highlightModeOn;
+   }
+
+
+  public _DtdLexer(java.io.Reader in) {
+    this.zzReader = 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 _DtdLexer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] zzUnpackCMap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1578) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+  public final int getTokenStart(){
+    return zzStartRead;
+  }
+
+  public final int getTokenEnd(){
+    return getTokenStart() + yylength();
+  }
+
+  public void reset(CharSequence buffer, int start, int end,int initialState){
+    zzBuffer = buffer;
+    zzBufferArray = com.intellij.util.text.CharArrayUtil.fromSequenceWithoutCopying(buffer);
+    zzCurrentPos = zzMarkedPos = zzStartRead = start;
+    zzPushbackPos = 0;
+    zzAtEOF  = false;
+    zzAtBOL = true;
+    zzEndRead = end;
+    yybegin(initialState);
+  }
+
+  /**
+   * Refills the input buffer.
+   *
+   * @return      <code>false</code>, iff there was new input.
+   *
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean zzRefill() throws java.io.IOException {
+    return true;
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  public final int yystate() {
+    return zzLexicalState;
+  }
+
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  public final void yybegin(int newState) {
+    zzLexicalState = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  public final CharSequence yytext() {
+    return zzBuffer.subSequence(zzStartRead, zzMarkedPos);
+  }
+
+
+  /**
+   * 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
+   */
+  public final char yycharat(int pos) {
+    return zzBufferArray != null ? zzBufferArray[zzStartRead+pos]:zzBuffer.charAt(zzStartRead+pos);
+  }
+
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  public final int yylength() {
+    return zzMarkedPos-zzStartRead;
+  }
+
+
+  /**
+   * 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 zzScanError(int errorCode) {
+    String message;
+    try {
+      message = ZZ_ERROR_MSG[errorCode];
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      message = ZZ_ERROR_MSG[ZZ_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()!
+   */
+  public void yypushback(int number)  {
+    if ( number > yylength() )
+      zzScanError(ZZ_PUSHBACK_2BIG);
+
+    zzMarkedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void zzDoEOF() {
+    if (!zzEOFDone) {
+      zzEOFDone = true;
+    
+    }
+  }
+
+
+  /**
+   * 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   java.io.IOException  if any I/O-Error occurs
+   */
+  public IElementType advance() throws java.io.IOException {
+    int zzInput;
+    int zzAction;
+
+    // cached fields:
+    int zzCurrentPosL;
+    int zzMarkedPosL;
+    int zzEndReadL = zzEndRead;
+    CharSequence zzBufferL = zzBuffer;
+    char[] zzBufferArrayL = zzBufferArray;
+    char [] zzCMapL = ZZ_CMAP;
+
+    int [] zzTransL = ZZ_TRANS;
+    int [] zzRowMapL = ZZ_ROWMAP;
+    int [] zzAttrL = ZZ_ATTRIBUTE;
+
+    while (true) {
+      zzMarkedPosL = zzMarkedPos;
+
+      zzAction = -1;
+
+      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+
+      zzState = ZZ_LEXSTATE[zzLexicalState];
+
+
+      zzForAction: {
+        while (true) {
+
+          if (zzCurrentPosL < zzEndReadL)
+            zzInput = zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++]:zzBufferL.charAt(zzCurrentPosL++);
+          else if (zzAtEOF) {
+            zzInput = YYEOF;
+            break zzForAction;
+          }
+          else {
+            // store back cached positions
+            zzCurrentPos  = zzCurrentPosL;
+            zzMarkedPos   = zzMarkedPosL;
+            boolean eof = zzRefill();
+            // get translated positions and possibly new buffer
+            zzCurrentPosL  = zzCurrentPos;
+            zzMarkedPosL   = zzMarkedPos;
+            zzBufferL      = zzBuffer;
+            zzEndReadL     = zzEndRead;
+            if (eof) {
+              zzInput = YYEOF;
+              break zzForAction;
+            }
+            else {
+              zzInput = zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++]:zzBufferL.charAt(zzCurrentPosL++);
+            }
+          }
+          int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
+          if (zzNext == -1) break zzForAction;
+          zzState = zzNext;
+
+          int zzAttributes = zzAttrL[zzState];
+          if ( (zzAttributes & 1) == 1 ) {
+            zzAction = zzState;
+            zzMarkedPosL = zzCurrentPosL;
+            if ( (zzAttributes & 8) == 8 ) break zzForAction;
+          }
+
+        }
+      }
+
+      // store back cached position
+      zzMarkedPos = zzMarkedPosL;
+
+      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 53: 
+          { yybegin(DOCTYPE_MARKUP_STARTED); yypushback(yylength());
+          }
+        case 72: break;
+        case 21: 
+          { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_MARKUP_START;
+          }
+        case 73: break;
+        case 1: 
+          { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+          }
+        case 74: break;
+        case 60: 
+          { return XmlTokenType.XML_DOCTYPE_SYSTEM;
+          }
+        case 75: break;
+        case 36: 
+          { return XmlTokenType.XML_COMMA;
+          }
+        case 76: break;
+        case 9: 
+          { return XmlTokenType.XML_EQ;
+          }
+        case 77: break;
+        case 66: 
+          { yybegin(CDATA); return XmlTokenType.XML_CDATA_START;
+          }
+        case 78: break;
+        case 16: 
+          { yybegin(ATTRIBUTE_VALUE_START); return XmlTokenType.XML_EQ;
+          }
+        case 79: break;
+        case 61: 
+          { return XmlTokenType.XML_CONDITIONAL_IGNORE;
+          }
+        case 80: break;
+        case 26: 
+          { return XmlTokenType.XML_SEMI;
+          }
+        case 81: break;
+        case 55: 
+          { yybegin(DECL); return XmlTokenType.XML_DECL_START;
+          }
+        case 82: break;
+        case 11: 
+          { yybegin(DECL_ATTR_VALUE_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 83: break;
+        case 69: 
+          { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_ELEMENT_DECL_START;
+          }
+        case 84: break;
+        case 14: 
+          { return XmlTokenType.XML_NAME;
+          }
+        case 85: break;
+        case 19: 
+          { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;
+          }
+        case 86: break;
+        case 10: 
+          { yybegin(DECL_ATTR_VALUE_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 87: break;
+        case 59: 
+          { return XmlTokenType.XML_DOCTYPE_PUBLIC;
+          }
+        case 88: break;
+        case 51: 
+          { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_START;
+          }
+        case 89: break;
+        case 7: 
+          { yybegin(DECL_ATTR); return XmlTokenType.XML_NAME;
+          }
+        case 90: break;
+        case 37: 
+          { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;
+          }
+        case 91: break;
+        case 65: 
+          { return XmlTokenType.XML_ATT_IMPLIED;
+          }
+        case 92: break;
+        case 68: 
+          { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_ATTLIST_DECL_START;
+          }
+        case 93: break;
+        case 3: 
+          { return XmlTokenType.XML_DATA_CHARACTERS;
+          }
+        case 94: break;
+        case 6: 
+          { return XmlTokenType.XML_BAD_CHARACTER;
+          }
+        case 95: break;
+        case 15: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_TAG_END;
+          }
+        case 96: break;
+        case 13: 
+          { yybegin(TAG_ATTRIBUTES); return isHighlightModeOn ? XmlTokenType.XML_TAG_NAME:XmlTokenType.XML_NAME;
+          }
+        case 97: break;
+        case 48: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_COMMENT_END;
+          }
+        case 98: break;
+        case 31: 
+          { return XmlTokenType.XML_LEFT_PAREN;
+          }
+        case 99: break;
+        case 62: 
+          { return XmlTokenType.XML_PCDATA;
+          }
+        case 100: break;
+        case 39: 
+          { yybegin(TAG_NAME); return XmlTokenType.XML_END_TAG_START;
+          }
+        case 101: break;
+        case 58: 
+          { return XmlTokenType.XML_ATT_FIXED;
+          }
+        case 102: break;
+        case 44: 
+          { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_COMMENT_END;
+          }
+        case 103: break;
+        case 23: 
+          { yybegin(DOCTYPE); return XmlTokenType.XML_MARKUP_END;
+          }
+        case 104: break;
+        case 43: 
+          { yybegin(DOCTYPE_COMMENT); return XmlTokenType.XML_COMMENT_START;
+          }
+        case 105: break;
+        case 20: 
+          { return XmlTokenType.XML_PI_TARGET;
+          }
+        case 106: break;
+        case 63: 
+          { return XmlTokenType.XML_CONDITIONAL_INCLUDE;
+          }
+        case 107: break;
+        case 41: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_EMPTY_ELEMENT_END;
+          }
+        case 108: break;
+        case 32: 
+          { return XmlTokenType.XML_RIGHT_PAREN;
+          }
+        case 109: break;
+        case 8: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_BAD_CHARACTER;
+          }
+        case 110: break;
+        case 38: 
+          { yybegin(PROCESSING_INSTRUCTION); return XmlTokenType.XML_PI_START;
+          }
+        case 111: break;
+        case 64: 
+          { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_ENTITY_DECL_START;
+          }
+        case 112: break;
+        case 29: 
+          { yybegin(DOCTYPE_MARKUP_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 113: break;
+        case 54: 
+          { return XmlTokenType.XML_CONTENT_EMPTY;
+          }
+        case 114: break;
+        case 33: 
+          { return XmlTokenType.XML_PLUS;
+          }
+        case 115: break;
+        case 30: 
+          { yybegin(DOCTYPE_MARKUP_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 116: break;
+        case 49: 
+          { return XmlTokenType.XML_CONTENT_ANY;
+          }
+        case 117: break;
+        case 22: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_DOCTYPE_END;
+          }
+        case 118: break;
+        case 52: 
+          { return XmlTokenType.XML_CHAR_ENTITY_REF;
+          }
+        case 119: break;
+        case 70: 
+          { return XmlTokenType.XML_ATT_REQUIRED;
+          }
+        case 120: break;
+        case 28: 
+          { return XmlTokenType.XML_QUESTION;
+          }
+        case 121: break;
+        case 57: 
+          { yybegin(DOCTYPE_EXTERNAL_ID); return XmlTokenType.XML_DOCTYPE_SYSTEM;
+          }
+        case 122: break;
+        case 34: 
+          { return XmlTokenType.XML_STAR;
+          }
+        case 123: break;
+        case 40: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_DECL_END;
+          }
+        case 124: break;
+        case 4: 
+          { return XmlTokenType.XML_WHITE_SPACE;
+          }
+        case 125: break;
+        case 47: 
+          { return XmlTokenType.XML_ENTITY_REF_TOKEN;
+          }
+        case 126: break;
+        case 27: 
+          { return XmlTokenType.XML_PERCENT;
+          }
+        case 127: break;
+        case 5: 
+          { yybegin(TAG_NAME); return XmlTokenType.XML_START_TAG_START;
+          }
+        case 128: break;
+        case 46: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_CONDITIONAL_SECTION_END;
+          }
+        case 129: break;
+        case 50: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_CDATA_END;
+          }
+        case 130: break;
+        case 56: 
+          { yybegin(DOCTYPE_EXTERNAL_ID); return XmlTokenType.XML_DOCTYPE_PUBLIC;
+          }
+        case 131: break;
+        case 12: 
+          { yybegin(DECL); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;
+          }
+        case 132: break;
+        case 25: 
+          { return XmlTokenType.XML_AMP;
+          }
+        case 133: break;
+        case 42: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_PI_END;
+          }
+        case 134: break;
+        case 18: 
+          { yybegin(ATTRIBUTE_VALUE_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 135: break;
+        case 67: 
+          { yybegin(DOCTYPE); return XmlTokenType.XML_DOCTYPE_START;
+          }
+        case 136: break;
+        case 17: 
+          { yybegin(ATTRIBUTE_VALUE_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 137: break;
+        case 71: 
+          { yybegin(DOCTYPE_MARKUP); return XmlTokenType.XML_NOTATION_DECL_START;
+          }
+        case 138: break;
+        case 24: 
+          { return XmlTokenType.XML_TAG_END;
+          }
+        case 139: break;
+        case 35: 
+          { return XmlTokenType.XML_BAR;
+          }
+        case 140: break;
+        case 2: 
+          { return XmlTokenType.XML_COMMENT_CHARACTERS;
+          }
+        case 141: break;
+        case 45: 
+          { yybegin(CONDITIONAL); return XmlTokenType.XML_CONDITIONAL_SECTION_START;
+          }
+        case 142: break;
+        default:
+          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+            zzAtEOF = true;
+            zzDoEOF();
+            return null;
+          }
+          else {
+            zzScanError(ZZ_NO_MATCH);
+          }
+      }
+    }
+  }
+
+
+}
diff --git a/xml/impl/src/com/intellij/lexer/_HtmlLexer.flex b/xml/impl/src/com/intellij/lexer/_HtmlLexer.flex
new file mode 100644
index 0000000..8def2be
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/_HtmlLexer.flex
@@ -0,0 +1,157 @@
+/* It's an automatically generated code. Do not modify it. */
+package com.intellij.lexer;
+
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.*;
+import com.intellij.psi.xml.*;
+
+%%
+
+%unicode
+
+%{
+  private IElementType elTokenType = XmlTokenType.XML_DATA_CHARACTERS;
+  private IElementType elTokenType2 = XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+
+  public void setElTypes(IElementType _elTokenType,IElementType _elTokenType2) {
+    elTokenType = _elTokenType;
+    elTokenType2 = _elTokenType2;
+  }
+
+  public _HtmlLexer() {
+    this((java.io.Reader)null);
+  }
+%}
+
+%class _HtmlLexer
+%public
+%implements FlexLexer,ELHostLexer
+%function advance
+%type IElementType
+%eof{ return;
+%eof}
+
+%state DOC_TYPE
+%state COMMENT
+%state START_TAG_NAME
+%state END_TAG_NAME
+%state TAG_ATTRIBUTES
+%state ATTRIBUTE_VALUE_START
+%state ATTRIBUTE_VALUE_DQ
+%state ATTRIBUTE_VALUE_SQ
+%state PROCESSING_INSTRUCTION
+%state START_TAG_NAME2
+%state END_TAG_NAME2
+%state TAG_CHARACTERS
+%state C_COMMENT_START
+%state C_COMMENT_END
+/* IMPORTANT! number of states should not exceed 16. See JspHighlightingLexer. */
+
+ALPHA=[:letter:]
+DIGIT=[0-9]
+WHITE_SPACE_CHARS=[ \n\r\t\f]+
+
+TAG_NAME=({ALPHA}|"_"|":")({ALPHA}|{DIGIT}|"_"|":"|"."|"-")*
+TAG_NAME_FWT=("#")({ALPHA}|{DIGIT}|"_"|":"|"."|"-")*
+ATTRIBUTE_NAME=({ALPHA}|"_"|":")({ALPHA}|{DIGIT}|"_"|":"|"."|"-")*
+
+DTD_REF= "\"" [^\"]* "\"" | "'" [^']* "'"
+DOCTYPE= "<!" (D|d)(O|o)(C|c)(T|t)(Y|y)(P|p)(E|e)
+HTML= (H|h)(T|t)(M|m)(L|l)
+PUBLIC= (P|p)(U|u)(B|b)(L|l)(I|i)(C|c)
+EL_EMBEDDMENT="${" [^\}]* "}"
+
+END_COMMENT="--"[ \n\r\t\f]*">"
+
+CONDITIONAL_COMMENT_CONDITION=({ALPHA})({ALPHA}|{WHITE_SPACE_CHARS}|{DIGIT}|"."|"("|")"|"|"|"!"|"&")*
+%%
+
+<YYINITIAL> "<?" { yybegin(PROCESSING_INSTRUCTION); return XmlTokenType.XML_PI_START; }
+<PROCESSING_INSTRUCTION> "?"? ">" { yybegin(YYINITIAL); return XmlTokenType.XML_PI_END; }
+<PROCESSING_INSTRUCTION> ([^\?\>] | (\?[^\>]))* { return XmlTokenType.XML_PI_TARGET; }
+
+<YYINITIAL> {DOCTYPE} { yybegin(DOC_TYPE); return XmlTokenType.XML_DOCTYPE_START; }
+<DOC_TYPE> {HTML} { return XmlTokenType.XML_NAME; }
+<DOC_TYPE> {PUBLIC} { return XmlTokenType.XML_DOCTYPE_PUBLIC; }
+<DOC_TYPE> {DTD_REF} { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+<DOC_TYPE> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_DOCTYPE_END; }
+<YYINITIAL> {WHITE_SPACE_CHARS} { return XmlTokenType.XML_REAL_WHITE_SPACE; }
+<DOC_TYPE,TAG_ATTRIBUTES,ATTRIBUTE_VALUE_START,PROCESSING_INSTRUCTION, START_TAG_NAME, END_TAG_NAME, END_TAG_NAME2, TAG_CHARACTERS> {WHITE_SPACE_CHARS} { return XmlTokenType.XML_WHITE_SPACE; }
+<YYINITIAL> "<" {TAG_NAME} { yybegin(START_TAG_NAME); yypushback(yylength()); }
+<YYINITIAL> "<" {TAG_NAME_FWT} { yybegin(START_TAG_NAME2); yypushback(yylength()); }
+<START_TAG_NAME, START_TAG_NAME2, TAG_CHARACTERS> "<" { return XmlTokenType.XML_START_TAG_START; }
+
+<YYINITIAL> "</" {TAG_NAME} { yybegin(END_TAG_NAME); yypushback(yylength()); }
+<YYINITIAL> "</" {TAG_NAME_FWT} { yybegin(END_TAG_NAME2); yypushback(yylength()); }
+<YYINITIAL, END_TAG_NAME, END_TAG_NAME2> "</" { return XmlTokenType.XML_END_TAG_START; }
+
+<YYINITIAL> "<!--" { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_START; }
+<COMMENT> "[" { yybegin(C_COMMENT_START); return XmlTokenType.XML_CONDITIONAL_COMMENT_START; }
+<COMMENT> "<![" { yybegin(C_COMMENT_END); return XmlTokenType.XML_CONDITIONAL_COMMENT_END_START; }
+<COMMENT> {END_COMMENT} { yybegin(YYINITIAL); return XmlTokenType.XML_COMMENT_END; }
+<COMMENT> [^] { return XmlTokenType.XML_COMMENT_CHARACTERS; }
+
+<C_COMMENT_START,C_COMMENT_END> {CONDITIONAL_COMMENT_CONDITION} { return XmlTokenType.XML_COMMENT_CHARACTERS; }
+<C_COMMENT_START> [^] { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_CHARACTERS; }
+<C_COMMENT_START> "]>" { yybegin(COMMENT); return XmlTokenType.XML_CONDITIONAL_COMMENT_START_END; }
+<C_COMMENT_START,C_COMMENT_END> {END_COMMENT} { yybegin(YYINITIAL); return XmlTokenType.XML_COMMENT_END; }
+<C_COMMENT_END> "]" { yybegin(COMMENT); return XmlTokenType.XML_CONDITIONAL_COMMENT_END; }
+<C_COMMENT_END> [^] { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_CHARACTERS; }
+
+<YYINITIAL> \\\$ {
+  return XmlTokenType.XML_DATA_CHARACTERS;
+}
+
+<YYINITIAL> {EL_EMBEDDMENT} {
+  return elTokenType;
+}
+
+<START_TAG_NAME, END_TAG_NAME> {TAG_NAME} { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_NAME; }
+<END_TAG_NAME2> {TAG_NAME_FWT} { return XmlTokenType.XML_NAME; }
+<START_TAG_NAME2> {TAG_NAME_FWT} { yybegin(TAG_CHARACTERS); return XmlTokenType.XML_NAME; }
+
+<TAG_ATTRIBUTES, END_TAG_NAME2, TAG_CHARACTERS> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_TAG_END; }
+<TAG_ATTRIBUTES, TAG_CHARACTERS> "/>" { yybegin(YYINITIAL); return XmlTokenType.XML_EMPTY_ELEMENT_END; }
+<TAG_ATTRIBUTES> {ATTRIBUTE_NAME} { return XmlTokenType.XML_NAME; }
+<TAG_ATTRIBUTES> "=" { yybegin(ATTRIBUTE_VALUE_START); return XmlTokenType.XML_EQ; }
+<TAG_ATTRIBUTES,START_TAG_NAME, END_TAG_NAME, END_TAG_NAME2> [^] { yybegin(YYINITIAL); yypushback(1); break; }
+
+<TAG_CHARACTERS> [^] { return XmlTokenType.XML_TAG_CHARACTERS; }
+
+<ATTRIBUTE_VALUE_START> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_TAG_END; }
+<ATTRIBUTE_VALUE_START> "/>" { yybegin(YYINITIAL); return XmlTokenType.XML_EMPTY_ELEMENT_END; }
+ <ATTRIBUTE_VALUE_START> {EL_EMBEDDMENT} {
+  return elTokenType2;
+}
+
+<ATTRIBUTE_VALUE_START> ([^ \n\r\t\f'\"\>]|(\/[^\>]))* { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN; }
+<ATTRIBUTE_VALUE_START> "\"" { yybegin(ATTRIBUTE_VALUE_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER; }
+<ATTRIBUTE_VALUE_START> "'" { yybegin(ATTRIBUTE_VALUE_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER; }
+
+<ATTRIBUTE_VALUE_DQ> {
+  "\"" { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER; }
+  \\\$ { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN; }
+  "${" [^\}\"]* "}" { return elTokenType2; }
+  [^] { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+}
+
+<ATTRIBUTE_VALUE_SQ> {
+  "'" { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER; }
+  \\\$ { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN; }
+  "${" [^\}\']* "}" { return elTokenType2; }
+  [^] { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+}
+
+"&lt;" |
+"&gt;" |
+"&apos;" |
+"&quot;" |
+"&nbsp;" |
+"&amp;" |
+"&#"{DIGIT}+";" |
+"&#x"({DIGIT}|[a-fA-F])+";" { return XmlTokenType.XML_CHAR_ENTITY_REF; }
+"&"{TAG_NAME}";" { return XmlTokenType.XML_ENTITY_REF_TOKEN; }
+
+<YYINITIAL> ([^<&\$# \n\r\t\f]|(\\\$)|(\\#))* { return XmlTokenType.XML_DATA_CHARACTERS; }
+<YYINITIAL> [^] { return XmlTokenType.XML_DATA_CHARACTERS; }
+[^] { return XmlTokenType.XML_BAD_CHARACTER; }
diff --git a/xml/impl/src/com/intellij/lexer/_HtmlLexer.java b/xml/impl/src/com/intellij/lexer/_HtmlLexer.java
new file mode 100644
index 0000000..e35b5b9
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/_HtmlLexer.java
@@ -0,0 +1,834 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* The following code was generated by JFlex 1.4.1 on 01.06.09 13:59 */
+
+/* It's an automatically generated code. Do not modify it. */
+package com.intellij.lexer;
+
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4.1
+ * on 01.06.09 13:59 from the specification file
+ * <tt>C:/Trunk/tools/lexer/_HtmlLexer.flex</tt>
+ */
+public class _HtmlLexer implements FlexLexer {
+  /** initial size of the lookahead buffer */
+  private static final int ZZ_BUFFERSIZE = 16384;
+
+  /** lexical states */
+  public static final int PROCESSING_INSTRUCTION = 9;
+  public static final int C_COMMENT_END = 14;
+  public static final int END_TAG_NAME = 4;
+  public static final int START_TAG_NAME = 3;
+  public static final int ATTRIBUTE_VALUE_SQ = 8;
+  public static final int DOC_TYPE = 1;
+  public static final int ATTRIBUTE_VALUE_DQ = 7;
+  public static final int YYINITIAL = 0;
+  public static final int TAG_CHARACTERS = 12;
+  public static final int START_TAG_NAME2 = 10;
+  public static final int TAG_ATTRIBUTES = 5;
+  public static final int COMMENT = 2;
+  public static final int ATTRIBUTE_VALUE_START = 6;
+  public static final int C_COMMENT_START = 13;
+  public static final int END_TAG_NAME2 = 11;
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final String ZZ_CMAP_PACKED = 
+    "\11\0\2\3\1\0\2\3\22\0\1\3\1\13\1\10\1\7\1\40"+
+    "\1\0\1\45\1\11\1\44\1\44\3\0\1\6\1\5\1\47\12\2"+
+    "\1\4\1\54\1\12\1\53\1\43\1\46\1\0\1\63\1\35\1\17"+
+    "\1\14\1\25\1\63\1\1\1\26\1\37\2\1\1\31\1\27\1\1"+
+    "\1\15\1\23\3\1\1\20\1\33\3\1\1\22\1\1\1\50\1\52"+
+    "\1\51\1\0\1\4\1\0\1\56\1\36\1\17\1\14\1\25\1\63"+
+    "\1\55\1\26\1\37\2\1\1\32\1\30\1\61\1\16\1\24\1\60"+
+    "\1\1\1\57\1\21\1\34\2\1\1\62\1\22\1\1\1\41\1\44"+
+    "\1\42\54\0\1\1\12\0\1\1\4\0\1\1\5\0\27\1\1\0"+
+    "\37\1\1\0\u013f\1\31\0\162\1\4\0\14\1\16\0\5\1\11\0"+
+    "\1\1\213\0\1\1\13\0\1\1\1\0\3\1\1\0\1\1\1\0"+
+    "\24\1\1\0\54\1\1\0\46\1\1\0\5\1\4\0\202\1\10\0"+
+    "\105\1\1\0\46\1\2\0\2\1\6\0\20\1\41\0\46\1\2\0"+
+    "\1\1\7\0\47\1\110\0\33\1\5\0\3\1\56\0\32\1\5\0"+
+    "\13\1\43\0\2\1\1\0\143\1\1\0\1\1\17\0\2\1\7\0"+
+    "\2\1\12\0\3\1\2\0\1\1\20\0\1\1\1\0\36\1\35\0"+
+    "\3\1\60\0\46\1\13\0\1\1\u0152\0\66\1\3\0\1\1\22\0"+
+    "\1\1\7\0\12\1\43\0\10\1\2\0\2\1\2\0\26\1\1\0"+
+    "\7\1\1\0\1\1\3\0\4\1\3\0\1\1\36\0\2\1\1\0"+
+    "\3\1\16\0\2\1\23\0\6\1\4\0\2\1\2\0\26\1\1\0"+
+    "\7\1\1\0\2\1\1\0\2\1\1\0\2\1\37\0\4\1\1\0"+
+    "\1\1\23\0\3\1\20\0\11\1\1\0\3\1\1\0\26\1\1\0"+
+    "\7\1\1\0\2\1\1\0\5\1\3\0\1\1\22\0\1\1\17\0"+
+    "\2\1\43\0\10\1\2\0\2\1\2\0\26\1\1\0\7\1\1\0"+
+    "\2\1\1\0\5\1\3\0\1\1\36\0\2\1\1\0\3\1\17\0"+
+    "\1\1\21\0\1\1\1\0\6\1\3\0\3\1\1\0\4\1\3\0"+
+    "\2\1\1\0\1\1\1\0\2\1\3\0\2\1\3\0\3\1\3\0"+
+    "\10\1\1\0\3\1\113\0\10\1\1\0\3\1\1\0\27\1\1\0"+
+    "\12\1\1\0\5\1\46\0\2\1\43\0\10\1\1\0\3\1\1\0"+
+    "\27\1\1\0\12\1\1\0\5\1\3\0\1\1\40\0\1\1\1\0"+
+    "\2\1\43\0\10\1\1\0\3\1\1\0\27\1\1\0\20\1\46\0"+
+    "\2\1\43\0\22\1\3\0\30\1\1\0\11\1\1\0\1\1\2\0"+
+    "\7\1\72\0\60\1\1\0\2\1\14\0\7\1\72\0\2\1\1\0"+
+    "\1\1\2\0\2\1\1\0\1\1\2\0\1\1\6\0\4\1\1\0"+
+    "\7\1\1\0\3\1\1\0\1\1\1\0\1\1\2\0\2\1\1\0"+
+    "\4\1\1\0\2\1\11\0\1\1\2\0\5\1\1\0\1\1\25\0"+
+    "\2\1\42\0\1\1\77\0\10\1\1\0\42\1\35\0\4\1\164\0"+
+    "\42\1\1\0\5\1\1\0\2\1\45\0\6\1\112\0\46\1\12\0"+
+    "\51\1\7\0\132\1\5\0\104\1\5\0\122\1\6\0\7\1\1\0"+
+    "\77\1\1\0\1\1\1\0\4\1\2\0\7\1\1\0\1\1\1\0"+
+    "\4\1\2\0\47\1\1\0\1\1\1\0\4\1\2\0\37\1\1\0"+
+    "\1\1\1\0\4\1\2\0\7\1\1\0\1\1\1\0\4\1\2\0"+
+    "\7\1\1\0\7\1\1\0\27\1\1\0\37\1\1\0\1\1\1\0"+
+    "\4\1\2\0\7\1\1\0\47\1\1\0\23\1\105\0\125\1\14\0"+
+    "\u026c\1\2\0\10\1\12\0\32\1\5\0\113\1\25\0\15\1\1\0"+
+    "\4\1\16\0\22\1\16\0\22\1\16\0\15\1\1\0\3\1\17\0"+
+    "\64\1\43\0\1\1\4\0\1\1\103\0\130\1\10\0\51\1\127\0"+
+    "\35\1\63\0\36\1\2\0\5\1\u038b\0\154\1\224\0\234\1\4\0"+
+    "\132\1\6\0\26\1\2\0\6\1\2\0\46\1\2\0\6\1\2\0"+
+    "\10\1\1\0\1\1\1\0\1\1\1\0\1\1\1\0\37\1\2\0"+
+    "\65\1\1\0\7\1\1\0\1\1\3\0\3\1\1\0\7\1\3\0"+
+    "\4\1\2\0\6\1\4\0\15\1\5\0\3\1\1\0\7\1\164\0"+
+    "\1\1\15\0\1\1\202\0\1\1\4\0\1\1\2\0\12\1\1\0"+
+    "\1\1\3\0\5\1\6\0\1\1\1\0\1\1\1\0\1\1\1\0"+
+    "\4\1\1\0\3\1\1\0\7\1\3\0\3\1\5\0\5\1\u0ebb\0"+
+    "\2\1\52\0\5\1\5\0\2\1\4\0\126\1\6\0\3\1\1\0"+
+    "\132\1\1\0\4\1\5\0\50\1\4\0\136\1\21\0\30\1\70\0"+
+    "\20\1\u0200\0\u19b6\1\112\0\u51a6\1\132\0\u048d\1\u0773\0\u2ba4\1\u215c\0"+
+    "\u012e\1\2\0\73\1\225\0\7\1\14\0\5\1\5\0\1\1\1\0"+
+    "\12\1\1\0\15\1\1\0\5\1\1\0\1\1\1\0\2\1\1\0"+
+    "\2\1\1\0\154\1\41\0\u016b\1\22\0\100\1\2\0\66\1\50\0"+
+    "\14\1\164\0\5\1\1\0\207\1\44\0\32\1\6\0\32\1\13\0"+
+    "\131\1\3\0\6\1\2\0\6\1\2\0\6\1\2\0\3\1\43\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+  /** 
+   * Translates DFA states to action switch labels.
+   */
+  private static final int [] ZZ_ACTION = zzUnpackAction();
+
+  private static final String ZZ_ACTION_PACKED_0 =
+    "\1\1\5\0\1\2\2\0\1\3\5\0\1\1\1\4"+
+    "\5\1\1\5\1\6\4\5\1\7\1\5\4\10\1\11"+
+    "\1\12\1\13\1\14\2\12\1\15\1\16\1\12\1\17"+
+    "\1\2\1\20\1\21\2\2\1\22\1\23\4\22\1\3"+
+    "\1\24\1\5\1\25\3\26\1\27\1\10\3\27\1\30"+
+    "\1\31\1\32\1\0\1\33\1\34\15\0\1\34\1\35"+
+    "\2\2\3\0\1\36\2\0\1\37\1\40\1\41\1\42"+
+    "\11\0\1\43\1\44\1\0\1\45\1\2\1\45\1\46"+
+    "\1\0\1\47\3\0\1\15\3\0\1\50\2\0\1\51";
+
+  private static int [] zzUnpackAction() {
+    int [] result = new int[129];
+    int offset = 0;
+    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAction(String packed, int offset, int [] result) {
+    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++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
+
+  private static final String ZZ_ROWMAP_PACKED_0 =
+    "\0\0\0\64\0\150\0\234\0\320\0\u0104\0\u0138\0\u016c"+
+    "\0\u01a0\0\u01d4\0\u0208\0\u023c\0\u0270\0\u02a4\0\u02d8\0\u030c"+
+    "\0\u0340\0\u0374\0\u03a8\0\u03dc\0\u0410\0\u0444\0\u0374\0\u0478"+
+    "\0\u04ac\0\u04e0\0\u0514\0\u0548\0\u0374\0\u0410\0\u0374\0\u057c"+
+    "\0\u05b0\0\u0410\0\u0374\0\u0374\0\u05e4\0\u0374\0\u0410\0\u0618"+
+    "\0\u064c\0\u0374\0\u0680\0\u0374\0\u06b4\0\u0374\0\u0374\0\u06e8"+
+    "\0\u071c\0\u0374\0\u0374\0\u0750\0\u0410\0\u0784\0\u07b8\0\u07ec"+
+    "\0\u0374\0\u0820\0\u0854\0\u0374\0\u0410\0\u0680\0\u0374\0\u0888"+
+    "\0\u057c\0\u0410\0\u08bc\0\u0374\0\u08f0\0\u0924\0\u0958\0\u0374"+
+    "\0\u098c\0\u09c0\0\u09f4\0\u0a28\0\u0a5c\0\u0a90\0\u0ac4\0\u0af8"+
+    "\0\u04ac\0\u04e0\0\u0b2c\0\u0b60\0\u0b94\0\u0bc8\0\u0374\0\u0374"+
+    "\0\u0bfc\0\u0c30\0\u0c64\0\u0c98\0\u0ccc\0\u0374\0\u0d00\0\u0d34"+
+    "\0\u0d68\0\u0d9c\0\u0374\0\u0374\0\u0dd0\0\u0e04\0\u0e38\0\u0e6c"+
+    "\0\u0ea0\0\u0ed4\0\u0f08\0\u0f3c\0\u0f70\0\u0374\0\u0374\0\u0fa4"+
+    "\0\u06b4\0\u0fd8\0\u0374\0\u0374\0\u100c\0\u0374\0\u1040\0\u1074"+
+    "\0\u10a8\0\u0374\0\u10dc\0\u1110\0\u1144\0\u0374\0\u1178\0\u11ac"+
+    "\0\u0374";
+
+  private static int [] zzUnpackRowMap() {
+    int [] result = new int[129];
+    int offset = 0;
+    offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackRowMap(String packed, int offset, int [] result) {
+    int i = 0;  /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int high = packed.charAt(i++) << 16;
+      result[j++] = high | packed.charAt(i++);
+    }
+    return j;
+  }
+
+  /** 
+   * The transition table of the DFA
+   */
+  private static final int [] ZZ_TRANS = zzUnpackTrans();
+
+  private static final String ZZ_TRANS_PACKED_0 =
+    "\3\20\1\21\3\20\1\22\2\20\1\23\25\20\1\24"+
+    "\4\20\1\25\4\20\1\26\11\20\3\27\1\30\4\27"+
+    "\1\31\1\32\11\27\2\33\1\27\1\34\14\27\1\35"+
+    "\1\27\1\36\16\27\6\37\1\40\3\37\1\41\32\37"+
+    "\1\42\2\37\1\43\13\37\1\44\1\45\1\44\1\30"+
+    "\1\45\5\44\1\46\1\44\24\45\5\44\1\47\7\44"+
+    "\7\45\1\44\1\45\1\44\1\30\1\45\5\44\1\50"+
+    "\1\44\24\45\5\44\1\47\7\44\7\45\1\44\1\51"+
+    "\1\44\1\30\1\51\7\44\24\51\3\44\1\52\1\44"+
+    "\1\47\1\44\1\53\3\44\1\54\1\44\7\51\3\55"+
+    "\1\30\4\55\1\56\1\57\26\55\1\60\2\55\1\52"+
+    "\3\55\1\61\14\55\10\62\1\63\27\62\1\64\4\62"+
+    "\1\65\4\62\1\66\22\62\1\63\26\62\1\67\4\62"+
+    "\1\65\4\62\1\66\11\62\43\70\1\71\2\70\1\72"+
+    "\15\70\7\27\1\73\2\27\1\46\32\27\1\36\16\27"+
+    "\3\44\1\30\3\44\1\51\2\44\1\50\30\44\1\52"+
+    "\1\44\1\47\16\44\3\74\1\30\6\74\1\46\30\74"+
+    "\1\52\1\74\1\75\1\74\1\76\14\74\1\77\1\100"+
+    "\4\77\1\101\5\77\24\100\5\77\1\102\3\77\1\103"+
+    "\3\77\7\100\1\77\1\100\4\77\1\101\5\77\24\100"+
+    "\5\77\1\102\3\77\1\104\3\77\7\100\3\20\1\0"+
+    "\3\20\1\0\2\20\1\0\25\20\1\0\4\20\1\0"+
+    "\4\20\1\26\11\20\3\0\1\21\145\0\1\105\2\0"+
+    "\1\105\2\0\1\106\3\0\1\107\24\105\6\0\1\110"+
+    "\1\111\5\0\7\105\41\0\1\112\23\0\1\113\2\0"+
+    "\1\113\2\0\1\114\4\0\16\113\1\115\5\113\15\0"+
+    "\1\115\1\116\1\113\1\117\1\120\2\113\3\20\1\0"+
+    "\6\20\1\0\32\20\1\0\4\20\1\26\11\20\3\0"+
+    "\1\30\60\0\10\121\1\62\53\121\11\122\1\62\52\122"+
+    "\33\0\2\123\47\0\2\124\50\0\1\125\70\0\1\126"+
+    "\51\0\2\45\1\0\3\45\5\0\24\45\15\0\7\45"+
+    "\47\0\1\127\15\0\2\51\1\0\3\51\5\0\24\51"+
+    "\15\0\7\51\43\0\1\130\20\0\3\55\1\0\4\55"+
+    "\2\0\31\55\1\0\3\55\1\131\17\55\1\0\4\55"+
+    "\2\0\27\55\1\132\1\55\1\0\3\55\1\131\57\55"+
+    "\1\130\3\55\1\131\14\55\41\0\1\133\62\0\1\62"+
+    "\64\0\1\134\22\0\43\70\1\0\2\70\1\135\60\70"+
+    "\1\71\20\70\1\0\2\73\1\0\3\73\5\0\24\73"+
+    "\15\0\7\73\1\0\3\100\1\0\1\100\5\0\25\100"+
+    "\4\0\2\100\7\0\7\100\43\0\1\136\21\0\2\105"+
+    "\1\0\3\105\5\0\24\105\15\0\7\105\1\0\2\106"+
+    "\1\0\3\106\5\0\24\106\15\0\7\106\6\0\1\137"+
+    "\5\0\1\140\50\0\1\141\2\0\1\141\2\0\1\142"+
+    "\4\0\24\141\15\0\7\141\42\112\1\143\21\112\1\0"+
+    "\2\113\1\0\3\113\5\0\24\113\14\0\1\144\7\113"+
+    "\2\0\1\145\57\0\1\146\2\0\2\113\1\0\3\113"+
+    "\5\0\5\113\1\147\16\113\14\0\1\144\7\113\1\0"+
+    "\2\113\1\0\3\113\5\0\10\113\1\150\3\113\1\151"+
+    "\7\113\14\0\1\144\7\113\1\0\2\113\1\0\3\113"+
+    "\5\0\20\113\1\152\3\113\14\0\1\144\7\113\1\0"+
+    "\2\113\1\0\3\113\5\0\22\113\1\153\1\113\14\0"+
+    "\1\144\7\113\35\0\2\154\54\0\2\155\36\0\1\125"+
+    "\37\0\1\156\70\0\1\157\13\0\43\55\1\0\3\55"+
+    "\1\131\14\55\3\132\1\160\4\132\2\160\30\132\1\161"+
+    "\1\160\3\132\1\162\14\132\10\133\1\0\31\133\1\163"+
+    "\21\133\11\134\1\0\30\134\1\163\21\134\43\70\1\0"+
+    "\20\70\6\0\1\164\72\0\2\165\46\0\2\141\1\0"+
+    "\3\141\5\0\24\141\15\0\7\141\1\0\2\142\1\0"+
+    "\3\142\5\0\24\142\15\0\7\142\2\0\1\145\51\0"+
+    "\1\166\11\0\1\167\11\0\1\167\2\0\1\167\5\0"+
+    "\1\167\7\0\2\167\17\0\1\167\4\0\1\167\1\0"+
+    "\2\113\1\0\3\113\5\0\24\113\14\0\1\166\7\113"+
+    "\1\0\2\113\1\0\3\113\5\0\2\113\1\170\21\113"+
+    "\14\0\1\144\7\113\1\0\2\113\1\0\3\113\5\0"+
+    "\10\113\1\147\13\113\14\0\1\144\7\113\1\0\2\113"+
+    "\1\0\3\113\5\0\2\113\1\115\21\113\14\0\1\144"+
+    "\7\113\1\0\2\113\1\0\3\113\5\0\24\113\14\0"+
+    "\1\144\2\113\1\151\4\113\31\0\2\171\62\0\2\172"+
+    "\31\0\42\160\1\163\21\160\42\132\1\161\1\160\3\132"+
+    "\1\162\14\132\17\0\1\173\46\0\1\167\11\0\1\167"+
+    "\2\0\1\167\5\0\1\167\7\0\2\167\15\0\1\166"+
+    "\1\0\1\167\4\0\1\167\1\0\2\113\1\0\3\113"+
+    "\5\0\24\113\14\0\1\144\2\113\1\147\4\113\37\0"+
+    "\1\174\44\0\2\175\61\0\1\176\66\0\1\177\64\0"+
+    "\2\200\64\0\1\201\36\0";
+
+  private static int [] zzUnpackTrans() {
+    int [] result = new int[4576];
+    int offset = 0;
+    offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackTrans(String packed, int offset, int [] result) {
+    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 result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /* error codes */
+  private static final int ZZ_UNKNOWN_ERROR = 0;
+  private static final int ZZ_NO_MATCH = 1;
+  private static final int ZZ_PUSHBACK_2BIG = 2;
+  private static final char[] EMPTY_BUFFER = new char[0];
+  private static final int YYEOF = -1;
+  private static java.io.Reader zzReader = null; // Fake
+
+  /* error messages for the codes above */
+  private static final String ZZ_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /**
+   * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+  private static final String ZZ_ATTRIBUTE_PACKED_0 =
+    "\1\1\5\0\1\1\2\0\1\1\5\0\2\1\1\11"+
+    "\4\1\1\11\5\1\1\11\1\1\1\11\3\1\2\11"+
+    "\1\1\1\11\3\1\1\11\1\1\1\11\1\1\2\11"+
+    "\2\1\2\11\5\1\1\11\2\1\1\11\2\1\1\11"+
+    "\4\1\1\11\2\1\1\0\1\11\1\1\15\0\2\11"+
+    "\2\1\3\0\1\11\2\0\2\1\2\11\11\0\2\11"+
+    "\1\0\2\1\2\11\1\0\1\11\3\0\1\11\3\0"+
+    "\1\11\2\0\1\11";
+
+  private static int [] zzUnpackAttribute() {
+    int [] result = new int[129];
+    int offset = 0;
+    offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAttribute(String packed, int offset, int [] result) {
+    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++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+  /** the current state of the DFA */
+  private int zzState;
+
+  /** the current lexical state */
+  private int zzLexicalState = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private CharSequence zzBuffer = "";
+
+  /** this buffer may contains the current text array to be matched when it is cheap to acquire it */
+  private char[] zzBufferArray;
+
+  /** the textposition at the last accepting state */
+  private int zzMarkedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int zzPushbackPos;
+
+  /** the current text position in the buffer */
+  private int zzCurrentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int zzStartRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int zzEndRead;
+
+  /**
+   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean zzAtBOL = true;
+
+  /** zzAtEOF == true <=> the scanner is at the EOF */
+  private boolean zzAtEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean zzEOFDone;
+
+  /* user code: */
+  private IElementType elTokenType = XmlTokenType.XML_DATA_CHARACTERS;
+  private IElementType elTokenType2 = XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+
+  public void setElTypes(IElementType _elTokenType,IElementType _elTokenType2) {
+    elTokenType = _elTokenType;
+    elTokenType2 = _elTokenType2;
+  }
+
+  public _HtmlLexer() {
+    this((java.io.Reader)null);
+  }
+
+
+  public _HtmlLexer(java.io.Reader in) {
+    this.zzReader = 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 _HtmlLexer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] zzUnpackCMap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1260) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+  public final int getTokenStart(){
+    return zzStartRead;
+  }
+
+  public final int getTokenEnd(){
+    return getTokenStart() + yylength();
+  }
+
+  public void reset(CharSequence buffer, int start, int end,int initialState){
+    zzBuffer = buffer;
+    zzBufferArray = com.intellij.util.text.CharArrayUtil.fromSequenceWithoutCopying(buffer);
+    zzCurrentPos = zzMarkedPos = zzStartRead = start;
+    zzPushbackPos = 0;
+    zzAtEOF  = false;
+    zzAtBOL = true;
+    zzEndRead = end;
+    yybegin(initialState);
+  }
+
+  /**
+   * Refills the input buffer.
+   *
+   * @return      <code>false</code>, iff there was new input.
+   *
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean zzRefill() throws java.io.IOException {
+    return true;
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  public final int yystate() {
+    return zzLexicalState;
+  }
+
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  public final void yybegin(int newState) {
+    zzLexicalState = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  public final CharSequence yytext() {
+    return zzBuffer.subSequence(zzStartRead, zzMarkedPos);
+  }
+
+
+  /**
+   * 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
+   */
+  public final char yycharat(int pos) {
+    return zzBufferArray != null ? zzBufferArray[zzStartRead+pos]:zzBuffer.charAt(zzStartRead+pos);
+  }
+
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  public final int yylength() {
+    return zzMarkedPos-zzStartRead;
+  }
+
+
+  /**
+   * 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 zzScanError(int errorCode) {
+    String message;
+    try {
+      message = ZZ_ERROR_MSG[errorCode];
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      message = ZZ_ERROR_MSG[ZZ_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()!
+   */
+  public void yypushback(int number)  {
+    if ( number > yylength() )
+      zzScanError(ZZ_PUSHBACK_2BIG);
+
+    zzMarkedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void zzDoEOF() {
+    if (!zzEOFDone) {
+      zzEOFDone = true;
+    
+    }
+  }
+
+
+  /**
+   * 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   java.io.IOException  if any I/O-Error occurs
+   */
+  public IElementType advance() throws java.io.IOException {
+    int zzInput;
+    int zzAction;
+
+    // cached fields:
+    int zzCurrentPosL;
+    int zzMarkedPosL;
+    int zzEndReadL = zzEndRead;
+    CharSequence zzBufferL = zzBuffer;
+    char[] zzBufferArrayL = zzBufferArray;
+    char [] zzCMapL = ZZ_CMAP;
+
+    int [] zzTransL = ZZ_TRANS;
+    int [] zzRowMapL = ZZ_ROWMAP;
+    int [] zzAttrL = ZZ_ATTRIBUTE;
+
+    while (true) {
+      zzMarkedPosL = zzMarkedPos;
+
+      zzAction = -1;
+
+      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+
+      zzState = zzLexicalState;
+
+
+      zzForAction: {
+        while (true) {
+
+          if (zzCurrentPosL < zzEndReadL)
+            zzInput = zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++]:zzBufferL.charAt(zzCurrentPosL++);
+          else if (zzAtEOF) {
+            zzInput = YYEOF;
+            break zzForAction;
+          }
+          else {
+            // store back cached positions
+            zzCurrentPos  = zzCurrentPosL;
+            zzMarkedPos   = zzMarkedPosL;
+            boolean eof = zzRefill();
+            // get translated positions and possibly new buffer
+            zzCurrentPosL  = zzCurrentPos;
+            zzMarkedPosL   = zzMarkedPos;
+            zzBufferL      = zzBuffer;
+            zzEndReadL     = zzEndRead;
+            if (eof) {
+              zzInput = YYEOF;
+              break zzForAction;
+            }
+            else {
+              zzInput = zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++]:zzBufferL.charAt(zzCurrentPosL++);
+            }
+          }
+          int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
+          if (zzNext == -1) break zzForAction;
+          zzState = zzNext;
+
+          int zzAttributes = zzAttrL[zzState];
+          if ( (zzAttributes & 1) == 1 ) {
+            zzAction = zzState;
+            zzMarkedPosL = zzCurrentPosL;
+            if ( (zzAttributes & 8) == 8 ) break zzForAction;
+          }
+
+        }
+      }
+
+      // store back cached position
+      zzMarkedPos = zzMarkedPosL;
+
+      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 18: 
+          { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+          }
+        case 42: break;
+        case 25: 
+          { yybegin(START_TAG_NAME); yypushback(yylength());
+          }
+        case 43: break;
+        case 22: 
+          { return XmlTokenType.XML_TAG_CHARACTERS;
+          }
+        case 44: break;
+        case 15: 
+          { yybegin(ATTRIBUTE_VALUE_START); return XmlTokenType.XML_EQ;
+          }
+        case 45: break;
+        case 33: 
+          { return elTokenType;
+          }
+        case 46: break;
+        case 13: 
+          { return XmlTokenType.XML_NAME;
+          }
+        case 47: break;
+        case 19: 
+          { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;
+          }
+        case 48: break;
+        case 10: 
+          { yybegin(YYINITIAL); yypushback(1); break;
+          }
+        case 49: break;
+        case 40: 
+          { return XmlTokenType.XML_DOCTYPE_PUBLIC;
+          }
+        case 50: break;
+        case 38: 
+          { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_START;
+          }
+        case 51: break;
+        case 4: 
+          { return XmlTokenType.XML_REAL_WHITE_SPACE;
+          }
+        case 52: break;
+        case 31: 
+          { yybegin(END_TAG_NAME); yypushback(yylength());
+          }
+        case 53: break;
+        case 1: 
+          { return XmlTokenType.XML_DATA_CHARACTERS;
+          }
+        case 54: break;
+        case 24: 
+          { yybegin(COMMENT); return XmlTokenType.XML_CONDITIONAL_COMMENT_END;
+          }
+        case 55: break;
+        case 32: 
+          { yybegin(END_TAG_NAME2); yypushback(yylength());
+          }
+        case 56: break;
+        case 5: 
+          { return XmlTokenType.XML_BAD_CHARACTER;
+          }
+        case 57: break;
+        case 14: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_TAG_END;
+          }
+        case 58: break;
+        case 30: 
+          { yybegin(COMMENT); return XmlTokenType.XML_CONDITIONAL_COMMENT_START_END;
+          }
+        case 59: break;
+        case 28: 
+          { return XmlTokenType.XML_END_TAG_START;
+          }
+        case 60: break;
+        case 35: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_COMMENT_END;
+          }
+        case 61: break;
+        case 41: 
+          { yybegin(DOC_TYPE); return XmlTokenType.XML_DOCTYPE_START;
+          }
+        case 62: break;
+        case 3: 
+          { return XmlTokenType.XML_PI_TARGET;
+          }
+        case 63: break;
+        case 29: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_EMPTY_ELEMENT_END;
+          }
+        case 64: break;
+        case 36: 
+          { yybegin(C_COMMENT_END); return XmlTokenType.XML_CONDITIONAL_COMMENT_END_START;
+          }
+        case 65: break;
+        case 27: 
+          { yybegin(PROCESSING_INSTRUCTION); return XmlTokenType.XML_PI_START;
+          }
+        case 66: break;
+        case 9: 
+          { yybegin(C_COMMENT_START); return XmlTokenType.XML_CONDITIONAL_COMMENT_START;
+          }
+        case 67: break;
+        case 21: 
+          { yybegin(TAG_CHARACTERS); return XmlTokenType.XML_NAME;
+          }
+        case 68: break;
+        case 7: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_DOCTYPE_END;
+          }
+        case 69: break;
+        case 39: 
+          { return XmlTokenType.XML_CHAR_ENTITY_REF;
+          }
+        case 70: break;
+        case 12: 
+          { return XmlTokenType.XML_START_TAG_START;
+          }
+        case 71: break;
+        case 6: 
+          { return XmlTokenType.XML_WHITE_SPACE;
+          }
+        case 72: break;
+        case 34: 
+          { return XmlTokenType.XML_ENTITY_REF_TOKEN;
+          }
+        case 73: break;
+        case 23: 
+          { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_CHARACTERS;
+          }
+        case 74: break;
+        case 37: 
+          { return elTokenType2;
+          }
+        case 75: break;
+        case 20: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_PI_END;
+          }
+        case 76: break;
+        case 16: 
+          { yybegin(ATTRIBUTE_VALUE_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 77: break;
+        case 17: 
+          { yybegin(ATTRIBUTE_VALUE_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 78: break;
+        case 11: 
+          { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_NAME;
+          }
+        case 79: break;
+        case 26: 
+          { yybegin(START_TAG_NAME2); yypushback(yylength());
+          }
+        case 80: break;
+        case 2: 
+          { yybegin(TAG_ATTRIBUTES); return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+          }
+        case 81: break;
+        case 8: 
+          { return XmlTokenType.XML_COMMENT_CHARACTERS;
+          }
+        case 82: break;
+        default:
+          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+            zzAtEOF = true;
+            zzDoEOF();
+            return null;
+          }
+          else {
+            zzScanError(ZZ_NO_MATCH);
+          }
+      }
+    }
+  }
+
+
+}
diff --git a/xml/impl/src/com/intellij/lexer/_XmlLexer.flex b/xml/impl/src/com/intellij/lexer/_XmlLexer.flex
new file mode 100644
index 0000000..7715b96
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/_XmlLexer.flex
@@ -0,0 +1,178 @@
+ /* It's an automatically generated code. Do not modify it. */
+package com.intellij.lexer;
+
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.*;
+import com.intellij.psi.xml.*;
+
+%%
+
+%{
+  private IElementType elTokenType = XmlTokenType.XML_DATA_CHARACTERS;
+  private IElementType elTokenType2 = XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+  private IElementType javaEmbeddedTokenType = XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+  private boolean myConditionalCommentsSupport;
+
+  public void setConditionalCommentsSupport(final boolean b) {
+    myConditionalCommentsSupport = b;
+  }
+
+  public void setElTypes(IElementType _elTokenType,IElementType _elTokenType2) {
+    elTokenType = _elTokenType;
+    elTokenType2 = _elTokenType2;
+  }
+
+  public void setJavaEmbeddedType(IElementType _tokenType) {
+    javaEmbeddedTokenType = _tokenType;
+  }
+
+  private int myPrevState = YYINITIAL;
+
+  public int yyprevstate() {
+    return myPrevState;
+  }
+
+  private int popState(){
+    final int prev = myPrevState;
+    myPrevState = YYINITIAL;
+    return prev;
+  }
+
+  protected void pushState(int state){
+    myPrevState = state;
+  }
+%}
+
+%unicode
+%class __XmlLexer
+%public
+%implements FlexLexer
+%function advance
+%type IElementType
+%eof{  return;
+%eof}
+
+%state TAG
+%state PROCESSING_INSTRUCTION
+%state PI_ANY
+%state END_TAG
+%xstate COMMENT
+%state ATTR_LIST
+%state ATTR
+%state ATTR_VALUE_START
+%state ATTR_VALUE_DQ
+%state ATTR_VALUE_SQ
+%state DTD_MARKUP
+%state DOCTYPE
+%xstate CDATA
+%state C_COMMENT_START
+%state C_COMMENT_END
+
+ALPHA=[:letter:]
+DIGIT=[0-9]
+WS=[\ \n\r\t\f]
+S={WS}+
+
+EL_EMBEDMENT_START="${" | "#{"
+NAME=({ALPHA}|"_")({ALPHA}|{DIGIT}|"_"|"."|"-")*(":"({ALPHA}|"_")?({ALPHA}|{DIGIT}|"_"|"."|"-")*)?
+
+END_COMMENT="-->"
+CONDITIONAL_COMMENT_CONDITION=({ALPHA})({ALPHA}|{S}|{DIGIT}|"."|"("|")"|"|"|"!"|"&")*
+
+%%
+"<![CDATA[" {yybegin(CDATA); return XmlTokenType.XML_CDATA_START; }
+<CDATA>{
+ "]]>"  {yybegin(YYINITIAL); return XmlTokenType.XML_CDATA_END; }
+ [^] {return XmlTokenType.XML_DATA_CHARACTERS; }
+}
+
+"<!--" { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_START; }
+<COMMENT> "[" { if (myConditionalCommentsSupport) {
+    yybegin(C_COMMENT_START);
+    return XmlTokenType.XML_CONDITIONAL_COMMENT_START;
+  } else return XmlTokenType.XML_COMMENT_CHARACTERS; }
+<COMMENT> "<![" { if (myConditionalCommentsSupport) {
+    yybegin(C_COMMENT_END);
+    return XmlTokenType.XML_CONDITIONAL_COMMENT_END_START;
+  } else return XmlTokenType.XML_COMMENT_CHARACTERS; }
+<COMMENT> {END_COMMENT} { yybegin(YYINITIAL); return XmlTokenType.XML_COMMENT_END; }
+<COMMENT> [^\-]|(-[^\-]) { return XmlTokenType.XML_COMMENT_CHARACTERS; }
+<COMMENT> [^] { return XmlTokenType.XML_BAD_CHARACTER; }
+
+<C_COMMENT_START,C_COMMENT_END> {CONDITIONAL_COMMENT_CONDITION} { return XmlTokenType.XML_COMMENT_CHARACTERS; }
+<C_COMMENT_START> [^] { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_CHARACTERS; }
+<C_COMMENT_START> "]>" { yybegin(COMMENT); return XmlTokenType.XML_CONDITIONAL_COMMENT_START_END; }
+<C_COMMENT_START,C_COMMENT_END> {END_COMMENT} { yybegin(YYINITIAL); return XmlTokenType.XML_COMMENT_END; }
+<C_COMMENT_END> "]" { yybegin(COMMENT); return XmlTokenType.XML_CONDITIONAL_COMMENT_END; }
+<C_COMMENT_END> [^] { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_CHARACTERS; }
+
+"&lt;" |
+"&gt;" |
+"&apos;" |
+"&quot;" |
+"&nbsp;" |
+"&amp;" |
+"&#"{DIGIT}+";" |
+"&#x"({DIGIT}|[a-fA-F])+";" { return XmlTokenType.XML_CHAR_ENTITY_REF; }
+"&"{NAME}";" { return XmlTokenType.XML_ENTITY_REF_TOKEN; }
+
+<YYINITIAL> "<!DOCTYPE" { yybegin(DOCTYPE); return XmlTokenType.XML_DOCTYPE_START; }
+<DOCTYPE> "SYSTEM" { return XmlTokenType.XML_DOCTYPE_SYSTEM;  }
+<DOCTYPE> "PUBLIC" { return XmlTokenType.XML_DOCTYPE_PUBLIC;  }
+<DOCTYPE> {NAME} { return XmlTokenType.XML_NAME;  }
+<DOCTYPE> "\""[^\"]*"\"" { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+<DOCTYPE> "'"[^']*"'" { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+<DOCTYPE> "["(([^\]\"]*)|(\"[^\"]*\"))*"]" { return XmlElementType.XML_MARKUP_DECL;}
+<DOCTYPE> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_DOCTYPE_END; }
+
+<YYINITIAL> "<?" { yybegin(PROCESSING_INSTRUCTION); return XmlTokenType.XML_PI_START; }
+<PROCESSING_INSTRUCTION> "xml" { yybegin(ATTR_LIST); pushState(PROCESSING_INSTRUCTION); return XmlTokenType.XML_NAME; }
+<PROCESSING_INSTRUCTION> {NAME} { yybegin(PI_ANY); return XmlTokenType.XML_NAME; }
+<PI_ANY, PROCESSING_INSTRUCTION> "?>" { yybegin(YYINITIAL); return XmlTokenType.XML_PI_END; }
+<PI_ANY> {S} { return XmlTokenType.XML_WHITE_SPACE; }
+<PI_ANY> [^] { return XmlTokenType.XML_TAG_CHARACTERS; }
+
+<YYINITIAL> {EL_EMBEDMENT_START} [^<\}]* "}" {
+  return elTokenType;
+}
+
+<YYINITIAL> "<" { yybegin(TAG); return XmlTokenType.XML_START_TAG_START; }
+<TAG> {NAME} { yybegin(ATTR_LIST); pushState(TAG); return XmlTokenType.XML_NAME; }
+<TAG> "/>" { yybegin(YYINITIAL); return XmlTokenType.XML_EMPTY_ELEMENT_END; }
+<TAG> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_TAG_END; }
+
+<YYINITIAL> "</" { yybegin(END_TAG); return XmlTokenType.XML_END_TAG_START; }
+<END_TAG> {NAME} { return XmlTokenType.XML_NAME; }
+<END_TAG> ">" { yybegin(YYINITIAL); return XmlTokenType.XML_TAG_END; }
+
+<ATTR_LIST> {NAME} {yybegin(ATTR); return XmlTokenType.XML_NAME;}
+<ATTR> "=" { return XmlTokenType.XML_EQ;}
+<ATTR> "'" { yybegin(ATTR_VALUE_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;}
+<ATTR> "\"" { yybegin(ATTR_VALUE_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;}
+<ATTR> [^\ \n\r\t\f] {yybegin(ATTR_LIST); yypushback(yylength()); }
+
+<ATTR_VALUE_DQ>{
+  "\"" { yybegin(ATTR_LIST); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;}
+  "&" { return XmlTokenType.XML_BAD_CHARACTER; }
+  {EL_EMBEDMENT_START} [^\}\"]* "}" { return elTokenType2; }
+  "%=" [^%\"]* "%" { return javaEmbeddedTokenType; }
+  [^] { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+}
+
+<ATTR_VALUE_SQ>{
+  "&" { return XmlTokenType.XML_BAD_CHARACTER; }
+  "'" { yybegin(ATTR_LIST); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;}
+  {EL_EMBEDMENT_START} [^\}\']* "}" { return elTokenType2; }
+  "%=" [^%\']* "%" { return javaEmbeddedTokenType; }
+  [^] { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;}
+}
+
+<YYINITIAL> {S} { return XmlTokenType.XML_REAL_WHITE_SPACE; }
+<ATTR_LIST,ATTR,TAG,END_TAG,DOCTYPE> {S} { return XmlTokenType.XML_WHITE_SPACE; }
+<YYINITIAL> ([^<&\$# \n\r\t\f]|(\\\$)|(\\#))* { return XmlTokenType.XML_DATA_CHARACTERS; }
+<YYINITIAL> [^<&\ \n\r\t\f]|(\\\$)|(\\#) { return XmlTokenType.XML_DATA_CHARACTERS; }
+
+[^] { if(yystate() == YYINITIAL){
+        return XmlTokenType.XML_BAD_CHARACTER;
+      }
+      else yybegin(popState()); yypushback(yylength());}
diff --git a/xml/impl/src/com/intellij/lexer/_XmlLexer.java b/xml/impl/src/com/intellij/lexer/_XmlLexer.java
new file mode 100644
index 0000000..d78deb8
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/_XmlLexer.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* The following code was generated by JFlex 1.4 on 3/14/05 5:43 PM */
+
+/* It's an automatically generated code. Do not modify it. */
+package com.intellij.lexer;
+
+public class _XmlLexer extends FlexAdapter {
+  private int myState = __XmlLexer.YYINITIAL;
+
+  public _XmlLexer(final __XmlLexer flexLexer) {
+    this(flexLexer, false);
+  }
+
+  public _XmlLexer(final __XmlLexer flexLexer, final boolean conditionalCommentsSupport) {
+    super(flexLexer);
+    flexLexer.setConditionalCommentsSupport(conditionalCommentsSupport);
+  }
+
+  private void packState() {
+    final __XmlLexer flex = (__XmlLexer)getFlex();
+    myState = ((flex.yyprevstate() & 15) << 4) | (flex.yystate() & 15);
+  }
+
+  private void handleState(final int initialState) {
+    final __XmlLexer flex = (__XmlLexer)getFlex();
+    flex.yybegin(initialState & 15);
+    flex.pushState((initialState >> 4) & 15);
+    packState();
+  }
+
+  public void start(final CharSequence buffer, final int startOffset, final int endOffset, final int initialState) {
+    super.start(buffer, startOffset, endOffset, initialState);
+    handleState(initialState);
+  }
+
+  public int getState() {
+    return myState;
+  }
+
+  public void advance() {
+    super.advance();
+    packState();
+  }
+}
diff --git a/xml/impl/src/com/intellij/lexer/__XmlLexer.java b/xml/impl/src/com/intellij/lexer/__XmlLexer.java
new file mode 100644
index 0000000..6fb8b5c
--- /dev/null
+++ b/xml/impl/src/com/intellij/lexer/__XmlLexer.java
@@ -0,0 +1,886 @@
+/* The following code was generated by JFlex 1.4.1 on 27.10.09 1:12 */
+
+ /* It's an automatically generated code. Do not modify it. */
+package com.intellij.lexer;
+
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4.1
+ * on 27.10.09 1:12 from the specification file
+ * <tt>C:/IDEA/tools/lexer/_XmlLexer.flex</tt>
+ */
+public class __XmlLexer implements FlexLexer {
+  /** initial size of the lookahead buffer */
+  private static final int ZZ_BUFFERSIZE = 16384;
+
+  /** lexical states */
+  public static final int PROCESSING_INSTRUCTION = 2;
+  public static final int ATTR_LIST = 6;
+  public static final int END_TAG = 4;
+  public static final int ATTR_VALUE_DQ = 9;
+  public static final int C_COMMENT_END = 14;
+  public static final int DTD_MARKUP = 8;
+  public static final int CDATA = 12;
+  public static final int ATTR = 7;
+  public static final int TAG = 1;
+  public static final int PI_ANY = 3;
+  public static final int ATTR_VALUE_START = 8;
+  public static final int YYINITIAL = 0;
+  public static final int COMMENT = 5;
+  public static final int DOCTYPE = 11;
+  public static final int C_COMMENT_START = 13;
+  public static final int ATTR_VALUE_SQ = 10;
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final String ZZ_CMAP_PACKED = 
+    "\11\0\2\3\1\0\2\3\22\0\1\3\1\15\1\57\1\6\1\4"+
+    "\1\65\1\16\1\60\1\14\1\14\3\0\1\11\1\10\1\63\12\2"+
+    "\1\12\1\30\1\17\1\64\1\13\1\61\1\0\1\23\1\54\1\21"+
+    "\1\22\1\50\1\44\2\1\1\56\2\1\1\55\1\52\1\1\1\45"+
+    "\1\47\2\1\1\51\1\24\1\53\3\1\1\46\1\1\1\20\1\66"+
+    "\1\25\1\0\1\7\1\0\1\32\1\41\4\44\1\31\4\1\1\26"+
+    "\1\42\1\40\1\34\1\33\1\36\1\1\1\35\1\27\1\37\2\1"+
+    "\1\43\2\1\1\5\1\14\1\62\54\0\1\1\12\0\1\1\4\0"+
+    "\1\1\5\0\27\1\1\0\37\1\1\0\u013f\1\31\0\162\1\4\0"+
+    "\14\1\16\0\5\1\11\0\1\1\213\0\1\1\13\0\1\1\1\0"+
+    "\3\1\1\0\1\1\1\0\24\1\1\0\54\1\1\0\46\1\1\0"+
+    "\5\1\4\0\202\1\10\0\105\1\1\0\46\1\2\0\2\1\6\0"+
+    "\20\1\41\0\46\1\2\0\1\1\7\0\47\1\110\0\33\1\5\0"+
+    "\3\1\56\0\32\1\5\0\13\1\43\0\2\1\1\0\143\1\1\0"+
+    "\1\1\17\0\2\1\7\0\2\1\12\0\3\1\2\0\1\1\20\0"+
+    "\1\1\1\0\36\1\35\0\3\1\60\0\46\1\13\0\1\1\u0152\0"+
+    "\66\1\3\0\1\1\22\0\1\1\7\0\12\1\43\0\10\1\2\0"+
+    "\2\1\2\0\26\1\1\0\7\1\1\0\1\1\3\0\4\1\3\0"+
+    "\1\1\36\0\2\1\1\0\3\1\16\0\2\1\23\0\6\1\4\0"+
+    "\2\1\2\0\26\1\1\0\7\1\1\0\2\1\1\0\2\1\1\0"+
+    "\2\1\37\0\4\1\1\0\1\1\23\0\3\1\20\0\11\1\1\0"+
+    "\3\1\1\0\26\1\1\0\7\1\1\0\2\1\1\0\5\1\3\0"+
+    "\1\1\22\0\1\1\17\0\2\1\43\0\10\1\2\0\2\1\2\0"+
+    "\26\1\1\0\7\1\1\0\2\1\1\0\5\1\3\0\1\1\36\0"+
+    "\2\1\1\0\3\1\17\0\1\1\21\0\1\1\1\0\6\1\3\0"+
+    "\3\1\1\0\4\1\3\0\2\1\1\0\1\1\1\0\2\1\3\0"+
+    "\2\1\3\0\3\1\3\0\10\1\1\0\3\1\113\0\10\1\1\0"+
+    "\3\1\1\0\27\1\1\0\12\1\1\0\5\1\46\0\2\1\43\0"+
+    "\10\1\1\0\3\1\1\0\27\1\1\0\12\1\1\0\5\1\3\0"+
+    "\1\1\40\0\1\1\1\0\2\1\43\0\10\1\1\0\3\1\1\0"+
+    "\27\1\1\0\20\1\46\0\2\1\43\0\22\1\3\0\30\1\1\0"+
+    "\11\1\1\0\1\1\2\0\7\1\72\0\60\1\1\0\2\1\14\0"+
+    "\7\1\72\0\2\1\1\0\1\1\2\0\2\1\1\0\1\1\2\0"+
+    "\1\1\6\0\4\1\1\0\7\1\1\0\3\1\1\0\1\1\1\0"+
+    "\1\1\2\0\2\1\1\0\4\1\1\0\2\1\11\0\1\1\2\0"+
+    "\5\1\1\0\1\1\25\0\2\1\42\0\1\1\77\0\10\1\1\0"+
+    "\42\1\35\0\4\1\164\0\42\1\1\0\5\1\1\0\2\1\45\0"+
+    "\6\1\112\0\46\1\12\0\51\1\7\0\132\1\5\0\104\1\5\0"+
+    "\122\1\6\0\7\1\1\0\77\1\1\0\1\1\1\0\4\1\2\0"+
+    "\7\1\1\0\1\1\1\0\4\1\2\0\47\1\1\0\1\1\1\0"+
+    "\4\1\2\0\37\1\1\0\1\1\1\0\4\1\2\0\7\1\1\0"+
+    "\1\1\1\0\4\1\2\0\7\1\1\0\7\1\1\0\27\1\1\0"+
+    "\37\1\1\0\1\1\1\0\4\1\2\0\7\1\1\0\47\1\1\0"+
+    "\23\1\105\0\125\1\14\0\u026c\1\2\0\10\1\12\0\32\1\5\0"+
+    "\113\1\25\0\15\1\1\0\4\1\16\0\22\1\16\0\22\1\16\0"+
+    "\15\1\1\0\3\1\17\0\64\1\43\0\1\1\4\0\1\1\103\0"+
+    "\130\1\10\0\51\1\127\0\35\1\63\0\36\1\2\0\5\1\u038b\0"+
+    "\154\1\224\0\234\1\4\0\132\1\6\0\26\1\2\0\6\1\2\0"+
+    "\46\1\2\0\6\1\2\0\10\1\1\0\1\1\1\0\1\1\1\0"+
+    "\1\1\1\0\37\1\2\0\65\1\1\0\7\1\1\0\1\1\3\0"+
+    "\3\1\1\0\7\1\3\0\4\1\2\0\6\1\4\0\15\1\5\0"+
+    "\3\1\1\0\7\1\164\0\1\1\15\0\1\1\202\0\1\1\4\0"+
+    "\1\1\2\0\12\1\1\0\1\1\3\0\5\1\6\0\1\1\1\0"+
+    "\1\1\1\0\1\1\1\0\4\1\1\0\3\1\1\0\7\1\3\0"+
+    "\3\1\5\0\5\1\u0ebb\0\2\1\52\0\5\1\5\0\2\1\4\0"+
+    "\126\1\6\0\3\1\1\0\132\1\1\0\4\1\5\0\50\1\4\0"+
+    "\136\1\21\0\30\1\70\0\20\1\u0200\0\u19b6\1\112\0\u51a6\1\132\0"+
+    "\u048d\1\u0773\0\u2ba4\1\u215c\0\u012e\1\2\0\73\1\225\0\7\1\14\0"+
+    "\5\1\5\0\1\1\1\0\12\1\1\0\15\1\1\0\5\1\1\0"+
+    "\1\1\1\0\2\1\1\0\2\1\1\0\154\1\41\0\u016b\1\22\0"+
+    "\100\1\2\0\66\1\50\0\14\1\164\0\5\1\1\0\207\1\44\0"+
+    "\32\1\6\0\32\1\13\0\131\1\3\0\6\1\2\0\6\1\2\0"+
+    "\6\1\2\0\3\1\43\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+  /** 
+   * Translates DFA states to action switch labels.
+   */
+  private static final int [] ZZ_ACTION = zzUnpackAction();
+
+  private static final String ZZ_ACTION_PACKED_0 =
+    "\1\1\16\0\1\1\1\2\1\1\1\3\1\4\1\1"+
+    "\1\3\1\5\1\6\1\7\2\3\2\10\1\3\4\11"+
+    "\1\12\1\13\1\14\1\13\1\15\1\16\3\17\1\20"+
+    "\1\21\1\22\2\23\1\14\1\23\1\24\3\23\1\25"+
+    "\1\3\2\12\2\3\2\1\1\26\1\13\4\26\1\27"+
+    "\10\0\1\30\1\31\1\5\1\0\1\32\2\10\1\33"+
+    "\1\12\2\0\1\16\5\0\1\34\1\0\2\12\3\0"+
+    "\1\35\1\36\1\0\1\37\12\0\1\40\1\41\1\42"+
+    "\1\43\1\44\2\12\1\45\1\46\2\0\1\47\2\0"+
+    "\2\12\2\0\2\12\2\0\1\50\1\51\4\0\1\52"+
+    "\1\53";
+
+  private static int [] zzUnpackAction() {
+    int [] result = new int[145];
+    int offset = 0;
+    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAction(String packed, int offset, int [] result) {
+    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++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
+
+  private static final String ZZ_ROWMAP_PACKED_0 =
+    "\0\0\0\67\0\156\0\245\0\334\0\u0113\0\u014a\0\u0181"+
+    "\0\u01b8\0\u01ef\0\u0226\0\u025d\0\u0294\0\u02cb\0\u0302\0\u0339"+
+    "\0\u0370\0\u03a7\0\u03de\0\u0415\0\u044c\0\u0483\0\u04ba\0\u04f1"+
+    "\0\u0483\0\u0528\0\u055f\0\u0596\0\u05cd\0\u0604\0\u0483\0\u03de"+
+    "\0\u0528\0\u0604\0\u063b\0\u0483\0\u0672\0\u06a9\0\u0483\0\u06e0"+
+    "\0\u0483\0\u03de\0\u0528\0\u0483\0\u0483\0\u0483\0\u0483\0\u0717"+
+    "\0\u03de\0\u0528\0\u0483\0\u074e\0\u0785\0\u07bc\0\u0483\0\u07f3"+
+    "\0\u082a\0\u0861\0\u0898\0\u08cf\0\u0483\0\u0906\0\u0483\0\u093d"+
+    "\0\u0974\0\u03de\0\u0528\0\u09ab\0\u0483\0\u09e2\0\u0a19\0\u0a50"+
+    "\0\u0a87\0\u0abe\0\u0af5\0\u0b2c\0\u0b63\0\u0483\0\u0483\0\u0b9a"+
+    "\0\u0bd1\0\u0483\0\u0c08\0\u0c3f\0\u0483\0\u0c76\0\u0cad\0\u0ce4"+
+    "\0\u0d1b\0\u0d52\0\u0d89\0\u0dc0\0\u0df7\0\u07f3\0\u0483\0\u0e2e"+
+    "\0\u0e65\0\u0e9c\0\u0898\0\u08cf\0\u0ed3\0\u0483\0\u0483\0\u0f0a"+
+    "\0\u0483\0\u0f41\0\u0f78\0\u0faf\0\u0fe6\0\u101d\0\u1054\0\u108b"+
+    "\0\u10c2\0\u10f9\0\u1130\0\u0596\0\u0483\0\u0483\0\u0483\0\u0483"+
+    "\0\u1167\0\u119e\0\u0483\0\u0483\0\u11d5\0\u120c\0\u0483\0\u1243"+
+    "\0\u127a\0\u12b1\0\u12e8\0\u131f\0\u1356\0\u138d\0\u13c4\0\u13fb"+
+    "\0\u1432\0\u063b\0\u063b\0\u1469\0\u14a0\0\u14d7\0\u150e\0\u0483"+
+    "\0\u0483";
+
+  private static int [] zzUnpackRowMap() {
+    int [] result = new int[145];
+    int offset = 0;
+    offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackRowMap(String packed, int offset, int [] result) {
+    int i = 0;  /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int high = packed.charAt(i++) << 16;
+      result[j++] = high | packed.charAt(i++);
+    }
+    return j;
+  }
+
+  /** 
+   * The transition table of the DFA
+   */
+  private static final int [] ZZ_TRANS = zzUnpackTrans();
+
+  private static final String ZZ_TRANS_PACKED_0 =
+    "\3\20\1\21\1\22\1\20\1\22\7\20\1\23\1\24"+
+    "\46\20\1\25\1\26\1\27\1\26\1\30\3\26\1\27"+
+    "\3\26\1\31\2\26\1\23\1\32\1\26\4\27\1\26"+
+    "\2\27\1\26\26\27\4\26\1\33\4\26\1\34\5\26"+
+    "\1\34\6\26\1\23\1\32\1\26\4\34\1\26\2\34"+
+    "\1\26\12\34\1\35\13\34\2\26\1\36\5\26\3\37"+
+    "\1\30\12\37\1\40\1\41\41\37\1\42\5\37\1\26"+
+    "\1\43\1\26\1\30\3\26\1\43\3\26\1\31\2\26"+
+    "\1\23\1\32\1\26\4\43\1\26\2\43\1\26\26\43"+
+    "\10\26\11\44\1\45\5\44\1\46\1\47\46\44\1\26"+
+    "\1\50\1\26\1\30\3\26\1\50\6\26\1\23\1\32"+
+    "\1\26\4\50\1\26\2\50\1\26\26\50\10\26\3\51"+
+    "\1\30\12\51\1\52\1\53\37\51\1\54\1\55\3\51"+
+    "\1\56\2\51\16\26\1\23\1\32\47\26\4\57\1\60"+
+    "\1\57\1\60\7\57\1\61\1\62\37\57\1\63\5\57"+
+    "\1\64\5\57\1\65\1\57\1\65\7\57\1\61\1\62"+
+    "\40\57\1\63\4\57\1\66\1\57\1\26\1\43\1\26"+
+    "\1\30\3\26\1\43\3\26\1\67\2\26\1\23\1\32"+
+    "\1\70\4\43\1\26\2\43\1\26\16\43\1\71\1\43"+
+    "\1\72\5\43\1\73\1\74\6\26\25\75\1\76\41\75"+
+    "\1\77\1\100\7\77\1\101\4\77\1\102\1\103\1\77"+
+    "\4\100\1\104\2\100\1\77\26\100\11\77\1\100\7\77"+
+    "\1\101\4\77\1\102\1\103\1\77\4\100\1\105\2\100"+
+    "\1\77\26\100\10\77\3\20\2\0\1\20\1\0\7\20"+
+    "\2\0\46\20\1\25\3\0\1\21\70\0\1\106\62\0"+
+    "\1\107\4\0\1\110\1\107\11\0\4\107\1\0\1\111"+
+    "\1\107\1\0\1\111\1\112\3\107\1\113\1\107\1\114"+
+    "\16\107\25\0\1\115\43\0\1\116\1\0\1\117\3\0"+
+    "\3\20\1\0\12\20\2\0\46\20\1\25\70\0\2\27"+
+    "\4\0\3\27\1\120\6\0\4\27\1\0\2\27\1\0"+
+    "\26\27\13\0\1\30\100\0\1\121\64\0\1\122\54\0"+
+    "\2\34\4\0\3\34\1\123\6\0\4\34\1\0\2\34"+
+    "\1\0\26\34\11\0\2\34\4\0\3\34\1\123\6\0"+
+    "\4\34\1\0\2\34\1\0\11\34\1\124\14\34\23\0"+
+    "\1\125\54\0\2\43\4\0\3\43\1\126\6\0\4\43"+
+    "\1\0\2\43\1\0\26\43\10\0\11\44\1\127\55\44"+
+    "\15\0\1\130\52\0\2\50\4\0\3\50\1\131\6\0"+
+    "\4\50\1\0\2\50\1\0\26\50\15\0\1\132\145\0"+
+    "\1\133\7\0\1\134\145\0\1\135\2\0\25\136\1\137"+
+    "\31\136\1\140\7\136\1\0\2\43\4\0\3\43\1\126"+
+    "\6\0\4\43\1\0\2\43\1\0\22\43\1\141\3\43"+
+    "\11\0\2\43\4\0\3\43\1\126\6\0\4\43\1\0"+
+    "\2\43\1\0\15\43\1\142\10\43\10\0\57\143\1\57"+
+    "\7\143\60\144\1\57\6\144\25\0\1\145\42\0\3\100"+
+    "\4\0\1\100\3\0\3\100\2\0\4\100\1\0\2\100"+
+    "\1\0\26\100\21\0\1\127\70\0\1\146\53\0\17\106"+
+    "\1\0\42\106\1\147\4\106\1\0\2\107\4\0\3\107"+
+    "\1\150\6\0\4\107\1\0\2\107\1\151\26\107\12\0"+
+    "\1\152\40\0\1\153\24\0\2\107\4\0\3\107\1\150"+
+    "\6\0\4\107\1\0\1\107\1\154\1\151\26\107\11\0"+
+    "\2\107\4\0\3\107\1\150\6\0\4\107\1\0\2\107"+
+    "\1\151\2\107\1\155\6\107\1\156\14\107\11\0\2\107"+
+    "\4\0\3\107\1\150\6\0\4\107\1\0\2\107\1\151"+
+    "\6\107\1\157\17\107\11\0\2\107\4\0\3\107\1\150"+
+    "\6\0\4\107\1\0\2\107\1\151\10\107\1\160\15\107"+
+    "\21\0\1\161\6\0\1\162\1\0\1\163\45\0\2\120"+
+    "\4\0\3\120\7\0\4\120\1\0\2\120\1\0\26\120"+
+    "\21\0\1\161\6\0\1\162\47\0\2\123\4\0\3\123"+
+    "\7\0\4\123\1\0\2\123\1\0\26\123\11\0\2\34"+
+    "\4\0\3\34\1\123\6\0\4\34\1\0\1\164\1\34"+
+    "\1\0\26\34\11\0\2\126\4\0\3\126\7\0\4\126"+
+    "\1\0\2\126\1\0\26\126\23\0\1\165\73\0\1\166"+
+    "\47\0\2\131\4\0\3\131\7\0\4\131\1\0\2\131"+
+    "\1\0\26\131\10\0\57\132\1\0\2\132\1\167\4\132"+
+    "\57\133\1\0\5\133\1\170\1\133\60\134\1\0\1\134"+
+    "\1\167\4\134\60\135\1\0\4\135\1\170\1\135\57\140"+
+    "\1\136\7\140\1\0\2\43\4\0\3\43\1\126\6\0"+
+    "\4\43\1\0\2\43\1\0\23\43\1\171\2\43\11\0"+
+    "\2\43\4\0\3\43\1\126\6\0\4\43\1\0\2\43"+
+    "\1\0\20\43\1\172\5\43\23\0\1\173\54\0\2\150"+
+    "\4\0\3\150\7\0\4\150\1\0\2\150\1\151\26\150"+
+    "\12\0\1\152\25\0\1\174\40\0\1\175\16\0\3\175"+
+    "\6\0\1\175\6\0\1\175\2\0\1\175\3\0\1\175"+
+    "\3\0\1\175\13\0\2\107\4\0\3\107\1\150\6\0"+
+    "\4\107\1\0\2\107\1\174\26\107\11\0\2\107\4\0"+
+    "\3\107\1\150\6\0\4\107\1\0\2\107\1\151\3\107"+
+    "\1\176\22\107\11\0\2\107\4\0\3\107\1\150\6\0"+
+    "\4\107\1\0\2\107\1\151\2\107\1\154\23\107\11\0"+
+    "\2\107\4\0\3\107\1\150\6\0\4\107\1\0\2\107"+
+    "\1\151\3\107\1\111\22\107\11\0\2\107\4\0\3\107"+
+    "\1\150\6\0\4\107\1\0\2\107\1\151\4\107\1\156"+
+    "\21\107\21\0\1\177\76\0\1\200\112\0\1\201\22\0"+
+    "\2\43\4\0\3\43\1\126\6\0\4\43\1\0\2\43"+
+    "\1\0\24\43\1\202\1\43\11\0\2\43\4\0\3\43"+
+    "\1\126\6\0\3\43\1\203\1\0\2\43\1\0\26\43"+
+    "\12\0\1\175\16\0\3\175\4\0\1\174\1\0\1\175"+
+    "\6\0\1\175\2\0\1\175\3\0\1\175\3\0\1\175"+
+    "\13\0\2\107\4\0\3\107\1\150\6\0\4\107\1\0"+
+    "\2\107\1\151\4\107\1\154\21\107\32\0\1\204\65\0"+
+    "\1\205\46\0\2\43\4\0\3\43\1\126\6\0\4\43"+
+    "\1\0\2\43\1\0\25\43\1\206\11\0\2\43\4\0"+
+    "\3\43\1\126\6\0\4\43\1\0\2\43\1\0\17\43"+
+    "\1\207\6\43\33\0\1\210\67\0\1\211\43\0\2\43"+
+    "\4\0\3\43\1\126\6\0\1\212\3\43\1\0\2\43"+
+    "\1\0\26\43\11\0\2\43\4\0\3\43\1\126\6\0"+
+    "\4\43\1\0\2\43\1\0\21\43\1\213\4\43\34\0"+
+    "\1\214\110\0\1\215\43\0\1\216\112\0\1\217\37\0"+
+    "\1\220\116\0\1\221\16\0";
+
+  private static int [] zzUnpackTrans() {
+    int [] result = new int[5445];
+    int offset = 0;
+    offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackTrans(String packed, int offset, int [] result) {
+    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 result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /* error codes */
+  private static final int ZZ_UNKNOWN_ERROR = 0;
+  private static final int ZZ_NO_MATCH = 1;
+  private static final int ZZ_PUSHBACK_2BIG = 2;
+  private static final char[] EMPTY_BUFFER = new char[0];
+  private static final int YYEOF = -1;
+  private static java.io.Reader zzReader = null; // Fake
+
+  /* error messages for the codes above */
+  private static final String ZZ_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /**
+   * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+  private static final String ZZ_ATTRIBUTE_PACKED_0 =
+    "\1\1\16\0\6\1\1\11\2\1\1\11\5\1\1\11"+
+    "\4\1\1\11\2\1\1\11\1\1\1\11\2\1\4\11"+
+    "\3\1\1\11\3\1\1\11\5\1\1\11\1\1\1\11"+
+    "\5\1\1\11\10\0\2\11\1\1\1\0\1\11\2\1"+
+    "\1\11\1\1\2\0\1\1\5\0\1\11\1\0\2\1"+
+    "\3\0\2\11\1\0\1\11\12\0\1\1\4\11\2\1"+
+    "\2\11\2\0\1\11\2\0\2\1\2\0\2\1\2\0"+
+    "\2\1\4\0\2\11";
+
+  private static int [] zzUnpackAttribute() {
+    int [] result = new int[145];
+    int offset = 0;
+    offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAttribute(String packed, int offset, int [] result) {
+    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++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+  /** the current state of the DFA */
+  private int zzState;
+
+  /** the current lexical state */
+  private int zzLexicalState = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private CharSequence zzBuffer = "";
+
+  /** this buffer may contains the current text array to be matched when it is cheap to acquire it */
+  private char[] zzBufferArray;
+
+  /** the textposition at the last accepting state */
+  private int zzMarkedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int zzPushbackPos;
+
+  /** the current text position in the buffer */
+  private int zzCurrentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int zzStartRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int zzEndRead;
+
+  /**
+   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean zzAtBOL = true;
+
+  /** zzAtEOF == true <=> the scanner is at the EOF */
+  private boolean zzAtEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean zzEOFDone;
+
+  /* user code: */
+  private IElementType elTokenType = XmlTokenType.XML_DATA_CHARACTERS;
+  private IElementType elTokenType2 = XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+  private IElementType javaEmbeddedTokenType = XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+  private boolean myConditionalCommentsSupport;
+
+  public void setConditionalCommentsSupport(final boolean b) {
+    myConditionalCommentsSupport = b;
+  }
+
+  public void setElTypes(IElementType _elTokenType,IElementType _elTokenType2) {
+    elTokenType = _elTokenType;
+    elTokenType2 = _elTokenType2;
+  }
+
+  public void setJavaEmbeddedType(IElementType _tokenType) {
+    javaEmbeddedTokenType = _tokenType;
+  }
+
+  private int myPrevState = YYINITIAL;
+
+  public int yyprevstate() {
+    return myPrevState;
+  }
+
+  private int popState(){
+    final int prev = myPrevState;
+    myPrevState = YYINITIAL;
+    return prev;
+  }
+
+  protected void pushState(int state){
+    myPrevState = state;
+  }
+
+
+  public __XmlLexer(java.io.Reader in) {
+    this.zzReader = 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 __XmlLexer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] zzUnpackCMap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1248) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+  public final int getTokenStart(){
+    return zzStartRead;
+  }
+
+  public final int getTokenEnd(){
+    return getTokenStart() + yylength();
+  }
+
+  public void reset(CharSequence buffer, int start, int end,int initialState){
+    zzBuffer = buffer;
+    zzBufferArray = com.intellij.util.text.CharArrayUtil.fromSequenceWithoutCopying(buffer);
+    zzCurrentPos = zzMarkedPos = zzStartRead = start;
+    zzPushbackPos = 0;
+    zzAtEOF  = false;
+    zzAtBOL = true;
+    zzEndRead = end;
+    yybegin(initialState);
+  }
+
+  /**
+   * Refills the input buffer.
+   *
+   * @return      <code>false</code>, iff there was new input.
+   *
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean zzRefill() throws java.io.IOException {
+    return true;
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  public final int yystate() {
+    return zzLexicalState;
+  }
+
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  public final void yybegin(int newState) {
+    zzLexicalState = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  public final CharSequence yytext() {
+    return zzBuffer.subSequence(zzStartRead, zzMarkedPos);
+  }
+
+
+  /**
+   * 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
+   */
+  public final char yycharat(int pos) {
+    return zzBufferArray != null ? zzBufferArray[zzStartRead+pos]:zzBuffer.charAt(zzStartRead+pos);
+  }
+
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  public final int yylength() {
+    return zzMarkedPos-zzStartRead;
+  }
+
+
+  /**
+   * 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 zzScanError(int errorCode) {
+    String message;
+    try {
+      message = ZZ_ERROR_MSG[errorCode];
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      message = ZZ_ERROR_MSG[ZZ_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()!
+   */
+  public void yypushback(int number)  {
+    if ( number > yylength() )
+      zzScanError(ZZ_PUSHBACK_2BIG);
+
+    zzMarkedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void zzDoEOF() {
+    if (!zzEOFDone) {
+      zzEOFDone = true;
+    
+    }
+  }
+
+
+  /**
+   * 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   java.io.IOException  if any I/O-Error occurs
+   */
+  public IElementType advance() throws java.io.IOException {
+    int zzInput;
+    int zzAction;
+
+    // cached fields:
+    int zzCurrentPosL;
+    int zzMarkedPosL;
+    int zzEndReadL = zzEndRead;
+    CharSequence zzBufferL = zzBuffer;
+    char[] zzBufferArrayL = zzBufferArray;
+    char [] zzCMapL = ZZ_CMAP;
+
+    int [] zzTransL = ZZ_TRANS;
+    int [] zzRowMapL = ZZ_ROWMAP;
+    int [] zzAttrL = ZZ_ATTRIBUTE;
+
+    while (true) {
+      zzMarkedPosL = zzMarkedPos;
+
+      zzAction = -1;
+
+      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+
+      zzState = zzLexicalState;
+
+
+      zzForAction: {
+        while (true) {
+
+          if (zzCurrentPosL < zzEndReadL)
+            zzInput = zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++]:zzBufferL.charAt(zzCurrentPosL++);
+          else if (zzAtEOF) {
+            zzInput = YYEOF;
+            break zzForAction;
+          }
+          else {
+            // store back cached positions
+            zzCurrentPos  = zzCurrentPosL;
+            zzMarkedPos   = zzMarkedPosL;
+            boolean eof = zzRefill();
+            // get translated positions and possibly new buffer
+            zzCurrentPosL  = zzCurrentPos;
+            zzMarkedPosL   = zzMarkedPos;
+            zzBufferL      = zzBuffer;
+            zzEndReadL     = zzEndRead;
+            if (eof) {
+              zzInput = YYEOF;
+              break zzForAction;
+            }
+            else {
+              zzInput = zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++]:zzBufferL.charAt(zzCurrentPosL++);
+            }
+          }
+          int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
+          if (zzNext == -1) break zzForAction;
+          zzState = zzNext;
+
+          int zzAttributes = zzAttrL[zzState];
+          if ( (zzAttributes & 1) == 1 ) {
+            zzAction = zzState;
+            zzMarkedPosL = zzCurrentPosL;
+            if ( (zzAttributes & 8) == 8 ) break zzForAction;
+          }
+
+        }
+      }
+
+      // store back cached position
+      zzMarkedPos = zzMarkedPosL;
+
+      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 20: 
+          { yybegin(ATTR_LIST); return XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER;
+          }
+        case 44: break;
+        case 19: 
+          { return XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
+          }
+        case 45: break;
+        case 41: 
+          { return XmlTokenType.XML_DOCTYPE_SYSTEM;
+          }
+        case 46: break;
+        case 18: 
+          { return XmlTokenType.XML_EQ;
+          }
+        case 47: break;
+        case 9: 
+          { return XmlTokenType.XML_TAG_CHARACTERS;
+          }
+        case 48: break;
+        case 42: 
+          { yybegin(CDATA); return XmlTokenType.XML_CDATA_START;
+          }
+        case 49: break;
+        case 5: 
+          { yybegin(ATTR_LIST); pushState(TAG); return XmlTokenType.XML_NAME;
+          }
+        case 50: break;
+        case 25: 
+          { yybegin(END_TAG); return XmlTokenType.XML_END_TAG_START;
+          }
+        case 51: break;
+        case 30: 
+          { return elTokenType;
+          }
+        case 52: break;
+        case 10: 
+          { return XmlTokenType.XML_NAME;
+          }
+        case 53: break;
+        case 40: 
+          { return XmlTokenType.XML_DOCTYPE_PUBLIC;
+          }
+        case 54: break;
+        case 39: 
+          { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_START;
+          }
+        case 55: break;
+        case 13: 
+          { if (myConditionalCommentsSupport) {
+    yybegin(C_COMMENT_START);
+    return XmlTokenType.XML_CONDITIONAL_COMMENT_START;
+  } else return XmlTokenType.XML_COMMENT_CHARACTERS;
+          }
+        case 56: break;
+        case 36: 
+          { return javaEmbeddedTokenType;
+          }
+        case 57: break;
+        case 28: 
+          { return XmlElementType.XML_MARKUP_DECL;
+          }
+        case 58: break;
+        case 32: 
+          { yybegin(ATTR_LIST); pushState(PROCESSING_INSTRUCTION); return XmlTokenType.XML_NAME;
+          }
+        case 59: break;
+        case 2: 
+          { return XmlTokenType.XML_REAL_WHITE_SPACE;
+          }
+        case 60: break;
+        case 1: 
+          { return XmlTokenType.XML_DATA_CHARACTERS;
+          }
+        case 61: break;
+        case 23: 
+          { yybegin(COMMENT); return XmlTokenType.XML_CONDITIONAL_COMMENT_END;
+          }
+        case 62: break;
+        case 12: 
+          { return XmlTokenType.XML_BAD_CHARACTER;
+          }
+        case 63: break;
+        case 7: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_TAG_END;
+          }
+        case 64: break;
+        case 29: 
+          { yybegin(COMMENT); return XmlTokenType.XML_CONDITIONAL_COMMENT_START_END;
+          }
+        case 65: break;
+        case 3: 
+          { if(yystate() == YYINITIAL){
+        return XmlTokenType.XML_BAD_CHARACTER;
+      }
+      else yybegin(popState()); yypushback(yylength());
+          }
+        case 66: break;
+        case 33: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_COMMENT_END;
+          }
+        case 67: break;
+        case 4: 
+          { yybegin(TAG); return XmlTokenType.XML_START_TAG_START;
+          }
+        case 68: break;
+        case 34: 
+          { if (myConditionalCommentsSupport) {
+    yybegin(C_COMMENT_END);
+    return XmlTokenType.XML_CONDITIONAL_COMMENT_END_START;
+  } else return XmlTokenType.XML_COMMENT_CHARACTERS;
+          }
+        case 69: break;
+        case 26: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_EMPTY_ELEMENT_END;
+          }
+        case 70: break;
+        case 24: 
+          { yybegin(PROCESSING_INSTRUCTION); return XmlTokenType.XML_PI_START;
+          }
+        case 71: break;
+        case 8: 
+          { yybegin(PI_ANY); return XmlTokenType.XML_NAME;
+          }
+        case 72: break;
+        case 14: 
+          { yybegin(ATTR); return XmlTokenType.XML_NAME;
+          }
+        case 73: break;
+        case 15: 
+          { yybegin(ATTR_LIST); yypushback(yylength());
+          }
+        case 74: break;
+        case 21: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_DOCTYPE_END;
+          }
+        case 75: break;
+        case 38: 
+          { return XmlTokenType.XML_CHAR_ENTITY_REF;
+          }
+        case 76: break;
+        case 6: 
+          { return XmlTokenType.XML_WHITE_SPACE;
+          }
+        case 77: break;
+        case 31: 
+          { return XmlTokenType.XML_ENTITY_REF_TOKEN;
+          }
+        case 78: break;
+        case 16: 
+          { yybegin(ATTR_VALUE_DQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 79: break;
+        case 17: 
+          { yybegin(ATTR_VALUE_SQ); return XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER;
+          }
+        case 80: break;
+        case 22: 
+          { yybegin(COMMENT); return XmlTokenType.XML_COMMENT_CHARACTERS;
+          }
+        case 81: break;
+        case 37: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_CDATA_END;
+          }
+        case 82: break;
+        case 35: 
+          { return elTokenType2;
+          }
+        case 83: break;
+        case 27: 
+          { yybegin(YYINITIAL); return XmlTokenType.XML_PI_END;
+          }
+        case 84: break;
+        case 43: 
+          { yybegin(DOCTYPE); return XmlTokenType.XML_DOCTYPE_START;
+          }
+        case 85: break;
+        case 11: 
+          { return XmlTokenType.XML_COMMENT_CHARACTERS;
+          }
+        case 86: break;
+        default:
+          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+            zzAtEOF = true;
+            zzDoEOF();
+            return null;
+          }
+          else {
+            zzScanError(ZZ_NO_MATCH);
+          }
+      }
+    }
+  }
+
+
+}
diff --git a/xml/impl/src/com/intellij/navigation/HtmlGotoRelatedProvider.java b/xml/impl/src/com/intellij/navigation/HtmlGotoRelatedProvider.java
new file mode 100644
index 0000000..7cb7521
--- /dev/null
+++ b/xml/impl/src/com/intellij/navigation/HtmlGotoRelatedProvider.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.navigation;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: Eugene.Kudelevsky
+ * Date: 3/29/11
+ * Time: 4:21 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class HtmlGotoRelatedProvider extends GotoRelatedProvider {
+  @NotNull
+  @Override
+  public List<? extends GotoRelatedItem> getItems(@NotNull PsiElement context) {
+    final PsiFile file = context.getContainingFile();
+    if (file == null || !isAvailable(file)) {
+      return Collections.emptyList();
+    }
+
+    return getRelatedFiles(file);
+  }
+
+  private static boolean isAvailable(@NotNull PsiFile psiFile) {
+    for (PsiFile file : psiFile.getViewProvider().getAllFiles()) {
+      Language language = file.getLanguage();
+      if (language.isKindOf(HTMLLanguage.INSTANCE) || language.isKindOf(XHTMLLanguage.INSTANCE)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private static List<? extends GotoRelatedItem> getRelatedFiles(@NotNull PsiFile file) {
+    List<GotoRelatedItem> items = new ArrayList<GotoRelatedItem>();
+
+    for (PsiFile psiFile : file.getViewProvider().getAllFiles()) {
+      if (psiFile instanceof XmlFile) {
+        final XmlFile xmlFile = (XmlFile)psiFile;
+
+        for (RelatedToHtmlFilesContributor contributor : RelatedToHtmlFilesContributor.EP_NAME.getExtensions()) {
+          HashSet<PsiFile> resultSet = new HashSet<PsiFile>();
+          contributor.fillRelatedFiles(xmlFile, resultSet);
+          for (PsiFile f: resultSet) {
+            items.add(new GotoRelatedItem(f, contributor.getGroupName()));
+          }
+        }
+      }
+    }
+    return items;
+  }
+}
diff --git a/xml/impl/src/com/intellij/navigation/LinkedToHtmlFilesContributor.java b/xml/impl/src/com/intellij/navigation/LinkedToHtmlFilesContributor.java
new file mode 100644
index 0000000..86f83e9
--- /dev/null
+++ b/xml/impl/src/com/intellij/navigation/LinkedToHtmlFilesContributor.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.navigation;
+
+import com.intellij.psi.*;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.Processor;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class LinkedToHtmlFilesContributor extends RelatedToHtmlFilesContributor {
+  @Override
+  public void fillRelatedFiles(@NotNull final XmlFile xmlFile, @NotNull final Set<PsiFile> resultSet) {
+    HtmlUtil.processLinks(xmlFile, new Processor<XmlTag>() {
+      @Override
+      public boolean process(XmlTag tag) {
+        final XmlAttribute attribute = tag.getAttribute("href");
+        if (attribute == null) {
+          return true;
+        }
+
+        final XmlAttributeValue link = attribute.getValueElement();
+        if (link == null) {
+          return true;
+        }
+
+        for (PsiReference reference : link.getReferences()) {
+          if (reference instanceof PsiPolyVariantReference) {
+            final ResolveResult[] results = ((PsiPolyVariantReference)reference).multiResolve(false);
+
+            for (ResolveResult result : results) {
+              final PsiElement resolvedElement = result.getElement();
+              if (resolvedElement instanceof PsiFile) {
+                resultSet.add((PsiFile)resolvedElement);
+              }
+            }
+          }
+          else {
+            final PsiElement resolvedElement = reference.resolve();
+            if (resolvedElement instanceof PsiFile) {
+              resultSet.add((PsiFile)resolvedElement);
+            }
+          }
+        }
+        return true;
+      }
+    });
+  }
+
+  @Override
+  public String getGroupName() {
+    return "Linked files";
+  }
+}
diff --git a/xml/impl/src/com/intellij/navigation/RelatedToHtmlFilesContributor.java b/xml/impl/src/com/intellij/navigation/RelatedToHtmlFilesContributor.java
new file mode 100644
index 0000000..5aef333
--- /dev/null
+++ b/xml/impl/src/com/intellij/navigation/RelatedToHtmlFilesContributor.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.navigation;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class RelatedToHtmlFilesContributor {
+  public static final ExtensionPointName<RelatedToHtmlFilesContributor> EP_NAME =
+    ExtensionPointName.create("com.intellij.xml.relatedToHtmlFilesContributor");
+
+  public abstract void fillRelatedFiles(@NotNull XmlFile xmlFile, @NotNull Set<PsiFile> resultSet);
+  public abstract String getGroupName();
+}
diff --git a/xml/impl/src/com/intellij/openapi/options/colors/pages/HTMLColorsPage.java b/xml/impl/src/com/intellij/openapi/options/colors/pages/HTMLColorsPage.java
new file mode 100644
index 0000000..417fcf3
--- /dev/null
+++ b/xml/impl/src/com/intellij/openapi/options/colors/pages/HTMLColorsPage.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.options.colors.pages;
+
+import com.intellij.codeInsight.daemon.impl.tagTreeHighlighting.XmlTagTreeHighlightingColors;
+import com.intellij.ide.highlighter.HtmlFileHighlighter;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.editor.XmlHighlighterColors;
+import com.intellij.openapi.editor.colors.ColorKey;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.options.colors.AttributesDescriptor;
+import com.intellij.openapi.options.colors.ColorDescriptor;
+import com.intellij.openapi.options.colors.ColorSettingsPage;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.Map;
+
+public class HTMLColorsPage implements ColorSettingsPage {
+  private static final AttributesDescriptor[] ATTRS = new AttributesDescriptor[] {
+    new AttributesDescriptor(OptionsBundle.message("options.html.attribute.descriptor.code"), XmlHighlighterColors.HTML_CODE),
+    new AttributesDescriptor(OptionsBundle.message("options.html.attribute.descriptor.comment"), XmlHighlighterColors.HTML_COMMENT),
+    new AttributesDescriptor(OptionsBundle.message("options.html.attribute.descriptor.tag"), XmlHighlighterColors.HTML_TAG),
+    new AttributesDescriptor(OptionsBundle.message("options.html.attribute.descriptor.tag.name"), XmlHighlighterColors.HTML_TAG_NAME),
+    new AttributesDescriptor(OptionsBundle.message("options.html.attribute.descriptor.attribute.name"), XmlHighlighterColors.HTML_ATTRIBUTE_NAME),
+    new AttributesDescriptor(OptionsBundle.message("options.html.attribute.descriptor.attribute.value"), XmlHighlighterColors.HTML_ATTRIBUTE_VALUE),
+    new AttributesDescriptor(OptionsBundle.message("options.html.attribute.descriptor.entity.reference"), XmlHighlighterColors.HTML_ENTITY_REFERENCE),
+  };
+  private static final String FULL_PRODUCT_NAME = ApplicationNamesInfo.getInstance().getFullProductName();
+
+  @NotNull
+  public String getDisplayName() {
+    return OptionsBundle.message("options.html.display.name");
+  }
+
+  public Icon getIcon() {
+    return StdFileTypes.HTML.getIcon();
+  }
+
+  @NotNull
+  public AttributesDescriptor[] getAttributeDescriptors() {
+    return ATTRS;
+  }
+
+  @NotNull
+  public ColorDescriptor[] getColorDescriptors() {
+    // todo: make preview for it
+
+    final ColorKey[] colorKeys = XmlTagTreeHighlightingColors.getColorKeys();
+    final ColorDescriptor[] colorDescriptors = new ColorDescriptor[colorKeys.length];
+
+    for (int i = 0; i < colorDescriptors.length; i++) {
+      colorDescriptors[i] = new ColorDescriptor(OptionsBundle.message("options.html.attribute.descriptor.tag.tree", i + 1),
+                                                colorKeys[i], ColorDescriptor.Kind.BACKGROUND);
+    }
+
+    return colorDescriptors;
+  }
+
+  @NotNull
+  public SyntaxHighlighter getHighlighter() {
+    return new HtmlFileHighlighter();
+  }
+
+  @NotNull
+  public String getDemoText() {
+    return "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n" +
+           "<!--\n" +
+           "*        Sample comment\n" +
+           "-->\n" +
+           "<HTML>\n" +
+           "<head>\n" +
+           "<title>" + FULL_PRODUCT_NAME + "</title>\n" +
+           "</head>\n" +
+           "<body>\n" +
+           "<h1>" + FULL_PRODUCT_NAME + "</h1>\n" +
+           "<p><br><b><IMG border=0 height=12 src=\"images/hg.gif\" width=18 >\n" +
+           "What is " + FULL_PRODUCT_NAME.replaceAll(" ", "&nbsp;") + "? &#x00B7; &Alpha; </b><br><br>\n" +
+           "</body>\n" +
+           "</html>";
+  }
+
+  public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMap() {
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/openapi/options/colors/pages/XMLColorsPage.java b/xml/impl/src/com/intellij/openapi/options/colors/pages/XMLColorsPage.java
new file mode 100644
index 0000000..e968f73
--- /dev/null
+++ b/xml/impl/src/com/intellij/openapi/options/colors/pages/XMLColorsPage.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.options.colors.pages;
+
+import com.intellij.ide.highlighter.XmlFileHighlighter;
+import com.intellij.openapi.editor.XmlHighlighterColors;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.options.colors.AttributesDescriptor;
+import com.intellij.openapi.options.colors.ColorDescriptor;
+import com.intellij.openapi.options.colors.ColorSettingsPage;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.Map;
+
+public class XMLColorsPage implements ColorSettingsPage {
+  private static final AttributesDescriptor[] ATTRS = new AttributesDescriptor[] {
+    new AttributesDescriptor(OptionsBundle.message("options.xml.attribute.descriptor.prologue"), XmlHighlighterColors.XML_PROLOGUE),
+    new AttributesDescriptor(OptionsBundle.message("options.xml.attribute.descriptor.comment"), XmlHighlighterColors.XML_COMMENT),
+    new AttributesDescriptor(OptionsBundle.message("options.xml.attribute.descriptor.tag"), XmlHighlighterColors.XML_TAG),
+    new AttributesDescriptor(OptionsBundle.message("options.xml.attribute.descriptor.tag.name"), XmlHighlighterColors.XML_TAG_NAME),
+    new AttributesDescriptor(OptionsBundle.message("options.xml.attribute.descriptor.attribute.name"), XmlHighlighterColors.XML_ATTRIBUTE_NAME),
+    new AttributesDescriptor(OptionsBundle.message("options.xml.attribute.descriptor.attribute.value"), XmlHighlighterColors.XML_ATTRIBUTE_VALUE),
+    new AttributesDescriptor(OptionsBundle.message("options.xml.attribute.descriptor.tag.data"), XmlHighlighterColors.XML_TAG_DATA),
+    new AttributesDescriptor(OptionsBundle.message("options.xml.attribute.descriptor.descriptor.entity,reference"), XmlHighlighterColors.XML_ENTITY_REFERENCE),
+  };
+
+  @NotNull
+  public String getDisplayName() {
+    return OptionsBundle.message("options.xml.display.name");
+  }
+
+  public Icon getIcon() {
+    return StdFileTypes.XML.getIcon();
+  }
+
+  @NotNull
+  public AttributesDescriptor[] getAttributeDescriptors() {
+    return ATTRS;
+  }
+
+  @NotNull
+  public ColorDescriptor[] getColorDescriptors() {
+    return ColorDescriptor.EMPTY_ARRAY;                       
+  }
+
+  @NotNull
+  public SyntaxHighlighter getHighlighter() {
+    return new XmlFileHighlighter();
+  }
+
+  @NotNull
+  public String getDemoText() {
+    return "<?xml version='1.0' encoding='ISO-8859-1'  ?>\n" +
+           "<!DOCTYPE index>\n" +
+           "<!-- Some xml example -->\n" +
+           "<index version=\"1.0\">\n" +
+           "   <name>Main Index</name>\n" +
+           "   <indexitem text=\"rename\" target=\"refactoring.rename\"/>\n" +
+           "   <indexitem text=\"move\" target=\"refactoring.move\"/>\n" +
+           "   <indexitem text=\"migrate\" target=\"refactoring.migrate\"/>\n" +
+           "   <indexitem text=\"usage search\" target=\"find.findUsages\"/>\n&amp; &#x00B7;" +
+           "   <indexitem text=\"project\" target=\"project.management\"/>\n" +
+           "</index>";
+  }
+
+  public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMap() {
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java
new file mode 100644
index 0000000..eb9da7b
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl;
+
+import com.intellij.pom.PomModel;
+import com.intellij.pom.PomModelAspect;
+import com.intellij.pom.event.PomChangeSet;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.XmlChangeSet;
+import com.intellij.pom.xml.events.XmlChange;
+import com.intellij.psi.xml.XmlFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+public class XmlAspectChangeSetImpl implements XmlChangeSet {
+  private final PomModel myModel;
+  private final List<XmlChange> myChanges = new ArrayList<XmlChange>();
+  private final List<XmlFile> myChangedFiles = new ArrayList<XmlFile>();
+
+  public XmlAspectChangeSetImpl(PomModel model) {
+    myModel = model;
+  }
+
+  public XmlAspectChangeSetImpl(final PomModel model, @Nullable final XmlFile xmlFile) {
+    this(model);
+    if (xmlFile != null) {
+      addChangedFile(xmlFile);
+    }
+  }
+
+  public List<XmlChange> getChanges(){
+    return Collections.unmodifiableList(myChanges);
+  }
+
+  @NotNull
+  public PomModelAspect getAspect() {
+    return myModel.getModelAspect(XmlAspect.class);
+  }
+
+  public void merge(@NotNull PomChangeSet blocked) {
+    final List<XmlChange> changes = ((XmlAspectChangeSetImpl)blocked).myChanges;
+    for (XmlChange xmlChange : changes) {
+      add(xmlChange);
+    }
+  }
+
+  public void add(XmlChange xmlChange) {
+    myChanges.add(xmlChange);
+  }
+
+  public void clear() {
+    myChanges.clear();
+  }
+
+  @NotNull
+  public Iterable<XmlFile> getChangedFiles() {
+    return myChangedFiles;
+  }
+
+  public String toString(){
+    final StringBuffer buffer = new StringBuffer();
+    final Iterator<XmlChange> iterator = myChanges.iterator();
+    while (iterator.hasNext()) {
+      XmlChange xmlChange = iterator.next();
+      buffer.append("(");
+      buffer.append(xmlChange.toString());
+      buffer.append(")");
+      if(iterator.hasNext()) buffer.append(", ");
+    }
+    return buffer.toString();
+  }
+
+  public void addChangedFile(@NotNull final XmlFile xmlFile) {
+    myChangedFiles.add(xmlFile);
+  }
+}
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectImpl.java
new file mode 100644
index 0000000..db75802
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/XmlAspectImpl.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.pom.PomModel;
+import com.intellij.pom.PomModelAspect;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.tree.TreeAspect;
+import com.intellij.pom.tree.events.ChangeInfo;
+import com.intellij.pom.tree.events.ReplaceChangeInfo;
+import com.intellij.pom.tree.events.TreeChange;
+import com.intellij.pom.tree.events.TreeChangeEvent;
+import com.intellij.pom.tree.events.impl.ChangeInfoImpl;
+import com.intellij.pom.tree.events.impl.TreeChangeImpl;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.impl.events.*;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.impl.source.tree.FileElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.*;
+import com.intellij.util.CharTable;
+
+import java.util.Collections;
+
+public class XmlAspectImpl implements XmlAspect {
+  private final PomModel myModel;
+  private final TreeAspect myTreeAspect;
+
+  public XmlAspectImpl(PomModel model, TreeAspect aspect) {
+    myModel = model;
+    myTreeAspect = aspect;
+    myModel.registerAspect(XmlAspect.class, this, Collections.singleton((PomModelAspect)myTreeAspect));
+  }
+
+  public void update(PomModelEvent event) {
+    if (!event.getChangedAspects().contains(myTreeAspect)) return;
+    final TreeChangeEvent changeSet = (TreeChangeEvent)event.getChangeSet(myTreeAspect);
+    if (changeSet == null) return;
+    final ASTNode rootElement = changeSet.getRootElement();
+    final PsiFile file = (PsiFile)rootElement.getPsi();
+    if (!(file instanceof XmlFile)) return;
+    final XmlAspectChangeSetImpl xmlChangeSet = event.registerChangeSetIfAbsent(this, new XmlAspectChangeSetImpl(myModel));
+    xmlChangeSet.addChangedFile((XmlFile)file);
+
+    final ASTNode[] changedElements = changeSet.getChangedElements();
+    final CharTable table = ((FileElement)changeSet.getRootElement()).getCharTable();
+    for (ASTNode changedElement : changedElements) {
+      TreeChange changesByElement = changeSet.getChangesByElement(changedElement);
+      PsiElement psiElement = null;
+      while (changedElement != null && (psiElement = changedElement.getPsi()) == null) {
+        final ASTNode parent = changedElement.getTreeParent();
+        final ChangeInfoImpl changeInfo = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, changedElement);
+        changeInfo.compactChange(changesByElement);
+        changesByElement = new TreeChangeImpl(parent);
+        changesByElement.addChange(changedElement, changeInfo);
+        changedElement = parent;
+      }
+      if (changedElement == null) continue;
+      final TreeChange finalChangedElement = changesByElement;
+      psiElement.accept(new XmlElementVisitor() {
+        TreeChange myChange = finalChangedElement;
+
+        @Override
+        public void visitElement(PsiElement element) {
+          final ASTNode child = element.getNode();
+          final ASTNode treeParent = child.getTreeParent();
+          if (treeParent == null) return;
+          final PsiElement parent = treeParent.getPsi();
+          final ChangeInfoImpl changeInfo = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, child);
+
+          changeInfo.compactChange(myChange);
+          myChange = new TreeChangeImpl(treeParent);
+
+          myChange.addChange(child, changeInfo);
+          parent.accept(this);
+        }
+
+        @Override
+        public void visitXmlAttribute(XmlAttribute attribute) {
+          final ASTNode[] affectedChildren = myChange.getAffectedChildren();
+          String oldName = null;
+          String oldValue = null;
+          for (final ASTNode treeElement : affectedChildren) {
+            final ChangeInfo changeByChild = myChange.getChangeByChild(treeElement);
+            final int changeType = changeByChild.getChangeType();
+            if (treeElement.getElementType() == XmlTokenType.XML_NAME) {
+              if (changeType == ChangeInfo.REMOVED) {
+                oldName = treeElement.getText();
+              }
+              else if (changeType == ChangeInfo.REPLACE) {
+                oldName = ((ReplaceChangeInfo)changeByChild).getReplaced().getText();
+              }
+            }
+            if (treeElement.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE) {
+              if (changeType == ChangeInfo.REMOVED) {
+                oldValue = treeElement.getText();
+              }
+              else if (changeType == ChangeInfo.REPLACE) {
+                oldValue = ((ReplaceChangeInfo)changeByChild).getReplaced().getText();
+              }
+            }
+          }
+          if (oldName != null && !oldName.equals(attribute.getName())) {
+            xmlChangeSet.add(new XmlAttributeSetImpl(attribute.getParent(), oldName, null));
+            xmlChangeSet.add(new XmlAttributeSetImpl(attribute.getParent(), attribute.getName(), attribute.getValue()));
+          }
+          else if (oldValue != null) {
+            xmlChangeSet.add(new XmlAttributeSetImpl(attribute.getParent(), attribute.getName(), attribute.getValue()));
+          }
+          else {
+            xmlChangeSet.add(new XmlElementChangedImpl(attribute));
+          }
+        }
+
+        @Override
+        public void visitXmlTag(XmlTag tag) {
+          ASTNode[] affectedChildren = shortenChange(myChange.getAffectedChildren(), changeSet);
+
+          for (final ASTNode treeElement : affectedChildren) {
+            /*final IElementType type = treeElement.getElementType();
+            if (type == ElementType.WHITE_SPACE) continue;
+            if (type == ElementType.XML_NAME) {
+              if (myChange.getChangeByChild(treeElement).getChangeType() == ChangeInfo.REPLACE) {
+                continue;
+              }
+            }*/
+
+            if (!(treeElement.getPsi() instanceof XmlTagChild)) {
+              visitElement(tag);
+              return;
+            }
+          }
+
+          for (final ASTNode treeElement : affectedChildren) {
+            final ChangeInfo changeByChild = myChange.getChangeByChild(treeElement);
+            final int changeType = changeByChild.getChangeType();
+            final IElementType type = treeElement.getElementType();
+            if (type == TokenType.WHITE_SPACE) continue;
+            /*
+            if (type == ElementType.XML_NAME) {
+              final XmlToken xmlToken = (XmlToken)((ReplaceChangeInfo)changeByChild).getReplaced();
+              xmlChangeSet.add(new XmlTagNameChangedImpl(tag, xmlToken.getText()));
+              continue;
+            }
+            */
+
+            final PsiElement element = treeElement.getPsi();
+
+            switch (changeType) {
+              case ChangeInfo.ADD:
+                xmlChangeSet.add(new XmlTagChildAddImpl(tag, (XmlTagChild)element));
+                break;
+              case ChangeInfo.REMOVED:
+                treeElement.putUserData(CharTable.CHAR_TABLE_KEY, table);
+                xmlChangeSet.add(new XmlTagChildRemovedImpl(tag, (XmlTagChild)element));
+                break;
+              case ChangeInfo.CONTENTS_CHANGED:
+                xmlChangeSet.add(new XmlTagChildChangedImpl(tag, (XmlTagChild)element));
+                break;
+              case ChangeInfo.REPLACE:
+                final PsiElement psi = ((ReplaceChangeInfo)changeByChild).getReplaced().getPsi();
+                if (psi instanceof XmlTagChild) {
+                  final XmlTagChild replaced = (XmlTagChild)psi;
+                  replaced.putUserData(CharTable.CHAR_TABLE_KEY, table);
+                  xmlChangeSet.add(new XmlTagChildRemovedImpl(tag, replaced));
+                  xmlChangeSet.add(new XmlTagChildAddImpl(tag, (XmlTagChild)element));
+                }
+                break;
+            }
+          }
+        }
+
+        @Override
+        public void visitXmlDocument(XmlDocument document) {
+          xmlChangeSet.clear();
+          xmlChangeSet.add(new XmlDocumentChangedImpl(document));
+        }
+
+        @Override
+        public void visitFile(PsiFile file) {
+          final XmlDocument document = ((XmlFile)file).getDocument();
+
+          if (document != null) {
+            xmlChangeSet.clear();
+            xmlChangeSet.add(new XmlDocumentChangedImpl(document));
+          }
+        }
+      });
+    }
+  }
+
+  private ASTNode[] shortenChange(ASTNode[] affectedChildren, TreeChangeEvent event) {
+    // TODO
+    return affectedChildren;
+  }
+}
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/events/XmlAttributeSetImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlAttributeSetImpl.java
new file mode 100644
index 0000000..df7ac29
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlAttributeSetImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl.events;
+
+import com.intellij.pom.PomModel;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.XmlChangeVisitor;
+import com.intellij.pom.xml.events.XmlAttributeSet;
+import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+
+public class XmlAttributeSetImpl implements XmlAttributeSet {
+  private final String myName;
+  private final String myValue;
+  private final XmlTag myTag;
+
+  public XmlAttributeSetImpl(XmlTag xmlTag, String name, String value) {
+    myName = name;
+    myValue = value;
+    myTag = xmlTag;
+  }
+
+  public String getName() {
+    return myName;
+  }
+
+  public String getValue() {
+    return myValue;
+  }
+
+  public XmlTag getTag() {
+    return myTag;
+  }
+
+  public static PomModelEvent createXmlAttributeSet(PomModel model, XmlTag xmlTag, String name, String value) {
+    final PomModelEvent event = new PomModelEvent(model);
+    final XmlAspectChangeSetImpl xmlAspectChangeSet = new XmlAspectChangeSetImpl(model, PsiTreeUtil.getParentOfType(xmlTag, XmlFile.class));
+    xmlAspectChangeSet.add(new XmlAttributeSetImpl(xmlTag, name, value));
+    event.registerChangeSet(model.getModelAspect(XmlAspect.class), xmlAspectChangeSet);
+    return event;
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public String toString() {
+    return "Attribute \"" + getName() + "\" for tag \"" + getTag().getName() + "\" set to \"" + getValue() + "\"";
+  }
+
+  public void accept(XmlChangeVisitor visitor) {
+    visitor.visitXmlAttributeSet(this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/events/XmlDocumentChangedImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlDocumentChangedImpl.java
new file mode 100644
index 0000000..508831b
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlDocumentChangedImpl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl.events;
+
+import com.intellij.pom.PomModel;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.XmlChangeVisitor;
+import com.intellij.pom.xml.events.XmlDocumentChanged;
+import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import org.jetbrains.annotations.NotNull;
+
+public class XmlDocumentChangedImpl implements XmlDocumentChanged {
+  private final XmlDocument myDocument;
+
+  public XmlDocumentChangedImpl(@NotNull XmlDocument document) {
+    myDocument = document;
+  }
+
+  public XmlDocument getDocument() {
+    return myDocument;
+  }
+
+  public static PomModelEvent createXmlDocumentChanged(PomModel source, XmlDocument document) {
+    final PomModelEvent event = new PomModelEvent(source);
+    final XmlAspectChangeSetImpl xmlAspectChangeSet = new XmlAspectChangeSetImpl(source, (XmlFile)document.getParent());
+    xmlAspectChangeSet.add(new XmlDocumentChangedImpl(document));
+    event.registerChangeSet(source.getModelAspect(XmlAspect.class), xmlAspectChangeSet);
+    return event;
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public String toString() {
+    return "Xml document changed";
+  }
+
+  public void accept(XmlChangeVisitor visitor) {
+    visitor.visitDocumentChanged(this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/events/XmlElementChangedImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlElementChangedImpl.java
new file mode 100644
index 0000000..50b1632
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlElementChangedImpl.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl.events;
+
+import com.intellij.pom.xml.XmlChangeVisitor;
+import com.intellij.pom.xml.events.XmlElementChanged;
+import com.intellij.psi.xml.XmlElement;
+
+public class XmlElementChangedImpl implements XmlElementChanged {
+  private final XmlElement myElement;
+
+  public XmlElementChangedImpl(XmlElement treeElement) {
+    myElement = treeElement;
+  }
+
+  public XmlElement getElement() {
+    return myElement;
+  }
+
+  public void accept(XmlChangeVisitor visitor) {
+    visitor.visitXmlElementChanged(this);
+  }
+
+  public String toString() {
+    return "Xml element changed: " + myElement;
+  }
+}
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagChildAddImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagChildAddImpl.java
new file mode 100644
index 0000000..3ee06ba
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagChildAddImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl.events;
+
+import com.intellij.pom.xml.XmlChangeVisitor;
+import com.intellij.pom.xml.events.XmlTagChildAdd;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTagChild;
+
+public class XmlTagChildAddImpl implements XmlTagChildAdd {
+  private final XmlTag myTag;
+  private final XmlTagChild myChild;
+  public XmlTagChildAddImpl(XmlTag context, XmlTagChild treeElement) {
+    myTag = context;
+    myChild = treeElement;
+  }
+
+  public XmlTag getTag() {
+    return myTag;
+  }
+
+  public XmlTagChild getChild() {
+    return myChild;
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public String toString() {
+    return "child added to " + getTag().getName() + " child: " + myChild.toString();
+  }
+
+  public void accept(XmlChangeVisitor visitor) {
+    visitor.visitXmlTagChildAdd(this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagChildChangedImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagChildChangedImpl.java
new file mode 100644
index 0000000..2568cb9
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagChildChangedImpl.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl.events;
+
+import com.intellij.pom.PomModel;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.XmlChangeVisitor;
+import com.intellij.pom.xml.events.XmlChange;
+import com.intellij.pom.xml.events.XmlTagChildChanged;
+import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl;
+import com.intellij.pom.xml.XmlChangeVisitor;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTagChild;
+
+public class XmlTagChildChangedImpl implements XmlTagChildChanged {
+  private final XmlTag myTag;
+  private final XmlTagChild myChild;
+  public XmlTagChildChangedImpl(XmlTag context, XmlTagChild treeElement) {
+    myTag = context;
+    myChild = treeElement;
+  }
+
+  public XmlTag getTag() {
+    return myTag;
+  }
+
+  public XmlTagChild getChild() {
+    return myChild;
+  }
+
+  public static PomModelEvent createXmlTagChildChanged(PomModel source, XmlTag context, XmlTagChild treeElement) {
+    final PomModelEvent event = new PomModelEvent(source);
+    final XmlAspectChangeSetImpl xmlAspectChangeSet = new XmlAspectChangeSetImpl(source, PsiTreeUtil.getParentOfType(context, XmlFile.class));
+    xmlAspectChangeSet.add(new XmlTagChildChangedImpl(context, treeElement));
+    event.registerChangeSet(source.getModelAspect(XmlAspect.class), xmlAspectChangeSet);
+    return event;
+  }
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public String toString() {
+    return "child changed in " + getTag().getName() + " child: " + myChild.toString();
+  }
+
+  public void accept(XmlChangeVisitor visitor) {
+    visitor.visitXmlTagChildChanged(this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagChildRemovedImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagChildRemovedImpl.java
new file mode 100644
index 0000000..dd92cac
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagChildRemovedImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl.events;
+
+import com.intellij.pom.xml.XmlChangeVisitor;
+import com.intellij.pom.xml.events.XmlTagChildRemoved;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTagChild;
+
+public class XmlTagChildRemovedImpl implements XmlTagChildRemoved {
+  private final XmlTag myTag;
+  private final XmlTagChild myChild;
+  public XmlTagChildRemovedImpl(XmlTag context, XmlTagChild treeElement) {
+    myTag = context;
+    myChild = treeElement;
+  }
+
+  public XmlTag getTag() {
+    return myTag;
+  }
+
+  public XmlTagChild getChild() {
+    return myChild;
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public String toString() {
+    return "child removed from " + getTag().getName() + " child: " + myChild.toString();
+  }
+
+  public void accept(XmlChangeVisitor visitor) {
+    visitor.visitXmlTagChildRemoved(this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagNameChangedImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagNameChangedImpl.java
new file mode 100644
index 0000000..3457fe1
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTagNameChangedImpl.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl.events;
+
+import com.intellij.pom.PomModel;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl;
+import com.intellij.pom.xml.XmlChangeVisitor;
+import com.intellij.pom.xml.events.XmlTagNameChanged;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+
+public class XmlTagNameChangedImpl implements XmlTagNameChanged {
+  private final String myOldName;
+  private final XmlTag myTag;
+
+  public XmlTagNameChangedImpl(XmlTag tag, String oldName) {
+    myOldName = oldName;
+    myTag = tag;
+  }
+
+  public String getOldName() {
+    return myOldName;
+  }
+
+  public XmlTag getTag() {
+    return myTag;
+  }
+
+  public static PomModelEvent createXmlTagNameChanged(PomModel model, XmlTag tag, String oldName) {
+    final PomModelEvent event = new PomModelEvent(model);
+    final XmlAspectChangeSetImpl xmlAspectChangeSet = new XmlAspectChangeSetImpl(model, PsiTreeUtil.getParentOfType(tag, XmlFile.class));
+    xmlAspectChangeSet.add(new XmlTagNameChangedImpl(tag, oldName));
+    event.registerChangeSet(model.getModelAspect(XmlAspect.class), xmlAspectChangeSet);
+    return event;
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public String toString() {
+    return "tag name changed to " + getTag().getName() + " was: " + getOldName();
+  }
+
+  public void accept(XmlChangeVisitor visitor) {
+    visitor.visitXmlTagNameChanged(this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTextChangedImpl.java b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTextChangedImpl.java
new file mode 100644
index 0000000..b191996
--- /dev/null
+++ b/xml/impl/src/com/intellij/pom/xml/impl/events/XmlTextChangedImpl.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.pom.xml.impl.events;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.pom.PomModel;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.events.XmlChange;
+import com.intellij.pom.xml.events.XmlTextChanged;
+import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl;
+import com.intellij.pom.xml.XmlChangeVisitor;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlText;
+
+public class XmlTextChangedImpl implements XmlTextChanged {
+  private final String myOldText;
+  private final XmlText myText;
+  public XmlTextChangedImpl(XmlText xmlText, String oldText) {
+    myOldText = oldText;
+    myText = xmlText;
+  }
+
+  public String getOldText() {
+    return myOldText;
+  }
+
+  public XmlText getText() {
+    return myText;
+  }
+
+  public static PomModelEvent createXmlTextChanged(PomModel source, XmlText xmlText, String oldText) {
+    final PomModelEvent event = new PomModelEvent(source);
+    final XmlAspectChangeSetImpl xmlAspectChangeSet = new XmlAspectChangeSetImpl(source, PsiTreeUtil.getParentOfType(xmlText, XmlFile.class));
+    xmlAspectChangeSet.add(new XmlTextChangedImpl(xmlText, oldText));
+    event.registerChangeSet(source.getModelAspect(XmlAspect.class), xmlAspectChangeSet);
+    return event;
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public String toString() {
+    return "text changed to '" + StringUtil.escapeStringCharacters(myText.getValue()) + "' was: '"
+           + StringUtil.escapeStringCharacters(myOldText) + "'";
+  }
+
+  public void accept(XmlChangeVisitor visitor) {
+    visitor.visitXmlTextChanged(this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/XmlElementFactoryImpl.java b/xml/impl/src/com/intellij/psi/XmlElementFactoryImpl.java
new file mode 100644
index 0000000..77c1b5e
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/XmlElementFactoryImpl.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi;
+
+import com.intellij.ide.highlighter.XHtmlFileType;
+import com.intellij.ide.highlighter.XmlFileType;
+import com.intellij.lang.ASTFactory;
+import com.intellij.lang.Language;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.util.XmlTagUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlElementFactoryImpl extends XmlElementFactory {
+
+  private final Project myProject;
+
+  public XmlElementFactoryImpl(Project project) {
+    myProject = project;
+  }
+
+  @NotNull
+  public XmlTag createTagFromText(@NotNull @NonNls String text, @NotNull Language language) throws IncorrectOperationException {
+    assert language instanceof XMLLanguage:"Tag can be created only for xml language";
+    FileType type = language.getAssociatedFileType();
+    if (type == null) type = StdFileTypes.XML;
+    final XmlDocument document = createXmlDocument(text, "dummy."+ type.getDefaultExtension(), type);
+    final XmlTag tag = document.getRootTag();
+    if (tag == null) throw new IncorrectOperationException("Incorrect tag text");
+    return tag;
+  }
+
+  @NotNull
+  public XmlTag createTagFromText(@NotNull String text) throws IncorrectOperationException {
+    return createTagFromText(text, StdFileTypes.XML.getLanguage());
+  }
+
+  @NotNull
+  public XmlAttribute createXmlAttribute(@NotNull String name, @NotNull String value) throws IncorrectOperationException {
+    final char quoteChar;
+    if (!value.contains("\"")) {
+      quoteChar = '"';
+    } else if (!value.contains("'")) {
+      quoteChar = '\'';
+    } else {
+      quoteChar = '"';
+      value = StringUtil.replace(value, "\"", "&quot;");
+    }
+    final XmlDocument document = createXmlDocument("<tag " + name + "=" + quoteChar + value + quoteChar + "/>", "dummy.xml",
+                                                   XmlFileType.INSTANCE);
+    XmlTag tag = document.getRootTag();
+    assert tag != null;
+    return tag.getAttributes()[0];
+  }
+
+  @NotNull
+  public XmlText createDisplayText(@NotNull String s) throws IncorrectOperationException {
+    final XmlTag tagFromText = createTagFromText("<a>" + XmlTagUtil.getCDATAQuote(s) + "</a>");
+    final XmlText[] textElements = tagFromText.getValue().getTextElements();
+    if (textElements.length == 0) return (XmlText)ASTFactory.composite(XmlElementType.XML_TEXT);
+    return textElements[0];
+  }
+
+  @NotNull
+  public XmlTag createXHTMLTagFromText(@NotNull String text) throws IncorrectOperationException {
+    final XmlDocument document = createXmlDocument(text, "dummy.xhtml", XHtmlFileType.INSTANCE);
+    final XmlTag tag = document.getRootTag();
+    assert tag != null;
+    return tag;
+  }
+
+  private XmlDocument createXmlDocument(@NonNls final String text, @NonNls final String fileName, FileType fileType) {
+    final XmlDocument document = ((XmlFile)PsiFileFactory.getInstance(myProject).createFileFromText(fileName, fileType, text)).getDocument();
+    assert document != null;
+    return document;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/filters/TagNameFilter.java b/xml/impl/src/com/intellij/psi/filters/TagNameFilter.java
new file mode 100644
index 0000000..e1846cd
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/TagNameFilter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.filters;
+
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 30.01.2003
+ * Time: 13:57:35
+ * To change this template use Options | File Templates.
+ */
+public class TagNameFilter extends PlainTextFilter {
+
+  public TagNameFilter(){
+    myValue = ArrayUtil.EMPTY_STRING_ARRAY;
+  }
+
+  public TagNameFilter(@NonNls String value, boolean insensitiveFlag) {
+    super(value, insensitiveFlag);
+  }
+
+  public TagNameFilter(@NonNls String value){
+    super(value);
+  }
+
+  public TagNameFilter(@NonNls String... values){
+    super(values);
+  }
+
+  public TagNameFilter(@NonNls String value1, @NonNls String value2){
+    super(value1, value2);
+  }
+
+  @Override
+  protected String getTextByElement(final Object element) {
+    if (element instanceof XmlTag) {
+      return ((XmlTag)element).getLocalName();
+    }
+    else {
+      return super.getTextByElement(element);
+    }
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/psi/filters/TextContainFilter.java b/xml/impl/src/com/intellij/psi/filters/TextContainFilter.java
new file mode 100644
index 0000000..0a7ce9e
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/TextContainFilter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.filters;
+
+import com.intellij.psi.PsiElement;
+
+/**
+ * @author spleaner
+ */
+public class TextContainFilter extends XmlTextFilter {
+  public TextContainFilter(String[] values){
+    super(values);
+  }
+
+  public TextContainFilter(String value1, String value2){
+    super(value1, value2);
+  }
+
+  public TextContainFilter(String value){
+    super(value);
+  }
+
+  public TextContainFilter(){}
+
+  public boolean isAcceptable(Object element, PsiElement context){
+    if(element != null) {
+      for (final String value : myValue) {
+        if (value == null) {
+          return true;
+        }
+        String elementValue = getTextByElement(element);
+        if (elementValue == null) return false;
+        if (elementValue.contains(value)) return true;
+      }
+    }
+
+    return false;
+  }
+
+
+}
diff --git a/xml/impl/src/com/intellij/psi/filters/TextStartFilter.java b/xml/impl/src/com/intellij/psi/filters/TextStartFilter.java
new file mode 100644
index 0000000..f11d806
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/TextStartFilter.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.filters;
+
+import com.intellij.psi.PsiElement;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 27.08.2003
+ * Time: 18:18:38
+ * To change this template use Options | File Templates.
+ */
+public class TextStartFilter extends XmlTextFilter{
+  public TextStartFilter(String[] values){
+    super(values);
+  }
+
+  public TextStartFilter(String value1, String value2){
+    super(value1, value2);
+  }
+
+  public TextStartFilter(String value){
+    super(value);
+  }
+
+  public TextStartFilter(){}
+
+  public boolean isAcceptable(Object element, PsiElement context){
+    if(element != null) {
+      for (final String value : myValue) {
+        if (value == null) {
+          return true;
+        }
+        String elementValue = getTextByElement(element);
+        if (elementValue == null) return false;
+        if (elementValue.startsWith(value)) return true;
+      }
+    }
+
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/filters/XmlTagFilter.java b/xml/impl/src/com/intellij/psi/filters/XmlTagFilter.java
new file mode 100644
index 0000000..2b2e773
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/XmlTagFilter.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi.filters;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlTag;
+
+public class XmlTagFilter implements ElementFilter {
+  public static final XmlTagFilter INSTANCE = new XmlTagFilter();
+
+  private XmlTagFilter() {}
+
+  public boolean isAcceptable(Object element, PsiElement context) {
+    return element instanceof XmlTag;
+  }
+
+  public boolean isClassAcceptable(Class hintClass) {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/filters/XmlTextFilter.java b/xml/impl/src/com/intellij/psi/filters/XmlTextFilter.java
new file mode 100644
index 0000000..9f63343
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/XmlTextFilter.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.filters;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 30.01.2003
+ * Time: 13:57:35
+ * To change this template use Options | File Templates.
+ */
+public class XmlTextFilter implements ElementFilter, InitializableFilter{
+  protected String[] myValue;
+  private boolean myCaseInsensitiveFlag = false;
+
+  public XmlTextFilter(){
+    myValue = ArrayUtil.EMPTY_STRING_ARRAY;
+  }
+  public XmlTextFilter(@NonNls String value, boolean incensetiveFlag){
+    myCaseInsensitiveFlag = incensetiveFlag;
+    myValue = new String[1];
+    myValue[0] = value;
+  }
+
+  public XmlTextFilter(@NonNls String value){
+    myValue = new String[1];
+    myValue[0] = value;
+  }
+
+  public XmlTextFilter(@NonNls String... values){
+    myValue = values;
+  }
+
+  public XmlTextFilter(@NonNls String value1, @NonNls String value2){
+    myValue = new String[2];
+    myValue[0] = value1;
+    myValue[1] = value2;
+  }
+
+  public boolean isClassAcceptable(Class hintClass){
+    return true;
+  }
+
+  public boolean isAcceptable(Object element, PsiElement context){
+    if(element != null) {
+      for (final String value : myValue) {
+        if (value == null) {
+          return true;
+        }
+        final String elementText = getTextByElement(element);
+        if (myCaseInsensitiveFlag) {
+          if (value.equalsIgnoreCase(elementText)) return true;
+        }
+        else {
+          if (value.equals(elementText)) return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  public String toString(){
+    String ret = "(";
+    for(int i = 0; i < myValue.length; i++){
+      ret += myValue[i];
+      if(i < myValue.length - 1){
+        ret += " | ";
+      }
+    }
+    ret += ")";
+    return ret;
+  }
+
+  public void init(Object[] fromGetter){
+    try{
+      myValue = new String[fromGetter.length];
+      System.arraycopy(fromGetter, 0, myValue, 0, fromGetter.length);
+    }
+    catch(ClassCastException cce){
+      myValue = ArrayUtil.EMPTY_STRING_ARRAY;
+    }
+  }
+
+  protected String getTextByElement(Object element){
+    String elementValue = null;
+    if(element instanceof PsiNamedElement){
+      if (element instanceof XmlTag) {
+        elementValue = ((XmlTag)element).getLocalName();
+      } else {
+        elementValue = ((PsiNamedElement)element).getName();
+      }
+    }
+    else if (element instanceof PsiElement) {
+      elementValue = ((PsiElement) element).getText();
+    }
+    return elementValue;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/filters/getters/HtmlAttributeValueGetter.java b/xml/impl/src/com/intellij/psi/filters/getters/HtmlAttributeValueGetter.java
new file mode 100644
index 0000000..6bc2334
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/getters/HtmlAttributeValueGetter.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.filters.getters;
+
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.nio.charset.Charset;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 24.11.2003
+ * Time: 14:17:59
+ * To change this template use Options | File Templates.
+ */
+public class HtmlAttributeValueGetter extends XmlAttributeValueGetter {
+  private final boolean myCaseSensitive;
+
+  public HtmlAttributeValueGetter(boolean _caseSensitive) {
+    myCaseSensitive = _caseSensitive;
+  }
+
+  @Nullable
+  @NonNls
+  protected String[] addSpecificCompletions(final XmlAttribute attribute) {
+    @NonNls String name = attribute.getName();
+    final XmlTag tag = attribute.getParent();
+    if (tag == null) return null;
+
+    @NonNls String tagName = tag.getName();
+    if (!myCaseSensitive) {
+      name = name.toLowerCase();
+      tagName = tagName.toLowerCase();
+    }
+
+    final String namespace = tag.getNamespace();
+    if (XmlUtil.XHTML_URI.equals(namespace) || XmlUtil.HTML_URI.equals(namespace)) {
+
+      if ("target".equals(name)) {
+        return new String[]{"_blank", "_top", "_self", "_parent"};
+      }
+      else if ("enctype".equals(name)) {
+        return new String[]{"multipart/form-data", "application/x-www-form-urlencoded"};
+      }
+      else if ("rel".equals(name) || "rev".equals(name)) {
+        return new String[]{"alternate", "stylesheet", "start", "next", "prev", "contents", "index", "glossary", "copyright", "chapter",
+            "section", "subsection", "appendix", "help", "bookmark", "script"};
+      }
+      else if ("media".equals(name)) {
+        return new String[]{"screen", "tty", "tv", "projection", "handheld", "print", "all", "aural", "braille"};
+      }
+      else if ("language".equals(name)) {
+        return new String[]{"JavaScript", "VBScript", "JScript", "JavaScript1.2", "JavaScript1.3", "JavaScript1.4", "JavaScript1.5"};
+      }
+      else if ("type".equals(name) && "link".equals(tagName)) {
+        return new String[]{"text/css", "text/html", "text/plain", "text/xml"};
+      }
+      else if ("http-equiv".equals(name) && "meta".equals(tagName)) {
+        return new String[]{"Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", "Accept-Ranges", "Age", "Allow",
+            "Authorization", "Cache-Control", "Connection", "Content-Encoding", "Content-Language", "Content-Length", "Content-Location",
+            "Content-MD5", "Content-Range", "Content-Type", "Date", "ETag", "Expect", "Expires", "From", "Host", "If-Match",
+            "If-Modified-Since", "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified", "Location", "Max-Forwards", "Pragma",
+            "Proxy-Authenticate", "Proxy-Authorization", "Range", "Referer", "Refresh", "Retry-After", "Server", "TE", "Trailer", "Transfer-Encoding",
+            "Upgrade", "User-Agent", "Vary", "Via", "Warning", "WWW-Authenticate"};
+      }
+      else if("content".equals(name) && "meta".equals(tagName) && getAttribute(tag, "name") == null) {
+        return HtmlUtil.CONTENT_TYPES;
+      }
+      else if("accept-charset".equals(name) || "charset".equals(name)) {
+        Charset[] charSets = CharsetToolkit.getAvailableCharsets();
+        String[] names = new String[charSets.length];
+        for (int i = 0; i < names.length; i++) {
+          names[i] = charSets[i].toString();
+        }
+        return names;
+      }
+    }
+
+    return null;
+  }
+
+  @Nullable
+  private XmlAttribute getAttribute(@NotNull XmlTag tag, @NotNull String attributeName) {
+    if (myCaseSensitive) {
+      return tag.getAttribute(attributeName);
+    }
+
+    for (XmlAttribute xmlAttribute : tag.getAttributes()) {
+      if (attributeName.equalsIgnoreCase(xmlAttribute.getName())) {
+        return xmlAttribute;
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/filters/getters/XmlAttributeValueGetter.java b/xml/impl/src/com/intellij/psi/filters/getters/XmlAttributeValueGetter.java
new file mode 100644
index 0000000..ddf656d
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/getters/XmlAttributeValueGetter.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.filters.getters;
+
+import com.intellij.codeInsight.completion.CompletionContext;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.filters.ContextGetter;
+import com.intellij.psi.impl.source.xml.XmlTokenImpl;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 24.11.2003
+ * Time: 14:17:59
+ * To change this template use Options | File Templates.
+ */
+public class XmlAttributeValueGetter implements ContextGetter {
+  public XmlAttributeValueGetter() {}
+
+  public Object[] get(PsiElement context, CompletionContext completionContext) {
+    return getApplicableAttributeVariants(context);
+  }
+
+  private Object[] getApplicableAttributeVariants(PsiElement _context) {
+    if (_context instanceof XmlTokenImpl && ((XmlTokenImpl)_context).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) {
+      XmlAttribute attr = PsiTreeUtil.getParentOfType(_context, XmlAttribute.class);
+      if (attr != null) {
+        final XmlAttributeDescriptor descriptor = attr.getDescriptor();
+
+        if (descriptor != null) {
+          if (descriptor.isFixed()) {
+            final String defaultValue = descriptor.getDefaultValue();
+            return defaultValue == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : new Object[]{defaultValue};
+          }
+
+          String[] values = descriptor instanceof BasicXmlAttributeDescriptor ?
+                            ((BasicXmlAttributeDescriptor)descriptor).getEnumeratedValues(attr)
+                                                                              : descriptor.getEnumeratedValues();
+
+          final String[] strings = addSpecificCompletions(attr);
+
+          if (values == null || values.length == 0) {
+            values = strings;
+          }
+          else if (strings != null) {
+            values = ArrayUtil.mergeArrays(values, strings);
+          }
+
+          return values == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : values;
+        }
+      }
+    }
+
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
+  }
+
+  @Nullable
+  protected String[] addSpecificCompletions(final XmlAttribute context) {
+    return null;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/filters/position/RootTagFilter.java b/xml/impl/src/com/intellij/psi/filters/position/RootTagFilter.java
new file mode 100644
index 0000000..ea39b3f
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/position/RootTagFilter.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.filters.position;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.filters.ElementFilter;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlTag;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 03.02.2003
+ * Time: 18:29:13
+ * To change this template use Options | File Templates.
+ */
+public class RootTagFilter extends PositionElementFilter{
+  public RootTagFilter(ElementFilter filter){
+    setFilter(filter);
+  }
+
+  public RootTagFilter(){}
+  public boolean isAcceptable(Object element, PsiElement scope){
+    if (!(element instanceof XmlDocument)) return false;
+    final XmlTag rootTag = ((XmlDocument)element).getRootTag();
+    if(rootTag == null) return false;
+
+    return getFilter().isAcceptable(rootTag, (PsiElement)element);
+  }
+
+  public String toString(){
+    return "roottag(" + getFilter().toString() + ")";
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/filters/position/TargetNamespaceFilter.java b/xml/impl/src/com/intellij/psi/filters/position/TargetNamespaceFilter.java
new file mode 100644
index 0000000..f64fe8b
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/position/TargetNamespaceFilter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.filters.position;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.filters.XmlTextFilter;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ReflectionCache;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 07.05.2003
+ * Time: 4:13:57
+ * To change this template use Options | File Templates.
+ */
+public class TargetNamespaceFilter extends XmlTextFilter {
+  public TargetNamespaceFilter(String str){
+    super(str);
+  }
+
+  public TargetNamespaceFilter(String[] strs){
+    super(strs);
+  }
+
+  public boolean isClassAcceptable(Class hintClass){
+    return ReflectionCache.isAssignable(XmlTag.class, hintClass) || ReflectionCache.isAssignable(XmlDocument.class, hintClass);
+  }
+
+  public boolean isAcceptable(Object element, PsiElement context){
+    if(element instanceof XmlTag){
+      final String attributeValue = ((XmlTag)element).getAttributeValue("targetNamespace");
+      if(attributeValue != null){
+        for (String aMyValue : myValue) {
+          if (aMyValue.equals(attributeValue)) return true;
+        }
+      }
+    }
+    else if(element instanceof XmlDocument){
+      return isAcceptable(((XmlDocument) element).getRootTag(), context);
+    }
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/filters/position/XmlTokenTypeFilter.java b/xml/impl/src/com/intellij/psi/filters/position/XmlTokenTypeFilter.java
new file mode 100644
index 0000000..c323476
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/filters/position/XmlTokenTypeFilter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.filters.position;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.filters.ElementFilter;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.util.ReflectionCache;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 10.03.2003
+ * Time: 12:10:08
+ * To change this template use Options | File Templates.
+ */
+public class XmlTokenTypeFilter implements ElementFilter{
+  private IElementType myType = null;
+
+  public XmlTokenTypeFilter(){}
+
+  public XmlTokenTypeFilter(IElementType type){
+    myType = type;
+  }
+
+  public boolean isClassAcceptable(Class hintClass){
+    return ReflectionCache.isAssignable(XmlToken.class, hintClass);
+  }
+
+  public boolean isAcceptable(Object element, PsiElement context){
+    if(element instanceof PsiElement) {
+      final ASTNode node = ((PsiElement)element).getNode();
+      return node != null && node.getElementType() == myType;
+    }
+    else if(element instanceof ASTNode){
+      return ((ASTNode)element).getElementType() == myType;
+    }
+    return false;
+  }
+
+  public String toString(){
+    return "token-type(" + myType + ")";
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/psi/formatter/MarkupLineWrapPositionStrategy.java b/xml/impl/src/com/intellij/psi/formatter/MarkupLineWrapPositionStrategy.java
new file mode 100644
index 0000000..4db5fbe
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/MarkupLineWrapPositionStrategy.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter;
+
+import com.intellij.openapi.editor.LineWrapPositionStrategy;
+import com.intellij.openapi.editor.PsiAwareDefaultLineWrapPositionStrategy;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.xml.XmlElementType;
+
+/**
+ * {@link LineWrapPositionStrategy} for markup languages like XML, HTML etc.
+ * 
+ * @author Denis Zhdanov
+ * @since 5/11/11 7:42 PM
+ */
+public class MarkupLineWrapPositionStrategy extends PsiAwareDefaultLineWrapPositionStrategy {
+
+  public MarkupLineWrapPositionStrategy() {
+    super(true, XmlElementType.XML_TEXT, TokenType.WHITE_SPACE);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractSyntheticBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractSyntheticBlock.java
new file mode 100644
index 0000000..0eb42a2
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractSyntheticBlock.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.templateLanguages.OuterLanguageElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+
+import java.util.List;
+
+
+public abstract class AbstractSyntheticBlock implements Block {
+  protected final Indent myIndent;
+  protected final XmlFormattingPolicy myXmlFormattingPolicy;
+  protected final ASTNode myEndTreeNode;
+  protected final ASTNode myStartTreeNode;
+  private final XmlTag myTag;
+
+  public AbstractSyntheticBlock(List<Block> subBlocks, Block parent, XmlFormattingPolicy policy, Indent indent) {
+    myEndTreeNode = getLastNode(subBlocks);
+    myStartTreeNode = getFirstNode(subBlocks);
+    myIndent = indent;
+    myXmlFormattingPolicy = policy;
+    if (parent instanceof AbstractXmlBlock) {
+      myTag = ((AbstractXmlBlock)parent).getTag();
+    }
+    else if (parent instanceof AbstractSyntheticBlock) {
+      myTag = ((AbstractSyntheticBlock)parent).getTag();
+    } else {
+      throw new IllegalStateException("Parent should be AbstractXmlBlock or AbstractSyntheticBlock, but it is " + parent.getClass());
+    }
+
+  }
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.xml.AbstractSyntheticBlock");
+
+  private ASTNode getFirstNode(final List<Block> subBlocks) {
+    LOG.assertTrue(!subBlocks.isEmpty());
+    final Block firstBlock = subBlocks.get(0);
+    if (firstBlock instanceof AbstractBlock) {
+      return ((AbstractBlock)firstBlock).getNode();
+    }
+    else {
+      return getFirstNode(firstBlock.getSubBlocks());
+    }
+  }
+
+  private ASTNode getLastNode(final List<Block> subBlocks) {
+    LOG.assertTrue(!subBlocks.isEmpty());
+    final Block lastBlock = subBlocks.get(subBlocks.size() - 1);
+    if (lastBlock instanceof AbstractBlock) {
+      return ((AbstractBlock)lastBlock).getNode();
+    }
+    else {
+      return getLastNode(lastBlock.getSubBlocks());
+    }
+  }
+
+  private boolean isEndOfTag() {
+    return myEndTreeNode.getElementType() == XmlElementType.XML_TAG_END;
+  }
+
+  public Wrap getWrap() {
+    return null;
+  }
+
+  public Indent getIndent() {
+    return myIndent;
+  }
+
+  public Alignment getAlignment() {
+    return null;
+  }
+
+  protected static boolean isXmlTagName(final IElementType type1, final IElementType type2) {
+    if (type1 == XmlElementType.XML_NAME && type2 == XmlElementType.XML_TAG_END) return true;
+    if (type1 == XmlElementType.XML_NAME && type2 == XmlElementType.XML_EMPTY_ELEMENT_END) return true;
+    if (type1 == XmlElementType.XML_ATTRIBUTE && type2 == XmlElementType.XML_EMPTY_ELEMENT_END) return true;
+    return type1 == XmlElementType.XML_ATTRIBUTE && type2 == XmlElementType.XML_TAG_END;
+  }
+
+  public boolean endsWithText() {
+    return myEndTreeNode.getElementType() == XmlElementType.XML_TEXT ||
+           myEndTreeNode.getElementType() == XmlElementType.XML_DATA_CHARACTERS;
+  }
+
+  public boolean isTagDescription() {
+    final ASTNode startTreeNode = myStartTreeNode;
+    return isTagDescription(startTreeNode);
+  }
+
+  private static boolean isTagDescription(final ASTNode startTreeNode) {
+    return startTreeNode.getElementType() == XmlElementType.XML_START_TAG_START ||
+           startTreeNode.getElementType() == XmlElementType.XML_END_TAG_START;
+  }
+
+  public boolean startsWithText() {
+    return myStartTreeNode.getElementType() == XmlElementType.XML_TEXT ||
+           myStartTreeNode.getElementType() == XmlElementType.XML_DATA_CHARACTERS;
+  }
+
+  public boolean endsWithTextElement() {
+    if (endsWithText()) return true;
+    if (isEndOfTag() && myXmlFormattingPolicy.isTextElement(getTag())) return true;
+    return isTextTag(myEndTreeNode);
+  }
+
+  protected XmlTag getTag() {
+    return myTag;
+  }
+
+  public boolean startsWithTextElement() {
+    if (startsWithText()) return true;
+    if (isStartOfTag() && myXmlFormattingPolicy.isTextElement(getTag())) return true;
+    return isTextTag(myStartTreeNode);
+  }
+
+  private boolean isTextTag(final ASTNode treeNode) {
+    return isXmlTag(treeNode) && myXmlFormattingPolicy.isTextElement((XmlTag)SourceTreeToPsiMap.treeElementToPsi(treeNode));
+  }
+
+  private boolean isXmlTag(final ASTNode treeNode) {
+    return (treeNode.getPsi() instanceof XmlTag);
+  }
+
+  private boolean isStartOfTag() {
+    return isTagDescription(myStartTreeNode);
+  }
+
+  protected static TextRange calculateTextRange(final List<Block> subBlocks) {
+    return new TextRange(subBlocks.get(0).getTextRange().getStartOffset(),
+                         subBlocks.get(subBlocks.size() - 1).getTextRange().getEndOffset());
+  }
+
+  public boolean isIncomplete() {
+    return getSubBlocks().get(getSubBlocks().size() - 1).isIncomplete();
+  }
+
+  public boolean startsWithTag() {
+    return isXmlTag(myStartTreeNode);
+  }
+
+  public XmlTag getStartTag() {
+    return (XmlTag)myStartTreeNode.getPsi();
+  }
+
+
+  public boolean endsWithTag() {
+    return isXmlTag(myEndTreeNode);
+  }
+
+  public boolean isJspTextBlock() {
+    return false;
+  }
+
+  public boolean isJspxTextBlock() {
+    return false;
+  }
+
+  /**
+   * Checks if the block contains a single node which belongs to the outer (template) language.
+   *
+   * @return True if it does, False otherwise.
+   */
+  public boolean isOuterLanguageBlock() {
+    return (myStartTreeNode == myEndTreeNode) && (myStartTreeNode instanceof OuterLanguageElement);
+  }
+
+  public boolean isLeaf() {
+    return false;
+  }
+
+  public boolean startsWithCDATA() {
+    return isCDATA(myStartTreeNode.getFirstChildNode());
+  }
+
+  private boolean isCDATA(final ASTNode node) {
+    return node != null && node.getElementType() == XmlElementType.XML_CDATA;
+  }
+
+  public boolean containsCDATA() {
+    return myStartTreeNode.getElementType() == XmlElementType.XML_CDATA_START &&
+           myEndTreeNode.getElementType() == XmlElementType.XML_CDATA_END;
+  }
+
+  public boolean endsWithCDATA() {
+    return isCDATA(myStartTreeNode.getLastChildNode());
+  }
+
+  public boolean insertLineFeedAfter() {
+    final List<Block> subBlocks = getSubBlocks();
+    final Block lastBlock = subBlocks.get(subBlocks.size() - 1);
+    if (lastBlock instanceof XmlTagBlock) {
+      return insertLineFeedAfter(((XmlTagBlock)lastBlock).getTag());
+    }
+    if (endsWithText()) {
+      return insertLineFeedAfter(myTag);
+    }
+    return false;
+  }
+
+  protected boolean insertLineFeedAfter(final XmlTag tag) {
+    return myXmlFormattingPolicy.getWrappingTypeForTagBegin(tag) == WrapType.ALWAYS;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java
new file mode 100644
index 0000000..4609f73
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.*;
+import com.intellij.lang.*;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.formatter.WhiteSpaceFormattingStrategy;
+import com.intellij.psi.formatter.WhiteSpaceFormattingStrategyFactory;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.impl.source.tree.LeafElement;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.impl.source.tree.TreeUtil;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public abstract class AbstractXmlBlock extends AbstractBlock {
+  protected XmlFormattingPolicy myXmlFormattingPolicy;
+  protected XmlInjectedLanguageBlockBuilder myInjectedBlockBuilder;
+  private boolean myPreserveSpace;
+
+  protected AbstractXmlBlock(final ASTNode node,
+                            final Wrap wrap,
+                            final Alignment alignment,
+                            final XmlFormattingPolicy policy) {
+    this(node, wrap, alignment, policy, false);
+  }
+
+
+  protected AbstractXmlBlock(final ASTNode node,
+                          final Wrap wrap,
+                          final Alignment alignment,
+                          final XmlFormattingPolicy policy,
+                          final boolean preserveSpace) {
+    super(node, wrap, alignment);
+    myXmlFormattingPolicy = policy;
+    if (node == null) {
+      LOG.assertTrue(false);
+    }
+    if (node.getTreeParent() == null) {
+      myXmlFormattingPolicy.setRootBlock(node, this);
+    }
+    myInjectedBlockBuilder = new XmlInjectedLanguageBlockBuilder(myXmlFormattingPolicy);
+    myPreserveSpace = shouldPreserveSpace(node, preserveSpace);
+  }
+
+
+  /**
+   * Handles xml:space='preserve|default' attribute.
+   * See <a href="http://www.w3.org/TR/2004/REC-xml-20040204/#sec-white-space">Extensible Markup Language (XML) 1.0 (Third Edition),
+   * White Space Handling</a>
+   *
+   * @return True if the space must be preserved (xml:space='preserve'), false if the attribute
+   *         contains 'default'. If the attribute is not defined, return the current value.
+   */ 
+  private static boolean shouldPreserveSpace(ASTNode node, boolean defaultValue) {
+    if (node.getPsi() instanceof XmlTag) {
+      XmlTag tag = (XmlTag)node.getPsi();
+      if (tag != null) {
+        XmlAttribute spaceAttr = tag.getAttribute("xml:space");
+        if (spaceAttr != null) {
+          String value = spaceAttr.getValue();
+          if ("preserve".equals(value)) {
+            return true;
+          }
+          if ("default".equals(value))  {
+            return false;
+          }
+        }
+      }
+    }
+    return defaultValue;
+  }
+  
+  public boolean isPreserveSpace() {
+    return myPreserveSpace;
+  }
+
+
+  public static WrapType getWrapType(final int type) {
+    if (type == CodeStyleSettings.DO_NOT_WRAP) return WrapType.NONE;
+    if (type == CodeStyleSettings.WRAP_ALWAYS) return WrapType.ALWAYS;
+    if (type == CodeStyleSettings.WRAP_AS_NEEDED) return WrapType.NORMAL;
+    return WrapType.CHOP_DOWN_IF_LONG;
+  }
+
+  protected Alignment chooseAlignment(final ASTNode child, final Alignment attrAlignment, final Alignment textAlignment) {
+    if (myNode.getElementType() == XmlElementType.XML_TEXT) return getAlignment();
+    final IElementType elementType = child.getElementType();
+    if (elementType == XmlElementType.XML_ATTRIBUTE && myXmlFormattingPolicy.getShouldAlignAttributes()) return attrAlignment;
+    if (elementType == XmlElementType.XML_TEXT && myXmlFormattingPolicy.getShouldAlignText()) return textAlignment;
+    return null;
+  }
+
+  private Wrap getTagEndWrapping(final XmlTag parent) {
+    return Wrap.createWrap(myXmlFormattingPolicy.getWrappingTypeForTagEnd(parent), true);
+  }
+
+  protected Wrap chooseWrap(final ASTNode child, final Wrap tagBeginWrap, final Wrap attrWrap, final Wrap textWrap) {
+    if (myNode.getElementType() == XmlElementType.XML_TEXT) return textWrap;
+    final IElementType elementType = child.getElementType();
+    if (elementType == XmlElementType.XML_ATTRIBUTE) return attrWrap;
+    if (elementType == XmlElementType.XML_START_TAG_START) return tagBeginWrap;
+    if (elementType == XmlElementType.XML_END_TAG_START) {
+      final PsiElement parent = SourceTreeToPsiMap.treeElementToPsi(child.getTreeParent());
+      if (parent instanceof XmlTag) {
+        final XmlTag tag = (XmlTag)parent;
+        if (canWrapTagEnd(tag)) {
+          return getTagEndWrapping(tag);
+        }
+      }
+      return null;
+    }
+    if (elementType == XmlElementType.XML_TEXT || elementType == XmlElementType.XML_DATA_CHARACTERS) return textWrap;
+    return null;
+  }
+
+  protected boolean canWrapTagEnd(final XmlTag tag) {
+    return tag.getSubTags().length > 0;
+  }
+
+  protected XmlTag getTag() {
+    return getTag(myNode);
+  }
+
+  protected static XmlTag getTag(final ASTNode node) {
+    final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(node);
+    if (element instanceof XmlTag) {
+      return (XmlTag)element;
+    }
+    else {
+      return null;
+    }
+  }
+
+  protected Wrap createTagBeginWrapping(final XmlTag tag) {
+    return Wrap.createWrap(myXmlFormattingPolicy.getWrappingTypeForTagBegin(tag), true);
+  }
+
+  protected
+  @Nullable
+  ASTNode processChild(List<Block> result,
+                       final ASTNode child,
+                       final Wrap wrap,
+                       final Alignment alignment,
+                       final Indent indent) {
+    final Language myLanguage = myNode.getPsi().getLanguage();
+    final PsiElement childPsi = child.getPsi();
+    final Language childLanguage = childPsi.getLanguage();
+    if (useMyFormatter(myLanguage, childLanguage, childPsi)) {
+
+      XmlTag tag = getAnotherTreeTag(child);
+      if (tag != null
+          && containsTag(tag)
+          && doesNotIntersectSubTagsWith(tag)) {
+        ASTNode currentChild = createAnotherTreeNode(result, child, tag, indent, wrap, alignment);
+
+        if (currentChild == null) {
+          return null;
+        }
+
+        while (currentChild != null && currentChild.getTreeParent() != myNode && currentChild.getTreeParent() != child.getTreeParent()) {
+          currentChild = processAllChildrenFrom(result, currentChild, wrap, alignment, indent);
+          if (currentChild != null && (currentChild.getTreeParent() == myNode || currentChild.getTreeParent() == child.getTreeParent())) {
+            return currentChild;
+          }
+          if (currentChild != null) {
+            currentChild = currentChild.getTreeParent();
+
+          }
+        }
+
+        return currentChild;
+      }
+
+      processSimpleChild(child, indent, result, wrap, alignment);
+      return child;
+    }
+    else {
+      myInjectedBlockBuilder.addInjectedLanguageBlockWrapper(result, child, indent, 0, null);
+      return child;
+    }
+  }
+
+  protected boolean doesNotIntersectSubTagsWith(final PsiElement tag) {
+    final TextRange tagRange = tag.getTextRange();
+    final XmlTag[] subTags = getSubTags();
+    for (XmlTag subTag : subTags) {
+      final TextRange subTagRange = subTag.getTextRange();
+      if (subTagRange.getEndOffset() < tagRange.getStartOffset()) continue;
+      if (subTagRange.getStartOffset() > tagRange.getEndOffset()) return true;
+
+      if (tagRange.getStartOffset() > subTagRange.getStartOffset() && tagRange.getEndOffset() < subTagRange.getEndOffset()) return false;
+      if (tagRange.getEndOffset() > subTagRange.getStartOffset() && tagRange.getEndOffset() < subTagRange.getEndOffset()) return false;
+
+    }
+    return true;
+  }
+
+  private XmlTag[] getSubTags() {
+
+    if (myNode instanceof XmlTag) {
+      return ((XmlTag)myNode.getPsi()).getSubTags();
+    }
+    else if (myNode.getPsi() instanceof XmlElement) {
+      return collectSubTags((XmlElement)myNode.getPsi());
+    }
+    else {
+      return new XmlTag[0];
+    }
+
+  }
+
+  private static XmlTag[] collectSubTags(final XmlElement node) {
+    final List<XmlTag> result = new ArrayList<XmlTag>();
+    node.processElements(new PsiElementProcessor() {
+      public boolean execute(@NotNull final PsiElement element) {
+        if (element instanceof XmlTag) {
+          result.add((XmlTag)element);
+        }
+        return true;
+      }
+    }, node);
+    return result.toArray(new XmlTag[result.size()]);
+  }
+
+  protected boolean containsTag(final PsiElement tag) {
+    final ASTNode closingTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(myNode);
+    final ASTNode startTagStart = XmlChildRole.START_TAG_END_FINDER.findChild(myNode);
+
+    if (closingTagStart == null && startTagStart == null) {
+      return tag.getTextRange().getEndOffset() <= myNode.getTextRange().getEndOffset();
+    }
+    else if (closingTagStart == null) {
+      return false;
+    }
+    else {
+      return tag.getTextRange().getEndOffset() <= closingTagStart.getTextRange().getEndOffset();
+    }
+  }
+
+  private ASTNode processAllChildrenFrom(final List<Block> result,
+                                         final @NotNull ASTNode child,
+                                         final Wrap wrap,
+                                         final Alignment alignment,
+                                         final Indent indent) {
+    ASTNode resultNode = child;
+    ASTNode currentChild = child.getTreeNext();
+    while (currentChild != null && currentChild.getElementType() != XmlElementType.XML_END_TAG_START) {
+      if (!containsWhiteSpacesOnly(currentChild)) {
+        currentChild = processChild(result, currentChild, wrap, alignment, indent);
+        resultNode = currentChild;
+      }
+      if (currentChild != null) {
+        currentChild = currentChild.getTreeNext();
+      }
+    }
+    return resultNode;
+  }
+
+  protected void processSimpleChild(final ASTNode child,
+                                  final Indent indent,
+                                  final List<Block> result,
+                                  final Wrap wrap,
+                                  final Alignment alignment) {
+    if (isXmlTag(child)) {
+      result.add(createTagBlock(child, indent != null ? indent : Indent.getNoneIndent(), wrap, alignment));
+    } else if (child.getElementType() == XmlElementType.XML_DOCTYPE) {
+      result.add(
+        new XmlBlock(child, wrap, alignment, myXmlFormattingPolicy, indent, null, isPreserveSpace()) {
+          protected Wrap getDefaultWrap(final ASTNode node) {
+            final IElementType type = node.getElementType();
+            return type == XmlElementType.XML_ATTRIBUTE_VALUE_TOKEN ? Wrap.createWrap(getWrapType(myXmlFormattingPolicy.getAttributesWrap()), false) : null;
+          }
+        }
+      );
+    }
+    else {
+      result.add(createSimpleChild(child, indent, wrap, alignment));
+    }
+  }
+
+
+  protected XmlBlock createSimpleChild(final ASTNode child, final Indent indent, final Wrap wrap, final Alignment alignment) {
+    return new XmlBlock(child, wrap, alignment, myXmlFormattingPolicy, indent, null, isPreserveSpace());
+  }
+
+  protected XmlTagBlock createTagBlock(final ASTNode child, final Indent indent, final Wrap wrap, final Alignment alignment) {
+    return new XmlTagBlock(child, wrap, alignment, myXmlFormattingPolicy, indent != null ? indent : Indent.getNoneIndent(), isPreserveSpace());
+  }
+
+  @Nullable
+  protected XmlTag findXmlTagAt(final ASTNode child, final int startOffset) {
+    return null; 
+  }
+
+  @Nullable
+  protected ASTNode createAnotherTreeNode(final List<Block> result,
+                                            final ASTNode child,
+                                            PsiElement tag,
+                                            final Indent indent,
+                                            final Wrap wrap, final Alignment alignment) {
+    return null;
+  }
+
+  @Nullable
+  protected Block createAnotherTreeTagBlock(final PsiElement tag, final Indent childIndent) {
+    return null;
+  }
+
+  protected XmlFormattingPolicy createPolicyFor() {
+    return myXmlFormattingPolicy;
+  }
+
+  private CodeStyleSettings getSettings() {
+    return myXmlFormattingPolicy.getSettings();
+  }
+
+  @Nullable
+  protected XmlTag getAnotherTreeTag(final ASTNode child) {
+    return null;
+
+  }
+  protected boolean isXmlTag(final ASTNode child) {
+    return isXmlTag(child.getPsi());
+  }
+
+  protected boolean isXmlTag(final PsiElement psi) {
+    return psi instanceof XmlTag;
+  }
+
+  protected boolean useMyFormatter(final Language myLanguage, final Language childLanguage, final PsiElement childPsi) {
+    if (myLanguage == childLanguage ||
+        childLanguage == StdFileTypes.HTML.getLanguage() ||
+        childLanguage == StdFileTypes.XHTML.getLanguage() ||
+        childLanguage == StdFileTypes.XML.getLanguage()) {
+      return true;
+    }
+    final FormattingModelBuilder childFormatter = LanguageFormatting.INSTANCE.forLanguage(childLanguage);
+    return childFormatter == null ||
+           childFormatter instanceof DelegatingFormattingModelBuilder &&
+           ((DelegatingFormattingModelBuilder)childFormatter).dontFormatMyModel();
+  }
+
+  protected boolean isJspxJavaContainingNode(final ASTNode child) {
+    return false;
+  }
+
+  public abstract boolean insertLineBreakBeforeTag();
+
+  public abstract boolean removeLineBreakBeforeTag();
+
+  protected Spacing createDefaultSpace(boolean forceKeepLineBreaks, final boolean inText) {
+    boolean shouldKeepLineBreaks = getShouldKeepLineBreaks(inText, forceKeepLineBreaks);
+    return Spacing.createSpacing(0, Integer.MAX_VALUE, 0, shouldKeepLineBreaks, myXmlFormattingPolicy.getKeepBlankLines());
+  }
+
+  private boolean getShouldKeepLineBreaks(final boolean inText, final boolean forceKeepLineBreaks) {
+    if (forceKeepLineBreaks) {
+      return true;
+    }
+    if (inText && myXmlFormattingPolicy.getShouldKeepLineBreaksInText()) {
+      return true;
+    }
+    if (!inText && myXmlFormattingPolicy.getShouldKeepLineBreaks()) {
+      return true;
+    }
+    return false;
+  }
+
+  public abstract boolean isTextElement();
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.xml.AbstractXmlBlock");
+
+  protected void createJspTextNode(final List<Block> localResult, final ASTNode child, final Indent indent) {
+  }
+
+  @Nullable
+  protected static ASTNode findChildAfter(@NotNull final ASTNode child, final int endOffset) {
+    TreeElement fileNode = TreeUtil.getFileElement((TreeElement)child);
+    final LeafElement leaf = fileNode.findLeafElementAt(endOffset);
+    if (leaf != null && leaf.getStartOffset() == endOffset && endOffset > 0) {
+      return fileNode.findLeafElementAt(endOffset - 1);
+    }
+    return leaf;
+  }
+
+  public boolean isLeaf() {
+    return (isComment(myNode)) ||
+           myNode.getElementType() == TokenType.WHITE_SPACE ||
+           myNode.getElementType() == XmlElementType.XML_DATA_CHARACTERS ||
+           myNode.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE_TOKEN;
+  }
+
+  private static  boolean isComment(final ASTNode node) {
+    final PsiElement psiElement = SourceTreeToPsiMap.treeElementToPsi(node);
+    if (psiElement instanceof PsiComment) return true;
+    final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(psiElement.getLanguage());
+    if (parserDefinition == null) return false;
+    final TokenSet commentTokens = parserDefinition.getCommentTokens();
+    return commentTokens.contains(node.getElementType());
+  }
+
+  public void setXmlFormattingPolicy(final XmlFormattingPolicy xmlFormattingPolicy) {
+    myXmlFormattingPolicy = xmlFormattingPolicy;
+  }
+
+  protected boolean buildInjectedPsiBlocks(List<Block> result, final ASTNode child, Wrap wrap, Alignment alignment, Indent indent) {
+    if (myInjectedBlockBuilder.addInjectedBlocks(result, child, wrap, alignment, indent)) {
+      return true;
+    }
+
+    PsiFile containingFile = child.getPsi().getContainingFile();
+    FileViewProvider fileViewProvider = containingFile.getViewProvider();
+
+    if (fileViewProvider instanceof TemplateLanguageFileViewProvider) {
+      Language templateLanguage = ((TemplateLanguageFileViewProvider)fileViewProvider).getTemplateDataLanguage();
+      PsiElement at = fileViewProvider.findElementAt(child.getStartOffset(), templateLanguage);
+
+      if (at instanceof XmlToken) {
+        at = at.getParent();
+      }
+
+      // TODO: several comments
+      if (at instanceof PsiComment &&
+          at.getTextRange().equals(child.getTextRange()) &&
+          at.getNode() != child) {
+        return buildInjectedPsiBlocks(result, at.getNode(), wrap, alignment, indent);
+      }
+    }
+
+    return false;
+  }
+
+  public boolean isCDATAStart() {
+    return myNode.getElementType() == XmlElementType.XML_CDATA_START;
+  }
+
+  public boolean isCDATAEnd() {
+    return myNode.getElementType() == XmlElementType.XML_CDATA_END;
+  }
+
+  public static boolean containsWhiteSpacesOnly(ASTNode node) {
+    WhiteSpaceFormattingStrategy strategy =  WhiteSpaceFormattingStrategyFactory.getStrategy(node.getPsi().getLanguage());
+    String nodeText = node.getText();
+    int length = nodeText.length();
+    return strategy.check(nodeText, 0, length) >= length;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/AnotherLanguageBlockWrapper.java b/xml/impl/src/com/intellij/psi/formatter/xml/AnotherLanguageBlockWrapper.java
new file mode 100644
index 0000000..d33a2aa
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/AnotherLanguageBlockWrapper.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.Block;
+import com.intellij.formatting.ChildAttributes;
+import com.intellij.formatting.Indent;
+import com.intellij.formatting.Spacing;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.formatter.common.InjectedLanguageBlockWrapper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class AnotherLanguageBlockWrapper extends AbstractXmlBlock{
+  private final InjectedLanguageBlockWrapper myInjectedBlock;
+  private final Indent myIndent;
+
+  public AnotherLanguageBlockWrapper(final ASTNode node,
+                                     final XmlFormattingPolicy policy,
+                                     final Block original, final Indent indent,
+                                     final int offset,
+                                     @Nullable TextRange range) {
+    super(node, original.getWrap(), original.getAlignment(), policy, false);
+    myInjectedBlock = new InjectedLanguageBlockWrapper(original, offset, range, null);
+    myIndent = indent;
+  }
+
+  public Indent getIndent() {
+    return myIndent;
+  }
+
+  public boolean insertLineBreakBeforeTag() {
+    return false;
+  }
+
+  public boolean removeLineBreakBeforeTag() {
+    return false;
+  }
+
+  public boolean isTextElement() {
+    return true;
+  }
+
+  protected List<Block> buildChildren() {
+    return myInjectedBlock.getSubBlocks();
+  }
+
+  @NotNull
+  public TextRange getTextRange() {
+    return myInjectedBlock.getTextRange();
+  }
+
+  @Nullable
+  public Spacing getSpacing(Block child1, @NotNull Block child2) {
+    return myInjectedBlock.getSpacing(child1,  child2);
+  }
+
+  @NotNull
+  public ChildAttributes getChildAttributes(final int newChildIndex) {
+    return myInjectedBlock.getChildAttributes(newChildIndex);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/HtmlPolicy.java b/xml/impl/src/com/intellij/psi/formatter/xml/HtmlPolicy.java
new file mode 100644
index 0000000..48c1502
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/HtmlPolicy.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.FormattingDocumentModel;
+import com.intellij.formatting.WrapType;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.impl.source.tree.LeafElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class HtmlPolicy extends XmlFormattingPolicy {
+  
+  protected final CodeStyleSettings mySettings;
+
+  public HtmlPolicy(final CodeStyleSettings settings, final FormattingDocumentModel documentModel) {
+    super(documentModel);
+    mySettings = settings;
+
+  }
+
+  public boolean indentChildrenOf(final XmlTag parentTag) {
+    if (parentTag == null) {
+      return true;
+    }
+    final PsiElement firstChild = findFirstNonEmptyChild(parentTag);
+
+    if (firstChild == null) {
+      return false;
+    }
+
+    if (firstChild.getNode().getElementType() != XmlElementType.XML_START_TAG_START) {
+      return false;
+    }
+
+    if (mySettings.HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES > 0 && getLines(parentTag) > mySettings.HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES)
+    {
+      return false;
+    }
+    else {
+      return !checkName(parentTag, mySettings.HTML_DO_NOT_INDENT_CHILDREN_OF);
+    }
+  }
+
+  private PsiElement findFirstNonEmptyChild(final XmlTag parentTag) {
+    PsiElement result = parentTag.getFirstChild();
+    while (result != null && result.getTextLength() == 0) {
+      result = result.getNextSibling();
+    }
+    return result;
+  }
+
+  private int getLines(final XmlTag parentTag) {
+    final TextRange textRange = parentTag.getTextRange();
+    return myDocumentModel.getLineNumber(textRange.getEndOffset()) - myDocumentModel.getLineNumber(textRange.getStartOffset());
+  }
+
+  public boolean insertLineBreakBeforeTag(final XmlTag xmlTag) {
+    PsiElement prev = xmlTag.getPrevSibling();
+    if (prev == null) return false;
+    ASTNode prevNode = SourceTreeToPsiMap.psiElementToTree(prev);
+    while (prevNode != null && containsWhiteSpacesOnly(prevNode)) {
+      prevNode = prevNode.getTreePrev();
+    }
+    if (prevNode == null) return false;
+    if (!(SourceTreeToPsiMap.treeElementToPsi(prevNode)instanceof XmlTag)) return false;
+    return checkName(xmlTag, mySettings.HTML_ELEMENTS_TO_INSERT_NEW_LINE_BEFORE);
+  }
+
+  @Override
+  public boolean insertLineBreakBeforeFirstAttribute(XmlAttribute attribute) {
+    return false;
+  }
+
+  @Override
+  public boolean insertLineBreakAfterTagBegin(XmlTag tag) {
+    return false;
+  }
+
+  private boolean containsWhiteSpacesOnly(final ASTNode node) {
+    if (node == null) return false;
+    if (node.getElementType() == TokenType.WHITE_SPACE) return true;
+    if (node instanceof LeafElement) return false;
+    ASTNode child = node.getFirstChildNode();
+    while (child != null) {
+      if (!containsWhiteSpacesOnly(child)) return false;
+      child = child.getTreeNext();
+    }
+    return true;
+  }
+
+  public boolean removeLineBreakBeforeTag(final XmlTag xmlTag) {
+    return checkName(xmlTag, mySettings.HTML_ELEMENTS_TO_REMOVE_NEW_LINE_BEFORE);
+  }
+
+  protected boolean checkName(XmlTag tag, String option) {
+    if (option == null) return false;
+    for (String name : getTagNames(option)) {
+      if (name.trim().equalsIgnoreCase(tag.getName())) return true;
+    }
+    return false;
+  }
+
+  private final Map<String, String[]> myCachedSplits = new HashMap<String, String[]>();
+
+  private String[] getTagNames(final String option) {
+    String[] splits = myCachedSplits.get(option);
+    if (splits == null) {
+      splits = option.split(",");
+      myCachedSplits.put(option, splits);
+    }
+    return splits;
+  }
+
+  public boolean keepWhiteSpacesInsideTag(final XmlTag tag) {
+    return checkName(tag, mySettings.HTML_KEEP_WHITESPACES_INSIDE) || "jsp:attribute".equals(tag.getName());
+  }
+
+  public WrapType getWrappingTypeForTagEnd(final XmlTag xmlTag) {
+    return shouldBeWrapped(xmlTag) ? WrapType.ALWAYS : WrapType.NORMAL;
+  }
+
+  public WrapType getWrappingTypeForTagBegin(final XmlTag tag) {
+    if (shouldBeWrapped(tag)) {
+      return WrapType.ALWAYS;
+    }
+
+    if (!isInlineTag(tag)) {
+
+      if (checkName(tag, mySettings.HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT)) {
+        if (hasInlineContentOnly(tag)) return WrapType.NORMAL;
+      }
+
+      return WrapType.ALWAYS;
+    }
+
+    return WrapType.NORMAL;
+  }
+
+  private boolean hasInlineContentOnly(final XmlTag tag) {
+    final XmlTag[] tags = tag.getSubTags();
+    for (int i = 0; i < tags.length; i++) {
+      XmlTag xmlTag = tags[i];
+      if (!isInlineTag(xmlTag)) return false;
+      if (!hasInlineContentOnly(xmlTag)) return false;
+    }
+
+    return true;
+  }
+
+  protected boolean isInlineTag(final XmlTag tag) {
+    return checkName(tag, mySettings.HTML_INLINE_ELEMENTS);
+  }
+
+  protected boolean shouldBeWrapped(final XmlTag tag) {
+    return false;
+  }
+
+  public boolean isTextElement(XmlTag tag) {
+    return isInlineTag(tag);
+  }                               
+
+  public int getTextWrap(final XmlTag tag) {
+    return mySettings.HTML_TEXT_WRAP;
+  }
+
+  public int getAttributesWrap() {
+    return mySettings.HTML_ATTRIBUTE_WRAP;
+  }
+
+  public boolean getShouldAlignAttributes() {
+    return mySettings.HTML_ALIGN_ATTRIBUTES;
+  }
+
+  public boolean getShouldAlignText() {
+    return mySettings.HTML_ALIGN_TEXT;
+  }
+
+  public boolean getShouldKeepWhiteSpaces() {
+    return mySettings.HTML_KEEP_WHITESPACES;
+  }
+
+  public boolean getShouldAddSpaceAroundEqualityInAttribute() {
+    return mySettings.HTML_SPACE_AROUND_EQUALITY_IN_ATTRINUTE;
+  }
+
+  public boolean getShouldAddSpaceAroundTagName() {
+    return mySettings.HTML_SPACE_AFTER_TAG_NAME;
+  }
+
+  public int getKeepBlankLines() {
+    return mySettings.HTML_KEEP_BLANK_LINES;
+  }
+
+  public boolean getShouldKeepLineBreaks() {
+    return mySettings.HTML_KEEP_LINE_BREAKS;
+  }
+
+  public boolean getShouldKeepLineBreaksInText() {
+    return mySettings.HTML_KEEP_LINE_BREAKS_IN_TEXT;
+  }
+
+  @Override
+  public boolean getKeepWhiteSpacesInsideCDATA() {
+    return true;
+  }
+
+  @Override
+  public int getWhiteSpaceAroundCDATAOption() {
+    return XmlCodeStyleSettings.WS_AROUND_CDATA_PRESERVE;
+  }
+
+  public CodeStyleSettings getSettings() {
+    return mySettings;
+  }
+
+  public boolean addSpaceIntoEmptyTag() {
+    return mySettings.HTML_SPACE_INSIDE_EMPTY_TAG;
+  }
+
+  public boolean shouldSaveSpacesBetweenTagAndText() {
+    return true;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/ReadOnlyBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/ReadOnlyBlock.java
new file mode 100644
index 0000000..7898f77
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/ReadOnlyBlock.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.formatting.Block;
+import com.intellij.formatting.Spacing;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ReadOnlyBlock extends AbstractBlock {
+  private static final ArrayList<Block> EMPTY = new ArrayList<Block>();
+
+  public ReadOnlyBlock(ASTNode node) {
+    super(node, null, null);
+  }
+
+  public Spacing getSpacing(Block child1, @NotNull Block child2) {
+    return null;
+  }
+
+  public boolean isLeaf() {
+    return true;
+  }
+
+  protected List<Block> buildChildren() {
+    return EMPTY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/SyntheticBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/SyntheticBlock.java
new file mode 100644
index 0000000..33e06e3
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/SyntheticBlock.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class SyntheticBlock extends AbstractSyntheticBlock implements Block, ReadOnlyBlockContainer {
+  private final List<Block> mySubBlocks;
+  private final Indent myChildIndent;
+
+  public SyntheticBlock(final List<Block> subBlocks, final Block parent, final Indent indent, XmlFormattingPolicy policy, final Indent childIndent) {
+    super(subBlocks, parent, policy, indent);
+    mySubBlocks = subBlocks;
+    myChildIndent = childIndent;
+  }
+
+  @NotNull
+  public TextRange getTextRange() {
+    return calculateTextRange(mySubBlocks);
+  }
+
+  @NotNull
+  public List<Block> getSubBlocks() {
+    return mySubBlocks;
+  }
+
+  public Spacing getSpacing(Block child1, @NotNull Block child2) {
+    if (child1 instanceof ReadOnlyBlock || child2 instanceof ReadOnlyBlock) {
+      return Spacing.getReadOnlySpacing();
+    }
+    if (!(child1 instanceof AbstractXmlBlock) || !(child2 instanceof AbstractXmlBlock)) {
+      return null;
+    }
+    final ASTNode node1 = ((AbstractBlock)child1).getNode();
+    final ASTNode node2 = ((AbstractBlock)child2).getNode();
+
+    final IElementType type1 = node1.getElementType();
+    final IElementType type2 = node2.getElementType();
+
+    boolean firstIsText = isTextFragment(node1);
+    boolean secondIsText = isTextFragment(node2);
+
+    if (((AbstractXmlBlock)child1).isPreserveSpace() && ((AbstractXmlBlock)child2).isPreserveSpace()) {
+      return Spacing.getReadOnlySpacing();
+    }
+
+    if (type1 == XmlElementType.XML_CDATA_START || type2 == XmlElementType.XML_CDATA_END) {
+      if (myXmlFormattingPolicy.getKeepWhiteSpacesInsideCDATA()) {
+        return Spacing.getReadOnlySpacing();
+      }
+      if (type1 == XmlElementType.XML_CDATA_START && type2 == XmlElementType.XML_CDATA_END) {
+        return Spacing.createSpacing(0, 0, 0, myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines()); 
+      }
+      if (type1 == XmlElementType.XML_CDATA_START && child2 instanceof AnotherLanguageBlockWrapper ||
+          type2 == XmlElementType.XML_CDATA_END && child1 instanceof AnotherLanguageBlockWrapper) {
+        return Spacing.createSpacing(0, 0, 1, myXmlFormattingPolicy.getShouldKeepLineBreaks(), 0);
+      }
+    }
+
+    boolean firstIsTag = node1.getPsi() instanceof XmlTag && !firstIsText;
+    boolean secondIsTag = node2.getPsi() instanceof XmlTag && !secondIsText;
+
+    boolean firstIsEntityRef = isEntityRef(node1);
+    boolean secondIsEntityRef = isEntityRef(node2);
+
+    if (isSpaceInText(firstIsTag, secondIsTag, firstIsText, secondIsText) && keepWhiteSpaces()) {
+        return Spacing.getReadOnlySpacing();
+    }
+
+    if (firstIsEntityRef || secondIsEntityRef) {
+      return Spacing.createSafeSpacing(myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if (type2 == XmlElementType.XML_EMPTY_ELEMENT_END && myXmlFormattingPolicy.addSpaceIntoEmptyTag()) {
+      return Spacing.createSpacing(1, 1, 0,
+                                   myXmlFormattingPolicy.getShouldKeepLineBreaks(),
+                                   myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if (secondIsTag && myXmlFormattingPolicy.keepWhiteSpacesInsideTag((XmlTag)node2.getPsi()) && node2.textContains('\n')) {
+      return Spacing.getReadOnlySpacing();
+    }
+
+    if (isXmlTagName(type1, type2)){
+      final int spaces = shouldAddSpaceAroundTagName(node1, node2) ? 1 : 0;
+      return Spacing.createSpacing(spaces, spaces, 0, myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if (type2 == XmlElementType.XML_ATTRIBUTE) {
+      int minLineFeeds = 0;
+
+      if (type1 == XmlTokenType.XML_NAME) {
+        final PsiElement psi2 = node2.getPsi();
+        minLineFeeds = psi2 instanceof XmlAttribute &&
+                       myXmlFormattingPolicy.insertLineBreakBeforeFirstAttribute((XmlAttribute)psi2)
+                       ? 1 : 0;
+      }
+      return Spacing.createSpacing(1, 1, minLineFeeds, myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if (((AbstractXmlBlock)child1).isTextElement() && ((AbstractXmlBlock)child2).isTextElement()) {
+      return Spacing.createSafeSpacing(myXmlFormattingPolicy.getShouldKeepLineBreaksInText(), myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if (firstIsTag && insertLineFeedAfter((XmlTag)node1.getPsi())) {
+      return Spacing.createSpacing(0, 0, 1, true, myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if ((firstIsText || firstIsTag) && secondIsTag) {
+      //<tag/>text <tag/></tag>
+      if (((AbstractXmlBlock)child2).insertLineBreakBeforeTag()) {
+        return Spacing.createSpacing(0, Integer.MAX_VALUE, 2, myXmlFormattingPolicy.getShouldKeepLineBreaks(),
+                                     myXmlFormattingPolicy.getKeepBlankLines());
+      } else if (((AbstractXmlBlock)child2).removeLineBreakBeforeTag()) {
+        return Spacing.createSpacing(0, Integer.MAX_VALUE, 0, myXmlFormattingPolicy.getShouldKeepLineBreaks(),
+                                     myXmlFormattingPolicy.getKeepBlankLines());
+      }
+    }
+
+    final boolean saveSpacesBetweenTagAndText =
+      myXmlFormattingPolicy.shouldSaveSpacesBetweenTagAndText() && child1.getTextRange().getEndOffset() < child2.getTextRange().getStartOffset();
+
+    if (firstIsTag && secondIsText) {     //<tag/>-text
+
+      if (((AbstractXmlBlock)child1).isTextElement() || saveSpacesBetweenTagAndText) {
+        return Spacing.createSafeSpacing(true, myXmlFormattingPolicy.getKeepBlankLines());
+      } else {
+        return Spacing.createSpacing(0, 0, 0, true, myXmlFormattingPolicy.getKeepBlankLines());
+      }
+    }
+
+    if ( firstIsText && secondIsTag) {     //text-<tag/>
+      if (((AbstractXmlBlock)child2).isTextElement() || saveSpacesBetweenTagAndText) {
+        return Spacing.createSafeSpacing(true, myXmlFormattingPolicy.getKeepBlankLines());
+      } else {
+        return Spacing.createSpacing(0, 0, 0, true, myXmlFormattingPolicy.getKeepBlankLines());
+      }
+    }
+
+    if (firstIsTag && secondIsTag) {//<tag/><tag/>
+      return Spacing.createSpacing(0, Integer.MAX_VALUE, 0, true,
+                                   myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    return Spacing.createSpacing(0, Integer.MAX_VALUE, 0, myXmlFormattingPolicy.getShouldKeepLineBreaksInText(), myXmlFormattingPolicy.getKeepBlankLines());
+  }
+
+  private boolean isEntityRef(final ASTNode node) {
+    return node.getElementType() == XmlElementType.XML_ENTITY_REF;
+  }
+
+  private boolean shouldAddSpaceAroundTagName(final ASTNode node1, final ASTNode node2) {
+    if (node1.getElementType() == XmlElementType.XML_START_TAG_START && node1.textContains('%')) return true;
+    if (node2.getElementType() == XmlElementType.XML_EMPTY_ELEMENT_END && node2.textContains('%')) return true;
+    return myXmlFormattingPolicy.getShouldAddSpaceAroundTagName();
+  }
+
+  private boolean isSpaceInText(final boolean firstIsTag,
+                                final boolean secondIsTag,
+                                final boolean firstIsText,
+                                final boolean secondIsText) {
+    return
+      (firstIsText && secondIsText)
+      || (firstIsTag && secondIsTag)
+      || (firstIsTag && secondIsText)
+      || (firstIsText && secondIsTag);
+  }
+
+  private boolean keepWhiteSpaces() {
+    return (myXmlFormattingPolicy.keepWhiteSpacesInsideTag( getTag()) || myXmlFormattingPolicy.getShouldKeepWhiteSpaces());
+  }
+
+  protected boolean isTextFragment(final ASTNode node) {
+    final ASTNode parent = node.getTreeParent();
+    return parent != null && parent.getElementType() == XmlElementType.XML_TEXT
+           || node.getElementType() == XmlElementType.XML_DATA_CHARACTERS
+           
+      ;
+  }
+
+  @NotNull
+  public ChildAttributes getChildAttributes(final int newChildIndex) {
+    if (isOuterLanguageBlock()) return ChildAttributes.DELEGATE_TO_NEXT_CHILD;
+    final List<Block> subBlocks = getSubBlocks();
+    final int prevBlockIndex = newChildIndex - 1;
+    if (prevBlockIndex >= 0 && prevBlockIndex < subBlocks.size()) {
+      final Block prevBlock = subBlocks.get(newChildIndex - 1);
+      if (isAttributeBlock(prevBlock)) {
+        return new ChildAttributes(myChildIndent, prevBlock.getAlignment());
+      }
+    }
+    return new ChildAttributes(myChildIndent, null);
+  }
+
+  private boolean isAttributeBlock(final Block block) {
+    if (block instanceof XmlBlock) {
+      return ((XmlBlock)block).getNode().getElementType() == XmlElementType.XML_ATTRIBUTE;
+    }
+    return false;
+  }
+
+  public boolean isIncomplete() {
+    return getSubBlocks().get(getSubBlocks().size() - 1).isIncomplete();
+  }
+
+  public boolean endsWithAttribute() {
+    return isAttributeBlock(getSubBlocks().get(getSubBlocks().size() - 1));
+  }
+
+  public Indent getChildIndent() {
+    return myChildIndent;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java
new file mode 100644
index 0000000..f4a6dc5
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.templateLanguages.OuterLanguageElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.SmartList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class XmlBlock extends AbstractXmlBlock {
+  private final Indent myIndent;
+  private final TextRange myTextRange;
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.xml.XmlBlock");
+
+  public XmlBlock(final ASTNode node,
+                    final Wrap wrap,
+                    final Alignment alignment,
+                    final XmlFormattingPolicy policy,
+                    final Indent indent,
+                    final TextRange textRange) {
+    this(node, wrap, alignment, policy, indent, textRange, false);
+  }
+
+  public XmlBlock(final ASTNode node,
+                  final Wrap wrap,
+                  final Alignment alignment,
+                  final XmlFormattingPolicy policy,
+                  final Indent indent,
+                  final TextRange textRange,
+                  final boolean preserveSpace) {
+    super(node, wrap, alignment, policy, preserveSpace);
+    myIndent = indent;
+    myTextRange = textRange;
+  }
+
+  @NotNull
+  public TextRange getTextRange() {
+    if (myTextRange != null && !(isCDATAStart() || isCDATAEnd())) {
+      return myTextRange;
+    }
+    else {
+      return super.getTextRange();
+    }
+  }
+
+  protected List<Block> buildChildren() {
+
+    //
+    // Fix for EA-19269:
+    // Split XML attribute value to the value itself and delimiters (needed for the case when it contains
+    // template language tags inside).
+    //
+    if (myNode.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE) {
+      return splitAttribute(myNode, myXmlFormattingPolicy);
+    }
+
+    if (myNode.getElementType() == XmlElementType.XML_COMMENT) {
+      List<Block> result = new SmartList<Block>();
+      if (buildInjectedPsiBlocks(result, myNode, myWrap, null, Indent.getNoneIndent())) {
+        return result;
+      }
+      return splitComment();
+    }
+
+    if (myNode.getElementType() == XmlElementType.XML_TEXT) {
+      if (myXmlFormattingPolicy.getShouldKeepWhiteSpaces()) {
+        return EMPTY;
+      }
+
+      final ASTNode treeParent = myNode.getTreeParent();
+      final XmlTag tag = getTag(treeParent);
+      if (tag != null) {
+        if (myXmlFormattingPolicy.keepWhiteSpacesInsideTag(tag)) {
+          return EMPTY;
+        }
+      }
+    }
+
+    if (myNode.getFirstChildNode() != null) {
+      final ArrayList<Block> result = new ArrayList<Block>(5);
+      ASTNode child = myNode.getFirstChildNode();
+      while (child != null) {
+        if (!containsWhiteSpacesOnly(child) && child.getTextLength() > 0) {
+          child = processChild(result, child, getDefaultWrap(child), null, getChildDefaultIndent());
+        }
+        if (child != null) {
+          LOG.assertTrue(child.getTreeParent() == myNode);
+          child = child.getTreeNext();
+        }
+      }
+      return result;
+    }
+    else {
+      return EMPTY;
+    }
+  }
+
+
+  private List<Block> splitAttribute(ASTNode node, XmlFormattingPolicy formattingPolicy) {
+    final ArrayList<Block> result = new ArrayList<Block>(3);
+    ASTNode child = node.getFirstChildNode();
+    while (child != null) {
+      if (child.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE_START_DELIMITER ||
+          child.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE_END_DELIMITER) {
+        result.add(new XmlBlock(child, null, null, formattingPolicy, null, null, isPreserveSpace()));
+      }
+      else if (!child.getPsi().getLanguage().isKindOf(XMLLanguage.INSTANCE) && containsOuterLanguageElement(child)) {
+        // Fix for EA-20311:
+        // In case of another embedded language create a splittable XML block which can be
+        // merged with other language's code blocks.
+        createLeafBlocks(child, result);
+      }
+      else if (child.getElementType() != TokenType.ERROR_ELEMENT || child.getFirstChildNode() != null) {
+        result.add(new ReadOnlyBlock(child));
+      }
+      child = child.getTreeNext();
+    }
+    return result;
+  }
+
+  private void createLeafBlocks(ASTNode node, List<Block> result) {
+    if (node instanceof OuterLanguageElement) {
+      processChild(result, node, null, null, null);
+      return;
+    }
+
+    ASTNode child = node.getFirstChildNode();
+    if (child == null && !(node instanceof PsiWhiteSpace) && node.getElementType() != TokenType.ERROR_ELEMENT) {
+      result.add(new ReadOnlyBlock(node));
+      return;
+    }
+    while (child != null) {
+      createLeafBlocks(child, result);
+      child = child.getTreeNext();
+    }
+  }
+
+
+  private static boolean containsOuterLanguageElement(ASTNode node) {
+    if (node instanceof OuterLanguageElement) {
+      return true;
+    }
+    ASTNode child = node.getFirstChildNode();
+    while (child != null) {
+      if (child instanceof OuterLanguageElement) {
+        return true;
+      }
+      if (containsOuterLanguageElement(child)) return true;
+      child = child.getTreeNext();
+    }
+    return false;
+  }
+
+
+  private List<Block> splitComment() {
+    if (myNode.getElementType() != XmlElementType.XML_COMMENT) return EMPTY;
+    final ArrayList<Block> result = new ArrayList<Block>(3);
+    ASTNode child = myNode.getFirstChildNode();
+    boolean hasOuterLangElements = false;
+    while (child != null) {
+      if (child instanceof OuterLanguageElement) {
+        hasOuterLangElements = true;
+      }
+      result.add(new XmlBlock(child, null, null, myXmlFormattingPolicy, getChildIndent(), null, isPreserveSpace()));
+      child = child.getTreeNext();
+    }
+    if (hasOuterLangElements) {
+      return result;
+    }
+    else {
+      return EMPTY;
+    }
+  }
+
+  protected @Nullable Wrap getDefaultWrap(ASTNode node) {
+    return null;
+  }
+
+  @Nullable
+  protected Indent getChildDefaultIndent() {
+    if (myNode.getElementType() == XmlElementType.HTML_DOCUMENT) {
+      return Indent.getNoneIndent();
+    }
+    if (myNode.getElementType() == TokenType.DUMMY_HOLDER) {
+      return Indent.getNoneIndent();
+    }
+    if (myNode.getElementType() == XmlElementType.XML_PROLOG) {
+      return Indent.getNoneIndent();
+    }
+    else {
+      return null;
+    }
+  }
+
+  public Spacing getSpacing(Block child1, @NotNull Block child2) {
+    if (!(child1 instanceof AbstractBlock) || !(child2 instanceof AbstractBlock)) {
+      return null;
+    }
+
+    final IElementType elementType = myNode.getElementType();
+    final ASTNode node1 = ((AbstractBlock)child1).getNode();
+    final IElementType type1 = node1.getElementType();
+    final ASTNode node2 = ((AbstractBlock)child2).getNode();
+    final IElementType type2 = node2.getElementType();
+
+    if ((isXmlTag(node2) || type2 == XmlElementType.XML_END_TAG_START || type2 == XmlElementType.XML_TEXT) && myXmlFormattingPolicy
+      .getShouldKeepWhiteSpaces()) {
+      return Spacing.getReadOnlySpacing();
+    }
+
+    if (elementType == XmlElementType.XML_TEXT) {
+      return getSpacesInsideText(type1, type2);
+
+    }
+    else if (elementType == XmlElementType.XML_ATTRIBUTE) {
+      return getSpacesInsideAttribute(type1, type2);
+    }
+
+    if (type1 == XmlElementType.XML_PROLOG) {
+      return createDefaultSpace(true, false);
+    }
+
+    if (elementType == XmlElementType.XML_DOCTYPE) {
+      return createDefaultSpace(true, false);
+    }
+
+    return createDefaultSpace(false, false);
+  }
+
+  private Spacing getSpacesInsideAttribute(final IElementType type1, final IElementType type2) {
+    if (type1 == XmlElementType.XML_EQ || type2 == XmlElementType.XML_EQ) {
+      int spaces = myXmlFormattingPolicy.getShouldAddSpaceAroundEqualityInAttribute() ? 1 : 0;
+      return Spacing
+        .createSpacing(spaces, spaces, 0, myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+    }
+    else {
+      return createDefaultSpace(false, false);
+    }
+  }
+
+  private Spacing getSpacesInsideText(final IElementType type1, final IElementType type2) {
+    if (type1 == XmlElementType.XML_DATA_CHARACTERS && type2 == XmlElementType.XML_DATA_CHARACTERS) {
+      return Spacing
+        .createSpacing(1, 1, 0, myXmlFormattingPolicy.getShouldKeepLineBreaksInText(), myXmlFormattingPolicy.getKeepBlankLines());
+    }
+    else {
+      return createDefaultSpace(false, true);
+    }
+  }
+
+  public Indent getIndent() {
+    if (myNode.getElementType() == XmlElementType.XML_PROLOG || myNode.getElementType() == XmlElementType.XML_DOCTYPE ||
+        SourceTreeToPsiMap.treeElementToPsi(myNode) instanceof XmlDocument) {
+      return Indent.getNoneIndent();
+    }
+    return myIndent;
+  }
+
+  public boolean insertLineBreakBeforeTag() {
+    return false;
+  }
+
+  public boolean removeLineBreakBeforeTag() {
+    return false;
+  }
+
+  public boolean isTextElement() {
+    return myNode.getElementType() == XmlElementType.XML_TEXT || myNode.getElementType() == XmlElementType.XML_DATA_CHARACTERS ||
+           myNode.getElementType() == XmlElementType.XML_CHAR_ENTITY_REF;
+  }
+
+  @Override
+  @NotNull
+  public ChildAttributes getChildAttributes(final int newChildIndex) {
+    if (myNode.getPsi() instanceof PsiFile) {
+      return new ChildAttributes(Indent.getNoneIndent(), null);
+    }
+    else {
+      return super.getChildAttributes(newChildIndex);
+    }
+  }
+
+  public XmlFormattingPolicy getPolicy() {
+    return myXmlFormattingPolicy;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlCodeStyleSettings.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlCodeStyleSettings.java
new file mode 100644
index 0000000..50f7c6c
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlCodeStyleSettings.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
+
+/**
+ * Moved from CodeStyleSettings
+ * @author Rustam Vishnyakov
+ */
+public class XmlCodeStyleSettings extends CustomCodeStyleSettings {
+
+  public final static int WS_AROUND_CDATA_PRESERVE = 0;
+  public final static int WS_AROUND_CDATA_NONE = 1;
+  public final static int WS_AROUND_CDATA_NEW_LINES = 2;
+
+  public boolean XML_KEEP_WHITESPACES = false;
+  public int XML_ATTRIBUTE_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
+  public int XML_TEXT_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
+
+  public boolean XML_KEEP_LINE_BREAKS = true;
+  public boolean XML_KEEP_LINE_BREAKS_IN_TEXT = true;
+  public int XML_KEEP_BLANK_LINES = 2;
+
+  public boolean XML_ALIGN_ATTRIBUTES = true;
+  public boolean XML_ALIGN_TEXT = false;
+
+  public boolean XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE = false;
+  public boolean XML_SPACE_AFTER_TAG_NAME = false;
+  public boolean XML_SPACE_INSIDE_EMPTY_TAG = false;
+
+  public boolean XML_KEEP_WHITE_SPACES_INSIDE_CDATA = false;
+  public int XML_WHITE_SPACE_AROUND_CDATA = WS_AROUND_CDATA_PRESERVE;
+
+  public boolean XML_LEGACY_SETTINGS_IMPORTED = false;
+
+  public XmlCodeStyleSettings(CodeStyleSettings container) {
+    super("XML", container);
+  }
+
+  @Override
+  public void importLegacySettings() {
+    if (!XML_LEGACY_SETTINGS_IMPORTED) {
+      CodeStyleSettings container = getContainer();
+      CodeStyleSettings defaults = new CodeStyleSettings();
+      XML_KEEP_WHITESPACES = container.XML_KEEP_WHITESPACES;
+      XML_ATTRIBUTE_WRAP = container.XML_ATTRIBUTE_WRAP;
+      XML_TEXT_WRAP = container.XML_TEXT_WRAP;
+      XML_KEEP_LINE_BREAKS = container.XML_KEEP_LINE_BREAKS;
+      XML_KEEP_LINE_BREAKS_IN_TEXT = container.XML_KEEP_LINE_BREAKS_IN_TEXT;
+      XML_KEEP_BLANK_LINES = container.XML_KEEP_BLANK_LINES;
+      XML_ALIGN_ATTRIBUTES = container.XML_ALIGN_ATTRIBUTES;
+      XML_ALIGN_TEXT = container.XML_ALIGN_TEXT;
+      XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE = container.XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE;
+      XML_SPACE_AFTER_TAG_NAME = container.XML_SPACE_AFTER_TAG_NAME;
+      XML_SPACE_INSIDE_EMPTY_TAG = container.XML_SPACE_INSIDE_EMPTY_TAG;
+      XML_KEEP_WHITE_SPACES_INSIDE_CDATA = container.XML_KEEP_WHITE_SPACES_INSIDE_CDATA;
+      XML_WHITE_SPACE_AROUND_CDATA = container.XML_WHITE_SPACE_AROUND_CDATA;
+
+      container.XML_KEEP_WHITESPACES = defaults.XML_KEEP_WHITESPACES ;
+      container.XML_ATTRIBUTE_WRAP = defaults.XML_ATTRIBUTE_WRAP;
+      container.XML_TEXT_WRAP = defaults.XML_TEXT_WRAP;
+      container.XML_KEEP_LINE_BREAKS = defaults.XML_KEEP_LINE_BREAKS;
+      container.XML_KEEP_LINE_BREAKS_IN_TEXT = defaults.XML_KEEP_LINE_BREAKS_IN_TEXT;
+      container.XML_KEEP_BLANK_LINES = defaults.XML_KEEP_BLANK_LINES;
+      container.XML_ALIGN_ATTRIBUTES = defaults.XML_ALIGN_ATTRIBUTES;
+      container.XML_ALIGN_TEXT = defaults.XML_ALIGN_TEXT;
+      container.XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE = defaults.XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE;
+      container.XML_SPACE_AFTER_TAG_NAME = defaults.XML_SPACE_AFTER_TAG_NAME;
+      container.XML_SPACE_INSIDE_EMPTY_TAG = defaults.XML_SPACE_INSIDE_EMPTY_TAG;
+      container.XML_KEEP_WHITE_SPACES_INSIDE_CDATA = defaults.XML_KEEP_WHITE_SPACES_INSIDE_CDATA;
+      container.XML_WHITE_SPACE_AROUND_CDATA = defaults.XML_WHITE_SPACE_AROUND_CDATA;
+
+      XML_LEGACY_SETTINGS_IMPORTED = true;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java
new file mode 100644
index 0000000..ae6fb0b
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.Block;
+import com.intellij.formatting.FormattingDocumentModel;
+import com.intellij.formatting.FormattingModelBuilder;
+import com.intellij.formatting.WrapType;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.lang.LanguageFormatting;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.containers.HashMap;
+
+import java.util.Map;
+
+public abstract class XmlFormattingPolicy {
+
+  private Map<Pair<PsiElement, Language>, Block> myRootToBlockMap = new HashMap<Pair<PsiElement, Language>, Block>();
+  private boolean myProcessJsp = true;
+  protected final FormattingDocumentModel myDocumentModel;
+  private boolean myProcessJavaTree = true;
+
+  protected XmlFormattingPolicy(final FormattingDocumentModel documentModel) {
+    myDocumentModel = documentModel;
+  }
+
+  public void copyFrom(final XmlFormattingPolicy xmlFormattingPolicy) {
+    myProcessJsp = xmlFormattingPolicy.myProcessJsp;
+    myRootToBlockMap.putAll(xmlFormattingPolicy.myRootToBlockMap);
+    myProcessJavaTree = xmlFormattingPolicy.processJavaTree(); 
+  }
+
+  public Block getOrCreateBlockFor(Pair<PsiElement, Language> root){
+    if (!myRootToBlockMap.containsKey(root)) {
+      myRootToBlockMap.put(root, createBlockFor(root));
+    }
+    return myRootToBlockMap.get(root);
+  }
+
+  private Block createBlockFor(final Pair<PsiElement,Language> root) {
+    final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(root.getSecond(), root.getFirst());
+    if (builder != null) {
+      final Block result = builder.createModel(root.getFirst(), getSettings()).getRootBlock();
+      if (result instanceof XmlBlock) {
+        final XmlFormattingPolicy policy = getPolicy((XmlBlock)result);
+        policy.setRootModels(myRootToBlockMap);
+        policy.doNotProcessJsp();
+      }
+      return result;
+    } else {
+      return null;
+    }
+  }
+
+  protected XmlFormattingPolicy getPolicy(final XmlBlock result) {
+    return result.getPolicy();
+  }
+
+  private void doNotProcessJsp() {
+    myProcessJsp = false;
+  }
+
+  private void setRootModels(final Map<Pair<PsiElement, Language>, Block> rootToBlockMap) {
+    myRootToBlockMap = rootToBlockMap;
+  }
+
+  public abstract WrapType getWrappingTypeForTagEnd(XmlTag xmlTag);
+
+  public abstract WrapType getWrappingTypeForTagBegin(final XmlTag tag);
+
+  public abstract boolean insertLineBreakBeforeTag(XmlTag xmlTag);
+
+  public abstract boolean insertLineBreakBeforeFirstAttribute(XmlAttribute attribute);
+
+  public abstract boolean insertLineBreakAfterTagBegin(XmlTag tag);
+
+  public abstract boolean removeLineBreakBeforeTag(XmlTag xmlTag);
+
+  public abstract boolean keepWhiteSpacesInsideTag(XmlTag tag);
+
+  public abstract boolean indentChildrenOf(XmlTag parentTag);
+
+  public abstract boolean isTextElement(XmlTag tag);
+
+  public abstract int getTextWrap(final XmlTag tag);
+
+  public abstract int getAttributesWrap();
+
+  public abstract boolean getShouldAlignAttributes();
+
+  public abstract boolean getShouldAlignText();
+
+  public abstract boolean getShouldKeepWhiteSpaces();
+
+  public abstract boolean getShouldAddSpaceAroundEqualityInAttribute();
+
+  public abstract boolean getShouldAddSpaceAroundTagName();
+
+  public abstract int getKeepBlankLines();
+
+  public abstract boolean getShouldKeepLineBreaks();
+
+  public abstract boolean getShouldKeepLineBreaksInText();
+
+  public abstract boolean getKeepWhiteSpacesInsideCDATA();
+
+  public abstract int getWhiteSpaceAroundCDATAOption();
+
+  public abstract CodeStyleSettings getSettings();
+
+  public boolean processJsp() {
+    return myProcessJsp;
+  }
+
+  public abstract boolean addSpaceIntoEmptyTag();
+
+  public void setRootBlock(final ASTNode node, final Block rootBlock) {
+    myRootToBlockMap.put(new Pair<PsiElement, Language>(node.getPsi(), node.getPsi().getLanguage()), rootBlock);
+  }
+
+  public FormattingDocumentModel getDocumentModel() {
+    return myDocumentModel;
+  }
+
+  public abstract boolean shouldSaveSpacesBetweenTagAndText();
+
+  public boolean processJavaTree() {
+    return myProcessJavaTree;
+  }
+
+
+  public void dontProcessJavaTree() {
+    myProcessJavaTree = false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlInjectedLanguageBlockBuilder.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlInjectedLanguageBlockBuilder.java
new file mode 100644
index 0000000..28aa043
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlInjectedLanguageBlockBuilder.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.Alignment;
+import com.intellij.formatting.Block;
+import com.intellij.formatting.Indent;
+import com.intellij.formatting.Wrap;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.formatter.common.InjectedLanguageBlockBuilder;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlElementType;
+import org.jetbrains.annotations.Nullable;
+
+/**
+* @author nik
+*/
+public class XmlInjectedLanguageBlockBuilder extends InjectedLanguageBlockBuilder {
+  private final XmlFormattingPolicy myXmlFormattingPolicy;
+
+  public XmlInjectedLanguageBlockBuilder(final XmlFormattingPolicy formattingPolicy) {
+    myXmlFormattingPolicy = formattingPolicy;
+  }
+
+  @Override
+  public Block createInjectedBlock(ASTNode node,
+                                   Block originalBlock,
+                                   Indent indent,
+                                   int offset,
+                                   TextRange range,
+                                   @Nullable Language language)
+  {
+    return new AnotherLanguageBlockWrapper(node, myXmlFormattingPolicy, originalBlock, indent, offset, range);
+  }
+
+  @Override
+  public Block createBlockBeforeInjection(ASTNode node, Wrap wrap, Alignment alignment, Indent indent, TextRange range) {
+    return new XmlBlock(node, wrap, alignment, myXmlFormattingPolicy, indent, range);
+  }
+
+  @Override
+  public Block createBlockAfterInjection(ASTNode node, Wrap wrap, Alignment alignment, Indent indent, TextRange range) {
+    return new XmlBlock(node, wrap, alignment, myXmlFormattingPolicy, indent, range);
+  }
+
+  @Override
+  public CodeStyleSettings getSettings() {
+    return myXmlFormattingPolicy.getSettings();
+  }
+
+  @Override
+  public boolean canProcessFragment(String text, final ASTNode injectionHost) {
+    IElementType type = injectionHost.getElementType();
+    if (type == XmlElementType.XML_TEXT) {
+      text = text.trim();
+      text = text.replace("<![CDATA[", "");
+      text = text.replace("]]>", "");
+    }
+    else if (type == XmlElementType.XML_COMMENT) {   // <!--[if IE]>, <![endif]--> of conditional comments injection
+      return true;
+    }
+
+    return text.length() == 0;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlPolicy.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlPolicy.java
new file mode 100644
index 0000000..40bb6ab
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlPolicy.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.FormattingDocumentModel;
+import com.intellij.formatting.WrapType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlText;
+
+public class XmlPolicy extends XmlFormattingPolicy{
+  private final CodeStyleSettings mySettings;
+  private final XmlCodeStyleSettings myXmlSettings;
+
+  public XmlPolicy(final CodeStyleSettings settings, final FormattingDocumentModel documentModel) {
+    super(documentModel);
+    mySettings = settings;
+    myXmlSettings = settings.getCustomSettings(XmlCodeStyleSettings.class);
+  }
+
+  public boolean indentChildrenOf(final XmlTag parentTag) {
+    return !(parentTag.getFirstChild() instanceof PsiErrorElement);
+  }
+
+  public boolean insertLineBreakBeforeTag(final XmlTag xmlTag) {
+    return false;
+  }
+
+  @Override
+  public boolean insertLineBreakBeforeFirstAttribute(XmlAttribute attribute) {
+    return false;
+  }
+
+  @Override
+  public boolean insertLineBreakAfterTagBegin(XmlTag tag) {
+    return false;
+  }
+
+  public boolean removeLineBreakBeforeTag(final XmlTag xmlTag) {
+    return false;
+  }
+
+  public WrapType getWrappingTypeForTagEnd(final XmlTag xmlTag) {
+    return xmlTag.getSubTags().length > 0 ? WrapType.ALWAYS
+           : WrapType.NORMAL;
+  }
+
+  public WrapType getWrappingTypeForTagBegin(final XmlTag tag) {
+    final PsiElement element = tag.getNextSibling();
+    if (element instanceof XmlText && !(element.getFirstChild() instanceof PsiWhiteSpace) && tag.getSubTags().length == 0) return WrapType.NORMAL;
+    return WrapType.ALWAYS;
+  }
+
+  public boolean isTextElement(XmlTag tag) {
+    return false;
+  }
+
+  public boolean keepWhiteSpacesInsideTag(final XmlTag tag) {
+    return false;
+  }
+
+  public int getTextWrap(final XmlTag tag) {
+    return myXmlSettings.XML_TEXT_WRAP;
+  }
+
+  public int getAttributesWrap() {
+    return myXmlSettings.XML_ATTRIBUTE_WRAP;
+  }
+
+  public boolean getShouldAlignAttributes() {
+    return myXmlSettings.XML_ALIGN_ATTRIBUTES;
+  }
+  public boolean getShouldAlignText() {
+    return myXmlSettings.XML_ALIGN_TEXT;
+  }
+
+  public boolean getShouldKeepWhiteSpaces() {
+    return myXmlSettings.XML_KEEP_WHITESPACES;
+  }
+
+  public boolean getShouldAddSpaceAroundEqualityInAttribute() {
+    return myXmlSettings.XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE;
+  }
+
+  public boolean getShouldAddSpaceAroundTagName() {
+    return myXmlSettings.XML_SPACE_AFTER_TAG_NAME;
+  }
+
+  public int getKeepBlankLines() {
+    return myXmlSettings.XML_KEEP_BLANK_LINES;
+  }
+
+  public boolean getShouldKeepLineBreaks() {
+    return myXmlSettings.XML_KEEP_LINE_BREAKS;
+  }
+
+  public boolean getShouldKeepLineBreaksInText() {
+    return myXmlSettings.XML_KEEP_LINE_BREAKS_IN_TEXT;
+  }
+
+  @Override
+  public boolean getKeepWhiteSpacesInsideCDATA() {
+    return myXmlSettings.XML_KEEP_WHITE_SPACES_INSIDE_CDATA;
+  }
+
+  @Override
+  public int getWhiteSpaceAroundCDATAOption() {
+    return myXmlSettings.XML_WHITE_SPACE_AROUND_CDATA;
+  }
+
+  public CodeStyleSettings getSettings() {
+    return mySettings;
+  }
+
+  public boolean addSpaceIntoEmptyTag() {
+    return myXmlSettings.XML_SPACE_INSIDE_EMPTY_TAG;
+  }
+
+  public boolean shouldSaveSpacesBetweenTagAndText() {
+    return false;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java
new file mode 100644
index 0000000..79b32c9
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.formatter.xml;
+
+import com.intellij.formatting.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class XmlTagBlock extends AbstractXmlBlock{
+  private final Indent myIndent;
+
+  public XmlTagBlock(final ASTNode node,
+                       final Wrap wrap,
+                       final Alignment alignment,
+                       final XmlFormattingPolicy policy,
+                       final Indent indent) {
+      super(node, wrap, alignment, policy, false);
+      myIndent = indent;
+  }
+
+  public XmlTagBlock(final ASTNode node,
+                     final Wrap wrap,
+                     final Alignment alignment,
+                     final XmlFormattingPolicy policy,
+                     final Indent indent,
+                     final boolean preserveSpace) {
+    super(node, wrap, alignment, policy, preserveSpace);
+    myIndent = indent;
+  }
+
+  protected List<Block> buildChildren() {
+    ASTNode child = myNode.getFirstChildNode();
+    final Wrap attrWrap = Wrap.createWrap(getWrapType(myXmlFormattingPolicy.getAttributesWrap()), false);
+    final Wrap textWrap = Wrap.createWrap(getWrapType(myXmlFormattingPolicy.getTextWrap(getTag())), true);
+    final Wrap tagBeginWrap = createTagBeginWrapping(getTag());
+    final Alignment attrAlignment = Alignment.createAlignment();
+    final Alignment textAlignment = Alignment.createAlignment();
+    final ArrayList<Block> result = new ArrayList<Block>(3);
+    ArrayList<Block> localResult = new ArrayList<Block>(1);
+
+    boolean insideTag = true;
+
+    while (child != null) {
+      if (!containsWhiteSpacesOnly(child) && child.getTextLength() > 0){
+
+        Wrap wrap = chooseWrap(child, tagBeginWrap, attrWrap, textWrap);
+        Alignment alignment = chooseAlignment(child, attrAlignment, textAlignment);
+
+        if (child.getElementType() == XmlElementType.XML_TAG_END) {
+          child = processChild(localResult,child, wrap, alignment, null);
+          result.add(createTagDescriptionNode(localResult));
+          localResult = new ArrayList<Block>(1);
+          insideTag = true;
+        }
+        else if (child.getElementType() == XmlElementType.XML_START_TAG_START) {
+          insideTag = false;
+          if (!localResult.isEmpty()) {
+            result.add(createTagContentNode(localResult));
+          }
+          localResult = new ArrayList<Block>(1);
+          child = processChild(localResult,child, wrap, alignment, null);
+        }
+        else if (child.getElementType() == XmlElementType.XML_END_TAG_START) {
+          insideTag = false;
+          if (!localResult.isEmpty()) {
+            result.add(createTagContentNode(localResult));
+            localResult = new ArrayList<Block>(1);
+          }
+          child = processChild(localResult,child, wrap, alignment, null);
+        } else if (child.getElementType() == XmlElementType.XML_EMPTY_ELEMENT_END) {
+          child = processChild(localResult,child, wrap, alignment, null);
+          result.add(createTagDescriptionNode(localResult));
+          localResult = new ArrayList<Block>(1);
+        }
+        else if (isJspxJavaContainingNode(child)) {
+          createJspTextNode(localResult, child, getChildIndent());
+        }
+        /*
+        else if (child.getElementType() == ElementType.XML_TEXT) {
+          child  = createXmlTextBlocks(localResult, child, wrap, alignment);
+        }
+        */
+        else {
+          final Indent indent;
+
+          if (isJspResult(localResult)) {
+            //indent = FormatterEx.getInstance().getNoneIndent();
+            indent = getChildrenIndent();
+          } else if (!insideTag) {
+            indent = null;
+          }
+          else {
+            indent = getChildrenIndent();
+          }
+
+          child = processChild(localResult,child, wrap, alignment, indent);
+        }
+      }
+      if (child != null) {
+        child = child.getTreeNext();
+      }
+    }
+
+    if (!localResult.isEmpty()) {
+      result.add(createTagContentNode(localResult));
+    }
+
+    return result;
+
+  }
+
+  protected boolean isJspResult(final ArrayList<Block> localResult) {
+    return false;
+  }
+
+  protected
+  @Nullable
+  ASTNode processChild(List<Block> result, final ASTNode child, final Wrap wrap, final Alignment alignment, final Indent indent) {
+    IElementType type = child.getElementType();
+    if (type == XmlElementType.XML_TEXT) {
+      final PsiElement parent = child.getPsi().getParent();
+
+      if (parent instanceof XmlTag && ((XmlTag)parent).getSubTags().length == 0) {
+        if (buildInjectedPsiBlocks(result, child, wrap, alignment, indent)) return child;
+      }
+      return createXmlTextBlocks(result, child, wrap, alignment);
+    } else if (type == XmlElementType.XML_COMMENT) {
+      if (buildInjectedPsiBlocks(result, child, wrap, alignment, indent)) return child;
+      return super.processChild(result, child, wrap, alignment, indent);
+    }
+    else {
+      return super.processChild(result, child, wrap, alignment, indent);
+    }
+  }
+
+  protected Indent getChildrenIndent() {
+    return myXmlFormattingPolicy.indentChildrenOf(getTag())
+           ? Indent.getNormalIndent()
+           : Indent.getNoneIndent();
+  }
+
+  public Indent getIndent() {
+    return myIndent;
+  }
+
+  private ASTNode createXmlTextBlocks(final List<Block> list, final ASTNode textNode, final Wrap wrap, final Alignment alignment) {
+    ASTNode child = textNode.getFirstChildNode();
+    return createXmlTextBlocks(list, textNode, child, wrap, alignment);
+  }
+
+  private ASTNode createXmlTextBlocks(final List<Block> list, final ASTNode textNode, ASTNode child,
+                                      final Wrap wrap,
+                                      final Alignment alignment
+  ) {
+    while (child != null) {
+      if (!XmlBlock.containsWhiteSpacesOnly(child) && child.getTextLength() > 0){
+        final Indent indent = getChildrenIndent();
+        child = processChild(list,child,  wrap, alignment, indent);
+        if (child == null) return child;
+        if (child.getTreeParent() != textNode) {
+          if (child.getTreeParent() != myNode) {
+            return createXmlTextBlocks(list, child.getTreeParent(), child.getTreeNext(), wrap, alignment);
+          } else {
+            return child;
+          }
+        }
+      }
+      child = child.getTreeNext();
+    }
+    return textNode;
+  }
+
+  private Block createTagContentNode(final ArrayList<Block> localResult) {
+    return createSyntheticBlock(localResult, getChildrenIndent());
+  }
+
+  protected Block createSyntheticBlock(final ArrayList<Block> localResult, final Indent childrenIndent) {
+    return new SyntheticBlock(localResult, this, Indent.getNoneIndent(), myXmlFormattingPolicy, childrenIndent);
+  }
+
+  private Block createTagDescriptionNode(final ArrayList<Block> localResult) {
+    return createSyntheticBlock(localResult, null);
+  }
+
+  public Spacing getSpacing(Block child1, @NotNull Block child2) {
+    if (isPreserveSpace()) return Spacing.getReadOnlySpacing();
+    if(child1 instanceof AbstractSyntheticBlock && child2 instanceof AbstractSyntheticBlock) {
+      return getSpacing((AbstractSyntheticBlock)child1, (AbstractSyntheticBlock)child2);
+    }
+    return null;
+  }
+
+  protected Spacing getSpacing(final AbstractSyntheticBlock syntheticBlock1, final AbstractSyntheticBlock syntheticBlock2) {
+    if (syntheticBlock2.startsWithCDATA() || syntheticBlock1.endsWithCDATA()) {
+      return Spacing.getReadOnlySpacing();
+    }
+
+    if (syntheticBlock1.containsCDATA() && syntheticBlock2.isTagDescription()
+        || syntheticBlock1.isTagDescription() && syntheticBlock2.containsCDATA()) {
+      int lineFeeds = 0;
+      switch(myXmlFormattingPolicy.getWhiteSpaceAroundCDATAOption()) {
+        case XmlCodeStyleSettings.WS_AROUND_CDATA_NONE:
+          break;
+        case XmlCodeStyleSettings.WS_AROUND_CDATA_NEW_LINES:
+          lineFeeds = 1;
+          break;
+        case XmlCodeStyleSettings.WS_AROUND_CDATA_PRESERVE:
+          return Spacing.getReadOnlySpacing();
+        default:
+          assert false : "Unexpected whitespace around CDATA code style option.";
+      }
+      return Spacing.createSpacing(0, 0, lineFeeds, myXmlFormattingPolicy.getShouldKeepLineBreaks(),
+                                   myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if (syntheticBlock2.isJspTextBlock() || syntheticBlock1.isJspTextBlock()) {
+      return Spacing.createSafeSpacing(myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if (syntheticBlock2.isJspxTextBlock() || syntheticBlock1.isJspxTextBlock()) {
+      return Spacing.createSpacing(0, 0, 1, myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if (myXmlFormattingPolicy.keepWhiteSpacesInsideTag(getTag())) return Spacing.getReadOnlySpacing();
+
+    if (myXmlFormattingPolicy.getShouldKeepWhiteSpaces()) {
+      return Spacing.getReadOnlySpacing();
+    }
+
+    if (syntheticBlock2.startsWithTag() ) {
+      final XmlTag startTag = syntheticBlock2.getStartTag();
+      if (myXmlFormattingPolicy.keepWhiteSpacesInsideTag(startTag) && startTag.textContains('\n')) {
+        return getChildrenIndent() != Indent.getNoneIndent() ? Spacing.getReadOnlySpacing():Spacing.createSpacing(0,0,0,true,myXmlFormattingPolicy.getKeepBlankLines());
+      }
+    }
+
+    boolean saveSpacesBetweenTagAndText = myXmlFormattingPolicy.shouldSaveSpacesBetweenTagAndText() &&
+      syntheticBlock1.getTextRange().getEndOffset() < syntheticBlock2.getTextRange().getStartOffset();
+
+    if (syntheticBlock1.endsWithTextElement() && syntheticBlock2.startsWithTextElement()) {
+      return Spacing.createSafeSpacing(myXmlFormattingPolicy.getShouldKeepLineBreaksInText(), myXmlFormattingPolicy.getKeepBlankLines());
+    }
+
+    if (syntheticBlock1.endsWithText()) { //text</tag
+      if (syntheticBlock1.insertLineFeedAfter()) {
+        return Spacing.createDependentLFSpacing(0, 0, getTag().getTextRange(), myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+      }
+      if (saveSpacesBetweenTagAndText) {
+        return Spacing.createSafeSpacing(myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+      }
+      return Spacing.createSpacing(0, 0, 0, myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+
+    } else if (syntheticBlock1.isTagDescription() && syntheticBlock2.isTagDescription()) { //></
+      return Spacing.createSpacing(0, 0, 0, myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
+    } else if (syntheticBlock2.startsWithText()) { //>text
+      if (saveSpacesBetweenTagAndText) {
+        return Spacing.createSafeSpacing(true, myXmlFormattingPolicy.getKeepBlankLines());
+      }
+      return Spacing.createSpacing(0, 0, 0, true, myXmlFormattingPolicy.getKeepBlankLines());
+    } else if (syntheticBlock1.isTagDescription() && syntheticBlock2.startsWithTag()) {
+      return Spacing.createSpacing(0, 0, myXmlFormattingPolicy.insertLineBreakAfterTagBegin(getTag()) ?  2 : 0,
+                                   true, myXmlFormattingPolicy.getKeepBlankLines());
+    } else if (syntheticBlock1.insertLineFeedAfter()) {
+      return Spacing.createSpacing(0,0,1,true,myXmlFormattingPolicy.getKeepBlankLines());
+    } else if (syntheticBlock1.endsWithTag() && syntheticBlock2.isTagDescription()) {
+      return Spacing.createSpacing(0, 0, myXmlFormattingPolicy.insertLineBreakAfterTagBegin(getTag()) ? 2 : 0,
+                                   true, myXmlFormattingPolicy.getKeepBlankLines());
+    } else {
+      return createDefaultSpace(true, true);
+    }
+  }
+
+  public boolean insertLineBreakBeforeTag() {
+    return myXmlFormattingPolicy.insertLineBreakBeforeTag(getTag());
+  }
+
+  public boolean removeLineBreakBeforeTag() {
+    return myXmlFormattingPolicy.removeLineBreakBeforeTag(getTag());
+  }
+
+  public boolean isTextElement() {
+    return myXmlFormattingPolicy.isTextElement(getTag());
+  }
+
+  @Override
+  @NotNull
+  public ChildAttributes getChildAttributes(final int newChildIndex) {
+    if (isAfterAttribute(newChildIndex)) {
+      List<Block> subBlocks = getSubBlocks();
+      Block subBlock = subBlocks.get(newChildIndex - 1);
+      int prevSubBlockChildrenCount = subBlock.getSubBlocks().size();
+      return subBlock.getChildAttributes(prevSubBlockChildrenCount);
+    }
+    else {
+      if (myXmlFormattingPolicy.indentChildrenOf(getTag())) {
+        return new ChildAttributes(Indent.getNormalIndent(), null);
+      } else {
+        return new ChildAttributes(Indent.getNoneIndent(), null);
+      }
+    }
+  }
+
+  private boolean isAfterAttribute(final int newChildIndex) {
+    List<Block> subBlocks = getSubBlocks();
+    int index = newChildIndex - 1;
+    Block prevBlock = index < subBlocks.size() ? subBlocks.get(index):null;
+    return prevBlock instanceof SyntheticBlock && ((SyntheticBlock)prevBlock).endsWithAttribute();
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/HtmlIdIndexer.java b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/HtmlIdIndexer.java
new file mode 100644
index 0000000..907743a
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/HtmlIdIndexer.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.cache.impl.idCache;
+
+import com.intellij.lexer.HtmlHighlightingLexer;
+import com.intellij.lexer.Lexer;
+import com.intellij.psi.impl.cache.impl.OccurrenceConsumer;
+import com.intellij.psi.impl.cache.impl.id.LexerBasedIdIndexer;
+
+public class HtmlIdIndexer extends LexerBasedIdIndexer {
+  public Lexer createLexer(final OccurrenceConsumer consumer) {
+    return createIndexingLexer(consumer);
+  }
+
+  static XHtmlFilterLexer createIndexingLexer(OccurrenceConsumer consumer) {
+    return new XHtmlFilterLexer(new HtmlHighlightingLexer(), consumer);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/HtmlTodoIndexer.java b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/HtmlTodoIndexer.java
new file mode 100644
index 0000000..b6ca609
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/HtmlTodoIndexer.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.cache.impl.idCache;
+
+import com.intellij.lexer.Lexer;
+import com.intellij.psi.impl.cache.impl.OccurrenceConsumer;
+import com.intellij.psi.impl.cache.impl.todo.LexerBasedTodoIndexer;
+
+public class HtmlTodoIndexer extends LexerBasedTodoIndexer {
+  @Override
+  public Lexer createLexer(OccurrenceConsumer consumer) {
+    return HtmlIdIndexer.createIndexingLexer(consumer);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XHtmlFilterLexer.java b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XHtmlFilterLexer.java
new file mode 100644
index 0000000..f0d3a01
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XHtmlFilterLexer.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.cache.impl.idCache;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.lexer.Lexer;
+import com.intellij.psi.impl.cache.impl.BaseFilterLexer;
+import com.intellij.psi.impl.cache.CacheUtil;
+import com.intellij.psi.impl.cache.impl.OccurrenceConsumer;
+import com.intellij.psi.search.UsageSearchContext;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlElementType;
+
+public class XHtmlFilterLexer extends BaseFilterLexer {
+
+  public XHtmlFilterLexer(Lexer originalLexer, OccurrenceConsumer table) {
+    super(originalLexer, table);
+  }
+
+  public void advance() {
+    final IElementType tokenType = myDelegate.getTokenType();
+
+    if (tokenType == XmlElementType.XML_COMMENT_CHARACTERS) {
+      scanWordsInToken(UsageSearchContext.IN_COMMENTS, false, false);
+      advanceTodoItemCountsInToken();
+    } else if (tokenType == XmlElementType.XML_ATTRIBUTE_VALUE_TOKEN ||
+        tokenType == XmlElementType.XML_NAME ||
+        tokenType == XmlElementType.XML_TAG_NAME
+       ) {
+      scanWordsInToken(UsageSearchContext.IN_PLAIN_TEXT | UsageSearchContext.IN_FOREIGN_LANGUAGES, tokenType == XmlElementType.XML_ATTRIBUTE_VALUE_TOKEN,
+                       false);
+    } else if (tokenType.getLanguage() != XMLLanguage.INSTANCE &&
+      tokenType.getLanguage() != Language.ANY         
+    ) {
+      boolean inComments = CacheUtil.isInComments(tokenType);
+      scanWordsInToken((inComments)?UsageSearchContext.IN_COMMENTS:UsageSearchContext.IN_PLAIN_TEXT | UsageSearchContext.IN_FOREIGN_LANGUAGES, true,
+                       false);
+      
+      if (inComments) advanceTodoItemCountsInToken();
+    }
+    else if (!XmlFilterLexer.ourNoWordsTokenSet.contains(tokenType)) {
+      scanWordsInToken(UsageSearchContext.IN_PLAIN_TEXT, false, false);
+    }
+
+    myDelegate.advance();
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XHtmlIdIndexer.java b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XHtmlIdIndexer.java
new file mode 100644
index 0000000..4ae3e83
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XHtmlIdIndexer.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.cache.impl.idCache;
+
+import com.intellij.lexer.Lexer;
+import com.intellij.lexer.XHtmlHighlightingLexer;
+import com.intellij.psi.impl.cache.impl.OccurrenceConsumer;
+import com.intellij.psi.impl.cache.impl.id.LexerBasedIdIndexer;
+
+public class XHtmlIdIndexer extends LexerBasedIdIndexer {
+  public Lexer createLexer(final OccurrenceConsumer consumer) {
+    return createIndexingLexer(consumer);
+  }
+
+  static XHtmlFilterLexer createIndexingLexer(OccurrenceConsumer consumer) {
+    return new XHtmlFilterLexer(new XHtmlHighlightingLexer(), consumer);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XHtmlTodoIndexer.java b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XHtmlTodoIndexer.java
new file mode 100644
index 0000000..bd3458f
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XHtmlTodoIndexer.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.cache.impl.idCache;
+
+import com.intellij.lexer.Lexer;
+import com.intellij.psi.impl.cache.impl.OccurrenceConsumer;
+import com.intellij.psi.impl.cache.impl.todo.LexerBasedTodoIndexer;
+
+public class XHtmlTodoIndexer extends LexerBasedTodoIndexer {
+  @Override
+  public Lexer createLexer(OccurrenceConsumer consumer) {
+    return XHtmlIdIndexer.createIndexingLexer(consumer);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XmlFilterLexer.java b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XmlFilterLexer.java
new file mode 100644
index 0000000..e8e75da
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XmlFilterLexer.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.cache.impl.idCache;
+
+import com.intellij.lexer.Lexer;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.impl.cache.impl.BaseFilterLexer;
+import com.intellij.psi.impl.cache.impl.OccurrenceConsumer;
+import com.intellij.psi.search.UsageSearchContext;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+
+public class XmlFilterLexer extends BaseFilterLexer {
+  static final TokenSet ourNoWordsTokenSet = TokenSet.create(
+    XmlTokenType.TAG_WHITE_SPACE,
+    TokenType.WHITE_SPACE,
+    XmlTokenType.XML_REAL_WHITE_SPACE,
+    XmlTokenType.XML_EQ,
+    XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER,
+    XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER,
+    XmlTokenType.XML_START_TAG_START,
+    XmlTokenType.XML_EMPTY_ELEMENT_END,
+    XmlTokenType.XML_END_TAG_START,
+    XmlTokenType.XML_TAG_END,
+    XmlTokenType.XML_DOCTYPE_END,
+    XmlTokenType.XML_COMMENT_START,
+    XmlTokenType.XML_COMMENT_END,
+    XmlTokenType.XML_PI_START,
+    XmlTokenType.XML_PI_END,
+    XmlTokenType.XML_CDATA_END
+  );
+
+  public XmlFilterLexer(Lexer originalLexer, OccurrenceConsumer table) {
+    super(originalLexer, table);
+  }
+
+  public void advance() {
+    final IElementType tokenType = myDelegate.getTokenType();
+
+    if (tokenType == XmlElementType.XML_COMMENT_CHARACTERS) {
+      scanWordsInToken(UsageSearchContext.IN_COMMENTS, false, false);
+      advanceTodoItemCountsInToken();
+    }
+
+    if (tokenType == XmlElementType.XML_ATTRIBUTE_VALUE_TOKEN) {
+      scanWordsInToken(UsageSearchContext.IN_PLAIN_TEXT | UsageSearchContext.IN_FOREIGN_LANGUAGES, true, false);
+    }
+    else if (tokenType == XmlElementType.XML_NAME || tokenType == XmlElementType.XML_DATA_CHARACTERS) {
+      scanWordsInToken(UsageSearchContext.IN_PLAIN_TEXT | UsageSearchContext.IN_FOREIGN_LANGUAGES, false, false);
+    }
+    else if (tokenType == XmlElementType.XML_ENTITY_REF_TOKEN || tokenType == XmlElementType.XML_CHAR_ENTITY_REF) {
+      scanWordsInToken(UsageSearchContext.IN_CODE, false, false);
+    }
+    else if (tokenType == XmlElementType.XML_TEXT) {
+      scanWordsInToken(UsageSearchContext.IN_PLAIN_TEXT | UsageSearchContext.IN_FOREIGN_LANGUAGES, false, false);
+    }
+    else if (!ourNoWordsTokenSet.contains(tokenType)) {
+      scanWordsInToken(UsageSearchContext.IN_PLAIN_TEXT, false, false);
+    }
+
+    myDelegate.advance();
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XmlIdIndexer.java b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XmlIdIndexer.java
new file mode 100644
index 0000000..ba04785
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XmlIdIndexer.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.cache.impl.idCache;
+
+import com.intellij.lexer.Lexer;
+import com.intellij.lexer.XmlLexer;
+import com.intellij.psi.impl.cache.impl.OccurrenceConsumer;
+import com.intellij.psi.impl.cache.impl.id.LexerBasedIdIndexer;
+
+public class XmlIdIndexer extends LexerBasedIdIndexer {
+  public Lexer createLexer(final OccurrenceConsumer consumer) {
+    return createIndexingLexer(consumer);
+  }
+
+  static XmlFilterLexer createIndexingLexer(OccurrenceConsumer consumer) {
+    return new XmlFilterLexer(new XmlLexer(), consumer);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XmlTodoIndexer.java b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XmlTodoIndexer.java
new file mode 100644
index 0000000..4847f3d
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/cache/impl/idCache/XmlTodoIndexer.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.cache.impl.idCache;
+
+import com.intellij.lexer.Lexer;
+import com.intellij.psi.impl.cache.impl.OccurrenceConsumer;
+import com.intellij.psi.impl.cache.impl.todo.LexerBasedTodoIndexer;
+
+public class XmlTodoIndexer extends LexerBasedTodoIndexer {
+  @Override
+  public Lexer createLexer(OccurrenceConsumer consumer) {
+    return XmlIdIndexer.createIndexingLexer(consumer);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java
new file mode 100644
index 0000000..bcd6f5a
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.html;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.lang.injection.MultiHostInjector;
+import com.intellij.lang.injection.MultiHostRegistrar;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiComment;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiLanguageInjectionHost;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlComment;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author spleaner
+ */
+public class HtmlConditionalCommentInjector implements MultiHostInjector {
+
+  /**
+   * Allows to check if given element is a
+   * <a href="http://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx">conditional comment</a>.
+   * 
+   * @param host  target element to check
+   * @return      <code>true</code> if given element is conditional comment; <code>false</code> otherwise
+   */
+  public static boolean isConditionalComment(@NotNull PsiElement host) {
+    return parseConditionalCommentBoundaries(host) != null;
+  }
+
+  /**
+   * Tries to parse given element as <a href="http://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx">conditional comment</a>.
+   * 
+   * @param host  target element to parse
+   * @return      <code>null</code> if given element is not a conditional comment;
+   *              pair like <code>(conditional comment start element; conditional comment end element)</code> otherwise
+   */
+  @Nullable
+  private static Pair<ASTNode, ASTNode> parseConditionalCommentBoundaries(@NotNull PsiElement host) {
+    if (!(host instanceof XmlComment)) {
+      return null;
+    }
+    final ASTNode comment = host.getNode();
+    if (comment == null) {
+      return null;
+    }
+    final ASTNode conditionalStart = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_START_END));
+    if (conditionalStart == null) {
+      return null;
+    }
+    final ASTNode conditionalEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END_START));
+    if (conditionalEnd == null) {
+      return null;
+    }
+    final ASTNode endOfEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END));
+    return endOfEnd == null ? null : new Pair<ASTNode, ASTNode>(conditionalStart, conditionalEnd);
+  }
+  
+  public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement host) {
+    Pair<ASTNode, ASTNode> pair = parseConditionalCommentBoundaries(host);
+    if (pair == null) {
+      return;
+    }
+    final TextRange textRange = host.getTextRange();
+    final int startOffset = textRange.getStartOffset();
+    Language language = host.getParent().getLanguage();
+    ASTNode conditionalStart = pair.first;
+    ASTNode conditionalEnd = pair.second;
+    TextRange range = new TextRange(conditionalStart.getTextRange().getEndOffset() - startOffset, conditionalEnd.getStartOffset() - startOffset);
+    if (range.getStartOffset() < range.getEndOffset()) {
+      registrar.startInjecting(language).addPlace(null, null, (PsiLanguageInjectionHost)host, range).doneInjecting();
+    }
+  }
+
+  @NotNull
+  public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
+    return Arrays.asList(PsiComment.class);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlDocumentImpl.java b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlDocumentImpl.java
new file mode 100644
index 0000000..7aa9ce9
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlDocumentImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.html;
+
+import com.intellij.psi.impl.source.xml.XmlDocumentImpl;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class HtmlDocumentImpl extends XmlDocumentImpl {
+  public HtmlDocumentImpl() {
+    super(XmlElementType.HTML_DOCUMENT);
+  }
+
+  public XmlTag getRootTag() {
+    return (XmlTag)findElementByTokenType(XmlElementType.HTML_TAG);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java
new file mode 100644
index 0000000..4154cfe
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.html;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.impl.source.tree.CompositeElement;
+import com.intellij.psi.impl.source.xml.XmlFileImpl;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlElementType;
+
+/**
+ * @author maxim
+ */
+public class HtmlFileImpl extends XmlFileImpl {
+  public HtmlFileImpl(FileViewProvider provider) {
+    super(provider, XmlElementType.HTML_FILE);
+  }
+
+  public String toString() {
+    return "HtmlFile:" + getName();
+  }
+
+  public XmlDocument getDocument() {
+    CompositeElement treeElement = calcTreeElement();
+
+    ASTNode node = treeElement.findChildByType(XmlElementType.HTML_DOCUMENT);
+    return node != null ? (XmlDocument)node.getPsi() : null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlTagImpl.java b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlTagImpl.java
new file mode 100644
index 0000000..1d32413
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlTagImpl.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.html;
+
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.impl.source.xml.XmlTagImpl;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class HtmlTagImpl extends XmlTagImpl implements HtmlTag {
+  public HtmlTagImpl() {
+    super(XmlElementType.HTML_TAG);
+  }
+
+  @NotNull
+  public XmlTag[] findSubTags(String name, String namespace) {
+    final XmlTag[] subTags = getSubTags();
+    List<XmlTag> result = null;
+
+    for (final XmlTag subTag : subTags) {
+      if (namespace == null) {
+        String tagName = subTag.getName();
+        tagName = tagName.toLowerCase();
+
+        if (name == null || name.equals(tagName)) {
+          if (result == null) {
+            result = new ArrayList<XmlTag>(3);
+          }
+
+          result.add(subTag);
+        }
+      }
+      else if (namespace.equals(subTag.getNamespace()) &&
+               (name == null || name.equals(subTag.getLocalName()))
+        ) {
+        if (result == null) {
+          result = new ArrayList<XmlTag>(3);
+        }
+
+        result.add(subTag);
+      }
+    }
+
+    return result == null ? EMPTY : result.toArray(new XmlTag[result.size()]);
+  }
+
+  protected boolean isCaseSensitive() {
+    return false;
+  }
+
+  public String getAttributeValue(String qname) {
+    qname = qname.toLowerCase();
+    return super.getAttributeValue(qname);
+  }
+
+  protected void cacheOneAttributeValue(String name, String value, final Map<String, String> attributesValueMap) {
+    name = name.toLowerCase();
+    super.cacheOneAttributeValue(name, value, attributesValueMap);
+  }
+
+  public String getAttributeValue(String name, String namespace) {
+    name = name.toLowerCase();
+    return super.getAttributeValue(name, namespace);
+  }
+
+  @NotNull
+  public String getNamespace() {
+    final String xmlNamespace = super.getNamespace();
+
+    if (getNamespacePrefix().length() > 0) {
+      return xmlNamespace;
+    }
+
+    if (xmlNamespace.length() == 0 || xmlNamespace.equals(XmlUtil.XHTML_URI)) {
+      return XmlUtil.HTML_URI;
+    }
+
+    // ex.: mathML and SVG namespaces can be used inside html file
+    return xmlNamespace;
+  }
+
+  protected String getRealNs(final String value) {
+    if (XmlUtil.XHTML_URI.equals(value)) return XmlUtil.HTML_URI;
+    return value;
+  }
+
+  public String toString() {
+    return "HtmlTag:" + getName();
+  }
+
+  public String getPrefixByNamespace(String namespace) {
+    if (XmlUtil.HTML_URI.equals(namespace)) namespace = XmlUtil.XHTML_URI;
+    return super.getPrefixByNamespace(namespace);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/ScriptSupportUtil.java b/xml/impl/src/com/intellij/psi/impl/source/html/ScriptSupportUtil.java
new file mode 100644
index 0000000..55d68f8
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/html/ScriptSupportUtil.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.html;
+
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.ResolveState;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceUtil;
+import com.intellij.psi.scope.PsiScopeProcessor;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.xml.*;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class ScriptSupportUtil {
+  private static final Key<CachedValue<XmlTag[]>> CachedScriptTagsKey = Key.create("script tags");
+  private static final ThreadLocal<String> ProcessingDeclarationsFlag = new ThreadLocal<String>();
+  private static final @NonNls String SCRIPT_TAG = "script";
+
+  private ScriptSupportUtil() {
+  }
+
+  public static void clearCaches(XmlFile element) {
+    element.putUserData(CachedScriptTagsKey,null);
+  }
+
+  public static boolean processDeclarations(final XmlFile element,
+                                            PsiScopeProcessor processor,
+                                            ResolveState state,
+                                            PsiElement lastParent,
+                                            PsiElement place) {
+    CachedValue<XmlTag[]> myCachedScriptTags = element.getUserData(CachedScriptTagsKey);
+    if (myCachedScriptTags == null) {
+      myCachedScriptTags = CachedValuesManager.getManager(element.getProject())
+          .createCachedValue(new CachedValueProvider<XmlTag[]>() {
+            @Override
+            public Result<XmlTag[]> compute() {
+              final List<XmlTag> scriptTags = new ArrayList<XmlTag>();
+              final XmlDocument document = HtmlUtil.getRealXmlDocument(element.getDocument());
+
+              if (document != null) {
+                PsiElementProcessor psiElementProcessor = new PsiElementProcessor() {
+                  public boolean execute(@NotNull final PsiElement element) {
+                    if (element instanceof XmlTag) {
+                      final XmlTag tag = (XmlTag)element;
+
+                      if (SCRIPT_TAG.equalsIgnoreCase(tag.getName())) {
+                        final XmlElementDescriptor descriptor = tag.getDescriptor();
+                        if (descriptor != null && SCRIPT_TAG.equals(descriptor.getName())) {
+                          scriptTags.add(tag);
+                        }
+                      }
+                    }
+                    return true;
+                  }
+                };
+                XmlUtil.processXmlElements(document, psiElementProcessor, true);
+              }
+
+              return new Result<XmlTag[]>(scriptTags.toArray(new XmlTag[scriptTags.size()]), element);
+            }
+          }, false);
+      element.putUserData(CachedScriptTagsKey, myCachedScriptTags);
+    }
+
+    if (ProcessingDeclarationsFlag.get() != null) return true;
+
+    try {
+      ProcessingDeclarationsFlag.set("");
+
+      for (XmlTag tag : myCachedScriptTags.getValue()) {
+        final XmlTagChild[] children = tag.getValue().getChildren();
+        for (XmlTagChild child : children) {
+          if (!child.processDeclarations(processor, state, null, place)) return false;
+        }
+
+        if (tag.getAttributeValue("src") != null) {
+          final XmlAttribute attribute = tag.getAttribute("src", null);
+
+          if (attribute != null) {
+            final PsiFile psiFile = FileReferenceUtil.findFile(attribute.getValueElement());
+
+            if (psiFile != null && psiFile.isValid()) {
+              if (!psiFile.processDeclarations(processor, state, null, place)) {
+                return false;
+              }
+            }
+          }
+        }
+      }
+    }
+    finally {
+      ProcessingDeclarationsFlag.set(null);
+    }
+
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java b/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java
new file mode 100644
index 0000000..75f8ae5
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.html.dtd;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class HtmlAttributeDescriptorImpl implements XmlAttributeDescriptor {
+  private final XmlAttributeDescriptor delegate;
+  private final boolean myCaseSensitive;
+
+  public HtmlAttributeDescriptorImpl(XmlAttributeDescriptor _delegate, boolean caseSensitive) {
+    delegate = _delegate;
+    myCaseSensitive = caseSensitive;
+  }
+
+  public boolean isRequired() {
+    return delegate.isRequired();
+  }
+
+  public boolean isFixed() {
+    return delegate.isFixed();
+  }
+
+  public boolean hasIdType() {
+    return delegate.hasIdType();
+  }
+
+  public boolean hasIdRefType() {
+    return delegate.hasIdRefType();
+  }
+
+  public String getDefaultValue() {
+    return delegate.getDefaultValue();
+  }
+
+  //todo: refactor to hierarchy of value descriptor?
+  public boolean isEnumerated() {
+    return delegate.isEnumerated();
+  }
+
+  public String[] getEnumeratedValues() {
+    return delegate.getEnumeratedValues();
+  }
+
+  public String validateValue(XmlElement context, String value) {
+    if (!myCaseSensitive) value = value.toLowerCase();
+    return delegate.validateValue(context, value);
+  }
+
+  public PsiElement getDeclaration() {
+    return delegate.getDeclaration();
+  }
+
+  public String getName(PsiElement context) {
+    return delegate.getName(context);
+  }
+
+  public String getName() {
+    return delegate.getName();
+  }
+
+  public void init(PsiElement element) {
+    delegate.init(element);
+  }
+
+  public Object[] getDependences() {
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlElementDescriptorImpl.java b/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlElementDescriptorImpl.java
new file mode 100644
index 0000000..12b2468
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlElementDescriptorImpl.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.html.dtd;
+
+import com.intellij.html.impl.RelaxedHtmlFromSchemaElementDescriptor;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.impl.dtd.BaseXmlElementDescriptorImpl;
+import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
+import com.intellij.xml.util.XmlUtil;
+
+import java.util.HashMap;
+
+/**
+ * @by Maxim.Mossienko
+ */
+public class HtmlElementDescriptorImpl extends BaseXmlElementDescriptorImpl {
+  private final XmlElementDescriptor myDelegate;
+  private final boolean myRelaxed;
+  private final boolean myCaseSensitive;
+
+  public HtmlElementDescriptorImpl(XmlElementDescriptor _delegate, boolean relaxed, boolean caseSensitive) {
+    myDelegate = _delegate;
+    myRelaxed = relaxed;
+    myCaseSensitive = caseSensitive;
+  }
+
+  public String getQualifiedName() {
+    return myDelegate.getQualifiedName();
+  }
+
+  public String getDefaultName() {
+    return myDelegate.getDefaultName();
+  }
+
+  // Read-only calculation
+  protected final XmlElementDescriptor[] doCollectXmlDescriptors(final XmlTag context) {
+    XmlElementDescriptor[] elementsDescriptors = myDelegate.getElementsDescriptors(context);
+    XmlElementDescriptor[] temp = new XmlElementDescriptor[elementsDescriptors.length];
+
+    for (int i = 0; i < elementsDescriptors.length; i++) {
+      temp[i] = new HtmlElementDescriptorImpl( elementsDescriptors[i], myRelaxed, myCaseSensitive );
+    }
+    return temp;
+  }
+
+  public XmlElementDescriptor getElementDescriptor(XmlTag element, XmlTag contextTag) {
+    String name = element.getName();
+    if (!myCaseSensitive) name = name.toLowerCase();
+
+    XmlElementDescriptor xmlElementDescriptor = getElementDescriptor(name, element);
+    if (xmlElementDescriptor == null && myRelaxed) {
+      xmlElementDescriptor = RelaxedHtmlFromSchemaElementDescriptor.getRelaxedDescriptor(this, element);
+    }
+
+    return xmlElementDescriptor;
+  }
+
+  // Read-only calculation
+  protected HashMap<String, XmlElementDescriptor> collectElementDescriptorsMap(final XmlTag element) {
+    final HashMap<String, XmlElementDescriptor> hashMap = new HashMap<String, XmlElementDescriptor>();
+    final XmlElementDescriptor[] elementDescriptors = myDelegate.getElementsDescriptors(element);
+
+    for (XmlElementDescriptor elementDescriptor : elementDescriptors) {
+      hashMap.put(elementDescriptor.getName(), new HtmlElementDescriptorImpl(elementDescriptor, myRelaxed, myCaseSensitive));
+    }
+    return hashMap;
+  }
+
+  // Read-only calculation
+  protected XmlAttributeDescriptor[] collectAttributeDescriptors(final XmlTag context) {
+    final XmlAttributeDescriptor[] attributesDescriptors = myDelegate.getAttributesDescriptors(context);
+    XmlAttributeDescriptor[] temp = new XmlAttributeDescriptor[attributesDescriptors.length];
+
+    for (int i = 0; i < attributesDescriptors.length; i++) {
+      temp[i] = new HtmlAttributeDescriptorImpl(attributesDescriptors[i], myCaseSensitive);
+    }
+    return temp;
+  }
+
+  public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, final XmlTag context) {
+    if (!myCaseSensitive) attributeName = attributeName.toLowerCase();
+    XmlAttributeDescriptor descriptor = super.getAttributeDescriptor(attributeName, context);
+    if (descriptor == null) descriptor = RelaxedHtmlFromSchemaElementDescriptor.getAttributeDescriptorFromFacelets(attributeName, context);
+    
+    if (descriptor == null) {
+      String prefix = XmlUtil.findPrefixByQualifiedName(attributeName);
+      
+      if ("xml".equals(prefix)) { // todo this is not technically correct dtd document references namespaces but we should handle it at least for xml stuff
+        XmlNSDescriptor nsdescriptor = context.getNSDescriptor(XmlUtil.XML_NAMESPACE_URI, true);
+        if (nsdescriptor instanceof XmlNSDescriptorImpl) {
+          descriptor = ((XmlNSDescriptorImpl)nsdescriptor).getAttribute(
+            XmlUtil.findLocalNameByQualifiedName(attributeName), XmlUtil.XML_NAMESPACE_URI, context);
+        }
+      }
+    }
+    return descriptor;
+  }
+
+  // Read-only calculation
+  protected HashMap<String, XmlAttributeDescriptor> collectAttributeDescriptorsMap(final XmlTag context) {
+    final HashMap<String, XmlAttributeDescriptor> hashMap = new HashMap<String, XmlAttributeDescriptor>();
+    XmlAttributeDescriptor[] elementAttributeDescriptors = myDelegate.getAttributesDescriptors(context);
+
+    for (final XmlAttributeDescriptor attributeDescriptor : elementAttributeDescriptors) {
+      hashMap.put(
+        attributeDescriptor.getName(),
+        new HtmlAttributeDescriptorImpl(attributeDescriptor, myCaseSensitive)
+      );
+    }
+    return hashMap;
+  }
+
+  public XmlNSDescriptor getNSDescriptor() {
+    return myDelegate.getNSDescriptor();
+  }
+
+  public int getContentType() {
+    return myDelegate.getContentType();
+  }
+
+  public PsiElement getDeclaration() {
+    return myDelegate.getDeclaration();
+  }
+
+  public String getName(PsiElement context) {
+    return myDelegate.getName(context);
+  }
+
+  public String getName() {
+    return myDelegate.getName();
+  }
+
+  public void init(PsiElement element) {
+    myDelegate.init(element);
+  }
+
+  public Object[] getDependences() {
+    return myDelegate.getDependences();
+  }
+
+  public XmlAttributeDescriptor[] getAttributesDescriptors(final XmlTag context) {
+    return RelaxedHtmlFromSchemaElementDescriptor.addAttrDescriptorsForFacelets(context, super.getAttributesDescriptors(context));
+  }
+
+  public boolean allowElementsFromNamespace(final String namespace, final XmlTag context) {
+    return true;
+  }
+
+  @Override
+  public String toString() {
+    return myDelegate.toString();
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java b/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java
new file mode 100644
index 0000000..840e335
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.html.dtd;
+
+import com.intellij.html.RelaxedHtmlNSDescriptor;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.util.SimpleFieldCache;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.impl.schema.TypeDescriptor;
+import com.intellij.xml.impl.schema.XmlNSTypeDescriptorProvider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class HtmlNSDescriptorImpl implements XmlNSDescriptor, DumbAware, XmlNSTypeDescriptorProvider {
+  private XmlNSDescriptor myDelegate;
+  private boolean myRelaxed;
+  private boolean myCaseSensitive;
+
+  private static final SimpleFieldCache<Map<String, XmlElementDescriptor>, HtmlNSDescriptorImpl> myCachedDeclsCache = new SimpleFieldCache<Map<String, XmlElementDescriptor>, HtmlNSDescriptorImpl>() {
+    protected Map<String, XmlElementDescriptor> compute(final HtmlNSDescriptorImpl htmlNSDescriptor) {
+      return htmlNSDescriptor.doBuildCachedMap();
+    }
+
+    protected Map<String, XmlElementDescriptor> getValue(final HtmlNSDescriptorImpl htmlNSDescriptor) {
+      return htmlNSDescriptor.myCachedDecls;
+    }
+
+    protected void putValue(final Map<String, XmlElementDescriptor> map, final HtmlNSDescriptorImpl htmlNSDescriptor) {
+      htmlNSDescriptor.myCachedDecls = map;
+    }
+  };
+
+  private volatile Map<String, XmlElementDescriptor> myCachedDecls;
+
+  public HtmlNSDescriptorImpl(XmlNSDescriptor _delegate) {
+    this(_delegate, _delegate instanceof RelaxedHtmlNSDescriptor, false);
+  }
+
+  public HtmlNSDescriptorImpl(XmlNSDescriptor _delegate, boolean relaxed, boolean caseSensitive) {
+    myDelegate = _delegate;
+    myRelaxed = relaxed;
+    myCaseSensitive = caseSensitive;
+  }
+
+  private Map<String,XmlElementDescriptor> buildDeclarationMap() {
+    return myCachedDeclsCache.get(this);
+  }
+
+  // Read-only calculation
+  private HashMap<String, XmlElementDescriptor> doBuildCachedMap() {
+    HashMap<String, XmlElementDescriptor> decls = new HashMap<String, XmlElementDescriptor>();
+    XmlElementDescriptor[] elements = myDelegate == null ? XmlElementDescriptor.EMPTY_ARRAY : myDelegate.getRootElementsDescriptors(null);
+
+    for (XmlElementDescriptor element : elements) {
+      decls.put(
+        element.getName(),
+        new HtmlElementDescriptorImpl(element, myRelaxed, myCaseSensitive)
+      );
+    }
+    return decls;
+  }
+
+  public XmlElementDescriptor getElementDescriptor(@NotNull XmlTag tag) {
+    String name = tag.getLocalName();
+    if (!myCaseSensitive) name = name.toLowerCase();
+
+    XmlElementDescriptor xmlElementDescriptor = buildDeclarationMap().get(name);
+    if (xmlElementDescriptor == null && myRelaxed) {
+      xmlElementDescriptor = myDelegate.getElementDescriptor(tag);
+    }
+    return xmlElementDescriptor;
+  }
+
+  @NotNull
+  public XmlElementDescriptor[] getRootElementsDescriptors(@Nullable final XmlDocument document) {
+    return myDelegate == null ? XmlElementDescriptor.EMPTY_ARRAY : myDelegate.getRootElementsDescriptors(document);
+  }
+
+  @Nullable
+  public XmlFile getDescriptorFile() {
+    return myDelegate == null ? null : myDelegate.getDescriptorFile();
+  }
+
+  public boolean isHierarhyEnabled() {
+    return false;
+  }
+
+  public PsiElement getDeclaration() {
+    return myDelegate == null ? null : myDelegate.getDeclaration();
+  }
+
+  public String getName(PsiElement context) {
+    return myDelegate == null ? "" : myDelegate.getName(context);
+  }
+
+  public String getName() {
+    return myDelegate == null ? "" : myDelegate.getName();
+  }
+
+  public void init(PsiElement element) {
+    myDelegate.init(element);
+  }
+
+  public Object[] getDependences() {
+    return myDelegate == null ? null : myDelegate.getDependences();
+  }
+
+  @Override
+  public TypeDescriptor getTypeDescriptor(String name, XmlTag context) {
+    return myDelegate instanceof XmlNSTypeDescriptorProvider ?
+           ((XmlNSTypeDescriptorProvider)myDelegate).getTypeDescriptor(name, context) : null;
+  }
+
+  @Override
+  public TypeDescriptor getTypeDescriptor(XmlTag descriptorTag) {
+    return myDelegate instanceof XmlNSTypeDescriptorProvider ?
+           ((XmlNSTypeDescriptorProvider)myDelegate).getTypeDescriptor(descriptorTag) : null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/DtdParsing.java b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/DtdParsing.java
new file mode 100644
index 0000000..06a1bea
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/DtdParsing.java
@@ -0,0 +1,871 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.parsing.xml;
+
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.LanguageParserDefinitions;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.PsiBuilderFactory;
+import com.intellij.lang.dtd.DTDLanguage;
+import com.intellij.lexer.DtdLexer;
+import com.intellij.lexer._DtdLexer;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.DummyHolder;
+import com.intellij.psi.impl.source.DummyHolderFactory;
+import com.intellij.psi.impl.source.resolve.FileContextUtil;
+import com.intellij.psi.impl.source.tree.FileElement;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlEntityDecl;
+import com.intellij.xml.XmlBundle;
+
+/**
+ * @author Mike
+ */
+public class DtdParsing extends XmlParsing implements XmlElementType {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.parsing.xml.XmlParser");
+
+  private final IElementType myRootType;
+  public static final XmlEntityDecl.EntityContextType TYPE_FOR_MARKUP_DECL = XmlEntityDecl.EntityContextType.ELEMENT_CONTENT_SPEC;
+  private final XmlEntityDecl.EntityContextType myContextType;
+
+  public DtdParsing(IElementType root, XmlEntityDecl.EntityContextType contextType, PsiBuilder builder) {
+    super(builder);
+    myRootType = root;
+    myContextType = contextType;
+    myBuilder.enforceCommentTokens(TokenSet.EMPTY);
+  }
+
+  public DtdParsing(CharSequence chars,
+                    final IElementType type,
+                    final XmlEntityDecl.EntityContextType contextType,
+                    PsiFile contextFile
+  ) {
+    this(
+      type,
+      contextType,
+      PsiBuilderFactory.getInstance().createBuilder(
+        LanguageParserDefinitions.INSTANCE.forLanguage(DTDLanguage.INSTANCE),
+        new DtdLexer(false) {
+          final int myInitialState = getLexerInitialState(type, contextType);
+          @Override
+          public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
+            super.start(buffer, startOffset, endOffset, myInitialState);
+          }
+        }, chars
+      )
+    );
+    if (contextFile != null) myBuilder.putUserDataUnprotected(FileContextUtil.CONTAINING_FILE_KEY, contextFile);
+  }
+
+  public ASTNode parse() {
+    final PsiBuilder.Marker root = myBuilder.mark();
+
+    if (myRootType == XML_MARKUP_DECL) {
+      parseTopLevelMarkupDecl();
+      root.done(myRootType);
+      return myBuilder.getTreeBuilt();
+    }
+
+    PsiBuilder.Marker document = null;
+    if (myRootType == DTD_FILE) {
+      document = myBuilder.mark();
+      parseProlog();
+    } 
+
+    switch (myContextType) {
+      case GENERIC_XML:
+        parseGenericXml();
+        break;
+      case ELEMENT_CONTENT_SPEC:
+        parseElementContentSpec();
+        break;
+      case ATTLIST_SPEC:
+        parseAttlistContent();
+        break;
+      case ATTR_VALUE:
+        parseAttrValue();
+      case ATTRIBUTE_SPEC:
+        parseAttributeContentSpec();
+        break;
+      case ENTITY_DECL_CONTENT:
+        parseEntityDeclContent();
+        break;
+      case ENUMERATED_TYPE:
+        parseEnumeratedTypeContent();
+        break;
+    }
+
+    while(!myBuilder.eof()) myBuilder.advanceLexer();
+    if (document != null) document.done(XML_DOCUMENT);
+    root.done(myRootType);
+    ASTNode astNode = myBuilder.getTreeBuilt();
+
+    if (myRootType != DTD_FILE) {
+      PsiFile file = myBuilder.getUserDataUnprotected(FileContextUtil.CONTAINING_FILE_KEY);
+      if (file != null) {
+        final DummyHolder result = DummyHolderFactory.createHolder(file.getManager(), DTDLanguage.INSTANCE, file);
+        final FileElement holder = result.getTreeElement();
+        holder.rawAddChildren((TreeElement)astNode);
+      }
+    }
+
+    return astNode;
+  }
+
+  private static int getLexerInitialState(IElementType rootNodeType, XmlEntityDecl.EntityContextType context) {
+    short state = 0;
+
+    switch (context) {
+      case ELEMENT_CONTENT_SPEC:
+      case ATTRIBUTE_SPEC:
+      case ATTLIST_SPEC:
+      case ENUMERATED_TYPE:
+      case ENTITY_DECL_CONTENT:
+      {
+        state = _DtdLexer.DOCTYPE_MARKUP;
+        break;
+      }
+
+      case ATTR_VALUE:
+      case GENERIC_XML: {
+        break;
+      }
+
+
+      default: LOG.error("context: " + context);
+    }
+
+    if (rootNodeType == XML_MARKUP_DECL && context == TYPE_FOR_MARKUP_DECL) {
+      state = _DtdLexer.DOCTYPE;
+    }
+    return state;
+  }
+
+  private void parseGenericXml() {
+    IElementType tokenType;
+
+    while ((tokenType = myBuilder.getTokenType()) != null) {
+      if (tokenType == XML_ATTLIST_DECL_START) {
+        parseAttlistDecl();
+      }
+      else if (tokenType == XML_ELEMENT_DECL_START) {
+        parseElementDecl();
+      }
+      else if (tokenType == XML_ENTITY_DECL_START) {
+        parseEntityDecl();
+      }
+      else if (tokenType == XML_NOTATION_DECL_START) {
+        parseNotationDecl();
+      }
+      else if (tokenType == XML_ENTITY_REF_TOKEN) {
+        parseEntityRef();
+      }
+      else if (parseProcessingInstruction()) {
+      }
+      else if (tokenType == XML_START_TAG_START) {
+        parseTag(false);
+      } else if (isCommentToken(tokenType)) {
+        parseComment();
+      }
+      else if (parseConditionalSection()) {
+      }
+      else if (tokenType != null) {
+        addToken();
+      }
+    }
+  }
+
+  private void parseNotationDecl() {
+    if (myBuilder.getTokenType() != XML_NOTATION_DECL_START) {
+      return;
+    }
+
+    PsiBuilder.Marker decl = myBuilder.mark();
+    addToken();
+
+    if (!parseName()) {
+      decl.done(XML_NOTATION_DECL);
+      return;
+    }
+
+    parseEntityDeclContent();
+
+    if (myBuilder.getTokenType() != null) {
+      addToken();
+    }
+
+    decl.done(XML_NOTATION_DECL);
+  }
+
+  private void parseEntityDecl() {
+    if (myBuilder.getTokenType() != XML_ENTITY_DECL_START) {
+      return;
+    }
+
+    PsiBuilder.Marker decl = myBuilder.mark();
+    addToken();
+
+    if (myBuilder.getTokenType() == XML_PERCENT) {
+      addToken();
+    }
+
+    if (parseCompositeName()) {
+      decl.done(XML_ENTITY_DECL);
+      return;
+    }
+
+    parseEntityDeclContent();
+
+    if (myBuilder.getTokenType() != null) {
+      addToken();
+    }
+
+    decl.done(XML_ENTITY_DECL);
+  }
+
+  private boolean parseCompositeName() {
+    if (!parseName()) {
+      if (myBuilder.getTokenType() == XML_LEFT_PAREN) {
+        parseGroup();
+      } else {
+        myBuilder.error(XmlBundle.message("dtd.parser.message.name.expected"));
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private void parseEntityDeclContent() {
+    IElementType tokenType = myBuilder.getTokenType();
+    if (tokenType != XML_ATTRIBUTE_VALUE_START_DELIMITER &&
+        tokenType != XML_DOCTYPE_PUBLIC &&
+        tokenType != XML_DOCTYPE_SYSTEM) {
+      myBuilder.error(XmlBundle.message("dtd.parser.message.literal.public.system.expected"));
+      return;
+    }
+
+    while (tokenType != XML_TAG_END && tokenType != null) {
+      if (tokenType == XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+        parseAttributeValue();
+      }
+      else {
+        addToken();
+      }
+
+      tokenType = myBuilder.getTokenType();
+    }
+  }
+
+  private boolean parseConditionalSection() {
+    if (myBuilder.getTokenType() != XML_CONDITIONAL_SECTION_START) {
+      return false;
+    }
+    
+    PsiBuilder.Marker conditionalSection = myBuilder.mark();
+
+    addToken();
+    IElementType tokenType = myBuilder.getTokenType();
+    if (tokenType != XML_CONDITIONAL_IGNORE &&
+        tokenType != XML_CONDITIONAL_INCLUDE &&
+        tokenType != XML_ENTITY_REF_TOKEN) {
+      conditionalSection.done(XML_CONDITIONAL_SECTION);
+      return true;
+    }
+
+    if (tokenType == XML_ENTITY_REF_TOKEN) {
+      parseEntityRef();
+    } else {
+      addToken();
+    }
+
+    if (myBuilder.getTokenType() != XML_MARKUP_START) {
+      conditionalSection.done(XML_CONDITIONAL_SECTION);
+      return true;
+    }
+
+    parseMarkupContent();
+
+    if (myBuilder.getTokenType() != XML_CONDITIONAL_SECTION_END) {
+      conditionalSection.done(XML_CONDITIONAL_SECTION);
+      return true;
+    }
+    addToken();
+    conditionalSection.done(XML_CONDITIONAL_SECTION);
+    return true;
+  }
+
+  private boolean parseProcessingInstruction() {
+    if (myBuilder.getTokenType() != XML_PI_START) {
+      return false;
+    }
+    PsiBuilder.Marker tag = myBuilder.mark();
+
+    addToken();
+    if (myBuilder.getTokenType() != XML_PI_TARGET) {
+      tag.done(XML_PROCESSING_INSTRUCTION);
+      return true;
+    }
+    addToken();
+    if (myBuilder.getTokenType() != XML_PI_END) {
+      tag.done(XML_PROCESSING_INSTRUCTION);
+      return true;
+    }
+    addToken();
+    tag.done(XML_PROCESSING_INSTRUCTION);
+    return true;
+  }
+
+  private void parseEntityRef() {
+    PsiBuilder.Marker ref = myBuilder.mark();
+
+    if (myBuilder.getTokenType() == XML_ENTITY_REF_TOKEN) {
+      addToken();
+    }
+
+    ref.done(XML_ENTITY_REF);
+  }
+
+  private void parseProlog() {
+    PsiBuilder.Marker prolog = myBuilder.mark();
+
+    while (parseProcessingInstruction()) {}
+
+    if (myBuilder.getTokenType() == XML_DECL_START) {
+      parseDecl();
+    }
+
+    while (parseProcessingInstruction()) {}
+
+    if (myBuilder.getTokenType() == XML_DOCTYPE_START) {
+      parseDocType();
+    }
+
+    while (parseProcessingInstruction()) {}
+
+    prolog.done(XML_PROLOG);
+  }
+
+  private void parseDocType() {
+    if (myBuilder.getTokenType() != XML_DOCTYPE_START) {
+      return;
+    }
+
+    PsiBuilder.Marker docType = myBuilder.mark();
+    addToken();
+
+    if (myBuilder.getTokenType() != XML_NAME) {
+      docType.done(XML_DOCTYPE);
+      return;
+    }
+
+    addToken();
+
+    if (myBuilder.getTokenType() == XML_DOCTYPE_SYSTEM) {
+      addToken();
+
+      if (myBuilder.getTokenType() == XML_ATTRIBUTE_VALUE_TOKEN) {
+        addToken();
+      }
+    }
+    else if (myBuilder.getTokenType() == XML_DOCTYPE_PUBLIC) {
+      addToken();
+
+      if (myBuilder.getTokenType() == XML_ATTRIBUTE_VALUE_TOKEN) {
+        addToken();
+      }
+
+      if (myBuilder.getTokenType() == XML_ATTRIBUTE_VALUE_TOKEN) {
+        addToken();
+      }
+    }
+
+    if (myBuilder.getTokenType() == XML_MARKUP_START) {
+      parseMarkupDecl();
+    }
+
+    if (myBuilder.getTokenType() != XML_DOCTYPE_END) {
+      docType.done(XML_DOCTYPE);
+      return;
+    }
+
+    addToken();
+
+    docType.done(XML_DOCTYPE);
+  }
+
+  private void parseMarkupDecl() {
+    PsiBuilder.Marker decl = myBuilder.mark();
+    parseMarkupContent();
+
+    decl.done(XML_MARKUP_DECL);
+  }
+
+  private void parseMarkupContent() {
+    IElementType tokenType = myBuilder.getTokenType();
+    if (tokenType == XML_MARKUP_START) {
+      addToken();
+    }
+
+    while (true) {
+      tokenType = myBuilder.getTokenType();
+      
+      if (tokenType == XML_ELEMENT_DECL_START) {
+        parseElementDecl();
+      }
+      else if (tokenType == XML_ATTLIST_DECL_START) {
+        parseAttlistDecl();
+      }
+      else if (tokenType == XML_ENTITY_DECL_START) {
+        parseEntityDecl();
+      }
+      else if (tokenType == XML_NOTATION_DECL_START) {
+        parseNotationDecl();
+      } else if (tokenType == XML_ENTITY_REF_TOKEN) {
+        parseEntityRef();
+      } else if (tokenType == XML_COMMENT_START) {
+        parseComment();
+      }
+      else if (parseConditionalSection()) {
+      }
+      else {
+        break;
+      }
+    }
+
+    if (tokenType == XML_MARKUP_END) {
+      addToken();
+    }
+  }
+
+  private void parseElementDecl() {
+    if (myBuilder.getTokenType() != XML_ELEMENT_DECL_START) {
+      return;
+    }
+
+    PsiBuilder.Marker decl = myBuilder.mark();
+
+    addToken();
+
+    if (parseCompositeName()) {
+      decl.done(XML_ELEMENT_DECL);
+      return;
+    }
+
+    doParseContentSpec(false);
+
+    skipTillEndOfBlock();
+
+    decl.done(XML_ELEMENT_DECL);
+  }
+
+  private void skipTillEndOfBlock() {
+    while (!myBuilder.eof() &&
+           myBuilder.getTokenType() != XML_TAG_END &&
+           !isAnotherDeclStart(myBuilder.getTokenType())
+      ) {
+      if (myBuilder.getTokenType() == XML_COMMENT_START) parseComment();
+      else addToken();
+    }
+
+    if(myBuilder.getTokenType() == XML_TAG_END) addToken();
+  }
+
+  private boolean isAnotherDeclStart(IElementType type) {
+    return type == XML_ATTLIST_DECL_START || type == XML_ELEMENT_DECL_START;
+  }
+
+  private boolean parseName() {
+    if (myBuilder.getTokenType() == XML_NAME) {
+      addToken();
+
+      return true;
+    }
+
+    if (myBuilder.getTokenType() == XML_ENTITY_REF_TOKEN) {
+      parseEntityRef();
+      return true;
+    }
+
+    return false;
+  }
+
+  private void parseElementContentSpec() {
+    doParseContentSpec(true);
+  }
+
+  private void doParseContentSpec(boolean topLevel) {
+    if (!topLevel && myBuilder.rawLookup(0) != XML_WHITE_SPACE) {
+      myBuilder.error(XmlBundle.message("dtd.parser.message.whitespace.expected"));
+    } else if (!topLevel) {
+      final IElementType tokenType = myBuilder.getTokenType();
+      String tokenText;
+
+      if (tokenType != XML_LEFT_PAREN &&
+          tokenType != XML_ENTITY_REF_TOKEN &&
+          tokenType != XML_CONTENT_ANY &&
+          tokenType != XML_CONTENT_EMPTY &&
+          (tokenType != XML_NAME || ( !("-".equals(tokenText = myBuilder.getTokenText())) && !"O".equals(tokenText))) // sgml compatibility
+        ) {
+        PsiBuilder.Marker spec = myBuilder.mark();
+        spec.done(XML_ELEMENT_CONTENT_SPEC);
+        myBuilder.error(XmlBundle.message("dtd.parser.message.left.paren.or.entityref.or.empty.or.any.expected"));
+        return;
+      }
+    }
+
+    PsiBuilder.Marker spec = myBuilder.mark();
+    
+    parseElementContentSpecInner(topLevel);
+
+    spec.done(XML_ELEMENT_CONTENT_SPEC);
+  }
+
+  private boolean parseElementContentSpecInner(boolean topLevel) {
+    IElementType tokenType = myBuilder.getTokenType();
+    boolean endedWithDelimiter = false;
+
+    while (
+      tokenType != null &&
+      tokenType != XML_TAG_END &&
+      tokenType != XML_START_TAG_START &&
+      tokenType != XML_ELEMENT_DECL_START &&
+      tokenType != XML_RIGHT_PAREN &&
+      tokenType != XML_COMMENT_START
+    ) {
+      if (tokenType == XML_BAR && topLevel) {
+        addToken();
+        tokenType = myBuilder.getTokenType();
+        continue;
+      } else
+      if (tokenType == XML_LEFT_PAREN) {
+        if (!parseGroup()) return false;
+        endedWithDelimiter = false;
+      } else
+      if (tokenType == XML_ENTITY_REF_TOKEN) {
+        parseEntityRef();
+        endedWithDelimiter = false;
+      } else if (tokenType == XML_NAME ||
+                 tokenType == XML_CONTENT_EMPTY ||
+                 tokenType == XML_CONTENT_ANY ||
+                 tokenType == XML_PCDATA
+                 ) {
+        addToken();
+        endedWithDelimiter = false;
+      }
+      else {
+        myBuilder.error(XmlBundle.message("dtd.parser.message.name.or.entity.ref.expected"));
+        return false;
+      }
+
+      tokenType = myBuilder.getTokenType();
+
+      if (tokenType == XML_STAR ||
+          tokenType == XML_PLUS ||
+          tokenType == XML_QUESTION
+         ) {
+        addToken();
+        tokenType = myBuilder.getTokenType();
+
+        if (tokenType == XML_PLUS) {
+          addToken();
+          tokenType = myBuilder.getTokenType();
+        }
+      }
+      if (tokenType == XML_BAR || tokenType == XML_COMMA) {
+        addToken();
+        tokenType = myBuilder.getTokenType();
+        endedWithDelimiter = true;
+      }
+    }
+
+    if (endedWithDelimiter && tokenType == XML_RIGHT_PAREN) {
+      myBuilder.error(XmlBundle.message("dtd.parser.message.name.or.entity.ref.expected"));
+    }
+    return true;
+  }
+
+  private boolean parseGroup() {
+    PsiBuilder.Marker group = myBuilder.mark();
+    addToken();
+    boolean b = parseElementContentSpecInner(false);
+    if (b && myBuilder.getTokenType() == XML_RIGHT_PAREN) {
+      addToken();
+      group.done(XML_ELEMENT_CONTENT_GROUP);
+      return true;
+    } else if (b) {
+      myBuilder.error(XmlBundle.message("dtd.parser.message.rbrace.expected"));
+      group.done(XML_ELEMENT_CONTENT_GROUP);
+      return false;
+    }
+    group.done(XML_ELEMENT_CONTENT_GROUP);
+    return b;
+  }
+
+  private void parseAttlistDecl() {
+    if (myBuilder.getTokenType() != XML_ATTLIST_DECL_START) {
+      return;
+    }
+
+    PsiBuilder.Marker decl = myBuilder.mark();
+    addToken();
+
+    if (!parseName()) {
+      final IElementType tokenType = myBuilder.getTokenType();
+      if (tokenType == XML_LEFT_PAREN) {
+        parseGroup();
+      } else {
+        myBuilder.error(XmlBundle.message("dtd.parser.message.name.expected"));
+        decl.done(XML_ATTLIST_DECL);
+        return;
+      }
+    }
+
+    parseAttlistContent();
+
+    skipTillEndOfBlock();
+
+    decl.done(XML_ATTLIST_DECL);
+  }
+
+  private void parseAttlistContent() {
+    while (true) {
+      if (myBuilder.getTokenType() == XML_ENTITY_REF_TOKEN) {
+        parseEntityRef();
+      }
+      else if (myBuilder.getTokenType() == XML_COMMENT_START) {
+        parseComment();
+      } else if (parseAttributeDecl()) {
+      }
+      else {
+        break;
+      }
+    }
+  }
+
+  private boolean parseAttributeDecl() {
+    if (myBuilder.getTokenType() != XML_NAME) {
+      return false;
+    }
+
+    PsiBuilder.Marker decl = myBuilder.mark();
+
+    addToken();
+
+    final boolean b = parseAttributeContentSpec();
+    //if (myBuilder.getTokenType() == XML_COMMENT_START) parseComment();
+    decl.done(XML_ATTRIBUTE_DECL);
+    return b;
+  }
+
+  private boolean parseAttributeContentSpec() {
+    if (parseName()) {
+    }
+    else if (myBuilder.getTokenType() == XML_LEFT_PAREN) {
+      parseEnumeratedType();
+    }
+    else {
+      return true;
+    }
+
+    if (myBuilder.getTokenType() == XML_ATT_IMPLIED) {
+      addToken();
+    }
+    else if (myBuilder.getTokenType() == XML_ATT_REQUIRED) {
+      addToken();
+    }
+    else if (myBuilder.getTokenType() == XML_ATT_FIXED) {
+      addToken();
+
+      if (myBuilder.getTokenType() == XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+        parseAttributeValue();
+      }
+    }
+    else if (myBuilder.getTokenType() == XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+      parseAttributeValue();
+    }
+
+    return true;
+  }
+
+  private void parseEnumeratedType() {
+    PsiBuilder.Marker enumeratedType = myBuilder.mark();
+    addToken();
+
+    parseEnumeratedTypeContent();
+
+    if (myBuilder.getTokenType() == XML_RIGHT_PAREN) {
+      addToken();
+    }
+
+    enumeratedType.done(XML_ENUMERATED_TYPE);
+  }
+
+  private void parseEnumeratedTypeContent() {
+    while (true) {
+      if (myBuilder.getTokenType() == XML_ENTITY_REF_TOKEN) {
+        parseEntityRef();
+        continue;
+      }
+
+      if (myBuilder.getTokenType() != XML_NAME && myBuilder.getTokenType() != XML_BAR) break;
+      addToken();
+    }
+  }
+
+  private void parseDecl() {
+    if (myBuilder.getTokenType() != XML_DECL_START) {
+      return;
+    }
+
+    PsiBuilder.Marker decl = myBuilder.mark();
+    addToken();
+
+    parseAttributeList();
+
+    if (myBuilder.getTokenType() == XML_DECL_END) {
+      addToken();
+    }
+    else {
+      myBuilder.error(XmlErrorMessages.message("expected.prologue.tag.termination.expected"));
+    }
+
+    decl.done(XML_DECL);
+  }
+
+  private void parseAttributeList() {
+    int lastPosition = -1;
+    while (true) {
+      if (myBuilder.getTokenType() == XML_ENTITY_REF_TOKEN) {
+        parseEntityRef();
+        continue;
+      }
+
+      if (myBuilder.getTokenType() != XML_NAME) {
+        return;
+      }
+
+      if (lastPosition != -1) {
+        if (lastPosition == myBuilder.getCurrentOffset()) {
+          myBuilder.error(XmlErrorMessages.message("expected.whitespace"));
+          lastPosition = -1;
+        }
+      }
+
+      addToken();
+
+      if (myBuilder.getTokenType() != XML_EQ) {
+        myBuilder.error(XmlErrorMessages.message("expected.attribute.eq.sign"));
+        continue;
+      }
+
+      addToken();
+
+      if (myBuilder.getTokenType() != XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+        return;
+      }
+
+      addToken();
+
+      if (myBuilder.getTokenType() == XML_ATTRIBUTE_VALUE_TOKEN) {
+        addToken();
+        
+        if (myBuilder.getTokenType() == XML_ATTRIBUTE_VALUE_END_DELIMITER) {
+          lastPosition = myBuilder.getCurrentOffset();
+          addToken();
+        }
+        else {
+          lastPosition = -1;
+        }
+      }
+      else if (myBuilder.getTokenType() == XML_ATTRIBUTE_VALUE_END_DELIMITER) {
+        lastPosition = myBuilder.getCurrentOffset();
+        addToken();
+      }
+      else {
+        lastPosition = -1;
+      }
+    }
+  }
+
+  private int parseAttributeValue() {
+    if (myBuilder.getTokenType() != XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+      return -1;
+    }
+
+    PsiBuilder.Marker value = myBuilder.mark();
+
+    addToken();
+
+    while (true) {
+      if (myBuilder.getTokenType() == XML_ATTRIBUTE_VALUE_TOKEN) {
+        addToken();
+      }
+      else if (myBuilder.getTokenType() == XML_CHAR_ENTITY_REF) {
+        addToken();
+      }
+      else if (myBuilder.getTokenType() == XML_ENTITY_REF_TOKEN) {
+        parseEntityRef();
+      }
+      else {
+        break;
+      }
+    }
+
+    if (myBuilder.getTokenType() != XML_ATTRIBUTE_VALUE_END_DELIMITER) {
+      value.done(XML_ATTRIBUTE_VALUE);
+      return -1;
+    }
+
+    int tokenEnd = myBuilder.getCurrentOffset();
+    addToken();
+    value.done(XML_ATTRIBUTE_VALUE);
+    return tokenEnd;
+  }
+
+  private void addToken() {
+    myBuilder.advanceLexer();
+  }
+
+  private void parseTopLevelMarkupDecl() {
+    parseMarkupContent();
+    while (myBuilder.getTokenType() != null) {
+      if (myBuilder.getTokenType() == XML_ENTITY_REF_TOKEN) {
+        parseEntityRef();
+      }
+      else if (myBuilder.getTokenType() == XML_ENTITY_DECL_START) {
+        parseEntityDecl();
+      }
+      else {
+        myBuilder.advanceLexer();
+      }
+    }
+  }
+
+  private void parseAttrValue() {
+    while(myBuilder.getTokenType() != null) {
+      if (myBuilder.getTokenType() == XML_ENTITY_REF_TOKEN) {
+        parseEntityRef();
+      } else {
+        addToken();
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/HtmlBuilderDriver.java b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/HtmlBuilderDriver.java
new file mode 100644
index 0000000..571b1e4
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/HtmlBuilderDriver.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi.impl.source.parsing.xml;
+
+import com.intellij.lang.LanguageParserDefinitions;
+import com.intellij.lang.ParserDefinition;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.PsiBuilderFactory;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.html.HtmlParsing;
+
+public class HtmlBuilderDriver extends XmlBuilderDriver {
+  public HtmlBuilderDriver(final CharSequence text) {
+    super(text);
+  }
+
+  protected PsiBuilder createBuilderAndParse() {
+    final ParserDefinition htmlParserDef = LanguageParserDefinitions.INSTANCE.forLanguage(HTMLLanguage.INSTANCE);
+    assert htmlParserDef != null;
+
+    PsiBuilder b = PsiBuilderFactory.getInstance().createBuilder(htmlParserDef, htmlParserDef.createLexer(null), getText());
+    new HtmlParsing(b).parseDocument();
+    return b;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilder.java b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilder.java
new file mode 100644
index 0000000..0594a70
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilder.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi.impl.source.parsing.xml;
+
+import org.jetbrains.annotations.Nullable;
+
+public interface XmlBuilder {
+  void doctype(@Nullable final CharSequence publicId, @Nullable final CharSequence systemId, final int startOffset, final int endOffset);
+
+  enum ProcessingOrder {
+    TAGS,
+    TAGS_AND_TEXTS,
+    TAGS_AND_ATTRIBUTES,
+    TAGS_AND_ATTRIBUTES_AND_TEXTS
+  }
+
+  ProcessingOrder startTag(CharSequence localName, String namespace, int startoffset, int endoffset, final int headerEndOffset);
+  void endTag(CharSequence localName, String namespace, int startoffset, int endoffset);
+
+  void attribute(CharSequence name, CharSequence value, int startoffset, int endoffset);
+
+  void textElement(CharSequence display, CharSequence physical, int startoffset, int endoffset);
+
+  void entityRef(CharSequence ref, int startOffset, int endOffset);
+
+  void error(String message, int startOffset, int endOffset);
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilderDriver.java b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilderDriver.java
new file mode 100644
index 0000000..0518f9d
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilderDriver.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi.impl.source.parsing.xml;
+
+import com.intellij.lang.*;
+import com.intellij.lang.impl.PsiBuilderImpl;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.containers.Stack;
+import com.intellij.util.diff.FlyweightCapableTreeStructure;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+public class XmlBuilderDriver {
+  private final Stack<String> myNamespacesStack = new Stack<String>();
+  private final Stack<String> myPrefixesStack = new Stack<String>();
+  private final CharSequence myText;
+  @NonNls private static final String XMLNS = "xmlns";
+  @NonNls private static final String XMLNS_COLON = "xmlns:";
+
+  public XmlBuilderDriver(final CharSequence text) {
+    myText = text;
+  }
+
+  protected CharSequence getText() {
+    return myText;
+  }
+
+  public void addImplicitBinding(@NonNls @NotNull String prefix, @NonNls @NotNull String namespace) {
+    myNamespacesStack.push(namespace);
+    myPrefixesStack.push(prefix);
+  }
+
+  public void build(XmlBuilder builder) {
+    PsiBuilder b = createBuilderAndParse();
+
+    FlyweightCapableTreeStructure<LighterASTNode> structure = b.getLightTree();
+
+    LighterASTNode root = structure.getRoot();
+    root = structure.prepareForGetChildren(root);
+
+    final Ref<LighterASTNode[]> childrenRef = Ref.create(null);
+    final int count = structure.getChildren(root, childrenRef);
+    LighterASTNode[] children = childrenRef.get();
+
+    for (int i = 0; i < count; i++) {
+      LighterASTNode child = children[i];
+      final IElementType tt = child.getTokenType();
+      if (tt == XmlElementType.XML_TAG || tt == XmlElementType.HTML_TAG) {
+        processTagNode(b, structure, child, builder);
+      }
+      else if (tt == XmlElementType.XML_PROLOG) {
+        processPrologNode(b, builder, structure, child);
+      }
+    }
+
+    structure.disposeChildren(children, count);
+  }
+
+  private void processPrologNode(PsiBuilder psiBuilder,
+                                 XmlBuilder builder,
+                                 FlyweightCapableTreeStructure<LighterASTNode> structure,
+                                 LighterASTNode prolog) {
+    final Ref<LighterASTNode[]> prologChildren = new Ref<LighterASTNode[]>(null);
+    final int prologChildrenCount = structure.getChildren(structure.prepareForGetChildren(prolog), prologChildren);
+    for (int i = 0; i < prologChildrenCount; i++) {
+      LighterASTNode node = prologChildren.get()[i];
+      IElementType type = node.getTokenType();
+      if (type == XmlElementType.XML_DOCTYPE) {
+        processDoctypeNode(builder, structure, node);
+        break;
+      }
+      if (type == TokenType.ERROR_ELEMENT) {
+        processErrorNode(psiBuilder, node, builder);
+      }
+    }
+  }
+
+  private void processDoctypeNode(final XmlBuilder builder, final FlyweightCapableTreeStructure<LighterASTNode> structure,
+                                  final LighterASTNode doctype) {
+    final Ref<LighterASTNode[]> tokens = new Ref<LighterASTNode[]>(null);
+    final int tokenCount = structure.getChildren(structure.prepareForGetChildren(doctype), tokens);
+    if (tokenCount > 0) {
+      CharSequence publicId = null;
+      boolean afterPublic = false;
+      CharSequence systemId = null;
+      boolean afterSystem = false;
+      for (int i = 0; i < tokenCount; i++) {
+        LighterASTNode token = tokens.get()[i];
+        if (token.getTokenType() == XmlElementType.XML_DOCTYPE_PUBLIC) {
+          afterPublic = true;
+        }
+        else if (token.getTokenType() == XmlElementType.XML_DOCTYPE_SYSTEM) {
+          afterSystem = true;
+        }
+        else if (token.getTokenType() != TokenType.WHITE_SPACE && token.getTokenType() != XmlElementType.XML_COMMENT) {
+          if (token.getTokenType() == XmlElementType.XML_ATTRIBUTE_VALUE_TOKEN) {
+            if (afterPublic) publicId = getTokenText(token);
+            else if (afterSystem) systemId = getTokenText(token);
+          }
+          afterPublic = afterSystem = false;
+        }
+      }
+      builder.doctype(publicId, systemId, doctype.getStartOffset(), doctype.getEndOffset());
+    }
+  }
+
+  private CharSequence getTokenText(final LighterASTNode token) {
+    return myText.subSequence(token.getStartOffset(), token.getEndOffset());
+  }
+
+  protected PsiBuilder createBuilderAndParse() {
+    final ParserDefinition xmlParserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(XMLLanguage.INSTANCE);
+    assert xmlParserDefinition != null;
+
+    PsiBuilder b = PsiBuilderFactory.getInstance().createBuilder(xmlParserDefinition, xmlParserDefinition.createLexer(null), myText);
+    new XmlParsing(b).parseDocument();
+    return b;
+  }
+
+  private void processErrorNode(PsiBuilder psiBuilder, LighterASTNode node, XmlBuilder builder) {
+    assert node.getTokenType() == TokenType.ERROR_ELEMENT;
+    String message = PsiBuilderImpl.getErrorMessage(node);
+    assert message != null;
+    builder.error(message, node.getStartOffset(), node.getEndOffset());
+  }
+
+  private void processTagNode(PsiBuilder psiBuilder,
+                              FlyweightCapableTreeStructure<LighterASTNode> structure,
+                              LighterASTNode node,
+                              XmlBuilder builder) {
+    final IElementType nodeTT = node.getTokenType();
+    assert nodeTT == XmlElementType.XML_TAG || nodeTT == XmlElementType.HTML_TAG;
+
+    node = structure.prepareForGetChildren(node);
+
+    final Ref<LighterASTNode[]> childrenRef = Ref.create(null);
+    final int count = structure.getChildren(node, childrenRef);
+    LighterASTNode[] children = childrenRef.get();
+
+    int stackFrameSize = myNamespacesStack.size();
+    CharSequence tagName = "";
+    int headerEndOffset = node.getEndOffset();
+    for (int i = 0; i < count; i++) {
+      LighterASTNode child = children[i];
+      final IElementType tt = child.getTokenType();
+      if (tt == XmlElementType.XML_ATTRIBUTE) checkForXmlns(child, structure);
+      if (tt == XmlTokenType.XML_TAG_END || tt == XmlTokenType.XML_EMPTY_ELEMENT_END) {
+        headerEndOffset = child.getEndOffset();
+        break;
+      }
+      if (tt == XmlTokenType.XML_NAME || tt == XmlTokenType.XML_TAG_NAME) {
+        tagName = getTokenText(child);
+      }
+    }
+
+    CharSequence localName = XmlUtil.getLocalName(tagName);
+    String namespace = getNamespace(tagName);
+
+    XmlBuilder.ProcessingOrder order = builder.startTag(localName, namespace, node.getStartOffset(), node.getEndOffset(), headerEndOffset);
+    boolean processAttrs = order == XmlBuilder.ProcessingOrder.TAGS_AND_ATTRIBUTES ||
+                           order == XmlBuilder.ProcessingOrder.TAGS_AND_ATTRIBUTES_AND_TEXTS;
+
+    boolean processTexts = order == XmlBuilder.ProcessingOrder.TAGS_AND_TEXTS ||
+                           order == XmlBuilder.ProcessingOrder.TAGS_AND_ATTRIBUTES_AND_TEXTS;
+
+    for (int i = 0; i < count; i++) {
+      LighterASTNode child = children[i];
+      IElementType tt = child.getTokenType();
+      if (tt == TokenType.ERROR_ELEMENT) processErrorNode(psiBuilder, child, builder);
+      if (tt == XmlElementType.XML_TAG || tt == XmlElementType.HTML_TAG) processTagNode(psiBuilder, structure, child, builder);
+      if (processAttrs && tt == XmlElementType.XML_ATTRIBUTE) processAttributeNode(child, structure, builder);
+      if (processTexts && tt == XmlElementType.XML_TEXT) processTextNode(structure, child, builder);
+      if (tt == XmlElementType.XML_ENTITY_REF) builder.entityRef(getTokenText(child), child.getStartOffset(), child.getEndOffset());
+    }
+
+    builder.endTag(localName, namespace, node.getStartOffset(), node.getEndOffset());
+
+    int framesToDrop = myNamespacesStack.size() - stackFrameSize;
+    for (int i = 0; i < framesToDrop; i++) {
+      myNamespacesStack.pop();
+      myPrefixesStack.pop();
+    }
+
+    structure.disposeChildren(children, count);
+  }
+
+  private void processTextNode(FlyweightCapableTreeStructure<LighterASTNode> structure, LighterASTNode node, XmlBuilder builder) {
+    node = structure.prepareForGetChildren(node);
+
+    final Ref<LighterASTNode[]> childrenRef = Ref.create(null);
+    final int count = structure.getChildren(node, childrenRef);
+    LighterASTNode[] children = childrenRef.get();
+
+    for (int i = 0; i < count; i++) {
+      LighterASTNode child = children[i];
+      IElementType tt = child.getTokenType();
+      final int start = child.getStartOffset();
+      final int end = child.getEndOffset();
+      final CharSequence physical = getTokenText(child);
+
+      if (XmlTokenType.COMMENTS.contains(tt)) continue;
+
+      if (tt == XmlTokenType.XML_CDATA_START || tt == XmlTokenType.XML_CDATA_END) {
+        builder.textElement("", physical, start, end);
+      }
+      else if (tt == XmlElementType.XML_CDATA) {
+        processTextNode(structure, child, builder);
+      }
+      else if (tt == XmlTokenType.XML_CHAR_ENTITY_REF) {
+        builder.textElement(new String(new char[] {XmlUtil.getCharFromEntityRef(physical.toString())}), physical, start, end);
+      }
+      else {
+        builder.textElement(physical, physical, start, end);
+      }
+    }
+
+    structure.disposeChildren(children, count);
+  }
+
+  private void processAttributeNode(final LighterASTNode attrNode, FlyweightCapableTreeStructure<LighterASTNode> structure, XmlBuilder builder) {
+    builder.attribute(getAttributeName(attrNode, structure), getAttributeValue(attrNode, structure), attrNode.getStartOffset(), attrNode.getEndOffset());
+  }
+
+  private String getNamespace(final CharSequence tagName) {
+    final String namespacePrefix;
+    int pos = StringUtil.indexOf(tagName, ':');
+    if (pos == -1) {
+      namespacePrefix = "";
+    }
+    else {
+      namespacePrefix = tagName.subSequence(0, pos).toString();
+    }
+
+    for (int i = myPrefixesStack.size() - 1; i >= 0; i--) {
+      if (namespacePrefix.equals(myPrefixesStack.get(i))) return myNamespacesStack.get(i);
+    }
+
+    return "";
+  }
+
+  private void checkForXmlns(LighterASTNode attrNode, FlyweightCapableTreeStructure<LighterASTNode> structure) {
+    final CharSequence name = getAttributeName(attrNode, structure);
+    if (Comparing.equal(name, XMLNS)) {
+      myPrefixesStack.push("");
+      myNamespacesStack.push(getAttributeValue(attrNode, structure).toString());
+    }
+    else if (StringUtil.startsWith(name, XMLNS_COLON)) {
+      myPrefixesStack.push(name.subSequence(XMLNS_COLON.length(), name.length()).toString());
+      myNamespacesStack.push(getAttributeValue(attrNode, structure).toString());
+    }
+  }
+
+
+  private CharSequence getAttributeName(LighterASTNode attrNode, FlyweightCapableTreeStructure<LighterASTNode> structure) {
+    return findTextByTokenType(attrNode, structure, XmlTokenType.XML_NAME);
+  }
+
+  private CharSequence getAttributeValue(LighterASTNode attrNode, FlyweightCapableTreeStructure<LighterASTNode> structure) {
+    final CharSequence fullValue = findTextByTokenType(attrNode, structure, XmlElementType.XML_ATTRIBUTE_VALUE);
+    int start = 0;
+    if (fullValue.length() > 0 && fullValue.charAt(0) == '\"') start++;
+
+    int end = fullValue.length();
+    if (fullValue.length() > start && fullValue.charAt(fullValue.length() - 1) == '\"') end--;
+
+    return fullValue.subSequence(start, end);
+  }
+
+  private CharSequence findTextByTokenType(LighterASTNode attrNode,
+                                           FlyweightCapableTreeStructure<LighterASTNode> structure,
+                                           IElementType tt) {
+    attrNode = structure.prepareForGetChildren(attrNode);
+
+    final Ref<LighterASTNode[]> childrenRef = Ref.create(null);
+    final int count = structure.getChildren(attrNode, childrenRef);
+    LighterASTNode[] children = childrenRef.get();
+
+    CharSequence name = "";
+    for (int i = 0; i < count; i++) {
+      LighterASTNode child = children[i];
+      if (child.getTokenType() == tt) {
+        name = getTokenText(child);
+        break;
+      }
+    }
+
+    structure.disposeChildren(children, count);
+
+    return name;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParser.java b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParser.java
new file mode 100644
index 0000000..02f336a
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParser.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi.impl.source.parsing.xml;
+
+import com.intellij.lang.*;
+import com.intellij.lang.impl.PsiBuilderImpl;
+import com.intellij.openapi.util.Ref;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.ThreeState;
+import com.intellij.util.TripleFunction;
+import com.intellij.util.diff.FlyweightCapableTreeStructure;
+import org.jetbrains.annotations.NotNull;
+
+public class XmlParser implements PsiParser {
+  // tries to match an old and new XmlTag by name
+  private static final TripleFunction<ASTNode,LighterASTNode,FlyweightCapableTreeStructure<LighterASTNode>,ThreeState>
+    REPARSE_XML_TAG_BY_NAME = new TripleFunction<ASTNode, LighterASTNode, FlyweightCapableTreeStructure<LighterASTNode>, ThreeState>() {
+      @Override
+      public ThreeState fun(ASTNode oldNode,
+                            LighterASTNode newNode,
+                            FlyweightCapableTreeStructure<LighterASTNode> structure) {
+        if (oldNode instanceof XmlTag && newNode.getTokenType() == XmlElementType.XML_TAG) {
+          String oldName = ((XmlTag)oldNode).getName();
+          Ref<LighterASTNode[]> childrenRef = Ref.create(null);
+          int count = structure.getChildren(newNode, childrenRef);
+          if (count < 3) return ThreeState.UNSURE;
+          LighterASTNode[] children = childrenRef.get();
+          if (children[0].getTokenType() != XmlTokenType.XML_START_TAG_START) return ThreeState.UNSURE;
+          if (children[1].getTokenType() != XmlTokenType.XML_NAME) return ThreeState.UNSURE;
+          if (children[2].getTokenType() != XmlTokenType.XML_TAG_END) return ThreeState.UNSURE;
+          LighterASTTokenNode name = (LighterASTTokenNode)children[1];
+          CharSequence newName = name.getText();
+          if (!oldName.equals(newName)) return ThreeState.NO;
+        }
+
+        return ThreeState.UNSURE;
+      }
+    };
+
+  @NotNull
+  public ASTNode parse(final IElementType root, final PsiBuilder builder) {
+    builder.enforceCommentTokens(TokenSet.EMPTY);
+    builder.putUserDataUnprotected(PsiBuilderImpl.CUSTOM_COMPARATOR, REPARSE_XML_TAG_BY_NAME);
+    final PsiBuilder.Marker file = builder.mark();
+    new XmlParsing(builder).parseDocument();
+    file.done(root);
+    return builder.getTreeBuilt();
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParsing.java b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParsing.java
new file mode 100644
index 0000000..a98e5db
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParsing.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.parsing.xml;
+
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.psi.tree.CustomParsingType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.ILazyParseableElementType;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.containers.Stack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static com.intellij.psi.xml.XmlElementType.*;
+
+/*
+ * @author max
+ */
+public class XmlParsing {
+  private static final int BALANCING_DEPTH_THRESHOLD = 1000;
+
+  protected final PsiBuilder myBuilder;
+  private final Stack<String> myTagNamesStack = new Stack<String>();
+
+  public XmlParsing(final PsiBuilder builder) {
+    myBuilder = builder;
+  }
+
+  public void parseDocument() {
+    final PsiBuilder.Marker document = mark();
+
+    while (isCommentToken(token())) {
+      parseComment();
+    }
+
+    parseProlog();
+
+    int rootTagCount = 0;
+    PsiBuilder.Marker error = null;
+    while (!eof()) {
+      final IElementType tt = token();
+      if (tt == XML_START_TAG_START) {
+        error = flushError(error);
+        rootTagCount++;
+        parseTag(rootTagCount > 1);
+      }
+      else if (isCommentToken(tt)) {
+        error = flushError(error);
+        parseComment();
+      }
+      else if (tt == XML_PI_START) {
+        error = flushError(error);
+        parseProcessingInstruction();
+      }
+      else if (tt == XML_REAL_WHITE_SPACE) {
+        error = flushError(error);
+        advance();
+      }
+      else {
+        if (error == null) error = mark();
+        advance();
+      }
+    }
+
+    if (error != null) {
+      error.error(XmlErrorMessages.message("top.level.element.is.not.completed"));
+    }
+
+    if (rootTagCount == 0) {
+      final PsiBuilder.Marker rootTag = mark();
+      error = mark();
+      error.error(XmlErrorMessages.message("xml.parsing.absent.root.tag"));
+      rootTag.done(XmlElementType.XML_TAG);
+    }
+
+    document.done(XmlElementType.XML_DOCUMENT);
+  }
+
+  @Nullable
+  private static PsiBuilder.Marker flushError(PsiBuilder.Marker error) {
+    if (error != null) {
+      error.error(XmlErrorMessages.message("xml.parsing.unexpected.tokens"));
+      error = null;
+    }
+    return error;
+  }
+
+  private void parseDoctype() {
+    assert token() == XML_DOCTYPE_START : "Doctype start expected";
+    final PsiBuilder.Marker doctype = mark();
+    advance();
+
+    while (token() != XML_DOCTYPE_END && !eof()) advance();
+    if (eof()) {
+      error(XmlErrorMessages.message("xml.parsing.unexpected.end.of.file"));
+    }
+    else {
+      advance();
+    }
+
+    doctype.done(XML_DOCTYPE);
+  }
+
+  protected void parseTag(boolean multipleRootTagError) {
+    assert token() == XML_START_TAG_START : "Tag start expected";
+    final PsiBuilder.Marker tag = mark();
+
+    final String tagName = parseTagHeader(multipleRootTagError, tag);
+    if (tagName == null) return;
+
+    final PsiBuilder.Marker content = mark();
+    parseTagContent();
+
+    if (token() == XML_END_TAG_START) {
+      final PsiBuilder.Marker footer = mark();
+      advance();
+
+      if (token() == XML_NAME) {
+        String endName = myBuilder.getTokenText();
+        if (!tagName.equals(endName) && myTagNamesStack.contains(endName)) {
+          footer.rollbackTo();
+          myTagNamesStack.pop();
+          tag.doneBefore(XmlElementType.XML_TAG, content, XmlErrorMessages.message("named.element.is.not.closed", tagName));
+          content.drop();
+          return;
+        }
+
+        advance();
+      }
+      footer.drop();
+
+      while (token() != XmlTokenType.XML_TAG_END && token() != XmlTokenType.XML_START_TAG_START && token() != XmlTokenType.XML_END_TAG_START && !eof()) {
+        error(XmlErrorMessages.message("xml.parsing.unexpected.token"));
+        advance();
+      }
+
+      if (token() == XML_TAG_END) {
+        advance();
+      }
+      else {
+        error(XmlErrorMessages.message("xml.parsing.closing.tag.is.not.done"));
+      }
+    }
+    else {
+      error(XmlErrorMessages.message("xml.parsing.unexpected.end.of.file"));
+    }
+
+    content.drop();
+    myTagNamesStack.pop();
+    tag.done(XmlElementType.XML_TAG);
+  }
+
+  @Nullable
+  private String parseTagHeader(final boolean multipleRootTagError, final PsiBuilder.Marker tag) {
+    if (multipleRootTagError) {
+      final PsiBuilder.Marker error = mark();
+      advance();
+      error.error(XmlErrorMessages.message("xml.parsing.multiple.root.tags"));
+    }
+    else {
+      advance();
+    }
+
+    final String tagName;
+    if (token() != XML_NAME) {
+      error(XmlErrorMessages.message("xml.parsing.tag.name.expected"));
+      tagName = "";
+    }
+    else {
+      tagName = myBuilder.getTokenText();
+      assert tagName != null;
+      advance();
+    }
+    myTagNamesStack.push(tagName);
+
+    do {
+      final IElementType tt = token();
+      if (tt == XML_NAME) {
+        parseAttribute();
+      }
+      else if (tt == XML_CHAR_ENTITY_REF || tt == XML_ENTITY_REF_TOKEN) {
+        parseReference();
+      }
+      else {
+        break;
+      }
+    }
+    while (true);
+
+    if (token() == XML_EMPTY_ELEMENT_END) {
+      advance();
+      myTagNamesStack.pop();
+      tag.done(XmlElementType.XML_TAG);
+      return null;
+    }
+
+    if (token() == XML_TAG_END) {
+      advance();
+    }
+    else {
+      error(XmlErrorMessages.message("tag.start.is.not.closed"));
+      myTagNamesStack.pop();
+      tag.done(XmlElementType.XML_TAG);
+      return null;
+    }
+
+    if (myTagNamesStack.size() > BALANCING_DEPTH_THRESHOLD) {
+      error(XmlErrorMessages.message("way.too.unbalanced"));
+      tag.done(XmlElementType.XML_TAG);
+      return null;
+    }
+
+    return tagName;
+  }
+
+  public void parseTagContent() {
+    PsiBuilder.Marker xmlText = null;
+    while (token() != XML_END_TAG_START && !eof()) {
+      final IElementType tt = token();
+      if (tt == XML_START_TAG_START) {
+        xmlText = terminateText(xmlText);
+        parseTag(false);
+      }
+      else if (tt == XML_PI_START) {
+        xmlText = terminateText(xmlText);
+        parseProcessingInstruction();
+      }
+      else if (tt == XML_ENTITY_REF_TOKEN) {
+        xmlText = terminateText(xmlText);
+        parseReference();
+      }
+      else if (tt == XML_CHAR_ENTITY_REF) {
+        xmlText = startText(xmlText);
+        parseReference();
+      }
+      else if (tt == XML_CDATA_START) {
+        xmlText = startText(xmlText);
+        parseCData();
+      }
+      else if (isCommentToken(tt)) {
+        xmlText = terminateText(xmlText);
+        parseComment();
+      }
+      else if (tt == XML_BAD_CHARACTER) {
+        xmlText = startText(xmlText);
+        final PsiBuilder.Marker error = mark();
+        advance();
+        error.error(XmlErrorMessages.message("unescaped.ampersand.or.nonterminated.character.entity.reference"));
+      }
+      else if (tt instanceof CustomParsingType || tt instanceof ILazyParseableElementType) {
+        xmlText = terminateText(xmlText);
+        advance();
+      }
+      else {
+        xmlText = startText(xmlText);
+        advance();
+      }
+    }
+
+    terminateText(xmlText);
+  }
+
+  protected boolean isCommentToken(final IElementType tt) {
+    return tt == XML_COMMENT_START;
+  }
+
+  @NotNull
+  private PsiBuilder.Marker startText(@Nullable PsiBuilder.Marker xmlText) {
+    if (xmlText == null) {
+      xmlText = mark();
+      assert xmlText != null;
+    }
+    return xmlText;
+  }
+
+  protected final PsiBuilder.Marker mark() {
+    return myBuilder.mark();
+  }
+
+  @Nullable
+  private static PsiBuilder.Marker terminateText(@Nullable PsiBuilder.Marker xmlText) {
+    if (xmlText != null) {
+      xmlText.done(XML_TEXT);
+      xmlText = null;
+    }
+    return xmlText;
+  }
+
+  private void parseCData() {
+    assert token() == XML_CDATA_START;
+    final PsiBuilder.Marker cdata = mark();
+    while (token() != XML_CDATA_END && !eof()) {
+      advance();
+    }
+
+    if (!eof()) {
+      advance();
+    }
+
+    cdata.done(XML_CDATA);
+  }
+
+  protected void parseComment() {
+    final PsiBuilder.Marker comment = mark();
+    advance();
+    while (true) {
+      final IElementType tt = token();
+      if (tt == XML_COMMENT_CHARACTERS|| tt == XML_CONDITIONAL_COMMENT_START
+        || tt == XML_CONDITIONAL_COMMENT_START_END || tt == XML_CONDITIONAL_COMMENT_END_START
+        || tt == XML_CONDITIONAL_COMMENT_END) {
+        advance();
+        continue;
+      }
+      else if (tt == XML_BAD_CHARACTER) {
+        final PsiBuilder.Marker error = mark();
+        advance();
+        error.error(XmlErrorMessages.message("xml.parsing.bad.character"));
+        continue;
+      }
+      if (tt == XML_COMMENT_END) {
+        advance();
+      }
+      break;
+    }
+    comment.done(XML_COMMENT);
+  }
+
+  private void parseReference() {
+    if (token() == XML_CHAR_ENTITY_REF) {
+      advance();
+    }
+    else if (token() == XML_ENTITY_REF_TOKEN) {
+      final PsiBuilder.Marker ref = mark();
+      advance();
+      ref.done(XML_ENTITY_REF);
+    }
+    else {
+      assert false : "Unexpected token";
+    }
+  }
+
+  private void parseAttribute() {
+    assert token() == XML_NAME;
+    final PsiBuilder.Marker att = mark();
+    advance();
+    if (token() == XML_EQ) {
+      advance();
+      parseAttributeValue();
+      att.done(XML_ATTRIBUTE);
+    }
+    else {
+      error(XmlErrorMessages.message("expected.attribute.eq.sign"));
+      att.done(XML_ATTRIBUTE);
+    }
+  }
+
+  private void parseAttributeValue() {
+    final PsiBuilder.Marker attValue = mark();
+    if (token() == XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+      while (true) {
+        final IElementType tt = token();
+        if (tt == null || tt == XML_ATTRIBUTE_VALUE_END_DELIMITER || tt == XML_END_TAG_START || tt == XML_EMPTY_ELEMENT_END ||
+            tt == XML_START_TAG_START) {
+          break;
+        }
+
+        if (tt == XML_BAD_CHARACTER) {
+          final PsiBuilder.Marker error = mark();
+          advance();
+          error.error(XmlErrorMessages.message("unescaped.ampersand.or.nonterminated.character.entity.reference"));
+        }
+        else if (tt == XML_ENTITY_REF_TOKEN) {
+          parseReference();
+        }
+        else {
+          advance();
+        }
+      }
+
+      if (token() == XML_ATTRIBUTE_VALUE_END_DELIMITER) {
+        advance();
+      }
+      else {
+        error(XmlErrorMessages.message("xml.parsing.unclosed.attribute.value"));
+      }
+    }
+    else {
+      error(XmlErrorMessages.message("xml.parsing.attribute.value.expected"));
+    }
+
+    attValue.done(XML_ATTRIBUTE_VALUE);
+  }
+
+  private void parseProlog() {
+    final PsiBuilder.Marker prolog = mark();
+    while (true) {
+      final IElementType tt = token();
+      if (tt == XML_PI_START) {
+        parseProcessingInstruction();
+      }
+      else if (tt == XML_DOCTYPE_START) {
+        parseDoctype();
+      }
+      else if (isCommentToken(tt)) {
+        parseComment();
+      }
+      else if (tt == XML_REAL_WHITE_SPACE) {
+        advance();
+      }
+      else {
+        break;
+      }
+    }
+    prolog.done(XML_PROLOG);
+  }
+
+  private void parseProcessingInstruction() {
+    assert token() == XML_PI_START;
+    final PsiBuilder.Marker pi = mark();
+    advance();
+    if (token() != XML_NAME) {
+      error(XmlErrorMessages.message("xml.parsing.processing.instruction.name.expected"));
+    }
+    else {
+      advance();
+    }
+
+    final IElementType tokenType = token();
+    if (tokenType == XML_TAG_CHARACTERS) {
+      while (token() == XML_TAG_CHARACTERS) {
+        advance();
+      }
+    } else {
+      while (token() == XML_NAME) {
+        advance();
+        if (token() == XML_EQ) {
+          advance();
+        }
+        else {
+          error(XmlErrorMessages.message("expected.attribute.eq.sign"));
+        }
+        parseAttributeValue();
+      }
+    }
+
+    if (token() == XML_PI_END) {
+      advance();
+    }
+    else {
+      error(XmlErrorMessages.message("xml.parsing.unterminated.processing.instruction"));
+    }
+
+    pi.done(XML_PROCESSING_INSTRUCTION);
+  }
+
+  @Nullable
+  protected final IElementType token() {
+    return myBuilder.getTokenType();
+  }
+
+  protected final boolean eof() {
+    return myBuilder.eof();
+  }
+
+  protected final void advance() {
+    myBuilder.advanceLexer();
+  }
+
+  private void error(final String message) {
+    myBuilder.error(message);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlAttributeManipulator.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlAttributeManipulator.java
new file mode 100644
index 0000000..0039c32
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlAttributeManipulator.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.psi.impl.source.resolve.reference.impl.manipulators;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.AbstractElementManipulator;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.util.IncorrectOperationException;
+
+/**
+ * @author Gregory.Shrago
+ */
+public class XmlAttributeManipulator extends AbstractElementManipulator<XmlAttribute> {
+
+  private final static Logger LOG = Logger.getInstance(XmlAttributeManipulator.class);
+
+  public XmlAttribute handleContentChange(XmlAttribute attribute, TextRange range, String newContent) throws IncorrectOperationException {
+    String attr = attribute.getText();
+    ASTNode astNode = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(attribute.getNode());
+    assert astNode != null;
+    PsiElement namePsi = astNode.getPsi();
+    int startOffsetInParent = namePsi.getStartOffsetInParent();
+    TextRange nameRange = new TextRange(startOffsetInParent, startOffsetInParent + namePsi.getTextLength());
+
+    if (nameRange.contains(range)) {
+      String content = attr.substring(0, range.getStartOffset()) + newContent + attr.substring(range.getEndOffset(), nameRange.getEndOffset());
+
+      attribute.setName(content);
+    } else {
+      final XmlAttributeValue value = attribute.getValueElement();
+
+      if (value == null) {
+        assert range.getStartOffset() == 0 && range.getEndOffset() == 0;
+        attribute.setValue(newContent);
+        return attribute;
+      }
+      final StringBuilder replacement = new StringBuilder(value.getText());
+      int offset = value.getTextRange().getStartOffset() - attribute.getTextRange().getStartOffset();
+
+      replacement.replace(
+        range.getStartOffset() - offset,
+        range.getEndOffset() - offset,
+        newContent
+      );
+      attribute.setValue(replacement.toString());
+    }
+    return attribute;
+  }
+
+  public TextRange getRangeInElement(final XmlAttribute attribute) {
+    final XmlAttributeValue value = attribute.getValueElement();
+    if (value == null) return TextRange.from(0, 0);
+    TextRange range = attribute.getValueTextRange();
+    if (range == null) {
+      LOG.error("Null range in " + attribute + " '" + attribute.getText() + "'");
+    }
+    return range.shiftRight(value.getStartOffsetInParent());
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlAttributeValueManipulator.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlAttributeValueManipulator.java
new file mode 100644
index 0000000..f646e4e
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlAttributeValueManipulator.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.manipulators;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.AbstractElementManipulator;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.CheckUtil;
+import com.intellij.psi.impl.source.tree.CompositeElement;
+import com.intellij.psi.impl.source.tree.Factory;
+import com.intellij.psi.impl.source.tree.LeafElement;
+import com.intellij.psi.impl.source.tree.SharedImplUtil;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.CharTable;
+import com.intellij.util.IncorrectOperationException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 06.01.2004
+ * Time: 20:00:23
+ * To change this template use Options | File Templates.
+ */
+public class XmlAttributeValueManipulator extends AbstractElementManipulator<XmlAttributeValue> {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.reference.impl.manipulators.XmlAttributeValueManipulator");
+
+  public XmlAttributeValue handleContentChange(XmlAttributeValue element, TextRange range, String newContent) throws IncorrectOperationException{
+
+    CheckUtil.checkWritable(element);
+    final CompositeElement attrNode = (CompositeElement)element.getNode();
+    final ASTNode valueNode = attrNode.findLeafElementAt(range.getStartOffset());
+    LOG.assertTrue(valueNode != null, "Leaf not found in " + attrNode + " at offset " + range.getStartOffset());
+    final PsiElement elementToReplace = valueNode.getPsi();
+
+    String text;
+    try {
+      text = elementToReplace.getText();
+      final int offsetInParent = elementToReplace.getStartOffsetInParent();
+      String textBeforeRange = text.substring(0, range.getStartOffset() - offsetInParent);
+      String textAfterRange = text.substring(range.getEndOffset()- offsetInParent, text.length());
+      text = textBeforeRange + newContent + textAfterRange;
+    } catch(StringIndexOutOfBoundsException e) {
+      LOG.error("Range: " + range + " in text: '" + element.getText() + "'", e);
+      throw e;
+    }
+    final CharTable charTableByTree = SharedImplUtil.findCharTableByTree(attrNode);
+    final LeafElement newValueElement = Factory.createSingleLeafElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN, text, charTableByTree, element.getManager());
+
+    attrNode.replaceChildInternal(valueNode, newValueElement);
+    return element;
+  }
+
+  public TextRange getRangeInElement(final XmlAttributeValue xmlAttributeValue) {
+    final PsiElement child = xmlAttributeValue.getFirstChild();
+    if (child == null) {
+      return TextRange.EMPTY_RANGE;
+    }
+    final ASTNode node = child.getNode();
+    assert node != null;
+    final int textLength = xmlAttributeValue.getTextLength();
+    if (node.getElementType() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+      return new TextRange(1, textLength <= 1 ? 1 : textLength - 1);
+    } else {
+      return new TextRange(0, textLength);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTagManipulator.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTagManipulator.java
new file mode 100644
index 0000000..1803c58
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTagManipulator.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.manipulators;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.AbstractElementManipulator;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTagValue;
+import com.intellij.psi.xml.XmlText;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class XmlTagManipulator extends AbstractElementManipulator<XmlTag> {
+
+  public XmlTag handleContentChange(XmlTag tag, TextRange range, String newContent) throws IncorrectOperationException {
+    
+    final StringBuilder replacement = new StringBuilder( tag.getValue().getText() );
+    final int valueOffset = tag.getValue().getTextRange().getStartOffset() - tag.getTextOffset();
+
+    replacement.replace(
+      range.getStartOffset() - valueOffset,
+      range.getEndOffset() - valueOffset,
+      newContent
+    );
+    tag.getValue().setText(replacement.toString());
+    return tag;
+  }
+
+  public TextRange getRangeInElement(final XmlTag tag) {
+    if (tag.getSubTags().length > 0) {
+      // Text range in tag with subtags is not supported, return empty range, consider making this function nullable.
+      return TextRange.EMPTY_RANGE;
+    }
+
+    final XmlTagValue value = tag.getValue();
+    final XmlText[] texts = value.getTextElements();
+    switch (texts.length) {
+      case 0:
+        return value.getTextRange().shiftRight(-tag.getTextOffset());
+      case 1:
+        return getValueRange(texts[0]);
+      default:
+        return TextRange.EMPTY_RANGE;
+    }
+  }
+
+  private static TextRange getValueRange(final XmlText xmlText) {
+    final int offset = xmlText.getStartOffsetInParent();
+    final String value = xmlText.getValue();
+    final String trimmed = value.trim();
+    final int i = value.indexOf(trimmed);
+    final int start = xmlText.displayToPhysical(i) + offset;    
+    return trimmed.length() == 0 ? new TextRange(start, start) : new TextRange(start, xmlText.displayToPhysical(i + trimmed.length() - 1) + offset + 1);
+  }
+
+  public static TextRange[] getValueRanges(final @NotNull XmlTag tag) {
+    final XmlTagValue value = tag.getValue();
+    final XmlText[] texts = value.getTextElements();
+    if (texts.length == 0) {
+      return new TextRange[] { value.getTextRange().shiftRight(-tag.getTextOffset()) };
+    } else {
+      final TextRange[] ranges = new TextRange[texts.length];
+      for (int i = 0; i < texts.length; i++) {
+        ranges[i] = getValueRange(texts[i]);
+      }
+      return ranges;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTextManipulator.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTextManipulator.java
new file mode 100644
index 0000000..f7baccc
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTextManipulator.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.psi.impl.source.resolve.reference.impl.manipulators;
+
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.AbstractElementManipulator;
+import com.intellij.psi.xml.XmlText;
+import com.intellij.util.IncorrectOperationException;
+
+/**
+ * @author Gregory.Shrago
+ */
+public class XmlTextManipulator extends AbstractElementManipulator<XmlText> {
+
+  public XmlText handleContentChange(XmlText text, TextRange range, String newContent) throws IncorrectOperationException {
+    final String newValue;
+    final String value = text.getValue();
+    if (range.equals(getRangeInElement(text))) {
+      newValue = newContent;
+    }
+    else {
+      final StringBuilder replacement = new StringBuilder(value);
+      replacement.replace(
+        range.getStartOffset(),
+        range.getEndOffset(),
+        newContent
+      );
+      newValue = replacement.toString();
+    }
+    if (Comparing.equal(value, newValue)) return text;
+    if (newValue.length() > 0) {
+      text.setValue(newValue);
+    }
+    else {
+      text.deleteChildRange(text.getFirstChild(), text.getLastChild());
+    }
+    return text;
+  }
+
+  public TextRange getRangeInElement(final XmlText text) {
+    return getValueRange(text);
+  }
+
+  private static TextRange getValueRange(final XmlText xmlText) {
+    final String value = xmlText.getValue();
+    final int i = value.indexOf(value);
+    final int start = xmlText.displayToPhysical(i);
+    return value.length() == 0 ? new TextRange(start, start) : new TextRange(start, xmlText.displayToPhysical(i + value.length() - 1) + 1);
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTokenManipulator.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTokenManipulator.java
new file mode 100644
index 0000000..e21796a
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTokenManipulator.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.manipulators;
+
+import com.intellij.lang.ASTFactory;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.AbstractElementManipulator;
+import com.intellij.psi.impl.source.DummyHolderFactory;
+import com.intellij.psi.impl.source.tree.FileElement;
+import com.intellij.psi.impl.source.tree.LeafElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.util.IncorrectOperationException;
+
+/**
+ * @author ven
+ */
+public class XmlTokenManipulator extends AbstractElementManipulator<XmlToken> {
+  public XmlToken handleContentChange(XmlToken xmlToken, TextRange range, String newContent) throws IncorrectOperationException {
+    String oldText = xmlToken.getText();
+    String newText = oldText.substring(0, range.getStartOffset()) + newContent + oldText.substring(range.getEndOffset());
+    IElementType tokenType = xmlToken.getTokenType();
+
+    FileElement holder = DummyHolderFactory.createHolder(xmlToken.getManager(), null).getTreeElement();
+    LeafElement leaf = ASTFactory.leaf(tokenType, holder.getCharTable().intern(newText));
+    holder.rawAddChildren(leaf);
+    return (XmlToken)xmlToken.replace(leaf.getPsi());
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/AttributeValueSelfReference.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/AttributeValueSelfReference.java
new file mode 100644
index 0000000..9ecba6f
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/AttributeValueSelfReference.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author peter
+*/
+public class AttributeValueSelfReference extends BasicAttributeValueReference {
+  public AttributeValueSelfReference(final PsiElement element) {
+    super(element);
+  }
+
+  public AttributeValueSelfReference(final PsiElement element, int offset) {
+    super(element, offset);
+  }
+
+  public AttributeValueSelfReference(final PsiElement element, TextRange range) {
+    super(element, range);
+  }
+
+  @Nullable
+  public PsiElement resolve() {
+    return myElement;
+  }
+
+  @NotNull
+  public Object[] getVariants() {
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
+  }
+
+  public boolean isSoft() {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/BasicAttributeValueReference.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/BasicAttributeValueReference.java
new file mode 100644
index 0000000..b3c0fbc
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/BasicAttributeValueReference.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.ElementManipulators;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author peter
+*/
+public abstract class BasicAttributeValueReference implements PsiReference {
+  protected PsiElement myElement;
+  protected TextRange myRange;
+
+  public BasicAttributeValueReference(final PsiElement element) {
+    this ( element, ElementManipulators.getValueTextRange(element));
+  }
+
+  public BasicAttributeValueReference(final PsiElement element, int offset) {
+    this ( element, new TextRange(offset, element.getTextLength() - offset));
+  }
+
+  public BasicAttributeValueReference(final PsiElement element, TextRange range) {
+    myElement = element;
+    myRange = range;
+  }
+
+  public PsiElement getElement() {
+    return myElement;
+  }
+
+  public TextRange getRangeInElement() {
+    return myRange;
+  }
+
+  @NotNull
+  public String getCanonicalText() {
+    final String s = myElement.getText();
+    if (myRange.getStartOffset() < s.length() && myRange.getEndOffset() <= s.length()) {
+      return myRange.substring(s);
+    }
+    return "";
+  }
+
+  public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+    return ElementManipulators.getManipulator(myElement).handleContentChange(
+      myElement,
+      getRangeInElement(),
+      newElementName
+    );
+  }
+
+  public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+    return null;
+  }
+
+  public boolean isReferenceTo(PsiElement element) {
+    return myElement.getManager().areElementsEquivalent(element, resolve());
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DtdReferencesProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DtdReferencesProvider.java
new file mode 100644
index 0000000..4a3fcba
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DtdReferencesProvider.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.codeInsight.completion.CompletionUtil;
+import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.LocalQuickFixProvider;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.filters.ElementFilter;
+import com.intellij.psi.impl.source.xml.XmlEntityRefImpl;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ProcessingContext;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.impl.dtd.XmlNSDescriptorImpl;
+import com.intellij.xml.util.CheckDtdReferencesInspection;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class DtdReferencesProvider extends PsiReferenceProvider {
+  static class ElementReference implements PsiReference, LocalQuickFixProvider, EmptyResolveMessageProvider {
+    private final XmlElement myElement;
+    private XmlElement myNameElement;
+    private final TextRange myRange;
+    @NonNls private static final String ELEMENT_DECLARATION_NAME = "ELEMENT";
+
+    public ElementReference(final XmlElement element, final XmlElement nameElement) {
+      myElement = element;
+      myNameElement = nameElement;
+
+      final int textOffset = element.getTextRange().getStartOffset();
+      final int nameTextOffset = nameElement.getTextOffset();
+
+      myRange = new TextRange(
+        nameTextOffset - textOffset,
+        nameTextOffset + nameElement.getTextLength() - textOffset
+      );
+
+    }
+
+    public PsiElement getElement() {
+      return myElement;
+    }
+
+    public TextRange getRangeInElement() {
+      return myRange;
+    }
+
+    @Nullable
+    public PsiElement resolve() {
+      XmlElementDescriptor descriptor = resolveElementReference(getCanonicalText(), myElement);
+      return descriptor == null ? null : descriptor.getDeclaration();
+    }
+
+
+    @NotNull
+    public String getCanonicalText() {
+      final XmlElement nameElement = myNameElement;
+      return nameElement != null ? nameElement.getText() : "";
+    }
+
+    public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+      myNameElement = ElementManipulators.getManipulator(myNameElement).handleContentChange(
+        myNameElement,
+        new TextRange(0,myNameElement.getTextLength()),
+        newElementName
+      );
+
+      return null;
+    }
+
+    public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+      return null;
+    }
+
+    public boolean isReferenceTo(PsiElement element) {
+      return myElement.getManager().areElementsEquivalent(element, resolve());
+    }
+
+    @NotNull
+    public Object[] getVariants() {
+      final XmlNSDescriptor rootTagNSDescriptor = getNsDescriptor(myElement);
+      return rootTagNSDescriptor != null ?
+             rootTagNSDescriptor.getRootElementsDescriptors(((XmlFile)getRealFile()).getDocument()):
+             ArrayUtil.EMPTY_OBJECT_ARRAY;
+    }
+
+    private PsiFile getRealFile() {
+      PsiFile psiFile = myElement.getContainingFile();
+      if (psiFile != null) psiFile = psiFile.getOriginalFile();
+      return psiFile;
+    }
+
+    public boolean isSoft() {
+      return true;
+    }
+
+    public LocalQuickFix[] getQuickFixes() {
+      if (!canHaveAdequateFix(getElement())) return LocalQuickFix.EMPTY_ARRAY;
+
+      return new LocalQuickFix[] {
+        new CheckDtdReferencesInspection.AddDtdDeclarationFix(
+          "xml.dtd.create.dtd.element.intention.name",
+          ELEMENT_DECLARATION_NAME,
+          this
+        )
+      };
+    }
+
+    public String getUnresolvedMessagePattern() {
+      return XmlBundle.message("xml.dtd.unresolved.element.reference", getCanonicalText());
+    }
+  }
+
+
+  @Nullable
+  private static XmlNSDescriptor getNsDescriptor(XmlElement element) {
+    final XmlElement parentThatProvidesMetaData = PsiTreeUtil.getParentOfType(
+      CompletionUtil.getOriginalElement(element),
+      XmlDocument.class,
+      XmlMarkupDecl.class
+    );
+
+    if (parentThatProvidesMetaData instanceof XmlDocument) {
+      final XmlDocument document = (XmlDocument)parentThatProvidesMetaData;
+      XmlNSDescriptor rootTagNSDescriptor = document.getRootTagNSDescriptor();
+      if (rootTagNSDescriptor == null) rootTagNSDescriptor = (XmlNSDescriptor)document.getMetaData();
+      return rootTagNSDescriptor;
+    } else if (parentThatProvidesMetaData instanceof XmlMarkupDecl) {
+      final XmlMarkupDecl markupDecl = (XmlMarkupDecl)parentThatProvidesMetaData;
+      final PsiMetaData psiMetaData = markupDecl.getMetaData();
+
+      if (psiMetaData instanceof XmlNSDescriptor) {
+        return (XmlNSDescriptor)psiMetaData;
+      }
+    }
+
+    return null;
+  }
+
+  @Nullable
+  public static XmlElementDescriptor resolveElementReference(String name, XmlElement context) {
+    XmlNSDescriptor rootTagNSDescriptor = getNsDescriptor(context);
+
+    if (rootTagNSDescriptor instanceof XmlNSDescriptorImpl) {
+      return ((XmlNSDescriptorImpl)rootTagNSDescriptor).getElementDescriptor(name);
+    }
+    return null;
+  }
+
+  static class EntityReference implements PsiReference,LocalQuickFixProvider, EmptyResolveMessageProvider {
+    private final PsiElement myElement;
+    private final TextRange myRange;
+    @NonNls private static final String ENTITY_DECLARATION_NAME = "ENTITY";
+
+    EntityReference(PsiElement element) {
+      myElement = element;
+      if (element instanceof XmlEntityRef) {
+        final PsiElement child = element.getLastChild();
+        final int startOffsetInParent = child.getStartOffsetInParent();
+        myRange = new TextRange(startOffsetInParent + 1, startOffsetInParent + child.getTextLength() - 1);
+      } else {
+        myRange = new TextRange(1,myElement.getTextLength()-1);
+      }
+    }
+
+    public PsiElement getElement() {
+      return myElement;
+    }
+
+    public TextRange getRangeInElement() {
+      return myRange;
+    }
+
+    @Nullable
+    public PsiElement resolve() {
+      XmlEntityDecl xmlEntityDecl = XmlEntityRefImpl.resolveEntity(
+        (XmlElement)myElement,
+        (myElement instanceof  XmlEntityRef ? myElement.getLastChild():myElement).getText(),
+        myElement.getContainingFile()
+      );
+
+      if (xmlEntityDecl != null && !xmlEntityDecl.isPhysical()) {
+        PsiNamedElement element = XmlUtil.findRealNamedElement(xmlEntityDecl);
+        if (element != null) xmlEntityDecl = (XmlEntityDecl)element;
+      }
+      return xmlEntityDecl;
+    }
+
+    @NotNull
+    public String getCanonicalText() {
+      return myRange.substring(myElement.getText());
+    }
+
+    public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+      final PsiElement elementAt = myElement.findElementAt(myRange.getStartOffset());
+      return ElementManipulators.getManipulator(elementAt).handleContentChange(elementAt, getRangeInElement(), newElementName);
+    }
+
+    public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+      return null;
+    }
+
+    public boolean isReferenceTo(PsiElement element) {
+      return myElement.getManager().areElementsEquivalent(resolve(), element);
+    }
+
+    @NotNull
+    public Object[] getVariants() {
+      return ArrayUtil.EMPTY_OBJECT_ARRAY;
+    }
+
+    public boolean isSoft() {
+      return false;
+    }
+
+    public LocalQuickFix[] getQuickFixes() {
+      if (!canHaveAdequateFix(getElement())) return LocalQuickFix.EMPTY_ARRAY;
+
+      return new LocalQuickFix[] {
+        new CheckDtdReferencesInspection.AddDtdDeclarationFix(
+          "xml.dtd.create.entity.intention.name",
+          myElement.getText().charAt(myRange.getStartOffset() - 1) == '%' ?
+          ENTITY_DECLARATION_NAME + " %":
+          ENTITY_DECLARATION_NAME,
+          this
+        )
+      };
+    }
+
+    public String getUnresolvedMessagePattern() {
+      return XmlBundle.message("xml.dtd.unresolved.entity.reference", getCanonicalText());
+    }
+  }
+
+  private static boolean canHaveAdequateFix(PsiElement element) {
+    final PsiFile containingFile = element.getContainingFile();
+
+    if (containingFile.getLanguage() == HTMLLanguage.INSTANCE ||
+        containingFile.getLanguage() == XHTMLLanguage.INSTANCE ||
+        containingFile.getViewProvider() instanceof TemplateLanguageFileViewProvider
+      ) {
+      return false;
+    }
+    return true;
+  }
+
+  @NotNull
+  public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull final ProcessingContext context) {
+    XmlElement nameElement = null;
+
+    if (element instanceof XmlDoctype) {
+      nameElement = ((XmlDoctype)element).getNameElement();
+    } else if (element instanceof XmlElementDecl) {
+      nameElement = ((XmlElementDecl)element).getNameElement();
+    } else if (element instanceof XmlAttlistDecl) {
+      nameElement = ((XmlAttlistDecl)element).getNameElement();
+    }
+    else if (element instanceof XmlElementContentSpec) {
+      final List<PsiReference> psiRefs = new ArrayList<PsiReference>();
+      element.accept(new PsiRecursiveElementVisitor() {
+        @Override
+        public void visitElement(PsiElement child) {
+          if (child instanceof XmlToken && ((XmlToken)child).getTokenType() == XmlTokenType.XML_NAME) {
+            psiRefs.add(new ElementReference((XmlElement)element, (XmlElement)child));
+          }
+          super.visitElement(child);
+        }
+      });
+      return psiRefs.toArray(new PsiReference[psiRefs.size()]);
+    }
+
+    if (nameElement != null) {
+      return new PsiReference[] { new ElementReference((XmlElement)element, nameElement) };
+    }
+
+    if (element instanceof XmlEntityRef ||
+        (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_CHAR_ENTITY_REF)) {
+      return new PsiReference[] { new EntityReference(element) };
+    }
+
+    return PsiReference.EMPTY_ARRAY;
+  }
+
+  public ElementFilter getSystemReferenceFilter() {
+    return new ElementFilter() {
+      public boolean isAcceptable(Object element, PsiElement context) {
+        final PsiElement parent = context.getParent();
+        
+        if((parent instanceof XmlEntityDecl &&
+           !((XmlEntityDecl)parent).isInternalReference()
+           )
+          ) {
+          PsiElement prevSibling = context.getPrevSibling();
+          if (prevSibling instanceof PsiWhiteSpace) {
+            prevSibling = prevSibling.getPrevSibling();
+          }
+
+          if (prevSibling instanceof XmlToken &&
+              ((XmlToken)prevSibling).getTokenType() == XmlTokenType.XML_DOCTYPE_SYSTEM ||
+              prevSibling instanceof XmlAttributeValue
+            ) {
+            return true;
+          }
+        }
+
+        return false;
+      }
+
+      public boolean isClassAcceptable(Class hintClass) {
+        return true;
+      }
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileBasedUserDataCache.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileBasedUserDataCache.java
new file mode 100644
index 0000000..75c5c3f
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileBasedUserDataCache.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.openapi.util.UserDataCache;
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.util.CachedValuesManager;
+
+/**
+ * @author Maxim.Mossienko
+*         Date: 30.12.2008
+*         Time: 21:03:42
+*/
+public abstract class FileBasedUserDataCache<T> extends UserDataCache<CachedValue<T>, PsiFile, Object> {
+  protected CachedValue<T> compute(final PsiFile xmlFile, final Object o) {
+    return CachedValuesManager.getManager(xmlFile.getProject()).createCachedValue(new CachedValueProvider<T>() {
+      public Result<T> compute() {
+
+        return new Result<T>(doCompute(xmlFile), getDependencies(xmlFile));
+      }
+    }, false);
+  }
+
+  protected Object[] getDependencies(PsiFile xmlFile) {
+    return new Object[] {xmlFile};
+  }
+
+  protected abstract T doCompute(PsiFile file);
+  protected abstract Key<CachedValue<T>> getKey();
+
+  public T compute(PsiFile file) {
+    final FileViewProvider fileViewProvider = file.getViewProvider();
+    final PsiFile baseFile = fileViewProvider.getPsi(fileViewProvider.getBaseLanguage());
+    baseFile.getFirstChild(); // expand chameleon out of lock
+    return get(getKey(), baseFile, null).getValue();
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdRefReference.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdRefReference.java
new file mode 100644
index 0000000..9feb17a
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdRefReference.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.PsiComment;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.XmlRecursiveElementVisitor;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlComment;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.util.XmlDeclareIdInCommentAction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author peter
+ */
+public class IdRefReference extends BasicAttributeValueReference {
+  private final boolean myIdAttrsOnly;
+
+  public IdRefReference(final PsiElement element, int offset, boolean idAttrsOnly) {
+    super(element, offset);
+    myIdAttrsOnly = idAttrsOnly;
+  }
+
+  public IdRefReference(final PsiElement element) {
+    super(element);
+    myIdAttrsOnly = false;
+  }
+
+  @Nullable
+  protected PsiElement getIdValueElement(PsiElement element) {
+    if (element instanceof XmlTag) {
+      final XmlTag tag = (XmlTag)element;
+      XmlAttribute attribute = tag.getAttribute(IdReferenceProvider.ID_ATTR_NAME, null);
+      if (!myIdAttrsOnly) {
+        if (attribute == null) {
+          attribute = tag.getAttribute(IdReferenceProvider.NAME_ATTR_NAME, null);
+        }
+        if (attribute == null) {
+          attribute = tag.getAttribute(IdReferenceProvider.STYLE_ID_ATTR_NAME, null);
+        }
+      }
+      return attribute != null ? attribute.getValueElement() : null;
+    }
+    else {
+      return element;
+    }
+  }
+
+  @Nullable
+  protected String getIdValue(final PsiElement element) {
+    if (element instanceof XmlTag) {
+      final XmlTag tag = (XmlTag)element;
+      String s = tag.getAttributeValue(IdReferenceProvider.ID_ATTR_NAME);
+      if (!myIdAttrsOnly) {
+        if (s == null) s = tag.getAttributeValue(IdReferenceProvider.NAME_ATTR_NAME);
+        if (s == null) s = tag.getAttributeValue(IdReferenceProvider.STYLE_ID_ATTR_NAME);
+      }
+      return s;
+    } else if (element instanceof PsiComment) {
+      return getImplicitIdValue((PsiComment) element);
+    }
+
+    return null;
+  }
+
+  protected static boolean isAcceptableTagType(final XmlTag subTag) {
+    return subTag.getAttributeValue(IdReferenceProvider.ID_ATTR_NAME) != null ||
+           subTag.getAttributeValue(IdReferenceProvider.FOR_ATTR_NAME) != null ||
+           (subTag.getAttributeValue(IdReferenceProvider.NAME_ATTR_NAME) != null &&
+            subTag.getName().indexOf(".directive") == -1);
+  }
+
+  private static final FileBasedUserDataCache<List<PsiElement>> ourCachedIdsCache = new FileBasedUserDataCache<List<PsiElement>>() {
+    private final Key<CachedValue<List<PsiElement>>> ourCachedIdsValueKey = Key.create("my.ids.cached.value");
+
+    protected List<PsiElement> doCompute(PsiFile file) {
+      final List<PsiElement> result = new ArrayList<PsiElement>();
+
+      file.accept(new XmlRecursiveElementVisitor(true) {
+        @Override
+        public void visitXmlTag(XmlTag tag) {
+          if (isAcceptableTagType(tag)) result.add(tag);
+          super.visitXmlTag(tag);
+        }
+
+        @Override
+        public void visitComment(final PsiComment comment) {
+          if (isDeclarationComment(comment)) result.add(comment);
+
+          super.visitComment(comment);
+        }
+
+        @Override
+        public void visitXmlComment(final XmlComment comment) {
+          if (isDeclarationComment(comment)) result.add(comment);
+
+          super.visitComment(comment);
+        }
+      });
+      return result;
+    }
+
+    protected Key<CachedValue<List<PsiElement>>> getKey() {
+      return ourCachedIdsValueKey;
+    }
+  };
+
+  private static boolean isDeclarationComment(@NotNull final PsiComment comment) {
+    return comment.getText().contains("@declare id=");
+  }
+
+  @Nullable
+  private static String getImplicitIdValue(@NotNull final PsiComment comment) {
+    return XmlDeclareIdInCommentAction.getImplicitlyDeclaredId(comment);
+  }
+
+  private void process(PsiElementProcessor<PsiElement> processor) {
+    final PsiFile psiFile = getElement().getContainingFile();
+    process(processor, psiFile);
+  }
+
+  public static void process(final PsiElementProcessor<PsiElement> processor, PsiFile file) {
+    for (PsiElement e : ourCachedIdsCache.compute(file)) {
+      if (!processor.execute(e)) return;
+    }
+  }
+
+  @Nullable
+  public PsiElement resolve() {
+    final PsiElement[] result = new PsiElement[1];
+    process(new PsiElementProcessor<PsiElement>() {
+      String canonicalText = getCanonicalText();
+
+      public boolean execute(@NotNull final PsiElement element) {
+        final String idValue = getIdValue(element);
+        if (idValue != null && idValue.equals(canonicalText)) {
+          result[0] = getIdValueElement(element);
+          return false;
+        }
+        return true;
+      }
+    });
+
+    return result[0];
+  }
+
+  @NotNull
+  public Object[] getVariants() {
+    final List<String> result = new LinkedList<String>();
+
+    process(new PsiElementProcessor<PsiElement>() {
+      public boolean execute(@NotNull final PsiElement element) {
+        String value = getIdValue(element);
+        if (value != null) {
+          result.add(value);
+        }
+        return true;
+      }
+    });
+
+    return ArrayUtil.toObjectArray(result);
+  }
+
+  public boolean isSoft() {
+    return false;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdReferenceProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdReferenceProvider.java
new file mode 100644
index 0000000..7446b7c
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdReferenceProvider.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.filters.ElementFilter;
+import com.intellij.psi.impl.source.resolve.reference.PsiReferenceProviderBase;
+import com.intellij.psi.templateLanguages.OuterLanguageElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ProcessingContext;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.util.XmlUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author peter
+ */
+public class IdReferenceProvider extends PsiReferenceProvider {
+  @NonNls public static final String FOR_ATTR_NAME = "for";
+  @NonNls public static final String ID_ATTR_NAME = "id";
+  @NonNls public static final String STYLE_ID_ATTR_NAME = "styleId";
+  @NonNls public static final String NAME_ATTR_NAME = "name";
+
+  private static final THashSet<String> ourNamespacesWithoutNameReference = new THashSet<String>();
+  static {
+    ourNamespacesWithoutNameReference.add( XmlUtil.JSP_URI );
+    ourNamespacesWithoutNameReference.add( XmlUtil.STRUTS_BEAN_URI );
+    ourNamespacesWithoutNameReference.add( XmlUtil.STRUTS_BEAN_URI2 );
+    ourNamespacesWithoutNameReference.add( XmlUtil.STRUTS_LOGIC_URI );
+    for(String s: XmlUtil.JSTL_CORE_URIS) ourNamespacesWithoutNameReference.add( s );
+    ourNamespacesWithoutNameReference.add( "http://struts.apache.org/tags-tiles" );
+    for(String s: XmlUtil.SCHEMA_URIS) ourNamespacesWithoutNameReference.add( s );
+  }
+
+  public String[] getIdForAttributeNames() {
+    return new String[]{FOR_ATTR_NAME, ID_ATTR_NAME, NAME_ATTR_NAME,STYLE_ID_ATTR_NAME};
+  }
+
+  public ElementFilter getIdForFilter() {
+    return new ElementFilter() {
+      public boolean isAcceptable(Object element, PsiElement context) {
+        final PsiElement grandParent = ((PsiElement)element).getParent().getParent();
+        if (grandParent instanceof XmlTag) {
+          final XmlTag tag = (XmlTag)grandParent;
+
+          if (tag.getNamespacePrefix().length() > 0) {
+            return true;
+          }
+        }
+        return false;
+      }
+
+      public boolean isClassAcceptable(Class hintClass) {
+        return true;
+      }
+    };
+  }
+
+  @NotNull
+  public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull final ProcessingContext context) {
+    if (element instanceof XmlAttributeValue) {
+      final XmlExtension extension = XmlExtension.getExtensionByElement(element);
+      if (extension != null && extension.hasDynamicComponents(element)) {
+        return PsiReference.EMPTY_ARRAY;
+      }
+
+      final PsiElement parentElement = element.getParent();
+      if (!(parentElement instanceof XmlAttribute)) return PsiReference.EMPTY_ARRAY;
+      final String name = ((XmlAttribute)parentElement).getName();
+      final String ns = ((XmlAttribute)parentElement).getParent().getNamespace();
+      final boolean jsfNs = XmlUtil.JSF_CORE_URI.equals(ns) || XmlUtil.JSF_HTML_URI.equals(ns);
+
+      if (FOR_ATTR_NAME.equals(name)) {
+        return new PsiReference[]{
+          jsfNs && element.getText().indexOf(':') == -1 ?
+          new IdRefReference(element):
+          new IdRefReference(element) {
+            public boolean isSoft() {
+              final XmlAttributeDescriptor descriptor = ((XmlAttribute)parentElement).getDescriptor();
+              return descriptor != null ? !descriptor.hasIdRefType() : false;
+            }
+          }
+        };
+      }
+      else {
+        final boolean allowReferences = !(ourNamespacesWithoutNameReference.contains(ns));
+        
+        if ((ID_ATTR_NAME.equals(name) && allowReferences) ||
+             STYLE_ID_ATTR_NAME.equals(name) ||
+             (NAME_ATTR_NAME.equals(name) && allowReferences)
+            ) {
+          final AttributeValueSelfReference attributeValueSelfReference;
+
+          if (jsfNs) {
+            attributeValueSelfReference = new AttributeValueSelfReference(element);
+          } else {
+            if (hasOuterLanguageElement(element)) return PsiReference.EMPTY_ARRAY;
+
+            attributeValueSelfReference =  new GlobalAttributeValueSelfReference(element, true);
+          }
+          return new PsiReference[]{attributeValueSelfReference};
+        }
+      }
+    }
+    return PsiReference.EMPTY_ARRAY;
+  }
+
+  private static boolean hasOuterLanguageElement(@NotNull PsiElement element) {
+    for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
+      if (child instanceof OuterLanguageElement) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  public static class GlobalAttributeValueSelfReference extends AttributeValueSelfReference {
+    private final boolean mySoft;
+
+    public GlobalAttributeValueSelfReference(PsiElement element, boolean soft) {
+      super(element);
+      mySoft = soft;
+    }
+
+    public boolean isSoft() {
+      return mySoft;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java
new file mode 100644
index 0000000..b4c39f1
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java
@@ -0,0 +1,715 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
+import com.intellij.codeInsight.daemon.QuickFixProvider;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInsight.template.Template;
+import com.intellij.codeInsight.template.TemplateManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.ResolveCache;
+import com.intellij.psi.impl.source.xml.SchemaPrefixReference;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ProcessingContext;
+import com.intellij.util.Processor;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.impl.schema.ComplexTypeDescriptor;
+import com.intellij.xml.impl.schema.TypeDescriptor;
+import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.PropertyKey;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @by Maxim.Mossienko
+ * @author Konstantin Bulenkov
+ */
+public class SchemaReferencesProvider extends PsiReferenceProvider {
+  @NonNls private static final String VALUE_ATTR_NAME = "value";
+  @NonNls private static final String PATTERN_TAG_NAME = "pattern";
+  @NonNls private static final String NAME_ATTR_NAME = "name";
+
+  @NonNls private static final String MEMBER_TYPES_ATTR_NAME = "memberTypes";
+  @NonNls private static final String ITEM_TYPE_ATTR_NAME = "itemType";
+  @NonNls private static final String BASE_ATTR_NAME = "base";
+  @NonNls private static final String GROUP_TAG_NAME = "group";
+
+  @NonNls private static final String ATTRIBUTE_GROUP_TAG_NAME = "attributeGroup";
+  @NonNls private static final String ATTRIBUTE_TAG_NAME = "attribute";
+  @NonNls private static final String ELEMENT_TAG_NAME = "element";
+  @NonNls private static final String SIMPLE_TYPE_TAG_NAME = "simpleType";
+
+  @NonNls private static final String COMPLEX_TYPE_TAG_NAME = "complexType";
+  @NonNls private static final String REF_ATTR_NAME = "ref";
+  @NonNls private static final String TARGET_NAMESPACE = "targetNamespace";
+  @NonNls private static final String TYPE_ATTR_NAME = "type";
+  @NonNls private static final String SUBSTITUTION_GROUP_ATTR_NAME = "substitutionGroup";
+
+  public String[] getCandidateAttributeNamesForSchemaReferences() {
+    return new String[] {REF_ATTR_NAME,TYPE_ATTR_NAME, BASE_ATTR_NAME,NAME_ATTR_NAME, SUBSTITUTION_GROUP_ATTR_NAME,MEMBER_TYPES_ATTR_NAME,
+      VALUE_ATTR_NAME, ITEM_TYPE_ATTR_NAME};
+  }
+
+  static class RegExpReference extends BasicAttributeValueReference implements EmptyResolveMessageProvider {
+    private String message;
+
+    public RegExpReference(final PsiElement element) {
+      super(element);
+    }
+
+    private static final Pattern pattern = Pattern.compile("^(?:\\\\i|\\\\l)");
+    private static final Pattern pattern2 = Pattern.compile("([^\\\\])(?:\\\\i|\\\\l)");
+
+    @Nullable
+    public PsiElement resolve() {
+      try {
+        String text = getCanonicalText();
+
+        // \i and \l are special classes that does not present in java reg exps, so replace their occurences with more usable \w
+        text = pattern2.matcher(pattern.matcher(text).replaceFirst("\\\\w")).replaceAll("$1\\\\w");
+
+        Pattern.compile(text);
+        message = null;
+        return myElement;
+      }
+      catch (Exception e) {
+        message = PsiBundle.message("invalid.regular.expression.message", getCanonicalText());
+        return null;
+      }
+    }
+
+    @NotNull
+    public Object[] getVariants() {
+      return ArrayUtil.EMPTY_OBJECT_ARRAY;
+    }
+
+    public boolean isSoft() {
+      return false;
+    }
+
+    public String getUnresolvedMessagePattern() {
+      return message;
+    }
+  }
+
+  public static class NameReference implements PsiReference {
+    private final PsiElement myElement;
+
+    public NameReference(PsiElement element) {
+      myElement = element;
+    }
+
+    public PsiElement getElement() {
+      return myElement;
+    }
+
+    public TextRange getRangeInElement() {
+      return new TextRange(1,myElement.getTextLength()-1);
+    }
+
+    @Nullable
+    public PsiElement resolve() {
+      return myElement.getParent().getParent();
+    }
+
+    @NotNull
+    public String getCanonicalText() {
+      String text = myElement.getText();
+      return text.substring(1,text.length()- 1);
+    }
+
+    public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+      return ElementManipulators.getManipulator(myElement).handleContentChange(
+        myElement,
+        getRangeInElement(),
+        newElementName.substring(newElementName.indexOf(':') + 1)
+      );
+    }
+
+    public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+      return null;
+    }
+
+    public boolean isReferenceTo(PsiElement element) {
+      return myElement.getManager().areElementsEquivalent(resolve(), element);
+    }
+
+    @NotNull
+    public Object[] getVariants() {
+      return ArrayUtil.EMPTY_OBJECT_ARRAY;
+    }
+
+    public boolean isSoft() {
+      return true;
+    }
+  }
+
+  public static class TypeOrElementOrAttributeReference implements PsiReference, QuickFixProvider<TypeOrElementOrAttributeReference> {
+    private final PsiElement myElement;
+    private TextRange myRange;
+    private String nsPrefix;
+
+    public void registerQuickfix(HighlightInfo info, TypeOrElementOrAttributeReference reference) {
+      if (myType == ReferenceType.TypeReference) {
+        QuickFixAction.registerQuickFixAction(
+          info, new CreateXmlElementIntentionAction("xml.schema.create.complex.type.intention.name",COMPLEX_TYPE_TAG_NAME,reference)
+        );
+        QuickFixAction.registerQuickFixAction(
+          info, new CreateXmlElementIntentionAction("xml.schema.create.simple.type.intention.name",SIMPLE_TYPE_TAG_NAME,reference)
+        );
+      } else if (myType != null) {
+        @PropertyKey(resourceBundle = XmlBundle.PATH_TO_BUNDLE) String key = null;
+        @NonNls String declarationTagName = null;
+
+        if (myType == ReferenceType.ElementReference) {
+          declarationTagName = ELEMENT_TAG_NAME;
+          key = "xml.schema.create.element.intention.name";
+        } else if (myType == ReferenceType.AttributeReference) {
+          declarationTagName = ATTRIBUTE_TAG_NAME;
+          key = "xml.schema.create.attribute.intention.name";
+        } else if (myType == ReferenceType.AttributeGroupReference) {
+          declarationTagName = ATTRIBUTE_GROUP_TAG_NAME;
+          key = "xml.schema.create.attribute.group.intention.name";
+        } else if (myType == ReferenceType.GroupReference) {
+          declarationTagName = GROUP_TAG_NAME;
+          key = "xml.schema.create.group.intention.name";
+        }
+
+        assert key != null && declarationTagName != null;
+        QuickFixAction.registerQuickFixAction(
+          info, new CreateXmlElementIntentionAction(key, declarationTagName, reference)
+        );
+      }
+    }
+
+    public void setNamespacePrefix(String prefix) {
+      this.nsPrefix = prefix;
+    }
+
+    protected enum ReferenceType {
+      ElementReference, AttributeReference, GroupReference, AttributeGroupReference, TypeReference
+    }
+
+    private final @Nullable ReferenceType myType;
+
+    protected TypeOrElementOrAttributeReference(PsiElement element, TextRange range,  @Nullable ReferenceType type) {
+      myElement = element;
+      myRange   = range;
+
+      assert myRange.getLength() >= 0;
+
+      myType = type;
+    }
+
+    TypeOrElementOrAttributeReference(PsiElement element, TextRange range) {
+      this(element, range, determineReferenceType(element));
+    }
+
+    @Nullable
+    private static ReferenceType determineReferenceType(PsiElement element) {
+      final XmlAttribute attribute = PsiTreeUtil.getParentOfType(element, XmlAttribute.class);
+      if (attribute == null) {
+        return null;
+      }
+      final XmlTag tag = attribute.getParent();
+      final String localName = tag.getLocalName();
+      final String attributeLocalName = attribute.getLocalName();
+
+      if (REF_ATTR_NAME.equals(attributeLocalName) || SUBSTITUTION_GROUP_ATTR_NAME.equals(attributeLocalName)) {
+        if (localName.equals(GROUP_TAG_NAME)) {
+          return ReferenceType.GroupReference;
+        } else if (localName.equals(ATTRIBUTE_GROUP_TAG_NAME)) {
+          return ReferenceType.AttributeGroupReference;
+        } else if (ELEMENT_TAG_NAME.equals(localName)) {
+          return ReferenceType.ElementReference;
+        } else if (ATTRIBUTE_TAG_NAME.equals(localName)) {
+          return ReferenceType.AttributeReference;
+        }
+      } else if (TYPE_ATTR_NAME.equals(attributeLocalName) ||
+                 BASE_ATTR_NAME.equals(attributeLocalName) ||
+                 MEMBER_TYPES_ATTR_NAME.equals(attributeLocalName) ||
+                 ITEM_TYPE_ATTR_NAME.equals(attributeLocalName)
+                ) {
+        return ReferenceType.TypeReference;
+      }
+      return null;
+    }
+
+    public PsiElement getElement() {
+      return myElement;
+    }
+
+    public TextRange getRangeInElement() {
+      return myRange;
+    }
+
+    @Nullable
+    public PsiElement resolve() {
+      final PsiElement psiElement = ResolveCache.getInstance(getElement().getProject()).resolveWithCaching(this, MyResolver.INSTANCE, false, false);
+
+      return psiElement != PsiUtilCore.NULL_PSI_ELEMENT ? psiElement:null;
+    }
+
+    private PsiElement resolveInner() {
+      final XmlTag tag = PsiTreeUtil.getContextOfType(myElement, XmlTag.class, false);
+      if (tag == null) return PsiUtilCore.NULL_PSI_ELEMENT;
+
+      String canonicalText = getCanonicalText();
+      XmlNSDescriptorImpl nsDescriptor = getDescriptor(tag,canonicalText);
+
+      if (myType != null && nsDescriptor != null && nsDescriptor.getTag() != null) {
+
+        switch(myType) {
+          case GroupReference: return nsDescriptor.findGroup(canonicalText);
+          case AttributeGroupReference: return nsDescriptor.findAttributeGroup(canonicalText);
+          case ElementReference: {
+            XmlElementDescriptor descriptor = nsDescriptor.getElementDescriptor(
+              XmlUtil.findLocalNameByQualifiedName(canonicalText), getNamespace(tag, canonicalText),
+              new HashSet<XmlNSDescriptorImpl>(),
+              true
+            );
+
+            return descriptor != null ? descriptor.getDeclaration(): PsiUtilCore.NULL_PSI_ELEMENT;
+          }
+          case AttributeReference: {
+            //final String prefixByQualifiedName = XmlUtil.findPrefixByQualifiedName(canonicalText);
+            final String localNameByQualifiedName = XmlUtil.findLocalNameByQualifiedName(canonicalText);
+            XmlAttributeDescriptor descriptor = nsDescriptor.getAttribute(
+              localNameByQualifiedName,
+              getNamespace(tag, canonicalText),
+              tag
+            );
+
+            if (descriptor != null) return descriptor.getDeclaration();
+
+            return PsiUtilCore.NULL_PSI_ELEMENT;
+          }
+          case TypeReference: {
+            TypeDescriptor typeDescriptor = nsDescriptor.getTypeDescriptor(canonicalText,tag);
+            if (typeDescriptor instanceof ComplexTypeDescriptor) {
+              return ((ComplexTypeDescriptor)typeDescriptor).getDeclaration();
+            } else if (typeDescriptor instanceof TypeDescriptor) {
+              return myElement;
+            }
+          }
+        }
+      }
+
+      return PsiUtilCore.NULL_PSI_ELEMENT;
+    }
+
+    private XmlNSDescriptorImpl getDescriptor(final XmlTag tag, String text) {
+      if (myType != ReferenceType.ElementReference &&
+          myType != ReferenceType.AttributeReference) {
+        final PsiElement parentElement = myElement.getContext();
+        final PsiElement grandParentElement = parentElement != null ? parentElement.getParent() : null;
+        boolean doRedefineCheck = false;
+
+        if (parentElement instanceof XmlAttribute &&
+            grandParentElement instanceof XmlTag
+           ) {
+          final String attrName = ((XmlAttribute)parentElement).getName();
+          final String tagLocalName = ((XmlTag)grandParentElement).getLocalName();
+
+          doRedefineCheck = (REF_ATTR_NAME.equals(attrName) &&
+            ( GROUP_TAG_NAME.equals(tagLocalName) ||
+              ATTRIBUTE_GROUP_TAG_NAME.equals(tagLocalName)
+            )
+           ) ||
+           ( BASE_ATTR_NAME.equals(attrName) ||
+             MEMBER_TYPES_ATTR_NAME.equals(attrName)
+           );
+        }
+
+        if (doRedefineCheck) {
+          XmlNSDescriptorImpl redefinedDescriptor = findRedefinedDescriptor(tag, text);
+          if (redefinedDescriptor != null) return redefinedDescriptor;
+        }
+      }
+
+      final String namespace = getNamespace(tag, text);
+      XmlNSDescriptor nsDescriptor = tag.getNSDescriptor(namespace,true);
+
+      final XmlDocument document = ((XmlFile)tag.getContainingFile()).getDocument();
+
+      if (nsDescriptor == null) { // import
+        nsDescriptor = (XmlNSDescriptor)document.getMetaData();
+      }
+
+      if (nsDescriptor == null) {
+        final XmlNSDescriptor[] descrs = new XmlNSDescriptor[1];
+
+        URLReference.processWsdlSchemas(
+          document.getRootTag(),
+          new Processor<XmlTag>() {
+            public boolean process(final XmlTag xmlTag) {
+              if (namespace.equals(xmlTag.getAttributeValue(TARGET_NAMESPACE))) {
+                descrs[0] = (XmlNSDescriptor)xmlTag.getMetaData();
+                return false;
+              }
+              return true;
+            }
+          }
+        );
+
+        if (descrs[0] instanceof XmlNSDescriptorImpl) return (XmlNSDescriptorImpl)descrs[0];
+      }
+
+      return nsDescriptor instanceof XmlNSDescriptorImpl ? (XmlNSDescriptorImpl)nsDescriptor:null;
+    }
+
+    private static String getNamespace(final XmlTag tag, final String text) {
+      final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(text);
+      final String namespaceByPrefix = tag.getNamespaceByPrefix(namespacePrefix);
+      if (namespaceByPrefix.length() > 0) return namespaceByPrefix;
+      final XmlTag rootTag = ((XmlFile)tag.getContainingFile()).getDocument().getRootTag();
+
+      if (rootTag != null &&
+          "schema".equals(rootTag.getLocalName()) &&
+          XmlUtil.ourSchemaUrisList.indexOf(rootTag.getNamespace()) != -1 ) {
+        final String targetNS = rootTag.getAttributeValue(TARGET_NAMESPACE);
+        
+        if (targetNS != null) {
+          final String targetNsPrefix = rootTag.getPrefixByNamespace(targetNS);
+
+          if (namespacePrefix.equals(targetNsPrefix) ||
+              (namespaceByPrefix.length() == 0 && targetNsPrefix == null)) {
+            return targetNS;
+          }
+        }
+      }
+      return namespaceByPrefix;
+    }
+
+    @NotNull
+    public String getCanonicalText() {
+      final String text = myElement.getText();
+      String name = myRange.getEndOffset() <= text.length() ? myRange.substring(text) : "";
+      if (name.length() > 0 && nsPrefix != null && nsPrefix.length() > 0) {
+        name = nsPrefix + ":" + name;
+      }
+      return name;
+    }
+
+    public PsiElement handleElementRename(String _newElementName) throws IncorrectOperationException {
+      final String canonicalText = getCanonicalText();
+      //final String newElementName = canonicalText.substring(0,canonicalText.indexOf(':') + 1) + _newElementName;
+      final String newElementName = _newElementName;
+
+      final PsiElement element = ElementManipulators.getManipulator(myElement)
+        .handleContentChange(myElement, getRangeInElement(), newElementName);
+      myRange = new TextRange(myRange.getStartOffset(),myRange.getEndOffset() - (canonicalText.length() - newElementName.length()));
+      return element;
+    }
+
+    public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+      throw new IncorrectOperationException();
+    }
+
+    public boolean isReferenceTo(PsiElement element) {
+      return myElement.getManager().areElementsEquivalent(resolve(), element);
+    }
+
+    class CompletionProcessor implements PsiElementProcessor<XmlTag> {
+      List<String> myElements = new ArrayList<String>(1);
+      String namespace;
+      XmlTag tag;
+
+      public boolean execute(@NotNull final XmlTag element) {
+        String name = element.getAttributeValue(NAME_ATTR_NAME);
+        final String prefixByNamespace = tag.getPrefixByNamespace(namespace);
+        if (prefixByNamespace != null && prefixByNamespace.length() > 0 && nsPrefix == null) {
+          name = prefixByNamespace + ":" + name;
+        }
+        myElements.add( name );
+        return true;
+      }
+    }
+
+    @NotNull
+    public Object[] getVariants() {
+      final XmlTag tag = PsiTreeUtil.getContextOfType(myElement, XmlTag.class, true);
+      if (tag == null || myType == null) return ArrayUtil.EMPTY_OBJECT_ARRAY;
+
+      String[] tagNames = null;
+
+      switch (myType) {
+        case GroupReference:
+          tagNames = new String[] {GROUP_TAG_NAME};
+          break;
+        case AttributeGroupReference:
+          tagNames = new String[] {ATTRIBUTE_GROUP_TAG_NAME};
+          break;
+        case AttributeReference:
+          tagNames = new String[] {ATTRIBUTE_TAG_NAME};
+          break;
+        case ElementReference:
+          tagNames = new String[] {ELEMENT_TAG_NAME};
+          break;
+        case TypeReference:
+          tagNames = new String[] {SIMPLE_TYPE_TAG_NAME,COMPLEX_TYPE_TAG_NAME};
+          break;
+      }
+
+      CompletionProcessor processor = new CompletionProcessor();
+      processor.tag = tag;
+
+      final XmlElement context = PsiTreeUtil.getContextOfType(myElement, XmlElement.class, false);
+      if (context == null) {
+        return ArrayUtil.EMPTY_OBJECT_ARRAY;
+      }
+      final XmlDocument document = ((XmlFile)context.getContainingFile()).getDocument();
+      if (document == null) {
+        return ArrayUtil.EMPTY_OBJECT_ARRAY;
+      }
+      final XmlTag rootTag = document.getRootTag();
+      String ourNamespace = rootTag != null ? rootTag.getAttributeValue(TARGET_NAMESPACE) : "";
+      if (ourNamespace == null) ourNamespace = "";
+
+      for(String namespace:tag.knownNamespaces()) {
+        if (ourNamespace.equals(namespace)) continue;
+        final XmlNSDescriptor nsDescriptor = tag.getNSDescriptor(namespace, true);
+
+        if (nsDescriptor instanceof XmlNSDescriptorImpl) {
+          processNamespace(namespace, processor, nsDescriptor, tagNames);
+        }
+      }
+
+
+      XmlNSDescriptor nsDescriptor = (XmlNSDescriptor)document.getMetaData();
+      if (nsDescriptor != null) {
+        processNamespace(
+          ourNamespace,
+          processor,
+          nsDescriptor,
+          tagNames
+        );
+      }
+
+      return ArrayUtil.toStringArray(processor.myElements);
+    }
+
+    private static void processNamespace(final String namespace,
+                                  final CompletionProcessor processor,
+                                  final XmlNSDescriptor nsDescriptor,
+                                  final String[] tagNames) {
+      processor.namespace = namespace;
+
+      final XmlNSDescriptorImpl xmlNSDescriptor = ((XmlNSDescriptorImpl)nsDescriptor);
+      XmlNSDescriptorImpl.processTagsInNamespace(
+        xmlNSDescriptor.getTag(),
+        tagNames,
+        processor
+      );
+    }
+
+    public boolean isSoft() {
+      return false;
+    }
+
+    private static class MyResolver implements ResolveCache.Resolver {
+      static MyResolver INSTANCE = new MyResolver(); 
+      public PsiElement resolve(@NotNull PsiReference ref, boolean incompleteCode) {
+        return ((TypeOrElementOrAttributeReference)ref).resolveInner();
+      }
+    }
+  }
+
+  private static class CreateXmlElementIntentionAction implements IntentionAction {
+    private final String myMessageKey;
+    protected final TypeOrElementOrAttributeReference myRef;
+    private boolean myIsAvailableEvaluated;
+    private XmlFile myTargetFile;
+    private final String myDeclarationTagName;
+
+    CreateXmlElementIntentionAction(
+      @PropertyKey(resourceBundle = XmlBundle.PATH_TO_BUNDLE) String messageKey,
+      @NonNls @NotNull String declarationTagName,
+      TypeOrElementOrAttributeReference ref) {
+
+      myMessageKey = messageKey;
+      myRef = ref;
+      myDeclarationTagName = declarationTagName;
+    }
+
+    @NotNull
+    public String getText() {
+      return XmlBundle.message(myMessageKey,XmlUtil.findLocalNameByQualifiedName(myRef.getCanonicalText()));
+    }
+
+    @NotNull
+    public String getFamilyName() {
+      return XmlBundle.message("xml.create.xml.declaration.intention.type");
+    }
+
+    public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
+      if (!myIsAvailableEvaluated) {
+        final XmlTag tag = PsiTreeUtil.getParentOfType(myRef.getElement(), XmlTag.class);
+        if (tag != null) {
+          final XmlNSDescriptorImpl descriptor = myRef.getDescriptor(tag, myRef.getCanonicalText());
+
+          if (descriptor != null &&
+              descriptor.getDescriptorFile() != null &&
+              descriptor.getDescriptorFile().isWritable()
+             ) {
+            myTargetFile = descriptor.getDescriptorFile();
+          }
+        }
+        myIsAvailableEvaluated = true;
+      }
+      return myTargetFile != null;
+    }
+
+    public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
+      if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
+
+      final XmlTag rootTag = myTargetFile.getDocument().getRootTag();
+
+      OpenFileDescriptor descriptor = new OpenFileDescriptor(
+        project,
+        myTargetFile.getVirtualFile(),
+        rootTag.getValue().getTextRange().getEndOffset()
+      );
+      Editor targetEditor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
+      TemplateManager manager = TemplateManager.getInstance(project);
+      final Template template = manager.createTemplate("", "");
+
+      addTextTo(template, rootTag);
+
+      manager.startTemplate(targetEditor, template);
+    }
+
+    protected void addTextTo(Template template, XmlTag rootTag) {
+      String schemaPrefix = rootTag.getPrefixByNamespace(XmlUtil.XML_SCHEMA_URI);
+      if (schemaPrefix.length() > 0) schemaPrefix += ":";
+
+      template.addTextSegment(
+        "<" + schemaPrefix + myDeclarationTagName + " name=\"" + XmlUtil.findLocalNameByQualifiedName(myRef.getCanonicalText()) + "\">"
+      );
+      template.addEndVariable();
+      template.addTextSegment(
+        "</" + schemaPrefix + myDeclarationTagName + ">\n"
+      );
+      template.setToReformat(true);
+    }
+
+    public boolean startInWriteAction() {
+      return true;
+    }
+  }
+
+  @NotNull
+  public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull final ProcessingContext context) {
+    final PsiElement parent = element.getParent();
+    if (!(parent instanceof XmlAttribute)) return PsiReference.EMPTY_ARRAY;
+    final String attrName = ((XmlAttribute)parent).getName();
+
+    if (VALUE_ATTR_NAME.equals(attrName)) {
+      if (PATTERN_TAG_NAME.equals(((XmlAttribute)parent).getParent().getLocalName())) {
+        return new PsiReference[] { new RegExpReference(element) };
+      } else {
+        return PsiReference.EMPTY_ARRAY;
+      }
+    } else if (NAME_ATTR_NAME.equals(attrName)) {
+      return new PsiReference[] { new NameReference(element) };
+    } else if (MEMBER_TYPES_ATTR_NAME.equals(attrName)) {
+      final List<PsiReference> result = new ArrayList<PsiReference>(1);
+      final String text = element.getText();
+      int lastIndex = 1;
+      final int testLength = text.length();
+
+      for(int i = 1; i < testLength; ++i) {
+        if (Character.isWhitespace(text.charAt(i))) {
+          if (lastIndex != i) result.add( new TypeOrElementOrAttributeReference(element, new TextRange(lastIndex, i) ) );
+          lastIndex = i + 1;
+        }
+      }
+
+      if (lastIndex != testLength - 1) result.add( new TypeOrElementOrAttributeReference(element, new TextRange(lastIndex, testLength - 1) ) );
+      return result.toArray(new PsiReference[result.size()]);
+    } else {
+      final PsiReference prefix = createSchemaPrefixReference(element);
+      final PsiReference ref = createTypeOrElementOrAttributeReference(element, prefix == null ? null : prefix.getCanonicalText());
+      return prefix == null ? new PsiReference[] {ref} : new PsiReference[] {ref, prefix};
+    }
+  }
+
+  public static PsiReference createTypeOrElementOrAttributeReference(final PsiElement element) {
+    return createTypeOrElementOrAttributeReference(element, null);
+  }
+
+  public static PsiReference createTypeOrElementOrAttributeReference(final PsiElement element, String ns) {
+    final int length = element.getTextLength();
+    int offset = (element instanceof XmlAttributeValue) ?
+      XmlUtil.findPrefixByQualifiedName(((XmlAttributeValue)element).getValue()).length() : 0;
+    if (offset > 0) offset++;
+    final TypeOrElementOrAttributeReference ref = new TypeOrElementOrAttributeReference(element, length >= 2 ? new TextRange(1 + offset, length - 1) : TextRange.EMPTY_RANGE);
+    ref.setNamespacePrefix(ns);
+    return ref;
+  }
+
+  @Nullable
+  private static PsiReference createSchemaPrefixReference(final PsiElement element) {
+    if (element instanceof XmlAttributeValue) {
+      final XmlAttributeValue attributeValue = (XmlAttributeValue)element;
+      final String prefix = XmlUtil.findPrefixByQualifiedName(attributeValue.getValue());
+      if (prefix.length() > 0) {
+        return new SchemaPrefixReference(attributeValue, TextRange.from(1, prefix.length()), prefix, null);
+      }
+    }
+    return null;
+  }
+
+  public static @Nullable XmlNSDescriptorImpl findRedefinedDescriptor(XmlTag tag, String text) {
+    final String localName = XmlUtil.findLocalNameByQualifiedName(text);
+    for(XmlTag parentTag = tag.getParentTag(); parentTag != null; parentTag = parentTag.getParentTag()) {
+
+      if (localName.equals(parentTag.getAttributeValue("name"))) {
+        final XmlTag grandParent = parentTag.getParentTag();
+
+        if (grandParent != null && "redefine".equals(grandParent.getLocalName())) {
+          return XmlNSDescriptorImpl.getRedefinedElementDescriptor(grandParent);
+        }
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URIReferenceProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URIReferenceProvider.java
new file mode 100644
index 0000000..5c8eb58
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URIReferenceProvider.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.codeInsight.daemon.QuickFixProvider;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.quickfix.FetchExtResourceAction;
+import com.intellij.codeInsight.daemon.impl.quickfix.IgnoreExtResourceAction;
+import com.intellij.codeInsight.daemon.impl.quickfix.ManuallySetupExtResourceAction;
+import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.filters.ElementFilter;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.ProcessingContext;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * @by Maxim.Mossienko
+ */
+public class URIReferenceProvider extends PsiReferenceProvider {
+
+  public static final ElementFilter ELEMENT_FILTER = new ElementFilter() {
+    public boolean isAcceptable(Object element, PsiElement context) {
+      final PsiElement parent = context.getParent();
+      if (parent instanceof XmlAttribute) {
+        final XmlAttribute attribute = ((XmlAttribute)parent);
+        return attribute.isNamespaceDeclaration();
+      }
+      return false;
+    }
+
+    public boolean isClassAcceptable(Class hintClass) {
+      return true;
+    }
+  };
+  @NonNls private static final String HTTP = "http://";
+  @NonNls private static final String URN = "urn:";
+  @NonNls private static final String FILE = "file:";
+  @NonNls private static final String CLASSPATH = "classpath:/";
+  @NonNls
+  private static final String NAMESPACE_ATTR_NAME = "namespace";
+
+  public static class DependentNSReference extends BasicAttributeValueReference implements QuickFixProvider {
+    private final URLReference myReference;
+
+    public DependentNSReference(final PsiElement element, TextRange range, URLReference ref) {
+      super(element, range);
+      myReference = ref;
+    }
+
+    @Nullable
+    public PsiFile resolveResource() {
+      final String canonicalText = getCanonicalText();
+      return ExternalResourceManager.getInstance().getResourceLocation(canonicalText, myElement.getContainingFile(), null);
+    }
+
+    @Nullable
+    public PsiElement resolve() {
+      final PsiFile file = resolveResource();
+      if (file != null) return file;
+      return myReference.resolve();
+    }
+
+    @NotNull
+    public Object[] getVariants() {
+      return ArrayUtil.EMPTY_OBJECT_ARRAY;
+    }
+
+    public boolean isSoft() {
+      return false;
+    }
+
+    public void registerQuickfix(HighlightInfo info, PsiReference reference) {
+      QuickFixAction.registerQuickFixAction(info, new FetchExtResourceAction());
+      QuickFixAction.registerQuickFixAction(info, new ManuallySetupExtResourceAction());
+      QuickFixAction.registerQuickFixAction(info, new IgnoreExtResourceAction());
+    }
+  }
+
+  @NotNull
+  public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull final ProcessingContext context) {
+    final String text = element.getText();
+    String s = StringUtil.stripQuotesAroundValue(text);
+    final PsiElement parent = element.getParent();
+
+    if (parent instanceof XmlAttribute && "xsi:schemaLocation".equals(((XmlAttribute)parent).getName())) {
+      final List<PsiReference> refs = new ArrayList<PsiReference>(2);
+      final StringTokenizer tokenizer = new StringTokenizer(s);
+
+      while(tokenizer.hasMoreElements()) {
+        final String namespace = tokenizer.nextToken();
+        int offset = text.indexOf(namespace);
+        final URLReference urlReference = new URLReference(element, new TextRange(offset, offset + namespace.length()), true);
+        refs.add(urlReference);
+        if (!tokenizer.hasMoreElements()) break;
+        String url = tokenizer.nextToken();
+
+        offset = text.indexOf(url);
+        if (isUrlText(url, element.getProject())) refs.add(new DependentNSReference(element, new TextRange(offset,offset + url.length()), urlReference));
+        else {
+          ContainerUtil.addAll(refs, new FileReferenceSet(url, element, offset, this, false).getAllReferences());
+        }
+      }
+
+      return refs.toArray(new PsiReference[refs.size()]);
+    }
+
+
+    if (isUrlText(s, element.getProject()) ||
+        (parent instanceof XmlAttribute &&
+          ( ((XmlAttribute)parent).isNamespaceDeclaration() ||
+            NAMESPACE_ATTR_NAME.equals(((XmlAttribute)parent).getName())
+          )
+         )
+      ) {
+      if (!s.startsWith(XmlUtil.TAG_DIR_NS_PREFIX)) {
+        boolean namespaceSoftRef = parent instanceof XmlAttribute &&
+          NAMESPACE_ATTR_NAME.equals(((XmlAttribute)parent).getName()) &&
+          ((XmlAttribute)parent).getParent().getAttributeValue("schemaLocation") != null;
+        if (!namespaceSoftRef && parent instanceof XmlAttribute && ((XmlAttribute)parent).isNamespaceDeclaration()) {
+          namespaceSoftRef = parent.getContainingFile().getContext() != null;
+        }
+        return new URLReference[] { new URLReference(element, null, namespaceSoftRef)};
+      }
+    }
+
+    s = s.substring(getPrefixLength(s));
+    return new FileReferenceSet(s,element,text.indexOf(s), this,true).getAllReferences();
+  }
+
+  public static int getPrefixLength(@NotNull final String s) {
+    if (s.startsWith(XmlUtil.TAG_DIR_NS_PREFIX)) return XmlUtil.TAG_DIR_NS_PREFIX.length();
+    if (s.startsWith(FILE)) return FILE.length();
+    if (s.startsWith(CLASSPATH)) return CLASSPATH.length();
+    return 0;
+  }
+
+  static boolean isUrlText(final String s, Project project) {
+    final boolean surelyUrl = s.startsWith(HTTP) || s.startsWith(URN);
+    if (surelyUrl) return surelyUrl;
+    int protocolIndex = s.indexOf(":/");
+    if (protocolIndex > 1 && !s.regionMatches(0,"classpath",0,protocolIndex)) return true;
+    return ExternalResourceManager.getInstance().getResourceLocation(s, project) != s;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReference.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReference.java
new file mode 100644
index 0000000..f582111
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReference.java
@@ -0,0 +1,248 @@
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
+import com.intellij.codeInsight.daemon.QuickFixProvider;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.quickfix.*;
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.javaee.ExternalResourceManagerEx;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.Processor;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.XmlSchemaProvider;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Avdeev
+*/
+public class URLReference implements PsiReference, QuickFixProvider, EmptyResolveMessageProvider {
+  @NonNls private static final String TARGET_NAMESPACE_ATTR_NAME = "targetNamespace";
+
+  private final PsiElement myElement;
+  private final TextRange myRange;
+  private final boolean mySoft;
+  private boolean myIncorrectResourceMapped;
+
+  public URLReference(PsiElement element) {
+    this(element, null, false);
+  }
+
+  public URLReference(PsiElement element, @Nullable TextRange range, boolean soft) {
+    myElement = element;
+    myRange = range;
+    mySoft = soft;
+  }
+
+  public PsiElement getElement() {
+    return myElement;
+  }
+
+  public TextRange getRangeInElement() {
+    return myRange != null ? myRange : ElementManipulators.getValueTextRange(myElement);
+  }
+
+  @Nullable
+  public PsiElement resolve() {
+    myIncorrectResourceMapped = false;
+    final String canonicalText = getCanonicalText();
+
+    if (canonicalText.length() == 0) {
+      final XmlAttribute attr = PsiTreeUtil.getParentOfType(getElement(), XmlAttribute.class);
+
+      if (attr != null &&
+            attr.isNamespaceDeclaration() &&
+            attr.getNamespacePrefix().length() == 0 ||
+          ExternalResourceManagerEx.getInstanceEx().isIgnoredResource(canonicalText)
+         ) {
+        // Namespaces in XML 1.0 2nd edition, Section 6.2, last paragraph
+        // The attribute value in a default namespace declaration MAY be empty. This has the same effect, within the scope of the declaration,
+        // of there being no default namespace
+        return myElement;
+      }
+      return null;
+    }
+
+    if (ExternalResourceManagerEx.getInstanceEx().isIgnoredResource(canonicalText)) return myElement;
+    final XmlTag tag = PsiTreeUtil.getParentOfType(myElement, XmlTag.class);
+    if (tag != null && canonicalText.equals(tag.getAttributeValue(TARGET_NAMESPACE_ATTR_NAME))) return tag;
+
+    final PsiFile containingFile = myElement.getContainingFile();
+
+    if (tag != null &&
+        tag.getAttributeValue("schemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI) == null
+       ) {
+      final PsiFile file = ExternalResourceManager.getInstance().getResourceLocation(canonicalText, containingFile, tag.getAttributeValue("version"));
+      if (file != null) return file;
+    }
+
+    if (containingFile instanceof XmlFile) {
+      final XmlDocument document = ((XmlFile)containingFile).getDocument();
+      assert document != null;
+      final XmlTag rootTag = document.getRootTag();
+
+     if (rootTag == null) {
+        return ExternalResourceManager.getInstance().getResourceLocation(canonicalText, containingFile, null);
+      }
+      final XmlNSDescriptor nsDescriptor = rootTag.getNSDescriptor(canonicalText, true);
+      if (nsDescriptor != null) return nsDescriptor.getDescriptorFile();
+
+      final String url = ExternalResourceManager.getInstance().getResourceLocation(canonicalText, myElement.getProject());
+      if (!url.equals(canonicalText)) {
+        myIncorrectResourceMapped = true;
+        return null;
+      }
+
+      if (tag == rootTag && (tag.getNamespace().equals(XmlUtil.XML_SCHEMA_URI) || tag.getNamespace().equals(XmlUtil.WSDL_SCHEMA_URI))) {
+        for(XmlTag t:tag.getSubTags()) {
+          final String name = t.getLocalName();
+          if ("import".equals(name)) {
+            if (canonicalText.equals(t.getAttributeValue("namespace"))) return t;
+          } else if (!"include".equals(name) && !"redefine".equals(name) && !"annotation".equals(name)) break;
+        }
+      }
+
+      final PsiElement[] result = new PsiElement[1];
+      processWsdlSchemas(rootTag,new Processor<XmlTag>() {
+        public boolean process(final XmlTag t) {
+          if (canonicalText.equals(t.getAttributeValue(TARGET_NAMESPACE_ATTR_NAME))) {
+            result[0] = t;
+            return false;
+          }
+          for (XmlTag anImport : t.findSubTags("import", t.getNamespace())) {
+            if (canonicalText.equals(anImport.getAttributeValue("namespace"))) {
+              final XmlAttribute location = anImport.getAttribute("schemaLocation");
+              if (location != null) {
+                result[0] = FileReferenceUtil.findFile(location.getValueElement());
+              }
+            }
+          }
+          return true;
+        }
+      });
+
+      return result[0];
+    }
+    return null;
+  }
+
+  @NotNull
+  public String getCanonicalText() {
+    final String text = myElement.getText();
+    if (text.length() > 1) {
+      return myRange == null ? text.substring(1, text.length() - 1) : myRange.substring(text);
+    }
+
+    return "";
+  }
+
+  public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+    final TextRange textRangeInElement = getRangeInElement();
+    final PsiElement elementToChange = myElement.findElementAt(textRangeInElement.getStartOffset());
+    assert elementToChange != null;
+    final ElementManipulator<PsiElement> manipulator = ElementManipulators.getManipulator(elementToChange);
+    assert manipulator != null;
+    final int offsetFromStart = myElement.getTextRange().getStartOffset() + textRangeInElement.getStartOffset() - elementToChange.getTextOffset();
+
+    manipulator.handleContentChange(elementToChange, new TextRange(offsetFromStart, offsetFromStart + textRangeInElement.getLength()),newElementName);
+    return myElement;
+  }
+
+  public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+    assert element instanceof PsiFile;
+
+    if (!URIReferenceProvider.isUrlText(getCanonicalText(), element.getProject())) {
+      // TODO: this should work!
+      final VirtualFile virtualFile = ((PsiFile)element).getVirtualFile();
+      assert virtualFile != null;
+      handleElementRename(VfsUtil.fixIDEAUrl(virtualFile.getPresentableUrl()));
+    }
+    return myElement;
+  }
+
+  public boolean isReferenceTo(PsiElement element) {
+    return myElement.getManager().areElementsEquivalent(resolve(),element);
+  }
+
+  @NotNull
+  public Object[] getVariants() {
+    final XmlFile file = (XmlFile)myElement.getContainingFile();
+    Set<String> list = new HashSet<String>();
+    for (XmlSchemaProvider provider : Extensions.getExtensions(XmlSchemaProvider.EP_NAME)) {
+      if (provider.isAvailable(file)) {
+        list.addAll(provider.getAvailableNamespaces(file, null));
+      }
+    }
+    if (!list.isEmpty()) {
+      return ArrayUtil.toObjectArray(list);
+    }
+    String[] resourceUrls = ExternalResourceManager.getInstance().getResourceUrls(null, true);
+    final XmlDocument document = file.getDocument();
+    assert document != null;
+    XmlTag rootTag = document.getRootTag();
+    final ArrayList<String> additionalNs = new ArrayList<String>();
+    if (rootTag != null) processWsdlSchemas(rootTag, new Processor<XmlTag>() {
+      public boolean process(final XmlTag xmlTag) {
+        final String s = xmlTag.getAttributeValue(TARGET_NAMESPACE_ATTR_NAME);
+        if (s != null) { additionalNs.add(s); }
+        return true;
+      }
+    });
+    resourceUrls = ArrayUtil.mergeArrays(resourceUrls, ArrayUtil.toStringArray(additionalNs));
+    return resourceUrls;
+  }
+
+  public boolean isSoft() {
+    return mySoft;
+  }
+
+  public void registerQuickfix(HighlightInfo info, PsiReference reference) {
+    QuickFixAction.registerQuickFixAction(info, new FetchExtResourceAction());
+    QuickFixAction.registerQuickFixAction(info, new ManuallySetupExtResourceAction());
+    QuickFixAction.registerQuickFixAction(info, new IgnoreExtResourceAction());
+
+    final PsiElement parentElement = reference.getElement().getParent();
+    if (parentElement instanceof XmlAttribute && ((XmlAttribute)parentElement).isNamespaceDeclaration()) {
+      QuickFixAction.registerQuickFixAction(info, new AddXsiSchemaLocationForExtResourceAction());
+    }
+  }
+
+  public String getUnresolvedMessagePattern() {
+    return XmlErrorMessages.message(myIncorrectResourceMapped ? "registered.resource.is.not.recognized":"uri.is.not.registered");
+  }
+
+  public static void processWsdlSchemas(final XmlTag rootTag, Processor<XmlTag> processor) {
+    if ("definitions".equals(rootTag.getLocalName())) {
+      final String nsPrefix = rootTag.getNamespacePrefix();
+      final String types = nsPrefix.length() == 0 ? "types" : nsPrefix  + ":types";
+      final XmlTag subTag = rootTag.findFirstSubTag(types);
+
+      if (subTag != null) {
+        for (int i = 0; i < XmlUtil.SCHEMA_URIS.length; i++) {
+          final XmlTag[] tags = subTag.findSubTags("schema", XmlUtil.SCHEMA_URIS[i]);
+          for (XmlTag t : tags) {
+            if (!processor.process(t)) return;
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XmlValueReference.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XmlValueReference.java
new file mode 100644
index 0000000..9bccd25
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XmlValueReference.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.reference.impl.providers;
+
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.ElementManipulators;
+import com.intellij.psi.ElementManipulator;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+*/
+public abstract class XmlValueReference implements PsiReference {
+  protected XmlTag myTag;
+  protected TextRange myRange;
+
+  protected XmlValueReference(XmlTag tag) {
+    myTag = tag;
+    myRange = ElementManipulators.getValueTextRange(tag);
+  }
+
+  public PsiElement getElement() {
+    return myTag;
+  }
+
+  public TextRange getRangeInElement() {
+    return myRange;
+  }
+
+  @NotNull
+  public String getCanonicalText() {
+    return myRange.substring(myTag.getText());
+  }
+
+  protected void replaceContent(final String str) throws IncorrectOperationException {
+    final ElementManipulator<XmlTag> manipulator = ElementManipulators.getManipulator(myTag);
+    manipulator.handleContentChange(myTag, myRange, str);
+    myRange = manipulator.getRangeInElement(myTag);
+  }
+
+  public boolean isReferenceTo(PsiElement element) {
+    return myTag.getManager().areElementsEquivalent(element, resolve());
+  }
+
+  public boolean isSoft() {
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/tree/HtmlFileElement.java b/xml/impl/src/com/intellij/psi/impl/source/tree/HtmlFileElement.java
new file mode 100644
index 0000000..e1d0624
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/tree/HtmlFileElement.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.tree;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlElementType;
+
+public class HtmlFileElement extends FileElement implements XmlElementType  {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.HtmlFileElement");
+
+  public HtmlFileElement(CharSequence text) {
+    super(HTML_FILE, text);
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    if (child.getElementType() == HTML_DOCUMENT) {
+      return XmlChildRole.HTML_DOCUMENT;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/tree/XmlFileElement.java b/xml/impl/src/com/intellij/psi/impl/source/tree/XmlFileElement.java
new file mode 100644
index 0000000..db3128d
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/tree/XmlFileElement.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.tree;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlElementType;
+
+public class XmlFileElement extends FileElement implements XmlElementType {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.XmlFileElement");
+
+  public XmlFileElement(CharSequence text) {
+    super(XML_FILE, text);
+  }
+
+  public XmlFileElement(IElementType type, CharSequence text) {
+    super(type, text);
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    if (child.getElementType() == XML_DOCUMENT ||
+        child.getElementType() == HTML_DOCUMENT) {
+      return XmlChildRole.XML_DOCUMENT;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlAttributeLiteralEscaper.java b/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlAttributeLiteralEscaper.java
new file mode 100644
index 0000000..2160661
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlAttributeLiteralEscaper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.tree.injected;
+
+import com.intellij.psi.impl.source.xml.XmlAttributeValueImpl;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.LiteralTextEscaper;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.ProperTextRange;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author cdr
+*/
+public class XmlAttributeLiteralEscaper extends LiteralTextEscaper<XmlAttributeValueImpl> {
+  private final XmlAttribute myXmlAttribute;
+
+  public XmlAttributeLiteralEscaper(XmlAttributeValueImpl host) {
+    super(host);
+    myXmlAttribute = (XmlAttribute)host.getParent();
+  }
+
+  public boolean decode(@NotNull final TextRange rangeInsideHost, @NotNull StringBuilder outChars) {
+    ProperTextRange.assertProperRange(rangeInsideHost);
+    TextRange valueTextRange = myXmlAttribute.getValueTextRange();
+    int startInDecoded = myXmlAttribute.physicalToDisplay(rangeInsideHost.getStartOffset() - valueTextRange.getStartOffset());
+    int endInDecoded = myXmlAttribute.physicalToDisplay(rangeInsideHost.getEndOffset() - valueTextRange.getStartOffset());
+    String displayValue = myXmlAttribute.getDisplayValue();
+    //todo investigate IIOB http://www.jetbrains.net/jira/browse/IDEADEV-16796
+    startInDecoded = startInDecoded < 0 ? 0 : startInDecoded > displayValue.length() ? displayValue.length() : startInDecoded;
+    endInDecoded = endInDecoded < 0 ? 0 : endInDecoded > displayValue.length() ? displayValue.length() : endInDecoded;
+    if (startInDecoded > endInDecoded) endInDecoded = startInDecoded;
+    outChars.append(displayValue, startInDecoded, endInDecoded);
+    return true;
+  }
+
+  public int getOffsetInHost(final int offsetInDecoded, @NotNull final TextRange rangeInsideHost) {
+    TextRange valueTextRange = myXmlAttribute.getValueTextRange();
+    int displayStart = myXmlAttribute.physicalToDisplay(rangeInsideHost.getStartOffset());
+
+    int dp = myXmlAttribute.displayToPhysical(offsetInDecoded + displayStart - valueTextRange.getStartOffset());
+    if (dp == -1) return -1;
+    return dp + valueTextRange.getStartOffset();
+  }
+
+  public boolean isOneLine() {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlCommentLiteralEscaper.java b/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlCommentLiteralEscaper.java
new file mode 100644
index 0000000..8426623
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlCommentLiteralEscaper.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.tree.injected;
+
+import com.intellij.psi.LiteralTextEscaper;
+import com.intellij.psi.impl.source.xml.XmlCommentImpl;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.ProperTextRange;
+import com.intellij.lang.Commenter;
+import com.intellij.lang.LanguageCommenters;
+import com.intellij.lang.CodeDocumentationAwareCommenter;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class XmlCommentLiteralEscaper extends LiteralTextEscaper<XmlCommentImpl> {
+  public XmlCommentLiteralEscaper(@NotNull XmlCommentImpl host) {
+    super(host);
+  }
+
+  public boolean decode(@NotNull final TextRange rangeInsideHost, @NotNull final StringBuilder outChars) {
+    ProperTextRange.assertProperRange(rangeInsideHost);
+    outChars.append(myHost.getText(), rangeInsideHost.getStartOffset(), rangeInsideHost.getEndOffset());
+    return true;
+  }
+
+  public int getOffsetInHost(final int offsetInDecoded, @NotNull final TextRange rangeInsideHost) {
+    int offset = offsetInDecoded + rangeInsideHost.getStartOffset();
+    if (offset < rangeInsideHost.getStartOffset()) offset = rangeInsideHost.getStartOffset();
+    if (offset > rangeInsideHost.getEndOffset()) offset = rangeInsideHost.getEndOffset();
+    return offset;
+  }
+
+  public boolean isOneLine() {
+    final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(myHost.getLanguage());
+    if (commenter instanceof CodeDocumentationAwareCommenter) {
+      return myHost.getTokenType() == ((CodeDocumentationAwareCommenter) commenter).getLineCommentTokenType();
+    }
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlTextLiteralEscaper.java b/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlTextLiteralEscaper.java
new file mode 100644
index 0000000..ca61547
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlTextLiteralEscaper.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.tree.injected;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.ProperTextRange;
+import com.intellij.psi.impl.source.xml.XmlTextImpl;
+import com.intellij.psi.LiteralTextEscaper;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author cdr
+*/
+public class XmlTextLiteralEscaper extends LiteralTextEscaper<XmlTextImpl> {
+  public XmlTextLiteralEscaper(final XmlTextImpl xmlText) {
+    super(xmlText);
+  }
+
+  public boolean decode(@NotNull final TextRange rangeInsideHost, @NotNull StringBuilder outChars) {
+    ProperTextRange.assertProperRange(rangeInsideHost);
+    int startInDecoded = myHost.physicalToDisplay(rangeInsideHost.getStartOffset());
+    int endInDecoded = myHost.physicalToDisplay(rangeInsideHost.getEndOffset());
+    outChars.append(myHost.getValue(), startInDecoded, endInDecoded);
+    return true;
+  }
+
+  public int getOffsetInHost(final int offsetInDecoded, @NotNull final TextRange rangeInsideHost) {
+    final int rangeInsideHostStartOffset = rangeInsideHost.getStartOffset();
+    int displayStart = myHost.physicalToDisplay(rangeInsideHostStartOffset);
+
+    int i = myHost.displayToPhysical(offsetInDecoded + displayStart);
+    if (i < rangeInsideHostStartOffset) i = rangeInsideHostStartOffset;
+    final int rangeInsideHostEndOffset = rangeInsideHost.getEndOffset();
+    if (i > rangeInsideHostEndOffset) i = rangeInsideHostEndOffset;
+    return i;
+  }
+
+  @NotNull
+  public TextRange getRelevantTextRange() {
+    return myHost.getCDATAInterior();
+  }
+
+  public boolean isOneLine() {
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/PossiblePrefixReference.java b/xml/impl/src/com/intellij/psi/impl/source/xml/PossiblePrefixReference.java
new file mode 100644
index 0000000..07e568a
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/PossiblePrefixReference.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.psi.PsiReference;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public interface PossiblePrefixReference extends PsiReference {
+
+  boolean isPrefixReference();
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefix.java b/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefix.java
new file mode 100644
index 0000000..5fbc795
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefix.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.ElementManipulators;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.RenameableFakePsiElement;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.PlatformIcons;
+import com.intellij.xml.XmlExtension;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class SchemaPrefix extends RenameableFakePsiElement {
+  private final TextRange myRange;
+  private final String myName;
+
+  public SchemaPrefix(final XmlAttribute parent, TextRange range, String name) {
+    super(parent);
+    myRange = range;
+    myName = name;
+  }
+
+  public static SchemaPrefix createJspPrefix(XmlAttributeValue element, String prefix) {
+    TextRange range = ElementManipulators.getValueTextRange(element).shiftRight(element.getStartOffsetInParent());
+    return new SchemaPrefix((XmlAttribute)element.getParent(), range, prefix) {
+      @Override
+      protected String getNamespace() {
+        return ((XmlAttribute)getParent()).getParent().getAttributeValue("uri");
+      }
+    };
+  }
+
+  public String getTypeName() {
+    return "XML Namespace Prefix";
+  }
+
+  public Icon getIcon() {
+    return PlatformIcons.VARIABLE_ICON;
+  }
+
+  @Override
+  public int getTextOffset() {
+    return getParent().getTextRange().getStartOffset() + myRange.getStartOffset();
+  }
+
+  @Override
+  public int getTextLength() {
+    return myName.length();
+  }
+
+  @Override
+  public String getName() {
+    return myName;
+  }
+
+  public XmlAttribute getDeclaration() {
+    return (XmlAttribute)getParent();
+  }
+
+  @Override
+  public TextRange getTextRange() {
+    return TextRange.from(getTextOffset(), getTextLength());
+  }
+
+  @NotNull
+  @Override
+  public SearchScope getUseScope() {
+    return XmlExtension.getExtension(getContainingFile()).getNsPrefixScope(getDeclaration());
+  }
+
+  @Override
+  public boolean isEquivalentTo(PsiElement another) {
+    return another instanceof SchemaPrefix && ((SchemaPrefix)another).getDeclaration() == getDeclaration();
+  }
+
+  public String getQuickNavigateInfo() {
+    String ns = getNamespace();
+    StringBuilder builder = new StringBuilder().append(getTypeName()).append(" \"").append(getName()).append("\"");
+    if (ns != null) {
+      builder.append(" (").append(ns).append(")");
+    }
+    return builder.toString();
+  }
+
+  @Nullable
+  protected String getNamespace() {
+    XmlAttribute parent = (XmlAttribute)getParent();
+    return parent.getValue();
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java b/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java
new file mode 100644
index 0000000..ba4c8b9
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReferenceBase;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlExtension;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class SchemaPrefixReference extends PsiReferenceBase<XmlElement> implements PossiblePrefixReference {
+
+  private final SchemaPrefix myPrefix;
+
+  private final String myName;
+  @Nullable
+  private final TagNameReference myTagNameReference;
+
+  /**
+   *
+   * @param element XmlAttribute || XmlAttributeValue
+   * @param range
+   * @param name
+   * @param tagNameReference
+   */
+  public SchemaPrefixReference(XmlElement element, TextRange range, String name, @Nullable TagNameReference tagNameReference) {
+    super(element, range);
+    myName = name;
+    myTagNameReference = tagNameReference;
+    if (myElement instanceof XmlAttribute && (((XmlAttribute)myElement).isNamespaceDeclaration())) {
+      myPrefix = new SchemaPrefix((XmlAttribute)myElement, getRangeInElement(), myName);
+    }
+    else if (myElement instanceof XmlAttributeValue &&
+             ((XmlAttribute)myElement.getParent()).getLocalName().equals("prefix")) {
+      myPrefix = SchemaPrefix.createJspPrefix((XmlAttributeValue)myElement, myName);
+    }
+    else {
+      myPrefix = null;
+    }
+  }
+
+  public String getNamespacePrefix() {
+    return myName;
+  }
+
+  public SchemaPrefix resolve() {
+    return myPrefix == null ? resolvePrefix(myElement, myName) : myPrefix;
+  }
+
+  @NotNull
+  public Object[] getVariants() {
+    if (myTagNameReference != null) {
+      return new LookupElement[]{ myTagNameReference.createClosingTagLookupElement(myTagNameReference.getTagElement(), true)};
+    }
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
+  }
+
+  @Override
+  public boolean isReferenceTo(PsiElement element) {
+    if (!(element instanceof SchemaPrefix) || !myName.equals(((SchemaPrefix)element).getName())) return false;
+    return super.isReferenceTo(element);
+  }
+
+  @Override
+  public PsiElement handleElementRename(String name) throws IncorrectOperationException {
+    if (myElement instanceof XmlAttribute) {
+      final XmlAttribute attr = (XmlAttribute)myElement;
+      return ("xmlns".equals(attr.getNamespacePrefix()))
+             ? attr.setName(attr.getNamespacePrefix() + ":" + name)
+             : attr.setName(name + ":" + attr.getLocalName());
+    }
+    else if (myElement instanceof XmlTag) {
+      final XmlTag tag = (XmlTag)myElement;
+      return tag.setName(name + ":" + tag.getLocalName());
+    }
+    return super.handleElementRename(name);
+  }
+
+  @Nullable
+  public static SchemaPrefix resolvePrefix(PsiElement element, String name) {
+    XmlExtension extension = XmlExtension.getExtension(element.getContainingFile());
+    return extension.getPrefixDeclaration(PsiTreeUtil.getParentOfType(element, XmlTag.class, false), name);
+  }
+
+  @Override
+  public boolean isSoft() {
+    return true;
+  }
+
+  @Override
+  public boolean isPrefixReference() {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/TagNameReference.java b/xml/impl/src/com/intellij/psi/impl/source/xml/TagNameReference.java
new file mode 100644
index 0000000..c89fb9b
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/TagNameReference.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.codeInsight.TailType;
+import com.intellij.codeInsight.completion.XmlTagInsertHandler;
+import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.codeInsight.lookup.TailTypeDecorator;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.meta.PsiMetaOwner;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.NullableFunction;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementDescriptorAwareAboutChildren;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.impl.schema.XmlElementDescriptorImpl;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+public class TagNameReference implements PsiReference {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.TagNameReference");
+
+  protected final boolean myStartTagFlag;
+  private final ASTNode myNameElement;
+
+  public TagNameReference(ASTNode nameElement, boolean startTagFlag) {
+    myStartTagFlag = startTagFlag;
+    myNameElement = nameElement;
+  }
+
+  public PsiElement getElement() {
+    PsiElement element = myNameElement.getPsi();
+    final PsiElement parent = element.getParent();
+    return parent instanceof XmlTag ? parent : element;
+  }
+
+  @Nullable
+  protected XmlTag getTagElement() {
+    final PsiElement element = getElement();
+    if(element == myNameElement.getPsi()) return null;
+    return (XmlTag)element;
+  }
+
+  public TextRange getRangeInElement() {
+    final ASTNode nameElement = getNameElement();
+    if (nameElement == null){
+      return TextRange.EMPTY_RANGE;
+    }
+
+    int colon = nameElement.getText().indexOf(':') + 1;
+    if (myStartTagFlag) {
+      final int parentOffset = ((TreeElement)nameElement).getStartOffsetInParent();
+      return new TextRange(parentOffset + colon, parentOffset + nameElement.getTextLength());
+    }
+    else {
+      final PsiElement element = getElement();
+      if (element == myNameElement) return new TextRange(colon, myNameElement.getTextLength());
+
+      final int elementLength = element.getTextLength();
+      int diffFromEnd = 0;
+
+      for(ASTNode node = element.getNode().getLastChildNode(); node != nameElement && node != null; node = node.getTreePrev()) {
+        diffFromEnd += node.getTextLength();
+      }
+
+      final int nameEnd = elementLength - diffFromEnd;
+      return new TextRange(nameEnd - nameElement.getTextLength() + colon, nameEnd);
+    }
+  }
+
+  private ASTNode getNameElement() {
+    return myNameElement;
+  }
+
+  public PsiElement resolve() {
+    final XmlTag tag = getTagElement();
+    final XmlElementDescriptor descriptor = tag != null ? tag.getDescriptor():null;
+
+    LOG.debug("Descriptor for tag " +
+              (tag != null ? tag.getName() : "NULL") +
+              " is " +
+              (descriptor != null ? (descriptor.toString() + ": " + descriptor.getClass().getCanonicalName()) : "NULL"));
+
+    if (descriptor != null){
+      return descriptor instanceof AnyXmlElementDescriptor ? tag : descriptor.getDeclaration();
+    }
+    return null;
+  }
+
+  @NotNull
+  public String getCanonicalText() {
+    return getNameElement().getText();
+  }
+
+  @Nullable
+  public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+    final XmlTag element = getTagElement();
+    if (element == null || !myStartTagFlag) return element;
+
+    if (newElementName.indexOf(':') == -1) {
+      final String namespacePrefix = element.getNamespacePrefix();
+      final int index = newElementName.lastIndexOf('.');
+
+      if (index != -1) {
+        final PsiElement psiElement = resolve();
+        
+        if (psiElement instanceof PsiFile || (psiElement != null && psiElement.isEquivalentTo(psiElement.getContainingFile()))) {
+          newElementName = newElementName.substring(0, index);
+        }
+      }
+      newElementName = prependNamespacePrefix(newElementName, namespacePrefix);
+    }
+    element.setName(newElementName);
+    return element;
+  }
+
+  private static String prependNamespacePrefix(String newElementName, String namespacePrefix) {
+    newElementName = (namespacePrefix.length() > 0 ? namespacePrefix + ":":namespacePrefix) + newElementName;
+    return newElementName;
+  }
+
+  public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+    PsiMetaData metaData = null;
+
+    if (element instanceof PsiMetaOwner){
+      final PsiMetaOwner owner = (PsiMetaOwner)element;
+      metaData = owner.getMetaData();
+
+      if (metaData instanceof XmlElementDescriptor){
+        return getTagElement().setName(metaData.getName(getElement())); // TODO: need to evaluate new ns prefix
+      }
+    } else if (element instanceof PsiFile) {
+      final XmlTag tagElement = getTagElement();
+      if (tagElement == null || !myStartTagFlag) return tagElement;
+      String newElementName = ((PsiFile)element).getName();
+      final int index = newElementName.lastIndexOf('.');
+
+      // TODO: need to evaluate new ns prefix
+      newElementName = prependNamespacePrefix(newElementName.substring(0, index), tagElement.getNamespacePrefix());
+
+      return getTagElement().setName(newElementName);
+    }
+
+    throw new IncorrectOperationException("Cant bind to not a xml element definition!"+element+","+metaData);
+  }
+
+  public boolean isReferenceTo(PsiElement element) {
+    return getElement().getManager().areElementsEquivalent(element, resolve());
+  }
+
+  @NotNull
+  public LookupElement[] getVariants(){
+    final PsiElement element = getElement();
+    if(!myStartTagFlag){
+      if (element instanceof XmlTag) {
+        return new LookupElement[]{createClosingTagLookupElement((XmlTag)element, false)};
+      }
+      return LookupElement.EMPTY_ARRAY;
+    }
+    return getTagNameVariants((XmlTag)element, ((XmlTag)element).getNamespacePrefix());
+  }
+
+  public LookupElement createClosingTagLookupElement(XmlTag tag, boolean includePrefix) {
+    LookupElementBuilder builder = LookupElementBuilder.create(includePrefix || !myNameElement.getText().contains(":") ? tag.getName() : tag.getLocalName());
+    return TailTypeDecorator.withTail(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE.applyPolicy(builder),
+                                      TailType.createSimpleTailType('>'));
+  }
+
+  public static LookupElement[] getTagNameVariants(final @NotNull XmlTag tag, final String prefix) {
+    final List<String> namespaces;
+    if (prefix.isEmpty()) {
+      namespaces = new ArrayList<String>(Arrays.asList(tag.knownNamespaces()));
+      namespaces.add(XmlUtil.EMPTY_URI); // empty namespace
+    }
+    else {
+      namespaces = new ArrayList<String>(Collections.singletonList(tag.getNamespace()));
+    }
+    List<String> nsInfo = new ArrayList<String>();
+    final String[] variants = getTagNameVariants(tag, namespaces, nsInfo);
+    List<LookupElement> elements = new ArrayList<LookupElement>(variants.length);
+    for (int i = 0, variantsLength = variants.length; i < variantsLength; i++) {
+      String qname = variants[i];
+      if (!prefix.isEmpty() && qname.startsWith(prefix + ":")) {
+        qname = qname.substring(prefix.length() + 1);
+      }
+      LookupElementBuilder lookupElement = LookupElementBuilder.create(qname);
+      final int separator = qname.indexOf(':');
+      if (separator > 0) {
+        lookupElement = lookupElement.withLookupString(qname.substring(separator + 1));
+      }
+      String ns = nsInfo.get(i);
+      if (StringUtil.isNotEmpty(ns)) {
+        lookupElement = lookupElement.withTypeText(ns, true);
+      }
+      elements.add(lookupElement.withInsertHandler(XmlTagInsertHandler.INSTANCE));
+    }
+    return elements.toArray(new LookupElement[elements.size()]);
+  }
+
+  public static String[] getTagNameVariants(final XmlTag element,
+                                            final Collection<String> namespaces,
+                                            @Nullable List<String> nsInfo) {
+
+    XmlElementDescriptor elementDescriptor = null;
+    String elementNamespace = null;
+
+    final Map<String, XmlElementDescriptor> descriptorsMap = new HashMap<String, XmlElementDescriptor>();
+    PsiElement context = element.getParent();
+    PsiElement curElement = element.getParent();
+
+    {
+      while(curElement instanceof XmlTag){
+        final XmlTag declarationTag = (XmlTag)curElement;
+        final String namespace = declarationTag.getNamespace();
+
+        if(!descriptorsMap.containsKey(namespace)) {
+          final XmlElementDescriptor descriptor = declarationTag.getDescriptor();
+
+          if(descriptor != null) {
+            descriptorsMap.put(namespace, descriptor);
+            if(elementDescriptor == null) {
+              elementDescriptor = descriptor;
+              elementNamespace = namespace;
+            }
+          }
+        }
+        curElement = curElement.getContext();
+      }
+    }
+
+    final Set<XmlNSDescriptor> visited = new HashSet<XmlNSDescriptor>();
+    final XmlExtension extension = XmlExtension.getExtension(element.getContainingFile());
+    final ArrayList<XmlElementDescriptor> variants = new ArrayList<XmlElementDescriptor>();
+    for (final String namespace: namespaces) {
+      final int initialSize = variants.size();
+      processVariantsInNamespace(namespace, element, variants, elementDescriptor, elementNamespace, descriptorsMap, visited,
+                                 context instanceof XmlTag ? (XmlTag)context : element, extension);
+      if (nsInfo != null) {
+        for (int i = initialSize; i < variants.size(); i++) {
+          nsInfo.add(namespace);
+        }
+      }
+    }
+
+    final boolean hasPrefix = StringUtil.isNotEmpty(element.getNamespacePrefix());
+    final List<String> list = ContainerUtil.mapNotNull(variants, new NullableFunction<XmlElementDescriptor, String>() {
+      public String fun(XmlElementDescriptor descriptor) {
+        if (descriptor instanceof AnyXmlElementDescriptor) {
+          return null;
+        }
+        else if (hasPrefix && descriptor instanceof XmlElementDescriptorImpl && 
+                 !namespaces.contains(((XmlElementDescriptorImpl)descriptor).getNamespace())) {
+          return null;
+        }
+
+        return descriptor.getName(element);
+      }
+    });
+    return ArrayUtil.toStringArray(list);
+  }
+
+  private static void processVariantsInNamespace(final String namespace,
+                                                 final XmlTag element,
+                                                 final List<XmlElementDescriptor> variants,
+                                                 final XmlElementDescriptor elementDescriptor,
+                                                 final String elementNamespace,
+                                                 final Map<String, XmlElementDescriptor> descriptorsMap,
+                                                 final Set<XmlNSDescriptor> visited,
+                                                 XmlTag parent,
+                                                 final XmlExtension extension) {
+    if(descriptorsMap.containsKey(namespace)){
+        final XmlElementDescriptor descriptor = descriptorsMap.get(namespace);
+
+      if(isAcceptableNs(element, elementDescriptor, elementNamespace, namespace)){
+        for(XmlElementDescriptor containedDescriptor: descriptor.getElementsDescriptors(parent)) {
+          if (containedDescriptor != null) variants.add(containedDescriptor);
+        }
+      }
+
+      if (element instanceof HtmlTag) {
+        HtmlUtil.addHtmlSpecificCompletions(descriptor, element, variants);
+      }
+      visited.add(descriptor.getNSDescriptor());
+    }
+    else{
+      // Don't use default namespace in case there are other namespaces in scope
+      // If there are tags from default namespace they will be handeled via
+      // their element descriptors (prev if section)
+      if (namespace == null) return;
+      if(namespace.length() == 0 && !visited.isEmpty()) return;
+
+      XmlNSDescriptor nsDescriptor = getDescriptor(element, namespace, true, extension);
+      if (nsDescriptor == null) {
+        if(!descriptorsMap.isEmpty()) return;
+        nsDescriptor = getDescriptor(element, namespace, false, extension);
+      }
+
+      if(nsDescriptor != null && !visited.contains(nsDescriptor) &&
+         isAcceptableNs(element, elementDescriptor, elementNamespace, namespace)
+        ){
+        visited.add(nsDescriptor);
+        final XmlElementDescriptor[] rootElementsDescriptors =
+          nsDescriptor.getRootElementsDescriptors(PsiTreeUtil.getParentOfType(element, XmlDocument.class));
+
+        final XmlTag parentTag = extension.getParentTagForNamespace(element, nsDescriptor);
+        final XmlElementDescriptor parentDescriptor;
+        if (parentTag == element.getParentTag()) {
+          parentDescriptor = elementDescriptor;
+        }
+        else {
+          assert parentTag != null;
+          parentDescriptor = parentTag.getDescriptor();
+        }
+
+        for(XmlElementDescriptor candidateDescriptor: rootElementsDescriptors) {
+          if (candidateDescriptor != null &&
+              couldContainDescriptor(parentTag, parentDescriptor, candidateDescriptor, namespace, false)) {
+            variants.add(candidateDescriptor);
+          }
+        }
+      }
+    }
+  }
+
+  private static XmlNSDescriptor getDescriptor(final XmlTag element, final String namespace, final boolean strict,
+                                               final XmlExtension extension) {
+    return extension.getNSDescriptor(element, namespace, strict);
+  }
+
+  public static boolean couldContain(XmlTag parent, XmlTag child) {
+    return couldContainDescriptor(parent, parent.getDescriptor(), child.getDescriptor(), child.getNamespace(), true);
+  }
+
+  private static boolean couldContainDescriptor(final XmlTag parentTag,
+                                                final XmlElementDescriptor parentDescriptor,
+                                                final XmlElementDescriptor childDescriptor,
+                                                String childNamespace, boolean strict) {
+
+    if (XmlUtil.nsFromTemplateFramework(childNamespace)) return true;
+    if (parentTag == null) return true;
+    if (parentDescriptor == null) return false;
+    final XmlTag childTag = parentTag.createChildTag(childDescriptor.getName(), childNamespace, null, false);
+    childTag.putUserData(XmlElement.INCLUDING_ELEMENT, parentTag);
+    XmlElementDescriptor descriptor = parentDescriptor.getElementDescriptor(childTag, parentTag);
+    return descriptor != null && (!strict || !(descriptor instanceof AnyXmlElementDescriptor));
+  }
+
+  private static boolean isAcceptableNs(final XmlTag element, final XmlElementDescriptor elementDescriptor,
+                                        final String elementNamespace,
+                                        final String namespace) {
+    return !(elementDescriptor instanceof XmlElementDescriptorAwareAboutChildren) ||
+        elementNamespace == null ||
+        elementNamespace.equals(namespace) ||
+         ((XmlElementDescriptorAwareAboutChildren)elementDescriptor).allowElementsFromNamespace(namespace, element.getParentTag());
+  }
+
+  public boolean isSoft() {
+    return false;
+  }
+
+  @Nullable
+  static TagNameReference createTagNameReference(XmlElement element, @NotNull ASTNode nameElement, boolean startTagFlag) {
+    final XmlExtension extension = XmlExtension.getExtensionByElement(element);
+    return extension == null ? null : extension.createTagNameReference(nameElement, startTagFlag);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttlistDeclImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttlistDeclImpl.java
new file mode 100644
index 0000000..828e801
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttlistDeclImpl.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.filters.ClassFilter;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.scope.processor.FilterElementProcessor;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.xml.*;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Mike
+ */
+public class XmlAttlistDeclImpl extends XmlElementImpl implements XmlAttlistDecl {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlAttlistDeclImpl");
+
+  public XmlAttlistDeclImpl() {
+    super(XmlElementType.XML_ATTLIST_DECL);
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    if (child.getElementType() == XmlElementType.XML_NAME) {
+      return XmlChildRole.XML_NAME;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  public XmlElement getNameElement() {
+    return (XmlElement)findChildByRoleAsPsiElement(XmlChildRole.XML_NAME);
+  }
+
+  public XmlAttributeDecl[] getAttributeDecls() {
+    final List<XmlAttributeDecl> result = new ArrayList<XmlAttributeDecl>();
+    processElements(new FilterElementProcessor(new ClassFilter(XmlAttributeDecl.class), result) {
+      public boolean execute(@NotNull final PsiElement element) {
+        if (element instanceof XmlAttributeDecl) {
+          if (element.getNextSibling() == null && element.getChildren().length == 1) {
+            return true;
+          }
+          return super.execute(element);
+        }
+        return true;
+      }
+    }, this);
+    return result.toArray(new XmlAttributeDecl[result.size()]);
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    return ReferenceProvidersRegistry.getReferencesFromProviders(this,XmlAttlistDecl.class);
+  }
+
+  public String getName() {
+    XmlElement xmlElement = getNameElement();
+    if (xmlElement != null) return xmlElement.getText();
+
+    return getNameFromEntityRef(this, XmlElementType.XML_ATTLIST_DECL_START);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttributeDeclImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttributeDeclImpl.java
new file mode 100644
index 0000000..be7bf30
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttributeDeclImpl.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.ide.util.EditSourceUtil;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.pom.Navigatable;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.impl.meta.MetaRegistry;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Mike
+ */
+public class XmlAttributeDeclImpl extends XmlElementImpl implements XmlAttributeDecl, XmlElementType {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlAttributeDeclImpl");
+  @NonNls private static final String ID_ATT = "ID";
+  @NonNls private static final String IDREF_ATT = "IDREF";
+
+  public XmlAttributeDeclImpl() {
+    super(XML_ATTRIBUTE_DECL);
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    IElementType i = child.getElementType();
+    if (i == XML_NAME) {
+      return XmlChildRole.XML_NAME;
+    }
+    else if (i == XML_ATT_REQUIRED) {
+      return XmlChildRole.XML_ATT_REQUIRED;
+    }
+    else if (i == XML_ATT_FIXED) {
+      return XmlChildRole.XML_ATT_FIXED;
+    }
+    else if (i == XML_ATT_IMPLIED) {
+      return XmlChildRole.XML_ATT_IMPLIED;
+    }
+    else if (i == XML_ATTRIBUTE_VALUE) {
+      return XmlChildRole.XML_DEFAULT_VALUE;
+    }
+    else if (i == XML_ENUMERATED_TYPE) {
+      return XmlChildRole.XML_ENUMERATED_TYPE;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  public XmlElement getNameElement() {
+    return findElementByTokenType(XML_NAME);
+  }
+
+  public boolean isAttributeRequired() {
+    return findElementByTokenType(XML_ATT_REQUIRED) != null;
+  }
+
+  public boolean isAttributeFixed() {
+    return findElementByTokenType(XML_ATT_FIXED) != null;
+  }
+
+  public boolean isAttributeImplied() {
+    return findElementByTokenType(XML_ATT_IMPLIED) != null;
+  }
+
+  public XmlAttributeValue getDefaultValue() {
+    return (XmlAttributeValue)findElementByTokenType(XML_ATTRIBUTE_VALUE);
+  }
+
+  public String getDefaultValueText() {
+    XmlAttributeValue value = getDefaultValue();
+    if (value == null) return null;
+    String text = value.getText();
+    if (text.indexOf('%') == -1 && text.indexOf('&') == -1) return text;
+
+    final StringBuilder builder = new StringBuilder();
+    value.processElements(new PsiElementProcessor() {
+      public boolean execute(@NotNull PsiElement element) {
+        builder.append(element.getText());
+        return true;
+      }
+    }, null);
+    return builder.toString();
+  }
+
+  public boolean isEnumerated() {
+    return findElementByTokenType(XML_ENUMERATED_TYPE) != null;
+  }
+
+  public XmlElement[] getEnumeratedValues() {
+    XmlEnumeratedType enumeratedType = (XmlEnumeratedType)findElementByTokenType(XML_ENUMERATED_TYPE);
+    if (enumeratedType != null) {
+      return enumeratedType.getEnumeratedValues();
+    }
+    else {
+      return XmlElement.EMPTY_ARRAY;
+    }
+  }
+
+  public boolean isIdAttribute() {
+    final PsiElement elementType = findElementType();
+
+    return elementType != null && elementType.getText().equals(ID_ATT);
+  }
+
+  private PsiElement findElementType() {
+    final PsiElement elementName = findElementByTokenType(XML_NAME);
+    final PsiElement nextSibling = (elementName != null) ? elementName.getNextSibling() : null;
+    final PsiElement elementType = (nextSibling instanceof PsiWhiteSpace) ? nextSibling.getNextSibling() : nextSibling;
+
+    return elementType;
+  }
+
+  public boolean isIdRefAttribute() {
+    final PsiElement elementType = findElementType();
+
+    return elementType != null && elementType.getText().equals(IDREF_ATT);
+  }
+
+  public PsiMetaData getMetaData() {
+    return MetaRegistry.getMeta(this);
+  }
+
+  public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
+    XmlElementChangeUtil.doNameReplacement(this, getNameElement(), name);
+    return null;
+  }
+
+  public String getName() {
+    XmlElement name = getNameElement();
+    return (name != null) ? name.getText() : null;
+  }
+
+  public boolean canNavigate() {
+    if (isPhysical()) return super.canNavigate();
+    final PsiNamedElement psiNamedElement = XmlUtil.findRealNamedElement(this);
+    return psiNamedElement != null && psiNamedElement != this && ((Navigatable)psiNamedElement).canNavigate();
+  }
+
+  public void navigate(final boolean requestFocus) {
+    if (isPhysical()) {
+      super.navigate(requestFocus);
+      return;
+    }
+    final PsiNamedElement psiNamedElement = XmlUtil.findRealNamedElement(this);
+    Navigatable navigatable = EditSourceUtil.getDescriptor(psiNamedElement);
+
+    if (psiNamedElement instanceof XmlEntityDecl) {
+      final OpenFileDescriptor fileDescriptor = (OpenFileDescriptor)navigatable;
+      navigatable = new OpenFileDescriptor(
+        fileDescriptor.getProject(),
+        fileDescriptor.getFile(),
+        psiNamedElement.getTextRange().getStartOffset() + psiNamedElement.getText().indexOf(getName())
+      );
+    }
+    navigatable.navigate(requestFocus);
+  }
+
+  @NotNull
+  public PsiElement getNavigationElement() {
+    return this;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java
new file mode 100644
index 0000000..d3caa29
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.codeInsight.completion.*;
+import com.intellij.codeInsight.daemon.QuickFixProvider;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.NullableLazyValue;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.pom.PomManager;
+import com.intellij.pom.PomModel;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.impl.PomTransactionBase;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl;
+import com.intellij.pom.xml.impl.events.XmlAttributeSetImpl;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.meta.PsiMetaOwner;
+import com.intellij.psi.meta.PsiPresentableMetaData;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.impl.XmlAttributeDescriptorEx;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.xml.util.XmlUtil;
+import gnu.trove.TIntArrayList;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import static com.intellij.codeInsight.completion.CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED;
+
+/**
+ * @author Mike
+ */
+public class XmlAttributeImpl extends XmlElementImpl implements XmlAttribute {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlAttributeImpl");
+
+  private final int myHC = ourHC++;
+
+  @Override
+  public final int hashCode() {
+    return myHC;
+  }
+
+  public XmlAttributeImpl() {
+    super(XmlElementType.XML_ATTRIBUTE);
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    IElementType i = child.getElementType();
+    if (i == XmlTokenType.XML_NAME) {
+      return XmlChildRole.XML_NAME;
+    }
+    else if (i == XmlElementType.XML_ATTRIBUTE_VALUE) {
+      return XmlChildRole.XML_ATTRIBUTE_VALUE;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  public XmlAttributeValue getValueElement() {
+    return (XmlAttributeValue)XmlChildRole.ATTRIBUTE_VALUE_FINDER.findChild(this);
+  }
+
+  public void setValue(String valueText) throws IncorrectOperationException {
+    final ASTNode value = XmlChildRole.ATTRIBUTE_VALUE_FINDER.findChild(this);
+    final PomModel model = PomManager.getModel(getProject());
+    final XmlAttribute attribute = XmlElementFactory.getInstance(getProject()).createXmlAttribute("a", valueText);
+    final ASTNode newValue = XmlChildRole.ATTRIBUTE_VALUE_FINDER.findChild((ASTNode)attribute);
+    final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+    model.runTransaction(new PomTransactionBase(this, aspect) {
+      public PomModelEvent runInner() {
+        final XmlAttributeImpl att = XmlAttributeImpl.this;
+        if (value != null) {
+          if (newValue != null) {
+            att.replaceChild(value, newValue.copyElement());
+          }
+          else {
+            att.removeChild(value);
+          }
+        }
+        else {
+          if (newValue != null) {
+            att.addChild(newValue.copyElement());
+          }
+        }
+        return XmlAttributeSetImpl.createXmlAttributeSet(model, getParent(), getName(), newValue != null ? newValue.getText() : null);
+      }
+    });
+  }
+
+  public XmlElement getNameElement() {
+    return (XmlElement)XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(this);
+  }
+
+  @NotNull
+  public String getNamespace() {
+    final String name = getName();
+    final String prefixByQualifiedName = XmlUtil.findPrefixByQualifiedName(name);
+    // The namespace name for an unprefixed attribute name always has no value. Namespace recommendation section 6.2, third paragraph
+    if (prefixByQualifiedName.length() == 0) return XmlUtil.EMPTY_URI;
+    return getParent().getNamespaceByPrefix(prefixByQualifiedName);
+  }
+
+  @NonNls
+  @NotNull
+  public String getNamespacePrefix() {
+    return XmlUtil.findPrefixByQualifiedName(getName());
+  }
+
+  public XmlTag getParent() {
+    final PsiElement parentTag = super.getParent();
+    return parentTag instanceof XmlTag ? (XmlTag)parentTag : null; // Invalid elements might belong to DummyHolder instead.
+  }
+
+  @NotNull
+  public String getLocalName() {
+    return XmlUtil.findLocalNameByQualifiedName(getName());
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlAttribute(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public String getValue() {
+    final XmlAttributeValue valueElement = getValueElement();
+    return valueElement != null ? valueElement.getValue() : null;
+  }
+
+  private volatile String myDisplayText = null;
+  private volatile int[] myGapDisplayStarts = null;
+  private volatile int[] myGapPhysicalStarts = null;
+  private volatile TextRange myValueTextRange; // text inside quotes, if there are any
+
+  protected void appendChildToDisplayValue(StringBuilder buffer, ASTNode child) {
+    buffer.append(child.getChars());
+  }
+
+  public String getDisplayValue() {
+    String displayText = myDisplayText;
+    if (displayText != null) return displayText;
+    XmlAttributeValue value = getValueElement();
+    if (value == null) return null;
+    PsiElement firstChild = value.getFirstChild();
+    if (firstChild == null) return null;
+    ASTNode child = firstChild.getNode();
+    TextRange valueTextRange = new TextRange(0, value.getTextLength());
+    if (child != null && child.getElementType() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER) {
+      valueTextRange = new TextRange(child.getTextLength(), valueTextRange.getEndOffset());
+      child = child.getTreeNext();
+    }
+    final TIntArrayList gapsStarts = new TIntArrayList();
+    final TIntArrayList gapsShifts = new TIntArrayList();
+    StringBuilder buffer = new StringBuilder(getTextLength());
+    while (child != null) {
+      final int start = buffer.length();
+      IElementType elementType = child.getElementType();
+      if (elementType == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER) {
+        valueTextRange =
+          new TextRange(valueTextRange.getStartOffset(), child.getTextRange().getStartOffset() - value.getTextRange().getStartOffset());
+        break;
+      }
+      if (elementType == XmlTokenType.XML_CHAR_ENTITY_REF) {
+        buffer.append(XmlUtil.getCharFromEntityRef(child.getText()));
+      }
+      else if (elementType == XmlElementType.XML_ENTITY_REF) {
+        buffer.append(XmlUtil.getEntityValue((XmlEntityRef)child));
+      }
+      else {
+        appendChildToDisplayValue(buffer, child);
+      }
+
+      int end = buffer.length();
+      int originalLength = child.getTextLength();
+      if (end - start != originalLength) {
+        gapsStarts.add(start);
+        gapsShifts.add(originalLength - (end - start));
+      }
+      child = child.getTreeNext();
+    }
+    int[] gapDisplayStarts = ArrayUtil.newIntArray(gapsShifts.size());
+    int[] gapPhysicalStarts = ArrayUtil.newIntArray(gapsShifts.size());
+    int currentGapsSum = 0;
+    for (int i = 0; i < gapDisplayStarts.length; i++) {
+      currentGapsSum += gapsShifts.get(i);
+      gapDisplayStarts[i] = gapsStarts.get(i);
+      gapPhysicalStarts[i] = gapDisplayStarts[i] + currentGapsSum;
+    }
+    myGapDisplayStarts = gapDisplayStarts;
+    myGapPhysicalStarts = gapPhysicalStarts;
+    myValueTextRange = valueTextRange;
+    return myDisplayText = buffer.toString();
+  }
+
+  public int physicalToDisplay(int physicalIndex) {
+    getDisplayValue();
+    if (physicalIndex < 0 || physicalIndex > myValueTextRange.getLength()) return -1;
+    if (myGapPhysicalStarts.length == 0) return physicalIndex;
+
+    final int bsResult = Arrays.binarySearch(myGapPhysicalStarts, physicalIndex);
+
+    final int gapIndex;
+    if (bsResult > 0) {
+      gapIndex = bsResult;
+    }
+    else if (bsResult < -1) {
+      gapIndex = -bsResult - 2;
+    }
+    else {
+      gapIndex = -1;
+    }
+
+    if (gapIndex < 0) return physicalIndex;
+    final int shift = myGapPhysicalStarts[gapIndex] - myGapDisplayStarts[gapIndex];
+    return Math.max(myGapDisplayStarts[gapIndex], physicalIndex - shift);
+  }
+
+  public int displayToPhysical(int displayIndex) {
+    String displayValue = getDisplayValue();
+    if (displayValue == null || displayIndex < 0 || displayIndex > displayValue.length()) return -1;
+    if (myGapDisplayStarts.length == 0) return displayIndex;
+
+    final int bsResult = Arrays.binarySearch(myGapDisplayStarts, displayIndex);
+    final int gapIndex;
+
+    if (bsResult > 0) {
+      gapIndex = bsResult - 1;
+    }
+    else if (bsResult < -1) {
+      gapIndex = -bsResult - 2;
+    }
+    else {
+      gapIndex = -1;
+    }
+
+    if (gapIndex < 0) return displayIndex;
+    final int shift = myGapPhysicalStarts[gapIndex] - myGapDisplayStarts[gapIndex];
+    return displayIndex + shift;
+  }
+
+  public TextRange getValueTextRange() {
+    getDisplayValue();
+    return myValueTextRange;
+  }
+
+  public void clearCaches() {
+    super.clearCaches();
+    myDisplayText = null;
+    myGapDisplayStarts = null;
+    myGapPhysicalStarts = null;
+    myValueTextRange = null;
+  }
+
+  @NotNull
+  public String getName() {
+    XmlElement element = getNameElement();
+    return element != null ? element.getText() : "";
+  }
+
+  public boolean isNamespaceDeclaration() {
+    @NonNls final String name = getName();
+    return name.startsWith("xmlns:") || name.equals("xmlns");
+  }
+
+  public PsiElement setName(@NotNull final String nameText) throws IncorrectOperationException {
+    final ASTNode name = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(this);
+    final String oldName = name.getText();
+    final PomModel model = PomManager.getModel(getProject());
+    final XmlAttribute attribute = XmlElementFactory.getInstance(getProject()).createXmlAttribute(nameText, "");
+    final ASTNode newName = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild((ASTNode)attribute);
+    final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+    model.runTransaction(new PomTransactionBase(getParent(), aspect) {
+      public PomModelEvent runInner() {
+        final PomModelEvent event = new PomModelEvent(model);
+        final XmlAspectChangeSetImpl xmlAspectChangeSet = new XmlAspectChangeSetImpl(model, (XmlFile)getContainingFile());
+        xmlAspectChangeSet.add(new XmlAttributeSetImpl(getParent(), oldName, null));
+        xmlAspectChangeSet.add(new XmlAttributeSetImpl(getParent(), nameText, getValue()));
+        event.registerChangeSet(model.getModelAspect(XmlAspect.class), xmlAspectChangeSet);
+        CodeEditUtil.replaceChild(XmlAttributeImpl.this, name, newName);
+        return event;
+      }
+    });
+    return this;
+  }
+
+  public PsiReference getReference() {
+    final PsiReference[] refs = getReferences();
+    if (refs.length > 0) return refs[0];
+    return null;
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    final PsiElement parentElement = getParent();
+    if (!(parentElement instanceof XmlTag)) return PsiReference.EMPTY_ARRAY;
+    final PsiReference[] referencesFromProviders = ReferenceProvidersRegistry.getReferencesFromProviders(this, XmlAttribute.class);
+    if (referencesFromProviders == null) return new PsiReference[]{new MyPsiReference()};
+    PsiReference[] refs;
+    if (isNamespaceDeclaration()) {
+      refs = new PsiReference[referencesFromProviders.length + 1];
+      final String localName = getLocalName();
+      final String prefix = XmlUtil.findPrefixByQualifiedName(getName());
+      final TextRange range =
+        prefix.length() == 0 ? TextRange.from(getName().length(), 0) : TextRange.from(prefix.length() + 1, localName.length());
+      refs[0] = new SchemaPrefixReference(this, range, localName, null);
+    }
+    else {
+      final String prefix = getNamespacePrefix();
+      if (prefix.length() > 0 && getLocalName().length() > 0) {
+        refs = new PsiReference[referencesFromProviders.length + 2];
+        refs[0] = new SchemaPrefixReference(this, TextRange.from(0, prefix.length()), prefix, null);
+        refs[1] = new MyPsiReference();
+      }
+      else {
+        refs = new PsiReference[referencesFromProviders.length + 1];
+        refs[0] = new MyPsiReference();
+      }
+    }
+    System.arraycopy(referencesFromProviders, 0, refs, refs.length - referencesFromProviders.length, referencesFromProviders.length);
+    return refs;
+  }
+
+  @Nullable
+  public XmlAttributeDescriptor getDescriptor() {
+    final PsiElement parentElement = getParent();
+    if (parentElement instanceof XmlDecl) return null;
+    final XmlTag tag = (XmlTag)parentElement;
+    final XmlElementDescriptor descr = tag.getDescriptor();
+    if (descr == null) return null;
+    final XmlAttributeDescriptor attributeDescr = descr.getAttributeDescriptor(this);
+    return attributeDescr == null ? descr.getAttributeDescriptor(getName(), tag) : attributeDescr;
+  }
+
+  private class MyPsiReference implements PsiReference, QuickFixProvider {
+
+    private final NullableLazyValue<XmlAttributeDescriptor> myDescriptor = new NullableLazyValue<XmlAttributeDescriptor>() {
+      protected XmlAttributeDescriptor compute() {
+        XmlTag parent = getParent();
+        final XmlElementDescriptor descr = parent.getDescriptor();
+        if (descr != null) {
+          return descr.getAttributeDescriptor(XmlAttributeImpl.this);
+        }
+        return null;
+      }
+    };
+
+    public PsiElement getElement() {
+      return XmlAttributeImpl.this;
+    }
+
+    public TextRange getRangeInElement() {
+      final int parentOffset = getNameElement().getStartOffsetInParent();
+      int nsLen = getNamespacePrefix().length();
+      nsLen += nsLen > 0 && getRealLocalName().length() > 0 ? 1 : -nsLen;
+      return new TextRange(parentOffset + nsLen, parentOffset + getNameElement().getTextLength());
+    }
+
+    public PsiElement resolve() {
+      final XmlAttributeDescriptor descriptor = getDescriptor();
+      return descriptor != null ? descriptor.getDeclaration() : null;
+    }
+
+    @NotNull
+    public String getCanonicalText() {
+      return getName();
+    }
+
+    public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+      String newName = newElementName;
+      if (getDescriptor() instanceof XmlAttributeDescriptorEx) {
+        final XmlAttributeDescriptorEx xmlAttributeDescriptorEx = (XmlAttributeDescriptorEx)getDescriptor();
+        final String s = xmlAttributeDescriptorEx.handleTargetRename(newElementName);
+        if (s != null) {
+          final String prefix = getNamespacePrefix();
+          newName = StringUtil.isEmpty(prefix) ? s : prefix + ":" + s;
+        }
+      }
+      return setName(newName);
+    }
+
+    // TODO[ik]: namespace support
+
+    public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+      if (element instanceof PsiMetaOwner) {
+        final PsiMetaOwner owner = (PsiMetaOwner)element;
+        if (owner.getMetaData() instanceof XmlElementDescriptor) {
+          setName(owner.getMetaData().getName());
+        }
+      }
+      throw new IncorrectOperationException("Cant bind to not a xml element definition!");
+    }
+
+    public boolean isReferenceTo(PsiElement element) {
+      return getManager().areElementsEquivalent(element, resolve());
+    }
+
+    @NotNull
+    public Object[] getVariants() {
+      final List<LookupElement> variants = new ArrayList<LookupElement>();
+
+      final XmlTag declarationTag = getParent();
+      LOG.assertTrue(declarationTag.isValid());
+      final XmlElementDescriptor parentDescriptor = declarationTag.getDescriptor();
+      if (parentDescriptor != null) {
+        final XmlAttribute[] attributes = declarationTag.getAttributes();
+        XmlAttributeDescriptor[] descriptors = parentDescriptor.getAttributesDescriptors(declarationTag);
+
+        descriptors = HtmlUtil.appendHtmlSpecificAttributeCompletions(declarationTag, descriptors, XmlAttributeImpl.this);
+
+        addVariants(variants, attributes, descriptors);
+      }
+      return variants.toArray();
+    }
+
+    private void addVariants(final Collection<LookupElement> variants,
+                             final XmlAttribute[] attributes,
+                             final XmlAttributeDescriptor[] descriptors) {
+      final XmlTag tag = getParent();
+      final XmlExtension extension = XmlExtension.getExtension(tag.getContainingFile());
+      final String prefix = getName().contains(":") && getRealLocalName().length() > 0 ? getNamespacePrefix() + ":" : null;
+
+      CompletionData completionData = CompletionUtil.getCompletionDataByElement(XmlAttributeImpl.this, getContainingFile().getOriginalFile());
+      boolean caseSensitive = !(completionData instanceof HtmlCompletionData) || ((HtmlCompletionData)completionData).isCaseSensitive();
+
+      for (XmlAttributeDescriptor descriptor : descriptors) {
+        if (isValidVariant(descriptor, attributes, extension)) {
+          String name = descriptor.getName(tag);
+          if (prefix == null || name.startsWith(prefix)) {
+            if (prefix != null && name.length() > prefix.length()) {
+              name = descriptor.getName(tag).substring(prefix.length());
+            }
+            LookupElementBuilder element = LookupElementBuilder.create(name);
+            if (descriptor instanceof PsiPresentableMetaData) {
+              element = element.withIcon(((PsiPresentableMetaData)descriptor).getIcon());
+            }
+            final int separator = name.indexOf(':');
+            if (separator > 0) {
+              element = element.withLookupString(name.substring(separator + 1));
+            }
+            variants.add(element.withCaseSensitivity(caseSensitive).withInsertHandler(XmlAttributeInsertHandler.INSTANCE));
+          }
+        }
+      }
+    }
+
+    private boolean isValidVariant(@NotNull XmlAttributeDescriptor descriptor, final XmlAttribute[] attributes, final XmlExtension extension) {
+      if (extension.isIndirectSyntax(descriptor)) return false;
+      String descriptorName = descriptor.getName();
+      if (descriptorName == null) {
+        LOG.error("Null descriptor name for " + descriptor + " " + descriptor.getClass() + " ");
+        return false;
+      }
+      for (final XmlAttribute attribute : attributes) {
+        if (attribute != XmlAttributeImpl.this && attribute.getName().equals(descriptorName)) return false;
+      }
+      return !descriptorName.contains(DUMMY_IDENTIFIER_TRIMMED);
+    }
+
+    public boolean isSoft() {
+      return getDescriptor() == null;
+    }
+
+    public void registerQuickfix(final HighlightInfo info, final PsiReference reference) {
+      if (getDescriptor() instanceof QuickFixProvider) {
+        ((QuickFixProvider)getDescriptor()).registerQuickfix(info, reference);
+      }
+    }
+
+    @Nullable
+    private XmlAttributeDescriptor getDescriptor() {
+      return myDescriptor.getValue();
+    }
+  }
+
+  private String getRealLocalName() {
+    final String name = getLocalName();
+    return name.endsWith(DUMMY_IDENTIFIER_TRIMMED) ? name.substring(0, name.length() - DUMMY_IDENTIFIER_TRIMMED.length()) : name;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttributeValueImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttributeValueImpl.java
new file mode 100644
index 0000000..eb27880
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlAttributeValueImpl.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.navigation.ItemPresentation;
+import com.intellij.navigation.ItemPresentationWithSeparator;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.CheckUtil;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.impl.source.tree.injected.XmlAttributeLiteralEscaper;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.meta.PsiMetaOwner;
+import com.intellij.psi.presentation.java.SymbolPresentationUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author Mike
+ */
+public class XmlAttributeValueImpl extends XmlElementImpl implements XmlAttributeValue, PsiLanguageInjectionHost, PsiMetaOwner, PsiMetaData {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlAttributeValueImpl");
+  private volatile PsiReference[] myCachedReferences;
+  private volatile long myModCount;
+
+  public XmlAttributeValueImpl() {
+    super(XmlElementType.XML_ATTRIBUTE_VALUE);
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlAttributeValue(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public String getValue() {
+    // it is more correct way to strip quotes since injected xml may have quotes encoded
+    String text = getText();
+    ASTNode startQuote = findChildByType(XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER);
+    if (startQuote != null) {
+      text = StringUtil.trimStart(text, startQuote.getText());
+    }
+    ASTNode endQuote = findChildByType(XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER);
+    if (endQuote != null) {
+      text = StringUtil.trimEnd(text, endQuote.getText());
+    }
+    return text;
+  }
+
+  public TextRange getValueTextRange() {
+    final TextRange range = getTextRange();
+    final String value = getValue();
+    if (value.length() == 0) {
+      return range; 
+    }
+    final int start = range.getStartOffset() + getText().indexOf(value);
+    final int end = start + value.length();
+    return new TextRange(start, end);
+  }
+
+  public void clearCaches() {
+    super.clearCaches();
+    myCachedReferences = null;
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    PsiReference[] cachedReferences = myCachedReferences;
+    final long curModCount = getManager().getModificationTracker().getModificationCount();
+    if (cachedReferences != null && myModCount == curModCount) {
+      return cachedReferences;
+    }
+    cachedReferences = ReferenceProvidersRegistry.getReferencesFromProviders(this, XmlAttributeValue.class);
+    myCachedReferences = cachedReferences;
+    myModCount = curModCount;
+    return cachedReferences;
+  }
+
+  public PsiReference getReference() {
+    final PsiReference[] refs = getReferences();
+    if (refs.length > 0) return refs[0];
+    return null;
+  }
+
+
+  public int getTextOffset() {
+    return getTextRange().getStartOffset() + 1;
+  }
+
+  @Override
+  public boolean isValidHost() {
+    return getParent() instanceof XmlAttributeImpl;
+  }
+
+  public PsiLanguageInjectionHost updateText(@NotNull String text) {
+    try {
+      final String quoteChar = getTextLength() > 0 ? getText().substring(0, 1) : "";
+      String contents = StringUtil.containsAnyChar(quoteChar, "'\"") ?
+              StringUtil.trimEnd(StringUtil.trimStart(text, quoteChar), quoteChar) : text;
+      XmlAttribute newAttribute = XmlElementFactory.getInstance(getProject()).createXmlAttribute("q", contents);
+      XmlAttributeValue newValue = newAttribute.getValueElement();
+
+      CheckUtil.checkWritable(this);
+      replaceAllChildrenToChildrenOf(newValue.getNode());
+    }
+    catch (IncorrectOperationException e) {
+      LOG.error(e);
+    }
+    return this;
+  }
+
+  @NotNull
+  public LiteralTextEscaper<XmlAttributeValueImpl> createLiteralTextEscaper() {
+    return new XmlAttributeLiteralEscaper(this);
+  }
+
+  public PsiMetaData getMetaData() {
+    return this;
+  }
+
+  public PsiElement getDeclaration() {
+    return this;
+  }
+
+  public String getName(final PsiElement context) {
+    return getValue();
+  }
+
+  public String getName() {
+    return getValue();
+  }
+
+  public void init(final PsiElement element) {
+  }
+
+  public Object[] getDependences() {
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
+  }
+
+  @Override
+  public ItemPresentation getPresentation() {
+    return new ItemPresentationWithSeparator() {
+      @Override
+      public String getPresentableText() {
+        return getText();
+      }
+
+      @Override
+      public String getLocationString() {
+        return SymbolPresentationUtil.getFilePathPresentation(getContainingFile());
+      }
+
+      @Override
+      public Icon getIcon(boolean open) {
+        return null;
+      }
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlCommentImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlCommentImpl.java
new file mode 100644
index 0000000..9b3faa5
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlCommentImpl.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.psi.*;
+import com.intellij.psi.impl.meta.MetaRegistry;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.impl.source.tree.injected.XmlCommentLiteralEscaper;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.meta.PsiMetaOwner;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Mike
+ */
+public class XmlCommentImpl extends XmlElementImpl implements XmlComment, XmlElementType, PsiMetaOwner, PsiLanguageInjectionHost {
+  public XmlCommentImpl() {
+    super(XML_COMMENT);
+  }
+
+  public IElementType getTokenType() {
+    return XML_COMMENT;
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlComment(this);
+    }
+    else {
+      visitor.visitComment(this);
+    }
+  }
+
+  @Override
+  public boolean isValidHost() {
+    return true;
+  }
+
+  public XmlTag getParentTag() {
+    if(getParent() instanceof XmlTag) return (XmlTag)getParent();
+    return null;
+  }
+
+  public XmlTagChild getNextSiblingInTag() {
+    if(getParent() instanceof XmlTag) return (XmlTagChild)getNextSibling();
+    return null;
+  }
+
+  public XmlTagChild getPrevSiblingInTag() {
+    if(getParent() instanceof XmlTag) return (XmlTagChild)getPrevSibling();
+    return null;
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    return ReferenceProvidersRegistry.getReferencesFromProviders(this, XmlComment.class);
+  }
+
+  @Nullable
+  public PsiMetaData getMetaData() {
+    return MetaRegistry.getMetaBase(this);
+  }
+
+  public PsiLanguageInjectionHost updateText(@NotNull final String text) {
+    final PsiFile psiFile = getContainingFile();
+
+    final XmlDocument document =
+      ((XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("dummy", psiFile.getFileType(), text)).getDocument();
+    assert document != null;
+
+    final XmlComment comment = PsiTreeUtil.getChildOfType(document, XmlComment.class);
+    
+    assert comment != null;
+    replaceAllChildrenToChildrenOf(comment.getNode());
+
+    return this;
+  }
+
+  @NotNull
+  public LiteralTextEscaper<? extends PsiLanguageInjectionHost> createLiteralTextEscaper() {
+    return new XmlCommentLiteralEscaper(this);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlConditionalSectionImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlConditionalSectionImpl.java
new file mode 100644
index 0000000..426e221
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlConditionalSectionImpl.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.*;
+
+/**
+ * @author maxim.mossienko
+ */
+public class XmlConditionalSectionImpl extends XmlElementImpl implements XmlConditionalSection {
+  public XmlConditionalSectionImpl() {
+    super(XmlElementType.XML_CONDITIONAL_SECTION);
+  }
+
+  public boolean isIncluded(PsiFile targetFile) {
+    ASTNode child = findChildByType(XmlTokenType.XML_CONDITIONAL_SECTION_START);
+
+    if (child != null) {
+      child = child.getTreeNext();
+
+      if (child != null && child.getElementType() == TokenType.WHITE_SPACE) {
+        child = child.getTreeNext();
+      }
+
+      if (child != null) {
+        IElementType elementType = child.getElementType();
+        if (elementType == XmlTokenType.XML_CONDITIONAL_INCLUDE) return true;
+        if (elementType == XmlTokenType.XML_CONDITIONAL_IGNORE) return false;
+
+        if (elementType == XmlElementType.XML_ENTITY_REF) {
+          XmlEntityRef xmlEntityRef = (XmlEntityRef)child.getPsi();
+
+          final String text = xmlEntityRef.getText();
+          String name = text.substring(1,text.length() - 1);
+
+          PsiElement psiElement = targetFile != null ? XmlEntityRefImpl.getCachedEntity( targetFile, name): null;
+
+          if (psiElement instanceof XmlEntityDecl) {
+            final XmlEntityDecl decl = (XmlEntityDecl)psiElement;
+            
+            if(decl.isInternalReference()) {
+              for (ASTNode e = decl.getNode().getFirstChildNode(); e != null; e = e.getTreeNext()) {
+                if (e.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE) {
+                  final boolean b = StringUtil.stripQuotesAroundValue(e.getText()).equals("INCLUDE");
+                  return b;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  public PsiElement getBodyStart() {
+    ASTNode child = findChildByType(XmlTokenType.XML_MARKUP_START);
+    if (child != null) child = child.getTreeNext();
+    if (child != null) return child.getPsi();
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlContentDFA.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlContentDFA.java
new file mode 100644
index 0000000..cf49e5a
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlContentDFA.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public abstract class XmlContentDFA {
+
+  public abstract List<XmlElementDescriptor> getPossibleElements();
+
+  public abstract void transition(XmlTag xmlTag);
+
+  @Nullable
+  public static XmlContentDFA getContentDFA(@NotNull XmlTag parentTag) {
+    XmlContentDFA contentDFA = XsContentDFA.createContentDFA(parentTag);
+    if (contentDFA != null) return contentDFA;
+    return XmlContentDFAImpl.createContentDFA(parentTag);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlContentDFAImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlContentDFAImpl.java
new file mode 100644
index 0000000..3c4b859
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlContentDFAImpl.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+class XmlContentDFAImpl extends XmlContentDFA {
+
+  enum Result {
+    NONE,
+    CONSUME,
+    PROCEED_TO_NEXT
+  }
+
+  private final XmlElementsGroup myGroup;
+  private int myOccurs;
+  private XmlContentDFAImpl myLastChild;
+
+  @Nullable
+  public static XmlContentDFA createContentDFA(XmlTag parentTag) {
+    XmlElementDescriptor descriptor = parentTag.getDescriptor();
+    if (descriptor == null) {
+      return null;
+    }
+    XmlElementsGroup topGroup = descriptor.getTopGroup();
+    if (topGroup == null) {
+      return null;
+    }
+    return new XmlContentDFAImpl(topGroup);
+  }
+
+  private XmlContentDFAImpl(@NotNull XmlElementsGroup group) {
+    myGroup = group;
+  }
+
+  @Override
+  public List<XmlElementDescriptor> getPossibleElements() {
+    ArrayList<XmlElementDescriptor> list = new ArrayList<XmlElementDescriptor>();
+    getPossibleElements(list);
+    return list;
+  }
+
+  private void getPossibleElements(List<XmlElementDescriptor> elements) {
+    switch (myGroup.getGroupType()) {
+      case SEQUENCE:
+        getLastChild();
+        while (myLastChild != null) {
+          myLastChild.getPossibleElements(elements);
+          if (myLastChild.myGroup.getMinOccurs() == 0) {
+            myLastChild = getNextSubGroup();
+          }
+          else return;
+        }
+        break;
+      case CHOICE:
+      case ALL:
+      case GROUP:
+        for (XmlElementsGroup group : myGroup.getSubGroups()) {
+          new XmlContentDFAImpl(group).getPossibleElements(elements);
+        }
+        break;
+      case LEAF:
+        ContainerUtil.addIfNotNull(elements, myGroup.getLeafDescriptor());
+        break;
+    }
+  }
+
+  @Override
+  public void transition(XmlTag xmlTag) {
+    XmlElementDescriptor descriptor = xmlTag.getDescriptor();
+    if (descriptor != null) {
+      doTransition(descriptor);
+    }
+  }
+
+  private Result doTransition(@NotNull XmlElementDescriptor element) {
+    if (myGroup.getGroupType() == XmlElementsGroup.Type.LEAF) {
+      if (element.equals(myGroup.getLeafDescriptor())) {
+        return consume();
+      }
+      else return Result.NONE;
+    }
+    return processSubGroups(element);
+  }
+
+  private Result consume() {
+    return ++myOccurs >= myGroup.getMaxOccurs() ? Result.PROCEED_TO_NEXT : Result.CONSUME;
+  }
+
+  private Result processSubGroups(XmlElementDescriptor element) {
+    getLastChild();
+    while (myLastChild != null) {
+      Result result = myLastChild.doTransition(element);
+      switch (result) {
+        case CONSUME:
+          return Result.CONSUME;
+        case NONE:
+          myLastChild = getNextSubGroup();
+          break;
+        case PROCEED_TO_NEXT:
+          myLastChild = getNextSubGroup();
+          return myLastChild == null ? Result.PROCEED_TO_NEXT : Result.CONSUME;
+      }
+    }
+    return Result.NONE;
+  }
+
+  private void getLastChild() {
+    if (myLastChild == null) {
+      List<XmlElementsGroup> subGroups = myGroup.getSubGroups();
+      if (!subGroups.isEmpty()) {
+        myLastChild = new XmlContentDFAImpl(subGroups.get(0));
+      }
+    }
+  }
+
+  @Nullable
+  private XmlContentDFAImpl getNextSubGroup() {
+    List<XmlElementsGroup> subGroups = myGroup.getSubGroups();
+    int i = subGroups.indexOf(myLastChild.myGroup) + 1;
+    return i == subGroups.size() ? null : new XmlContentDFAImpl(subGroups.get(i));
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlContentParticleImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlContentParticleImpl.java
new file mode 100644
index 0000000..e8e85d9
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlContentParticleImpl.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.DtdReferencesProvider;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlContentParticle;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.xml.XmlElementDescriptor;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlContentParticleImpl implements XmlContentParticle, XmlTokenType {
+
+  private final XmlToken myToken;
+
+  public XmlContentParticleImpl(XmlToken token) {
+    myToken = token;
+  }
+
+  @Override
+  public Type getType() {
+    return Type.ELEMENT;
+  }
+
+  @Override
+  public Quantifier getQuantifier() {
+    return getQuantifierImpl(myToken);
+  }
+
+  public static Quantifier getQuantifierImpl(PsiElement element) {
+    PsiElement nextSibling = element.getNextSibling();
+    while (nextSibling instanceof PsiWhiteSpace) {
+      nextSibling = nextSibling.getNextSibling();
+    }
+
+    if (nextSibling instanceof XmlToken) {
+      IElementType tokenType = ((XmlToken)nextSibling).getTokenType();
+      if (tokenType == XML_PLUS) {
+        return Quantifier.ONE_OR_MORE;
+      }
+      else if (tokenType == XML_STAR) {
+        return Quantifier.ZERO_OR_MORE;
+      }
+      else if (tokenType == XML_QUESTION) {
+        return Quantifier.OPTIONAL;
+      }
+    }
+    return Quantifier.REQUIRED;
+  }
+
+  @Override
+  public XmlContentParticle[] getSubParticles() {
+    return new XmlContentParticle[0];
+  }
+
+  @Override
+  public XmlElementDescriptor getElementDescriptor() {
+    return DtdReferencesProvider.resolveElementReference(myToken.getText(), myToken);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDeclImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDeclImpl.java
new file mode 100644
index 0000000..da165b6
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDeclImpl.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.xml.XmlDecl;
+import com.intellij.psi.xml.XmlElementType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Mike
+ */
+public class XmlDeclImpl extends XmlElementImpl implements XmlDecl{
+  public XmlDeclImpl() {
+    super(XmlElementType.XML_DECL);
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlDecl(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java
new file mode 100644
index 0000000..14d0771
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.injection.InjectedLanguageManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.URLReference;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Mike
+ */
+public class XmlDoctypeImpl extends XmlElementImpl implements XmlDoctype {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlDoctypeImpl");
+
+  public XmlDoctypeImpl() {
+    super(XmlElementType.XML_DOCTYPE);
+  }
+
+  public void clearCaches() {
+    final XmlDocument doc = getContainingDocument();
+    if (doc != null) {
+      final XmlTag rootTag = doc.getRootTag();
+      if (rootTag instanceof TreeElement) {
+        ((TreeElement)rootTag).clearCaches();
+      }
+    }
+    super.clearCaches();
+  }
+
+  private XmlDocument getContainingDocument() {
+    for (PsiElement elem = getParent(); elem != null; elem = elem.getParent()) {
+      if (elem instanceof XmlDocument) {
+        return (XmlDocument)elem;
+      }
+      if (elem instanceof PsiFile) {
+        break; // optimization
+      }
+    }
+    return null;
+  }
+  
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    IElementType i = child.getElementType();
+    if (i == XmlTokenType.XML_DOCTYPE_PUBLIC) {
+      return XmlChildRole.XML_DOCTYPE_PUBLIC;
+    }
+    else if (i == XmlTokenType.XML_DOCTYPE_SYSTEM) {
+      return XmlChildRole.XML_DOCTYPE_SYSTEM;
+    }
+    else if (i == XmlTokenType.XML_NAME) {
+      return XmlChildRole.XML_NAME;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  @Nullable
+  public String getDtdUri() {
+    final PsiElement dtdUrlElement = getDtdUrlElement();
+    if (dtdUrlElement == null || dtdUrlElement.getTextLength() == 0) return null;
+    return extractValue(dtdUrlElement);
+  }
+
+  private static String extractValue(PsiElement element) {
+    String text = element.getText();
+    
+    if (!text.startsWith("\"") && !text.startsWith("\'")) {
+      if (hasInjectedEscapingQuotes(element, text)) return stripInjectedEscapingQuotes(text);
+    }
+    return StringUtil.stripQuotesAroundValue(text);
+  }
+
+  // TODO: share common code
+  private static String stripInjectedEscapingQuotes(String text) {
+    return text.substring(2, text.length() - 2);
+  }
+
+  private static boolean hasInjectedEscapingQuotes(PsiElement element, String text) {
+    if (text.startsWith("\\") && text.length() >= 4) {
+      char escapedChar = text.charAt(1);
+      PsiElement context =
+        InjectedLanguageManager.getInstance(element.getContainingFile().getProject()).getInjectionHost(element.getContainingFile());
+      
+      if (context != null && 
+          context.textContains(escapedChar) && 
+          context.getText().startsWith(String.valueOf(escapedChar)) &&
+          text.endsWith("\\"+escapedChar)
+        ) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Nullable
+  public PsiElement getDtdUrlElement() {
+    PsiElement docTypePublic = findChildByRoleAsPsiElement(XmlChildRole.XML_DOCTYPE_PUBLIC);
+
+    if (docTypePublic != null){
+      PsiElement element = docTypePublic.getNextSibling();
+
+      while(element instanceof PsiWhiteSpace || element instanceof XmlComment){
+        element = element.getNextSibling();
+      }
+
+      //element = element.getNextSibling(); // pass qoutes
+      if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN){
+        element = element.getNextSibling();
+
+        while(element instanceof PsiWhiteSpace || element instanceof XmlComment){
+          element = element.getNextSibling();
+        }
+
+        if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN){
+          return (XmlElement)element;
+        }
+      }
+    }
+
+    PsiElement docTypeSystem = findChildByRoleAsPsiElement(XmlChildRole.XML_DOCTYPE_SYSTEM);
+
+    if (docTypeSystem != null){
+      PsiElement element = docTypeSystem.getNextSibling();
+
+      //element = element.getNextSibling(); // pass qoutes
+      while(element instanceof PsiWhiteSpace || element instanceof XmlComment){
+        element = element.getNextSibling();
+      }
+
+      if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN){
+        return (XmlElement)element;
+      }
+    }
+
+    return null;
+  }
+
+  public XmlElement getNameElement() {
+    return (XmlElement)findChildByRoleAsPsiElement(XmlChildRole.XML_NAME);
+  }
+
+  @Nullable
+  public String getPublicId() {
+    return getSomeId(XmlChildRole.XML_DOCTYPE_PUBLIC);
+  }
+
+  public String getSystemId() {
+    return getSomeId(XmlChildRole.XML_DOCTYPE_SYSTEM);
+  }
+
+  private String getSomeId(final int role) {
+    PsiElement docTypeSystem = findChildByRoleAsPsiElement(role);
+
+    if (docTypeSystem != null) {
+      PsiElement element = docTypeSystem.getNextSibling();
+
+      while (element instanceof PsiWhiteSpace || element instanceof XmlComment) {
+        element = element.getNextSibling();
+      }
+
+      //element = element.getNextSibling(); // pass qoutes
+      if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) {
+        if (element.getTextLength() != 0) {
+          return extractValue(element);
+        }
+      }
+    }
+    return null;
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlDoctype(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public XmlMarkupDecl getMarkupDecl() {
+    for(PsiElement child = getFirstChild(); child != null; child = child.getNextSibling()){
+      if (child instanceof XmlMarkupDecl){
+        return (XmlMarkupDecl)child;
+      }
+    }
+
+    return null;
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    final PsiElement dtdUrlElement = getDtdUrlElement();
+
+    PsiReference uriRef = null;
+    if (dtdUrlElement != null) {
+      uriRef = createUrlReference(dtdUrlElement);
+    }
+
+    final PsiReference[] refs = ReferenceProvidersRegistry.getReferencesFromProviders(this);
+
+    return uriRef == null ? refs : ArrayUtil.mergeArrays(new PsiReference[] {uriRef}, refs);
+  }
+
+  protected PsiReference createUrlReference(final PsiElement dtdUrlElement) {
+    return new URLReference(XmlDoctypeImpl.this) {
+      @NotNull
+      public Object[] getVariants() {
+        return findChildByRoleAsPsiElement(XmlChildRole.XML_DOCTYPE_PUBLIC) != null ?
+               super.getVariants(): EMPTY_ARRAY;
+      }
+      @NotNull
+      public String getCanonicalText() {
+        return extractValue(dtdUrlElement);
+      }
+      public TextRange getRangeInElement() {
+        return TextRange.from(dtdUrlElement.getTextRange().getStartOffset() - getTextRange().getStartOffset() + 1, Math.max(dtdUrlElement.getTextRange().getLength() - 2, 0));
+      }
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDocumentImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDocumentImpl.java
new file mode 100644
index 0000000..c432aab
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDocumentImpl.java
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.javaee.ExternalResourceManagerEx;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.dtd.DTDLanguage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.pom.PomManager;
+import com.intellij.pom.PomModel;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.impl.PomTransactionBase;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.impl.events.XmlDocumentChangedImpl;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiCachedValueImpl;
+import com.intellij.psi.impl.meta.MetaRegistry;
+import com.intellij.psi.impl.source.html.dtd.HtmlNSDescriptorImpl;
+import com.intellij.psi.impl.source.tree.CompositePsiElement;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.meta.PsiMetaOwner;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ConcurrentHashMap;
+import com.intellij.xml.Html5SchemaProvider;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.index.XmlNamespaceIndex;
+import com.intellij.xml.util.XmlNSDescriptorSequence;
+import com.intellij.xml.util.XmlUtil;
+import gnu.trove.TObjectIntHashMap;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Mike
+ */
+public class XmlDocumentImpl extends XmlElementImpl implements XmlDocument {
+
+  private static final Key<Boolean> AUTO_GENERATED = Key.create("auto-generated xml schema");
+
+  public static boolean isAutoGeneratedSchema(XmlFile file) {
+    return file.getUserData(AUTO_GENERATED) != null;
+  }
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlDocumentImpl");
+  private volatile XmlProlog myProlog;
+  private volatile XmlTag myRootTag;
+  private volatile long myExtResourcesModCount = -1;
+
+  public XmlDocumentImpl() {
+    this(XmlElementType.XML_DOCUMENT);
+  }
+
+  protected XmlDocumentImpl(IElementType type) {
+    super(type);
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlDocument(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    IElementType i = child.getElementType();
+    if (i == XmlElementType.XML_PROLOG) {
+      return XmlChildRole.XML_PROLOG;
+    }
+    else if (i == XmlElementType.XML_TAG) {
+      return XmlChildRole.XML_TAG;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  public XmlProlog getProlog() {
+    XmlProlog prolog = myProlog;
+
+    if (prolog == null) {
+      synchronized (PsiLock.LOCK) {
+        prolog = myProlog;
+        if (prolog == null) {
+          prolog = (XmlProlog)findElementByTokenType(XmlElementType.XML_PROLOG);
+          myProlog = prolog;
+        }
+      }
+    }
+
+    return myProlog;
+  }
+
+  public XmlTag getRootTag() {
+    XmlTag rootTag = myRootTag;
+
+    if (rootTag == null) {
+      synchronized (PsiLock.LOCK) {
+        rootTag = myRootTag;
+        if (rootTag == null) {
+          rootTag = (XmlTag)findElementByTokenType(XmlElementType.XML_TAG);
+          myRootTag = rootTag;
+        }
+      }
+    }
+
+    return myRootTag;
+  }
+
+  @SuppressWarnings("ConstantConditions")
+  public XmlNSDescriptor getRootTagNSDescriptor() {
+    XmlTag rootTag = getRootTag();
+    return rootTag != null ? rootTag.getNSDescriptor(rootTag.getNamespace(), false) : null;
+  }
+
+  private ConcurrentHashMap<String, CachedValue<XmlNSDescriptor>> myDefaultDescriptorsCacheStrict = new ConcurrentHashMap<String, CachedValue<XmlNSDescriptor>>();
+  private ConcurrentHashMap<String, CachedValue<XmlNSDescriptor>> myDefaultDescriptorsCacheNotStrict = new ConcurrentHashMap<String, CachedValue<XmlNSDescriptor>>();
+
+  public void clearCaches() {
+    myDefaultDescriptorsCacheStrict.clear();
+    myDefaultDescriptorsCacheNotStrict.clear();
+    myProlog = null;
+    myRootTag = null;
+    super.clearCaches();
+  }
+
+  public XmlNSDescriptor getDefaultNSDescriptor(final String namespace, final boolean strict) {
+    long curExtResourcesModCount = ExternalResourceManagerEx.getInstanceEx().getModificationCount(getProject());
+    if (myExtResourcesModCount != curExtResourcesModCount) {
+      myDefaultDescriptorsCacheNotStrict.clear();
+      myDefaultDescriptorsCacheStrict.clear();
+      myExtResourcesModCount = curExtResourcesModCount;
+    }
+
+    final ConcurrentHashMap<String, CachedValue<XmlNSDescriptor>> defaultDescriptorsCache;
+    if (strict) {
+      defaultDescriptorsCache = myDefaultDescriptorsCacheStrict;
+    }
+    else {
+      defaultDescriptorsCache = myDefaultDescriptorsCacheNotStrict;
+    }
+
+    CachedValue<XmlNSDescriptor> cachedValue = defaultDescriptorsCache.get(namespace);
+    if (cachedValue == null) {
+      defaultDescriptorsCache.put(namespace, cachedValue = new PsiCachedValueImpl<XmlNSDescriptor>(getManager(), new CachedValueProvider<XmlNSDescriptor>() {
+        public Result<XmlNSDescriptor> compute() {
+          final XmlNSDescriptor defaultNSDescriptorInner = getDefaultNSDescriptorInner(namespace, strict);
+
+          if (isGeneratedFromDtd(defaultNSDescriptorInner)) {
+            return new Result<XmlNSDescriptor>(defaultNSDescriptorInner, XmlDocumentImpl.this, ExternalResourceManager.getInstance());
+          }
+
+          return new Result<XmlNSDescriptor>(defaultNSDescriptorInner, defaultNSDescriptorInner != null
+                                                                       ? defaultNSDescriptorInner.getDependences()
+                                                                       : ExternalResourceManager.getInstance());
+        }
+      }));
+    }
+    return cachedValue.getValue();
+  }
+
+  private boolean isGeneratedFromDtd(XmlNSDescriptor defaultNSDescriptorInner) {
+    if (defaultNSDescriptorInner == null) {
+      return false;
+    }
+    XmlFile descriptorFile = defaultNSDescriptorInner.getDescriptorFile();
+    if (descriptorFile == null) {
+        return false;
+    }
+    @NonNls String otherName = XmlUtil.getContainingFile(this).getName() + ".dtd";
+    return descriptorFile.getName().equals(otherName);
+  }
+
+  private XmlNSDescriptor getDefaultNSDescriptorInner(final String namespace, final boolean strict) {
+    final XmlFile containingFile = XmlUtil.getContainingFile(this);
+    if (containingFile == null) return null;
+    final XmlProlog prolog = getProlog();
+    final XmlDoctype doctype = prolog != null ? prolog.getDoctype() : null;
+    boolean dtdUriFromDocTypeIsNamespace = false;
+
+    if (XmlUtil.HTML_URI.equals(namespace)) {
+      XmlNSDescriptor nsDescriptor = doctype != null ? getNsDescriptorFormDocType(doctype, containingFile, true) : null;
+      if (doctype != null) {
+        LOG.debug(
+          "Descriptor from doctype " + doctype + " is " + (nsDescriptor != null ? nsDescriptor.getClass().getCanonicalName() : "NULL"));
+      }
+
+      if (nsDescriptor == null) {
+        String htmlns = ExternalResourceManagerEx.getInstanceEx().getDefaultHtmlDoctype(getProject());
+        if (htmlns == null || htmlns.length() == 0) {
+          htmlns = Html5SchemaProvider.HTML5_SCHEMA_LOCATION;
+        }
+        nsDescriptor = getDefaultNSDescriptor(htmlns, false);
+      }
+      return new HtmlNSDescriptorImpl(nsDescriptor);
+    }
+    else if (XmlUtil.XHTML_URI.equals(namespace)) {
+      String xhtmlNamespace = XmlUtil.getDefaultXhtmlNamespace(getProject());
+      if (xhtmlNamespace == null || xhtmlNamespace.length() == 0) {
+        xhtmlNamespace = Html5SchemaProvider.XHTML5_SCHEMA_LOCATION;
+      }
+      return getDefaultNSDescriptor(xhtmlNamespace, false);
+    }
+    else if (namespace != null && namespace != XmlUtil.EMPTY_URI) {
+      if (doctype == null || !namespace.equals(XmlUtil.getDtdUri(doctype))) {
+        boolean documentIsSchemaThatDefinesNs = namespace.equals(XmlUtil.getTargetSchemaNsFromTag(getRootTag()));
+
+        final XmlFile xmlFile = documentIsSchemaThatDefinesNs
+                                ? containingFile
+                                : XmlUtil.findNamespace(containingFile, namespace);
+        if (xmlFile != null) {
+          final XmlDocument document = xmlFile.getDocument();
+          if (document != null) {
+            return (XmlNSDescriptor)document.getMetaData();
+          }
+        }
+      } else {
+        dtdUriFromDocTypeIsNamespace = true;
+      }
+    }
+
+    if (strict && !dtdUriFromDocTypeIsNamespace) return null;
+
+    if (doctype != null) {
+      XmlNSDescriptor descr = getNsDescriptorFormDocType(doctype, containingFile, false);
+
+      if (descr != null) {
+        return XmlExtension.getExtension(containingFile).getDescriptorFromDoctype(containingFile, descr);
+      }
+    }
+
+    if (strict) return null;
+    if (namespace == XmlUtil.EMPTY_URI) {
+      final XmlFile xmlFile = XmlUtil.findNamespace(containingFile, namespace);
+      if (xmlFile != null) {
+        return (XmlNSDescriptor)xmlFile.getDocument().getMetaData();
+      }
+    }
+    try {
+      final PsiFile fileFromText = PsiFileFactory.getInstance(getProject())
+        .createFileFromText(containingFile.getName() + ".dtd", DTDLanguage.INSTANCE, XmlUtil.generateDocumentDTD(this, false), false, false);
+      if (fileFromText instanceof XmlFile) {
+        fileFromText.putUserData(AUTO_GENERATED, Boolean.TRUE);
+        return (XmlNSDescriptor)((XmlFile)fileFromText).getDocument().getMetaData();
+      }
+    }
+    catch (ProcessCanceledException ex) {
+      throw ex;
+    }
+    catch (RuntimeException ignored) {
+    } // e.g. dtd isn't mapped to xml type
+
+    return null;
+  }
+  
+  @NotNull
+  private static String getFilePathForLogging(@Nullable PsiFile file) {
+    if (file == null) {
+      return "NULL";
+    }
+    final VirtualFile vFile = file.getVirtualFile();
+    return vFile != null ? vFile.getPath() : "NULL_VFILE";
+  }
+
+  @Nullable
+  private XmlNSDescriptor getNsDescriptorFormDocType(final XmlDoctype doctype, final XmlFile containingFile, final boolean forHtml) {
+    XmlNSDescriptor descriptor = getNSDescriptorFromMetaData(doctype.getMarkupDecl(), true);
+
+    final String filePath = getFilePathForLogging(containingFile);
+
+    final String dtdUri = XmlUtil.getDtdUri(doctype);
+    LOG.debug("DTD url for doctype " + doctype.getText() + " in file " + filePath + " is " + dtdUri);
+    
+    if (dtdUri != null && dtdUri.length() > 0){
+      XmlFile xmlFile = XmlUtil.findNamespace(containingFile, dtdUri);
+      if (xmlFile == null) {
+        // try to auto-detect it
+        xmlFile = XmlNamespaceIndex.guessDtd(dtdUri, containingFile);
+      }
+      final String schemaFilePath = getFilePathForLogging(xmlFile);
+      
+      LOG.debug("Schema file for " + filePath + " is " + schemaFilePath);
+      
+      XmlNSDescriptor descriptorFromDtd = getNSDescriptorFromMetaData(xmlFile == null ? null : xmlFile.getDocument(), forHtml);
+
+      LOG.debug("Descriptor from meta data for schema file " +
+                schemaFilePath +
+                " is " +
+                (descriptorFromDtd != null ? descriptorFromDtd.getClass().getCanonicalName() : "NULL"));
+
+      if (descriptor != null && descriptorFromDtd != null){
+        descriptor = new XmlNSDescriptorSequence(new XmlNSDescriptor[]{descriptor, descriptorFromDtd});
+      }
+      else if (descriptorFromDtd != null) {
+        descriptor = descriptorFromDtd;
+      }
+    }
+    return descriptor;
+  }
+
+  @Nullable
+  private XmlNSDescriptor getNSDescriptorFromMetaData(@Nullable PsiMetaOwner metaOwner, boolean nonEmpty) {
+    if (metaOwner == null) return null;
+    XmlNSDescriptor descriptor = (XmlNSDescriptor)metaOwner.getMetaData();
+    if (descriptor == null) return null;
+    if (nonEmpty && descriptor.getRootElementsDescriptors(this).length == 0) {
+      return null;
+    }
+    return descriptor;
+  }
+
+  public CompositePsiElement clone() {
+    HashMap<String, CachedValue<XmlNSDescriptor>> cacheStrict = new HashMap<String, CachedValue<XmlNSDescriptor>>(
+      myDefaultDescriptorsCacheStrict
+    );
+    HashMap<String, CachedValue<XmlNSDescriptor>> cacheNotStrict = new HashMap<String, CachedValue<XmlNSDescriptor>>(
+      myDefaultDescriptorsCacheNotStrict
+    );
+    final XmlDocumentImpl copy = (XmlDocumentImpl) super.clone();
+    updateSelfDependentDtdDescriptors(copy, cacheStrict, cacheNotStrict);
+    return copy;
+  }
+
+  public PsiElement copy() {
+    HashMap<String, CachedValue<XmlNSDescriptor>> cacheStrict = new HashMap<String, CachedValue<XmlNSDescriptor>>(
+      myDefaultDescriptorsCacheStrict
+    );
+    HashMap<String, CachedValue<XmlNSDescriptor>> cacheNotStrict = new HashMap<String, CachedValue<XmlNSDescriptor>>(
+      myDefaultDescriptorsCacheNotStrict
+    );
+    final XmlDocumentImpl copy = (XmlDocumentImpl)super.copy();
+    updateSelfDependentDtdDescriptors(copy, cacheStrict, cacheNotStrict);
+    return copy;
+  }
+
+  private void updateSelfDependentDtdDescriptors(XmlDocumentImpl copy, HashMap<String,
+    CachedValue<XmlNSDescriptor>> cacheStrict, HashMap<String, CachedValue<XmlNSDescriptor>> cacheNotStrict) {
+    copy.myDefaultDescriptorsCacheNotStrict = new ConcurrentHashMap<String, CachedValue<XmlNSDescriptor>>();
+    copy.myDefaultDescriptorsCacheStrict = new ConcurrentHashMap<String, CachedValue<XmlNSDescriptor>>();
+
+    for(Map.Entry<String, CachedValue<XmlNSDescriptor>> e:cacheStrict.entrySet()) {
+      if (e.getValue().hasUpToDateValue()) {
+        final XmlNSDescriptor nsDescriptor = e.getValue().getValue();
+        if (!isGeneratedFromDtd(nsDescriptor)) copy.myDefaultDescriptorsCacheStrict.put(e.getKey(), e.getValue());
+      }
+    }
+
+    for(Map.Entry<String, CachedValue<XmlNSDescriptor>> e:cacheNotStrict.entrySet()) {
+      if (e.getValue().hasUpToDateValue()) {
+        final XmlNSDescriptor nsDescriptor = e.getValue().getValue();
+        if (!isGeneratedFromDtd(nsDescriptor)) copy.myDefaultDescriptorsCacheNotStrict.put(e.getKey(), e.getValue());
+      }
+    }
+  }
+
+  public PsiMetaData getMetaData() {
+    return MetaRegistry.getMeta(this);
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public void dumpStatistics(){
+    System.out.println("Statistics:");
+    final TObjectIntHashMap<Object> map = new TObjectIntHashMap<Object>();
+
+    final PsiElementVisitor psiRecursiveElementVisitor = new XmlRecursiveElementVisitor(){
+      @NonNls private static final String TOKENS_KEY = "Tokens";
+      @NonNls private static final String ELEMENTS_KEY = "Elements";
+
+      @Override public void visitXmlToken(XmlToken token) {
+        inc(TOKENS_KEY);
+      }
+
+      @Override public void visitElement(PsiElement element) {
+        inc(ELEMENTS_KEY);
+        super.visitElement(element);
+      }
+
+      private void inc(final String key) {
+        map.put(key, map.get(key) + 1);
+      }
+    };
+
+    accept(psiRecursiveElementVisitor);
+
+    final Object[] keys = map.keys();
+    for (final Object key : keys) {
+      System.out.println(key + ": " + map.get(key));
+    }
+  }
+
+  public TreeElement addInternal(final TreeElement first, final ASTNode last, final ASTNode anchor, final Boolean before) {
+    final PomModel model = PomManager.getModel(getProject());
+    final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+    final TreeElement[] holder = new TreeElement[1];
+    try{
+      model.runTransaction(new PomTransactionBase(this, aspect) {
+        public PomModelEvent runInner() {
+          holder[0] = XmlDocumentImpl.super.addInternal(first, last, anchor, before);
+          return XmlDocumentChangedImpl.createXmlDocumentChanged(model, XmlDocumentImpl.this);
+        }
+      });
+    }
+    catch(IncorrectOperationException ignored){}
+    return holder[0];
+  }
+
+  public void deleteChildInternal(@NotNull final ASTNode child) {
+    final PomModel model = PomManager.getModel(getProject());
+    final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+    try{
+      model.runTransaction(new PomTransactionBase(this, aspect) {
+        public PomModelEvent runInner() {
+          XmlDocumentImpl.super.deleteChildInternal(child);
+          return XmlDocumentChangedImpl.createXmlDocumentChanged(model, XmlDocumentImpl.this);
+        }
+      });
+    }
+    catch(IncorrectOperationException ignored){}
+  }
+
+  public void replaceChildInternal(@NotNull final ASTNode child, @NotNull final TreeElement newElement) {
+    final PomModel model = PomManager.getModel(getProject());
+    final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+    try{
+      model.runTransaction(new PomTransactionBase(this, aspect) {
+        public PomModelEvent runInner() {
+          XmlDocumentImpl.super.replaceChildInternal(child, newElement);
+          return XmlDocumentChangedImpl.createXmlDocumentChanged(model, XmlDocumentImpl.this);
+        }
+      });
+    }
+    catch(IncorrectOperationException ignored){}
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementChangeUtil.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementChangeUtil.java
new file mode 100644
index 0000000..6a48ffe
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementChangeUtil.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: Maxim.Mossienko
+ * Date: Oct 18, 2006
+ * Time: 3:50:51 PM
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.impl.source.tree.Factory;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.IncorrectOperationException;
+
+public class XmlElementChangeUtil {
+  private XmlElementChangeUtil() {}
+
+  static void doNameReplacement(final PsiNamedElement xmlElementDecl, XmlElement nameElement, final String name) throws
+                                                                                                                 IncorrectOperationException {
+    if (xmlElementDecl.isWritable() && isInProjectContent(xmlElementDecl.getProject(), xmlElementDecl.getContainingFile().getVirtualFile())) {
+
+      if (nameElement!=null) {
+        nameElement.replace(
+          SourceTreeToPsiMap.treeElementToPsi(Factory.createSingleLeafElement(XmlTokenType.XML_NAME, name, null, xmlElementDecl.getManager()))
+        );
+      }
+    }
+  }
+
+  static boolean isInProjectContent(Project project, VirtualFile vfile) {
+    return vfile== null || ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(vfile)!=null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentGroupImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentGroupImpl.java
new file mode 100644
index 0000000..06be625
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentGroupImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlContentParticle;
+import com.intellij.psi.xml.XmlElementContentGroup;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlElementContentGroupImpl  extends XmlElementImpl implements XmlElementContentGroup,
+                                                                           XmlElementType {
+
+  private NotNullLazyValue<XmlContentParticle[]> myParticles = new NotNullLazyValue<XmlContentParticle[]>() {
+    @NotNull
+    @Override
+    protected XmlContentParticle[] compute() {
+      return ContainerUtil.map(getChildren(TokenSet.create(XML_ELEMENT_CONTENT_GROUP, XML_NAME)), new Function<ASTNode, XmlContentParticle>() {
+        @Override
+        public XmlContentParticle fun(ASTNode astNode) {
+          PsiElement element = astNode.getPsi();
+          assert element != null;
+          return element instanceof XmlToken ? new XmlContentParticleImpl((XmlToken)element) : (XmlContentParticle)element;
+        }
+      }, new XmlContentParticle[0]);
+    }
+  };
+
+  public XmlElementContentGroupImpl() {
+    super(XML_ELEMENT_CONTENT_GROUP);
+  }
+
+  @Override
+  public Type getType() {
+    return findElementByTokenType(XML_BAR) == null ? Type.SEQUENCE : Type.CHOICE;
+  }
+
+  @Override
+  public Quantifier getQuantifier() {
+    return XmlContentParticleImpl.getQuantifierImpl(this);
+  }
+
+  @Override
+  public XmlContentParticle[] getSubParticles() {
+    return myParticles.getValue();
+  }
+
+  @Override
+  public XmlElementDescriptor getElementDescriptor() {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentSpecImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentSpecImpl.java
new file mode 100644
index 0000000..c060c43
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentSpecImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlElementContentGroup;
+import com.intellij.psi.xml.XmlElementContentSpec;
+import com.intellij.psi.xml.XmlElementType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Mike
+ */
+public class XmlElementContentSpecImpl extends XmlElementImpl implements XmlElementContentSpec, XmlElementType {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlElementContentSpecImpl");
+
+  public XmlElementContentSpecImpl() {
+    super(XML_ELEMENT_CONTENT_SPEC);
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    IElementType i = child.getElementType();
+    if (i == XML_CONTENT_ANY) {
+      return XmlChildRole.XML_CONTENT_ANY;
+    }
+    else if (i == XML_CONTENT_EMPTY) {
+      return XmlChildRole.XML_CONTENT_EMPTY;
+    }
+    else if (i == XML_PCDATA) {
+      return XmlChildRole.XML_PCDATA;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  public boolean isEmpty() {
+    return findElementByTokenType(XML_CONTENT_EMPTY) != null;
+  }
+
+  public boolean isAny() {
+    return findElementByTokenType(XML_CONTENT_ANY) != null;
+  }
+
+  public boolean isMixed() {
+    XmlElementContentGroup topGroup = getTopGroup();
+    return topGroup != null && ((XmlElementImpl)topGroup).findElementByTokenType(XML_PCDATA) != null;
+  }
+
+  public boolean hasChildren() {
+    return !(isEmpty() || isAny() || isMixed());
+  }
+
+  @Override
+  public XmlElementContentGroup getTopGroup() {
+    return (XmlElementContentGroup)findElementByTokenType(XML_ELEMENT_CONTENT_GROUP);
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    return ReferenceProvidersRegistry.getReferencesFromProviders(this,XmlElementContentSpec.class);
+  }
+
+  public void accept(@NotNull final PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlElement(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementDeclImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementDeclImpl.java
new file mode 100644
index 0000000..2685a8b
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementDeclImpl.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.pom.Navigatable;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.meta.MetaRegistry;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Mike
+ */
+public class XmlElementDeclImpl extends XmlElementImpl implements XmlElementDecl, XmlElementType {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlElementDeclImpl");
+
+  public XmlElementDeclImpl() {
+    super(XML_ELEMENT_DECL);
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    IElementType i = child.getElementType();
+    if (i == XML_NAME) {
+      return XmlChildRole.XML_NAME;
+    }
+    else if (i == XML_ELEMENT_CONTENT_SPEC) {
+      return XmlChildRole.XML_ELEMENT_CONTENT_SPEC;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  public int getTextOffset() {
+    final XmlElement name = getNameElement();
+    return name != null ? name.getTextOffset() : super.getTextOffset();
+  }
+
+  public XmlElement getNameElement() {
+    return (XmlElement)findChildByRoleAsPsiElement(XmlChildRole.XML_NAME);
+  }
+
+  public XmlElementContentSpec getContentSpecElement() {
+    return (XmlElementContentSpec)findChildByRoleAsPsiElement(XmlChildRole.XML_ELEMENT_CONTENT_SPEC);
+  }
+
+  public PsiMetaData getMetaData() {
+    return MetaRegistry.getMeta(this);
+  }
+
+  public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
+    XmlElementChangeUtil.doNameReplacement(this, getNameElement(), name);
+
+    return null;
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    return ReferenceProvidersRegistry.getReferencesFromProviders(this,XmlElementDecl.class);
+  }
+  
+  public PsiElement getOriginalElement() {
+    if (isPhysical()) return super.getOriginalElement();
+
+    final PsiNamedElement element = XmlUtil.findRealNamedElement(this);
+
+    if (element != null) {
+      return element;
+    }
+
+    return this;
+  }
+
+  public boolean canNavigate() {
+    if (!isPhysical()) {
+      return getOriginalElement() != this;
+    }
+
+    return super.canNavigate();
+  }
+
+  public void navigate(boolean requestFocus) {
+    if (!isPhysical()) {
+      PsiElement element = getOriginalElement();
+
+      if (element != this) {
+        ((Navigatable)element).navigate(requestFocus);
+        return;
+      }
+    }
+
+    super.navigate(requestFocus);
+  }
+
+  public String getName() {
+    XmlElement xmlElement = getNameElement();
+    if (xmlElement != null) return xmlElement.getText();
+
+    return getNameFromEntityRef(this, XmlElementType.XML_ELEMENT_DECL_START);
+  }
+
+  @Override
+  public boolean isEquivalentTo(final PsiElement another) {
+    if (!(another instanceof XmlElementDecl)) return false;
+    PsiElement element1 = this;
+    PsiElement element2 = another;
+    if (!element1.isPhysical()) element1 = element1.getOriginalElement();
+    if (!element2.isPhysical()) element2 = element2.getOriginalElement();
+
+    return element1 == element2;
+  }
+
+  public PsiElement getNameIdentifier() {
+    return null;
+  }
+
+  @NotNull
+  public PsiElement getNavigationElement() {
+    return this;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementDescriptorProvider.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementDescriptorProvider.java
new file mode 100644
index 0000000..6940bcf
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementDescriptorProvider.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementDescriptor;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author yole
+ */
+public interface XmlElementDescriptorProvider {
+  ExtensionPointName<XmlElementDescriptorProvider> EP_NAME = ExtensionPointName.create("com.intellij.xml.elementDescriptorProvider");
+
+  @Nullable
+  XmlElementDescriptor getDescriptor(XmlTag tag);
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementImpl.java
new file mode 100644
index 0000000..86b15fb
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementImpl.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: mike
+ * Date: Aug 26, 2002
+ * Time: 6:25:08 PM
+ * To change template for new class use 
+ * Code Style | Class Templates options (Tools | IDE Options).
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.psi.PsiAnchor;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.impl.source.tree.CompositeElement;
+import com.intellij.psi.impl.source.tree.CompositePsiElement;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class XmlElementImpl extends CompositePsiElement implements XmlElement {
+  public XmlElementImpl(IElementType type) {
+    super(type);
+  }
+
+  public boolean processElements(PsiElementProcessor processor, PsiElement place){
+    return XmlUtil.processXmlElements(this, processor, false);
+  }
+
+  public boolean processChildren(PsiElementProcessor processor){
+    return XmlUtil.processXmlElementChildren(this, processor, false);
+  }
+
+  public XmlElement findElementByTokenType(final IElementType type){
+    final XmlElement[] result = new XmlElement[1];
+    result[0] = null;
+
+    processElements(new PsiElementProcessor(){
+      public boolean execute(@NotNull PsiElement element){
+        if(element instanceof TreeElement && ((ASTNode)element).getElementType() == type){
+          result[0] = (XmlElement)element;
+          return false;
+        }
+        return true;
+      }
+    }, this);
+
+    return result[0];
+  }
+
+  public PsiElement getContext() {
+    final XmlElement data = getUserData(INCLUDING_ELEMENT);
+    if(data != null) return data;
+    return getAstParent();
+  }
+
+  private PsiElement getAstParent() {
+    return super.getParent();
+  }
+
+  @Nullable
+  private PsiElement findIncludedRoot() {
+    PsiElement cur = this;
+    while (cur != null && !(cur instanceof PsiFile)) {
+      final PsiElement parent = cur instanceof XmlElementImpl ? ((XmlElementImpl)cur).getAstParent() : cur.getParent();
+      if (parent instanceof PsiFile && cur.getUserData(INCLUDING_ELEMENT) != null) {
+        return cur;
+      }
+
+      cur = parent;
+    }
+    return null;
+  }
+
+  @NotNull
+  public PsiElement getNavigationElement() {
+    if (!isPhysical()) {
+      final PsiElement root = findIncludedRoot();
+      if (root != null) {
+        final PsiAnchor anchor = root.getUserData(XmlUtil.ORIGINAL_ELEMENT);
+        if (anchor != null) {
+          final PsiElement original = anchor.retrieve();
+          if (original != null) {
+            final int endOffset = getTextRange().getEndOffset() + original.getTextRange().getStartOffset();
+
+            PsiElement candidate = original.findElementAt(getTextRange().getStartOffset() - root.getTextRange().getStartOffset());
+            while (candidate != null && candidate.getStartOffsetInParent() == 0 && candidate.getTextRange().getEndOffset() < endOffset) {
+              candidate = candidate.getParent();
+            }
+
+            if (candidate != null && candidate.getTextRange().getEndOffset() == endOffset) {
+              return candidate.getNavigationElement();
+            }
+          }
+        }
+      }
+
+      final XmlElement including = getUserData(INCLUDING_ELEMENT);
+      if (including != null) {
+        return including;
+      }
+      PsiElement astParent = getAstParent();
+      PsiElement parentNavigation = astParent.getNavigationElement();
+      if (parentNavigation.getTextOffset() == getTextOffset()) return parentNavigation;
+      return this;
+    }
+    return super.getNavigationElement();
+  }
+
+  public PsiElement getParent(){
+    return getContext();
+  }
+
+  @NotNull
+  public Language getLanguage() {
+    return getContainingFile().getLanguage();
+  }
+
+  @Nullable
+  protected static String getNameFromEntityRef(final CompositeElement compositeElement, final IElementType xmlEntityDeclStart) {
+    final ASTNode node = compositeElement.findChildByType(xmlEntityDeclStart);
+    if (node == null) return null;
+    ASTNode name = node.getTreeNext();
+
+    if (name != null && name.getElementType() == TokenType.WHITE_SPACE) {
+      name = name.getTreeNext();
+    }
+
+    if (name != null && name.getElementType() == XmlElementType.XML_ENTITY_REF) {
+      final StringBuilder builder = new StringBuilder();
+
+      ((XmlElement)name.getPsi()).processElements(new PsiElementProcessor() {
+        public boolean execute(@NotNull final PsiElement element) {
+          builder.append(element.getText());
+          return true;
+        }
+      }, name.getPsi());
+      if (builder.length() > 0) return builder.toString();
+    }
+    return null;
+  }
+
+  @NotNull
+  public SearchScope getUseScope() {
+    return GlobalSearchScope.allScope(getProject());
+  }
+
+  @Override
+  public boolean isEquivalentTo(final PsiElement another) {
+
+    if (super.isEquivalentTo(another)) return true;
+    PsiElement element1 = this;
+    PsiElement element2 = another;
+
+    // TODO: seem to be only necessary for tag dirs equivalens checking.
+    if (element1 instanceof XmlTag && element2 instanceof XmlTag) {
+      if (!element1.isPhysical() && !element2.isPhysical()) return element1.getText().equals(element2.getText());
+    }
+
+    return false;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java
new file mode 100644
index 0000000..59afb95
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.pom.Navigatable;
+import com.intellij.psi.ElementManipulators;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.impl.source.parsing.xml.DtdParsing;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.URIReferenceProvider;
+import com.intellij.psi.tree.xml.IXmlLeafElementType;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author mike
+ */
+public class XmlEntityDeclImpl extends XmlElementImpl implements XmlEntityDecl, XmlElementType {
+  public XmlEntityDeclImpl() {
+    super(XML_ENTITY_DECL);
+  }
+
+  public PsiElement getNameElement() {
+    for (ASTNode e = getFirstChildNode(); e != null; e = e.getTreeNext()) {
+      if (e instanceof XmlTokenImpl) {
+        XmlTokenImpl xmlToken = (XmlTokenImpl)e;
+
+        if (xmlToken.getTokenType() == XmlTokenType.XML_NAME) return xmlToken;
+      }
+    }
+
+    return null;
+  }
+
+  public XmlAttributeValue getValueElement() {
+    if (isInternalReference()) {
+      for (ASTNode e = getFirstChildNode(); e != null; e = e.getTreeNext()) {
+        if (e.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE) {
+          return (XmlAttributeValue)SourceTreeToPsiMap.treeElementToPsi(e);
+        }
+      }
+    }
+    else {
+      for (ASTNode e = getLastChildNode(); e != null; e = e.getTreePrev()) {
+        if (e.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE) {
+          return (XmlAttributeValue)SourceTreeToPsiMap.treeElementToPsi(e);
+        }
+      }
+    }
+
+    return null;
+  }
+
+  public String getName() {
+    PsiElement nameElement = getNameElement();
+    return nameElement != null ? nameElement.getText() : "";
+  }
+
+  public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
+    final PsiElement nameElement = getNameElement();
+
+    if (nameElement != null) {
+      return ElementManipulators.getManipulator(nameElement).handleContentChange(
+        nameElement,
+        new TextRange(0,nameElement.getTextLength()),
+        name
+      );
+    }
+    return null;
+  }
+
+  public PsiElement parse(PsiFile baseFile, EntityContextType contextType, final XmlEntityRef originalElement) {
+    PsiElement dep = XmlElement.DEPENDING_ELEMENT.get(getParent());
+    PsiElement dependsOnElement = getValueElement(dep instanceof PsiFile ? (PsiFile)dep : baseFile);
+    String value = null;
+    if (dependsOnElement instanceof XmlAttributeValue) {
+      XmlAttributeValue attributeValue = (XmlAttributeValue)dependsOnElement;
+      value = attributeValue.getValue();
+    }
+    else if (dependsOnElement instanceof PsiFile) {
+      PsiFile file = (PsiFile)dependsOnElement;
+      value = file.getText();
+    }
+
+    if (value == null) return null;
+
+    DtdParsing dtdParsing = new DtdParsing(value, XML_ELEMENT_DECL, contextType, baseFile);
+    PsiElement generated = dtdParsing.parse().getPsi().getFirstChild();
+    if (contextType == EntityContextType.ELEMENT_CONTENT_SPEC && generated instanceof XmlElementContentSpec) {
+      generated = generated.getFirstChild();
+    }
+    setDependsOnElement(generated, dependsOnElement);
+    return setOriginalElement(generated, originalElement);
+  }
+
+  private PsiElement setDependsOnElement(PsiElement generated, PsiElement dependsOnElement) {
+    PsiElement e = generated;
+    while (e != null) {
+      e.putUserData(XmlElement.DEPENDING_ELEMENT, dependsOnElement);
+      e = e.getNextSibling();
+    }
+    return generated;
+  }
+
+  private PsiElement setOriginalElement(PsiElement element, PsiElement valueElement) {
+    PsiElement e = element;
+    while (e != null) {
+      e.putUserData(XmlElement.INCLUDING_ELEMENT, (XmlElement)valueElement);
+      e = e.getNextSibling();
+    }
+    return element;
+  }
+
+  @Nullable
+  private PsiElement getValueElement(PsiFile baseFile) {
+    final XmlAttributeValue attributeValue = getValueElement();
+    if (isInternalReference()) return attributeValue;
+
+    if (attributeValue != null) {
+      final String value = attributeValue.getValue();
+      if (value != null) {
+        XmlFile xmlFile = XmlUtil.findNamespaceByLocation(baseFile, value);
+        if (xmlFile != null) {
+          return xmlFile;
+        }
+
+        final int i = URIReferenceProvider.getPrefixLength(value);
+        if (i > 0) {
+          return XmlUtil.findNamespaceByLocation(baseFile, value.substring(i));
+        }
+      }
+    }
+
+    return null;
+  }
+
+  public boolean isInternalReference() {
+    for (ASTNode e = getFirstChildNode(); e != null; e = e.getTreeNext()) {
+      if (e.getElementType() instanceof IXmlLeafElementType) {
+        XmlToken token = (XmlToken)SourceTreeToPsiMap.treeElementToPsi(e);
+        if (token.getTokenType() == XmlTokenType.XML_DOCTYPE_PUBLIC ||
+            token.getTokenType() == XmlTokenType.XML_DOCTYPE_SYSTEM) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  @NotNull
+  public PsiElement getNavigationElement() {
+    return getNameElement();
+  }
+
+  public int getTextOffset() {
+    final PsiElement name = getNameElement();
+    return name != null ? name.getTextOffset() : super.getTextOffset();
+  }
+
+  public boolean canNavigate() {
+    if (isPhysical()) return super.canNavigate();
+    final PsiNamedElement psiNamedElement = XmlUtil.findRealNamedElement(this);
+    return psiNamedElement != null;
+  }
+
+  public void navigate(final boolean requestFocus) {
+    if (!isPhysical()) {
+      ((Navigatable)XmlUtil.findRealNamedElement(this)).navigate(requestFocus);
+      return;
+    }
+    super.navigate(requestFocus);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java
new file mode 100644
index 0000000..45b6526
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author mike
+ */
+public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef {
+  private static final Key<Map<String,CachedValue<XmlEntityDecl>>> XML_ENTITY_DECL_MAP = Key.create("XML_ENTITY_DECL_MAP");
+  @NonNls private static final String GT_ENTITY = "&gt;";
+  @NonNls private static final String QUOT_ENTITY = "&quot;";
+
+  public XmlEntityRefImpl() {
+    super(XmlElementType.XML_ENTITY_REF);
+  }
+
+  private static final Key<String> EVALUATION_IN_PROCESS = Key.create("EvalKey");
+
+  public XmlEntityDecl resolve(PsiFile targetFile) {
+    String text = getText();
+    if (text.equals(GT_ENTITY) || text.equals(QUOT_ENTITY)) return null;
+    return resolveEntity(this, text, targetFile);
+  }
+
+  public static XmlEntityDecl getCachedEntity(PsiFile file, String name) {
+    CachedValue<XmlEntityDecl> cachedValue;
+    synchronized(PsiLock.LOCK) {
+      final Map<String, CachedValue<XmlEntityDecl>> cachingMap = getCachingMap(file);
+      cachedValue = cachingMap.get(name);
+    }
+    return cachedValue != null ? cachedValue.getValue():null;
+  }
+
+  public static void cacheParticularEntity(PsiFile file, XmlEntityDecl decl) {
+    synchronized(PsiLock.LOCK) {
+      final Map<String, CachedValue<XmlEntityDecl>> cachingMap = getCachingMap(file);
+      final String name = decl.getName();
+      if (cachingMap.containsKey(name)) return;
+      final SmartPsiElementPointer declPointer = SmartPointerManager.getInstance(file.getProject()).createSmartPsiElementPointer(decl);
+
+      cachingMap.put(
+        name, CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<XmlEntityDecl>() {
+          public Result<XmlEntityDecl> compute() {
+            PsiElement declElement = declPointer.getElement();
+            if (declElement instanceof XmlEntityDecl && declElement.isValid() && name.equals(((XmlEntityDecl)declElement).getName()))
+              return new Result<XmlEntityDecl>((XmlEntityDecl)declElement, declElement);
+            cachingMap.put(name,null);
+            return new Result<XmlEntityDecl>(null,null);
+          }
+        },
+        false
+      ));
+    }
+  }
+
+  public static XmlEntityDecl resolveEntity(final XmlElement element, final String text, PsiFile targetFile) {
+    if (targetFile instanceof XmlFile) {
+      XmlDocument document = ((XmlFile)targetFile).getDocument();
+      if (document != null && document.getUserData(DISABLE_ENTITY_EXPAND) != null) return null;
+    }
+    
+    final String entityName = text.substring(1, text.length() - 1);
+
+    final PsiElement targetElement = targetFile != null ? targetFile : element;
+    CachedValue<XmlEntityDecl> value;
+    synchronized(PsiLock.LOCK) {
+      Map<String, CachedValue<XmlEntityDecl>> map = getCachingMap(targetElement);
+
+      value = map.get(entityName);
+      final PsiFile containingFile = element.getContainingFile();
+
+      if (value == null) {
+        final PsiManager manager = element.getManager();
+        if(manager == null){
+          return resolveEntity(targetElement, entityName, containingFile).getValue();
+        }
+        value = CachedValuesManager.getManager(manager.getProject()).createCachedValue(new CachedValueProvider<XmlEntityDecl>() {
+          public Result<XmlEntityDecl> compute() {
+            return resolveEntity(targetElement, entityName, containingFile);
+          }
+        });
+
+
+        map.put(entityName, value);
+      }
+    }
+    return value.getValue();
+  }
+
+  private static Map<String, CachedValue<XmlEntityDecl>> getCachingMap(final PsiElement targetElement) {
+    Map<String, CachedValue<XmlEntityDecl>> map = targetElement.getUserData(XML_ENTITY_DECL_MAP);
+    if (map == null){
+      map = new HashMap<String,CachedValue<XmlEntityDecl>>();
+      targetElement.putUserData(XML_ENTITY_DECL_MAP, map);
+    }
+    return map;
+  }
+
+  private static final Key<Boolean> DISABLE_ENTITY_EXPAND = Key.create("disable.entity.expand");
+
+  private static CachedValueProvider.Result<XmlEntityDecl> resolveEntity(final PsiElement targetElement, final String entityName, PsiFile contextFile) {
+    if (targetElement.getUserData(EVALUATION_IN_PROCESS) != null) {
+      return new CachedValueProvider.Result<XmlEntityDecl>(null,targetElement);
+    }
+    try {
+      targetElement.putUserData(EVALUATION_IN_PROCESS, "");
+      final List<PsiElement> deps = new ArrayList<PsiElement>();
+      final XmlEntityDecl[] result = new XmlEntityDecl[]{null};
+
+      PsiElementProcessor processor = new PsiElementProcessor() {
+        public boolean execute(@NotNull PsiElement element) {
+          if (element instanceof XmlDoctype) {
+            XmlDoctype xmlDoctype = (XmlDoctype)element;
+            final String dtdUri = XmlUtil.getDtdUri(xmlDoctype);
+            if (dtdUri != null) {
+              XmlFile file = XmlUtil.getContainingFile(element);
+              if (file == null) return true;
+              final XmlFile xmlFile = XmlUtil.findNamespace(file, dtdUri);
+              if (xmlFile != null) {
+                if (xmlFile != targetElement) {
+                  deps.add(xmlFile);
+                  if(!XmlUtil.processXmlElements(xmlFile, this,true)) return false;
+                }
+              }
+            }
+            final XmlMarkupDecl markupDecl = xmlDoctype.getMarkupDecl();
+            if (markupDecl != null) {
+              if (!XmlUtil.processXmlElements(markupDecl, this, true)) return false;
+            }
+          }
+          else if (element instanceof XmlEntityDecl) {
+            XmlEntityDecl entityDecl = (XmlEntityDecl)element;
+            final String declName = entityDecl.getName();
+            if (declName.equals(entityName)) {
+              result[0] = entityDecl;
+              return false;
+            }
+          }
+
+          return true;
+        }
+      };
+      FileViewProvider provider = targetElement.getContainingFile().getViewProvider();
+      deps.add(provider.getPsi(provider.getBaseLanguage()));
+
+      boolean notfound = PsiTreeUtil.processElements(targetElement, processor);
+      if (notfound) {
+        if (contextFile != targetElement && contextFile != null && contextFile.isValid()) {
+          notfound = PsiTreeUtil.processElements(contextFile, processor);
+        }
+      }
+
+      if (notfound &&       // no dtd ref at all
+          targetElement instanceof XmlFile &&
+          deps.size() == 1 &&
+          ((XmlFile)targetElement).getFileType() != StdFileTypes.DTD
+         ) {
+        XmlDocument document = ((XmlFile)targetElement).getDocument();
+        final XmlTag rootTag = document.getRootTag();
+
+        if (rootTag != null && document.getUserData(DISABLE_ENTITY_EXPAND) == null) {
+          final XmlElementDescriptor descriptor = rootTag.getDescriptor();
+
+            if (descriptor != null && !(descriptor instanceof AnyXmlElementDescriptor)) {
+              PsiElement element = descriptor.getDeclaration();
+              final PsiFile containingFile = element != null ? element.getContainingFile():null;
+              final XmlFile descriptorFile = containingFile instanceof XmlFile ? (XmlFile)containingFile:null;
+
+              if (descriptorFile != null &&
+                  !descriptorFile.getName().equals(((XmlFile)targetElement).getName()+".dtd")) {
+                deps.add(descriptorFile);
+                XmlUtil.processXmlElements(
+                  descriptorFile,
+                  processor,
+                  true
+                );
+              }
+            }
+        }
+      }
+
+      return new CachedValueProvider.Result<XmlEntityDecl>(result[0], ArrayUtil.toObjectArray(deps));
+    }
+    finally {
+      targetElement.putUserData(EVALUATION_IN_PROCESS, null);
+    }
+  }
+
+  public XmlTag getParentTag() {
+    final XmlElement parent = (XmlElement)getParent();
+    if(parent instanceof XmlTag) return (XmlTag)parent;
+    return null;
+  }
+
+  public XmlTagChild getNextSiblingInTag() {
+    PsiElement nextSibling = getNextSibling();
+    if(nextSibling instanceof XmlTagChild) return (XmlTagChild)nextSibling;
+    return null;
+  }
+
+  public XmlTagChild getPrevSiblingInTag() {
+    final PsiElement prevSibling = getPrevSibling();
+    if(prevSibling instanceof XmlTagChild) return (XmlTagChild)prevSibling;
+    return null;
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    return ReferenceProvidersRegistry.getReferencesFromProviders(this,XmlEntityRef.class);
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlElement(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public static void copyEntityCaches(final PsiFile file, final PsiFile context) {
+    synchronized (PsiLock.LOCK) {
+      final Map<String, CachedValue<XmlEntityDecl>> cachingMap = getCachingMap(file);
+      for(Map.Entry<String,CachedValue<XmlEntityDecl>> entry:getCachingMap(context).entrySet()) {
+        cachingMap.put(entry.getKey(), entry.getValue());
+      }
+    }
+
+  }
+
+  public static void setNoEntityExpandOutOfDocument(XmlDocument doc, boolean b) {
+    if (b) doc.putUserData(DISABLE_ENTITY_EXPAND, Boolean.TRUE);
+    else doc.putUserData(DISABLE_ENTITY_EXPAND, null);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEnumeratedTypeImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEnumeratedTypeImpl.java
new file mode 100644
index 0000000..2390f7f
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEnumeratedTypeImpl.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.psi.filters.position.XmlTokenTypeFilter;
+import com.intellij.psi.scope.processor.FilterElementProcessor;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlEnumeratedType;
+import com.intellij.psi.xml.XmlTokenType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author mike
+ */
+public class XmlEnumeratedTypeImpl extends XmlElementImpl implements XmlEnumeratedType, XmlElementType {
+  public XmlEnumeratedTypeImpl() {
+    super(XML_ENUMERATED_TYPE);
+  }
+
+  public XmlElement[] getEnumeratedValues() {
+    final List<XmlElement> result = new ArrayList<XmlElement>();
+    processElements(new FilterElementProcessor(new XmlTokenTypeFilter(XmlTokenType.XML_NAME), result), this);
+    return result.toArray(new XmlElement[result.size()]);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlFileImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlFileImpl.java
new file mode 100644
index 0000000..6c9fd3c
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlFileImpl.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.PsiFileImpl;
+import com.intellij.psi.impl.source.html.ScriptSupportUtil;
+import com.intellij.psi.scope.PsiScopeProcessor;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.ProjectScope;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Mike
+ */
+public class XmlFileImpl extends PsiFileImpl implements XmlFile {
+
+  public XmlFileImpl(FileViewProvider viewProvider, IElementType elementType) {
+    super(elementType, elementType, viewProvider);
+  }
+
+  public XmlDocument getDocument() {
+    PsiElement child = getFirstChild();
+    while (child != null) {
+      if (child instanceof XmlDocument) return (XmlDocument)child;
+      child = child.getNextSibling();
+    }
+
+    return null;
+  }
+
+  @Override
+  public XmlTag getRootTag() {
+    XmlDocument document = getDocument();
+    return document == null ? null : document.getRootTag();
+  }
+
+  public boolean processElements(PsiElementProcessor processor, PsiElement place){
+    final XmlDocument document = getDocument();
+    return document == null || document.processElements(processor, place);
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlFile(this);
+    }
+    else {
+      visitor.visitFile(this);
+    }
+  }
+
+  public String toString() {
+    return "XmlFile:" + getName();
+  }
+
+  private FileType myType = null;
+  @NotNull
+  public FileType getFileType() {
+    if (myType == null) {
+      myType = getLanguage().getAssociatedFileType();
+      if (myType == null) {
+        VirtualFile virtualFile = getOriginalFile().getVirtualFile();
+        myType = virtualFile == null ? FileTypeManager.getInstance().getFileTypeByFileName(getName()) : virtualFile.getFileType();
+      }
+    }
+    return myType;
+  }
+
+  @Override
+  public void clearCaches() {
+    super.clearCaches();
+
+    if (isWebFileType()) {
+      ScriptSupportUtil.clearCaches(this);
+    }
+  }
+
+  private boolean isWebFileType() {
+    return getLanguage() == XHTMLLanguage.INSTANCE || getLanguage() == HTMLLanguage.INSTANCE;
+  }
+
+  public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) {
+    return super.processDeclarations(processor, state, lastParent, place) &&
+           (!isWebFileType() || ScriptSupportUtil.processDeclarations(this, processor, state, lastParent, place));
+
+  }
+
+  public GlobalSearchScope getFileResolveScope() {
+    return ProjectScope.getAllScope(getProject());
+  }
+
+  @Override
+  public boolean ignoreReferencedElementAccessibility() {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlMarkupDeclImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlMarkupDeclImpl.java
new file mode 100644
index 0000000..a022992
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlMarkupDeclImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.psi.impl.meta.MetaRegistry;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlMarkupDecl;
+
+/**
+ * @author Mike
+ */
+public class XmlMarkupDeclImpl extends XmlElementImpl implements XmlMarkupDecl {
+  public XmlMarkupDeclImpl() {
+    super(XmlElementType.XML_MARKUP_DECL);
+  }
+
+  public PsiMetaData getMetaData(){
+    return MetaRegistry.getMeta(this);
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlNotationDeclImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlNotationDeclImpl.java
new file mode 100644
index 0000000..e7e07a2
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlNotationDeclImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.xml.*;
+import com.intellij.psi.tree.ChildRoleBase;
+
+/**
+ * @author Mike
+ */
+public class XmlNotationDeclImpl extends XmlElementImpl implements XmlNotationDecl, XmlElementType {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlElementDeclImpl");
+
+  public XmlNotationDeclImpl() {
+    super(XML_NOTATION_DECL);
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    if (child.getElementType() == XML_ELEMENT_CONTENT_SPEC) {
+      return XmlChildRole.XML_ELEMENT_CONTENT_SPEC;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  public XmlElement getNameElement() {
+    return (XmlElement)findChildByRoleAsPsiElement(XmlChildRole.XML_NAME);
+  }
+
+  public XmlElementContentSpec getContentSpecElement() {
+    return (XmlElementContentSpec)findChildByRoleAsPsiElement(XmlChildRole.XML_ELEMENT_CONTENT_SPEC);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlProcessingInstructionImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlProcessingInstructionImpl.java
new file mode 100644
index 0000000..b8c640d
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlProcessingInstructionImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: mike
+ * Date: Jul 31, 2002
+ * Time: 9:03:01 PM
+ * To change template for new class use 
+ * Code Style | Class Templates options (Tools | IDE Options).
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlProcessingInstruction;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTagChild;
+import org.jetbrains.annotations.NotNull;
+
+public class XmlProcessingInstructionImpl extends XmlElementImpl implements XmlProcessingInstruction {
+  public XmlProcessingInstructionImpl() {
+    super(XmlElementType.XML_PROCESSING_INSTRUCTION);
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlProcessingInstruction(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public XmlTag getParentTag() {
+    final PsiElement parent = getParent();
+    if(parent instanceof XmlTag) return (XmlTag)parent;
+    return null;
+  }
+
+  public XmlTagChild getNextSiblingInTag() {
+    PsiElement nextSibling = getNextSibling();
+    if(nextSibling instanceof XmlTagChild) return (XmlTagChild)nextSibling;
+    return null;
+  }
+
+  public XmlTagChild getPrevSiblingInTag() {
+    final PsiElement prevSibling = getPrevSibling();
+    if(prevSibling instanceof XmlTagChild) return (XmlTagChild)prevSibling;
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlPrologImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlPrologImpl.java
new file mode 100644
index 0000000..88b5349
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlPrologImpl.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlDoctype;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlProlog;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Mike
+ */
+public class XmlPrologImpl extends XmlElementImpl implements XmlProlog, XmlElementType {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlPrologImpl");
+
+  public XmlPrologImpl() {
+    super(XML_PROLOG);
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlProlog(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    if (child.getElementType() == XML_DOCTYPE) {
+      return XmlChildRole.XML_DOCTYPE;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  public XmlDoctype getDoctype() {
+    return (XmlDoctype)findChildByRoleAsPsiElement(XmlChildRole.XML_DOCTYPE);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlPsiPolicy.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlPsiPolicy.java
new file mode 100644
index 0000000..dfe1fd5
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlPsiPolicy.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
+
+public interface XmlPsiPolicy {
+  ASTNode encodeXmlTextContents(String displayText, PsiElement text);
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java
new file mode 100644
index 0000000..e977301
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java
@@ -0,0 +1,1287 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.javaee.ExternalResourceManagerEx;
+import com.intellij.javaee.ImplicitNamespaceDescriptorProvider;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.pom.PomManager;
+import com.intellij.pom.PomModel;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.impl.PomTransactionBase;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.impl.events.XmlAttributeSetImpl;
+import com.intellij.pom.xml.impl.events.XmlTagNameChangedImpl;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.meta.MetaRegistry;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.impl.source.tree.*;
+import com.intellij.psi.impl.source.tree.Factory;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.meta.PsiMetaOwner;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.*;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.CharTable;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.BidirectionalMap;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlExtension;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.impl.dtd.XmlNSDescriptorImpl;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import com.intellij.xml.index.XmlNamespaceIndex;
+import com.intellij.xml.util.XmlTagUtil;
+import com.intellij.xml.util.XmlUtil;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.*;
+
+/**
+ * @author Mike
+ */
+
+public class XmlTagImpl extends XmlElementImpl implements XmlTag {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlTagImpl");
+
+  private volatile String myName = null;
+  private volatile String myLocalName;
+  private volatile XmlAttribute[] myAttributes = null;
+  private volatile Map<String, String> myAttributeValueMap = null;
+  private volatile XmlTagValue myValue = null;
+  private volatile Map<String, CachedValue<XmlNSDescriptor>> myNSDescriptorsMap = null;
+  private volatile String myCachedNamespace;
+  private volatile long myModCount;
+
+  private volatile XmlElementDescriptor myCachedDescriptor;
+  private volatile long myDescriptorModCount = -1;
+  private volatile long myExtResourcesModCount = -1;
+
+  private volatile boolean myHaveNamespaceDeclarations = false;
+  private volatile BidirectionalMap<String, String> myNamespaceMap = null;
+  @NonNls private static final String XML_NS_PREFIX = "xml";
+
+  private final int myHC = ourHC++;
+  private static final RecursionGuard ourGuard = RecursionManager.createGuard("xmlTag");
+
+  private static final Key<ParameterizedCachedValue<XmlTag[], XmlTagImpl>> SUBTAGS_KEY = Key.create("subtags");
+  private static final ParameterizedCachedValueProvider<XmlTag[],XmlTagImpl> CACHED_VALUE_PROVIDER =
+    new ParameterizedCachedValueProvider<XmlTag[], XmlTagImpl>() {
+      @Override
+      public CachedValueProvider.Result<XmlTag[]> compute(XmlTagImpl tag) {
+        final List<XmlTag> result = new ArrayList<XmlTag>();
+
+        tag.fillSubTags(result);
+
+        final int s = result.size();
+        XmlTag[] tags = s > 0 ? ContainerUtil.toArray(result, new XmlTag[s]) : EMPTY;
+        return CachedValueProvider.Result
+          .create(tags, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, tag.getContainingFile());
+      }
+    };
+
+  @Override
+  public final int hashCode() {
+    return myHC;
+  }
+
+  public XmlTagImpl() {
+    this(XmlElementType.XML_TAG);
+  }
+
+  protected XmlTagImpl(IElementType type) {
+    super(type);
+  }
+
+  public void clearCaches() {
+    myName = null;
+    myLocalName = null;
+    myNamespaceMap = null;
+    myCachedNamespace = null;
+    myCachedDescriptor = null;
+    myDescriptorModCount = -1;
+    myAttributes = null;
+    myAttributeValueMap = null;
+    myHaveNamespaceDeclarations = false;
+    myValue = null;
+    myNSDescriptorsMap = null;
+    super.clearCaches();
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    ProgressManager.checkCanceled();
+    final ASTNode startTagName = XmlChildRole.START_TAG_NAME_FINDER.findChild(this);
+    if (startTagName == null) return PsiReference.EMPTY_ARRAY;
+    final ASTNode endTagName = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(this);
+    List<PsiReference> refs = new ArrayList<PsiReference>();
+    String prefix = getNamespacePrefix();
+
+    TagNameReference startTagRef = TagNameReference.createTagNameReference(this, startTagName, true);
+    if (startTagRef != null) {
+      refs.add(startTagRef);
+    }
+    if (prefix.length() > 0) {
+      refs.add(createPrefixReference(startTagName, prefix, startTagRef));
+    }
+    if (endTagName != null) {
+      TagNameReference endTagRef = TagNameReference.createTagNameReference(this, endTagName, false);
+      if (endTagRef != null) {
+        refs.add(endTagRef);
+      }
+      prefix = XmlUtil.findPrefixByQualifiedName(endTagName.getText());
+      if (StringUtil.isNotEmpty(prefix)) {
+        refs.add(createPrefixReference(endTagName, prefix, endTagRef));
+      }
+    }
+
+
+    // ArrayList.addAll() makes a clone of the collection
+    //noinspection ManualArrayToCollectionCopy
+    for (PsiReference ref : ReferenceProvidersRegistry.getReferencesFromProviders(this, XmlTag.class)) {
+      refs.add(ref);
+    }
+
+    return ContainerUtil.toArray(refs, new PsiReference[refs.size()]);
+  }
+
+  private SchemaPrefixReference createPrefixReference(ASTNode startTagName, String prefix, TagNameReference tagRef) {
+    return new SchemaPrefixReference(this, TextRange.from(startTagName.getStartOffset() - getStartOffset(), prefix.length()), prefix, tagRef);
+  }
+
+  public XmlNSDescriptor getNSDescriptor(final String namespace, boolean strict) {
+    final XmlTag parentTag = getParentTag();
+
+    if (parentTag == null && namespace.equals(XmlUtil.XHTML_URI)) {
+      final XmlNSDescriptor descriptor = getDtdDescriptor(XmlUtil.getContainingFile(this));
+      if (descriptor != null) {
+        return descriptor;
+      }
+    }
+
+    Map<String, CachedValue<XmlNSDescriptor>> map = initNSDescriptorsMap();
+    final CachedValue<XmlNSDescriptor> descriptor = map.get(namespace);
+    if (descriptor != null) {
+      final XmlNSDescriptor value = descriptor.getValue();
+      if (value != null) {
+        return value;
+      }
+    }
+
+    if (parentTag == null) {
+      final XmlDocument parentOfType = PsiTreeUtil.getParentOfType(this, XmlDocument.class);
+      if (parentOfType == null) {
+        return null;
+      }
+      return parentOfType.getDefaultNSDescriptor(namespace, strict);
+    }
+
+    return parentTag.getNSDescriptor(namespace, strict);
+  }
+
+  @Nullable
+  private static XmlNSDescriptor getDtdDescriptor(@NotNull XmlFile containingFile) {
+    final XmlDocument document = containingFile.getDocument();
+    if (document == null) {
+      return null;
+    }
+    final String url = XmlUtil.getDtdUri(document);
+    if (url == null) {
+      return null;
+    }
+    return document.getDefaultNSDescriptor(url, true);
+  }
+
+  public boolean isEmpty() {
+    return XmlChildRole.CLOSING_TAG_START_FINDER.findChild(this) == null;
+  }
+
+  public void collapseIfEmpty() {
+    final XmlTag[] tags = getSubTags();
+    if (tags.length > 0) {
+      return;
+    }
+    final ASTNode closingName = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(this);
+    final ASTNode startTagEnd = XmlChildRole.START_TAG_END_FINDER.findChild(this);
+    if (closingName == null || startTagEnd == null) {
+      return;
+    }
+
+    final PomModel pomModel = PomManager.getModel(getProject());
+    final PomTransactionBase transaction = new PomTransactionBase(this, pomModel.getModelAspect(XmlAspect.class)) {
+
+      @Nullable
+      public PomModelEvent runInner() {
+        final ASTNode closingBracket = closingName.getTreeNext();
+        removeRange(startTagEnd, closingBracket);
+        final LeafElement emptyTagEnd = Factory.createSingleLeafElement(XmlTokenType.XML_EMPTY_ELEMENT_END, "/>", 0, 2, null, getManager());
+        replaceChild(closingBracket, emptyTagEnd);
+        return null;
+      }
+    };
+    try {
+      pomModel.runTransaction(transaction);
+    }
+    catch (IncorrectOperationException e) {
+      LOG.error(e);
+    }
+  }
+
+  @Nullable
+  @NonNls
+  public String getSubTagText(@NonNls String qname) {
+    final XmlTag tag = findFirstSubTag(qname);
+    if (tag == null) return null;
+    return tag.getValue().getText();
+  }
+
+  protected final Map<String, CachedValue<XmlNSDescriptor>> initNSDescriptorsMap() {
+    Map<String, CachedValue<XmlNSDescriptor>> map = myNSDescriptorsMap;
+    if (map == null) {
+      RecursionGuard.StackStamp stamp = ourGuard.markStack();
+      map = computeNsDescriptorMap();
+      if (stamp.mayCacheNow()) {
+        myNSDescriptorsMap = map;
+      }
+    }
+    return map;
+  }
+
+  @NotNull
+  private Map<String, CachedValue<XmlNSDescriptor>> computeNsDescriptorMap() {
+    Map<String, CachedValue<XmlNSDescriptor>> map = null;
+    // XSD aware attributes processing
+
+    final String noNamespaceDeclaration = getAttributeValue("noNamespaceSchemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI);
+    final String schemaLocationDeclaration = getAttributeValue("schemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI);
+
+    if (noNamespaceDeclaration != null) {
+      map = initializeSchema(XmlUtil.EMPTY_URI, null, noNamespaceDeclaration, map);
+    }
+    if (schemaLocationDeclaration != null) {
+      final StringTokenizer tokenizer = new StringTokenizer(schemaLocationDeclaration);
+      while (tokenizer.hasMoreTokens()) {
+        final String uri = tokenizer.nextToken();
+        if (tokenizer.hasMoreTokens()) {
+          map = initializeSchema(uri, null, tokenizer.nextToken(), map);
+        }
+      }
+    }
+    // namespace attributes processing (XSD declaration via ExternalResourceManager)
+
+    if (hasNamespaceDeclarations()) {
+      for (final XmlAttribute attribute : getAttributes()) {
+        if (attribute.isNamespaceDeclaration()) {
+          String ns = attribute.getValue();
+          if (ns == null) ns = XmlUtil.EMPTY_URI;
+          ns = getRealNs(ns);
+
+          if (map == null || !map.containsKey(ns)) {
+            map = initializeSchema(ns, getNSVersion(ns, this), getNsLocation(ns), map);
+          }
+        }
+      }
+    }
+    return map == null ? Collections.<String, CachedValue<XmlNSDescriptor>>emptyMap() : map;
+  }
+
+  @Nullable
+  private static String getNSVersion(String ns, final XmlTagImpl xmlTag) {
+    String versionValue = xmlTag.getAttributeValue("version");
+    if (versionValue != null && xmlTag.getNamespace().equals(ns)) {
+      return versionValue;
+    }
+    return null;
+  }
+
+  private Map<String, CachedValue<XmlNSDescriptor>> initializeSchema(final String namespace,
+                                                                     @Nullable final String version,
+                                                                     final String fileLocation,
+                                                                     Map<String, CachedValue<XmlNSDescriptor>> map) {
+    if (map == null) map = new THashMap<String, CachedValue<XmlNSDescriptor>>();
+
+    // We put cached value in any case to cause its value update on e.g. mapping change
+    map.put(namespace, CachedValuesManager.getManager(getManager().getProject()).createCachedValue(new CachedValueProvider<XmlNSDescriptor>() {
+      public Result<XmlNSDescriptor> compute() {
+        XmlNSDescriptor descriptor = getImplicitNamespaceDescriptor(fileLocation);
+        if (descriptor != null) {
+          return new Result<XmlNSDescriptor>(descriptor, ArrayUtil.append(descriptor.getDependences(), XmlTagImpl.this));
+        }
+
+        XmlFile currentFile = retrieveFile(fileLocation, version, namespace);
+        if (currentFile == null) {
+          final XmlDocument document = XmlUtil.getContainingFile(XmlTagImpl.this).getDocument();
+          if (document != null) {
+            final String uri = XmlUtil.getDtdUri(document);
+            if (uri != null) {
+              final XmlFile containingFile = XmlUtil.getContainingFile(document);
+              final XmlFile xmlFile = XmlUtil.findNamespace(containingFile, uri);
+              descriptor = xmlFile == null ? null : (XmlNSDescriptor)xmlFile.getDocument().getMetaData();
+            }
+
+            // We want to get fixed xmlns attr from dtd and check its default with requested namespace
+            if (descriptor instanceof XmlNSDescriptorImpl) {
+              final XmlElementDescriptor elementDescriptor = descriptor.getElementDescriptor(XmlTagImpl.this);
+              if (elementDescriptor != null) {
+                final XmlAttributeDescriptor attributeDescriptor = elementDescriptor.getAttributeDescriptor("xmlns", XmlTagImpl.this);
+                if (attributeDescriptor != null && attributeDescriptor.isFixed()) {
+                  final String defaultValue = attributeDescriptor.getDefaultValue();
+                  if (defaultValue != null && defaultValue.equals(namespace)) {
+                    return new Result<XmlNSDescriptor>(descriptor, descriptor.getDependences(), XmlTagImpl.this,
+                                                       ExternalResourceManager.getInstance());
+                  }
+                }
+              }
+            }
+          }
+        }
+        PsiMetaOwner currentOwner = retrieveOwner(currentFile, namespace);
+        if (currentOwner != null) {
+          descriptor = (XmlNSDescriptor)currentOwner.getMetaData();
+          if (descriptor != null) {
+            return new Result<XmlNSDescriptor>(descriptor, descriptor.getDependences(), XmlTagImpl.this,
+                                               ExternalResourceManager.getInstance());
+          }
+        }
+        return new Result<XmlNSDescriptor>(null, XmlTagImpl.this, currentFile, ExternalResourceManager.getInstance());
+      }
+    }, false));
+
+    return map;
+  }
+
+  @Nullable
+  private XmlNSDescriptor getImplicitNamespaceDescriptor(String ns) {
+    PsiFile file = getContainingFile();
+    if (file == null) return null;
+    Module module = ModuleUtilCore.findModuleForPsiElement(file);
+    if (module != null) {
+      for (ImplicitNamespaceDescriptorProvider provider : Extensions.getExtensions(ImplicitNamespaceDescriptorProvider.EP_NAME)) {
+        XmlNSDescriptor nsDescriptor = provider.getNamespaceDescriptor(module, ns, file);
+        if (nsDescriptor != null) return nsDescriptor;
+      }
+    }
+    return null;
+  }
+
+  @Nullable
+  private XmlFile retrieveFile(final String fileLocation, final String version, String namespace) {
+    final String targetNs = XmlUtil.getTargetSchemaNsFromTag(this);
+    if (fileLocation.equals(targetNs)) {
+      return null;
+    }
+
+    final XmlFile file = XmlUtil.getContainingFile(this);
+    final PsiFile psiFile = ExternalResourceManager.getInstance().getResourceLocation(fileLocation, file, version);
+    if (psiFile instanceof XmlFile) {
+      return (XmlFile)psiFile;
+    }
+
+    return XmlNamespaceIndex.guessSchema(namespace, myLocalName, version, file);
+  }
+
+  @Nullable
+  private PsiMetaOwner retrieveOwner(final XmlFile file, final String namespace) {
+    if (file == null) {
+      return namespace.equals(XmlUtil.getTargetSchemaNsFromTag(this)) ? this : null;
+    }
+    return file.getDocument();
+  }
+
+  public PsiReference getReference() {
+    return ArrayUtil.getFirstElement(getReferences());
+  }
+
+  public XmlElementDescriptor getDescriptor() {
+    final long curModCount = getManager().getModificationTracker().getModificationCount();
+    long curExtResourcesModCount = ExternalResourceManagerEx.getInstanceEx().getModificationCount(getProject());
+    if (myDescriptorModCount != curModCount || myExtResourcesModCount != curExtResourcesModCount) {
+      if (myExtResourcesModCount != curExtResourcesModCount) {
+        myNSDescriptorsMap = null;
+      }
+      RecursionGuard.StackStamp stamp = ourGuard.markStack();
+      XmlElementDescriptor descriptor = computeElementDescriptor();
+      if (!stamp.mayCacheNow()) {
+        return descriptor;
+      }
+
+      myCachedDescriptor = descriptor;
+      myDescriptorModCount = curModCount;
+      myExtResourcesModCount = curExtResourcesModCount;
+    }
+    return myCachedDescriptor;
+  }
+
+  @Nullable
+  protected XmlElementDescriptor computeElementDescriptor() {
+    for (XmlElementDescriptorProvider provider : Extensions.getExtensions(XmlElementDescriptorProvider.EP_NAME)) {
+      XmlElementDescriptor elementDescriptor = provider.getDescriptor(this);
+      if (elementDescriptor != null) {
+        return elementDescriptor;
+      }
+    }
+
+    final String namespace = getNamespace();
+    if (XmlUtil.EMPTY_URI.equals(namespace)) { //nonqualified items
+      final XmlTag parent = getParentTag();
+      if (parent != null) {
+        final XmlElementDescriptor descriptor = parent.getDescriptor();
+        if (descriptor != null) {
+          XmlElementDescriptor fromParent = descriptor.getElementDescriptor(this, parent);
+          if (fromParent != null && !(fromParent instanceof AnyXmlElementDescriptor)) {
+            return fromParent;
+          }
+        }
+      }
+    }
+
+    XmlElementDescriptor elementDescriptor = null;
+    final XmlNSDescriptor nsDescriptor = getNSDescriptor(namespace, false);
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug(
+        "Descriptor for namespace " + namespace + " is " + (nsDescriptor != null ? nsDescriptor.getClass().getCanonicalName() : "NULL"));
+    }
+
+    if (nsDescriptor != null) {
+      if (!DumbService.getInstance(getProject()).isDumb() || DumbService.isDumbAware(nsDescriptor)) {
+        elementDescriptor = nsDescriptor.getElementDescriptor(this);
+      }
+    }
+    if (elementDescriptor == null) {
+      return XmlUtil.findXmlDescriptorByType(this);
+    }
+
+    return elementDescriptor;
+  }
+
+  public int getChildRole(ASTNode child) {
+    LOG.assertTrue(child.getTreeParent() == this);
+    IElementType i = child.getElementType();
+    if (i == XmlTokenType.XML_NAME || i == XmlTokenType.XML_TAG_NAME) {
+      return XmlChildRole.XML_TAG_NAME;
+    }
+    else if (i == XmlElementType.XML_ATTRIBUTE) {
+      return XmlChildRole.XML_ATTRIBUTE;
+    }
+    else {
+      return ChildRoleBase.NONE;
+    }
+  }
+
+  @NotNull
+  public String getName() {
+    String name = myName;
+    if (name == null) {
+      final ASTNode nameElement = XmlChildRole.START_TAG_NAME_FINDER.findChild(this);
+      if (nameElement != null) {
+        name = nameElement.getText();
+      }
+      else {
+        name = "";
+      }
+      myName = name;
+    }
+    return name;
+  }
+
+  public PsiElement setName(@NotNull final String name) throws IncorrectOperationException {
+    final PomModel model = PomManager.getModel(getProject());
+    final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+    model.runTransaction(new PomTransactionBase(this, aspect) {
+      public PomModelEvent runInner() throws IncorrectOperationException {
+        final String oldName = getName();
+        final XmlTagImpl dummyTag =
+          (XmlTagImpl)XmlElementFactory.getInstance(getProject()).createTagFromText(XmlTagUtil.composeTagText(name, "aa"));
+        final XmlTagImpl tag = XmlTagImpl.this;
+        final CharTable charTableByTree = SharedImplUtil.findCharTableByTree(tag);
+        ASTNode child = XmlChildRole.START_TAG_NAME_FINDER.findChild(tag);
+        LOG.assertTrue(child != null, "It seems '" + name + "' is not a valid tag name");
+        TreeElement tagElement = (TreeElement)XmlChildRole.START_TAG_NAME_FINDER.findChild(dummyTag);
+        LOG.assertTrue(tagElement != null, "What's wrong with it? '" + name + "'");
+        tag.replaceChild(child, ChangeUtil.copyElement(tagElement, charTableByTree));
+        final ASTNode childByRole = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(tag);
+        if (childByRole != null) {
+          final TreeElement treeElement = (TreeElement)XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(dummyTag);
+          if (treeElement != null) {
+            tag.replaceChild(childByRole, ChangeUtil.copyElement(treeElement, charTableByTree));
+          }
+        }
+
+        return XmlTagNameChangedImpl.createXmlTagNameChanged(model, tag, oldName);
+      }
+    });
+    return this;
+  }
+
+  @NotNull
+  public XmlAttribute[] getAttributes() {
+    XmlAttribute[] attributes = myAttributes;
+    if (attributes == null) {
+      Map<String, String> attributesValueMap = new THashMap<String, String>();
+      attributes = calculateAttributes(attributesValueMap);
+      myAttributeValueMap = attributesValueMap;
+      myAttributes = attributes;
+    }
+    return attributes;
+  }
+
+  @NotNull
+  private XmlAttribute[] calculateAttributes(final Map<String, String> attributesValueMap) {
+    final List<XmlAttribute> result = new ArrayList<XmlAttribute>(10);
+    processChildren(new PsiElementProcessor() {
+      public boolean execute(@NotNull PsiElement element) {
+        if (element instanceof XmlAttribute) {
+          XmlAttribute attribute = (XmlAttribute)element;
+          result.add(attribute);
+          cacheOneAttributeValue(attribute.getName(), attribute.getValue(), attributesValueMap);
+          myHaveNamespaceDeclarations = myHaveNamespaceDeclarations || attribute.isNamespaceDeclaration();
+        }
+        else if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_TAG_END) {
+          return false;
+        }
+        return true;
+      }
+    });
+    if (result.isEmpty()) {
+      return XmlAttribute.EMPTY_ARRAY;
+    }
+    else {
+      return ContainerUtil.toArray(result, new XmlAttribute[result.size()]);
+    }
+  }
+
+  protected void cacheOneAttributeValue(String name, String value, final Map<String, String> attributesValueMap) {
+    attributesValueMap.put(name, value);
+  }
+
+  public String getAttributeValue(String qname) { //todo ?
+    Map<String, String> map = myAttributeValueMap;
+    while (map == null) {
+      getAttributes();
+      map = myAttributeValueMap;
+
+      if (map == null) {
+        myAttributes = null;
+      }
+    }
+    return map.get(qname);
+  }
+
+  public String getAttributeValue(String _name, String namespace) {
+    if (namespace == null) {
+      return getAttributeValue(_name);
+    }
+
+    XmlTagImpl current = this;
+    PsiElement parent = getParent();
+
+    while (current != null) {
+      BidirectionalMap<String, String> map = current.initNamespaceMaps(parent);
+      if (map != null) {
+        List<String> keysByValue = map.getKeysByValue(namespace);
+        if (keysByValue != null && !keysByValue.isEmpty()) {
+
+          for (String prefix : keysByValue) {
+            if (prefix != null && prefix.length() > 0) {
+              final String value = getAttributeValue(prefix + ":" + _name);
+              if (value != null) return value;
+            }
+          }
+        }
+      }
+
+      current = parent instanceof XmlTag ? (XmlTagImpl)parent : null;
+      parent = parent.getParent();
+    }
+
+    if (namespace.length() == 0 || getNamespace().equals(namespace)) {
+      return getAttributeValue(_name);
+    }
+    return null;
+  }
+
+  @NotNull
+  public XmlTag[] getSubTags() {
+    return CachedValuesManager.getManager(getProject()).getParameterizedCachedValue(this, SUBTAGS_KEY, CACHED_VALUE_PROVIDER, false, this);
+  }
+
+  protected void fillSubTags(final List<XmlTag> result) {
+    processElements(new PsiElementProcessor() {
+      public boolean execute(@NotNull PsiElement element) {
+        if (element instanceof XmlTag) {
+          assert element.isValid();
+          result.add((XmlTag)element);
+        }
+        return true;
+      }
+    }, this);
+  }
+
+  @NotNull
+  public XmlTag[] findSubTags(String name) {
+    return findSubTags(name, null);
+  }
+
+  @NotNull
+  public XmlTag[] findSubTags(final String name, @Nullable final String namespace) {
+    final XmlTag[] subTags = getSubTags();
+    final List<XmlTag> result = new ArrayList<XmlTag>();
+    for (final XmlTag subTag : subTags) {
+      if (namespace == null) {
+        if (name.equals(subTag.getName())) result.add(subTag);
+      }
+      else if (name.equals(subTag.getLocalName()) && namespace.equals(subTag.getNamespace())) {
+        result.add(subTag);
+      }
+    }
+    return ContainerUtil.toArray(result, new XmlTag[result.size()]);
+  }
+
+  public XmlTag findFirstSubTag(String name) {
+    final XmlTag[] subTags = findSubTags(name);
+    if (subTags.length > 0) return subTags[0];
+    return null;
+  }
+
+  public XmlAttribute getAttribute(String name, String namespace) {
+    if (name != null && name.indexOf(':') != -1 ||
+        namespace == null ||
+        XmlUtil.EMPTY_URI.equals(namespace) ||
+        XmlUtil.ANY_URI.equals(namespace)) {
+      return getAttribute(name);
+    }
+
+    final String prefix = getPrefixByNamespace(namespace);
+    if (prefix == null || prefix.length() == 0) return null;
+    return getAttribute(prefix + ":" + name);
+  }
+
+  @Nullable
+  public XmlAttribute getAttribute(String qname) {
+    if (qname == null) return null;
+    final XmlAttribute[] attributes = getAttributes();
+
+    final boolean caseSensitive = isCaseSensitive();
+
+    for (final XmlAttribute attribute : attributes) {
+      final LeafElement attrNameElement = (LeafElement)XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(attribute.getNode());
+      if (attrNameElement != null &&
+          (caseSensitive && Comparing.equal(attrNameElement.getChars(), qname) ||
+           !caseSensitive && Comparing.equal(attrNameElement.getChars(), qname, false))) {
+        return attribute;
+      }
+    }
+    return null;
+  }
+
+  protected boolean isCaseSensitive() {
+    return true;
+  }
+
+  @NotNull
+  public String getNamespace() {
+    String cachedNamespace = myCachedNamespace;
+    final long curModCount = getManager().getModificationTracker().getModificationCount();
+    if (cachedNamespace != null && myModCount == curModCount) {
+      return cachedNamespace;
+    }
+    RecursionGuard.StackStamp stamp = ourGuard.markStack();
+    cachedNamespace = getNamespaceByPrefix(getNamespacePrefix());
+    if (!stamp.mayCacheNow()) {
+      return cachedNamespace;
+    }
+
+    myCachedNamespace = cachedNamespace;
+    myModCount = curModCount;
+    return cachedNamespace;
+  }
+
+  @NotNull
+  public String getNamespacePrefix() {
+    return XmlUtil.findPrefixByQualifiedName(getName());
+  }
+
+  @NotNull
+  public String getNamespaceByPrefix(String prefix) {
+    final PsiElement parent = getParent();
+    if (!parent.isValid()) {
+      LOG.error(this.isValid());
+    }
+    BidirectionalMap<String, String> map = initNamespaceMaps(parent);
+    if (map != null) {
+      final String ns = map.get(prefix);
+      if (ns != null) return ns;
+    }
+    if (parent instanceof XmlTag) return ((XmlTag)parent).getNamespaceByPrefix(prefix);
+    //The prefix 'xml' is by definition bound to the namespace name http://www.w3.org/XML/1998/namespace. It MAY, but need not, be declared
+    if (XML_NS_PREFIX.equals(prefix)) return XmlUtil.XML_NAMESPACE_URI;
+
+    if (prefix.length() > 0 &&
+        !hasNamespaceDeclarations() &&
+        getNamespacePrefix().equals(prefix)) {
+      // When there is no namespace declarations then qualified names should be just used in dtds
+      // this implies that we may have "" namespace prefix ! (see last paragraph in Namespaces in Xml, Section 5)
+
+      String result = ourGuard.doPreventingRecursion("getNsByPrefix", true, new Computable<String>() {
+        @Override
+        public String compute() {
+          final String nsFromEmptyPrefix = getNamespaceByPrefix("");
+          final XmlNSDescriptor nsDescriptor = getNSDescriptor(nsFromEmptyPrefix, false);
+          final XmlElementDescriptor descriptor = nsDescriptor != null ? nsDescriptor.getElementDescriptor(XmlTagImpl.this) : null;
+          final String nameFromRealDescriptor =
+            descriptor != null && descriptor.getDeclaration() != null && descriptor.getDeclaration().isPhysical()
+            ? descriptor.getName()
+            : "";
+          if (nameFromRealDescriptor.equals(getName())) return nsFromEmptyPrefix;
+          return XmlUtil.EMPTY_URI;
+        }
+      });
+      if (result != null) {
+        return result;
+      }
+    }
+    return XmlUtil.EMPTY_URI;
+  }
+
+  public String getPrefixByNamespace(String namespace) {
+    final PsiElement parent = getParent();
+    BidirectionalMap<String, String> map = initNamespaceMaps(parent);
+    if (map != null) {
+      List<String> keysByValue = map.getKeysByValue(namespace);
+      final String ns = keysByValue == null || keysByValue.isEmpty() ? null : keysByValue.get(0);
+      if (ns != null) return ns;
+    }
+    if (parent instanceof XmlTag) return ((XmlTag)parent).getPrefixByNamespace(namespace);
+    //The prefix 'xml' is by definition bound to the namespace name http://www.w3.org/XML/1998/namespace. It MAY, but need not, be declared
+    if (XmlUtil.XML_NAMESPACE_URI.equals(namespace)) return XML_NS_PREFIX;
+    return null;
+  }
+
+  public String[] knownNamespaces() {
+    final PsiElement parentElement = getParent();
+    BidirectionalMap<String, String> map = initNamespaceMaps(parentElement);
+    Set<String> known = Collections.emptySet();
+    if (map != null) {
+      known = new HashSet<String>(map.values());
+    }
+    if (parentElement instanceof XmlTag) {
+      if (known.isEmpty()) return ((XmlTag)parentElement).knownNamespaces();
+      ContainerUtil.addAll(known, ((XmlTag)parentElement).knownNamespaces());
+    }
+    else {
+      XmlExtension xmlExtension = XmlExtension.getExtensionByElement(this);
+      if (xmlExtension != null) {
+        final XmlFile xmlFile = xmlExtension.getContainingFile(this);
+        if (xmlFile != null) {
+          final XmlTag rootTag = xmlFile.getRootTag();
+          if (rootTag != null && rootTag != this) {
+            if (known.isEmpty()) return rootTag.knownNamespaces();
+            ContainerUtil.addAll(known, rootTag.knownNamespaces());
+          }
+        }
+      }
+    }
+    return ArrayUtil.toStringArray(known);
+  }
+
+  @Nullable
+  private BidirectionalMap<String, String> initNamespaceMaps(PsiElement parent) {
+    BidirectionalMap<String, String> map = myNamespaceMap;
+
+    if (map == null) {
+      RecursionGuard.StackStamp stamp = ourGuard.markStack();
+      map = computeNamespaceMap(parent);
+      if (stamp.mayCacheNow()) {
+        myNamespaceMap = map;
+      }
+    }
+
+    return map;
+  }
+
+  @Nullable
+  private BidirectionalMap<String, String> computeNamespaceMap(PsiElement parent) {
+    BidirectionalMap<String, String> map = null;
+    if (hasNamespaceDeclarations()) {
+      map = new BidirectionalMap<String, String>();
+      final XmlAttribute[] attributes = getAttributes();
+
+      for (final XmlAttribute attribute : attributes) {
+        if (attribute.isNamespaceDeclaration()) {
+          final String name = attribute.getName();
+          int splitIndex = name.indexOf(':');
+          final String value = getRealNs(attribute.getValue());
+
+          if (value != null) {
+            if (splitIndex < 0) {
+              map.put("", value);
+            }
+            else {
+              map.put(XmlUtil.findLocalNameByQualifiedName(name), value);
+            }
+          }
+        }
+      }
+    }
+
+    if (parent instanceof XmlDocument) {
+      final XmlExtension extension = XmlExtension.getExtensionByElement(parent);
+      if (extension != null) {
+        final String[][] defaultNamespace = extension.getNamespacesFromDocument((XmlDocument)parent, map != null);
+        if (defaultNamespace != null) {
+          if (map == null) {
+            map = new BidirectionalMap<String, String>();
+          }
+          for (final String[] prefix2ns : defaultNamespace) {
+            map.put(prefix2ns[0], getRealNs(prefix2ns[1]));
+          }
+        }
+      }
+    }
+    return map;
+  }
+
+  private String getNsLocation(String ns) {
+    if (XmlUtil.XHTML_URI.equals(ns)) {
+      return XmlUtil.getDefaultXhtmlNamespace(getProject());
+    }
+    return ns;
+  }
+
+  protected String getRealNs(final String value) {
+    return value;
+  }
+
+  @NotNull
+  public String getLocalName() {
+    String localName = myLocalName;
+    if (localName == null) {
+      final String name = getName();
+      myLocalName = localName = name.substring(name.indexOf(':') + 1);
+    }
+    return localName;
+  }
+
+  public boolean hasNamespaceDeclarations() {
+    getAttributes();
+    return myHaveNamespaceDeclarations;
+  }
+
+  @NotNull
+  public Map<String, String> getLocalNamespaceDeclarations() {
+    Map<String, String> namespaces = new THashMap<String, String>();
+    for (final XmlAttribute attribute : getAttributes()) {
+      if (!attribute.isNamespaceDeclaration() || attribute.getValue() == null) continue;
+      // xmlns -> "", xmlns:a -> a
+      final String localName = attribute.getLocalName();
+      namespaces.put(localName.equals(attribute.getName()) ? "" : localName, attribute.getValue());
+    }
+    return namespaces;
+  }
+
+  public XmlAttribute setAttribute(String qname, String value) throws IncorrectOperationException {
+    final XmlAttribute attribute = getAttribute(qname);
+
+    if (attribute != null) {
+      if (value == null) {
+        deleteChildInternal(attribute.getNode());
+        return null;
+      }
+      attribute.setValue(value);
+      return attribute;
+    }
+    else if (value == null) {
+      return null;
+    }
+    else {
+      PsiElement xmlAttribute = add(XmlElementFactory.getInstance(getProject()).createXmlAttribute(qname, value));
+      while (!(xmlAttribute instanceof XmlAttribute)) xmlAttribute = xmlAttribute.getNextSibling();
+      return (XmlAttribute)xmlAttribute;
+    }
+  }
+
+  public XmlAttribute setAttribute(String name, String namespace, String value) throws IncorrectOperationException {
+    if (!Comparing.equal(namespace, "")) {
+      final String prefix = getPrefixByNamespace(namespace);
+      if (prefix != null && prefix.length() > 0) name = prefix + ":" + name;
+    }
+    return setAttribute(name, value);
+  }
+
+  public XmlTag createChildTag(String localName, String namespace, String bodyText, boolean enforceNamespacesDeep) {
+    return XmlUtil.createChildTag(this, localName, namespace, bodyText, enforceNamespacesDeep);
+  }
+
+  @Override
+  public XmlTag addSubTag(XmlTag subTag, boolean first) {
+    XmlTagChild[] children = getSubTags();
+    if (children.length == 0) {
+      children = getValue().getChildren();
+    }
+    if (children.length == 0) {
+      return (XmlTag)add(subTag);
+    }
+    else if (first) {
+      return (XmlTag)addBefore(subTag, children[0]);
+    }
+    else {
+      return (XmlTag)addAfter(subTag, ArrayUtil.getLastElement(children));
+    }
+  }
+
+  @NotNull
+  public XmlTagValue getValue() {
+    XmlTagValue tagValue = myValue;
+    if (tagValue == null) {
+      myValue = tagValue = XmlTagValueImpl.createXmlTagValue(this);
+    }
+    return tagValue;
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlTag(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public String toString() {
+    return "XmlTag:" + getName();
+  }
+
+  public PsiMetaData getMetaData() {
+    return MetaRegistry.getMeta(this);
+  }
+
+  public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean beforeB) {
+    TreeElement firstAppended = null;
+    boolean before = beforeB == null || beforeB.booleanValue();
+    try {
+      TreeElement next;
+      do {
+        next = first.getTreeNext();
+
+        if (firstAppended == null) {
+          firstAppended = addInternal(first, anchor, before);
+          anchor = firstAppended;
+        }
+        else {
+          anchor = addInternal(first, anchor, false);
+        }
+      }
+      while (first != last && (first = next) != null);
+    }
+    catch (IncorrectOperationException ignored) {
+    }
+    finally {
+      clearCaches();
+    }
+    return firstAppended;
+  }
+
+  private TreeElement addInternal(TreeElement child, ASTNode anchor, boolean before) throws IncorrectOperationException {
+    final PomModel model = PomManager.getModel(getProject());
+    if (anchor != null && child.getElementType() == XmlElementType.XML_TEXT) {
+      XmlText psi = null;
+      if (anchor.getPsi() instanceof XmlText) {
+        psi = (XmlText)anchor.getPsi();
+      }
+      else {
+        final ASTNode other = before ? anchor.getTreePrev() : anchor.getTreeNext();
+        if (other != null && other.getPsi() instanceof XmlText) {
+          before = !before;
+          psi = (XmlText)other.getPsi();
+        }
+      }
+
+      if (psi != null) {
+        if (before) {
+          psi.insertText(((XmlText)child.getPsi()).getValue(), 0);
+        }
+        else {
+          psi.insertText(((XmlText)child.getPsi()).getValue(), psi.getValue().length());
+        }
+        return (TreeElement)psi.getNode();
+      }
+    }
+    LOG.assertTrue(child.getPsi() instanceof XmlAttribute || child.getPsi() instanceof XmlTagChild);
+    final InsertTransaction transaction;
+    if (child.getElementType() == XmlElementType.XML_ATTRIBUTE) {
+      transaction = new InsertAttributeTransaction(child, anchor, before, model);
+    }
+    else if (anchor == null) {
+      transaction = getBodyInsertTransaction(child);
+    }
+    else {
+      transaction = new GenericInsertTransaction(child, anchor, before);
+    }
+    model.runTransaction(transaction);
+    return transaction.getFirstInserted();
+  }
+
+  protected InsertTransaction getBodyInsertTransaction(final TreeElement child) {
+    return new BodyInsertTransaction(child);
+  }
+
+  public void deleteChildInternal(@NotNull final ASTNode child) {
+    final PomModel model = PomManager.getModel(getProject());
+    final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+
+    if (child.getElementType() == XmlElementType.XML_ATTRIBUTE) {
+      try {
+        model.runTransaction(new PomTransactionBase(this, aspect) {
+          public PomModelEvent runInner() {
+            final String name = ((XmlAttribute)child).getName();
+            XmlTagImpl.super.deleteChildInternal(child);
+            return XmlAttributeSetImpl.createXmlAttributeSet(model, XmlTagImpl.this, name, null);
+          }
+        });
+      }
+      catch (IncorrectOperationException e) {
+        LOG.error(e);
+      }
+    }
+    else {
+      final ASTNode treePrev = child.getTreePrev();
+      final ASTNode treeNext = child.getTreeNext();
+      XmlTagImpl.super.deleteChildInternal(child);
+      if (treePrev != null &&
+          treeNext != null &&
+          treePrev.getElementType() == XmlElementType.XML_TEXT &&
+          treeNext.getElementType() == XmlElementType.XML_TEXT) {
+        final XmlText prevText = (XmlText)treePrev.getPsi();
+        final XmlText nextText = (XmlText)treeNext.getPsi();
+        try {
+          prevText.setValue(prevText.getValue() + nextText.getValue());
+          nextText.delete();
+        }
+        catch (IncorrectOperationException e) {
+          LOG.error(e);
+        }
+      }
+    }
+  }
+
+  private ASTNode expandTag() throws IncorrectOperationException {
+    ASTNode endTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(this);
+    if (endTagStart == null) {
+      final XmlTagImpl tagFromText =
+        (XmlTagImpl)XmlElementFactory.getInstance(getProject()).createTagFromText("<" + getName() + "></" + getName() + ">");
+      final ASTNode startTagStart = XmlChildRole.START_TAG_END_FINDER.findChild(tagFromText);
+      endTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(tagFromText);
+      final LeafElement emptyTagEnd = (LeafElement)XmlChildRole.EMPTY_TAG_END_FINDER.findChild(this);
+      if (emptyTagEnd != null) removeChild(emptyTagEnd);
+      addChildren(startTagStart, null, null);
+    }
+    return endTagStart;
+  }
+
+  public XmlTag getParentTag() {
+    final PsiElement parent = getParent();
+    if (parent instanceof XmlTag) return (XmlTag)parent;
+    return null;
+  }
+
+  public XmlTagChild getNextSiblingInTag() {
+    final PsiElement nextSibling = getNextSibling();
+    if (nextSibling instanceof XmlTagChild) return (XmlTagChild)nextSibling;
+    return null;
+  }
+
+  public XmlTagChild getPrevSiblingInTag() {
+    final PsiElement prevSibling = getPrevSibling();
+    if (prevSibling instanceof XmlTagChild) return (XmlTagChild)prevSibling;
+    return null;
+  }
+
+  public Icon getElementIcon(int flags) {
+    return PlatformIcons.XML_TAG_ICON;
+  }
+
+  protected class BodyInsertTransaction extends InsertTransaction {
+    private final TreeElement myChild;
+    private ASTNode myNewElement;
+
+    public BodyInsertTransaction(TreeElement child) {
+      super(XmlTagImpl.this);
+      myChild = child;
+    }
+
+    public PomModelEvent runInner() throws IncorrectOperationException {
+      final ASTNode anchor = expandTag();
+      if (myChild.getElementType() == XmlElementType.XML_TAG) {
+        // compute where to insert tag according to DTD or XSD
+        final XmlElementDescriptor parentDescriptor = getDescriptor();
+        final XmlTag[] subTags = getSubTags();
+        final PsiElement declaration = parentDescriptor != null ? parentDescriptor.getDeclaration() : null;
+        // filtering out generated dtds
+        if (declaration != null &&
+            declaration.getContainingFile() != null &&
+            declaration.getContainingFile().isPhysical() &&
+            subTags.length > 0) {
+          final XmlElementDescriptor[] childElementDescriptors = parentDescriptor.getElementsDescriptors(XmlTagImpl.this);
+          int subTagNum = -1;
+          for (final XmlElementDescriptor childElementDescriptor : childElementDescriptors) {
+            final String childElementName = childElementDescriptor.getName();
+            while (subTagNum < subTags.length - 1 && subTags[subTagNum + 1].getName().equals(childElementName)) {
+              subTagNum++;
+            }
+            if (childElementName.equals(XmlChildRole.START_TAG_NAME_FINDER.findChild(myChild).getText())) {
+              // insert child just after anchor
+              // insert into the position specified by index
+              if (subTagNum >= 0) {
+                final ASTNode subTag = (ASTNode)subTags[subTagNum];
+                if (subTag.getTreeParent() != XmlTagImpl.this) {
+                  // in entity
+                  final XmlEntityRef entityRef = PsiTreeUtil.getParentOfType(subTags[subTagNum], XmlEntityRef.class);
+                  throw new IncorrectOperationException(
+                    "Can't insert subtag to the entity. Entity reference text: " + (entityRef == null ? "" : entityRef.getText()));
+                }
+                myNewElement = XmlTagImpl.super.addInternal(myChild, myChild, subTag, Boolean.FALSE);
+              }
+              else {
+                final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(XmlTagImpl.this);
+                myNewElement = XmlTagImpl.super.addInternal(myChild, myChild, child, Boolean.FALSE);
+              }
+              return null;
+            }
+          }
+        }
+        else {
+          final ASTNode child = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(XmlTagImpl.this);
+          myNewElement = XmlTagImpl.super.addInternal(myChild, myChild, child, Boolean.TRUE);
+          return null;
+        }
+      }
+      myNewElement = XmlTagImpl.super.addInternal(myChild, myChild, anchor, Boolean.TRUE);
+      return null;
+    }
+
+    public TreeElement getFirstInserted() {
+      return (TreeElement)myNewElement;
+    }
+  }
+
+  protected class InsertAttributeTransaction extends InsertTransaction {
+    private final TreeElement myChild;
+    private final ASTNode myAnchor;
+    private final boolean myBefore;
+    private final PomModel myModel;
+    private TreeElement myFirstInserted = null;
+
+    public InsertAttributeTransaction(final TreeElement child, final ASTNode anchor, final boolean before, final PomModel model) {
+      super(XmlTagImpl.this);
+      myChild = child;
+      myAnchor = anchor;
+      myBefore = before;
+      myModel = model;
+    }
+
+    public PomModelEvent runInner() {
+      final String value = ((XmlAttribute)myChild).getValue();
+      final String name = ((XmlAttribute)myChild).getName();
+      if (myAnchor == null) {
+        ASTNode startTagEnd = XmlChildRole.START_TAG_END_FINDER.findChild(XmlTagImpl.this);
+        if (startTagEnd == null) startTagEnd = XmlChildRole.EMPTY_TAG_END_FINDER.findChild(XmlTagImpl.this);
+
+        if (startTagEnd == null) {
+          ASTNode anchor = getLastChildNode();
+
+          while (anchor instanceof PsiWhiteSpace) {
+            anchor = anchor.getTreePrev();
+          }
+
+          if (anchor instanceof PsiErrorElement) {
+            final LeafElement token = Factory
+              .createSingleLeafElement(XmlTokenType.XML_EMPTY_ELEMENT_END, "/>", 0, 2, SharedImplUtil.findCharTableByTree(anchor),
+                                       getManager());
+            replaceChild(anchor, token);
+            startTagEnd = token;
+          }
+        }
+
+        if (startTagEnd == null) {
+          ASTNode anchor = XmlChildRole.START_TAG_NAME_FINDER.findChild(XmlTagImpl.this);
+          myFirstInserted = XmlTagImpl.super.addInternal(myChild, myChild, anchor, Boolean.FALSE);
+        }
+        else {
+          myFirstInserted = XmlTagImpl.super.addInternal(myChild, myChild, startTagEnd, Boolean.TRUE);
+        }
+      }
+      else {
+        myFirstInserted = XmlTagImpl.super.addInternal(myChild, myChild, myAnchor, Boolean.valueOf(myBefore));
+      }
+      return XmlAttributeSetImpl.createXmlAttributeSet(myModel, XmlTagImpl.this, name, value);
+    }
+
+    public TreeElement getFirstInserted() {
+      return myFirstInserted;
+    }
+  }
+
+  protected class GenericInsertTransaction extends InsertTransaction {
+    private final TreeElement myChild;
+    private final ASTNode myAnchor;
+    private final boolean myBefore;
+    private TreeElement myRetHolder;
+
+    public GenericInsertTransaction(final TreeElement child, final ASTNode anchor, final boolean before) {
+      super(XmlTagImpl.this);
+      myChild = child;
+      myAnchor = anchor;
+      myBefore = before;
+    }
+
+    public PomModelEvent runInner() {
+      myRetHolder = XmlTagImpl.super.addInternal(myChild, myChild, myAnchor, Boolean.valueOf(myBefore));
+      return null;
+    }
+
+    public TreeElement getFirstInserted() {
+      return myRetHolder;
+    }
+  }
+
+  protected abstract class InsertTransaction extends PomTransactionBase {
+    public InsertTransaction(final PsiElement scope) {
+      super(scope, PomManager.getModel(getProject()).getModelAspect(XmlAspect.class));
+    }
+
+    public abstract TreeElement getFirstInserted();
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagValueImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagValueImpl.java
new file mode 100644
index 0000000..887cce5
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagValueImpl.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class XmlTagValueImpl implements XmlTagValue{
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlTagValueImpl");
+
+  private final XmlTag myTag;
+  private final XmlTagChild[] myElements;
+  private volatile XmlText[] myTextElements = null;
+  private volatile String myText = null;
+  private volatile String myTrimmedText = null;
+
+  public XmlTagValueImpl(@NotNull XmlTagChild[] bodyElements, @NotNull XmlTag tag) {
+    myTag = tag;
+    myElements = bodyElements;
+  }
+
+  @NotNull
+  public XmlTagChild[] getChildren() {
+    return myElements;
+  }
+
+  @NotNull
+  public XmlText[] getTextElements() {
+    XmlText[] textElements = myTextElements;
+    if(textElements != null) return textElements;
+    final List<XmlText> textElementsList = new ArrayList<XmlText>();
+    for (final XmlTagChild element : myElements) {
+      if (element instanceof XmlText) textElementsList.add((XmlText)element);
+    }
+    return myTextElements = textElementsList.isEmpty() ? XmlText.EMPTY_ARRAY : ContainerUtil.toArray(textElementsList, new XmlText[textElementsList.size()]);
+  }
+
+  @NotNull
+  public String getText() {
+    String text = myText;
+    if(text != null) return text;
+    final StringBuilder consolidatedText = new StringBuilder();
+    for (final XmlTagChild element : myElements) {
+      consolidatedText.append(element.getText());
+    }
+    return myText = consolidatedText.toString();
+  }
+
+  @NotNull
+  public TextRange getTextRange() {
+    if(myElements.length == 0){
+      final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild( (ASTNode)myTag);
+      if(child != null)
+        return new TextRange(child.getStartOffset() + 1, child.getStartOffset() + 1);
+      return new TextRange(myTag.getTextRange().getEndOffset(), myTag.getTextRange().getEndOffset());
+    }
+    return new TextRange(myElements[0].getTextRange().getStartOffset(), myElements[myElements.length - 1].getTextRange().getEndOffset());
+  }
+
+  @NotNull
+  public String getTrimmedText() {
+    String trimmedText = myTrimmedText;
+    if(trimmedText != null) return trimmedText;
+
+    final StringBuilder consolidatedText = new StringBuilder();
+    final XmlText[] textElements = getTextElements();
+    for (final XmlText textElement : textElements) {
+      consolidatedText.append(textElement.getValue());
+    }
+    return myTrimmedText = consolidatedText.toString().trim();
+  }
+
+  public void setText(String value) {
+    try {
+      XmlText text = null;
+      if (value != null) {
+        final XmlText[] texts = getTextElements();
+        if (texts.length == 0) {
+          text = (XmlText)myTag.add(XmlElementFactory.getInstance(myTag.getProject()).createDisplayText("x"));
+        } else {
+          text = texts[0];
+        }
+        if (StringUtil.isEmpty(value)) {
+          text.delete();
+        }
+        else {
+          text.setValue(value);
+        }
+      }
+
+      if(myElements.length > 0){
+        for (final XmlTagChild child : myElements) {
+          if (child != text) {
+            child.delete();
+          }
+        }
+      }
+    }
+    catch (IncorrectOperationException e) {
+      LOG.error(e);
+    }
+  }
+
+  @Override
+  public boolean hasCDATA() {
+    for (XmlText xmlText : myTextElements) {
+      PsiElement[] children = xmlText.getChildren();
+      for (PsiElement child : children) {
+        if (child.getNode().getElementType() == XmlElementType.XML_CDATA) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  public static XmlTagValue createXmlTagValue(XmlTag tag) {
+    final List<XmlTagChild> bodyElements = new ArrayList<XmlTagChild>();
+
+    tag.processElements(new PsiElementProcessor() {
+      boolean insideBody = false;
+      public boolean execute(@NotNull PsiElement element) {
+        final ASTNode treeElement = element.getNode();
+        if (insideBody) {
+          if (treeElement != null && treeElement.getElementType() == XmlTokenType.XML_END_TAG_START) return false;
+          if (!(element instanceof XmlTagChild)) return true;
+          bodyElements.add((XmlTagChild)element);
+        }
+        else if (treeElement != null && treeElement.getElementType() == XmlTokenType.XML_TAG_END) insideBody = true;
+        return true;
+      }
+    }, tag);
+
+    XmlTagChild[] tagChildren = ContainerUtil.toArray(bodyElements, new XmlTagChild[bodyElements.size()]);
+    return new XmlTagValueImpl(tagChildren, tag);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java
new file mode 100644
index 0000000..b33ae84
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java
@@ -0,0 +1,528 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.lang.ASTFactory;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.injection.InjectedLanguageManager;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.pom.PomManager;
+import com.intellij.pom.PomModel;
+import com.intellij.pom.event.PomModelEvent;
+import com.intellij.pom.impl.PomTransactionBase;
+import com.intellij.pom.xml.XmlAspect;
+import com.intellij.pom.xml.events.XmlChange;
+import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl;
+import com.intellij.pom.xml.impl.events.XmlTagChildAddImpl;
+import com.intellij.pom.xml.impl.events.XmlTextChangedImpl;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.DummyHolderFactory;
+import com.intellij.psi.impl.source.PsiFileImpl;
+import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
+import com.intellij.psi.impl.source.tree.FileElement;
+import com.intellij.psi.impl.source.tree.LeafElement;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.psi.impl.source.tree.injected.XmlTextLiteralEscaper;
+import com.intellij.psi.impl.source.xml.behavior.DefaultXmlPsiPolicy;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.util.XmlUtil;
+import gnu.trove.TIntArrayList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class XmlTextImpl extends XmlElementImpl implements XmlText, PsiLanguageInjectionHost {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlTextImpl");
+  private volatile String myDisplayText = null;
+  private volatile int[] myGapDisplayStarts = null;
+  private volatile int[] myGapPhysicalStarts = null;
+
+  public XmlTextImpl() {
+    super(XmlElementType.XML_TEXT);
+  }
+
+  public String toString() {
+    return "XmlText";
+  }
+
+  @Override
+  public boolean isValidHost() {
+    return true;
+  }
+
+  @Nullable
+  public XmlText split(int displayIndex) {
+    try {
+      return _splitText(displayIndex);
+    }
+    catch (IncorrectOperationException e) {
+      throw new IllegalArgumentException(e);
+    }
+  }
+
+  public String getValue() {
+    String displayText = myDisplayText;
+    if (displayText != null) return displayText;
+    StringBuilder buffer = new StringBuilder();
+    ASTNode child = getFirstChildNode();
+    final TIntArrayList gapsStarts = new TIntArrayList();
+    final TIntArrayList gapsShifts = new TIntArrayList();
+    while (child != null) {
+      final int start = buffer.length();
+      IElementType elementType = child.getElementType();
+      if (elementType == XmlElementType.XML_CDATA) {
+        final ASTNode cdata = child;
+        child = cdata.getFirstChildNode();
+      }
+      else if (elementType == XmlTokenType.XML_CHAR_ENTITY_REF) {
+        String text = child.getText();
+        LOG.assertTrue(text != null, child);
+        buffer.append(XmlUtil.getCharFromEntityRef(text));
+      }
+      else if (elementType == XmlTokenType.XML_WHITE_SPACE || elementType == XmlTokenType.XML_DATA_CHARACTERS || elementType == XmlTokenType
+        .XML_ATTRIBUTE_VALUE_TOKEN) {
+        buffer.append(child.getText());
+      }
+      else if (elementType == TokenType.ERROR_ELEMENT || elementType == TokenType.NEW_LINE_INDENT) {
+        buffer.append(child.getText());
+      }
+
+      int end = buffer.length();
+      int originalLength = child.getTextLength();
+      if (end - start != originalLength) {
+        gapsStarts.add(end);
+        gapsShifts.add(originalLength - (end - start));
+      }
+      final ASTNode next = child.getTreeNext();
+      if (next == null && child.getTreeParent().getElementType() == XmlElementType.XML_CDATA) {
+        child = child.getTreeParent().getTreeNext();
+      }
+      else {
+        child = next;
+      }
+    }
+    int[] gapDisplayStarts = ArrayUtil.newIntArray(gapsShifts.size());
+    int[] gapPhysicalStarts = ArrayUtil.newIntArray(gapsShifts.size());
+    int currentGapsSum = 0;
+    for (int i = 0; i < gapDisplayStarts.length; i++) {
+      currentGapsSum += gapsShifts.get(i);
+      gapDisplayStarts[i] = gapsStarts.get(i);
+      gapPhysicalStarts[i] = gapDisplayStarts[i] + currentGapsSum;
+    }
+    myGapDisplayStarts = gapDisplayStarts;
+    myGapPhysicalStarts = gapPhysicalStarts;
+    String text = buffer.toString();
+    myDisplayText = text;
+    return text;
+  }
+
+  public int physicalToDisplay(int physicalIndex) {
+    getValue();
+    if (myGapPhysicalStarts.length == 0) return physicalIndex;
+
+    final int bsResult = Arrays.binarySearch(myGapPhysicalStarts, physicalIndex);
+
+    if (bsResult >= 0) return myGapDisplayStarts[bsResult];
+
+    int insertionIndex = -bsResult - 1;
+
+    //if (insertionIndex == myGapDisplayStarts.length) return getValue().length();
+
+    int prevPhysGapStart = insertionIndex > 0 ? myGapPhysicalStarts[insertionIndex - 1] : 0;
+    int prevDisplayGapStart = insertionIndex > 0 ? myGapDisplayStarts[insertionIndex - 1] : 0;
+
+    if (insertionIndex < myGapDisplayStarts.length) {
+      int prevDisplayGapLength =
+        insertionIndex > 0 ? myGapDisplayStarts[insertionIndex] - myGapDisplayStarts[insertionIndex - 1] : myGapDisplayStarts[0];
+      if (physicalIndex - prevPhysGapStart > prevDisplayGapLength) return myGapDisplayStarts[insertionIndex];
+    }
+
+    return physicalIndex - prevPhysGapStart + prevDisplayGapStart;
+  }
+
+  public int displayToPhysical(int displayIndex) {
+    getValue();
+    if (myGapDisplayStarts.length == 0) return displayIndex;
+
+    final int bsResult = Arrays.binarySearch(myGapDisplayStarts, displayIndex);
+    if (bsResult >= 0) return myGapPhysicalStarts[bsResult];
+
+    int insertionIndex = -bsResult - 1;
+    int prevPhysGapStart = insertionIndex > 0 ? myGapPhysicalStarts[insertionIndex - 1] : 0;
+    int prevDisplayGapStart = insertionIndex > 0 ? myGapDisplayStarts[insertionIndex - 1] : 0;
+    return displayIndex - prevDisplayGapStart + prevPhysGapStart;
+  }
+
+  public void setValue(String s) throws IncorrectOperationException {
+    doSetValue(s, getPolicy());
+  }
+
+  private void doSetValue(final String s, XmlPsiPolicy policy) throws IncorrectOperationException {
+    final ASTNode firstEncodedElement = policy.encodeXmlTextContents(s, this);
+
+    if (firstEncodedElement == null) {
+      delete();
+      return;
+    }
+
+    final PomModel model = PomManager.getModel(getProject());
+    final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+    model.runTransaction(new PomTransactionBase(this, aspect) {
+      public PomModelEvent runInner() {
+        final String oldText = getText();
+        replaceAllChildrenToChildrenOf(firstEncodedElement.getTreeParent());
+        clearCaches();
+        return XmlTextChangedImpl.createXmlTextChanged(model, XmlTextImpl.this, oldText);
+      }
+    });
+  }
+
+  public XmlElement insertAtOffset(final XmlElement element, final int displayOffset) throws IncorrectOperationException {
+    if (element instanceof XmlText) {
+      insertText(((XmlText)element).getValue(), displayOffset);
+    }
+    else {
+      final PomModel model = PomManager.getModel(getProject());
+      final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+      model.runTransaction(new PomTransactionBase(getParent(), aspect) {
+        public PomModelEvent runInner() throws IncorrectOperationException {
+          final XmlTag tag = getParentTag();
+          assert tag != null;
+
+          final XmlText rightPart = _splitText(displayOffset);
+          PsiElement result;
+          if (rightPart != null) {
+            result = tag.addBefore(element, rightPart);
+          }
+          else {
+            result = tag.addAfter(element, XmlTextImpl.this);
+          }
+          return createEvent(new XmlTagChildAddImpl(tag, (XmlTagChild)result));
+        }
+      });
+    }
+
+    return this;
+  }
+
+  private XmlPsiPolicy getPolicy() {
+    return ((XMLLanguage)getLanguage()).getPsiPolicy();
+  }
+
+  public void insertText(String text, int displayOffset) throws IncorrectOperationException {
+    if (text == null || text.length() == 0) return;
+
+    final int physicalOffset = displayToPhysical(displayOffset);
+    final PsiElement psiElement = findElementAt(physicalOffset);
+    //if (!(psiElement instanceof XmlTokenImpl)) throw new IncorrectOperationException("Can't insert at offset: " + displayOffset);
+    final IElementType elementType = psiElement != null ? psiElement.getNode().getElementType() : null;
+
+    if (elementType == XmlTokenType.XML_DATA_CHARACTERS) {
+      int insertOffset = physicalOffset - psiElement.getStartOffsetInParent();
+
+      final String oldElementText = psiElement.getText();
+      final String newElementText = oldElementText.substring(0, insertOffset) + text + oldElementText.substring(insertOffset);
+
+      final PomModel model = PomManager.getModel(getProject());
+      final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+      model.runTransaction(new PomTransactionBase(this, aspect) {
+        public PomModelEvent runInner() {
+          final String oldText = getText();
+
+          final ASTNode e =
+            getPolicy().encodeXmlTextContents(newElementText, XmlTextImpl.this);
+
+          final ASTNode node = psiElement.getNode();
+          final ASTNode treeNext = node.getTreeNext();
+
+          addChildren(e, null, treeNext);
+
+          deleteChildInternal(node);
+
+
+          clearCaches();
+          return XmlTextChangedImpl.createXmlTextChanged(model, XmlTextImpl.this, oldText);
+        }
+      });
+    }
+    else {
+      setValue(new StringBuffer(getValue()).insert(displayOffset, text).toString());
+    }
+  }
+
+  public void removeText(int displayStart, int displayEnd) throws IncorrectOperationException {
+    final String value = getValue();
+
+    final int physicalStart = displayToPhysical(displayStart);
+    final PsiElement psiElement = findElementAt(physicalStart);
+    if (psiElement != null) {
+      final IElementType elementType = psiElement.getNode().getElementType();
+      final int elementDisplayEnd = physicalToDisplay(psiElement.getStartOffsetInParent() + psiElement.getTextLength());
+      final int elementDisplayStart = physicalToDisplay(psiElement.getStartOffsetInParent());
+      if (elementType == XmlTokenType.XML_DATA_CHARACTERS || elementType == TokenType.WHITE_SPACE) {
+        if (elementDisplayEnd >= displayEnd && elementDisplayStart <= displayStart) {
+          int physicalEnd = physicalStart;
+          while (physicalEnd < getTextRange().getLength()) {
+            if (physicalToDisplay(physicalEnd) == displayEnd) break;
+            physicalEnd++;
+          }
+
+          int removeStart = physicalStart - psiElement.getStartOffsetInParent();
+          int removeEnd = physicalEnd - psiElement.getStartOffsetInParent();
+
+          final String oldElementText = psiElement.getText();
+          final String newElementText = oldElementText.substring(0, removeStart) + oldElementText.substring(removeEnd);
+
+          final PomModel model = PomManager.getModel(getProject());
+          final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+          model.runTransaction(new PomTransactionBase(this, aspect) {
+            public PomModelEvent runInner() throws IncorrectOperationException {
+              final String oldText = getText();
+
+              if (newElementText.length() > 0) {
+                final ASTNode e =
+                  getPolicy().encodeXmlTextContents(newElementText, XmlTextImpl.this);
+                replaceChild(psiElement.getNode(), e);
+              }
+              else {
+                psiElement.delete();
+              }
+
+              clearCaches();
+              return XmlTextChangedImpl.createXmlTextChanged(model, XmlTextImpl.this, oldText);
+            }
+          });
+
+          return;
+        }
+      }
+    }
+
+    if (displayStart == 0 && displayEnd == value.length()) {
+      delete();
+    }
+    else {
+      setValue(new StringBuffer(getValue()).replace(displayStart, displayEnd, "").toString());
+    }
+  }
+
+  public XmlTag getParentTag() {
+    final PsiElement parent = getParent();
+    if (parent instanceof XmlTag) return (XmlTag)parent;
+    return null;
+  }
+
+  public XmlTagChild getNextSiblingInTag() {
+    PsiElement nextSibling = getNextSibling();
+    if (nextSibling instanceof XmlTagChild) return (XmlTagChild)nextSibling;
+    return null;
+  }
+
+  public XmlTagChild getPrevSiblingInTag() {
+    PsiElement prevSibling = getPrevSibling();
+    if (prevSibling instanceof XmlTagChild) return (XmlTagChild)prevSibling;
+    return null;
+  }
+
+  public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
+    throw new RuntimeException("Clients must not use operations with direct children of XmlText!");
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlText(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public void clearCaches() {
+    super.clearCaches();
+    myDisplayText = null;
+    myGapDisplayStarts = null;
+    myGapPhysicalStarts = null;
+  }
+
+  @Nullable
+  public List<Pair<PsiElement, TextRange>> getInjectedPsi() {
+    return InjectedLanguageManager.getInstance(getProject()).getInjectedPsiFiles(this);
+  }
+
+  public TextRange getCDATAInterior() {
+    PsiElement[] elements = getChildren();
+    int start = 0;
+    int first = 0;
+    if (elements.length > 0 && elements[0] instanceof PsiWhiteSpace) {
+      first ++;
+    }
+    if (elements.length > first && elements[first].getNode().getElementType() == XmlElementType.XML_CDATA) {
+      ASTNode startNode = elements[first].getNode().findChildByType(XmlTokenType.XML_CDATA_START);
+      if (startNode != null) {
+        start = startNode.getTextRange().getEndOffset() - getTextRange().getStartOffset();
+      }
+    }
+    int end = getTextLength();
+    int last = elements.length - 1;
+    if (last > 0 && elements[last] instanceof PsiWhiteSpace) {
+      last --;
+    }
+    if (last >= 0 && elements[last].getNode().getElementType() == XmlElementType.XML_CDATA) {
+      ASTNode startNode = elements[last].getNode().findChildByType(XmlTokenType.XML_CDATA_END);
+      if (startNode != null) {
+        end = startNode.getTextRange().getStartOffset() - getTextRange().getStartOffset();
+      }
+    }
+
+    return new TextRange(start, end);
+  }
+
+  public PsiLanguageInjectionHost updateText(@NotNull final String text) {
+    try {
+      doSetValue(text, new DefaultXmlPsiPolicy());
+    }
+    catch (IncorrectOperationException e) {
+      LOG.error(e);
+    }
+    return this;
+  }
+
+  @Nullable
+  private XmlText _splitText(final int displayOffset) throws IncorrectOperationException{
+    final XmlTag xmlTag = (XmlTag)getParent();
+    if(displayOffset == 0) return this;
+    final int length = getValue().length();
+    if(displayOffset >= length) {
+      return null;
+    }
+
+    final PomModel model = PomManager.getModel(xmlTag.getProject());
+    final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
+
+    class MyTransaction extends PomTransactionBase {
+      private XmlTextImpl myRight;
+
+      MyTransaction() {
+        super(xmlTag, aspect);
+      }
+
+      @Nullable
+      public PomModelEvent runInner() throws IncorrectOperationException {
+        final String oldText = getValue();
+        final int physicalOffset = displayToPhysical(displayOffset);
+        PsiElement childElement = findElementAt(physicalOffset);
+
+        if (childElement != null && childElement.getNode().getElementType() == XmlTokenType.XML_DATA_CHARACTERS) {
+          FileElement holder = DummyHolderFactory.createHolder(getManager(), null).getTreeElement();
+
+          int splitOffset = physicalOffset - childElement.getStartOffsetInParent();
+          myRight = (XmlTextImpl)ASTFactory.composite(XmlElementType.XML_TEXT);
+          CodeEditUtil.setNodeGenerated(myRight, true);
+          holder.rawAddChildren(myRight);
+
+          PsiElement e = childElement;
+          while (e != null) {
+            CodeEditUtil.setNodeGenerated(e.getNode(), true);
+            e = e.getNextSibling();
+          }
+
+          String leftText = childElement.getText().substring(0, splitOffset);
+          String rightText = childElement.getText().substring(splitOffset);
+
+
+          LeafElement rightElement =
+            ASTFactory.leaf(XmlTokenType.XML_DATA_CHARACTERS, holder.getCharTable().intern(rightText));
+          CodeEditUtil.setNodeGenerated(rightElement, true);
+
+          LeafElement leftElement = ASTFactory.leaf(XmlTokenType.XML_DATA_CHARACTERS, holder.getCharTable().intern(leftText));
+          CodeEditUtil.setNodeGenerated(leftElement, true);
+
+          rawInsertAfterMe(myRight);
+
+          myRight.rawAddChildren(rightElement);
+          if (childElement.getNextSibling() != null) {
+            myRight.rawAddChildren((TreeElement)childElement.getNextSibling());
+          }
+          ((TreeElement)childElement).rawRemove();
+          XmlTextImpl.this.rawAddChildren(leftElement);
+        }
+        else {
+          final PsiFile containingFile = xmlTag.getContainingFile();
+          final FileElement holder = DummyHolderFactory
+            .createHolder(containingFile.getManager(), null, ((PsiFileImpl)containingFile).getTreeElement().getCharTable()).getTreeElement();
+          final XmlTextImpl rightText = (XmlTextImpl)ASTFactory.composite(XmlElementType.XML_TEXT);
+          CodeEditUtil.setNodeGenerated(rightText, true);
+
+          holder.rawAddChildren(rightText);
+
+          ((ASTNode)xmlTag).addChild(rightText, getTreeNext());
+
+          final String value = getValue();
+
+          setValue(value.substring(0, displayOffset));
+          rightText.setValue(value.substring(displayOffset));
+
+          CodeEditUtil.setNodeGenerated(rightText, true);
+
+          myRight = rightText;
+        }
+
+        clearCaches();
+        myRight.clearCaches();
+        return createEvent(new XmlTextChangedImpl(XmlTextImpl.this, oldText), new XmlTagChildAddImpl(xmlTag, myRight));
+      }
+
+      public XmlText getResult() {
+        return myRight;
+      }
+    }
+    final MyTransaction transaction = new MyTransaction();
+    model.runTransaction(transaction);
+
+    return transaction.getResult();
+  }
+
+  private PomModelEvent createEvent(final XmlChange...events) {
+    final PomModelEvent event = new PomModelEvent(PomManager.getModel(getProject()));
+
+    final XmlAspectChangeSetImpl xmlAspectChangeSet = new XmlAspectChangeSetImpl(PomManager.getModel(getProject()), (XmlFile)getContainingFile());
+
+    for (XmlChange xmlChange : events) {
+      xmlAspectChangeSet.add(xmlChange);
+    }
+
+    event.registerChangeSet(PomManager.getModel(getProject()).getModelAspect(XmlAspect.class), xmlAspectChangeSet);
+
+    return event;
+  }
+
+  @NotNull
+  public LiteralTextEscaper<XmlTextImpl> createLiteralTextEscaper() {
+    return new XmlTextLiteralEscaper(this);
+  }
+  public void processInjectedPsi(@NotNull InjectedPsiVisitor visitor) {
+    InjectedLanguageUtil.enumerate(this, visitor);
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTokenImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTokenImpl.java
new file mode 100644
index 0000000..822e615
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTokenImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.ide.util.EditSourceUtil;
+import com.intellij.pom.Navigatable;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.impl.source.tree.LeafPsiElement;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.xml.IDTDElementType;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ik
+ */
+public class XmlTokenImpl extends LeafPsiElement implements XmlToken, Navigatable {
+  public XmlTokenImpl(IElementType type, CharSequence text) {
+    super(type, text);
+  }
+
+  public boolean processElements(PsiElementProcessor processor, PsiElement place) {
+    return false;
+  }
+
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof XmlElementVisitor) {
+      ((XmlElementVisitor)visitor).visitXmlToken(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  public String toString() {
+    if(getTokenType() instanceof IDTDElementType){
+      return "DTDToken:" + getTokenType().toString();
+    }
+    return "XmlToken:" + getTokenType().toString();
+  }
+
+// Implementation specific
+
+  public IElementType getTokenType() {
+    return getElementType();
+  }
+
+  @NotNull
+  public PsiReference[] getReferences() {
+    final IElementType elementType = getElementType();
+
+    if (elementType == XmlTokenType.XML_DATA_CHARACTERS ||
+        elementType == XmlTokenType.XML_CHAR_ENTITY_REF
+      ) {
+      return ReferenceProvidersRegistry.getReferencesFromProviders(this, XmlToken.class);
+    } else if (elementType == XmlTokenType.XML_NAME && getParent() instanceof PsiErrorElement) {
+      final PsiElement element = getPrevSibling();
+      
+      if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_END_TAG_START) {
+        return new PsiReference[] {TagNameReference.createTagNameReference(this, getNode(), false)};
+      }
+    }
+
+    return super.getReferences();
+  }
+
+  public void navigate(boolean requestFocus) {
+    EditSourceUtil.getDescriptor(this).navigate(requestFocus);
+  }
+
+  public boolean canNavigate() {
+    return getTokenType() == XmlTokenType.XML_NAME && EditSourceUtil.canNavigate(this);
+  }
+
+  public boolean canNavigateToSource() {
+    return canNavigate();
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XsContentDFA.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XsContentDFA.java
new file mode 100644
index 0000000..3aff250
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XsContentDFA.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.NullableComputable;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.actions.ValidateXmlActionHandler;
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.xs.SubstitutionGroupHandler;
+import org.apache.xerces.impl.xs.XSComplexTypeDecl;
+import org.apache.xerces.impl.xs.XSElementDecl;
+import org.apache.xerces.impl.xs.XSGrammarBucket;
+import org.apache.xerces.impl.xs.models.CMBuilder;
+import org.apache.xerces.impl.xs.models.CMNodeFactory;
+import org.apache.xerces.impl.xs.models.XSCMValidator;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.grammars.Grammar;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.apache.xerces.xni.grammars.XSGrammar;
+import org.apache.xerces.xs.XSElementDeclaration;
+import org.apache.xerces.xs.XSModel;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+class XsContentDFA extends XmlContentDFA {
+
+  private final XSCMValidator myContentModel;
+  private final SubstitutionGroupHandler myHandler;
+  private final int[] myState;
+  private final XmlElementDescriptor[] myElementDescriptors;
+
+  @Nullable
+  public static XmlContentDFA createContentDFA(@NotNull XmlTag parentTag) {
+    final PsiFile file = parentTag.getContainingFile().getOriginalFile();
+    if (!(file instanceof XmlFile)) return null;
+    XSModel xsModel = ApplicationManager.getApplication().runReadAction(new NullableComputable<XSModel>() {
+      @Override
+      public XSModel compute() {
+        return getXSModel((XmlFile)file);
+      }
+    });
+    if (xsModel == null) {
+      return null;
+    }
+
+    XSElementDeclaration decl = getElementDeclaration(parentTag, xsModel);
+    if (decl == null) {
+      return null;
+    }
+    return new XsContentDFA(decl, parentTag);
+  }
+
+  public XsContentDFA(@NotNull XSElementDeclaration decl, final XmlTag parentTag) {
+    XSComplexTypeDecl definition = (XSComplexTypeDecl)decl.getTypeDefinition();
+    myContentModel = definition.getContentModel(new CMBuilder(new CMNodeFactory()));
+    myHandler = new SubstitutionGroupHandler(new XSGrammarBucket());
+    myState = myContentModel.startContentModel();
+    myElementDescriptors = ApplicationManager.getApplication().runReadAction(new Computable<XmlElementDescriptor[]>() {
+
+      @Override
+      public XmlElementDescriptor[] compute() {
+        XmlElementDescriptor parentTagDescriptor = parentTag.getDescriptor();
+        assert parentTagDescriptor != null;
+        return parentTagDescriptor.getElementsDescriptors(parentTag);
+      }
+    });
+  }
+
+  @Override
+  public List<XmlElementDescriptor> getPossibleElements() {
+    final List vector = myContentModel.whatCanGoHere(myState);
+    ArrayList<XmlElementDescriptor> list = new ArrayList<XmlElementDescriptor>();
+    for (Object o : vector) {
+      if (o instanceof XSElementDecl) {
+        final XSElementDecl elementDecl = (XSElementDecl)o;
+        XmlElementDescriptor descriptor = ContainerUtil.find(myElementDescriptors, new Condition<XmlElementDescriptor>() {
+          @Override
+          public boolean value(XmlElementDescriptor elementDescriptor) {
+            return elementDecl.getName().equals(elementDescriptor.getName());
+          }
+        });
+        ContainerUtil.addIfNotNull(descriptor, list);
+      }
+    }
+    return list;
+  }
+
+  @Override
+  public void transition(XmlTag xmlTag) {
+    myContentModel.oneTransition(createQName(xmlTag), myState, myHandler);
+  }
+
+  private static QName createQName(XmlTag tag) {
+    //todo don't use intern to not pollute PermGen
+    String namespace = tag.getNamespace();
+    return new QName(tag.getNamespacePrefix().intern(),
+                     tag.getLocalName().intern(),
+                     tag.getName().intern(),
+                     namespace.length() == 0 ? null : namespace.intern());
+  }
+
+  @Nullable
+  private static XSElementDeclaration getElementDeclaration(XmlTag tag, XSModel xsModel) {
+
+    List<XmlTag> ancestors = new ArrayList<XmlTag>();
+    for (XmlTag t = tag; t != null; t = t.getParentTag()) {
+      ancestors.add(t);
+    }
+    Collections.reverse(ancestors);
+    XSElementDeclaration declaration = null;
+    SubstitutionGroupHandler fSubGroupHandler = new SubstitutionGroupHandler(new XSGrammarBucket());
+    CMBuilder cmBuilder = new CMBuilder(new CMNodeFactory());
+    for (XmlTag ancestor : ancestors) {
+      if (declaration == null) {
+        declaration = xsModel.getElementDeclaration(ancestor.getLocalName(), ancestor.getNamespace());
+        if (declaration == null) return null;
+        else continue;
+      }
+      XSTypeDefinition typeDefinition = declaration.getTypeDefinition();
+      if (!(typeDefinition instanceof XSComplexTypeDecl)) {
+        return null;
+      }
+
+      XSCMValidator model = ((XSComplexTypeDecl)typeDefinition).getContentModel(cmBuilder);
+      int[] ints = model.startContentModel();
+      for (XmlTag subTag : ancestor.getParentTag().getSubTags()) {
+        QName qName = createQName(subTag);
+        Object o = model.oneTransition(qName, ints, fSubGroupHandler);
+        if (subTag == ancestor) {
+          if (o instanceof XSElementDecl) {
+            declaration = (XSElementDecl)o;
+            break;
+          }
+          else return null;
+        }
+      }
+    }
+    return declaration;
+  }
+
+  @Nullable
+  private static XSModel getXSModel(XmlFile file) {
+
+    ValidateXmlActionHandler handler = new ValidateXmlActionHandler(false) {
+      @Override
+      protected SAXParser createParser() throws SAXException, ParserConfigurationException {
+        SAXParser parser = super.createParser();
+        parser.getXMLReader().setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE, true);
+        return parser;
+      }
+    };
+    handler.setErrorReporter(handler.new TestErrorReporter());
+    handler.doValidate(file);
+    XMLGrammarPool grammarPool = ValidateXmlActionHandler.getGrammarPool(file);
+    if (grammarPool == null) {
+      return null;
+    }
+    Grammar[] grammars = grammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA);
+
+    return grammars.length == 0 ? null : ((XSGrammar)grammars[0]).toXSModel(ContainerUtil.map(grammars, new Function<Grammar, XSGrammar>() {
+      @Override
+      public XSGrammar fun(Grammar grammar) {
+        return (XSGrammar)grammar;
+      }
+    }, new XSGrammar[0]));
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/behavior/CDATAOnAnyEncodedPolicy.java b/xml/impl/src/com/intellij/psi/impl/source/xml/behavior/CDATAOnAnyEncodedPolicy.java
new file mode 100644
index 0000000..c22c6d9
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/behavior/CDATAOnAnyEncodedPolicy.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml.behavior;
+
+import com.intellij.lang.ASTFactory;
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.GeneratedMarkerVisitor;
+import com.intellij.psi.impl.source.DummyHolderFactory;
+import com.intellij.psi.impl.source.tree.CompositeElement;
+import com.intellij.psi.impl.source.tree.FileElement;
+import com.intellij.psi.impl.source.tree.SharedImplUtil;
+import com.intellij.psi.xml.XmlElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.CharTable;
+import com.intellij.xml.util.XmlUtil;
+
+public class CDATAOnAnyEncodedPolicy extends DefaultXmlPsiPolicy{
+  public ASTNode encodeXmlTextContents(String displayText, PsiElement text) {
+    final ASTNode firstChild = text.getNode().getFirstChildNode();
+    boolean textAlreadyHasCDATA = firstChild != null && firstChild.getElementType() == XmlElementType.XML_CDATA;
+    if ((textAlreadyHasCDATA || XmlUtil.toCode(displayText)) && displayText.length() > 0) {
+      final FileElement dummyParent = createCDATAElement(text.getManager(), SharedImplUtil.findCharTableByTree(text.getNode()), displayText);
+      return dummyParent.getFirstChildNode();
+    }
+    else {
+      return super.encodeXmlTextContents(displayText, text);
+    }
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  public static FileElement createCDATAElement(final PsiManager manager, final CharTable charTableByTree, final String displayText) {
+    final FileElement dummyParent = DummyHolderFactory.createHolder(manager, null, charTableByTree).getTreeElement();
+    final CompositeElement cdata = ASTFactory.composite(XmlElementType.XML_CDATA);
+    dummyParent.rawAddChildren(cdata);
+    cdata.rawAddChildren(ASTFactory.leaf(XmlTokenType.XML_CDATA_START, "<![CDATA["));
+    cdata.rawAddChildren(ASTFactory.leaf(XmlTokenType.XML_DATA_CHARACTERS, dummyParent.getCharTable().intern(displayText)));
+    cdata.rawAddChildren(ASTFactory.leaf(XmlTokenType.XML_CDATA_END, "]]>"));
+    dummyParent.acceptTree(new GeneratedMarkerVisitor());
+    return dummyParent;
+  }
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/behavior/DefaultXmlPsiPolicy.java b/xml/impl/src/com/intellij/psi/impl/source/xml/behavior/DefaultXmlPsiPolicy.java
new file mode 100644
index 0000000..a5bfb19
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/behavior/DefaultXmlPsiPolicy.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml.behavior;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.impl.source.DummyHolderFactory;
+import com.intellij.psi.impl.source.tree.FileElement;
+import com.intellij.psi.impl.source.tree.SharedImplUtil;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.impl.source.tree.TreeUtil;
+import com.intellij.psi.impl.source.xml.XmlPsiPolicy;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTagChild;
+import com.intellij.util.CharTable;
+
+public class DefaultXmlPsiPolicy implements XmlPsiPolicy{
+  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.behavior.DefaultXmlPsiPolicy");
+
+  public ASTNode encodeXmlTextContents(String displayText, PsiElement text) {
+    final PsiFile containingFile = text.getContainingFile();
+    CharTable charTable = SharedImplUtil.findCharTableByTree(text.getNode());
+    final FileElement dummyParent = DummyHolderFactory.createHolder(text.getManager(), null, charTable).getTreeElement();
+    final XmlTag rootTag =
+      ((XmlFile)PsiFileFactory.getInstance(containingFile.getProject())
+        .createFileFromText("a.xml", "<a>" + displayText + "</a>")).getRootTag();
+
+    assert rootTag != null;
+    final XmlTagChild[] tagChildren = rootTag.getValue().getChildren();
+
+    final XmlTagChild child = tagChildren.length > 0 ? tagChildren[0]:null;
+    LOG.assertTrue(child != null, "Child is null for tag: " + rootTag.getText());
+
+    final TreeElement element = (TreeElement)child.getNode();
+    ((TreeElement)tagChildren[tagChildren.length - 1].getNode().getTreeNext()).rawRemoveUpToLast();
+    dummyParent.rawAddChildren(element);
+    TreeUtil.clearCaches(dummyParent);
+    return element.getFirstChildNode();
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/behavior/EncodeEachSymbolPolicy.java b/xml/impl/src/com/intellij/psi/impl/source/xml/behavior/EncodeEachSymbolPolicy.java
new file mode 100644
index 0000000..ebb0117
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/behavior/EncodeEachSymbolPolicy.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.xml.behavior;
+
+import com.intellij.lang.ASTFactory;
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.impl.GeneratedMarkerVisitor;
+import com.intellij.psi.impl.source.DummyHolderFactory;
+import com.intellij.psi.impl.source.tree.FileElement;
+import com.intellij.psi.impl.source.tree.TreeElement;
+import com.intellij.psi.impl.source.tree.SharedImplUtil;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.CharTable;
+
+public class EncodeEachSymbolPolicy extends DefaultXmlPsiPolicy{
+  public ASTNode encodeXmlTextContents(String displayText, PsiElement text) {
+    if(!toCode(displayText)) return super.encodeXmlTextContents(displayText, text);
+    final FileElement dummyParent = DummyHolderFactory.createHolder(text.getManager(), null, SharedImplUtil.findCharTableByTree(text.getNode())).getTreeElement();
+    int sectionStartOffset = 0;
+    int offset = 0;
+    while (offset < displayText.length()) {
+      if (toCode(displayText.charAt(offset))) {
+        final String plainSection = displayText.substring(sectionStartOffset, offset);
+        if (plainSection.length() > 0) {
+          dummyParent.rawAddChildren((TreeElement)super.encodeXmlTextContents(plainSection, text));
+        }
+        dummyParent.rawAddChildren(createCharEntity(displayText.charAt(offset), dummyParent.getCharTable()));
+        sectionStartOffset = offset + 1;
+      }
+      offset++;
+    }
+    final String plainSection = displayText.substring(sectionStartOffset, offset);
+    if (plainSection.length() > 0) {
+      dummyParent.rawAddChildren((TreeElement)super.encodeXmlTextContents(plainSection, text));
+    }
+
+    dummyParent.acceptTree(new GeneratedMarkerVisitor());
+    return dummyParent.getFirstChildNode();
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  private static TreeElement createCharEntity(char ch, CharTable charTable) {
+    switch (ch) {
+      case '<':
+        return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, "&lt;");
+      case '\'':
+        return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, "&apos;");
+      case '"':
+        return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, "&quot;");
+      case '>':
+        return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, "&gt;");
+      case '&':
+        return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, "&amp;");
+      case '\u00a0':
+        return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, "&nbsp;");
+
+      default:
+        final String charEncoding = "&#" + (int)ch + ";";
+        return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, charTable.intern(charEncoding));
+    }
+  }
+
+  private static boolean toCode(String str) {
+    for (int i = 0; i < str.length(); i++) {
+      final char ch = str.charAt(i);
+      if ( toCode(ch)) return true;
+    }
+    return false;
+  }
+
+  private static boolean toCode(final char ch) {
+    return "<&>\u00a0'\"".indexOf(ch) >= 0;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/psi/xml/XmlChildRole.java b/xml/impl/src/com/intellij/psi/xml/XmlChildRole.java
new file mode 100644
index 0000000..0e39ab2
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/xml/XmlChildRole.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.DefaultRoleFinder;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.RoleFinder;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.util.XmlTagUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public interface XmlChildRole {
+
+  interface StartTagEndTokenProvider {
+    IElementType[] getTypes();
+  }
+
+  ExtensionPointName<StartTagEndTokenProvider> EP_NAME = new ExtensionPointName<StartTagEndTokenProvider>("com.intellij.xml.startTagEndToken");
+
+  RoleFinder START_TAG_NAME_FINDER = new RoleFinder() {
+    public ASTNode findChild(@NotNull ASTNode parent) {
+      final PsiElement element = XmlTagUtil.getStartTagNameElement((XmlTag)parent.getPsi());
+      return element == null ? null : element.getNode();
+    }
+  };
+
+  RoleFinder CLOSING_TAG_NAME_FINDER = new RoleFinder() {
+    @Nullable
+    public ASTNode findChild(@NotNull ASTNode parent) {
+      final PsiElement element = XmlTagUtil.getEndTagNameElement((XmlTag)parent.getPsi());
+      return element == null ? null : element.getNode();
+    }
+  };
+
+  RoleFinder DOCUMENT_FINDER = new RoleFinder() {
+    public ASTNode findChild(@NotNull ASTNode parent) {
+      ASTNode oldDocument = parent.findChildByType(XmlElementType.XML_DOCUMENT);
+      if(oldDocument == null) oldDocument = parent.findChildByType(XmlElementType.HTML_DOCUMENT);
+      return oldDocument;
+    }
+  };
+
+  RoleFinder ATTRIBUTE_VALUE_FINDER = new DefaultRoleFinder(XmlElementType.XML_ATTRIBUTE_VALUE);
+  RoleFinder CLOSING_TAG_START_FINDER = new DefaultRoleFinder(XmlTokenType.XML_END_TAG_START);
+  RoleFinder EMPTY_TAG_END_FINDER = new DefaultRoleFinder(XmlTokenType.XML_EMPTY_ELEMENT_END);
+  RoleFinder ATTRIBUTE_NAME_FINDER = new DefaultRoleFinder(XmlTokenType.XML_NAME);
+  RoleFinder ATTRIBUTE_VALUE_VALUE_FINDER = new DefaultRoleFinder(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN);
+  RoleFinder START_TAG_END_FINDER = new DefaultRoleFinder(XmlTokenType.XML_TAG_END) {
+    {
+      final StartTagEndTokenProvider[] tokenProviders = Extensions.getExtensions(EP_NAME);
+      for (StartTagEndTokenProvider tokenProvider : tokenProviders) {
+        myElementTypes = ArrayUtil.mergeArrays(myElementTypes, tokenProvider.getTypes());
+      }
+    }
+  };
+  RoleFinder START_TAG_START_FINDER = new DefaultRoleFinder(XmlTokenType.XML_START_TAG_START);
+  RoleFinder PROLOG_FINDER = new DefaultRoleFinder(XmlElementType.XML_PROLOG);
+
+
+  int XML_DOCUMENT = 223;
+  int XML_TAG_NAME = 224;
+  int XML_PROLOG = 225;
+  int XML_DOCTYPE = 226;
+  int XML_DOCTYPE_PUBLIC = 227;
+  int XML_DOCTYPE_SYSTEM = 228;
+  int XML_NAME = 229;
+  int XML_ELEMENT_CONTENT_SPEC = 230;
+  int XML_CONTENT_ANY = 231;
+  int XML_CONTENT_EMPTY = 232;
+  int XML_PCDATA = 233;
+  int XML_ATT_REQUIRED = 234;
+  int XML_ATT_IMPLIED = 235;
+  int XML_ATT_FIXED = 236;
+  int XML_DEFAULT_VALUE = 237;
+  int XML_ENUMERATED_TYPE = 238;
+  int XML_ATTRIBUTE = 240;
+  int XML_TAG = 241;
+  int XML_ATTRIBUTE_VALUE = 243;
+  int HTML_DOCUMENT = 252;
+}
diff --git a/xml/impl/src/com/intellij/psi/xml/XmlElementType.java b/xml/impl/src/com/intellij/psi/xml/XmlElementType.java
new file mode 100644
index 0000000..4b33722
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/xml/XmlElementType.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.xml;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.dtd.DTDLanguage;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.impl.source.parsing.xml.DtdParsing;
+import com.intellij.psi.tree.CustomParsingType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.IFileElementType;
+import com.intellij.psi.tree.xml.IXmlElementType;
+import com.intellij.util.CharTable;
+
+
+public interface XmlElementType extends XmlTokenType {
+  IElementType XML_DOCUMENT = new IXmlElementType("XML_DOCUMENT");
+  IElementType XML_PROLOG = new IXmlElementType("XML_PROLOG");
+  IElementType XML_DECL = new IXmlElementType("XML_DECL");
+  IElementType XML_DOCTYPE = new IXmlElementType("XML_DOCTYPE");
+  IElementType XML_ATTRIBUTE = new IXmlElementType("XML_ATTRIBUTE");
+  IElementType XML_COMMENT = new IXmlElementType("XML_COMMENT");
+  IElementType XML_TAG = new IXmlElementType("XML_TAG");
+  IElementType XML_ELEMENT_DECL = new IXmlElementType("XML_ELEMENT_DECL");
+  IElementType XML_CONDITIONAL_SECTION = new IXmlElementType("XML_CONDITIONAL_SECTION");
+
+  IElementType XML_ATTLIST_DECL = new IXmlElementType("XML_ATTLIST_DECL");
+  IElementType XML_NOTATION_DECL = new IXmlElementType("XML_NOTATION_DECL");
+  IElementType XML_ENTITY_DECL = new IXmlElementType("XML_ENTITY_DECL");
+  IElementType XML_ELEMENT_CONTENT_SPEC = new IXmlElementType("XML_ELEMENT_CONTENT_SPEC");
+  IElementType XML_ELEMENT_CONTENT_GROUP = new IXmlElementType("XML_ELEMENT_CONTENT_GROUP");
+  IElementType XML_ATTRIBUTE_DECL = new IXmlElementType("XML_ATTRIBUTE_DECL");
+  IElementType XML_ATTRIBUTE_VALUE = new IXmlElementType("XML_ATTRIBUTE_VALUE");
+  IElementType XML_ENTITY_REF = new IXmlElementType("XML_ENTITY_REF");
+  IElementType XML_ENUMERATED_TYPE = new IXmlElementType("XML_ENUMERATED_TYPE");
+  IElementType XML_PROCESSING_INSTRUCTION = new IXmlElementType("XML_PROCESSING_INSTRUCTION");
+  IElementType XML_CDATA = new IXmlElementType("XML_CDATA");
+
+  //todo: move to html
+  IElementType HTML_DOCUMENT = new IXmlElementType("HTML_DOCUMENT");
+  IElementType HTML_TAG = new IXmlElementType("HTML_TAG");
+  IFileElementType HTML_FILE = new IFileElementType(HTMLLanguage.INSTANCE);
+
+  IElementType XML_TEXT = new XmlTextElementType();
+
+  IFileElementType XML_FILE = new IFileElementType(XMLLanguage.INSTANCE);
+  IElementType XHTML_FILE = new IFileElementType(XHTMLLanguage.INSTANCE);
+
+
+  IFileElementType DTD_FILE = new IFileElementType("DTD_FILE", DTDLanguage.INSTANCE);
+
+  IElementType XML_MARKUP_DECL = new CustomParsingType("XML_MARKUP_DECL", XMLLanguage.INSTANCE){
+    public ASTNode parse(CharSequence text, CharTable table) {
+      return new DtdParsing(text, XML_MARKUP_DECL, DtdParsing.TYPE_FOR_MARKUP_DECL, null).parse();
+    }
+  };
+}
diff --git a/xml/impl/src/com/intellij/psi/xml/XmlTextElementType.java b/xml/impl/src/com/intellij/psi/xml/XmlTextElementType.java
new file mode 100644
index 0000000..911981f
--- /dev/null
+++ b/xml/impl/src/com/intellij/psi/xml/XmlTextElementType.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi.xml;
+
+import com.intellij.psi.tree.IStrongWhitespaceHolderElementType;
+import com.intellij.psi.tree.xml.IXmlElementType;
+
+class XmlTextElementType extends IXmlElementType implements IStrongWhitespaceHolderElementType {
+  public XmlTextElementType() {
+    super("XML_TEXT");
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/refactoring/XmlImportOptimizer.java b/xml/impl/src/com/intellij/refactoring/XmlImportOptimizer.java
new file mode 100644
index 0000000..3803b16
--- /dev/null
+++ b/xml/impl/src/com/intellij/refactoring/XmlImportOptimizer.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.refactoring;
+
+import com.intellij.codeInsight.daemon.impl.analysis.XmlUnusedNamespaceInspection;
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.codeInspection.QuickFix;
+import com.intellij.lang.ImportOptimizer;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.*;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Avdeev
+ *         Date: 11/7/11
+ */
+public class XmlImportOptimizer implements ImportOptimizer {
+
+  private final XmlUnusedNamespaceInspection myInspection = new XmlUnusedNamespaceInspection();
+  private final Condition<ProblemDescriptor> myCondition = new Condition<ProblemDescriptor>() {
+    @Override
+    public boolean value(ProblemDescriptor descriptor) {
+      PsiElement element = descriptor.getPsiElement();
+      PsiElement parent = element.getParent();
+      return parent != null && !myInspection.isSuppressedFor(parent);
+    }
+  };
+
+  @Override
+  public boolean supports(PsiFile file) {
+    return file instanceof XmlFile;
+  }
+
+  @NotNull
+  @Override
+  public Runnable processFile(final PsiFile file) {
+    return new Runnable() {
+      @Override
+      public void run() {
+        XmlFile xmlFile = (XmlFile)file;
+        Project project = xmlFile.getProject();
+        ProblemsHolder holder = new ProblemsHolder(InspectionManager.getInstance(project), xmlFile, false);
+        final XmlElementVisitor visitor = (XmlElementVisitor)myInspection.buildVisitor(holder, false);
+        new PsiRecursiveElementVisitor() {
+          @Override
+          public void visitElement(PsiElement element) {
+            if (element instanceof XmlAttribute) {
+              visitor.visitXmlAttribute((XmlAttribute)element);
+            }
+            else {
+              super.visitElement(element);
+            }
+          }
+        }.visitFile(xmlFile);
+        ProblemDescriptor[] results = holder.getResultsArray();
+        ArrayUtil.reverseArray(results);
+        List<ProblemDescriptor> list = ContainerUtil.filter(results, myCondition);
+
+        Map<XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix, ProblemDescriptor> fixes = new LinkedHashMap<XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix, ProblemDescriptor>();
+        for (ProblemDescriptor result : list) {
+          for (QuickFix fix : result.getFixes()) {
+            if (fix instanceof XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix) {
+              fixes.put((XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix)fix, result);
+            }
+          }
+        }
+
+        SmartPsiElementPointer<XmlTag> pointer = null;
+        for (Map.Entry<XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix, ProblemDescriptor> fix : fixes.entrySet()) {
+          pointer = fix.getKey().doFix(project, fix.getValue(), false);
+        }
+        if (pointer != null) {
+          XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix.reformatStartTag(project, pointer);
+        }
+      }
+    };
+  }
+}
diff --git a/xml/impl/src/com/intellij/refactoring/rename/RenameXmlAttributeProcessor.java b/xml/impl/src/com/intellij/refactoring/rename/RenameXmlAttributeProcessor.java
new file mode 100644
index 0000000..1f7885b
--- /dev/null
+++ b/xml/impl/src/com/intellij/refactoring/rename/RenameXmlAttributeProcessor.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.refactoring.rename;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.refactoring.listeners.RefactoringElementListener;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.Queue;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class RenameXmlAttributeProcessor extends RenamePsiElementProcessor {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.RenameXmlAttributeProcessor");
+
+  public boolean canProcessElement(@NotNull final PsiElement element) {
+    return element instanceof XmlAttribute || element instanceof XmlAttributeValue;
+  }
+
+  public void renameElement(final PsiElement element,
+                            final String newName,
+                            final UsageInfo[] usages,
+                            @Nullable RefactoringElementListener listener) throws IncorrectOperationException {
+    if (element instanceof XmlAttribute) {
+      doRenameXmlAttribute((XmlAttribute)element, newName, listener);
+    }
+    else if (element instanceof XmlAttributeValue) {
+      doRenameXmlAttributeValue((XmlAttributeValue)element, newName, usages, listener);
+    }
+  }
+
+  private static void doRenameXmlAttribute(XmlAttribute attribute,
+                                           String newName,
+                                           @Nullable RefactoringElementListener listener) {
+    try {
+      final PsiElement element = attribute.setName(newName);
+      if (listener != null) {
+        listener.elementRenamed(element);
+      }
+    }
+    catch (IncorrectOperationException e) {
+      LOG.error(e);
+    }
+  }
+
+  private static void doRenameXmlAttributeValue(@NotNull XmlAttributeValue value,
+                                                String newName,
+                                                UsageInfo[] infos,
+                                                @Nullable RefactoringElementListener listener)
+    throws IncorrectOperationException {
+    LOG.assertTrue(value.isValid());
+
+    renameAll(value, infos, newName, value.getValue());
+
+    PsiManager psiManager = value.getManager();
+    LOG.assertTrue(psiManager != null);
+    XmlFile file = (XmlFile)PsiFileFactory.getInstance(psiManager.getProject()).createFileFromText("dummy.xml", "<a attr=\"" + newName + "\"/>");
+    final PsiElement element = value.replace(file.getDocument().getRootTag().getAttributes()[0].getValueElement());
+    if (listener != null) {
+      listener.elementRenamed(element);
+    }
+  }
+
+  private static void renameAll(PsiElement originalElement, UsageInfo[] infos, String newName,
+                                String originalName) throws IncorrectOperationException {
+    if (newName.equals(originalName)) return;
+    Queue<PsiReference> queue = new Queue<PsiReference>(infos.length);
+    for (UsageInfo info : infos) {
+      if (info.getElement() == null) continue;
+      PsiReference ref = info.getReference();
+      if (ref == null) continue;
+      queue.addLast(ref);
+    }
+
+    while(!queue.isEmpty()) {
+      final PsiReference reference = queue.pullFirst();
+      final PsiElement oldElement = reference.getElement();
+      if (!oldElement.isValid() || oldElement == originalElement) continue;
+      final PsiElement newElement = reference.handleElementRename(newName);
+      if (!oldElement.isValid()) {
+        for (PsiReference psiReference : ReferencesSearch.search(originalElement, new LocalSearchScope(newElement), false)) {
+          queue.addLast(psiReference);
+        }
+      }
+    }
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/refactoring/util/XmlNonCodeSearchElementDescriptionProvider.java b/xml/impl/src/com/intellij/refactoring/util/XmlNonCodeSearchElementDescriptionProvider.java
new file mode 100644
index 0000000..dac3df8
--- /dev/null
+++ b/xml/impl/src/com/intellij/refactoring/util/XmlNonCodeSearchElementDescriptionProvider.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.refactoring.util;
+
+import com.intellij.psi.ElementDescriptionLocation;
+import com.intellij.psi.ElementDescriptionProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class XmlNonCodeSearchElementDescriptionProvider implements ElementDescriptionProvider {
+  public String getElementDescription(@NotNull final PsiElement element, @NotNull final ElementDescriptionLocation location) {
+    if (!(location instanceof NonCodeSearchDescriptionLocation)) return null;
+    final NonCodeSearchDescriptionLocation ncdLocation = (NonCodeSearchDescriptionLocation)location;
+    if (ncdLocation.isNonJava()) return null;
+    if (element instanceof XmlTag) {
+      return ((XmlTag)element).getValue().getTrimmedText();
+    }
+    else if (element instanceof XmlAttribute) {
+      return ((XmlAttribute)element).getValue();
+    }
+    else if (element instanceof XmlAttributeValue) {
+      return ((XmlAttributeValue)element).getValue();
+    }
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/usageView/XmlUsageViewDescriptionProvider.java b/xml/impl/src/com/intellij/usageView/XmlUsageViewDescriptionProvider.java
new file mode 100644
index 0000000..b499d78
--- /dev/null
+++ b/xml/impl/src/com/intellij/usageView/XmlUsageViewDescriptionProvider.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.usageView;
+
+import com.intellij.psi.ElementDescriptionLocation;
+import com.intellij.psi.ElementDescriptionProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class XmlUsageViewDescriptionProvider implements ElementDescriptionProvider {
+  public String getElementDescription(@NotNull final PsiElement element, @NotNull final ElementDescriptionLocation location) {
+    if (location instanceof UsageViewShortNameLocation) {
+      if (element instanceof XmlAttributeValue) {
+        return ((XmlAttributeValue)element).getValue();
+      }
+    }
+
+    if (location instanceof UsageViewLongNameLocation) {
+      if (element instanceof XmlTag) {
+        return ((XmlTag)element).getName();
+      }
+      else if (element instanceof XmlAttributeValue) {
+        return ((XmlAttributeValue)element).getValue();
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/vcsUtil/XmlVcsSelectionProvider.java b/xml/impl/src/com/intellij/vcsUtil/XmlVcsSelectionProvider.java
new file mode 100644
index 0000000..50b9279
--- /dev/null
+++ b/xml/impl/src/com/intellij/vcsUtil/XmlVcsSelectionProvider.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.vcsUtil;
+
+import com.intellij.codeInsight.TargetElementUtilBase;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vcs.VcsBundle;
+import com.intellij.openapi.vcs.actions.VcsContext;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlText;
+
+/**
+ * @author yole
+ */
+public class XmlVcsSelectionProvider implements VcsSelectionProvider {
+  public VcsSelection getSelection(VcsContext context) {
+    final Editor editor = context.getEditor();
+      if (editor == null) return null;
+      PsiElement psiElement = TargetElementUtilBase.findTargetElement(editor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
+      if (psiElement == null || !psiElement.isValid()) {
+        return null;
+      }
+
+      final String actionName;
+
+      if (psiElement instanceof XmlTag) {
+        actionName = VcsBundle.message("action.name.show.history.for.tag");
+      }
+      else if (psiElement instanceof XmlText) {
+        actionName = VcsBundle.message("action.name.show.history.for.text");
+      }
+      else {
+        return null;
+      }
+
+      TextRange textRange = psiElement.getTextRange();
+      if (textRange == null) {
+        return null;
+      }
+
+      VirtualFile virtualFile = psiElement.getContainingFile().getVirtualFile();
+      if (virtualFile == null) {
+        return null;
+      }
+      if (!virtualFile.isValid()) {
+        return null;
+      }
+
+      Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
+      return new VcsSelection(document, textRange, actionName);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/DefaultXmlExtension.java b/xml/impl/src/com/intellij/xml/DefaultXmlExtension.java
new file mode 100644
index 0000000..d692afa
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/DefaultXmlExtension.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.impl.source.xml.SchemaPrefix;
+import com.intellij.psi.impl.source.xml.TagNameReference;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.index.XmlNamespaceIndex;
+import com.intellij.xml.index.XmlTagNamesIndex;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class DefaultXmlExtension extends XmlExtension {
+  
+  public boolean isAvailable(final PsiFile file) {
+    return true;
+  }
+
+  @NotNull
+  public List<Pair<String,String>> getAvailableTagNames(@NotNull final XmlFile file, @NotNull final XmlTag context) {
+
+    final Set<String> namespaces = new HashSet<String>(Arrays.asList(context.knownNamespaces()));
+    final List<XmlSchemaProvider> providers = XmlSchemaProvider.getAvailableProviders(file);
+    for (XmlSchemaProvider provider : providers) {
+      namespaces.addAll(provider.getAvailableNamespaces(file, null));
+    }
+    final ArrayList<String> nsInfo = new ArrayList<String>();
+    final String[] names = TagNameReference.getTagNameVariants(context, namespaces, nsInfo);
+    final List<Pair<String, String>> set = new ArrayList<Pair<String,String>>(names.length);
+    final Iterator<String> iterator = nsInfo.iterator();
+    for (String name : names) {
+      final int pos = name.indexOf(':');
+      final String s = pos >= 0 ? name.substring(pos + 1) : name;
+      set.add(Pair.create(s, iterator.next()));
+    }
+    return set;
+  }
+
+  @NotNull
+  public Set<String> getNamespacesByTagName(@NotNull final String tagName, @NotNull final XmlFile context) {
+    final List<XmlSchemaProvider> providers = XmlSchemaProvider.getAvailableProviders(context);
+
+    HashSet<String> set = new HashSet<String>();
+    for (XmlSchemaProvider provider : providers) {
+      set.addAll(provider.getAvailableNamespaces(context, tagName));
+    }
+    return set;
+  }
+
+  public static Set<String> filterNamespaces(final Set<String> namespaces, final String tagName, final XmlFile context) {
+    if (tagName == null) {
+      return namespaces;
+    }
+    final HashSet<String> set = new HashSet<String>();
+    for (String namespace : namespaces) {
+      final XmlFile xmlFile = XmlUtil.findNamespace(context, namespace);
+      if (xmlFile != null) {
+        final XmlDocument document = xmlFile.getDocument();
+        assert document != null;
+        final XmlNSDescriptor nsDescriptor = (XmlNSDescriptor)document.getMetaData();
+        assert nsDescriptor != null;
+        final XmlElementDescriptor[] elementDescriptors = nsDescriptor.getRootElementsDescriptors(document);
+        for (XmlElementDescriptor elementDescriptor : elementDescriptors) {
+          if (hasTag(elementDescriptor, tagName, new HashSet<XmlElementDescriptor>())) {
+            set.add(namespace);
+            break;
+          }
+        }
+      }
+    }
+    return set;
+  }
+
+  private static boolean hasTag(XmlElementDescriptor elementDescriptor, String tagName, Set<XmlElementDescriptor> visited) {
+    final String name = elementDescriptor.getDefaultName();
+    if (name.equals(tagName)) {
+      return true;
+    }
+    for (XmlElementDescriptor descriptor : elementDescriptor.getElementsDescriptors(null)) {
+      if (!visited.contains(elementDescriptor)) {
+        visited.add(elementDescriptor);
+        if (hasTag(descriptor, tagName, visited)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  @NotNull
+  public Set<String> guessUnboundNamespaces(@NotNull final PsiElement element, @NotNull XmlFile file) {
+    if (!(element instanceof XmlTag)) {
+      return Collections.emptySet();
+    }
+    final XmlTag tag = (XmlTag)element;
+    final String name = tag.getLocalName();
+    final Set<String> byTagName = getNamespacesByTagName(name, file);
+    if (!byTagName.isEmpty()) {
+      Set<String> filtered = new HashSet<String>(byTagName);
+      filtered.removeAll(Arrays.asList(tag.knownNamespaces()));
+      return filtered;
+    }
+    final Set<String> set = guessNamespace(file, name);
+    set.removeAll(Arrays.asList(tag.knownNamespaces()));
+
+    final XmlTag parentTag = tag.getParentTag();
+    ns: for (Iterator<String> i = set.iterator(); i.hasNext();) {
+      final String s = i.next();
+      final Collection<XmlFile> namespaces = XmlUtil.findNSFilesByURI(s, element.getProject(), ModuleUtilCore.findModuleForPsiElement(file));
+      for (XmlFile namespace : namespaces) {
+        final XmlDocument document = namespace.getDocument();
+        assert document != null;
+        final XmlNSDescriptor nsDescriptor = (XmlNSDescriptor)document.getMetaData();
+        assert nsDescriptor != null;
+        if (parentTag != null) {
+          continue ns;
+        }
+        final XmlElementDescriptor[] descriptors = nsDescriptor.getRootElementsDescriptors(document);
+        for (XmlElementDescriptor descriptor : descriptors) {
+          if (descriptor == null) {
+            LOG.error(nsDescriptor + " returned null element for getRootElementsDescriptors() array");
+          }
+          if (descriptor.getName().equals(name)) {
+            continue ns;
+          }
+        }
+      }
+      i.remove();
+    }
+    return set;
+  }
+
+  public void insertNamespaceDeclaration(@NotNull final XmlFile file,
+                                         @Nullable final Editor editor,
+                                         @NotNull final Set<String> possibleNamespaces,
+                                         @Nullable String nsPrefix,
+                                         @Nullable final Runner<String, IncorrectOperationException> runAfter) throws IncorrectOperationException {
+
+    final String namespace = possibleNamespaces.iterator().next();
+
+    final Project project = file.getProject();
+    final XmlDocument document = file.getDocument();
+    assert document != null;
+    final XmlTag rootTag = document.getRootTag();
+    assert rootTag != null;
+    final XmlAttribute[] attributes = rootTag.getAttributes();
+    XmlAttribute anchor = null;
+    for (XmlAttribute attribute : attributes) {
+      final XmlAttributeDescriptor descriptor = attribute.getDescriptor();
+      if (attribute.isNamespaceDeclaration() || (descriptor != null && descriptor.isRequired())) {
+        anchor = attribute;
+      } else {
+        break;
+      }
+    }
+    
+    final List<XmlSchemaProvider> providers = XmlSchemaProvider.getAvailableProviders(file);
+    String prefix = nsPrefix;
+    if (prefix == null) {
+      for (XmlSchemaProvider provider : providers) {
+        prefix = provider.getDefaultPrefix(namespace, file);
+        if (prefix != null) {
+          break;
+        }
+      }
+    }
+    if (prefix == null) {
+      prefix = "";
+    }
+    final XmlElementFactory elementFactory = XmlElementFactory.getInstance(project);
+
+    @NonNls final String qname = "xmlns" + (prefix.length() > 0 ? ":"+ prefix :"");
+    final XmlAttribute attribute = elementFactory.createXmlAttribute(qname, namespace);
+    if (anchor == null) {
+      rootTag.add(attribute);
+    } else {
+      rootTag.addAfter(attribute, anchor);
+    }
+
+    String location = null;
+    if (namespace.length() > 0) {
+      for (XmlSchemaProvider provider : providers) {
+        Set<String> locations = provider.getLocations(namespace, file);
+        if (locations != null && !locations.isEmpty()) {
+          location = locations.iterator().next();
+        }
+      }
+    }
+
+    if (location != null) {
+      XmlAttribute xmlAttribute = rootTag.getAttribute("xsi:schemaLocation");
+      final String pair = namespace + " " + location;
+      if (xmlAttribute == null) {
+        xmlAttribute = elementFactory.createXmlAttribute("xsi:schemaLocation", pair);
+        rootTag.add(xmlAttribute);
+      } else {
+        final String value = xmlAttribute.getValue();
+        if (!value.contains(namespace)) {
+          if (StringUtil.isEmptyOrSpaces(value)) {
+            xmlAttribute.setValue(pair);
+          } else {
+            xmlAttribute.setValue(value.trim() + " " + pair);
+          }
+        }
+      }
+    }
+    XmlUtil.reformatTagStart(rootTag);
+    
+    if (editor != null && namespace.length() == 0) {
+      final XmlAttribute xmlAttribute = rootTag.getAttribute(qname);
+      if (xmlAttribute != null) {
+        final XmlAttributeValue value = xmlAttribute.getValueElement();
+        assert value != null;
+        final int startOffset = value.getTextOffset();
+        editor.getCaretModel().moveToOffset(startOffset);
+        editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+      }
+    }
+    if (runAfter != null) {
+      runAfter.run(prefix);
+    }
+  }
+
+  public SchemaPrefix getPrefixDeclaration(final XmlTag context, String namespacePrefix) {
+    @NonNls String nsDeclarationAttrName = null;
+    for(XmlTag t = context; t != null; t = t.getParentTag()) {
+      if (t.hasNamespaceDeclarations()) {
+        if (nsDeclarationAttrName == null) nsDeclarationAttrName = namespacePrefix.length() > 0 ? "xmlns:"+namespacePrefix:"xmlns";
+        XmlAttribute attribute = t.getAttribute(nsDeclarationAttrName);
+        if (attribute != null) {
+          final String attrPrefix = attribute.getNamespacePrefix();
+          final TextRange textRange = TextRange.from(attrPrefix.length() + 1, namespacePrefix.length());
+          return new SchemaPrefix(attribute, textRange, namespacePrefix);
+        }
+      }
+    }
+    return null;
+  }
+
+  private static Set<String> guessNamespace(final PsiFile file, String tagName) {
+    final Project project = file.getProject();
+    final Collection<VirtualFile> files = XmlTagNamesIndex.getFilesByTagName(tagName, project);
+    final Set<String> possibleUris = new LinkedHashSet<String>(files.size());
+    for (VirtualFile virtualFile : files) {
+      final String namespace = XmlNamespaceIndex.getNamespace(virtualFile, project, file);
+      if (namespace != null) {
+        possibleUris.add(namespace);
+      }
+    }
+    return possibleUris;
+  }
+
+  private final static Logger LOG = Logger.getInstance(DefaultXmlExtension.class);
+}
diff --git a/xml/impl/src/com/intellij/xml/Html5SchemaProvider.java b/xml/impl/src/com/intellij/xml/Html5SchemaProvider.java
new file mode 100644
index 0000000..218498b
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/Html5SchemaProvider.java
@@ -0,0 +1,70 @@
+package com.intellij.xml;
+
+import com.intellij.javaee.ExternalResourceManagerImpl;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.util.io.URLUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.net.URL;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class Html5SchemaProvider {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.Html5SchemaProvider");
+
+  private static final ExtensionPointName<Html5SchemaProvider> EP_NAME = ExtensionPointName.create("com.intellij.xml.html5SchemaProvider");
+
+  public static final String HTML5_SCHEMA_LOCATION;
+  public static final String XHTML5_SCHEMA_LOCATION;
+
+  @NotNull
+  public abstract URL getHtmlSchemaLocation();
+
+  @NotNull
+  public abstract URL getXhtmlSchemaLocation();
+
+  static {
+    final Html5SchemaProvider[] providers = EP_NAME.getExtensions();
+    final URL htmlSchemaLocationURL;
+    final URL xhtmlSchemaLocationURL;
+
+    LOG.assertTrue(providers.length > 0, "RelaxNG based schema for HTML5 is not supported. Old XSD schema will be used");
+
+    if (providers.length > 1) {
+      LOG.error("More than one HTML5 schema providers found: " + getClassesListString(providers));
+    }
+
+    if (providers.length > 0) {
+      htmlSchemaLocationURL = providers[0].getHtmlSchemaLocation();
+      xhtmlSchemaLocationURL = providers[0].getXhtmlSchemaLocation();
+    }
+    else {
+      htmlSchemaLocationURL = Html5SchemaProvider.class.getResource(ExternalResourceManagerImpl.STANDARD_SCHEMAS + "html5/xhtml5.xsd");
+      xhtmlSchemaLocationURL = htmlSchemaLocationURL;
+    }
+
+    HTML5_SCHEMA_LOCATION = VfsUtilCore.urlToPath(VfsUtil.fixURLforIDEA(
+      URLUtil.unescapePercentSequences(htmlSchemaLocationURL.toExternalForm())));
+    LOG.info("HTML5_SCHEMA_LOCATION = " + HTML5_SCHEMA_LOCATION);
+
+    XHTML5_SCHEMA_LOCATION = VfsUtilCore.urlToPath(VfsUtil.fixURLforIDEA(
+      URLUtil.unescapePercentSequences(xhtmlSchemaLocationURL.toExternalForm())));
+    LOG.info("XHTML5_SCHEMA_LOCATION = " + XHTML5_SCHEMA_LOCATION);
+  }
+
+  private static <T> String getClassesListString(T[] a) {
+    final StringBuilder builder = new StringBuilder();
+    for (int i = 0, n = a.length; i < n; i++) {
+      T element = a[i];
+      builder.append(element != null ? element.getClass().getName() : "NULL");
+      if (i < n - 1) {
+        builder.append(", ");
+      }
+    }
+    return builder.toString();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/XmlAttributeDescriptorsProvider.java b/xml/impl/src/com/intellij/xml/XmlAttributeDescriptorsProvider.java
new file mode 100644
index 0000000..f235c0e
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/XmlAttributeDescriptorsProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public interface XmlAttributeDescriptorsProvider {
+
+  ExtensionPointName<XmlAttributeDescriptorsProvider> EP_NAME = new ExtensionPointName<XmlAttributeDescriptorsProvider>("com.intellij.xml.attributeDescriptorsProvider");
+
+  XmlAttributeDescriptor[] getAttributeDescriptors(final XmlTag context);
+
+  @Nullable
+  XmlAttributeDescriptor getAttributeDescriptor(final String attributeName, final XmlTag context);
+
+}
diff --git a/xml/impl/src/com/intellij/xml/XmlChangeLocalityDetector.java b/xml/impl/src/com/intellij/xml/XmlChangeLocalityDetector.java
new file mode 100644
index 0000000..fb65aa5
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/XmlChangeLocalityDetector.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml;
+
+import com.intellij.codeInsight.daemon.ChangeLocalityDetector;
+import com.intellij.codeInspection.DefaultXmlSuppressionProvider;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.PsiComment;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+public class XmlChangeLocalityDetector implements ChangeLocalityDetector {
+  @Override
+  public PsiElement getChangeHighlightingDirtyScopeFor(@NotNull PsiElement changedElement) {
+    // rehighlight everything when inspection suppress comment changed
+    if (changedElement.getLanguage() instanceof XMLLanguage
+        && changedElement instanceof PsiComment
+        && changedElement.getText().contains(DefaultXmlSuppressionProvider.SUPPRESS_MARK)) {
+      return changedElement.getContainingFile();
+    }
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/XmlExtension.java b/xml/impl/src/com/intellij/xml/XmlExtension.java
new file mode 100644
index 0000000..1adcb3b
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/XmlExtension.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml;
+
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
+import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.xml.SchemaPrefix;
+import com.intellij.psi.impl.source.xml.TagNameReference;
+import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public abstract class XmlExtension {
+  private static final ExtensionPointName<XmlExtension> EP_NAME = new ExtensionPointName<XmlExtension>("com.intellij.xml.xmlExtension");
+
+  public static final XmlExtension DEFAULT_EXTENSION = new DefaultXmlExtension();
+
+  public static XmlExtension getExtension(PsiFile file) {
+    for (XmlExtension extension : Extensions.getExtensions(EP_NAME)) {
+      if (extension.isAvailable(file)) {
+        return extension;
+      }
+    }
+    return DEFAULT_EXTENSION;
+  }
+
+  @SuppressWarnings("ConstantConditions")
+  public static XmlExtension getExtensionByElement(PsiElement element) {
+    final PsiFile psiFile = element.getContainingFile();
+    if (psiFile != null) {
+      return getExtension(psiFile);
+    }
+    return null;
+  }
+
+  public abstract boolean isAvailable(PsiFile file);
+
+  @NotNull
+  public abstract List<Pair<String,String>> getAvailableTagNames(@NotNull final XmlFile file, @NotNull final XmlTag context);
+
+  @NotNull
+  public abstract Set<String> getNamespacesByTagName(@NotNull final String tagName, @NotNull final XmlFile context);
+  @NotNull
+  public abstract Set<String> guessUnboundNamespaces(@NotNull PsiElement element, final XmlFile file);
+
+  @Nullable
+  public TagNameReference createTagNameReference(final ASTNode nameElement, final boolean startTagFlag) {
+    return new TagNameReference(nameElement, startTagFlag);
+  }
+
+  @Nullable
+  public String[][] getNamespacesFromDocument(final XmlDocument parent, boolean declarationsExist) {
+    return declarationsExist ? null : XmlUtil.getDefaultNamespaces(parent);
+  }
+
+  public interface Runner<P, T extends Throwable> {
+    void run(P param) throws T;
+  }
+
+  public abstract void insertNamespaceDeclaration(@NotNull final XmlFile file,
+                                                    @Nullable final Editor editor,
+                                                    @NonNls @NotNull final Set<String> possibleNamespaces,
+                                                    @NonNls @Nullable final String nsPrefix,
+                                                    @Nullable Runner<String, IncorrectOperationException> runAfter) throws IncorrectOperationException;
+
+  @Nullable
+  public String getNamespacePrefix(PsiElement element) {
+    final PsiElement tag = element instanceof XmlTag ? element : element.getParent();
+    if (tag instanceof XmlTag) {
+      return ((XmlTag)tag).getNamespacePrefix();
+    } else {
+      return null;
+    }
+  }
+
+  public boolean qualifyWithPrefix(final String namespacePrefix, final PsiElement element, final Document document) throws
+                                                                                                                 IncorrectOperationException {
+    final PsiElement tag = element instanceof XmlTag ? element : element.getParent();
+    if (tag instanceof XmlTag) {
+      final String prefix = ((XmlTag)tag).getNamespacePrefix();
+      if (!prefix.equals(namespacePrefix)) {
+        final String name = namespacePrefix + ":" + ((XmlTag)tag).getLocalName();
+        ((XmlTag)tag).setName(name);
+      }
+      return true;
+    }
+    return false;
+  }
+
+  public String getNamespaceAlias(@NotNull final XmlFile file) {
+    return XmlBundle.message("namespace.alias");
+  }
+
+  public void createAddAttributeFix(@NotNull final XmlAttribute attribute, final HighlightInfo highlightInfo) {
+    final XmlTag tag = attribute.getParent();
+    String namespace = attribute.getNamespace();
+
+    if(StringUtil.isEmptyOrSpaces(namespace)) namespace = tag.getNamespace();
+
+    final XmlNSDescriptor nsDescriptor = tag.getNSDescriptor(namespace, true);
+    if (nsDescriptor instanceof XmlUndefinedElementFixProvider) {
+      final IntentionAction[] actions = ((XmlUndefinedElementFixProvider)nsDescriptor).createFixes(attribute);
+      for (IntentionAction action : actions) {
+        QuickFixAction.registerQuickFixAction(highlightInfo, action);
+      }
+    }
+  }
+
+  public boolean canBeDuplicated(XmlAttribute attribute) {
+    return false;
+  }
+
+  public boolean isRequiredAttributeImplicitlyPresent(XmlTag tag, String attrName) {
+    return false;
+  }
+
+  public HighlightInfoType getHighlightInfoType(XmlFile file) {
+    return HighlightInfoType.ERROR;
+  }
+
+  @Nullable
+  public abstract SchemaPrefix getPrefixDeclaration(final XmlTag context, String namespacePrefix);
+
+  public SearchScope getNsPrefixScope(XmlAttribute declaration) {
+    return new LocalSearchScope(declaration.getParent());
+  }
+
+  public boolean shouldBeHighlightedAsTag(XmlTag tag) {
+    return true;
+  }
+
+  @Nullable
+  public XmlElementDescriptor getElementDescriptor(XmlTag tag, XmlTag contextTag, final XmlElementDescriptor parentDescriptor) {
+    return parentDescriptor.getElementDescriptor(tag, contextTag);
+  }
+
+  @Nullable
+  public XmlNSDescriptor getNSDescriptor(final XmlTag element, final String namespace, final boolean strict) {
+    return element.getNSDescriptor(namespace, strict);  
+  }
+
+  @Nullable
+  public XmlTag getParentTagForNamespace(XmlTag tag, XmlNSDescriptor namespace) {
+    return tag.getParentTag();
+  }
+
+  @Nullable
+  public XmlFile getContainingFile(PsiElement element) {
+    if (element == null) {
+      return null;
+    }
+    final PsiFile psiFile = element.getContainingFile();
+    return psiFile instanceof XmlFile ? (XmlFile)psiFile : null;
+  }
+
+  public XmlNSDescriptor getDescriptorFromDoctype(final XmlFile containingFile, XmlNSDescriptor descr) {
+    return descr;
+  }
+
+  public boolean hasDynamicComponents(final PsiElement element) {
+    return false;
+  }
+
+  public boolean isIndirectSyntax(final XmlAttributeDescriptor descriptor) {
+    return false;
+  }
+
+  public boolean isCustomTagAllowed(final XmlTag tag) {
+    return false;
+  }
+
+  public boolean needWhitespaceBeforeAttribute() {
+    return true;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/XmlFileTypeFactory.java b/xml/impl/src/com/intellij/xml/XmlFileTypeFactory.java
new file mode 100644
index 0000000..fa5d933
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/XmlFileTypeFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml;
+
+import com.intellij.codeInsight.editorActions.TypedHandler;
+import com.intellij.ide.highlighter.DTDFileType;
+import com.intellij.ide.highlighter.HtmlFileType;
+import com.intellij.ide.highlighter.XHtmlFileType;
+import com.intellij.ide.highlighter.XmlFileType;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.fileTypes.FileTypeConsumer;
+import com.intellij.openapi.fileTypes.FileTypeFactory;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class XmlFileTypeFactory extends FileTypeFactory {
+  public void createFileTypes(@NotNull final FileTypeConsumer consumer) {
+    consumer.consume(HtmlFileType.INSTANCE, "html;htm;sht;shtm;shtml");
+    consumer.consume(XHtmlFileType.INSTANCE, "xhtml");
+    consumer.consume(DTDFileType.INSTANCE, "dtd;ent;mod;elt");
+
+    consumer.consume(XmlFileType.INSTANCE, "xml;xsd;tld;xsl;jnlp;wsdl;jhm;ant;xul;xslt;rng;fxml");
+    TypedHandler.registerBaseLanguageQuoteHandler(XMLLanguage.class, TypedHandler.getQuoteHandlerForType(XmlFileType.INSTANCE));
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/XmlUndefinedElementFixProvider.java b/xml/impl/src/com/intellij/xml/XmlUndefinedElementFixProvider.java
new file mode 100644
index 0000000..097602d
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/XmlUndefinedElementFixProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.psi.xml.XmlElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public interface XmlUndefinedElementFixProvider {
+
+  @NotNull IntentionAction[] createFixes(final @NotNull XmlElement element);
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/GenerateXmlTagAction.java b/xml/impl/src/com/intellij/xml/actions/GenerateXmlTagAction.java
new file mode 100644
index 0000000..5a2b4ea
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/GenerateXmlTagAction.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.actions.SimpleCodeInsightAction;
+import com.intellij.codeInsight.hint.HintManager;
+import com.intellij.codeInsight.lookup.impl.LookupCellRenderer;
+import com.intellij.codeInsight.template.TemplateBuilder;
+import com.intellij.codeInsight.template.TemplateBuilderFactory;
+import com.intellij.codeInsight.template.impl.MacroCallNode;
+import com.intellij.codeInsight.template.macro.CompleteMacro;
+import com.intellij.codeInsight.template.macro.CompleteSmartMacro;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.colors.EditorFontType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.impl.source.tree.Factory;
+import com.intellij.psi.impl.source.tree.LeafElement;
+import com.intellij.psi.impl.source.xml.XmlContentDFA;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.refactoring.util.CommonRefactoringUtil;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+import com.intellij.xml.impl.schema.XmlElementDescriptorImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class GenerateXmlTagAction extends SimpleCodeInsightAction {
+
+  public static final ThreadLocal<String> TEST_THREAD_LOCAL = new ThreadLocal<String>();
+  private final static Logger LOG = Logger.getInstance(GenerateXmlTagAction.class);
+
+  @Override
+  public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile file) {
+    if (!CodeInsightUtilBase.prepareEditorForWrite(editor)) return;
+    try {
+      final XmlTag contextTag = getContextTag(editor, file);
+      if (contextTag == null) {
+        throw new CommonRefactoringUtil.RefactoringErrorHintException("Caret should be positioned inside a tag");
+      }
+      XmlElementDescriptor currentTagDescriptor = contextTag.getDescriptor();
+      final XmlElementDescriptor[] descriptors = currentTagDescriptor.getElementsDescriptors(contextTag);
+      Arrays.sort(descriptors, new Comparator<XmlElementDescriptor>() {
+        @Override
+        public int compare(XmlElementDescriptor o1, XmlElementDescriptor o2) {
+          return o1.getName().compareTo(o2.getName());
+        }
+      });
+      final JBList list = new JBList(descriptors);
+      list.setCellRenderer(new MyListCellRenderer());
+      Runnable runnable = new Runnable() {
+        @Override
+        public void run() {
+          final XmlElementDescriptor selected = (XmlElementDescriptor)list.getSelectedValue();
+          new WriteCommandAction.Simple(project, "Generate XML Tag", file) {
+            @Override
+            protected void run() {
+              if (selected == null) return;
+              XmlTag newTag = createTag(contextTag, selected);
+
+              PsiElement anchor = getAnchor(contextTag, editor, selected);
+              if (anchor == null) { // insert it in the cursor position
+                int offset = editor.getCaretModel().getOffset();
+                Document document = editor.getDocument();
+                document.insertString(offset, newTag.getText());
+                PsiDocumentManager.getInstance(getProject()).commitDocument(document);
+                newTag = PsiTreeUtil.getParentOfType(file.findElementAt(offset + 1), XmlTag.class, false);
+              }
+              else {
+                newTag = (XmlTag)contextTag.addAfter(newTag, anchor);
+              }
+              generateTag(newTag);
+            }
+          }.execute();
+        }
+      };
+      if (ApplicationManager.getApplication().isUnitTestMode()) {
+        XmlElementDescriptor descriptor = ContainerUtil.find(descriptors, new Condition<XmlElementDescriptor>() {
+          @Override
+          public boolean value(XmlElementDescriptor xmlElementDescriptor) {
+            return xmlElementDescriptor.getName().equals(TEST_THREAD_LOCAL.get());
+          }
+        });
+        list.setSelectedValue(descriptor, false);
+        runnable.run();
+      }
+      else {
+        JBPopupFactory.getInstance().createListPopupBuilder(list)
+          .setTitle("Choose Tag Name")
+          .setItemChoosenCallback(runnable)
+          .setFilteringEnabled(new Function<Object, String>() {
+            @Override
+            public String fun(Object o) {
+              return ((XmlElementDescriptor)o).getName();
+            }
+          })
+          .createPopup()
+          .showInBestPositionFor(editor);
+      }
+    }
+    catch (CommonRefactoringUtil.RefactoringErrorHintException e) {
+      HintManager.getInstance().showErrorHint(editor, e.getMessage());
+    }
+  }
+
+  @Nullable
+  private static XmlTag getAnchor(@NotNull XmlTag contextTag, Editor editor, XmlElementDescriptor selected) {
+    XmlContentDFA contentDFA = XmlContentDFA.getContentDFA(contextTag);
+    int offset = editor.getCaretModel().getOffset();
+    if (contentDFA == null) {
+      return null;
+    }
+    XmlTag anchor = null;
+    boolean previousPositionIsPossible = true;
+    for (XmlTag subTag : contextTag.getSubTags()) {
+      if (contentDFA.getPossibleElements().contains(selected)) {
+        if (subTag.getTextOffset() > offset) {
+          break;
+        }
+        anchor = subTag;
+        previousPositionIsPossible = true;
+      }
+      else {
+        previousPositionIsPossible = false;
+      }
+      contentDFA.transition(subTag);
+    }
+    return previousPositionIsPossible ? null : anchor;
+  }
+
+  public static void generateTag(XmlTag newTag) {
+    generateRaw(newTag);
+    final XmlTag restored = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(newTag);
+    if (restored == null) {
+      LOG.error("Could not restore tag: " + newTag.getText());
+    }
+    TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(restored);
+    replaceElements(restored, builder);
+    builder.run();
+  }
+
+  private static void generateRaw(final XmlTag newTag) {
+    XmlElementDescriptor selected = newTag.getDescriptor();
+    if (selected == null) return;
+    switch (selected.getContentType()) {
+      case XmlElementDescriptor.CONTENT_TYPE_EMPTY:
+        newTag.collapseIfEmpty();
+        ASTNode node = newTag.getNode();
+        assert node != null;
+        ASTNode elementEnd = node.findChildByType(XmlTokenType.XML_EMPTY_ELEMENT_END);
+        if (elementEnd == null) {
+          LeafElement emptyTagEnd = Factory.createSingleLeafElement(XmlTokenType.XML_EMPTY_ELEMENT_END, "/>", 0, 2, null, newTag.getManager());
+          node.addChild(emptyTagEnd);
+        }
+        break;
+      case XmlElementDescriptor.CONTENT_TYPE_MIXED:
+        newTag.getValue().setText("");
+    }
+    for (XmlAttributeDescriptor descriptor : selected.getAttributesDescriptors(newTag)) {
+      if (descriptor.isRequired()) {
+        newTag.setAttribute(descriptor.getName(), "");
+      }
+    }
+    List<XmlElementDescriptor> tags = getRequiredSubTags(selected);
+    for (XmlElementDescriptor descriptor : tags) {
+      if (descriptor == null) {
+        XmlTag tag = XmlElementFactory.getInstance(newTag.getProject()).createTagFromText("<", newTag.getLanguage());
+        newTag.addSubTag(tag, false);
+      }
+      else {
+        XmlTag subTag = newTag.addSubTag(createTag(newTag, descriptor), false);
+        generateRaw(subTag);
+      }
+    }
+  }
+
+  public static List<XmlElementDescriptor> getRequiredSubTags(XmlElementDescriptor selected) {
+    XmlElementsGroup topGroup = selected.getTopGroup();
+    if (topGroup == null) return Collections.emptyList();
+    return computeRequiredSubTags(topGroup);
+  }
+
+  private static void replaceElements(XmlTag tag, TemplateBuilder builder) {
+    for (XmlAttribute attribute : tag.getAttributes()) {
+      XmlAttributeValue value = attribute.getValueElement();
+      if (value != null) {
+        builder.replaceElement(value, TextRange.from(1, 0), new MacroCallNode(new CompleteMacro()));
+      }
+    }
+    if ("<".equals(tag.getText())) {
+      builder.replaceElement(tag, TextRange.from(1, 0), new MacroCallNode(new CompleteSmartMacro()));
+    }
+    else if (tag.getSubTags().length == 0) {
+      int i = tag.getText().indexOf("></");
+      if (i > 0) {
+        builder.replaceElement(tag, TextRange.from(i + 1, 0), new MacroCallNode(new CompleteMacro()));
+      }
+    }
+    for (XmlTag subTag : tag.getSubTags()) {
+      replaceElements(subTag, builder);
+    }
+  }
+
+  private static XmlTag createTag(@NotNull XmlTag contextTag, @NotNull XmlElementDescriptor descriptor) {
+    String namespace = getNamespace(descriptor);
+    XmlTag tag = contextTag.createChildTag(descriptor.getName(), namespace, null, false);
+    PsiElement lastChild = tag.getLastChild();
+    assert lastChild != null;
+    lastChild.delete(); // remove XML_EMPTY_ELEMENT_END
+    return tag;
+  }
+
+  private static String getNamespace(XmlElementDescriptor descriptor) {
+    return descriptor instanceof XmlElementDescriptorImpl ? ((XmlElementDescriptorImpl)descriptor).getNamespace() : "";
+  }
+
+  @Nullable
+  private static XmlTag getContextTag(Editor editor, PsiFile file) {
+    PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+    XmlTag tag = null;
+    if (element != null) {
+      tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
+    }
+    if (tag == null) {
+      tag = ((XmlFile)file).getRootTag();
+    }
+    return tag;
+  }
+
+  private static List<XmlElementDescriptor> computeRequiredSubTags(XmlElementsGroup group) {
+
+    if (group.getMinOccurs() < 1) return Collections.emptyList();
+    switch (group.getGroupType()) {
+      case LEAF:
+        XmlElementDescriptor descriptor = group.getLeafDescriptor();
+        return descriptor == null ? Collections.<XmlElementDescriptor>emptyList() : Collections.singletonList(descriptor);
+      case CHOICE:
+        LinkedHashSet<XmlElementDescriptor> set = null;
+        for (XmlElementsGroup subGroup : group.getSubGroups()) {
+          List<XmlElementDescriptor> descriptors = computeRequiredSubTags(subGroup);
+          if (set == null) {
+            set = new LinkedHashSet<XmlElementDescriptor>(descriptors);
+          }
+          else {
+            set.retainAll(descriptors);
+          }
+        }
+        if (set == null || set.isEmpty()) {
+          return Collections.singletonList(null); // placeholder for smart completion
+        }
+        return new ArrayList<XmlElementDescriptor>(set);
+
+      default:
+        ArrayList<XmlElementDescriptor> list = new ArrayList<XmlElementDescriptor>();
+        for (XmlElementsGroup subGroup : group.getSubGroups()) {
+          list.addAll(computeRequiredSubTags(subGroup));
+        }
+        return list;
+    }
+  }
+
+  @Override
+  protected boolean isValidForFile(Project project, Editor editor, PsiFile file) {
+    if (!(file instanceof XmlFile)) return false;
+    XmlTag contextTag = getContextTag(editor, file);
+    return contextTag != null && contextTag.getDescriptor() != null;
+  }
+
+  @Override
+  public boolean startInWriteAction() {
+    return false;
+  }
+
+  private static class MyListCellRenderer implements ListCellRenderer {
+    private final JPanel myPanel;
+    private final JLabel myNameLabel;
+    private final JLabel myNSLabel;
+
+    public MyListCellRenderer() {
+      myPanel = new JPanel(new BorderLayout());
+      myPanel.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
+      myNameLabel = new JLabel();
+
+      myPanel.add(myNameLabel, BorderLayout.WEST);
+      myPanel.add(new JLabel("     "));
+      myNSLabel = new JLabel();
+      myPanel.add(myNSLabel, BorderLayout.EAST);
+
+      EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
+      Font font = scheme.getFont(EditorFontType.PLAIN);
+      myNameLabel.setFont(font);
+      myNSLabel.setFont(font);
+    }
+
+    @Override
+    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+
+      XmlElementDescriptor descriptor = (XmlElementDescriptor)value;
+      Color backgroundColor = isSelected ? list.getSelectionBackground() : list.getBackground();
+
+      myNameLabel.setText(descriptor.getName());
+      myNameLabel.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
+      myPanel.setBackground(backgroundColor);
+
+      myNSLabel.setText(getNamespace(descriptor));
+      myNSLabel.setForeground(LookupCellRenderer.getGrayedForeground(isSelected));
+      myNSLabel.setBackground(backgroundColor);
+
+      return myPanel;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/ValidateXmlAction.java b/xml/impl/src/com/intellij/xml/actions/ValidateXmlAction.java
new file mode 100644
index 0000000..da0454b
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/ValidateXmlAction.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions;
+
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author mike
+ */
+public class ValidateXmlAction extends AnAction {
+  private static final Key<String> runningValidationKey = Key.create("xml.running.validation.indicator");
+
+  public ValidateXmlAction() {
+  }
+
+  private ValidateXmlActionHandler getHandler(final @NotNull PsiFile file) {
+    ValidateXmlActionHandler handler = new ValidateXmlActionHandler(true);
+    handler.setErrorReporter(
+      handler.new StdErrorReporter(
+        file.getProject(),
+        new Runnable() {
+          public void run() {
+            doRunAction(file);
+          }
+        }
+      )
+    );
+    return handler;
+  }
+
+  public void actionPerformed(AnActionEvent e) {
+    final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(e.getDataContext());
+    if (psiFile != null) {
+      doRunAction(psiFile);
+    }
+  }
+
+  private void doRunAction(final @NotNull PsiFile psiFile) {
+
+    CommandProcessor.getInstance().executeCommand(psiFile.getProject(), new Runnable(){
+        public void run(){
+          final Runnable action = new Runnable() {
+            public void run() {
+              try {
+                psiFile.putUserData(runningValidationKey, "");
+                PsiDocumentManager.getInstance(psiFile.getProject()).commitAllDocuments();
+
+                getHandler(psiFile).doValidate((XmlFile)psiFile);
+              }
+              finally {
+                psiFile.putUserData(runningValidationKey, null);
+              }
+            }
+          };
+          ApplicationManager.getApplication().runWriteAction(action);
+        }
+      },
+      getCommandName(),
+      null
+    );
+  }
+
+  private String getCommandName(){
+    String text = getTemplatePresentation().getText();
+    return text != null ? text : "";
+  }
+
+  public void update(AnActionEvent event) {
+    super.update(event);
+
+    Presentation presentation = event.getPresentation();
+    PsiElement psiElement = LangDataKeys.PSI_FILE.getData(event.getDataContext());
+
+    boolean flag = psiElement instanceof XmlFile;
+    presentation.setVisible(flag);
+    boolean value = psiElement instanceof XmlFile;
+
+    if (value) {
+      final PsiFile containingFile = psiElement.getContainingFile();
+
+      if (containingFile!=null &&
+          (containingFile.getFileType() == StdFileTypes.XML ||
+           containingFile.getFileType() == StdFileTypes.XHTML
+          )) {
+        value = containingFile.getUserData(runningValidationKey) == null;
+      } else {
+        value = false;
+      }
+    }
+
+    presentation.setEnabled(value);
+    if (ActionPlaces.isPopupPlace(event.getPlace())) {
+      presentation.setVisible(value);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/ValidateXmlActionHandler.java b/xml/impl/src/com/intellij/xml/actions/ValidateXmlActionHandler.java
new file mode 100644
index 0000000..aa7a8ae
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/ValidateXmlActionHandler.java
@@ -0,0 +1,620 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions;
+
+import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel;
+import com.intellij.javaee.UriUtil;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.ToolWindowId;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.xml.*;
+import com.intellij.ui.content.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.ErrorTreeView;
+import com.intellij.util.ui.MessageCategory;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.util.XmlResourceResolver;
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.jaxp.JAXPConstants;
+import org.apache.xerces.jaxp.SAXParserFactoryImpl;
+import org.apache.xerces.util.XMLGrammarPoolImpl;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.swing.*;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.FileNotFoundException;
+import java.io.StringReader;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.Future;
+
+/**
+ * @author Mike
+ */
+public class ValidateXmlActionHandler {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.actions.ValidateXmlAction");
+  private static final Key<NewErrorTreeViewPanel> KEY = Key.create("ValidateXmlAction.KEY");
+  @NonNls private static final String SCHEMA_FULL_CHECKING_FEATURE_ID = "http://apache.org/xml/features/validation/schema-full-checking";
+  private static final String GRAMMAR_FEATURE_ID = Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
+
+  private static final Key<XMLGrammarPool> GRAMMAR_POOL_KEY = Key.create("GrammarPoolKey");
+  private static final Key<Long> GRAMMAR_POOL_TIME_STAMP_KEY = Key.create("GrammarPoolTimeStampKey");
+  private static final Key<VirtualFile[]> DEPENDENT_FILES_KEY = Key.create("GrammarPoolFilesKey");
+  private static final Key<String[]> KNOWN_NAMESPACES_KEY = Key.create("KnownNamespacesKey");
+
+  private Project myProject;
+  private XmlFile myFile;
+  private ErrorReporter myErrorReporter;
+  private SAXParser myParser;
+  private XmlResourceResolver myXmlResourceResolver;
+  private final boolean myForceChecking;
+  @NonNls
+  private static final String ENTITY_RESOLVER_PROPERTY_NAME = "http://apache.org/xml/properties/internal/entity-resolver";
+
+  public ValidateXmlActionHandler(boolean _forceChecking) {
+    myForceChecking = _forceChecking;
+  }
+
+  public void setErrorReporter(ErrorReporter errorReporter) {
+    myErrorReporter = errorReporter;
+  }
+
+  public VirtualFile getFile(String publicId, String systemId) {
+    if (publicId == null) {
+      if (systemId != null) {
+        final String path = myXmlResourceResolver.getPathByPublicId(systemId);
+        if (path != null) return UriUtil.findRelativeFile(path,null);
+        final PsiFile file = myXmlResourceResolver.resolve(null, systemId);
+        if (file != null) return file.getVirtualFile();
+      }
+      return myFile.getVirtualFile();
+    }
+    final String path = myXmlResourceResolver.getPathByPublicId(publicId);
+    if (path != null) return UriUtil.findRelativeFile(path,null);
+    return null;
+  }
+
+  public abstract class ErrorReporter {
+    protected final Set<String> ourErrorsSet = new HashSet<String>();
+    public abstract void processError(SAXParseException ex,boolean warning);
+
+    public boolean filterValidationException(Exception ex) {
+      if (ex instanceof ProcessCanceledException) throw (ProcessCanceledException)ex;
+      if (ex instanceof XmlResourceResolver.IgnoredResourceException) throw (XmlResourceResolver.IgnoredResourceException)ex;
+
+      if (ex instanceof FileNotFoundException ||
+            ex instanceof MalformedURLException ||
+            ex instanceof NoRouteToHostException ||
+            ex instanceof SocketTimeoutException ||
+            ex instanceof UnknownHostException ||
+            ex instanceof ConnectException
+            ) {
+        // do not log problems caused by malformed and/or ignored external resources
+        return true;
+      }
+
+      if (ex instanceof NullPointerException) {
+        return true; // workaround for NPE at org.apache.xerces.impl.dtd.XMLDTDProcessor.checkDeclaredElements
+      }
+
+      return false;
+    }
+
+    public void startProcessing() {
+      doParse();
+    }
+
+    public boolean isStopOnUndeclaredResource() {
+      return false;
+    }
+
+    public boolean isUniqueProblem(final SAXParseException e) {
+      String error = buildMessageString(e);
+      if (ourErrorsSet.contains(error)) return false;
+      ourErrorsSet.add(error);
+      return true;
+    }
+  }
+
+  private String buildMessageString(SAXParseException ex) {
+    String msg = "(" + ex.getLineNumber() + ":" + ex.getColumnNumber() + ") " + ex.getMessage();
+    final VirtualFile file = getFile(ex.getPublicId(), ex.getSystemId());
+
+    if ( file != null && !file.equals(myFile.getVirtualFile())) {
+      msg = file.getName() + ":" + msg;
+    }
+    return msg;
+  }
+
+  public class TestErrorReporter extends ErrorReporter {
+    private final ArrayList<String> errors = new ArrayList<String>(3);
+
+    public boolean isStopOnUndeclaredResource() {
+      return true;
+    }
+
+    public boolean filterValidationException(final Exception ex) {
+      if (ex instanceof XmlResourceResolver.IgnoredResourceException) throw (XmlResourceResolver.IgnoredResourceException)ex;
+      return errors.add(ex.getMessage());
+    }
+
+    public void processError(SAXParseException ex, boolean warning) {
+      errors.add(buildMessageString(ex));
+    }
+
+    public List<String> getErrors() {
+      return errors;
+    }
+  }
+
+  class StdErrorReporter extends ErrorReporter {
+    private final NewErrorTreeViewPanel myErrorsView;
+    private final String CONTENT_NAME = XmlBundle.message("xml.validate.tab.content.title");
+    private boolean myErrorsDetected = false;
+
+    StdErrorReporter(Project project, Runnable rerunAction) {
+      myErrorsView = new NewErrorTreeViewPanel(project, null, true, true, rerunAction);
+    }
+
+    public void startProcessing() {
+      final Runnable task = new Runnable() {
+        public void run() {
+          try {
+            ApplicationManager.getApplication().runReadAction(new Runnable() {
+              public void run() {
+                StdErrorReporter.super.startProcessing();
+              }
+            });
+
+            SwingUtilities.invokeLater(
+              new Runnable() {
+                  public void run() {
+                    if (!myErrorsDetected) {
+                      SwingUtilities.invokeLater(
+                          new Runnable() {
+                            public void run() {
+                              removeCompileContents(null);
+                              WindowManager.getInstance().getStatusBar(myProject).setInfo(
+                                XmlBundle.message("xml.validate.no.errors.detected.status.message"));
+                            }
+                          }
+                      );
+                    }
+                  }
+                }
+            );
+          }
+          finally {
+            boolean b = Thread.interrupted(); // reset interrupted
+          }
+        }
+      };
+
+      final MyProcessController processController = new MyProcessController();
+      myErrorsView.setProcessController(processController);
+      openMessageView();
+      processController.setFuture( ApplicationManager.getApplication().executeOnPooledThread(task) );
+
+      ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.MESSAGES_WINDOW).activate(null);
+    }
+
+    private void openMessageView() {
+      CommandProcessor commandProcessor = CommandProcessor.getInstance();
+      commandProcessor.executeCommand(
+          myProject, new Runnable() {
+            public void run() {
+              MessageView messageView = MessageView.SERVICE.getInstance(myProject);
+              final Content content = ContentFactory.SERVICE.getInstance().createContent(myErrorsView.getComponent(), CONTENT_NAME, true);
+              content.putUserData(KEY, myErrorsView);
+              messageView.getContentManager().addContent(content);
+              messageView.getContentManager().setSelectedContent(content);
+              messageView.getContentManager().addContentManagerListener(new CloseListener(content, messageView.getContentManager()));
+              removeCompileContents(content);
+              messageView.getContentManager().addContentManagerListener(new MyContentDisposer(content, messageView));
+            }
+          },
+          XmlBundle.message("validate.xml.open.message.view.command.name"),
+          null
+      );
+    }
+    private void removeCompileContents(Content notToRemove) {
+      MessageView messageView = MessageView.SERVICE.getInstance(myProject);
+
+      for (Content content : messageView.getContentManager().getContents()) {
+        if (content.isPinned()) continue;
+        if (CONTENT_NAME.equals(content.getDisplayName()) && content != notToRemove) {
+          ErrorTreeView listErrorView = (ErrorTreeView)content.getComponent();
+          if (listErrorView != null) {
+            if (messageView.getContentManager().removeContent(content, true)) {
+              content.release();
+            }
+          }
+        }
+      }
+    }
+
+    public void processError(final SAXParseException ex, final boolean warning) {
+      if (LOG.isDebugEnabled()) {
+        String error = buildMessageString(ex);
+        LOG.debug("enter: processError(error='" + error + "')");
+      }
+
+      myErrorsDetected = true;
+
+      if (!ApplicationManager.getApplication().isUnitTestMode()) {
+        SwingUtilities.invokeLater(
+            new Runnable() {
+              public void run() {
+                final VirtualFile file = getFile(ex.getPublicId(), ex.getSystemId());
+                myErrorsView.addMessage(
+                    warning ? MessageCategory.WARNING : MessageCategory.ERROR,
+                    new String[]{ex.getLocalizedMessage()},
+                    file,
+                    ex.getLineNumber() - 1,
+                    ex.getColumnNumber() - 1,
+                    null
+                );
+              }
+            }
+        );
+      }
+    }
+
+    private class CloseListener extends ContentManagerAdapter {
+      private Content myContent;
+      private final ContentManager myContentManager;
+
+      public CloseListener(Content content, ContentManager contentManager) {
+        myContent = content;
+        myContentManager = contentManager;
+      }
+
+      public void contentRemoved(ContentManagerEvent event) {
+        if (event.getContent() == myContent) {
+          myErrorsView.stopProcess();
+
+          myContentManager.removeContentManagerListener(this);
+          myContent.release();
+          myContent = null;
+        }
+      }
+
+      public void contentRemoveQuery(ContentManagerEvent event) {
+        if (event.getContent() == myContent) {
+          if (!myErrorsView.isProcessStopped()) {
+            int result = Messages.showYesNoDialog(
+              XmlBundle.message("xml.validate.validation.is.running.terminate.confirmation.text"),
+              XmlBundle.message("xml.validate.validation.is.running.terminate.confirmation.title"),
+                Messages.getQuestionIcon()
+            );
+            if (result != 0) {
+              event.consume();
+            }
+          }
+        }
+      }
+    }
+
+    private class MyProcessController implements NewErrorTreeViewPanel.ProcessController {
+      private Future<?> myFuture;
+
+      public void setFuture(Future<?> future) {
+        myFuture = future;
+      }
+
+      public void stopProcess() {
+        if (myFuture != null) {
+          myFuture.cancel(true);
+        }
+      }
+
+      public boolean isProcessStopped() {
+        return myFuture != null && myFuture.isDone();
+      }
+    }
+  }
+
+  public void doValidate(XmlFile file) {
+    myProject = file.getProject();
+    myFile = file;
+
+    myXmlResourceResolver = new XmlResourceResolver(myFile, myProject, myErrorReporter);
+    myXmlResourceResolver.setStopOnUnDeclaredResource( myErrorReporter.isStopOnUndeclaredResource() );
+
+    try {
+      try {
+        myParser = createParser();
+      }
+      catch (Exception e) {
+        filterAppException(e);
+      }
+
+      if (myParser == null) return;
+
+      myErrorReporter.startProcessing();
+    }
+    catch (XmlResourceResolver.IgnoredResourceException ignore) {
+    }
+    catch (Exception exception) {
+      filterAppException(exception);
+    }
+  }
+
+  private void filterAppException(Exception exception) {
+    if (!myErrorReporter.filterValidationException(exception)) {
+      LOG.error(exception);
+    }
+  }
+
+  private void doParse() {
+    try {
+      myParser.parse(new InputSource(new StringReader(myFile.getText())), new DefaultHandler() {
+        public void warning(SAXParseException e) {
+          if (myErrorReporter.isUniqueProblem(e)) myErrorReporter.processError(e, true);
+        }
+
+        public void error(SAXParseException e) {
+          if (myErrorReporter.isUniqueProblem(e)) myErrorReporter.processError(e, false);
+        }
+
+        public void fatalError(SAXParseException e) {
+          if (myErrorReporter.isUniqueProblem(e)) myErrorReporter.processError(e, false);
+        }
+
+        public InputSource resolveEntity(String publicId, String systemId) {
+          final PsiFile psiFile = myXmlResourceResolver.resolve(null, systemId);
+          if (psiFile == null) return null;
+          return new InputSource(new StringReader(psiFile.getText()));
+        }
+
+        public void startDocument() throws SAXException {
+          super.startDocument();
+          myParser.setProperty(
+            ENTITY_RESOLVER_PROPERTY_NAME,
+            myXmlResourceResolver
+          );
+        }
+      });
+
+      final String[] resourcePaths = myXmlResourceResolver.getResourcePaths();
+      if (resourcePaths.length > 0) { // if caches are used
+        final VirtualFile[] files = new VirtualFile[resourcePaths.length];
+        for (int i = 0; i < resourcePaths.length; ++i) {
+          files[i] = UriUtil.findRelativeFile(resourcePaths[i], null);
+        }
+
+        myFile.putUserData(DEPENDENT_FILES_KEY, files);
+        myFile.putUserData(GRAMMAR_POOL_TIME_STAMP_KEY, new Long(calculateTimeStamp(files, myProject)));
+      }
+       myFile.putUserData(KNOWN_NAMESPACES_KEY, getNamespaces(myFile));
+    }
+    catch (SAXException e) {
+      LOG.debug(e);
+    }
+    catch (Exception exception) {
+      filterAppException(exception);
+    }
+    catch (StackOverflowError error) {
+      // http://issues.apache.org/jira/browse/XERCESJ-589
+    }
+  }
+
+  protected SAXParser createParser() throws SAXException, ParserConfigurationException {
+      if (!needsDtdChecking() && !needsSchemaChecking() && !myForceChecking) {
+        return null;
+      }
+
+      SAXParserFactory factory = new SAXParserFactoryImpl();
+      boolean schemaChecking = false;
+
+      if (hasDtdDeclaration()) {
+        factory.setValidating(true);
+      }
+
+      if (needsSchemaChecking()) {
+        factory.setValidating(true);
+        factory.setNamespaceAware(true);
+        //jdk 1.5 API
+        try {
+          factory.setXIncludeAware(true);
+        } catch(NoSuchMethodError ignore) {}
+        schemaChecking = true;
+      }
+
+      SAXParser parser = factory.newSAXParser();
+
+      parser.setProperty(ENTITY_RESOLVER_PROPERTY_NAME, myXmlResourceResolver);
+
+      if (schemaChecking) { // when dtd checking schema refs could not be validated @see http://marc.theaimsgroup.com/?l=xerces-j-user&m=112504202423704&w=2
+        XMLGrammarPool grammarPool = getGrammarPool(myFile, myForceChecking);
+
+        parser.getXMLReader().setProperty(GRAMMAR_FEATURE_ID, grammarPool);
+      }
+
+      try {
+        if (schemaChecking) {
+          parser.setProperty(JAXPConstants.JAXP_SCHEMA_LANGUAGE,JAXPConstants.W3C_XML_SCHEMA);
+          parser.getXMLReader().setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, true);
+          
+          if (Boolean.TRUE.equals(Boolean.getBoolean(XmlResourceResolver.HONOUR_ALL_SCHEMA_LOCATIONS_PROPERTY_KEY))) {
+            parser.getXMLReader().setFeature("http://apache.org/xml/features/honour-all-schemaLocations", true);
+          }
+
+          parser.getXMLReader().setFeature("http://apache.org/xml/features/validation/warn-on-undeclared-elemdef",Boolean.TRUE);
+          parser.getXMLReader().setFeature("http://apache.org/xml/features/validation/warn-on-duplicate-attdef",Boolean.TRUE);
+        }
+
+        parser.getXMLReader().setFeature("http://apache.org/xml/features/warn-on-duplicate-entitydef",Boolean.TRUE);
+        parser.getXMLReader().setFeature("http://apache.org/xml/features/validation/unparsed-entity-checking",Boolean.FALSE);
+      } catch(SAXNotRecognizedException ex) {
+        // it is possible to continue work with configured parser
+        LOG.info("Xml parser installation seems screwed", ex);
+      }
+
+      return parser;
+  }
+
+  public static XMLGrammarPool getGrammarPool(XmlFile file, boolean forceChecking) {
+    final XMLGrammarPool previousGrammarPool = getGrammarPool(file);
+    XMLGrammarPool grammarPool = null;
+
+    // check if the pool is valid
+    if (!forceChecking && !isValidationDependentFilesOutOfDate(file)) {
+      grammarPool = previousGrammarPool;
+    }
+
+    if (grammarPool == null) {
+      grammarPool = new XMLGrammarPoolImpl();
+      file.putUserData(GRAMMAR_POOL_KEY,grammarPool);
+    }
+    return grammarPool;
+  }
+
+  @Nullable
+  public static XMLGrammarPool getGrammarPool(XmlFile file) {
+    return file.getUserData(GRAMMAR_POOL_KEY);
+  }
+
+  public static boolean isValidationDependentFilesOutOfDate(XmlFile myFile) {
+    final VirtualFile[] files = myFile.getUserData(DEPENDENT_FILES_KEY);
+    final Long grammarPoolTimeStamp = myFile.getUserData(GRAMMAR_POOL_TIME_STAMP_KEY);
+    String[] ns = myFile.getUserData(KNOWN_NAMESPACES_KEY);
+
+    if (!Arrays.equals(ns, getNamespaces(myFile))) {
+      return true;
+    }
+
+    if (grammarPoolTimeStamp != null && files != null) {
+      long dependentFilesTimestamp = calculateTimeStamp(files,myFile.getProject());
+
+      if (dependentFilesTimestamp == grammarPoolTimeStamp.longValue()) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  private static String[] getNamespaces(XmlFile file) {
+    XmlTag rootTag = file.getRootTag();
+    if (rootTag == null) return ArrayUtil.EMPTY_STRING_ARRAY;
+    return ContainerUtil.mapNotNull(rootTag.getAttributes(), new Function<XmlAttribute, String>() {
+      @Override
+      public String fun(XmlAttribute attribute) {
+        return attribute.getValue();
+      }
+    }, ArrayUtil.EMPTY_STRING_ARRAY);
+  }
+
+  private static long calculateTimeStamp(final VirtualFile[] files, Project myProject) {
+    long timestamp = 0;
+
+    for(VirtualFile file:files) {
+      if (file == null || !file.isValid()) break;
+      final PsiFile psifile = PsiManager.getInstance(myProject).findFile(file);
+
+      if (psifile != null && psifile.isValid()) {
+        timestamp += psifile.getViewProvider().getModificationStamp();
+      } else {
+        break;
+      }
+    }
+    return timestamp;
+  }
+
+  private boolean hasDtdDeclaration() {
+    XmlDocument document = myFile.getDocument();
+    if (document == null) return false;
+    XmlProlog prolog = document.getProlog();
+    if (prolog == null) return false;
+    XmlDoctype doctype = prolog.getDoctype();
+    if (doctype == null) return false;
+
+    return true;
+  }
+
+  private boolean needsDtdChecking() {
+    XmlDocument document = myFile.getDocument();
+    if (document == null) return false;
+
+    return (document.getProlog()!=null && document.getProlog().getDoctype()!=null);
+  }
+
+  private boolean needsSchemaChecking() {
+    XmlDocument document = myFile.getDocument();
+    if (document == null) return false;
+    XmlTag rootTag = document.getRootTag();
+    if (rootTag == null) return false;
+
+    XmlAttribute[] attributes = rootTag.getAttributes();
+    for (XmlAttribute attribute : attributes) {
+      if (attribute.isNamespaceDeclaration()) return true;
+    }
+
+    return false;
+  }
+  private static class MyContentDisposer implements ContentManagerListener {
+    private final Content myContent;
+    private final MessageView myMessageView;
+
+    public MyContentDisposer(final Content content, final MessageView messageView) {
+      myContent = content;
+      myMessageView = messageView;
+    }
+
+    public void contentRemoved(ContentManagerEvent event) {
+      final Content eventContent = event.getContent();
+      if (!eventContent.equals(myContent)) {
+        return;
+      }
+      myMessageView.getContentManager().removeContentManagerListener(this);
+      NewErrorTreeViewPanel errorTreeView = eventContent.getUserData(KEY);
+      if (errorTreeView != null) {
+        errorTreeView.dispose();
+      }
+      eventContent.putUserData(KEY, null);
+    }
+
+    public void contentAdded(ContentManagerEvent event) {
+    }
+    public void contentRemoveQuery(ContentManagerEvent event) {
+    }
+    public void selectionChanged(ContentManagerEvent event) {
+    }
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/XmlActionsGroup.java b/xml/impl/src/com/intellij/xml/actions/XmlActionsGroup.java
new file mode 100644
index 0000000..a5a5946
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/XmlActionsGroup.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions;
+
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class XmlActionsGroup extends DefaultActionGroup {
+  public XmlActionsGroup() {
+    super();
+    getTemplatePresentation().setText("XML Actions");
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/XmlSplitTagAction.java b/xml/impl/src/com/intellij/xml/actions/XmlSplitTagAction.java
new file mode 100644
index 0000000..77ec93a
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/XmlSplitTagAction.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class XmlSplitTagAction implements IntentionAction {
+
+  @Override
+  @NotNull
+  public String getText() {
+    return XmlBundle.message("xml.split.tag.intention.action");
+  }
+
+  @Override
+  @NotNull
+  public String getFamilyName() {
+    return XmlBundle.message("xml.split.tag.intention.action");
+  }
+
+  @Override
+  public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
+    if (file instanceof XmlFile) {
+      if (editor != null) {
+        final int offset = editor.getCaretModel().getOffset();
+        final PsiElement psiElement = file.findElementAt(offset);
+        if (psiElement != null) {
+          final PsiElement parent = psiElement.getParent();
+          if (parent != null && parent instanceof XmlText && parent.getText().trim().length() > 0) {
+            final PsiElement grandParent = parent.getParent();
+            if (grandParent != null && !isInsideUnsplittableElement(grandParent)) {
+              return true;
+            }
+          }
+        }
+      }
+    }
+
+    return false;
+  }
+
+  private static boolean isInsideUnsplittableElement(final PsiElement grandParent) {
+    if (!(grandParent instanceof HtmlTag) && grandParent.getContainingFile().getLanguage() != XHTMLLanguage.INSTANCE) {
+      return false;
+    }
+
+    final String name = ((XmlTag)grandParent).getName();
+    return "html".equals(name) || "body".equals(name) || "title".equals(name);
+  }
+
+  @Override
+  public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
+    if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
+
+    if (editor != null) {
+      final int offset = editor.getCaretModel().getOffset();
+      final PsiElement psiElement = file.findElementAt(offset);
+      if (psiElement != null) {
+        final PsiElement xmlText = psiElement.getParent();
+        final TextRange textRange = xmlText.getTextRange();
+        final int offsetInElement = offset - textRange.getStartOffset();
+
+        final PsiElement containingTag = xmlText.getParent();
+        if (containingTag instanceof XmlTag) {
+          final XmlTag xmlTag = (XmlTag)containingTag;
+
+          final String s = xmlText.getText();
+          String first = s.substring(0, offsetInElement);
+          String second = s.substring(offsetInElement);
+
+          if (xmlText instanceof XmlTagChild) {
+            XmlTagChild prev = ((XmlTagChild)xmlText).getPrevSiblingInTag();
+            while(prev != null) {
+              first = prev.getText() + first;
+              prev = prev.getPrevSiblingInTag();
+            }
+
+            XmlTagChild next = ((XmlTagChild)xmlText).getNextSiblingInTag();
+            while(next != null) {
+              second += next.getText();
+              next = next.getNextSiblingInTag();
+            }
+          }
+
+          final String filetext = buildNewText(xmlTag, first, second);
+
+          final XmlFile xmlFile = (XmlFile)PsiFileFactory.getInstance(project).createFileFromText("dummy.xml", XMLLanguage.INSTANCE,
+                                                                                               filetext);
+          final PsiElement parent2 = containingTag.getParent();
+          final XmlTag tag = xmlFile.getDocument().getRootTag();
+          XmlTag last = null;
+          final PsiElement[] children = tag.getChildren();
+          for (int i = children.length - 1; i >= 0; i--) {
+            PsiElement element = children[i];
+            if (element instanceof XmlTag) {
+              final XmlTag tag1 = (XmlTag)parent2.addAfter(element, containingTag);
+
+              if (last == null) {
+                last = tag1;
+              }
+            }
+          }
+
+          containingTag.delete();
+          editor.getCaretModel().moveToOffset(last.getValue().getTextRange().getStartOffset());
+        }
+      }
+    }
+  }
+
+  private static String buildNewText(final XmlTag xmlTag, final String first, final String second) {
+    final StringBuilder attrs = new StringBuilder();
+    final StringBuilder attrsWoId = new StringBuilder();
+    for (XmlAttribute attribute : xmlTag.getAttributes()) {
+      if (!"id".equals(attribute.getName())) {
+        attrs.append(attribute.getName()).append("=\"").append(attribute.getValue()).append("\" ");
+        attrsWoId.append(attribute.getName()).append("=\"").append(attribute.getValue()).append("\" ");
+      } else {
+        attrs.append(attribute.getName()).append("=\"").append(attribute.getValue()).append("\" ");
+      }
+
+    }
+
+    final StringBuilder sb = new StringBuilder();
+    final String name = xmlTag.getName();
+    sb.append("<root><").append(name);
+    if (attrs.length() > 0) {
+      sb.append(' ').append(attrs);
+    }
+    sb.append('>');
+    sb.append(first);
+    sb.append("</").append(name).append("><").append(name);
+    if (attrsWoId.length() > 0) {
+      sb.append(' ').append(attrsWoId);
+    }
+    sb.append('>');
+    sb.append(second).append("</").append(name).append("></root>");
+
+    return sb.toString();
+  }
+
+  @Override
+  public boolean startInWriteAction() {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/xmlbeans/FileUtils.java b/xml/impl/src/com/intellij/xml/actions/xmlbeans/FileUtils.java
new file mode 100644
index 0000000..832364c
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/xmlbeans/FileUtils.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions.xmlbeans;
+
+
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NonNls;
+
+import java.io.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class FileUtils {
+  @NonNls
+  public static final String CLASS_RESOURCE_STRING = "*?.class";
+  @NonNls
+  private static final String SOAP_ADDRESS = "soap:address";
+
+  private FileUtils() {
+  }
+
+  public static File saveStreamContentAsFile(String fullFileName, InputStream stream) throws IOException {
+    fullFileName = findFreeFileName(fullFileName);
+    OutputStream ostream = new FileOutputStream(fullFileName);
+    byte[] buf = new byte[8192];
+
+    while(true) {
+      int read = stream.read(buf,0,buf.length);
+      if (read == -1) break;
+      ostream.write(buf,0,read);
+    }
+    ostream.flush();
+    ostream.close();
+    return new File(fullFileName);
+  }
+
+  private static String findFreeFileName(String filename) {
+    File f = new File(filename);
+    if (! f.exists()) return filename;
+    int dot = filename.lastIndexOf('.'); // we believe file has some ext. For instance,  ".wsdl"
+    String name = filename.substring(0, dot);
+    String ext = filename.substring(dot);
+    int num = 0;
+    do {
+      f = new File(name + ++num + ext);
+    } while (f.exists());
+    return name + num + ext;
+  }
+
+
+  public static void saveText(VirtualFile virtualFile, String text) throws IOException {
+    VfsUtil.saveText(virtualFile, text);
+  }
+
+  public static boolean copyFile(File in, File out) {
+    try {
+      FileInputStream fis = new FileInputStream(in);
+      FileOutputStream fos = new FileOutputStream(out);
+      byte[] buf = new byte[1024];
+      int i;
+      while ((i = fis.read(buf)) != -1) {
+        fos.write(buf, 0, i);
+      }
+      fis.close();
+      fos.close();
+      return true;
+    } catch (Exception e) {
+      return false;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateInstanceDocumentFromSchemaAction.java b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateInstanceDocumentFromSchemaAction.java
new file mode 100644
index 0000000..22c7bbb
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateInstanceDocumentFromSchemaAction.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions.xmlbeans;
+
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.actionSystem.ActionPlaces;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlBundle;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class GenerateInstanceDocumentFromSchemaAction extends AnAction {
+  @Override
+  public void update(AnActionEvent e) {
+    final VirtualFile file = PlatformDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
+    final boolean enabled = isAcceptableFile(file);
+    e.getPresentation().setEnabled(enabled);
+    if (ActionPlaces.isPopupPlace(e.getPlace())) {
+      e.getPresentation().setVisible(enabled);
+    }
+  }
+
+  public void actionPerformed(AnActionEvent e) {
+    final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
+    final VirtualFile file = PlatformDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
+
+    final GenerateInstanceDocumentFromSchemaDialog dialog = new GenerateInstanceDocumentFromSchemaDialog(project, file);
+    dialog.setOkAction(new Runnable() {
+      public void run() {
+        doAction(project, dialog);
+      }
+    });
+
+    dialog.show();
+  }
+
+  private void doAction(final Project project, final GenerateInstanceDocumentFromSchemaDialog dialog) {
+    FileDocumentManager.getInstance().saveAllDocuments();
+
+    @NonNls List<String> parameters = new LinkedList<String>();
+
+    final String url = dialog.getUrl().getText();
+    final VirtualFile relativeFile = VfsUtil.findRelativeFile(ExternalResourceManager.getInstance().getResourceLocation(url), null);
+    final PsiFile file = PsiManager.getInstance(project).findFile(relativeFile);
+    if (! (file instanceof XmlFile)) {
+      Messages.showErrorDialog(project, "This is not XmlFile" + file == null ? "" : " (" + file.getFileType().getName() + ")", XmlBundle.message("error"));
+      return;
+    }
+
+    VirtualFile relativeFileDir;
+    if (relativeFile == null) {
+      Messages.showErrorDialog(project, XmlBundle.message("file.doesnt.exist", url), XmlBundle.message("error"));
+      return;
+    } else {
+      relativeFileDir = relativeFile.getParent();
+    }
+    if (relativeFileDir == null) {
+      Messages.showErrorDialog(project, XmlBundle.message("file.doesnt.exist", url), XmlBundle.message("error"));
+      return;
+    }
+
+    if (!dialog.enableRestrictionCheck()) {
+      parameters.add("-nopvr");
+    }
+
+    if (!dialog.enableUniquenessCheck()) {
+      parameters.add("-noupa");
+    }
+
+
+    String pathToUse;
+
+    try {
+      final File tempDir = FileUtil.createTempFile("xsd2inst", "");
+      tempDir.delete();
+      tempDir.mkdir();
+
+      pathToUse = tempDir.getPath() + File.separatorChar + Xsd2InstanceUtils.processAndSaveAllSchemas(
+        (XmlFile) file,
+        new THashMap<String, String>(),
+        new Xsd2InstanceUtils.SchemaReferenceProcessor() {
+          public void processSchema(String schemaFileName, byte[] schemaContent) {
+            try {
+              final String fullFileName = tempDir.getPath() + File.separatorChar + schemaFileName;
+              FileUtils.saveStreamContentAsFile(
+                fullFileName,
+                new ByteArrayInputStream(schemaContent)
+              );
+            } catch (IOException e) {
+              throw new RuntimeException(e);
+            }
+          }
+        }
+      );
+    } catch (IOException e) {
+      return;
+    }
+
+    parameters.add(pathToUse);
+
+    parameters.add("-name");
+    parameters.add(dialog.getElementName());
+
+    String xml;
+    try {
+      xml = Xsd2InstanceUtils.generate(ArrayUtil.toStringArray(parameters));
+    } catch (IllegalArgumentException e) {
+      Messages.showErrorDialog(project, StringUtil.getMessage(e), XmlBundle.message("error"));
+      return;
+    }
+
+
+
+    final VirtualFile baseDirForCreatedInstanceDocument1 = relativeFileDir;
+    String xmlFileName = baseDirForCreatedInstanceDocument1.getPath() + File.separatorChar + dialog.getOutputFileName();
+
+    FileOutputStream fileOutputStream;
+    try {
+      fileOutputStream = new FileOutputStream(xmlFileName);
+      try {
+        // the generated XML doesn't have any XML declaration -> utf-8
+        fileOutputStream.write(xml.getBytes("utf-8"));
+      }
+      finally {
+        fileOutputStream.close();
+      }
+
+      final File xmlFile = new File(xmlFileName);
+      VirtualFile virtualFile = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
+        @Nullable
+        public VirtualFile compute() {
+          return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(xmlFile);
+        }
+      });
+      FileEditorManager.getInstance(project).openFile(virtualFile, true);
+    }
+    catch (IOException e) {
+      Messages.showErrorDialog(project, "Could not save generated XML document: " + StringUtil.getMessage(e), XmlBundle.message("error"));
+    }
+  }
+
+  static boolean isAcceptableFileForGenerateSchemaFromInstanceDocument(VirtualFile virtualFile) {
+    return virtualFile != null && "xsd".equalsIgnoreCase(virtualFile.getExtension());
+  }
+
+  public static boolean isAcceptableFile(VirtualFile file) {
+    return isAcceptableFileForGenerateSchemaFromInstanceDocument(file);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateInstanceDocumentFromSchemaDialog.form b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateInstanceDocumentFromSchemaDialog.form
new file mode 100644
index 0000000..d7bb3fd
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateInstanceDocumentFromSchemaDialog.form
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.xml.actions.xmlbeans.GenerateInstanceDocumentFromSchemaDialog">
+  <grid id="fece0" binding="panel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="1" left="1" bottom="1" right="1"/>
+    <constraints>
+      <xy x="282" y="178" width="526" height="157"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="fc23b" class="javax.swing.JLabel" binding="generateFromUrlText">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/XmlBundle" key="schema2instance.dialog.schema.path"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.schema2instance.url.tooltip"/>
+        </properties>
+      </component>
+      <component id="bef0c" class="javax.swing.JLabel" binding="statusText">
+        <constraints>
+          <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/XmlBundle" key="any.dialog.status"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="webservice.status.tooltip"/>
+        </properties>
+      </component>
+      <component id="6432a" class="javax.swing.JLabel" binding="status">
+        <constraints>
+          <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text value=""/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="webservice.status.tooltip"/>
+        </properties>
+      </component>
+      <component id="b2571" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="generateFromUrl">
+        <constraints>
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+            <preferred-size width="150" height="-1"/>
+          </grid>
+        </constraints>
+        <properties>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.instance2schema.url.tooltip"/>
+        </properties>
+      </component>
+      <component id="73cde" class="javax.swing.JLabel" binding="rootElementChooserText">
+        <constraints>
+          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/XmlBundle" key="schema2instance.dialog.element.name"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.rootelement.tooltip"/>
+        </properties>
+      </component>
+      <component id="d3b6f" class="javax.swing.JComboBox" binding="rootElementChooser">
+        <constraints>
+          <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <editable value="true"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.rootelement.tooltip"/>
+        </properties>
+      </component>
+      <component id="a0090" class="javax.swing.JCheckBox" binding="enableRestrictionCheck">
+        <constraints>
+          <grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <margin top="0" left="0" bottom="0" right="0"/>
+          <selected value="true"/>
+          <text resource-bundle="messages/XmlBundle" key="schema2instance.dialog.enable.restriction.check"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.particle.valid.tooltip"/>
+        </properties>
+      </component>
+      <component id="3df45" class="javax.swing.JCheckBox" binding="enableUniqueCheck">
+        <constraints>
+          <grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <horizontalAlignment value="2"/>
+          <horizontalTextPosition value="4"/>
+          <margin top="0" left="0" bottom="0" right="0"/>
+          <selected value="true"/>
+          <text resource-bundle="messages/XmlBundle" key="schema2instance.dialog.enable.unique.check"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.unique.particle.tooltip"/>
+        </properties>
+      </component>
+      <component id="9cfb7" class="javax.swing.JLabel" binding="outputFileNameText">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <labelFor value="aa173"/>
+          <text resource-bundle="messages/XmlBundle" key="schema2instance.dialog.instance.document.name"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.instance.document.name.tooltip"/>
+        </properties>
+      </component>
+      <component id="aa173" class="javax.swing.JTextField" binding="outputFileName">
+        <constraints>
+          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+            <preferred-size width="150" height="-1"/>
+          </grid>
+        </constraints>
+        <properties>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.instance.document.name.tooltip"/>
+        </properties>
+      </component>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateInstanceDocumentFromSchemaDialog.java b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateInstanceDocumentFromSchemaDialog.java
new file mode 100644
index 0000000..33d7561
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateInstanceDocumentFromSchemaDialog.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions.xmlbeans;
+
+
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.ui.JBColor;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlElementDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class GenerateInstanceDocumentFromSchemaDialog extends DialogWrapper {
+  private JPanel panel;
+  private TextFieldWithBrowseButton generateFromUrl;
+  private JLabel status;
+  private JLabel statusText;
+  private JLabel generateFromUrlText;
+  private JComboBox rootElementChooser;
+  private JLabel rootElementChooserText;
+  private JCheckBox enableRestrictionCheck;
+  private JCheckBox enableUniqueCheck;
+  private JTextField outputFileName;
+  private JLabel outputFileNameText;
+  private String previousUri;
+  private Runnable myOkAction;
+  private final Project myProject;
+
+  public GenerateInstanceDocumentFromSchemaDialog(Project project, VirtualFile file) {
+    super(project, true);
+    myProject = project;
+
+    UIUtils
+      .configureBrowseButton(project, generateFromUrl, new String[]{"xsd"}, XmlBundle.message("select.xsd.schema.dialog.title"), false);
+
+    doInitFor(rootElementChooserText, rootElementChooser);
+    doInitFor(generateFromUrlText, generateFromUrl.getTextField());
+    doInitFor(outputFileNameText, outputFileName);
+    generateFromUrl.setText(file.getPresentableUrl());
+    updateFile();
+
+    setTitle(XmlBundle.message("generate.instance.document.from.schema.dialog.title"));
+
+    init();
+
+    outputFileName.setText(file.getName() + ".xml");
+  }
+
+  public void doInitFor(JLabel textComponent, JComponent component) {
+    textComponent.setLabelFor(component);
+
+    if (component instanceof JTextField) {
+      ((JTextField)component).getDocument().addDocumentListener(new DocumentListener() {
+        public void insertUpdate(DocumentEvent e) {
+          validateData();
+        }
+
+        public void removeUpdate(DocumentEvent e) {
+          validateData();
+        }
+
+        public void changedUpdate(DocumentEvent e) {
+          validateData();
+        }
+      });
+    }
+    else if (component instanceof JComboBox) {
+      JComboBox jComboBox = ((JComboBox)component);
+
+      jComboBox.addActionListener(new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+          validateData();
+        }
+      });
+
+      ((JTextField)jComboBox.getEditor().getEditorComponent()).getDocument().addDocumentListener(new DocumentListener() {
+        public void insertUpdate(DocumentEvent e) {
+          validateData();
+        }
+
+        public void removeUpdate(DocumentEvent e) {
+          validateData();
+        }
+
+        public void changedUpdate(DocumentEvent e) {
+          validateData();
+        }
+      });
+
+      if (jComboBox.isEditable()) {
+        jComboBox.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
+          public void keyTyped(KeyEvent e) {
+            validateData();
+          }
+        });
+      }
+    }
+  }
+
+  private void validateData() {
+    String msg = doValidateWithData();
+    setOKActionEnabled(msg == null);
+    status.setText(msg == null ? "" : msg);
+    status.setForeground(JBColor.RED);
+  }
+
+  public static void configureComboBox(JComboBox combo, List<String> lastValues) {  // without -editor.selectAll- no focus
+    combo.setModel(new DefaultComboBoxModel(ArrayUtil.toStringArray(lastValues)));
+  }
+
+  private void updateFile() {
+    String uri = generateFromUrl.getText();
+    boolean hasPrevious = (previousUri != null && previousUri.equals(uri));
+    final PsiFile psifile = findFile(uri);
+    List<String> myRootValues;
+
+    if (psifile == null) {
+      configureComboBox(rootElementChooser, Collections.<String>emptyList());
+      return;
+    }
+
+    final XmlTag rootTag = getRootTag(psifile);
+
+    if (rootTag == null) {
+      configureComboBox(rootElementChooser, Collections.<String>emptyList());
+      rootElementChooser.setSelectedIndex(-1);
+      previousUri = uri;
+      return;
+    }
+
+    myRootValues = Xsd2InstanceUtils.addVariantsFromRootTag(rootTag);
+
+    Object selectedItem = rootElementChooser.getSelectedItem();
+    configureComboBox(rootElementChooser, myRootValues);
+
+    if (hasPrevious) {
+      rootElementChooser.setSelectedItem(selectedItem);
+    }
+    else {
+      rootElementChooser.setSelectedIndex(myRootValues.size() > 0 ? 0 : -1);
+    }
+    previousUri = uri;
+  }
+
+  @Nullable
+  private static XmlTag getRootTag(PsiFile psifile) {
+    XmlFile xmlFile = null;
+    if (psifile instanceof XmlFile) {
+      xmlFile = (XmlFile)psifile;
+    }
+    else if (psifile.getViewProvider() instanceof TemplateLanguageFileViewProvider) {
+      TemplateLanguageFileViewProvider viewProvider = (TemplateLanguageFileViewProvider)psifile.getViewProvider();
+      if (viewProvider.getPsi(viewProvider.getTemplateDataLanguage()) instanceof XmlFile) {
+        xmlFile = (XmlFile)viewProvider.getPsi(viewProvider.getTemplateDataLanguage());
+      }
+    }
+
+    if (xmlFile != null) {
+      return xmlFile.getDocument().getRootTag();
+    }
+    else {
+      return null;
+    }
+  }
+
+  @Nullable
+  private PsiFile findFile(String uri) {
+    final VirtualFile file =
+      uri != null ? VfsUtil.findRelativeFile(ExternalResourceManager.getInstance().getResourceLocation(uri), null) : null;
+    return file != null ? PsiManager.getInstance(myProject).findFile(file) : null;
+  }
+
+  public String getOutputFileName() {
+    return outputFileName.getText();
+  }
+
+  public Boolean areCurrentParametersStillValid() {
+    updateFile();
+    return rootElementChooser.getSelectedItem() != null;
+  }
+
+  @Nullable
+  protected String doValidateWithData() {
+    String rootElementName = getElementName();
+    if (rootElementName == null || rootElementName.length() == 0) {
+      return XmlBundle.message("schema2.instance.no.valid.root.element.name.validation.error");
+    }
+
+    final PsiFile psiFile = findFile(getUrl().getText());
+    if (psiFile instanceof XmlFile) {
+      final XmlTag tag = getRootTag(psiFile);
+      if (tag != null) {
+        final XmlElementDescriptor descriptor = Xsd2InstanceUtils.getDescriptor(tag, rootElementName);
+
+        if (descriptor == null) {
+          return XmlBundle.message("schema2.instance.no.valid.root.element.name.validation.error");
+        }
+      }
+    }
+
+    final String fileName = getOutputFileName();
+    if (fileName == null || fileName.length() == 0) {
+      return XmlBundle.message("schema2.instance.output.file.name.is.empty.validation.problem");
+    }
+    return null;
+
+  }
+
+  protected static boolean isAcceptableFile(VirtualFile virtualFile) {
+    return GenerateInstanceDocumentFromSchemaAction.isAcceptableFileForGenerateSchemaFromInstanceDocument(virtualFile);
+  }
+
+
+  protected TextFieldWithBrowseButton getUrl() {
+    return generateFromUrl;
+  }
+
+  protected JLabel getUrlText() {
+    return generateFromUrlText;
+  }
+
+  protected JLabel getStatusTextField() {
+    return statusText;
+  }
+
+  protected JLabel getStatusField() {
+    return status;
+  }
+
+  protected JComponent createCenterPanel() {
+    return panel;
+  }
+
+  boolean enableUniquenessCheck() {
+    return enableUniqueCheck.isSelected();
+  }
+
+  boolean enableRestrictionCheck() {
+    return enableRestrictionCheck.isSelected();
+  }
+
+  String getElementName() {
+    return (String)rootElementChooser.getSelectedItem();
+  }
+
+  public void setOkAction(Runnable runnable) {
+    myOkAction = runnable;
+  }
+
+  @Override
+  protected void doOKAction() {
+    super.doOKAction();
+    if (myOkAction != null) {
+      myOkAction.run();
+    }
+  }
+
+  @NotNull
+  protected String getHelpId() {
+    return "webservices.GenerateInstanceDocumentFromSchema";
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateSchemaFromInstanceDocumentAction.java b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateSchemaFromInstanceDocumentAction.java
new file mode 100644
index 0000000..62bdcb7
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateSchemaFromInstanceDocumentAction.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions.xmlbeans;
+
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.ActionPlaces;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlBundle;
+import org.apache.xmlbeans.impl.inst2xsd.Inst2Xsd;
+import org.jetbrains.annotations.NonNls;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class GenerateSchemaFromInstanceDocumentAction extends AnAction {
+  private static final Map<String, String> DESIGN_TYPES = new HashMap<String, String>();
+  private static final Map<String, String> CONTENT_TYPES = new HashMap<String, String>();
+  static {
+    DESIGN_TYPES.put(GenerateSchemaFromInstanceDocumentDialog.LOCAL_ELEMENTS_GLOBAL_COMPLEX_TYPES, "vb");
+    DESIGN_TYPES.put(GenerateSchemaFromInstanceDocumentDialog.LOCAL_ELEMENTS_TYPES, "ss");
+    DESIGN_TYPES.put(GenerateSchemaFromInstanceDocumentDialog.GLOBAL_ELEMENTS_LOCAL_TYPES, "rd");
+    CONTENT_TYPES.put(GenerateSchemaFromInstanceDocumentDialog.SMART_TYPE, "smart");
+    CONTENT_TYPES.put(GenerateSchemaFromInstanceDocumentDialog.STRING_TYPE, "string");
+  }
+
+  //private static final
+  
+  @Override
+  public void update(AnActionEvent e) {
+    final VirtualFile file = PlatformDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
+    final boolean enabled = isAcceptableFile(file);
+    e.getPresentation().setEnabled(enabled);
+    if (ActionPlaces.isPopupPlace(e.getPlace())) {
+      e.getPresentation().setVisible(enabled);
+    }
+  }
+
+  public void actionPerformed(AnActionEvent e) {
+    final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
+    final VirtualFile file = PlatformDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
+
+    final GenerateSchemaFromInstanceDocumentDialog dialog = new GenerateSchemaFromInstanceDocumentDialog(project, file);
+    dialog.setOkAction(new Runnable() {
+      public void run() {
+        doAction(project, dialog);
+      }
+    });    
+
+    dialog.show();
+  }
+
+  private static void doAction(final Project project, final GenerateSchemaFromInstanceDocumentDialog dialog) {
+    FileDocumentManager.getInstance().saveAllDocuments();
+
+    final String url = dialog.getUrl().getText();
+    final VirtualFile relativeFile = VfsUtil.findRelativeFile(ExternalResourceManager.getInstance().getResourceLocation(url), null);
+    VirtualFile relativeFileDir;
+    if (relativeFile == null) {
+      Messages.showErrorDialog(project, XmlBundle.message("file.doesnt.exist", url), XmlBundle.message("error"));
+      return;
+    } else {
+      relativeFileDir = relativeFile.getParent();
+    }
+    if (relativeFileDir == null) {
+      Messages.showErrorDialog(project, XmlBundle.message("file.doesnt.exist", url), XmlBundle.message("error"));
+      return;
+    }
+
+    @NonNls List<String> parameters = new LinkedList<String>();
+    parameters.add("-design");
+    parameters.add(DESIGN_TYPES.get(dialog.getDesignType()));
+
+    parameters.add("-simple-content-types");
+    parameters.add(CONTENT_TYPES.get(dialog.getSimpleContentType()));
+
+    parameters.add("-enumerations");
+    String enumLimit = dialog.getEnumerationsLimit();
+    parameters.add("0".equals(enumLimit) ? "never" : enumLimit);
+
+    parameters.add("-outDir");
+    final String dirPath = relativeFileDir.getPath();
+    parameters.add(dirPath);
+
+    final File expectedSchemaFile = new File(dirPath + File.separator + relativeFile.getName() + "0.xsd");
+    if (expectedSchemaFile.exists()) {
+      if (!expectedSchemaFile.delete()) {
+        Messages.showErrorDialog(project, XmlBundle.message("cant.delete.file", expectedSchemaFile.getPath()), XmlBundle.message("error"));
+        return;
+      }
+    }
+
+    parameters.add("-outPrefix");
+    parameters.add(relativeFile.getName());
+
+    parameters.add(url);
+    File xsd = new File(dirPath + File.separator + dialog.getTargetSchemaName());
+    final VirtualFile xsdFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(xsd);
+    if (xsdFile != null) {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          public void run() {
+            try {
+              xsdFile.delete(null);
+            } catch (IOException e) {//
+            }
+          }
+        });
+    }
+
+    Inst2Xsd.main(ArrayUtil.toStringArray(parameters));
+    if (expectedSchemaFile.exists()) {
+      final boolean renamed = expectedSchemaFile.renameTo(xsd);
+      if (! renamed) {
+        Messages.showErrorDialog(project, XmlBundle.message("cant.rename.file", expectedSchemaFile.getPath(), xsd.getPath()), XmlBundle.message("error"));
+      }
+    }
+
+    VirtualFile xsdVFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(xsd);
+    if (xsdVFile != null) {
+      FileEditorManager.getInstance(project).openFile(xsdVFile, true);
+    } else {
+      Messages.showErrorDialog(project, XmlBundle.message("xml2xsd.generator.error.message"), XmlBundle.message("xml2xsd.generator.error"));
+    }
+
+  }
+
+  public static boolean isAcceptableFile(VirtualFile file) {
+    return file != null && "xml".equalsIgnoreCase(file.getExtension());
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateSchemaFromInstanceDocumentDialog.form b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateSchemaFromInstanceDocumentDialog.form
new file mode 100644
index 0000000..fecd029
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateSchemaFromInstanceDocumentDialog.form
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.xml.actions.xmlbeans.GenerateSchemaFromInstanceDocumentDialog">
+  <grid id="fece0" binding="panel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="1" left="1" bottom="1" right="1"/>
+    <constraints>
+      <xy x="282" y="178" width="645" height="153"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="fc23b" class="javax.swing.JLabel" binding="generateFromUrlText">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/XmlBundle" key="instance2schema.dialog.instance.document.path"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.instance2schema.url.tooltip"/>
+        </properties>
+      </component>
+      <component id="bef0c" class="javax.swing.JLabel" binding="statusText">
+        <constraints>
+          <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/XmlBundle" key="any.dialog.status"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="webservice.status.tooltip"/>
+        </properties>
+      </component>
+      <component id="6432a" class="javax.swing.JLabel" binding="status">
+        <constraints>
+          <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <foreground color="-65536"/>
+          <text value=""/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="webservice.status.tooltip"/>
+        </properties>
+      </component>
+      <component id="b2571" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="generateFromUrl">
+        <constraints>
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+            <preferred-size width="150" height="-1"/>
+          </grid>
+        </constraints>
+        <properties>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.instance2schema.url.tooltip"/>
+        </properties>
+      </component>
+      <component id="6ad20" class="javax.swing.JLabel" binding="designTypeText">
+        <constraints>
+          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/XmlBundle" key="instance2schema.dialog.design.type"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.designtype.tooltip"/>
+        </properties>
+      </component>
+      <component id="5c4f" class="javax.swing.JLabel" binding="detectSimpleContentTypesText">
+        <constraints>
+          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/XmlBundle" key="instance2schema.dialog.detect.simple.content.type"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.simplecontenttype.tooltip"/>
+        </properties>
+      </component>
+      <component id="cbbd3" class="javax.swing.JLabel" binding="detectEnumerationsLimitText">
+        <constraints>
+          <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <labelFor value="18828"/>
+          <text resource-bundle="messages/XmlBundle" key="instance2schema.dialog.detect.enumerations.limit"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.enumerations.tooltip"/>
+        </properties>
+      </component>
+      <component id="18828" class="javax.swing.JTextField" binding="detectEnumerationsLimit">
+        <constraints>
+          <grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+            <preferred-size width="150" height="-1"/>
+          </grid>
+        </constraints>
+        <properties>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.enumerations.tooltip"/>
+        </properties>
+      </component>
+      <component id="78b1e" class="com.intellij.openapi.ui.ComboBox" binding="detectSimpleContentTypes">
+        <constraints>
+          <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.simplecontenttype.tooltip"/>
+        </properties>
+      </component>
+      <component id="f3bf0" class="com.intellij.openapi.ui.ComboBox" binding="designType">
+        <constraints>
+          <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.designtype.tooltip"/>
+        </properties>
+      </component>
+      <component id="a7b02" class="javax.swing.JLabel" binding="resultSchemaFileNameText">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <labelFor value="6bb2c"/>
+          <text value="Result schema file name:"/>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.instance2schema.result.schema.name"/>
+        </properties>
+      </component>
+      <component id="6bb2c" class="javax.swing.JTextField" binding="resultSchemaFileName">
+        <constraints>
+          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+            <preferred-size width="150" height="-1"/>
+          </grid>
+        </constraints>
+        <properties>
+          <toolTipText resource-bundle="messages/XmlBundle" key="xmlbeans.enumerations.tooltip"/>
+        </properties>
+      </component>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateSchemaFromInstanceDocumentDialog.java b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateSchemaFromInstanceDocumentDialog.java
new file mode 100644
index 0000000..e57a753
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/xmlbeans/GenerateSchemaFromInstanceDocumentDialog.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions.xmlbeans;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.JBColor;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class GenerateSchemaFromInstanceDocumentDialog extends DialogWrapper {
+  private JPanel panel;
+  private TextFieldWithBrowseButton generateFromUrl;
+  private JLabel status;
+  private JLabel statusText;
+  private JLabel generateFromUrlText;
+  private JLabel designTypeText;
+  private JTextField detectEnumerationsLimit;
+  private ComboBox detectSimpleContentTypes;
+  private ComboBox designType;
+  private JLabel detectEnumerationsLimitText;
+  private JLabel detectSimpleContentTypesText;
+  private JLabel resultSchemaFileNameText;
+  private JTextField resultSchemaFileName;
+
+  static final String LOCAL_ELEMENTS_GLOBAL_COMPLEX_TYPES = XmlBundle.message("local.elements.global.complex.types.option.name");
+  static final String LOCAL_ELEMENTS_TYPES = XmlBundle.message("local.elements.types.option.name");
+  static final String GLOBAL_ELEMENTS_LOCAL_TYPES = XmlBundle.message("global.elements.local.types.option.name");
+
+  private static final List<String> designTypes = Arrays.asList(
+    LOCAL_ELEMENTS_GLOBAL_COMPLEX_TYPES,
+    LOCAL_ELEMENTS_TYPES,
+    GLOBAL_ELEMENTS_LOCAL_TYPES
+  );
+
+  static final String STRING_TYPE = "string";
+  static final String SMART_TYPE = "smart";
+  private static final List<String> simpleContentTypes = Arrays.asList(STRING_TYPE, SMART_TYPE);
+  private Runnable myOkAction;
+
+  public GenerateSchemaFromInstanceDocumentDialog(Project project, VirtualFile file) {
+    super(project, true);
+
+    setTitle(XmlBundle.message("generate.schema.from.instance.document.dialog.title"));
+
+    doInitFor(designTypeText, designType);
+    configureComboBox(designType,designTypes);
+
+    doInitFor(detectSimpleContentTypesText, detectSimpleContentTypes);
+    configureComboBox(detectSimpleContentTypes, simpleContentTypes);
+
+
+    doInitFor(detectEnumerationsLimitText, detectEnumerationsLimit);
+    detectEnumerationsLimit.setText("10");
+
+
+    UIUtils.configureBrowseButton(project, generateFromUrl, new String[] {"xml"}, XmlBundle.message("select.xml.document.dialog.title"), false);
+    doInitFor(generateFromUrlText, generateFromUrl.getTextField());
+
+    doInitFor(resultSchemaFileNameText, resultSchemaFileName);
+
+    init();
+    
+    generateFromUrl.setText(file.getPresentableUrl());
+    resultSchemaFileName.setText(file.getNameWithoutExtension() + ".xsd");
+  }
+
+  private void validateData() {
+    String msg = doValidateWithData();
+    setOKActionEnabled(msg == null);
+    status.setText(msg == null ? "" : msg);
+    status.setForeground(JBColor.RED);
+  }
+
+  public static void configureComboBox(JComboBox combo, List<String> lastValues) {
+    combo.setModel(new DefaultComboBoxModel(ArrayUtil.toStringArray(lastValues)));
+    if (combo.getItemCount() != 0) {
+      combo.setSelectedIndex(0);
+      combo.getEditor().selectAll();
+    }
+  }
+
+  public void setFileUrl(String url) {
+    generateFromUrl.setText(url);
+  }
+
+  @Override
+  protected void doOKAction() {
+    super.doOKAction();
+    if (myOkAction != null) {
+      myOkAction.run();
+    }
+  }
+
+  public void setOkAction(Runnable okAction) {
+    myOkAction = okAction;
+  }
+
+  public void doInitFor(JLabel textComponent, JComponent component) {
+    textComponent.setLabelFor(component);
+
+    if (component instanceof JTextField) {
+      ((JTextField)component).getDocument().addDocumentListener(new DocumentListener() {
+        public void insertUpdate(DocumentEvent e) {
+          validateData();
+        }
+
+        public void removeUpdate(DocumentEvent e) {
+          validateData();
+        }
+
+        public void changedUpdate(DocumentEvent e) {
+          validateData();
+        }
+      });
+    } else if (component instanceof JComboBox) {
+      JComboBox jComboBox = ((JComboBox) component);
+
+      jComboBox.addActionListener(new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+          validateData();
+        }
+      });
+
+      if (jComboBox.isEditable()) {
+        jComboBox.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
+          public void keyTyped(KeyEvent e) {
+            validateData();
+          }
+        });
+      }
+    }
+  }
+
+  protected TextFieldWithBrowseButton getUrl() {
+    return generateFromUrl;
+  }
+
+  protected JLabel getUrlText() {
+    return generateFromUrlText;
+  }
+
+  protected JLabel getStatusTextField() {
+    return statusText;
+  }
+
+  protected JLabel getStatusField() {
+    return status;
+  }
+
+  protected JComponent createCenterPanel() {
+    return panel;
+  }
+
+  String getDesignType() {
+    return (String) designType.getSelectedItem();
+  }
+
+  String getSimpleContentType() {
+    return (String) detectSimpleContentTypes.getSelectedItem();
+  }
+
+  String getEnumerationsLimit() {
+    return detectEnumerationsLimit.getText();
+  }
+
+  public String getTargetSchemaName() {
+    return resultSchemaFileName.getText();
+  }
+
+  protected String doValidateWithData() {
+    if (! new File(generateFromUrl.getText()).exists()) {
+      return XmlBundle.message("instance.document.file.is.not.exist");
+    }
+
+    try {
+      int i = Integer.parseInt(getEnumerationsLimit());
+      if (i < 0) return XmlBundle.message("negative.number.validation.problem");
+    } catch(NumberFormatException ex) {
+      return XmlBundle.message("invalid.number.validation.problem");
+    }
+
+    if (getTargetSchemaName() == null || getTargetSchemaName().length() == 0) {
+      return XmlBundle.message("result.schema.file.name.is.empty.validation.problem");
+    }
+    return null;
+  }
+
+  @NotNull
+  protected String getHelpId() {
+    return "webservices.GenerateSchemaFromInstanceDocument";
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/xmlbeans/UIUtils.java b/xml/impl/src/com/intellij/xml/actions/xmlbeans/UIUtils.java
new file mode 100644
index 0000000..cdde9af
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/xmlbeans/UIUtils.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions.xmlbeans;
+
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.xml.XmlBundle;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class UIUtils {
+  private UIUtils() {}
+
+  public static void configureBrowseButton(final Project myProject,
+                                       final TextFieldWithBrowseButton wsdlUrl,
+                                       final String[] _extensions,
+                                       final String selectFileDialogTitle,
+                                       final boolean multipleFileSelection) {
+    wsdlUrl.getButton().setToolTipText(XmlBundle.message("browse.button.tooltip"));
+    wsdlUrl.getButton().addActionListener(
+      new ActionListener() {
+        public void actionPerformed(ActionEvent actionEvent) {
+          final FileChooserDescriptor fileChooserDescriptor = new FileChooserDescriptor(true, false, false, false, false, multipleFileSelection) {
+            private final List<String> extensions = Arrays.asList(_extensions);
+
+            public boolean isFileSelectable(VirtualFile virtualFile) {
+              return extensions.contains(virtualFile.getExtension());
+            }
+
+            @Override
+            public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
+              return super.isFileVisible(file, showHiddenFiles) && (file.isDirectory() || isFileSelectable(file));
+            }
+          };
+
+          fileChooserDescriptor.setTitle(selectFileDialogTitle);
+
+          VirtualFile initialFile = myProject.getBaseDir();
+          String selectedItem = wsdlUrl.getTextField().getText();
+          if (selectedItem != null && selectedItem.startsWith(LocalFileSystem.PROTOCOL_PREFIX)) {
+            VirtualFile fileByPath = VfsUtil.findRelativeFile(ExternalResourceManager.getInstance().getResourceLocation(VfsUtil.fixURLforIDEA(selectedItem)), null);
+            if (fileByPath != null) initialFile = fileByPath;
+          }
+
+          final VirtualFile[] virtualFiles = FileChooser.chooseFiles(fileChooserDescriptor, myProject, initialFile);
+          if (virtualFiles.length == 1) {
+            String url = fixIDEAUrl(virtualFiles[0].getUrl());
+            wsdlUrl.setText(url);
+          }
+        }
+      }
+    );
+  }
+
+  public static String fixIDEAUrl(String url) {
+    return SystemInfo.isWindows ? VfsUtil.fixIDEAUrl(url) : url;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/actions/xmlbeans/Xsd2InstanceUtils.java b/xml/impl/src/com/intellij/xml/actions/xmlbeans/Xsd2InstanceUtils.java
new file mode 100644
index 0000000..c6c358e
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/actions/xmlbeans/Xsd2InstanceUtils.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.actions.xmlbeans;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.XmlRecursiveElementVisitor;
+import com.intellij.psi.impl.source.tree.LeafPsiElement;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
+import com.intellij.xml.util.XmlUtil;
+import org.apache.xmlbeans.*;
+import org.apache.xmlbeans.impl.tool.CommandLine;
+import org.apache.xmlbeans.impl.xsd2inst.SampleXmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.util.*;
+
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class Xsd2InstanceUtils {
+    public static String generate(String[] args) {
+        Set flags = new HashSet();
+        Set opts = new HashSet();
+        flags.add("h");
+        flags.add("help");
+        flags.add("usage");
+        flags.add("license");
+        flags.add("version");
+        flags.add("dl");
+        flags.add("noupa");
+        flags.add("nopvr");
+        flags.add("partial");
+        opts.add("name");
+
+        CommandLine cl = new CommandLine(args, flags, opts);
+
+        String[] badOpts = cl.getBadOpts();
+        if (badOpts.length > 0) {
+                throw new IllegalArgumentException("Unrecognized option: " + badOpts[0]);
+
+        }
+
+        boolean dl = (cl.getOpt("dl") != null);
+        boolean nopvr = (cl.getOpt("nopvr") != null);
+        boolean noupa = (cl.getOpt("noupa") != null);
+
+        File[] schemaFiles = cl.filesEndingWith(".xsd");
+        String rootName = cl.getOpt("name");
+
+        if (rootName == null) {
+            throw new IllegalArgumentException("Required option \"-name\" must be present");
+        }
+
+        // Process Schema files
+        List sdocs = new ArrayList();
+        for (int i = 0; i < schemaFiles.length; i++)
+        {
+            try
+            {
+                sdocs.add(XmlObject.Factory.parse(schemaFiles[i],
+                        (new XmlOptions()).setLoadLineNumbers().setLoadMessageDigest()));
+            }
+            catch (Exception e)
+            {
+                throw new IllegalArgumentException("Can not load schema file: " + schemaFiles[i] + ": " + e.getLocalizedMessage());
+            }
+        }
+
+        XmlObject[] schemas = (XmlObject[]) sdocs.toArray(new XmlObject[sdocs.size()]);
+
+        SchemaTypeSystem sts = null;
+        if (schemas.length > 0)
+        {
+            Collection errors = new ArrayList();
+            XmlOptions compileOptions = new XmlOptions();
+            if (dl)
+                compileOptions.setCompileDownloadUrls();
+            if (nopvr)
+                compileOptions.setCompileNoPvrRule();
+            if (noupa)
+                compileOptions.setCompileNoUpaRule();
+
+          try {
+            sts = XmlBeans.compileXsd(schemas, XmlBeans.getBuiltinTypeSystem(), compileOptions);
+          } catch (XmlException e) {
+              String out = "Schema compilation errors: ";
+              for (Object error : errors) out += "\n" + error;
+              throw new IllegalArgumentException(out);
+          }
+        }
+
+        if (sts == null)
+        {
+            throw new IllegalArgumentException("No Schemas to process.");
+        }
+        SchemaType[] globalElems = sts.documentTypes();
+        SchemaType elem = null;
+        for (int i = 0; i < globalElems.length; i++)
+        {
+            if (rootName.equals(globalElems[i].getDocumentElementName().getLocalPart()))
+            {
+                elem = globalElems[i];
+                break;
+            }
+        }
+
+        if (elem == null) {
+            throw new IllegalArgumentException("Could not find a global element with name \"" + rootName + "\"");
+        }
+
+        // Now generate it
+        return SampleXmlUtil.createSampleForType(elem);
+    }
+
+  public static XmlElementDescriptor getDescriptor(XmlTag tag, String elementName) {
+    final PsiMetaData metaData = tag.getMetaData();
+
+    if (metaData instanceof XmlNSDescriptorImpl) {
+      final XmlNSDescriptorImpl nsDescriptor = (XmlNSDescriptorImpl) metaData;
+      return nsDescriptor.getElementDescriptor(elementName, nsDescriptor.getDefaultNamespace());
+    }
+
+    return null;
+  }
+
+  public static List<String> addVariantsFromRootTag(XmlTag rootTag) {
+    PsiMetaData metaData = rootTag.getMetaData();
+    if (metaData instanceof XmlNSDescriptorImpl) {
+      XmlNSDescriptorImpl nsDescriptor = (XmlNSDescriptorImpl) metaData;
+
+      List<String> elementDescriptors = new ArrayList<String>();
+      XmlElementDescriptor[] rootElementsDescriptors = nsDescriptor.getRootElementsDescriptors(PsiTreeUtil.getParentOfType(rootTag, XmlDocument.class));
+      for(XmlElementDescriptor e:rootElementsDescriptors) {
+        elementDescriptors.add(e.getName());
+      }
+
+      return elementDescriptors;
+    }
+    return Collections.emptyList();
+  }
+
+  public static String processAndSaveAllSchemas(@NotNull XmlFile file, @NotNull final Map<String, String> scannedToFileName,
+                                          final @NotNull SchemaReferenceProcessor schemaReferenceProcessor) {
+    final String fileName = file.getName();
+
+    String previous = scannedToFileName.get(fileName);
+
+    if (previous != null) return previous;
+
+    scannedToFileName.put(fileName, fileName);
+
+    final StringBuilder result = new StringBuilder();
+
+    file.acceptChildren(new XmlRecursiveElementVisitor() {
+      @Override public void visitElement(PsiElement psiElement) {
+        super.visitElement(psiElement);
+        if (psiElement instanceof LeafPsiElement) {
+          final String text = psiElement.getText();
+          result.append(text);
+        }
+      }
+
+      @Override public void visitXmlAttribute(XmlAttribute xmlAttribute) {
+        boolean replaced = false;
+
+        if (xmlAttribute.isNamespaceDeclaration()) {
+          replaced = true;
+          final String value = xmlAttribute.getValue();
+          result.append(xmlAttribute.getText()).append(" ");
+
+          if (!scannedToFileName.containsKey(value)) {
+            final XmlNSDescriptor nsDescriptor = xmlAttribute.getParent().getNSDescriptor(value, true);
+
+            if (nsDescriptor != null) {
+              processAndSaveAllSchemas(nsDescriptor.getDescriptorFile(), scannedToFileName, schemaReferenceProcessor);
+            }
+          }
+        } else if ("schemaLocation".equals(xmlAttribute.getName())) {
+          final PsiReference[] references = xmlAttribute.getValueElement().getReferences();
+
+          if (references.length > 0) {
+            PsiElement psiElement = references[0].resolve();
+
+            if (psiElement instanceof XmlFile) {
+              final String s = processAndSaveAllSchemas(((XmlFile) psiElement), scannedToFileName, schemaReferenceProcessor);
+              if (s != null) {
+                result.append(xmlAttribute.getName()).append("='").append(s).append('\'');
+                replaced = true;
+              }
+            }
+          }
+        }
+        if (!replaced) result.append(xmlAttribute.getText());
+      }
+    });
+
+    final VirtualFile virtualFile = file.getVirtualFile();
+    final String content = result.toString();
+
+    byte[] bytes;
+    if (virtualFile != null) {
+      bytes = content.getBytes(virtualFile.getCharset());
+    } else {
+      try {
+        final String charsetName = XmlUtil.extractXmlEncodingFromProlog(content.getBytes());
+        bytes = charsetName != null ? content.getBytes(charsetName) : content.getBytes();
+      } catch (UnsupportedEncodingException e) {
+        bytes = content.getBytes();
+      }
+    }
+
+    schemaReferenceProcessor.processSchema(fileName, bytes);
+    return fileName;
+  }
+
+  public interface SchemaReferenceProcessor {
+    void processSchema(String schemaFileName, byte[] schemaContent);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsLoaderComponent.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsLoaderComponent.java
new file mode 100644
index 0000000..be1aece
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsLoaderComponent.java
@@ -0,0 +1,74 @@
+
+package com.intellij.xml.breadcrumbs;
+
+import com.intellij.application.options.editor.WebEditorOptions;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.fileEditor.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiManager;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author spleaner
+ */
+public class BreadcrumbsLoaderComponent extends AbstractProjectComponent {  
+
+  public BreadcrumbsLoaderComponent(@NotNull final Project project) {
+    super(project);
+  }
+
+  @NonNls
+  @NotNull
+  public String getComponentName() {
+    return "HtmlBreadcrumbsComponent";
+  }
+
+  public void initComponent() {
+    myProject.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new MyFileEditorManagerListener());
+  }
+
+  private static boolean isEnabled() {
+    final WebEditorOptions webEditorOptions = WebEditorOptions.getInstance();
+    return webEditorOptions.isBreadcrumbsEnabled() || webEditorOptions.isBreadcrumbsEnabledInXml();
+  }
+
+  private static class MyFileEditorManagerListener extends FileEditorManagerAdapter {
+    public void fileOpened(final FileEditorManager source, final VirtualFile file) {
+      if (isEnabled() && isSuitable(source.getProject(), file)) {
+        final FileEditor[] fileEditors = source.getEditors(file);
+        for (final FileEditor fileEditor : fileEditors) {
+          if (fileEditor instanceof TextEditor) {
+            final BreadcrumbsXmlWrapper wrapper = new BreadcrumbsXmlWrapper(((TextEditor)fileEditor).getEditor());
+            final JComponent c = wrapper.getComponent();
+            source.addTopComponent(fileEditor, c);
+
+            Disposer.register(fileEditor, wrapper);
+            Disposer.register(fileEditor, new Disposable() {
+              public void dispose() {
+                source.removeTopComponent(fileEditor, c);
+              }
+            });
+          }
+        }
+      }
+    }
+
+    private static boolean isSuitable(final Project project, final VirtualFile file) {
+      if (file instanceof HttpVirtualFile) {
+        return false;
+      }
+
+      final FileViewProvider provider = PsiManager.getInstance(project).findViewProvider(file);
+
+      return provider != null && BreadcrumbsXmlWrapper.findInfoProvider(provider) != null;
+    }
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsPsiItem.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsPsiItem.java
new file mode 100644
index 0000000..f0c6c75
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsPsiItem.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.breadcrumbs;
+
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author spleaner
+ */
+public class BreadcrumbsPsiItem extends BreadcrumbsItem {
+  private final PsiElement myElement;
+  private final BreadcrumbsInfoProvider myProvider;
+  private CrumbPresentation myPresentation;
+
+  public BreadcrumbsPsiItem(@NotNull final PsiElement element, @NotNull final BreadcrumbsInfoProvider provider) {
+    myElement = element;
+    myProvider = provider;
+  }
+
+  public void setPresentation(CrumbPresentation presentation) {
+    myPresentation = presentation;
+  }
+
+  public String getDisplayText() {
+    return isValid() ? myProvider.getElementInfo(myElement) : "INVALID";
+  }
+
+  public String getTooltip() {
+    final String s = isValid() ? myProvider.getElementTooltip(myElement) : "";
+    return s == null ? "" : s;
+  }
+
+  @Override
+  public CrumbPresentation getPresentation() {
+    return myPresentation;
+  }
+
+  public boolean isValid() {
+    return myElement != null && myElement.isValid();
+  }
+
+  public PsiElement getPsiElement() {
+    return myElement;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java
new file mode 100644
index 0000000..56b9b06
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java
@@ -0,0 +1,407 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.breadcrumbs;
+
+import com.intellij.application.options.editor.WebEditorOptions;
+import com.intellij.lang.Language;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.colors.EditorFontType;
+import com.intellij.openapi.editor.event.CaretEvent;
+import com.intellij.openapi.editor.event.CaretListener;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vcs.FileStatusListener;
+import com.intellij.openapi.vcs.FileStatusManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.update.MergingUpdateQueue;
+import com.intellij.util.ui.update.UiNotifyConnector;
+import com.intellij.util.ui.update.Update;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.PriorityQueue;
+
+/**
+ * @author spleaner
+ */
+public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener<BreadcrumbsPsiItem>, Disposable {
+  private final BreadcrumbsComponent<BreadcrumbsPsiItem> myComponent;
+  private final Project myProject;
+  private Editor myEditor;
+  private final VirtualFile myFile;
+  private boolean myUserCaretChange;
+  private final MergingUpdateQueue myQueue;
+  private final BreadcrumbsInfoProvider myInfoProvider;
+  private final JPanel myWrapperPanel;
+
+  public static final Key<BreadcrumbsXmlWrapper> BREADCRUMBS_COMPONENT_KEY = new Key<BreadcrumbsXmlWrapper>("BREADCRUMBS_KEY");
+
+  public BreadcrumbsXmlWrapper(@NotNull final Editor editor) {
+    myEditor = editor;
+    myEditor.putUserData(BREADCRUMBS_COMPONENT_KEY, this);
+
+    final Project project = editor.getProject();
+    assert project != null;
+    myProject = project;
+
+    Document document = myEditor.getDocument();
+    myFile = FileDocumentManager.getInstance().getFile(document);
+
+
+    final FileStatusManager manager = FileStatusManager.getInstance(project);
+    manager.addFileStatusListener(new FileStatusListener() {
+      public void fileStatusesChanged() {
+        if (myComponent != null && myEditor != null) {
+          final Font editorFont = myEditor.getColorsScheme().getFont(EditorFontType.PLAIN);
+          myComponent.setFont(editorFont.deriveFont(Font.PLAIN, editorFont.getSize2D()));
+          updateCrumbs(myEditor.getCaretModel().getLogicalPosition());
+        }
+      }
+
+      public void fileStatusChanged(@NotNull final VirtualFile virtualFile) {
+      }
+    }, this);
+
+
+    myInfoProvider = findInfoProvider(findViewProvider(myFile, myProject));
+
+    final CaretListener caretListener = new CaretListener() {
+      public void caretPositionChanged(final CaretEvent e) {
+        if (myUserCaretChange) {
+          queueUpdate(editor);
+        }
+
+        myUserCaretChange = true;
+      }
+    };
+
+    editor.getCaretModel().addCaretListener(caretListener);
+    Disposer.register(this, new Disposable() {
+      public void dispose() {
+        editor.getCaretModel().removeCaretListener(caretListener);
+      }
+    });
+
+    PsiManager.getInstance(project).addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
+      @Override
+      public void propertyChanged(@NotNull PsiTreeChangeEvent event) {
+        PsiFile psiFile = event.getFile();
+        VirtualFile file = psiFile == null ? null : psiFile.getVirtualFile();
+        if (!Comparing.equal(file, myFile)) return;
+        queueUpdate(editor);
+      }
+
+      @Override
+      public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
+        propertyChanged(event);
+      }
+
+      @Override
+      public void childMoved(@NotNull PsiTreeChangeEvent event) {
+        propertyChanged(event);
+      }
+
+      @Override
+      public void childReplaced(@NotNull PsiTreeChangeEvent event) {
+        propertyChanged(event);
+      }
+
+      @Override
+      public void childRemoved(@NotNull PsiTreeChangeEvent event) {
+        propertyChanged(event);
+      }
+
+      @Override
+      public void childAdded(@NotNull PsiTreeChangeEvent event) {
+        propertyChanged(event);
+      }
+    },this);
+
+    myComponent = new BreadcrumbsComponent<BreadcrumbsPsiItem>();
+    myComponent.addBreadcrumbsItemListener(this);
+
+    final Font editorFont = editor.getColorsScheme().getFont(EditorFontType.PLAIN);
+    myComponent.setFont(editorFont.deriveFont(Font.PLAIN, editorFont.getSize2D()));
+
+    final ComponentAdapter resizeListener = new ComponentAdapter() {
+      public void componentResized(final ComponentEvent e) {
+        queueUpdate(editor);
+      }
+    };
+
+    myComponent.addComponentListener(resizeListener);
+    Disposer.register(this, new Disposable() {
+      public void dispose() {
+        myComponent.removeComponentListener(resizeListener);
+      }
+    });
+
+    myQueue = new MergingUpdateQueue("Breadcrumbs.Queue", 200, true, myComponent);
+    myQueue.queue(new MyUpdate(this, editor));
+
+    Disposer.register(this, new UiNotifyConnector(myComponent, myQueue));
+    Disposer.register(this, myQueue);
+
+    myWrapperPanel = new JPanel();
+    myWrapperPanel.setLayout(new BorderLayout());
+    myWrapperPanel.setBorder(BorderFactory.createEmptyBorder(2, 2, 1, 2));
+    myWrapperPanel.setOpaque(false);
+
+    myWrapperPanel.add(myComponent, BorderLayout.CENTER);
+  }
+
+  public void queueUpdate(Editor editor) {
+    myQueue.cancelAllUpdates();
+    myQueue.queue(new MyUpdate(this, editor));
+  }
+
+  private void moveEditorCaretTo(@NotNull final PsiElement element) {
+    if (element.isValid()) {
+      setUserCaretChange(false);
+      myEditor.getCaretModel().moveToOffset(element.getTextOffset());
+      myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
+    }
+  }
+
+  @Nullable
+  private static BreadcrumbsInfoProvider findProviderForElement(@NotNull final PsiElement element,
+                                                                final BreadcrumbsInfoProvider defaultProvider) {
+    final BreadcrumbsInfoProvider provider = getInfoProvider(element.getLanguage());
+    return provider == null ? defaultProvider : provider;
+  }
+
+  private static PsiElement[] toPsiElementArray(Collection<BreadcrumbsPsiItem> items) {
+    final PsiElement[] elements = new PsiElement[items.size()];
+    int index = 0;
+    for (BreadcrumbsPsiItem item : items) {
+      elements[index++] = item.getPsiElement();
+    }
+    return elements;
+  }
+
+  @Nullable
+  private static CrumbPresentation[] getCrumbPresentations(final PsiElement[] elements) {
+    for (BreadcrumbsPresentationProvider provider : BreadcrumbsPresentationProvider.EP_NAME.getExtensions()) {
+      final CrumbPresentation[] presentations = provider.getCrumbPresentations(elements);
+      if (presentations != null) {
+        return presentations;
+      }
+    }
+    return null;
+  }
+
+  private void setUserCaretChange(final boolean userCaretChange) {
+    myUserCaretChange = userCaretChange;
+  }
+
+  @Nullable
+  private static LinkedList<BreadcrumbsPsiItem> getPresentableLineElements(@NotNull final LogicalPosition position,
+                                                                           final VirtualFile file,
+                                                                           final Editor editor,
+                                                                           final Project project,
+                                                                           final BreadcrumbsInfoProvider defaultInfoProvider) {
+    final LinkedList<BreadcrumbsPsiItem> result =
+      getLineElements(editor.logicalPositionToOffset(position), file, project, defaultInfoProvider);
+
+    if (result == null) return null;
+
+    final PsiElement[] elements = toPsiElementArray(result);
+    final CrumbPresentation[] presentations = getCrumbPresentations(elements);
+    if (presentations != null) {
+      int i = 0;
+      for (BreadcrumbsPsiItem item : result) {
+        item.setPresentation(presentations[i++]);
+      }
+    }
+
+    return result;
+  }
+
+  @Nullable
+  public static PsiElement[] getLinePsiElements(int offset, VirtualFile file, Project project, BreadcrumbsInfoProvider infoProvider) {
+    final LinkedList<BreadcrumbsPsiItem> lineElements = getLineElements(offset, file, project, infoProvider);
+    return lineElements != null ? toPsiElementArray(lineElements) : null;
+  }
+
+  @Nullable
+  private static LinkedList<BreadcrumbsPsiItem> getLineElements(final int offset,
+                                                                VirtualFile file,
+                                                                Project project,
+                                                                BreadcrumbsInfoProvider defaultInfoProvider) {
+    PsiElement element = findFirstBreadcrumbedElement(offset, file, project, defaultInfoProvider);
+    if (element == null) return null;
+
+    final LinkedList<BreadcrumbsPsiItem> result = new LinkedList<BreadcrumbsPsiItem>();
+    while (element != null) {
+      BreadcrumbsInfoProvider provider = findProviderForElement(element, defaultInfoProvider);
+
+      if (provider != null && provider.acceptElement(element)) {
+        result.addFirst(new BreadcrumbsPsiItem(element, provider));
+      }
+
+      element = (provider != null) ? provider.getParent(element) : element.getParent();
+    }
+    return result;
+  }
+
+  @Nullable
+  private static PsiElement findFirstBreadcrumbedElement(final int offset,
+                                                         final VirtualFile file,
+                                                         final Project project,
+                                                         final BreadcrumbsInfoProvider defaultInfoProvider) {
+    if (file == null || !file.isValid()) return null;
+
+    PriorityQueue<PsiElement> leafs = new PriorityQueue<PsiElement>(3, new Comparator<PsiElement>() {
+      public int compare(final PsiElement o1, final PsiElement o2) {
+        return o2.getTextRange().getStartOffset() - o1.getTextRange().getStartOffset();
+      }
+    });
+    FileViewProvider viewProvider = findViewProvider(file, project);
+    if (viewProvider == null) return null;
+
+    for (final Language language : viewProvider.getLanguages()) {
+      ContainerUtil.addIfNotNull(viewProvider.findElementAt(offset, language), leafs);
+    }
+    while (!leafs.isEmpty()) {
+      final PsiElement element = leafs.remove();
+      if (!element.isValid()) continue;
+
+      BreadcrumbsInfoProvider provider = findProviderForElement(element, defaultInfoProvider);
+      if (provider != null && provider.acceptElement(element)) {
+        return element;
+      }
+      if (!(element instanceof PsiFile)) {
+        ContainerUtil.addIfNotNull(element.getParent(), leafs);
+      }
+    }
+    return null;
+  }
+
+  @Nullable
+  private static FileViewProvider findViewProvider(final VirtualFile file, final Project project) {
+    if (file == null) return null;
+    return PsiManager.getInstance(project).findViewProvider(file);
+  }
+
+  private void updateCrumbs(final LogicalPosition position) {
+    if (myFile != null && myEditor != null) {
+      if (PsiDocumentManager.getInstance(myProject).isUncommited(myEditor.getDocument())) {
+        return;
+      }
+
+      myComponent.setItems(getPresentableLineElements(position, myFile, myEditor, myProject, myInfoProvider));
+    }
+  }
+
+  @Nullable
+  public static BreadcrumbsInfoProvider findInfoProvider(@Nullable FileViewProvider viewProvider) {
+    BreadcrumbsInfoProvider provider = null;
+    if (viewProvider != null) {
+      final WebEditorOptions webEditorOptions = WebEditorOptions.getInstance();
+      final Language baseLang = viewProvider.getBaseLanguage();
+      provider = getInfoProvider(baseLang);
+      if (!webEditorOptions.isBreadcrumbsEnabledInXml() && baseLang == XMLLanguage.INSTANCE) return null;
+      if (!webEditorOptions.isBreadcrumbsEnabled() && baseLang != XMLLanguage.INSTANCE) return null;
+      if (provider == null) {
+        for (final Language language : viewProvider.getLanguages()) {
+          provider = getInfoProvider(language);
+          if (provider != null) {
+            break;
+          }
+        }
+      }
+    }
+    return provider;
+  }
+
+  public JComponent getComponent() {
+    return myWrapperPanel;
+  }
+
+  public void itemSelected(@NotNull final BreadcrumbsPsiItem item, final int modifiers) {
+    final PsiElement psiElement = item.getPsiElement();
+    moveEditorCaretTo(psiElement);
+
+    if ((modifiers & Event.SHIFT_MASK) == Event.SHIFT_MASK || (modifiers & Event.META_MASK) == Event.META_MASK) {
+      final TextRange range = psiElement.getTextRange();
+      myEditor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
+    }
+  }
+
+  @Nullable
+  public static BreadcrumbsXmlWrapper getBreadcrumbsComponent(@NotNull Editor editor) {
+    return editor.getUserData(BREADCRUMBS_COMPONENT_KEY);
+  }
+
+  public void dispose() {
+    myEditor.putUserData(BREADCRUMBS_COMPONENT_KEY, null);
+    myEditor = null;
+  }
+
+  @Nullable
+  private static BreadcrumbsInfoProvider getInfoProvider(@NotNull final Language language) {
+    for (final BreadcrumbsInfoProvider provider : Extensions.getExtensions(BreadcrumbsInfoProvider.EP_NAME)) {
+      for (final Language language1 : provider.getLanguages()) {
+        if (language.isKindOf(language1)) {
+          return provider;
+        }
+      }
+    }
+
+    return null;
+  }
+
+  private class MyUpdate extends Update {
+    private final BreadcrumbsXmlWrapper myBreadcrumbsComponent;
+    private final Editor myEditor;
+
+    public MyUpdate(@NonNls final BreadcrumbsXmlWrapper c, @NotNull final Editor editor) {
+      super(c);
+
+      myBreadcrumbsComponent = c;
+      myEditor = editor;
+    }
+
+    public void run() {
+      myBreadcrumbsComponent.updateCrumbs(myEditor.getCaretModel().getLogicalPosition());
+    }
+
+    public boolean canEat(final Update update) {
+      return true;
+    }
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/XmlLanguageBreadcrumbsInfoProvider.java b/xml/impl/src/com/intellij/xml/breadcrumbs/XmlLanguageBreadcrumbsInfoProvider.java
new file mode 100644
index 0000000..9f736ee
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/breadcrumbs/XmlLanguageBreadcrumbsInfoProvider.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: spleaner
+ * Date: Jun 19, 2007
+ * Time: 4:44:25 PM
+ */
+package com.intellij.xml.breadcrumbs;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.StringTokenizer;
+
+public class XmlLanguageBreadcrumbsInfoProvider extends BreadcrumbsInfoProvider {
+  @NonNls private static final String CLASS_ATTRIBUTE_NAME = "class";
+  @NonNls private static final String ID_ATTRIBUTE_NAME = "id";
+
+  public boolean acceptElement(@NotNull final PsiElement e) {
+    return e instanceof XmlTag && e.isValid();
+  }
+
+  public Language[] getLanguages() {
+    return new Language[]{XMLLanguage.INSTANCE, XHTMLLanguage.INSTANCE, HTMLLanguage.INSTANCE};
+  }
+
+  @NotNull
+  public String getElementInfo(@NotNull final PsiElement e) {
+    final XmlTag tag = (XmlTag)e;
+    final StringBuffer sb = new StringBuffer();
+
+    sb.append(tag.getName());
+
+    final boolean addHtmlInfo = e.getContainingFile().getLanguage() != XMLLanguage.INSTANCE;
+
+    if (addHtmlInfo) {
+      final String id_value = tag.getAttributeValue(ID_ATTRIBUTE_NAME);
+      if (null != id_value) {
+        sb.append("#").append(id_value);
+      }
+
+      final String class_value = tag.getAttributeValue(CLASS_ATTRIBUTE_NAME);
+      if (null != class_value) {
+        final StringTokenizer tokenizer = new StringTokenizer(class_value, " ");
+        while (tokenizer.hasMoreTokens()) {
+          sb.append(".").append(tokenizer.nextToken());
+        }
+      }
+    }
+
+    return sb.toString();
+  }
+
+  @Nullable
+  public String getElementTooltip(@NotNull final PsiElement e) {
+    final XmlTag tag = (XmlTag)e;
+    final StringBuffer result = new StringBuffer("&lt;");
+    result.append(tag.getName());
+    final XmlAttribute[] attributes = tag.getAttributes();
+    for (final XmlAttribute each : attributes) {
+      result.append(" ").append(each.getText());
+    }
+
+    if (tag.isEmpty()) {
+      result.append("/&gt;");
+    }
+    else {
+      result.append("&gt;...&lt;/").append(tag.getName()).append("&gt;");
+    }
+
+    return result.toString();
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/config/ConfigFileSearcher.java b/xml/impl/src/com/intellij/xml/config/ConfigFileSearcher.java
new file mode 100644
index 0000000..20317e8
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/config/ConfigFileSearcher.java
@@ -0,0 +1,65 @@
+package com.intellij.xml.config;
+
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.JarFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Set;
+
+public abstract class ConfigFileSearcher {
+
+  private final MultiMap<Module, PsiFile> myFiles = new MultiMap<Module, PsiFile>();
+  private final MultiMap<VirtualFile, PsiFile> myJars = new MultiMap<VirtualFile, PsiFile>();
+  private final MultiMap<VirtualFile, PsiFile> myVirtualFiles = new MultiMap<VirtualFile, PsiFile>();
+  private final @Nullable Module myModule;
+  @NotNull private final Project myProject;
+
+  public ConfigFileSearcher(@Nullable Module module, @NotNull Project project) {
+    myModule = module;
+    myProject = project;
+  }
+
+  public void search() {
+    myFiles.clear();
+    myJars.clear();
+
+    PsiManager psiManager = PsiManager.getInstance(myProject);
+    for (PsiFile file : search(myModule, myProject)) {
+      VirtualFile jar = JarFileSystem.getInstance().getVirtualFileForJar(file.getVirtualFile());
+      if (jar != null) {
+        myJars.putValue(jar, file);
+      }
+      else {
+        Module module = ModuleUtilCore.findModuleForPsiElement(file);
+        if (module != null) {
+          myFiles.putValue(module, file);
+        }
+        else {
+          VirtualFile virtualFile = file.getVirtualFile();
+          myVirtualFiles.putValue(virtualFile.getParent(), psiManager.findFile(virtualFile));
+        }
+      }
+    }
+  }
+
+  public abstract Set<PsiFile> search(@Nullable Module module, @NotNull Project project);
+
+  public MultiMap<Module, PsiFile> getFilesByModules() {
+    return myFiles;
+  }
+
+  public MultiMap<VirtualFile, PsiFile> getJars() {
+    return myJars;
+  }
+
+  public MultiMap<VirtualFile, PsiFile> getVirtualFiles() {
+    return myVirtualFiles;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/config/ConfigFilesTreeBuilder.java b/xml/impl/src/com/intellij/xml/config/ConfigFilesTreeBuilder.java
new file mode 100644
index 0000000..f71505f
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/config/ConfigFilesTreeBuilder.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.config;
+
+import com.intellij.ide.presentation.VirtualFilePresentation;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleType;
+import com.intellij.openapi.vfs.JarFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.ui.TreeSpeedSearch;
+import com.intellij.util.containers.Convertor;
+import com.intellij.util.containers.MultiMap;
+
+import javax.swing.*;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+import java.util.*;
+
+/**
+ * @author Dmitry Avdeev
+ *         Date: 7/17/12
+ */
+public class ConfigFilesTreeBuilder {
+
+  private final JTree myTree;
+
+  public ConfigFilesTreeBuilder(JTree tree) {
+    myTree = tree;
+    installSearch(tree);
+  }
+
+  public Set<PsiFile> buildTree(ConfigFileSearcher searcher, DefaultMutableTreeNode root) {
+
+    final MultiMap<Module,PsiFile> files = searcher.getFilesByModules();
+    final MultiMap<VirtualFile, PsiFile> jars = searcher.getJars();
+    final Set<PsiFile> psiFiles = buildModuleNodes(files, jars, root);
+    final MultiMap<VirtualFile, PsiFile> virtualFiles = searcher.getVirtualFiles();
+
+    for (Map.Entry<VirtualFile, Collection<PsiFile>> entry : virtualFiles.entrySet()) {
+      DefaultMutableTreeNode node = createFileNode(entry.getKey());
+      List<PsiFile> list = new ArrayList<PsiFile>(entry.getValue());
+      Collections.sort(list, new Comparator<PsiFile>() {
+        @Override
+        public int compare(PsiFile o1, PsiFile o2) {
+          return o1.getName().compareToIgnoreCase(o2.getName());
+        }
+      });
+      for (PsiFile file : list) {
+        node.add(createFileNode(file));
+      }
+      root.add(node);
+    }
+    return psiFiles;
+  }
+
+
+  public void addFile(VirtualFile file) {
+    final DefaultMutableTreeNode root = (DefaultMutableTreeNode)myTree.getModel().getRoot();
+    final DefaultMutableTreeNode treeNode = createFileNode(file);
+    root.add(treeNode);
+    DefaultTreeModel model = (DefaultTreeModel)myTree.getModel();
+    model.nodeStructureChanged(root);
+  }
+
+  public Set<PsiFile> buildModuleNodes(final MultiMap<Module,PsiFile> files,
+                               final MultiMap<VirtualFile, PsiFile> jars,
+                               DefaultMutableTreeNode root) {
+
+    final HashSet<PsiFile> psiFiles = new HashSet<PsiFile>();
+    final List<Module> modules = new ArrayList<Module>(files.keySet());
+    Collections.sort(modules, new Comparator<Module>() {
+      public int compare(final Module o1, final Module o2) {
+        return o1.getName().compareTo(o2.getName());
+      }
+    });
+    for (Module module: modules) {
+      DefaultMutableTreeNode moduleNode = createFileNode(module);
+      root.add(moduleNode);
+      if (files.containsKey(module)) {
+        List<PsiFile> moduleFiles = new ArrayList<PsiFile>(files.get(module));
+        Collections.sort(moduleFiles, FILE_COMPARATOR);
+        for (PsiFile file: moduleFiles) {
+          final DefaultMutableTreeNode fileNode = createFileNode(file);
+          moduleNode.add(fileNode);
+          psiFiles.add(file);
+        }
+      }
+    }
+    for (VirtualFile file: jars.keySet()) {
+      final List<PsiFile> list = new ArrayList<PsiFile>(jars.get(file));
+      final PsiFile jar = list.get(0).getManager().findFile(file);
+      if (jar != null) {
+        final DefaultMutableTreeNode jarNode = createFileNode(jar);
+        root.add(jarNode);
+        Collections.sort(list, FILE_COMPARATOR);
+        for (PsiFile psiFile: list) {
+          jarNode.add(createFileNode(psiFile));
+          psiFiles.add(psiFile);
+        }
+      }
+    }
+    return psiFiles;
+  }
+
+  protected DefaultMutableTreeNode createFileNode(Object file) {
+    return new DefaultMutableTreeNode(file);
+  }
+
+  private static final Comparator<PsiFile> FILE_COMPARATOR = new Comparator<PsiFile>() {
+    public int compare(final PsiFile o1, final PsiFile o2) {
+      return o1.getName().compareTo(o2.getName());
+    }
+  };
+
+  public static void renderNode(Object value, boolean expanded, ColoredTreeCellRenderer renderer) {
+    if (!(value instanceof DefaultMutableTreeNode)) return;
+    final Object object = ((DefaultMutableTreeNode)value).getUserObject();
+    if (object instanceof Module) {
+      final Module module = (Module)object;
+      final Icon icon = ModuleType.get(module).getIcon();
+      renderer.setIcon(icon);
+      final String moduleName = module.getName();
+      renderer.append(moduleName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
+    } else if (object instanceof PsiFile) {
+      final PsiFile psiFile = (PsiFile)object;
+      final Icon icon = psiFile.getIcon(0);
+      renderer.setIcon(icon);
+      final String fileName = psiFile.getName();
+      renderer.append(fileName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
+      final VirtualFile virtualFile = psiFile.getVirtualFile();
+      if (virtualFile != null) {
+        String path = virtualFile.getPath();
+        final int i = path.indexOf(JarFileSystem.JAR_SEPARATOR);
+        if (i >= 0) {
+          path = path.substring(i + JarFileSystem.JAR_SEPARATOR.length());
+        }
+        renderer.append(" (" + path + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
+      }
+    } else if (object instanceof VirtualFile) {
+      VirtualFile file = (VirtualFile)object;
+      renderer.setIcon(VirtualFilePresentation.getIcon(file));
+      renderer.append(file.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+      String path = file.getPath();
+      final int i = path.indexOf(JarFileSystem.JAR_SEPARATOR);
+      if (i >= 0) {
+        path = path.substring(i + JarFileSystem.JAR_SEPARATOR.length());
+      }
+      renderer.append(" (" + path + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
+    }
+  }
+
+  public static void installSearch(JTree tree) {
+    new TreeSpeedSearch(tree, new Convertor<TreePath, String>() {
+      public String convert(final TreePath treePath) {
+        final Object object = ((DefaultMutableTreeNode)treePath.getLastPathComponent()).getUserObject();
+        if (object instanceof Module) {
+          return ((Module)object).getName();
+        } else if (object instanceof PsiFile) {
+          return ((PsiFile)object).getName();
+        } else if (object instanceof VirtualFile) {
+          return ((VirtualFile)object).getName();
+        } else {
+          return "";
+        }
+      }
+    });
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java b/xml/impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java
new file mode 100644
index 0000000..020baa8
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: mike
+ * Date: Aug 27, 2002
+ * Time: 9:55:06 PM
+ * To change template for new class use
+ * Code Style | Class Templates options (Tools | IDE Options).
+ */
+package com.intellij.xml.impl;
+
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class BasicXmlAttributeDescriptor implements XmlAttributeDescriptor {
+  public String validateValue(XmlElement context, String value) {
+    if (isFixed()) {
+      String defaultValue = getDefaultValue();
+
+      if (defaultValue != null && !defaultValue.equals(value)) {
+        return XmlErrorMessages.message("attribute.should.have.fixed.value", getName(), defaultValue);
+      }
+    }
+
+    if (isEnumerated(context) && XmlUtil.isSimpleXmlAttributeValue(value, (XmlAttributeValue)context)) {
+      String[] values = getEnumeratedValues(context);
+      boolean valueWasFound = false;
+
+      for (String enumValue : values) {
+        if (enumValue.equals(value)) {
+          valueWasFound = true;
+          break;
+        }
+      }
+
+      if (!valueWasFound) {
+        return XmlErrorMessages.message("wrong.attribute.value");
+      }
+    }
+
+    return null;
+  }
+
+  public String getName(PsiElement context){
+    return getName();
+  }
+
+  @Nullable
+  public String[] getEnumeratedValues(@Nullable XmlElement context) {
+    return getEnumeratedValues();
+  }
+
+  public boolean isEnumerated(@Nullable XmlElement context) {
+    return isEnumerated();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/ExternalDocumentValidator.java b/xml/impl/src/com/intellij/xml/impl/ExternalDocumentValidator.java
new file mode 100644
index 0000000..e8371ca
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/ExternalDocumentValidator.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl;
+
+import com.intellij.codeInsight.daemon.HighlightDisplayKey;
+import com.intellij.codeInsight.daemon.Validator;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.InspectionProfile;
+import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.ide.highlighter.XHtmlFileType;
+import com.intellij.ide.highlighter.XmlFileType;
+import com.intellij.lang.Language;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.reference.SoftReference;
+import com.intellij.xml.actions.ValidateXmlActionHandler;
+import com.intellij.xml.util.CheckXmlFileWithXercesValidatorInspection;
+import com.intellij.xml.util.XmlResourceResolver;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.xml.sax.SAXParseException;
+
+import java.lang.ref.WeakReference;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author maxim
+ */
+public class ExternalDocumentValidator {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.impl.ExternalDocumentValidator");
+  private static final Key<SoftReference<ExternalDocumentValidator>> validatorInstanceKey = Key.create("validatorInstance");
+  private ValidateXmlActionHandler myHandler;
+  private Validator.ValidationHost myHost;
+
+  private long myModificationStamp;
+  private PsiFile myFile;
+  @NonNls
+  private static final String CANNOT_FIND_DECLARATION_ERROR_PREFIX = "Cannot find the declaration of element";
+  @NonNls
+  private static final String ELEMENT_ERROR_PREFIX = "Element";
+  @NonNls
+  private static final String ROOT_ELEMENT_ERROR_PREFIX = "Document root element";
+  @NonNls
+  private static final String CONTENT_OF_ELEMENT_TYPE_ERROR_PREFIX = "The content of element type";
+  @NonNls
+  private static final String VALUE_ERROR_PREFIX = "Value ";
+  @NonNls
+  private static final String ATTRIBUTE_ERROR_PREFIX = "Attribute ";
+  @NonNls
+  private static final String STRING_ERROR_PREFIX = "The string";
+  @NonNls
+  private static final String ATTRIBUTE_MESSAGE_PREFIX = "cvc-attribute.";
+
+  private static class ValidationInfo {
+    PsiElement element;
+    String message;
+    int type;
+  }
+
+  private WeakReference<List<ValidationInfo>> myInfos; // last jaxp validation result
+
+  private void runJaxpValidation(final XmlElement element, Validator.ValidationHost host) {
+    final PsiFile file = element.getContainingFile();
+
+    if (myFile == file &&
+        file != null &&
+        myModificationStamp == file.getModificationStamp() &&
+        !ValidateXmlActionHandler.isValidationDependentFilesOutOfDate((XmlFile)file) &&
+        myInfos!=null &&
+        myInfos.get()!=null // we have validated before
+        ) {
+      addAllInfos(host,myInfos.get());
+      return;
+    }
+
+    if (myHandler==null)  myHandler = new ValidateXmlActionHandler(false);
+    final Project project = element.getProject();
+
+    final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
+    if (document==null) return;
+    final List<ValidationInfo> results = new LinkedList<ValidationInfo>();
+
+    myHost = new Validator.ValidationHost() {
+      public void addMessage(PsiElement context, String message, int type) {
+        final ValidationInfo o = new ValidationInfo();
+
+        results.add(o);
+        o.element = context;
+        o.message = message;
+        o.type = type;
+      }
+
+      public void addMessage(final PsiElement context, final String message, final ErrorType type, final IntentionAction... fixes) {
+        addMessage(context, message, type.ordinal());
+      }
+    };
+
+    myHandler.setErrorReporter(myHandler.new ErrorReporter() {
+      public boolean isStopOnUndeclaredResource() {
+        return true;
+      }
+
+      public void processError(final SAXParseException e, final boolean warning) {
+        try {
+          ApplicationManager.getApplication().runReadAction(new Runnable() {
+            public void run() {
+              if (e.getPublicId() != null) {
+                return;
+              }
+
+              final VirtualFile errorFile = myHandler.getFile(e.getPublicId(), e.getSystemId());
+              if (!Comparing.equal(errorFile, file.getVirtualFile()) && errorFile != null) {
+                return; // error in attached schema
+              }
+
+              if (document.getLineCount() < e.getLineNumber() || e.getLineNumber() <= 0) {
+                return;
+              }
+
+              int offset = Math.max(0, document.getLineStartOffset(e.getLineNumber() - 1) + e.getColumnNumber() - 2);
+              if (offset >= document.getTextLength()) return;
+              PsiElement currentElement = PsiDocumentManager.getInstance(project).getPsiFile(document).findElementAt(offset);
+              PsiElement originalElement = currentElement;
+              final String elementText = currentElement.getText();
+
+              if (elementText.equals("</")) {
+                currentElement = currentElement.getNextSibling();
+              }
+              else if (elementText.equals(">") || elementText.equals("=")) {
+                currentElement = currentElement.getPrevSibling();
+              }
+
+              // Cannot find the declaration of element
+              String localizedMessage = e.getLocalizedMessage();
+
+              // Ideally would be to switch one messageIds
+              int endIndex = localizedMessage.indexOf(':');
+              if (endIndex < localizedMessage.length() - 1 && localizedMessage.charAt(endIndex + 1) == '/') {
+                endIndex = -1;  // ignore : in http://
+              }
+              String messageId = endIndex != -1 ? localizedMessage.substring(0, endIndex ):"";
+              localizedMessage = localizedMessage.substring(endIndex + 1).trim();
+
+              if (localizedMessage.startsWith(CANNOT_FIND_DECLARATION_ERROR_PREFIX) ||
+                  localizedMessage.startsWith(ELEMENT_ERROR_PREFIX) ||
+                  localizedMessage.startsWith(ROOT_ELEMENT_ERROR_PREFIX) ||
+                  localizedMessage.startsWith(CONTENT_OF_ELEMENT_TYPE_ERROR_PREFIX)
+                  ) {
+                addProblemToTagName(currentElement, originalElement, localizedMessage, warning);
+                //return;
+              } else if (localizedMessage.startsWith(VALUE_ERROR_PREFIX)) {
+                addProblemToTagName(currentElement, originalElement, localizedMessage, warning);
+              } else if (messageId.startsWith(ATTRIBUTE_MESSAGE_PREFIX)) {
+                @NonNls String prefix = "of attribute ";
+                final int i = localizedMessage.indexOf(prefix);
+                
+                if (i != -1) {
+                  int messagePrefixLength = prefix.length() + i;
+                  final int nextQuoteIndex = localizedMessage.indexOf(localizedMessage.charAt(messagePrefixLength), messagePrefixLength + 1);
+                  String attrName = nextQuoteIndex == -1 ? null : localizedMessage.substring(messagePrefixLength + 1, nextQuoteIndex);
+
+                  XmlTag parent = PsiTreeUtil.getParentOfType(originalElement,XmlTag.class);
+                  currentElement = parent.getAttribute(attrName,null);
+
+                  if (currentElement != null) {
+                    currentElement = ((XmlAttribute)currentElement).getValueElement();
+                  }
+                }
+
+                if (currentElement!=null) {
+                  assertValidElement(currentElement, originalElement,localizedMessage);
+                  myHost.addMessage(currentElement,localizedMessage,warning ? Validator.ValidationHost.WARNING:Validator.ValidationHost.ERROR);
+                } else {
+                  addProblemToTagName(originalElement, originalElement, localizedMessage, warning);
+                }
+              }
+              else if (localizedMessage.startsWith(ATTRIBUTE_ERROR_PREFIX)) {
+                final int messagePrefixLength = ATTRIBUTE_ERROR_PREFIX.length();
+
+                if ( localizedMessage.charAt(messagePrefixLength) == '"' ||
+                     localizedMessage.charAt(messagePrefixLength) == '\''
+                   ) {
+                  // extract the attribute name from message and get it from tag!
+                  final int nextQuoteIndex = localizedMessage.indexOf(localizedMessage.charAt(messagePrefixLength), messagePrefixLength + 1);
+                  String attrName = nextQuoteIndex == -1 ? null : localizedMessage.substring(messagePrefixLength + 1, nextQuoteIndex);
+
+                  XmlTag parent = PsiTreeUtil.getParentOfType(originalElement,XmlTag.class);
+                  currentElement = parent.getAttribute(attrName,null);
+
+                  if (currentElement!=null) {
+                    currentElement = SourceTreeToPsiMap.treeElementToPsi(
+                      XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(
+                        SourceTreeToPsiMap.psiElementToTree(currentElement)
+                      )
+                    );
+                  }
+                } else {
+                  currentElement = PsiTreeUtil.getParentOfType(currentElement, XmlTag.class, false);
+                }
+
+                if (currentElement!=null) {
+                  assertValidElement(currentElement, originalElement,localizedMessage);
+                  myHost.addMessage(currentElement,localizedMessage,warning ? Validator.ValidationHost.WARNING:Validator.ValidationHost.ERROR);
+                } else {
+                  addProblemToTagName(originalElement, originalElement, localizedMessage, warning);
+                }
+              } else if (localizedMessage.startsWith(STRING_ERROR_PREFIX)) {
+                if (currentElement != null) {
+                  myHost.addMessage(currentElement,localizedMessage,Validator.ValidationHost.WARNING);
+                }
+              }
+              else {
+                currentElement = getNodeForMessage(currentElement != null ? currentElement:originalElement);
+                assertValidElement(currentElement, originalElement,localizedMessage);
+                if (currentElement!=null) {
+                  myHost.addMessage(currentElement,localizedMessage,warning ? Validator.ValidationHost.WARNING:Validator.ValidationHost.ERROR);
+                }
+              }
+            }
+          });
+        }
+        catch (Exception ex) {
+          if (ex instanceof ProcessCanceledException) throw (ProcessCanceledException)ex;
+          if (ex instanceof XmlResourceResolver.IgnoredResourceException) throw (XmlResourceResolver.IgnoredResourceException)ex;
+          LOG.error(ex);
+        }
+      }
+
+    });
+
+    myHandler.doValidate((XmlFile)element.getContainingFile());
+
+    myFile = file;
+    myModificationStamp = myFile.getModificationStamp();
+    myInfos = new WeakReference<List<ValidationInfo>>(results);
+
+    addAllInfos(host,results);
+  }
+
+  private static PsiElement getNodeForMessage(final PsiElement currentElement) {
+    PsiElement parentOfType = PsiTreeUtil.getNonStrictParentOfType(
+      currentElement,
+      XmlTag.class,
+      XmlProcessingInstruction.class,
+      XmlElementDecl.class,
+      XmlMarkupDecl.class,
+      XmlEntityRef.class,
+      XmlDoctype.class
+    );
+
+    if (parentOfType == null) {
+      if (currentElement instanceof XmlToken) {
+        parentOfType = currentElement.getParent();
+      }
+      else {
+        parentOfType = currentElement;
+      }
+    }
+    return parentOfType;
+  }
+
+  private static void addAllInfos(Validator.ValidationHost host,List<ValidationInfo> highlightInfos) {
+    for (ValidationInfo info : highlightInfos) {
+      host.addMessage(info.element, info.message, info.type);
+    }
+  }
+
+  private PsiElement addProblemToTagName(PsiElement currentElement,
+                                     final PsiElement originalElement,
+                                     final String localizedMessage,
+                                     final boolean warning) {
+    currentElement = PsiTreeUtil.getParentOfType(currentElement,XmlTag.class,false);
+    if (currentElement==null) {
+      currentElement = PsiTreeUtil.getParentOfType(originalElement,XmlElementDecl.class,false);
+    }
+    if (currentElement == null) {
+      currentElement = originalElement;
+    }
+    assertValidElement(currentElement, originalElement,localizedMessage);
+
+    if (currentElement!=null) {
+      myHost.addMessage(currentElement,localizedMessage,warning ? Validator.ValidationHost.WARNING:Validator.ValidationHost.ERROR);
+    }
+
+    return currentElement;
+  }
+
+  private static void assertValidElement(PsiElement currentElement, PsiElement originalElement, String message) {
+    if (currentElement==null) {
+      XmlTag tag = PsiTreeUtil.getParentOfType(originalElement, XmlTag.class);
+      LOG.error("The validator message:" + message + " is bound to null node,\n" + "initial element:" + originalElement.getText() + ",\n" +
+                "parent:" + originalElement.getParent() + ",\n" + "tag:" + (tag != null ? tag.getText() : "null") + ",\n" +
+                "offset in tag: " + (originalElement.getTextOffset() - (tag == null ? 0 : tag.getTextOffset())));
+    }
+  }
+
+  public static synchronized void doValidation(final XmlDocument document, final Validator.ValidationHost host) {
+    final PsiFile containingFile = document.getContainingFile();
+    if (containingFile == null) {
+      return;
+    }
+
+    if (containingFile.getViewProvider() instanceof TemplateLanguageFileViewProvider) {
+      return;
+    }
+    
+    final FileType fileType = containingFile.getViewProvider().getVirtualFile().getFileType();
+    if (fileType != XmlFileType.INSTANCE && fileType != XHtmlFileType.INSTANCE) {
+      return;
+    }
+
+    for(Language lang: containingFile.getViewProvider().getLanguages()) {
+      if ("ANT".equals(lang.getID())) return;
+    }
+
+    final XmlTag rootTag = document.getRootTag();
+    if (rootTag == null) return;
+
+    String namespace = rootTag.getNamespace();
+    if (XmlUtil.ANT_URI.equals(namespace)) return;
+
+    final Project project = document.getProject();
+
+    final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
+    final LocalInspectionToolWrapper toolWrapper =
+      (LocalInspectionToolWrapper)profile.getInspectionTool(CheckXmlFileWithXercesValidatorInspection.SHORT_NAME, containingFile);
+
+    if (toolWrapper == null) return;
+    if (!profile.isToolEnabled(HighlightDisplayKey.find(CheckXmlFileWithXercesValidatorInspection.SHORT_NAME), containingFile)) return;
+
+    SoftReference<ExternalDocumentValidator> validatorReference = project.getUserData(validatorInstanceKey);
+    ExternalDocumentValidator validator = validatorReference != null? validatorReference.get() : null;
+
+    if(validator == null) {
+      validator = new ExternalDocumentValidator();
+      project.putUserData(validatorInstanceKey,new SoftReference<ExternalDocumentValidator>(validator));
+    }
+
+    validator.runJaxpValidation(document,host);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/XmlAttributeDescriptorEx.java b/xml/impl/src/com/intellij/xml/impl/XmlAttributeDescriptorEx.java
new file mode 100644
index 0000000..5af26e6
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/XmlAttributeDescriptorEx.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl;
+
+import com.intellij.xml.XmlAttributeDescriptor;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author peter
+ */
+public interface XmlAttributeDescriptorEx extends XmlAttributeDescriptor {
+
+  /**
+   * @param newTargetName
+   * @return new attribute local name
+   */
+  @Nullable
+  @NonNls
+  String handleTargetRename(@NotNull @NonNls final String newTargetName);
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/XmlBraceMatcher.java b/xml/impl/src/com/intellij/xml/impl/XmlBraceMatcher.java
new file mode 100644
index 0000000..866be5f
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/XmlBraceMatcher.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl;
+
+import com.intellij.codeInsight.highlighting.BraceMatchingUtil;
+import com.intellij.codeInsight.highlighting.XmlAwareBraceMatcher;
+import com.intellij.lang.BracePair;
+import com.intellij.lang.LanguageBraceMatching;
+import com.intellij.lang.PairedBraceMatcher;
+import com.intellij.lang.Language;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.xml.IXmlLeafElementType;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.containers.BidirectionalMap;
+import com.intellij.xml.util.HtmlUtil;
+import com.intellij.ide.highlighter.XmlLikeFileType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Maxim.Mossienko
+ *         Date: Apr 15, 2008
+ *         Time: 4:27:25 PM
+ */
+public class XmlBraceMatcher implements XmlAwareBraceMatcher {
+  private static final int XML_TAG_TOKEN_GROUP = 1;
+  private static final int XML_VALUE_DELIMITER_GROUP = 2;
+
+  private static final BidirectionalMap<IElementType, IElementType> PAIRING_TOKENS = new BidirectionalMap<IElementType, IElementType>();
+
+  static {
+    PAIRING_TOKENS.put(XmlTokenType.XML_TAG_END, XmlTokenType.XML_START_TAG_START);
+    PAIRING_TOKENS.put(XmlTokenType.XML_CDATA_START, XmlTokenType.XML_CDATA_END);
+    PAIRING_TOKENS.put(XmlTokenType.XML_EMPTY_ELEMENT_END, XmlTokenType.XML_START_TAG_START);
+    PAIRING_TOKENS.put(XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER, XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER);
+  }
+
+  public int getBraceTokenGroupId(IElementType tokenType) {
+    final Language l = tokenType.getLanguage();
+    PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(l);
+    
+    if (matcher != null) {
+      BracePair[] pairs = matcher.getPairs();
+      for (BracePair pair : pairs) {
+        if (pair.getLeftBraceType() == tokenType || pair.getRightBraceType() == tokenType ) {
+          return l.hashCode();
+        }
+      }
+    }
+    if (tokenType instanceof IXmlLeafElementType) {
+      return tokenType == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER || tokenType == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER
+             ? XML_VALUE_DELIMITER_GROUP
+             : XML_TAG_TOKEN_GROUP;
+    }
+    else{
+      return BraceMatchingUtil.UNDEFINED_TOKEN_GROUP;
+    }
+  }
+
+  public boolean isLBraceToken(HighlighterIterator iterator, CharSequence fileText, FileType fileType) {
+    final IElementType tokenType = iterator.getTokenType();
+    PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(tokenType.getLanguage());
+    if (matcher != null) {
+      BracePair[] pairs = matcher.getPairs();
+      for (BracePair pair : pairs) {
+        if (pair.getLeftBraceType() == tokenType) return true;
+      }
+    }
+    return tokenType == XmlTokenType.XML_START_TAG_START ||
+           tokenType == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER ||
+           tokenType == XmlTokenType.XML_CDATA_START;
+  }
+
+  public boolean isRBraceToken(HighlighterIterator iterator, CharSequence fileText, FileType fileType) {
+    final IElementType tokenType = iterator.getTokenType();
+    PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(tokenType.getLanguage());
+    if (matcher != null) {
+      BracePair[] pairs = matcher.getPairs();
+      for (BracePair pair : pairs) {
+        if (pair.getRightBraceType() == tokenType) return true;
+      }
+    }
+
+    if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END ||
+        tokenType == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER ||
+        tokenType == XmlTokenType.XML_CDATA_END)
+    {
+      return true;
+    }
+    else if (tokenType == XmlTokenType.XML_TAG_END) {
+      final boolean result = findEndTagStart(iterator);
+
+      if (isFileTypeWithSingleHtmlTags(fileType)) {
+        final String tagName = getTagName(fileText, iterator);
+
+        if (tagName != null && HtmlUtil.isSingleHtmlTag(tagName)) {
+          return !result;
+        }
+      }
+
+      return result;
+    }
+    else {
+      return false;
+    }
+  }
+
+  protected boolean isFileTypeWithSingleHtmlTags(final FileType fileType) {
+    return fileType == StdFileTypes.HTML;
+  }
+
+  public boolean isPairBraces(IElementType tokenType1, IElementType tokenType2) {
+    PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(tokenType1.getLanguage());
+    if (matcher != null) {
+      BracePair[] pairs = matcher.getPairs();
+      for (BracePair pair : pairs) {
+        if (pair.getLeftBraceType() == tokenType1 ) return pair.getRightBraceType() == tokenType2;
+        if (pair.getRightBraceType() == tokenType1 ) return pair.getLeftBraceType() == tokenType2;
+      }
+    }
+    if (tokenType2.equals(PAIRING_TOKENS.get(tokenType1))) return true;
+    List<IElementType> keys = PAIRING_TOKENS.getKeysByValue(tokenType1);
+    return keys != null && keys.contains(tokenType2);
+  }
+
+  public boolean isStructuralBrace(HighlighterIterator iterator,CharSequence text, FileType fileType) {
+    IElementType tokenType = iterator.getTokenType();
+
+    PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(tokenType.getLanguage());
+    if (matcher != null) {
+      BracePair[] pairs = matcher.getPairs();
+      for (BracePair pair : pairs) {
+        if ((pair.getLeftBraceType() == tokenType || pair.getRightBraceType() == tokenType) &&
+            pair.isStructural()) return true;
+      }
+    }
+    if (fileType instanceof XmlLikeFileType) {
+      return isXmlStructuralBrace(iterator, text, fileType, tokenType);
+    }
+    return false;
+  }
+
+  protected boolean isXmlStructuralBrace(HighlighterIterator iterator, CharSequence text, FileType fileType, IElementType tokenType) {
+    return tokenType == XmlTokenType.XML_START_TAG_START ||
+           tokenType == XmlTokenType.XML_TAG_END ||
+           tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END ||
+           tokenType == XmlTokenType.XML_TAG_END && isFileTypeWithSingleHtmlTags(fileType) && isEndOfSingleHtmlTag(text, iterator);
+  }
+
+  public boolean isPairedBracesAllowedBeforeType(@NotNull final IElementType lbraceType, @Nullable final IElementType contextType) {
+    return true;
+  }
+
+  public boolean isStrictTagMatching(final FileType fileType, final int braceGroupId) {
+    switch(braceGroupId){
+      case XML_TAG_TOKEN_GROUP:
+        // Other xml languages may have nonbalanced tag names
+        return isStrictTagMatchingForFileType(fileType);
+
+      default:
+        return false;
+    }
+  }
+
+  protected boolean isStrictTagMatchingForFileType(final FileType fileType) {
+    return fileType == StdFileTypes.XML ||
+           fileType == StdFileTypes.XHTML;
+  }
+
+  public boolean areTagsCaseSensitive(final FileType fileType, final int braceGroupId) {
+    switch(braceGroupId){
+      case XML_TAG_TOKEN_GROUP:
+        return fileType == StdFileTypes.XML;
+      default:
+        return false;
+    }
+  }
+
+  private static boolean findEndTagStart(HighlighterIterator iterator) {
+    IElementType tokenType = iterator.getTokenType();
+    int balance = 0;
+    int count = 0;
+    while(balance >= 0){
+      iterator.retreat();
+      count++;
+      if (iterator.atEnd()) break;
+      tokenType = iterator.getTokenType();
+      if (tokenType == XmlTokenType.XML_TAG_END || tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END){
+        balance++;
+      }
+      else if (tokenType == XmlTokenType.XML_END_TAG_START || tokenType == XmlTokenType.XML_START_TAG_START){
+        balance--;
+      }
+    }
+    while(count-- > 0) iterator.advance();
+    return tokenType == XmlTokenType.XML_END_TAG_START;
+  }
+
+  private boolean isEndOfSingleHtmlTag(CharSequence text,HighlighterIterator iterator) {
+    String tagName = getTagName(text,iterator);
+    return tagName != null && HtmlUtil.isSingleHtmlTag(tagName);
+  }
+
+  public String getTagName(CharSequence fileText, HighlighterIterator iterator) {
+    final IElementType tokenType = iterator.getTokenType();
+    String name = null;
+    if (tokenType == XmlTokenType.XML_START_TAG_START) {
+      iterator.advance();
+      IElementType tokenType1 = iterator.atEnd() ? null : iterator.getTokenType();
+
+      boolean wasWhiteSpace = false;
+      if (isWhitespace(tokenType1)) {
+        wasWhiteSpace = true;
+        iterator.advance();
+        tokenType1 = iterator.atEnd() ? null : iterator.getTokenType();
+      }
+
+      if (tokenType1 == XmlTokenType.XML_TAG_NAME ||
+          tokenType1 == XmlTokenType.XML_NAME
+         ) {
+        name = fileText.subSequence(iterator.getStart(), iterator.getEnd()).toString();
+      }
+
+      if (wasWhiteSpace) iterator.retreat();
+      iterator.retreat();
+    }
+    else if (tokenType == XmlTokenType.XML_TAG_END || tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END) {
+      int balance = 0;
+      int count = 0;
+      IElementType tokenType1 = iterator.getTokenType();
+      while (balance >=0) {
+        iterator.retreat();
+        count++;
+        if (iterator.atEnd()) break;
+        tokenType1 = iterator.getTokenType();
+
+        if (tokenType1 == XmlTokenType.XML_TAG_END || tokenType1 == XmlTokenType.XML_EMPTY_ELEMENT_END) {
+          balance++;
+        }
+        else if (tokenType1 == XmlTokenType.XML_TAG_NAME) {
+          balance--;
+        }
+      }
+      if (tokenType1 == XmlTokenType.XML_TAG_NAME) {
+        name = fileText.subSequence(iterator.getStart(), iterator.getEnd()).toString();
+      }
+      while (count-- > 0) iterator.advance();
+    }
+
+    return name;
+  }
+
+  protected boolean isWhitespace(final IElementType tokenType1) {
+    return tokenType1 == TokenType.WHITE_SPACE;
+  }
+
+  public IElementType getOppositeBraceTokenType(@NotNull final IElementType type) {
+    PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(type.getLanguage());
+    if (matcher != null) {
+      BracePair[] pairs = matcher.getPairs();
+      for (BracePair pair : pairs) {
+        if (pair.getLeftBraceType() == type ) return pair.getRightBraceType();
+        if (pair.getRightBraceType() == type ) return pair.getLeftBraceType();
+      }
+    }
+    return null;
+  }
+
+  public int getCodeConstructStart(final PsiFile file, int openingBraceOffset) {
+    return openingBraceOffset;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/dtd/BaseXmlElementDescriptorImpl.java b/xml/impl/src/com/intellij/xml/impl/dtd/BaseXmlElementDescriptorImpl.java
new file mode 100644
index 0000000..6d01ce8
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/dtd/BaseXmlElementDescriptorImpl.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.dtd;
+
+import com.intellij.openapi.util.FieldCache;
+import com.intellij.openapi.util.SimpleFieldCache;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+
+import java.util.HashMap;
+
+/**
+ * @by maxim
+ */
+public abstract class BaseXmlElementDescriptorImpl implements XmlElementDescriptor {
+  private volatile XmlElementDescriptor[] myElementDescriptors = null;
+  private volatile XmlAttributeDescriptor[] myAttributeDescriptors;
+  private volatile HashMap<String,XmlElementDescriptor> myElementDescriptorsMap;
+  private volatile HashMap<String,XmlAttributeDescriptor> attributeDescriptorsMap;
+
+  protected BaseXmlElementDescriptorImpl() {}
+
+  @Override
+  public XmlElementsGroup getTopGroup() {
+    return null;
+  }
+
+  @Override
+  public String getDefaultValue() {
+    return null;
+  }
+
+  // Read-only action
+  protected abstract XmlElementDescriptor[] doCollectXmlDescriptors(final XmlTag context);
+
+  static final FieldCache<XmlElementDescriptor[],BaseXmlElementDescriptorImpl,Object, XmlTag> myElementDescriptorsCache =
+    new FieldCache<XmlElementDescriptor[], BaseXmlElementDescriptorImpl, Object, XmlTag>() {
+    protected final XmlElementDescriptor[] compute(final BaseXmlElementDescriptorImpl xmlElementDescriptor, XmlTag tag) {
+      return xmlElementDescriptor.doCollectXmlDescriptors(tag);
+    }
+
+    protected final XmlElementDescriptor[] getValue(final BaseXmlElementDescriptorImpl xmlElementDescriptor, Object o) {
+      return xmlElementDescriptor.myElementDescriptors;
+    }
+
+    protected final void putValue(final XmlElementDescriptor[] xmlElementDescriptors, final BaseXmlElementDescriptorImpl xmlElementDescriptor,Object o) {
+      xmlElementDescriptor.myElementDescriptors = xmlElementDescriptors;
+    }
+  };
+
+  public XmlElementDescriptor[] getElementsDescriptors(XmlTag context) {
+    return myElementDescriptorsCache.get(null, this, context);
+  }
+
+  private static final SimpleFieldCache<XmlAttributeDescriptor[],BaseXmlElementDescriptorImpl> myAttributeDescriptorsCache =
+    new SimpleFieldCache<XmlAttributeDescriptor[], BaseXmlElementDescriptorImpl>() {
+    protected final XmlAttributeDescriptor[] compute(final BaseXmlElementDescriptorImpl xmlElementDescriptor) {
+      return xmlElementDescriptor.collectAttributeDescriptors(null);
+    }
+
+    protected final XmlAttributeDescriptor[] getValue(final BaseXmlElementDescriptorImpl xmlElementDescriptor) {
+      return xmlElementDescriptor.myAttributeDescriptors;
+    }
+
+    protected final void putValue(final XmlAttributeDescriptor[] xmlAttributeDescriptors, final BaseXmlElementDescriptorImpl xmlElementDescriptor) {
+      xmlElementDescriptor.myAttributeDescriptors = xmlAttributeDescriptors;
+    }
+  };
+
+  public XmlAttributeDescriptor[] getAttributesDescriptors(final XmlTag context) {
+    return myAttributeDescriptorsCache.get(this);
+  }
+
+  // Read-only calculation
+  protected abstract XmlAttributeDescriptor[] collectAttributeDescriptors(final XmlTag context);
+
+  private static final SimpleFieldCache<HashMap<String,XmlAttributeDescriptor>, BaseXmlElementDescriptorImpl> attributeDescriptorsMapCache =
+    new SimpleFieldCache<HashMap<String, XmlAttributeDescriptor>, BaseXmlElementDescriptorImpl>() {
+      protected final HashMap<String, XmlAttributeDescriptor> compute(final BaseXmlElementDescriptorImpl baseXmlElementDescriptor) {
+        return baseXmlElementDescriptor.collectAttributeDescriptorsMap(null);
+      }
+
+      protected final HashMap<String, XmlAttributeDescriptor> getValue(final BaseXmlElementDescriptorImpl baseXmlElementDescriptor) {
+        return baseXmlElementDescriptor.attributeDescriptorsMap;
+      }
+
+      protected final void putValue(final HashMap<String, XmlAttributeDescriptor> hashMap, final BaseXmlElementDescriptorImpl baseXmlElementDescriptor) {
+        baseXmlElementDescriptor.attributeDescriptorsMap = hashMap;
+      }
+    };
+
+  public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, final XmlTag context) {
+    return attributeDescriptorsMapCache.get(this).get(attributeName);
+  }
+
+  // Read-only calculation
+  protected abstract HashMap<String, XmlAttributeDescriptor> collectAttributeDescriptorsMap(final XmlTag context);
+
+  private static final FieldCache<HashMap<String,XmlElementDescriptor>,BaseXmlElementDescriptorImpl,Object,XmlTag> myElementDescriptorsMapCache =
+    new FieldCache<HashMap<String, XmlElementDescriptor>, BaseXmlElementDescriptorImpl, Object, XmlTag>() {
+    protected final HashMap<String, XmlElementDescriptor> compute(final BaseXmlElementDescriptorImpl baseXmlElementDescriptor, final XmlTag p) {
+      return baseXmlElementDescriptor.collectElementDescriptorsMap(p);
+    }
+
+    protected final HashMap<String, XmlElementDescriptor> getValue(final BaseXmlElementDescriptorImpl baseXmlElementDescriptor, final Object p) {
+      return baseXmlElementDescriptor.myElementDescriptorsMap;
+    }
+
+    protected final void putValue(final HashMap<String, XmlElementDescriptor> hashMap,
+                            final BaseXmlElementDescriptorImpl baseXmlElementDescriptor, final Object p) {
+      baseXmlElementDescriptor.myElementDescriptorsMap = hashMap;
+    }
+  };
+
+  public XmlElementDescriptor getElementDescriptor(XmlTag element, XmlTag contextTag){
+    return myElementDescriptorsMapCache.get(null, this, element).get(element.getName());
+  }
+
+  public final XmlElementDescriptor getElementDescriptor(String name, XmlTag context){
+    return myElementDescriptorsMapCache.get(null, this, context).get(name);
+  }
+
+  // Read-only calculation
+  protected abstract HashMap<String, XmlElementDescriptor> collectElementDescriptorsMap(final XmlTag element);
+
+  public final XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attr){
+    return getAttributeDescriptor(attr.getName(), attr.getParent());
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/dtd/XmlAttributeDescriptorImpl.java b/xml/impl/src/com/intellij/xml/impl/dtd/XmlAttributeDescriptorImpl.java
new file mode 100644
index 0000000..1471fc4
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/dtd/XmlAttributeDescriptorImpl.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.dtd;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.meta.PsiWritableMetaData;
+import com.intellij.psi.xml.XmlAttributeDecl;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Mike
+ */
+public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor implements PsiWritableMetaData {
+  private XmlAttributeDecl myDecl;
+  private boolean myRequired;
+  private boolean myEnumerated;
+  private boolean myFixed;
+  private String myName;
+
+  public XmlAttributeDescriptorImpl() {
+
+  }
+  public XmlAttributeDescriptorImpl(XmlAttributeDecl decl) {
+    init(decl);
+  }
+
+  public boolean isRequired() {
+    return myRequired;
+  }
+
+  public PsiElement getDeclaration(){
+    return myDecl;
+  }
+
+  public String getName() {
+    if (myName!=null) {
+      return myName;
+    }
+    myName = myDecl.getNameElement().getText();
+    return myName;
+  }
+
+  public void init(PsiElement element){
+    myDecl = (XmlAttributeDecl) element;
+    myRequired = myDecl.isAttributeRequired();
+    myFixed = myDecl.isAttributeFixed();
+    myEnumerated = myDecl.isEnumerated();
+  }
+
+  public Object[] getDependences(){
+    return new Object[]{myDecl};
+  }
+
+  public boolean isFixed() {
+    return myFixed;
+  }
+
+  public boolean hasIdType() {
+    return myDecl.isIdAttribute();
+  }
+
+  public boolean hasIdRefType() {
+    return myDecl.isIdRefAttribute();
+  }
+
+  public String getDefaultValue() {
+    String text = myDecl.getDefaultValueText();
+    if (text != null) {
+      return text.substring(1, text.length() - 1);
+    }
+
+    return null;
+  }
+
+  public boolean isEnumerated() {
+    return myEnumerated;
+  }
+
+  public String[] getEnumeratedValues() {
+
+    XmlElement[] values = myDecl.getEnumeratedValues();
+    List<String> result = new ArrayList<String>();
+    for (XmlElement value : values) {
+      result.add(value.getText());
+    }
+
+    return ArrayUtil.toStringArray(result);
+  }
+
+  public String getQualifiedName() {
+    return getName();
+  }
+
+  public void setName(String name) throws IncorrectOperationException {
+    myName = name;
+    ((PsiNamedElement)getDeclaration()).setName(name);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/dtd/XmlElementDescriptorImpl.java b/xml/impl/src/com/intellij/xml/impl/dtd/XmlElementDescriptorImpl.java
new file mode 100644
index 0000000..d5b2851
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/dtd/XmlElementDescriptorImpl.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.dtd;
+
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataCache;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.filters.ClassFilter;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.meta.PsiWritableMetaData;
+import com.intellij.psi.scope.processor.FilterElementProcessor;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.util.XmlNSDescriptorSequence;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+/**
+ * @author Mike
+ */
+public class XmlElementDescriptorImpl extends BaseXmlElementDescriptorImpl implements PsiWritableMetaData {
+  protected XmlElementDecl myElementDecl;
+  private String myName;
+
+  private static final Class[] ourParentClassesToScanAttributes = new Class[] { XmlMarkupDecl.class, XmlDocument.class };
+  private static final Key<CachedValue<XmlAttlistDecl[]>> ourCachedAttlistKeys = Key.create("cached_decls");
+
+  public XmlElementDescriptorImpl(XmlElementDecl elementDecl) {
+    init(elementDecl);
+  }
+
+  public XmlElementDescriptorImpl() {}
+
+  private static final UserDataCache<CachedValue<XmlAttlistDecl[]>,XmlElement, Object> myAttlistDeclCache = new UserDataCache<CachedValue<XmlAttlistDecl[]>,XmlElement, Object>() {
+    protected final CachedValue<XmlAttlistDecl[]> compute(final XmlElement owner, Object o) {
+      return CachedValuesManager.getManager(owner.getProject()).createCachedValue(new CachedValueProvider<XmlAttlistDecl[]>() {
+        public Result<XmlAttlistDecl[]> compute() {
+          return new Result<XmlAttlistDecl[]>(doCollectAttlistDecls(owner),owner);
+        }
+      });
+    }
+  };
+
+  public PsiElement getDeclaration(){
+    return myElementDecl;
+  }
+
+  public String getName(PsiElement context){
+    return getName();
+  }
+
+  public String getName() {
+    if (myName!=null) return myName;
+    return myName = myElementDecl.getName();
+  }
+
+  public void init(PsiElement element){
+    myElementDecl = (XmlElementDecl) element;
+  }
+
+  public Object[] getDependences(){
+    return new Object[]{myElementDecl, ExternalResourceManager.getInstance()};
+  }
+
+  public XmlNSDescriptor getNSDescriptor() {
+    return getNsDescriptorFrom(myElementDecl);
+  }
+
+  @Nullable
+  private static XmlNSDescriptor getNsDescriptorFrom(final PsiElement elementDecl) {
+    final XmlFile file = XmlUtil.getContainingFile(elementDecl);
+    if(file == null) return null;
+    final XmlDocument document = file.getDocument();
+    XmlNSDescriptor descriptor = (XmlNSDescriptor) document.getMetaData();
+    if(descriptor == null) descriptor = document.getDefaultNSDescriptor(XmlUtil.EMPTY_URI, false);
+    return descriptor;
+  }
+
+  // Read-only action
+  protected final XmlElementDescriptor[] doCollectXmlDescriptors(final XmlTag context) {
+    final LinkedHashSet<XmlElementDescriptor> result = new LinkedHashSet<XmlElementDescriptor>();
+    final XmlElementContentSpec contentSpecElement = myElementDecl.getContentSpecElement();
+    final XmlNSDescriptor nsDescriptor = getNSDescriptor();
+    final XmlNSDescriptor NSDescriptor = nsDescriptor != null? nsDescriptor:getNsDescriptorFrom(context);
+    
+    XmlUtil.processXmlElements(contentSpecElement, new PsiElementProcessor(){
+      public boolean execute(@NotNull PsiElement child){
+        if (child instanceof XmlToken) {
+          final XmlToken token = (XmlToken)child;
+
+          if (token.getTokenType() == XmlTokenType.XML_NAME) {
+            final String text = child.getText();
+            XmlElementDescriptor element = getElementDescriptor(text, NSDescriptor);
+
+            if (element != null) {
+              result.add(element);
+            }
+          }
+          else if (token.getTokenType() == XmlTokenType.XML_CONTENT_ANY) {
+            if (NSDescriptor instanceof XmlNSDescriptorImpl) {
+              ContainerUtil.addAll(result, ((XmlNSDescriptorImpl)NSDescriptor).getElements());
+            } else if (NSDescriptor instanceof XmlNSDescriptorSequence) {
+
+              for (XmlNSDescriptor xmlNSDescriptor : ((XmlNSDescriptorSequence)NSDescriptor).getSequence()) {
+                if (xmlNSDescriptor instanceof XmlNSDescriptorImpl) {
+                  ContainerUtil.addAll(result, ((XmlNSDescriptorImpl)xmlNSDescriptor).getElements());
+                }
+              }
+            }
+          }
+        }
+        return true;
+      }
+    }, true, false, XmlUtil.getContainingFile(getDeclaration()));
+
+    return result.toArray(new XmlElementDescriptor[result.size()]);
+  }
+
+  private static XmlElementDescriptor getElementDescriptor(final String text, final XmlNSDescriptor NSDescriptor) {
+    XmlElementDescriptor element = null;
+    if (NSDescriptor instanceof XmlNSDescriptorImpl) {
+      element = ((XmlNSDescriptorImpl)NSDescriptor).getElementDescriptor(text);
+    }
+    else if (NSDescriptor instanceof XmlNSDescriptorSequence) {
+      final List<XmlNSDescriptor> sequence = ((XmlNSDescriptorSequence)NSDescriptor).getSequence();
+      for (XmlNSDescriptor xmlNSDescriptor : sequence) {
+        if (xmlNSDescriptor instanceof XmlNSDescriptorImpl) {
+          element = ((XmlNSDescriptorImpl)xmlNSDescriptor).getElementDescriptor(text);
+          if(element != null) break;
+        }
+      }
+    }
+    else {
+      element = null;
+    }
+    return element;
+  }
+
+  // Read-only calculation
+  protected final XmlAttributeDescriptor[] collectAttributeDescriptors(final XmlTag context) {
+    final XmlAttributeDescriptor[] attrDescrs;
+    final List<XmlAttributeDescriptor> result = new ArrayList<XmlAttributeDescriptor>();
+
+    for (XmlAttlistDecl attlistDecl : findAttlistDecls(getName())) {
+      for (XmlAttributeDecl attributeDecl : attlistDecl.getAttributeDecls()) {
+        final PsiMetaData psiMetaData = attributeDecl.getMetaData();
+        assert psiMetaData instanceof XmlAttributeDescriptor;
+        result.add((XmlAttributeDescriptor)psiMetaData);
+      }
+    }
+
+    attrDescrs = result.toArray(new XmlAttributeDescriptor[result.size()]);
+    return attrDescrs;
+  }
+
+  // Read-only calculation
+  protected HashMap<String, XmlAttributeDescriptor> collectAttributeDescriptorsMap(final XmlTag context) {
+    final HashMap<String, XmlAttributeDescriptor> localADM;
+    final XmlAttributeDescriptor[] xmlAttributeDescriptors = getAttributesDescriptors(context);
+    localADM = new HashMap<String, XmlAttributeDescriptor>(xmlAttributeDescriptors.length);
+
+    for (final XmlAttributeDescriptor xmlAttributeDescriptor : xmlAttributeDescriptors) {
+      localADM.put(xmlAttributeDescriptor.getName(), xmlAttributeDescriptor);
+    }
+    return localADM;
+  }
+
+  private XmlAttlistDecl[] findAttlistDecls(String elementName) {
+    final List<XmlAttlistDecl> result = new ArrayList<XmlAttlistDecl>();
+
+    final XmlAttlistDecl[] decls = getAttlistDecls();
+
+    for (final XmlAttlistDecl decl : decls) {
+      final String name = decl.getName();
+      if (name != null && name.equals(elementName)) {
+        result.add(decl);
+      }
+    }
+
+    return result.toArray(new XmlAttlistDecl[result.size()]);
+  }
+
+  private XmlAttlistDecl[] getAttlistDecls() {
+    return getCachedAttDecls((XmlElement)getDeclaration());
+  }
+
+  public static @NotNull XmlAttlistDecl[] getCachedAttDecls(@Nullable XmlElement owner) {
+    if (owner == null) return XmlAttlistDecl.EMPTY_ARRAY;
+    owner = (XmlElement)PsiTreeUtil.getParentOfType(owner, ourParentClassesToScanAttributes);
+    if (owner == null) return XmlAttlistDecl.EMPTY_ARRAY;
+    return myAttlistDeclCache.get(ourCachedAttlistKeys, owner, null).getValue();
+  }
+
+  private static final XmlAttlistDecl[] doCollectAttlistDecls(XmlElement xmlElement) {
+    final List<XmlAttlistDecl> result = new ArrayList<XmlAttlistDecl>();
+
+    XmlUtil.processXmlElements(xmlElement, new FilterElementProcessor(new ClassFilter(XmlAttlistDecl.class), result), false, false, XmlUtil.getContainingFile(xmlElement));
+
+    return result.toArray(new XmlAttlistDecl[result.size()]);
+  }
+
+  @Override
+  public XmlElementsGroup getTopGroup() {
+    XmlElementContentGroup topGroup = myElementDecl.getContentSpecElement().getTopGroup();
+    return topGroup == null ? null : new XmlElementsGroupImpl(topGroup, null);
+  }
+
+  public int getContentType() {
+    if (myElementDecl.getContentSpecElement().isAny()) {
+      return CONTENT_TYPE_ANY;
+    }
+    if (myElementDecl.getContentSpecElement().hasChildren()) {
+      return CONTENT_TYPE_CHILDREN;
+    }
+    if (myElementDecl.getContentSpecElement().isEmpty()) {
+      return CONTENT_TYPE_EMPTY;
+    }
+    if (myElementDecl.getContentSpecElement().isMixed()) {
+      return CONTENT_TYPE_MIXED;
+    }
+
+    return CONTENT_TYPE_ANY;
+  }
+
+  // Read-only calculation
+  protected HashMap<String, XmlElementDescriptor> collectElementDescriptorsMap(final XmlTag element) {
+    final HashMap<String, XmlElementDescriptor> elementDescriptorsMap;
+    final XmlElementDescriptor[] descriptors = getElementsDescriptors(element);
+    elementDescriptorsMap = new HashMap<String, XmlElementDescriptor>(descriptors.length);
+
+    for (final XmlElementDescriptor descriptor : descriptors) {
+      elementDescriptorsMap.put(descriptor.getName(), descriptor);
+    }
+    return elementDescriptorsMap;
+  }
+
+  public String getQualifiedName() {
+    return getName();
+  }
+
+  public String getDefaultName() {
+    return getName();
+  }
+
+  public void setName(final String name) throws IncorrectOperationException {
+    // IDEADEV-11439
+    myName = null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/dtd/XmlElementsGroupImpl.java b/xml/impl/src/com/intellij/xml/impl/dtd/XmlElementsGroupImpl.java
new file mode 100644
index 0000000..9f73416
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/dtd/XmlElementsGroupImpl.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.dtd;
+
+import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.psi.xml.XmlContentParticle;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlElementsGroupImpl implements XmlElementsGroup {
+
+  private final XmlContentParticle myParticle;
+  private final XmlElementsGroup myParent;
+  private final NotNullLazyValue<List<XmlElementsGroup>> mySubGroups = new NotNullLazyValue<List<XmlElementsGroup>>() {
+    @NotNull
+    @Override
+    protected List<XmlElementsGroup> compute() {
+      return ContainerUtil.map(myParticle.getSubParticles(), new Function<XmlContentParticle, XmlElementsGroup>() {
+        @Override
+        public XmlElementsGroup fun(XmlContentParticle xmlContentParticle) {
+          return new  XmlElementsGroupImpl(xmlContentParticle, XmlElementsGroupImpl.this);
+        }
+      });
+    }
+  };
+
+  public XmlElementsGroupImpl(@NotNull XmlContentParticle particle, XmlElementsGroup parent) {
+    myParticle = particle;
+    myParent = parent;
+  }
+
+  @Override
+  public int getMinOccurs() {
+    switch (myParticle.getQuantifier()) {
+      case ONE_OR_MORE:
+      case REQUIRED:
+        return 1;
+      case ZERO_OR_MORE:
+      case OPTIONAL:
+        return 0;
+    }
+    throw new AssertionError(myParticle.getQuantifier());
+  }
+
+  @Override
+  public int getMaxOccurs() {
+    switch (myParticle.getQuantifier()) {
+      case ONE_OR_MORE:
+      case ZERO_OR_MORE:
+        return Integer.MAX_VALUE;
+      case OPTIONAL:
+      case REQUIRED:
+        return 1;
+    }
+    throw new AssertionError(myParticle.getQuantifier());
+  }
+
+  @Override
+  public Type getGroupType() {
+    switch (myParticle.getType()) {
+      case SEQUENCE:
+        return Type.SEQUENCE;
+      case CHOICE:
+        return Type.CHOICE;
+      case ELEMENT:
+        return Type.LEAF;
+    }
+    throw new AssertionError(myParticle.getType());
+  }
+
+  @Override
+  public XmlElementsGroup getParentGroup() {
+    return myParent;
+  }
+
+  @Override
+  public List<XmlElementsGroup> getSubGroups() {
+    return mySubGroups.getValue();
+  }
+
+  @Override
+  public XmlElementDescriptor getLeafDescriptor() {
+    return myParticle.getElementDescriptor();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/dtd/XmlNSDescriptorImpl.java b/xml/impl/src/com/intellij/xml/impl/dtd/XmlNSDescriptorImpl.java
new file mode 100644
index 0000000..b95ac5d
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/dtd/XmlNSDescriptorImpl.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.dtd;
+
+import com.intellij.codeInsight.daemon.Validator;
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.lang.dtd.DTDLanguage;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.util.SimpleFieldCache;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.filters.ClassFilter;
+import com.intellij.psi.scope.processor.FilterElementProcessor;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.xml.*;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptorEx;
+import com.intellij.xml.impl.ExternalDocumentValidator;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Mike
+ */
+public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocument>, DumbAware {
+  private XmlElement myElement;
+  private XmlFile myDescriptorFile;
+
+  private static final SimpleFieldCache<CachedValue<Map<String, XmlElementDescriptor>>, XmlNSDescriptorImpl> myCachedDeclsCache = new
+    SimpleFieldCache<CachedValue<Map<String, XmlElementDescriptor>>, XmlNSDescriptorImpl>() {
+    protected final CachedValue<Map<String, XmlElementDescriptor>> compute(final XmlNSDescriptorImpl xmlNSDescriptor) {
+      return xmlNSDescriptor.doBuildDeclarationMap();
+    }
+
+    protected final CachedValue<Map<String, XmlElementDescriptor>> getValue(final XmlNSDescriptorImpl xmlNSDescriptor) {
+      return xmlNSDescriptor.myCachedDecls;
+    }
+
+    protected final void putValue(final CachedValue<Map<String, XmlElementDescriptor>> cachedValue, final XmlNSDescriptorImpl xmlNSDescriptor) {
+      xmlNSDescriptor.myCachedDecls = cachedValue;
+    }
+  };
+
+  private volatile CachedValue<Map<String, XmlElementDescriptor>> myCachedDecls;
+  private static final XmlUtil.DuplicationInfoProvider<XmlElementDecl> XML_ELEMENT_DECL_PROVIDER = new XmlUtil.DuplicationInfoProvider<XmlElementDecl>() {
+    public String getName(@NotNull final XmlElementDecl psiElement) {
+      return psiElement.getName();
+    }
+
+    @NotNull
+    public String getNameKey(@NotNull final XmlElementDecl psiElement, @NotNull final String name) {
+      return name;
+    }
+
+    @NotNull
+    public PsiElement getNodeForMessage(@NotNull final XmlElementDecl psiElement) {
+      return psiElement.getNameElement();
+    }
+  };
+
+  public XmlNSDescriptorImpl() {}
+
+  public XmlFile getDescriptorFile() {
+    return myDescriptorFile;
+  }
+
+  public boolean isHierarhyEnabled() {
+    return false;
+  }
+
+  public XmlElementDescriptor[] getElements() {
+    final Collection<XmlElementDescriptor> delcarations = buildDeclarationMap().values();
+    return delcarations.toArray(new XmlElementDescriptor[delcarations.size()]);
+  }
+
+  private Map<String,XmlElementDescriptor> buildDeclarationMap() {
+    return myCachedDeclsCache.get(this).getValue();
+  }
+
+  // Read-only calculation
+  private CachedValue<Map<String, XmlElementDescriptor>> doBuildDeclarationMap() {
+    return CachedValuesManager.getManager(myElement.getProject()).createCachedValue(new CachedValueProvider<Map<String, XmlElementDescriptor>>() {
+      public Result<Map<String, XmlElementDescriptor>> compute() {
+        final List<XmlElementDecl> result = new ArrayList<XmlElementDecl>();
+        myElement.processElements(new FilterElementProcessor(new ClassFilter(XmlElementDecl.class), result), getDeclaration());
+        final Map<String, XmlElementDescriptor> ret = new LinkedHashMap<String, XmlElementDescriptor>((int)(result.size() * 1.5));
+
+        for (final XmlElementDecl xmlElementDecl : result) {
+          final String name = xmlElementDecl.getName();
+          if (name != null) {
+            if (!ret.containsKey(name)) {
+              ret.put(name, new XmlElementDescriptorImpl(xmlElementDecl));
+            }
+          }
+        }
+        return new Result<Map<String, XmlElementDescriptor>>(ret, myDescriptorFile);
+       }
+     }, false);
+  }
+
+  public XmlElementDescriptor getElementDescriptor(@NotNull XmlTag tag) {
+    String name = tag.getName();
+    return getElementDescriptor(name);
+  }
+
+  @NotNull
+  public XmlElementDescriptor[] getRootElementsDescriptors(@Nullable final XmlDocument document) {
+    // Suggest more appropriate variant if DOCTYPE <element_name> exists
+    final XmlProlog prolog = document != null ? document.getProlog():null;
+
+    if (prolog != null) {
+      final XmlDoctype doctype = prolog.getDoctype();
+
+      if (doctype != null) {
+        final XmlElement element = doctype.getNameElement();
+
+        if (element != null) {
+          final XmlElementDescriptor descriptor = getElementDescriptor(element.getText());
+
+          if (descriptor != null) return new XmlElementDescriptor[] {descriptor};
+        }
+      }
+    }
+
+    return getElements();
+  }
+
+  public final XmlElementDescriptor getElementDescriptor(String name){
+    return buildDeclarationMap().get(name);
+  }
+
+  public PsiElement getDeclaration() {
+    return myElement;
+  }
+
+  public String getName(PsiElement context){
+    return getName();
+  }
+
+  public String getName(){
+    return myDescriptorFile.getName();
+  }
+
+  public void init(PsiElement element){
+    myElement = (XmlElement)element;
+    myDescriptorFile = (XmlFile)element.getContainingFile();
+
+    if (myElement instanceof XmlFile) {
+      myElement = ((XmlFile)myElement).getDocument();
+    }
+  }
+
+  public Object[] getDependences(){
+    return new Object[]{myElement, ExternalResourceManager.getInstance()};
+  }
+
+  public void validate(@NotNull XmlDocument document, @NotNull ValidationHost host) {
+    if (document.getLanguage() == DTDLanguage.INSTANCE) {
+      final List<XmlElementDecl> decls = new ArrayList<XmlElementDecl>(3);
+
+      XmlUtil.processXmlElements(document, new PsiElementProcessor() {
+        public boolean execute(@NotNull final PsiElement element) {
+          if (element instanceof XmlElementDecl) decls.add((XmlElementDecl)element);
+          return true;
+        }
+      }, false);
+      XmlUtil.doDuplicationCheckForElements(
+        decls.toArray(new XmlElementDecl[decls.size()]),
+        new HashMap<String, XmlElementDecl>(decls.size()),
+        XML_ELEMENT_DECL_PROVIDER,
+        host
+      );
+      return;
+    }
+    ExternalDocumentValidator.doValidation(document,host);
+  }
+
+  @Override
+  public XmlElementDescriptor getElementDescriptor(String localName, String namespace) {
+    return getElementDescriptor(localName);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlAttributeDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlAttributeDescriptor.java
new file mode 100644
index 0000000..986ea48
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlAttributeDescriptor.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: mike
+ * Date: Sep 30, 2002
+ * Time: 9:46:52 PM
+ * To change template for new class use 
+ * Code Style | Class Templates options (Tools | IDE Options).
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+
+public class AnyXmlAttributeDescriptor implements XmlAttributeDescriptor {
+  private final String myAttributeName;
+  private final ComplexTypeDescriptor.CanContainAttributeType myCanContainAttributeType;
+
+  public AnyXmlAttributeDescriptor(String attributeName) {
+    this(attributeName, ComplexTypeDescriptor.CanContainAttributeType.CanContainButDoNotSkip);
+  }
+
+  public AnyXmlAttributeDescriptor(String attributeName, ComplexTypeDescriptor.CanContainAttributeType canContainAttributeType) {
+    myAttributeName = attributeName;
+    myCanContainAttributeType = canContainAttributeType;
+  }
+
+  public PsiElement getDeclaration(){
+    return null;
+  }
+
+  public String getName(PsiElement context){
+    return myAttributeName;
+  }
+
+  public String getName() {
+    return myAttributeName;
+  }
+
+  public void init(PsiElement element){
+  }
+
+  public Object[] getDependences(){
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
+  }
+
+  public String getQualifiedName() {
+    return myAttributeName;
+  }
+
+  public String getDefaultName() {
+    return myAttributeName;
+  }
+
+  public boolean isRequired() {
+    return false;
+  }
+
+  public boolean isFixed() {
+    return false;
+  }
+
+  public boolean hasIdType() {
+    return false;
+  }
+
+  public boolean hasIdRefType() {
+    return false;
+  }
+
+  public String getDefaultValue() {
+    return null;
+  }
+
+  //todo: refactor to hierarchy of value descriptor?
+  public boolean isEnumerated() {
+    return false;
+  }
+
+  public String[] getEnumeratedValues() {
+    return ArrayUtil.EMPTY_STRING_ARRAY;
+  }
+
+  public String validateValue(XmlElement context, String value) {
+    return null;
+  }
+
+  public ComplexTypeDescriptor.CanContainAttributeType getCanContainAttributeType() {
+    return myCanContainAttributeType;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlElementDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlElementDescriptor.java
new file mode 100644
index 0000000..7343adf
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlElementDescriptor.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: mike
+ * Date: Sep 30, 2002
+ * Time: 8:55:08 PM
+ * To change template for new class use 
+ * Code Style | Class Templates options (Tools | IDE Options).
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+import com.intellij.xml.XmlNSDescriptor;
+
+public  class AnyXmlElementDescriptor implements XmlElementDescriptor {
+  private final XmlElementDescriptor myParentDescriptor;
+  private final XmlNSDescriptor myXmlNSDescriptor;
+
+  public AnyXmlElementDescriptor(XmlElementDescriptor parentDescriptor, XmlNSDescriptor xmlNSDescriptor) {
+    myParentDescriptor = parentDescriptor == null ? NullElementDescriptor.getInstance() : parentDescriptor;
+    myXmlNSDescriptor = xmlNSDescriptor;
+  }
+
+  public XmlNSDescriptor getNSDescriptor() {
+    return myXmlNSDescriptor;
+  }
+
+  @Override
+  public XmlElementsGroup getTopGroup() {
+    return null;
+  }
+
+  public PsiElement getDeclaration(){
+    return null;
+  }
+
+  public String getName(PsiElement context){
+    return getName();
+  }
+
+  public String getName() {
+    return myParentDescriptor.getName();
+  }
+
+  public void init(PsiElement element){
+  }
+
+  public Object[] getDependences(){
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
+  }
+
+  public String getQualifiedName() {
+    return myParentDescriptor.getQualifiedName();
+  }
+
+  public String getDefaultName() {
+    return myParentDescriptor.getDefaultName();
+  }
+
+  public XmlElementDescriptor[] getElementsDescriptors(XmlTag context) {
+    return myParentDescriptor.getElementsDescriptors(context);
+  }
+
+  public XmlElementDescriptor getElementDescriptor(XmlTag tag, XmlTag contextTag){
+    return new AnyXmlElementDescriptor(this, myXmlNSDescriptor);
+  }
+
+  public XmlAttributeDescriptor[] getAttributesDescriptors(final XmlTag context) {
+    return new XmlAttributeDescriptor[0];
+  }
+
+  public XmlAttributeDescriptor getAttributeDescriptor(final String attributeName, final XmlTag context) {
+    return new AnyXmlAttributeDescriptor(attributeName);
+  }
+
+  public XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attr){
+    return myParentDescriptor.getAttributeDescriptor(attr);
+  }
+
+  public int getContentType() {
+    return CONTENT_TYPE_UNKNOWN;
+  }
+
+  @Override
+  public String getDefaultValue() {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java
new file mode 100644
index 0000000..6068f42
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java
@@ -0,0 +1,474 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.FieldCache;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaReferencesProvider;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.ConcurrentFactoryMap;
+import com.intellij.util.containers.FactoryMap;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.util.XmlUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Mike
+ */
+public class ComplexTypeDescriptor extends TypeDescriptor {
+  protected final XmlNSDescriptorImpl myDocumentDescriptor;
+  private final XmlTag myTag;
+
+  private static final FieldCache<XmlElementDescriptor[],ComplexTypeDescriptor,Object, XmlElement> myElementDescriptorsCache =
+    new FieldCache<XmlElementDescriptor[],ComplexTypeDescriptor,Object, XmlElement>() {
+
+    protected XmlElementDescriptor[] compute(final ComplexTypeDescriptor complexTypeDescriptor, final XmlElement p) {
+      return complexTypeDescriptor.doCollectElements(p);
+    }
+
+    protected XmlElementDescriptor[] getValue(final ComplexTypeDescriptor complexTypeDescriptor, final Object p) {
+      return complexTypeDescriptor.myElementDescriptors;
+    }
+
+    protected void putValue(final XmlElementDescriptor[] xmlElementDescriptors,
+                            final ComplexTypeDescriptor complexTypeDescriptor, final Object p) {
+      complexTypeDescriptor.myElementDescriptors = xmlElementDescriptors;
+    }
+  };
+
+  private static final FieldCache<XmlAttributeDescriptor[], ComplexTypeDescriptor, Object, XmlElement> myAttributeDescriptorsCache =
+    new FieldCache<XmlAttributeDescriptor[], ComplexTypeDescriptor, Object, XmlElement>() {
+    protected final XmlAttributeDescriptor[] compute(final ComplexTypeDescriptor complexTypeDescriptor, XmlElement p) {
+      return complexTypeDescriptor.doCollectAttributes(p);
+    }
+
+    protected final XmlAttributeDescriptor[] getValue(final ComplexTypeDescriptor complexTypeDescriptor, Object o) {
+      return complexTypeDescriptor.myAttributeDescriptors;
+    }
+
+    protected final void putValue(final XmlAttributeDescriptor[] xmlAttributeDescriptors,
+                            final ComplexTypeDescriptor complexTypeDescriptor, final Object p) {
+      complexTypeDescriptor.myAttributeDescriptors = xmlAttributeDescriptors;
+    }
+  };
+
+  private final FactoryMap<String, CachedValue<CanContainAttributeType>> myAnyAttributeCache = new ConcurrentFactoryMap<String, CachedValue<CanContainAttributeType>>() {
+    @Override
+    protected CachedValue<CanContainAttributeType> create(final String key) {
+      return CachedValuesManager.getManager(myTag.getProject()).createCachedValue(new CachedValueProvider<CanContainAttributeType>() {
+        @Override
+        public Result<CanContainAttributeType> compute() {
+          THashSet<PsiFile> dependencies = new THashSet<PsiFile>();
+          CanContainAttributeType type = _canContainAttribute(key, myTag, null, new THashSet<String>(), dependencies);
+          if (dependencies.isEmpty()) {
+            dependencies.add(myTag.getContainingFile());
+          }
+          return Result.create(type, ArrayUtil.toObjectArray(dependencies));
+        }
+      }, false);
+    }
+  };
+
+  private volatile XmlElementDescriptor[] myElementDescriptors = null;
+  private volatile XmlAttributeDescriptor[] myAttributeDescriptors = null;
+  @NonNls
+  private static final String PROHIBITED_ATTR_VALUE = "prohibited";
+  @NonNls
+  private static final String OTHER_NAMESPACE_ATTR_VALUE = "##other";
+
+  @NonNls private static final String TRUE_ATTR_VALUE = "true";
+  @NonNls private static final String REF_ATTR_NAME = "ref";
+  @NonNls private static final String NAME_ATTR_NAME = "name";
+  @NonNls private static final String ELEMENT_TAG_NAME = "element";
+  @NonNls private static final String ATTRIBUTE_TAG_NAME = "attribute";
+  private boolean myHasAnyInContentModel;
+  @NonNls private static final String RESTRICTION_TAG_NAME = "restriction";
+  @NonNls private static final String EXTENSION_TAG_NAME = "extension";
+  @NonNls private static final String BASE_ATTR_NAME = "base";
+
+  public ComplexTypeDescriptor(XmlNSDescriptorImpl documentDescriptor, XmlTag tag) {
+    myDocumentDescriptor = documentDescriptor;
+    myTag = tag;
+  }
+
+  public XmlTag getDeclaration(){
+    return myTag;
+  }
+
+  @Nullable
+  public XmlElementsGroup getTopGroup() {
+    return XmlElementsGroupProcessor.computeGroups(myDocumentDescriptor, myTag);
+  }
+
+  public XmlElementDescriptor[] getElements(XmlElement context) {
+    return myElementDescriptorsCache.get(null, this, context);
+  }
+
+  // Read-only calculation
+  private XmlElementDescriptor[] doCollectElements(@Nullable XmlElement context) {
+    final Map<String,XmlElementDescriptor> map = new LinkedHashMap<String,XmlElementDescriptor>(5);
+    createProcessor(map).startProcessing(myTag);
+    addSubstitutionGroups(map, myDocumentDescriptor, new HashSet<XmlNSDescriptorImpl>());
+    filterAbstractElements(map);
+    return map.values().toArray(
+      new XmlElementDescriptor[map.values().size()]
+    );
+  }
+
+  protected XmlSchemaTagsProcessor createProcessor(final Map<String, XmlElementDescriptor> map) {
+    return new XmlSchemaTagsProcessor(myDocumentDescriptor) {
+      @Override
+      protected void tagStarted(XmlTag tag, String tagName, XmlTag context, XmlTag ref) {
+        addElementDescriptor(tag, tagName, map);
+      }
+    };
+  }
+
+  protected void addElementDescriptor(XmlTag tag, String tagName, Map<String, XmlElementDescriptor> map) {
+    if ("element".equals(tagName) && tag.getAttribute("name") != null) {
+      addElementDescriptor(map, myDocumentDescriptor.createElementDescriptor(tag));
+    }
+  }
+
+  private static void addSubstitutionGroups(Map<String, XmlElementDescriptor> result,
+                                            XmlNSDescriptorImpl nsDescriptor,
+                                            Set<XmlNSDescriptorImpl> visited) {
+    mainLoop: while (true) {
+      for (final XmlElementDescriptor xmlElementDescriptor : result.values()) {
+        XmlElementDescriptorImpl descriptor = (XmlElementDescriptorImpl)xmlElementDescriptor;
+
+        final XmlElementDescriptor[] substitutes = nsDescriptor.getSubstitutes(descriptor.getName(), descriptor.getNamespace());
+        boolean toContinue = false;
+
+        for (XmlElementDescriptor substitute : substitutes) {
+          if (result.get(substitute.getName()) == null) {
+            toContinue = true;
+            result.put(substitute.getName(), substitute);
+          }
+        }
+
+        if (toContinue) continue mainLoop;
+      }
+
+      break;
+    }
+
+    visited.add(nsDescriptor);
+    for (XmlTag tag : nsDescriptor.getTag().getSubTags()) {
+      if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "include")) {
+        PsiElement element = XmlSchemaTagsProcessor.resolveReference(tag.getAttribute("schemaLocation"));
+        if (element instanceof XmlFile) {
+          XmlDocument document = ((XmlFile)element).getDocument();
+          if (document != null) {
+            PsiMetaData metaData = document.getMetaData();
+            if (metaData instanceof XmlNSDescriptorImpl && !visited.contains(metaData)) {
+              addSubstitutionGroups(result, (XmlNSDescriptorImpl)metaData, visited);
+            }
+          }
+        }
+      }
+    }
+
+  }
+
+  private static void filterAbstractElements(Map<String,XmlElementDescriptor> result) {
+    for (Iterator<XmlElementDescriptor> iterator = result.values().iterator(); iterator.hasNext();) {
+      XmlElementDescriptorImpl descriptor = (XmlElementDescriptorImpl)iterator.next();
+      if (descriptor.isAbstract()) iterator.remove();
+    }
+  }
+
+  public XmlAttributeDescriptor[] getAttributes(@Nullable XmlElement context) {
+    return myAttributeDescriptorsCache.get(null, this, context);
+  }
+
+  // Read-only calculation
+  private XmlAttributeDescriptor[] doCollectAttributes(@Nullable final XmlElement context) {
+    final List<XmlAttributeDescriptor> result = new ArrayList<XmlAttributeDescriptor>();
+
+    XmlSchemaTagsProcessor processor = new XmlSchemaTagsProcessor(myDocumentDescriptor, "element") {
+      @Override
+      protected void tagStarted(XmlTag tag, String tagName, XmlTag context, XmlTag ref) {
+        if (ATTRIBUTE_TAG_NAME.equals(tagName)) {
+
+          String name = tag.getAttributeValue(NAME_ATTR_NAME);
+          if (name == null) return;
+
+          String use = null;
+          if (ATTRIBUTE_TAG_NAME.equals(context.getLocalName())) { // from ref
+            use = context.getAttributeValue("use");
+          }
+          if (use == null) use = tag.getAttributeValue("use");
+
+          if (PROHIBITED_ATTR_VALUE.equals(use)) {
+            removeAttributeDescriptor(result, name);
+          }
+          else {
+            XmlAttributeDescriptorImpl descriptor = myDocumentDescriptor.createAttributeDescriptor(tag);
+            descriptor.myUse = use;
+            addAttributeDescriptor(result, descriptor);
+          }
+        }
+      }
+    };
+    processor.startProcessing(myTag);
+    return result.toArray(new XmlAttributeDescriptor[result.size()]);
+  }
+
+  public XmlNSDescriptorImpl getNsDescriptors() {
+    return myDocumentDescriptor;
+  }
+
+  protected static void addElementDescriptor(Map<String,XmlElementDescriptor> result, XmlElementDescriptor element) {
+    result.remove(element.getName());
+    result.put(element.getName(),element);
+  }
+
+  private static void removeAttributeDescriptor(List<XmlAttributeDescriptor> result, String name) {
+    for (Iterator<XmlAttributeDescriptor> iterator = result.iterator(); iterator.hasNext();) {
+      XmlAttributeDescriptor attributeDescriptor = iterator.next();
+
+      if (attributeDescriptor.getName().equals(name)) {
+        iterator.remove();
+      }
+    }
+  }
+
+  private static void addAttributeDescriptor(List<XmlAttributeDescriptor> result, XmlAttributeDescriptor descriptor) {
+    removeAttributeDescriptor(result, descriptor.getName());
+
+    result.add(descriptor);
+  }
+
+  public boolean canContainTag(String localName, String namespace, XmlElement context) {
+    return _canContainTag(localName, namespace, myTag, context, new HashSet<XmlTag>(5),
+                          new CurrentContextInfo(myDocumentDescriptor, myDocumentDescriptor.getDefaultNamespace()));
+  }
+
+  static class CurrentContextInfo {
+    final XmlNSDescriptorImpl documentDescriptor;
+    final String expectedDefaultNs;
+
+    public CurrentContextInfo(XmlNSDescriptorImpl _nsDescriptor, String _ns) {
+      documentDescriptor = _nsDescriptor;
+      expectedDefaultNs = _ns;
+    }
+  }
+
+  static CurrentContextInfo getContextInfo(CurrentContextInfo info, String ref) {
+    XmlTag rootTag = info.documentDescriptor.getTag();
+    XmlNSDescriptorImpl nsDescriptor = XmlNSDescriptorImpl.getNSDescriptorToSearchIn(rootTag, ref, info.documentDescriptor);
+    String ns;
+    
+    if (nsDescriptor == info.documentDescriptor) {
+      ns = rootTag.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(ref));
+    } else {
+      ns = nsDescriptor.getDefaultNamespace();
+    }
+
+    if (Comparing.equal(info.expectedDefaultNs, ns) && info.documentDescriptor == nsDescriptor) return info;
+    return new CurrentContextInfo(nsDescriptor, ns);
+  }
+
+  private boolean _canContainTag(String localName, String namespace, XmlTag tag, XmlElement context, Set<XmlTag> visited,
+                                 CurrentContextInfo info) {
+    if (visited.contains(tag)) return false;
+    visited.add(tag);
+
+    if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "any")) {
+      myHasAnyInContentModel = true;
+      if (OTHER_NAMESPACE_ATTR_VALUE.equals(tag.getAttributeValue("namespace"))) {
+        return namespace == null || !namespace.equals(info.expectedDefaultNs);
+      }
+      return true;
+    }
+    else if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "group")) {
+      String ref = tag.getAttributeValue(REF_ATTR_NAME);
+
+      if (ref != null) {
+        XmlTag groupTag = info.documentDescriptor.findGroup(ref);
+        if (groupTag != null) {
+          if (_canContainTag(localName, namespace, groupTag, context, visited, getContextInfo(info, ref)))  return true;
+        }
+      }
+    }
+    else if (XmlNSDescriptorImpl.equalsToSchemaName(tag, RESTRICTION_TAG_NAME) ||
+             XmlNSDescriptorImpl.equalsToSchemaName(tag, EXTENSION_TAG_NAME)) {
+      String base = tag.getAttributeValue(BASE_ATTR_NAME);
+
+      if (base != null) {
+        TypeDescriptor descriptor = info.documentDescriptor.findTypeDescriptor(base);
+
+        if (descriptor instanceof ComplexTypeDescriptor) {
+          ComplexTypeDescriptor complexTypeDescriptor = (ComplexTypeDescriptor)descriptor;
+          if (complexTypeDescriptor._canContainTag(localName, namespace, complexTypeDescriptor.myTag, context, visited,
+                                                   getContextInfo(info, base))) {
+            myHasAnyInContentModel |= complexTypeDescriptor.myHasAnyInContentModel;
+            return true;
+          }
+        }
+      }
+    } else if (XmlNSDescriptorImpl.equalsToSchemaName(tag, ELEMENT_TAG_NAME)) {
+      final XmlAttribute ref = tag.getAttribute(REF_ATTR_NAME);
+      XmlTag descriptorTag = tag;
+
+      if (ref != null) {
+        final PsiElement psiElement = SchemaReferencesProvider.createTypeOrElementOrAttributeReference(ref.getValueElement()).resolve();
+        if (psiElement instanceof XmlTag) descriptorTag = (XmlTag)psiElement;
+      }
+
+      if (TRUE_ATTR_VALUE.equals(descriptorTag.getAttributeValue("abstract"))) {
+
+        XmlNSDescriptor _nsDescriptor = tag.getNSDescriptor(namespace, true);
+        if (_nsDescriptor == null && context instanceof XmlTag) {
+          _nsDescriptor = ((XmlTag)context).getNSDescriptor(namespace, true);
+        }
+        final XmlNSDescriptorImpl nsDescriptor = _nsDescriptor instanceof XmlNSDescriptorImpl ? (XmlNSDescriptorImpl)_nsDescriptor:null;
+        final XmlElementDescriptor descriptor = nsDescriptor != null ? nsDescriptor.getElementDescriptor(localName, namespace):null;
+        final String name = descriptorTag.getAttributeValue(NAME_ATTR_NAME);
+
+        if (descriptor != null && name != null) {
+          final String substitutionValue = ((XmlTag)descriptor.getDeclaration()).getAttributeValue("substitutionGroup");
+
+          if (substitutionValue != null && name.equals(XmlUtil.findLocalNameByQualifiedName(substitutionValue))) {
+            return true; // could be more parent-child relation complex!!!
+          }
+        }
+    }
+    }
+
+    for (XmlTag subTag : tag.getSubTags()) {
+      if (_canContainTag(localName, namespace, subTag, context, visited, info)) return true;
+    }
+
+    return false;
+  }
+
+  public CanContainAttributeType canContainAttribute(String namespace, @Nullable String qName) {
+    if (qName == null) {
+      return myAnyAttributeCache.get(namespace).getValue();
+    }
+    return _canContainAttribute(namespace, myTag, qName, new THashSet<String>(), null);
+  }
+  
+  enum CanContainAttributeType {
+    CanContainButSkip, CanContainButDoNotSkip, CanNotContain
+  }
+
+  private CanContainAttributeType _canContainAttribute(String namespace,
+                                                       XmlTag tag,
+                                                       @Nullable String qName,
+                                                       Set<String> visited,
+                                                       @Nullable Set<PsiFile> dependencies) {
+    if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "anyAttribute")) {
+      if (dependencies != null) {
+        dependencies.add(tag.getContainingFile());
+      }
+      String ns = tag.getAttributeValue("namespace");
+      CanContainAttributeType canContainAttributeType = CanContainAttributeType.CanContainButDoNotSkip;
+      if ("skip".equals(tag.getAttributeValue("processContents"))) canContainAttributeType= CanContainAttributeType.CanContainButSkip;
+      
+      if (OTHER_NAMESPACE_ATTR_VALUE.equals(ns)) {
+        return !namespace.equals(myDocumentDescriptor.getDefaultNamespace()) ? canContainAttributeType : CanContainAttributeType.CanNotContain;
+      }
+      return canContainAttributeType;
+    }
+    else if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "attributeGroup")) {
+      String ref = tag.getAttributeValue(REF_ATTR_NAME);
+
+      if (ref != null && !visited.contains(ref)) {
+        visited.add(ref);
+        XmlTag groupTag = myDocumentDescriptor.findAttributeGroup(ref);
+
+        if (groupTag != null) {
+          if (dependencies != null) {
+            dependencies.add(groupTag.getContainingFile());
+          }
+          final CanContainAttributeType containAttributeType = _canContainAttribute(namespace, groupTag, qName, visited, dependencies);
+          if (containAttributeType != CanContainAttributeType.CanNotContain) return containAttributeType;
+        }
+      }
+    }
+    else if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "attribute")) {
+      if (qName != null && qName.equals(tag.getAttributeValue(REF_ATTR_NAME))) {
+        return CanContainAttributeType.CanContainButDoNotSkip;
+      }
+    }
+    else if (XmlNSDescriptorImpl.equalsToSchemaName(tag, RESTRICTION_TAG_NAME) ||
+             XmlNSDescriptorImpl.equalsToSchemaName(tag, EXTENSION_TAG_NAME)) {
+      String base = tag.getAttributeValue(BASE_ATTR_NAME);
+
+      if (base != null && !visited.contains(base)) {
+        visited.add(base);
+        TypeDescriptor descriptor = myDocumentDescriptor.findTypeDescriptor(base);
+
+        if (descriptor instanceof ComplexTypeDescriptor) {
+          ComplexTypeDescriptor complexTypeDescriptor = (ComplexTypeDescriptor)descriptor;
+          if (dependencies != null) {
+            dependencies.add(((ComplexTypeDescriptor)descriptor).getDeclaration().getContainingFile());
+          }
+
+          final CanContainAttributeType containAttributeType =
+            complexTypeDescriptor._canContainAttribute(namespace, complexTypeDescriptor.getDeclaration(), qName, visited, dependencies);
+          if (containAttributeType != CanContainAttributeType.CanNotContain) return containAttributeType;
+        }
+      }
+    }
+
+    final XmlTag[] subTags = tag.getSubTags();
+    for (XmlTag subTag : subTags) {
+      final CanContainAttributeType containAttributeType = _canContainAttribute(namespace, subTag, qName, visited, dependencies);
+      if (containAttributeType != CanContainAttributeType.CanNotContain) return containAttributeType;
+    }
+
+    return CanContainAttributeType.CanNotContain;
+  }
+
+  public boolean hasAnyInContentModel() {
+    return myHasAnyInContentModel;
+  }
+
+  public int getContentType() {
+
+    if ("simpleType".equals(myTag.getLocalName()) || "true".equals(myTag.getAttributeValue("mixed"))) {
+      return XmlElementDescriptor.CONTENT_TYPE_MIXED;
+    }
+
+    if (getElements(null).length > 0) return XmlElementDescriptor.CONTENT_TYPE_CHILDREN;
+
+    for (XmlTag tag : myTag.getSubTags()) {
+      if ("simpleContent".equals(tag.getLocalName())) {
+        return XmlElementDescriptor.CONTENT_TYPE_MIXED;
+      }
+    }
+    return XmlElementDescriptor.CONTENT_TYPE_EMPTY;
+
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/GotoXmlSchemaTypeRendererProvider.java b/xml/impl/src/com/intellij/xml/impl/schema/GotoXmlSchemaTypeRendererProvider.java
new file mode 100644
index 0000000..1017b9a
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/GotoXmlSchemaTypeRendererProvider.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.codeInsight.navigation.GotoTargetHandler;
+import com.intellij.codeInsight.navigation.GotoTargetRendererProvider;
+import com.intellij.ide.util.PsiElementListCellRenderer;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.xml.XmlTagImpl;
+import com.intellij.psi.xml.XmlAttribute;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 7/5/12
+ * Time: 8:27 PM
+ */
+public class GotoXmlSchemaTypeRendererProvider implements GotoTargetRendererProvider {
+  @Override
+  public PsiElementListCellRenderer getRenderer(PsiElement element, GotoTargetHandler.GotoData gotoData) {
+    if (element instanceof XmlTagImpl) {
+      if (SchemaDefinitionsSearch.isTypeElement((XmlTagImpl)element)) {
+        return new MyRenderer("");
+      }  else if (SchemaDefinitionsSearch.isElementWithSomeEmbeddedType((XmlTagImpl)element)) {
+        return new MyRenderer("xsd:element: ");
+      }
+    }
+    return null;
+  }
+
+  private static class MyRenderer extends PsiElementListCellRenderer<XmlTagImpl> {
+    private final String myPrefix;
+
+    private MyRenderer(String prefix) {
+      myPrefix = prefix;
+    }
+
+    @Override
+    public String getElementText(XmlTagImpl element) {
+      final XmlAttribute attr = SchemaDefinitionsSearch.getNameAttr(element);
+      return myPrefix + (attr == null || attr.getValue() == null ? element.getName() : attr.getValue());
+    }
+
+    @Override
+    protected String getContainerText(XmlTagImpl element, String name) {
+      final PsiFile file = element.getContainingFile();
+      return "(" + file.getName() + ")";
+    }
+
+    @Override
+    protected int getIconFlags() {
+      return 0;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/NamedObjectDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/NamedObjectDescriptor.java
new file mode 100644
index 0000000..04779f1
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/NamedObjectDescriptor.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.meta.PsiWritableMetaData;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.IncorrectOperationException;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class NamedObjectDescriptor implements PsiWritableMetaData, PsiMetaData {
+  private XmlTag myDcl;
+
+  public NamedObjectDescriptor() {}
+
+  public void setName(String name) throws IncorrectOperationException {
+    setName(myDcl, name);
+  }
+
+  static void setName(final XmlTag dcl, final String name) throws IncorrectOperationException {
+    if (dcl.isWritable()) {
+      final VirtualFile virtualFile = dcl.getContainingFile().getVirtualFile();
+
+      if (virtualFile!=null &&
+          ProjectRootManager.getInstance(dcl.getProject()).getFileIndex().getModuleForFile(virtualFile)!=null
+          ) {
+        dcl.setAttribute("name",name.substring(name.indexOf(':')+1));
+      }
+    }
+  }
+
+  public PsiElement getDeclaration() {
+    return myDcl;
+  }
+
+  public String getName(PsiElement context) {
+    return getName();
+  }
+
+  public String getName() {
+    return myDcl.getAttributeValue("name");
+  }
+
+  public void init(PsiElement element) {
+    myDcl = (XmlTag)element;
+  }
+
+  public Object[] getDependences() {
+    return new Object[] { myDcl };
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/NullElementDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/NullElementDescriptor.java
new file mode 100644
index 0000000..3704042
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/NullElementDescriptor.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @author cdr
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+import com.intellij.xml.XmlNSDescriptor;
+
+public class NullElementDescriptor implements XmlElementDescriptor {
+  private static final NullElementDescriptor INSTANCE = new NullElementDescriptor();
+
+  public static NullElementDescriptor getInstance() {
+    return INSTANCE;
+  }
+
+  private NullElementDescriptor() {
+  }
+
+  public String getQualifiedName() {
+    return null;
+  }
+
+  public String getDefaultName() {
+    return null;
+  }
+
+  //todo: refactor to support full DTD spec
+  public XmlElementDescriptor[] getElementsDescriptors(XmlTag context) {
+    return new XmlElementDescriptor[0];
+  }
+
+  public XmlElementDescriptor getElementDescriptor(XmlTag childTag, XmlTag contextTag) {
+    return null;
+  }
+
+  public XmlAttributeDescriptor[] getAttributesDescriptors(final XmlTag context) {
+    return new XmlAttributeDescriptor[0];
+  }
+
+  public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, final XmlTag context) {
+    return null;
+  }
+
+  public XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attribute) {
+    return null;
+  }
+
+  public XmlNSDescriptor getNSDescriptor() {
+    return null;
+  }
+
+  @Override
+  public XmlElementsGroup getTopGroup() {
+    return null;
+  }
+
+  public int getContentType() {
+    return 0;
+  }
+
+  @Override
+  public String getDefaultValue() {
+    return null;
+  }
+
+  public PsiElement getDeclaration() {
+    return null;
+  }
+
+  public String getName(PsiElement context) {
+    return null;
+  }
+
+  public String getName() {
+    return null;
+  }
+
+  public void init(PsiElement element) {
+  }
+
+  public Object[] getDependences() {
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/RedefinedElementDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/RedefinedElementDescriptor.java
new file mode 100644
index 0000000..75a96f6
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/RedefinedElementDescriptor.java
@@ -0,0 +1,54 @@
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementDescriptor;
+
+import java.util.Map;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class RedefinedElementDescriptor extends XmlElementDescriptorImpl {
+
+  private final XmlNSDescriptorImpl myRedefinedNSDescriptor;
+
+  public RedefinedElementDescriptor(XmlElementDescriptorImpl original, XmlNSDescriptorImpl xmlNSDescriptor) {
+    super(original.myDescriptorTag);
+    myRedefinedNSDescriptor = xmlNSDescriptor;
+  }
+
+  @Override
+  public TypeDescriptor getType(XmlElement context) {
+    TypeDescriptor typeDescriptor = super.getType(context);
+    return typeDescriptor instanceof ComplexTypeDescriptor ? new RedefinedTypeDescriptor((ComplexTypeDescriptor)typeDescriptor) : typeDescriptor;
+  }
+
+  private class RedefinedTypeDescriptor extends ComplexTypeDescriptor {
+    public RedefinedTypeDescriptor(ComplexTypeDescriptor original) {
+      super(original.getNsDescriptors(), original.getDeclaration());
+    }
+
+    @Override
+    protected XmlSchemaTagsProcessor createProcessor(final Map<String, XmlElementDescriptor> map) {
+      return new XmlSchemaTagsProcessor(myDocumentDescriptor) {
+        @Override
+        protected void tagStarted(XmlTag tag, String tagName, XmlTag context, XmlTag ref) {
+          addElementDescriptor(tag, tagName, map);
+          if ("extension".equals(tagName)) {
+            String base = tag.getAttributeValue("base");
+            if (base != null) {
+              TypeDescriptor descriptor = myRedefinedNSDescriptor.findTypeDescriptor(base);
+              if (descriptor instanceof ComplexTypeDescriptor) {
+                XmlElementDescriptor[] elements = ((ComplexTypeDescriptor)descriptor).getElements(null);
+                for (XmlElementDescriptor element : elements) {
+                  addElementDescriptor(map, element);
+                }
+              }
+            }
+          }
+        }
+      };
+    }
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/SchemaDefinitionsSearch.java b/xml/impl/src/com/intellij/xml/impl/schema/SchemaDefinitionsSearch.java
new file mode 100644
index 0000000..fe3a323
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/SchemaDefinitionsSearch.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.source.xml.XmlTagImpl;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.PairConvertor;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import com.intellij.util.containers.hash.HashMap;
+import com.intellij.util.containers.hash.HashSet;
+import com.intellij.xml.index.SchemaTypeInfo;
+import com.intellij.xml.index.SchemaTypeInheritanceIndex;
+import com.intellij.xml.index.XmlNamespaceIndex;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 7/5/12
+ * Time: 5:34 PM
+ */
+public class SchemaDefinitionsSearch implements QueryExecutor<PsiElement, PsiElement> {
+  @Override
+  public boolean execute(@NotNull final PsiElement queryParameters, @NotNull final Processor<PsiElement> consumer) {
+    if (queryParameters instanceof XmlTagImpl) {
+      final XmlTagImpl xml = (XmlTagImpl) queryParameters;
+      if (isTypeElement(xml)) {
+        final Collection<SchemaTypeInfo> infos = ApplicationManager.getApplication().runReadAction(new Computable<Collection<SchemaTypeInfo>>() {
+
+          @Override
+          public Collection<SchemaTypeInfo> compute() {
+            return gatherInheritors(xml);
+          }
+        });
+
+        if (infos != null && ! infos.isEmpty()) {
+          XmlFile file = XmlUtil.getContainingFile(xml);
+          final Project project = file.getProject();
+          final Module module = ModuleUtil.findModuleForPsiElement(queryParameters);
+          //if (module == null) return false;
+
+          final VirtualFile vf = file.getVirtualFile();
+          String thisNs = XmlNamespaceIndex.getNamespace(vf, project, file);
+          thisNs = thisNs == null ? getDefaultNs(file) : thisNs;
+          // so thisNs can be null
+          if (thisNs == null) return false;
+          final ArrayList<SchemaTypeInfo> infosLst = new ArrayList<SchemaTypeInfo>(infos);
+          Collections.sort(infosLst);
+          final Map<String, Set<XmlFile>> nsMap = new HashMap<String, Set<XmlFile>>();
+          for (final SchemaTypeInfo info : infosLst) {
+            Set<XmlFile> targetFiles = nsMap.get(info.getNamespaceUri());
+            if (targetFiles == null) {
+              targetFiles = new HashSet<XmlFile>();
+              if (Comparing.equal(info.getNamespaceUri(), thisNs)) {
+                targetFiles.add(file);
+              }
+              final Collection<XmlFile> files = ApplicationManager.getApplication().runReadAction(new Computable<Collection<XmlFile>>() {
+                @Override
+                public Collection<XmlFile> compute() {
+                  return XmlUtil.findNSFilesByURI(info.getNamespaceUri(), project, module);
+                }
+              });
+              if (files != null) {
+                targetFiles.addAll(files);
+              }
+              nsMap.put(info.getNamespaceUri(), targetFiles);
+            }
+            if (! targetFiles.isEmpty()) {
+              for (final XmlFile targetFile : targetFiles) {
+                ApplicationManager.getApplication().runReadAction(new Runnable() {
+                  @Override
+                  public void run() {
+                    final String prefixByURI = XmlUtil.findNamespacePrefixByURI(targetFile, info.getNamespaceUri());
+                    if (prefixByURI == null) return;
+                    final PsiElementProcessor processor = new PsiElementProcessor() {
+                      @Override
+                      public boolean execute(@NotNull PsiElement element) {
+                        if (element instanceof XmlTagImpl) {
+                          if (isCertainTypeElement((XmlTagImpl)element, info.getTagName(), prefixByURI) ||
+                              isElementWithEmbeddedType((XmlTagImpl)element, info.getTagName(), prefixByURI)) {
+                            consumer.process(element);
+                            return false;
+                          }
+                        }
+                        return true;
+                      }
+                    };
+                    XmlUtil.processXmlElements(targetFile, processor, true);
+                  }
+                });
+              }
+            }
+          }
+        }
+      }
+    }
+    return true;
+  }
+
+  public static boolean isElementWithSomeEmbeddedType(XmlTagImpl xml) {
+    final String localName = xml.getLocalName();
+    if (! (XmlUtil.XML_SCHEMA_URI.equals(xml.getNamespace()) && "element".equals(localName))) {
+      return false;
+    }
+    final XmlTag[] tags = xml.getSubTags();
+    for (XmlTag tag : tags) {
+      if (isTypeElement((XmlTagImpl)tag)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static boolean isElementWithEmbeddedType(XmlTagImpl xml, final String typeName, final String typeNsPrefix) {
+    final String localName = xml.getLocalName();
+    if (! (XmlUtil.XML_SCHEMA_URI.equals(xml.getNamespace()) && "element".equals(localName))) {
+      return false;
+    }
+    final XmlAttribute nameAttr = getNameAttr(xml);
+    if (nameAttr == null || nameAttr.getValue() == null) return false;
+    final String localTypeName = XmlUtil.findLocalNameByQualifiedName(nameAttr.getValue());
+    final String prefix = XmlUtil.findPrefixByQualifiedName(nameAttr.getValue());
+    if (! typeName.equals(localTypeName) || ! typeNsPrefix.equals(prefix)) {
+      return false;
+    }
+    final XmlTag[] tags = xml.getSubTags();
+    for (XmlTag tag : tags) {
+      if (isTypeElement((XmlTagImpl)tag)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private boolean isCertainTypeElement(XmlTagImpl xml, final String typeName, final String nsPrefix) {
+    if (! isTypeElement(xml)) return false;
+    final XmlAttribute name = getNameAttr(xml);
+    if (name == null) return false;
+    final String value = name.getValue();
+    if (value == null) return false;
+    final String localName = XmlUtil.findLocalNameByQualifiedName(value);
+    return typeName.equals(localName) && nsPrefix.equals(XmlUtil.findPrefixByQualifiedName(value));
+  }
+
+  public static boolean isTypeElement(XmlTagImpl xml) {
+    final String localName = xml.getLocalName();
+    return XmlUtil.XML_SCHEMA_URI.equals(xml.getNamespace()) && ("complexType".equals(localName) || "simpleType".equals(localName));
+  }
+
+  private Collection<SchemaTypeInfo> gatherInheritors(XmlTagImpl xml) {
+    XmlAttribute name = getNameAttr(xml);
+    if (name == null || StringUtil.isEmptyOrSpaces(name.getValue())) return null;
+    String localName = name.getValue();
+    final boolean hasPrefix = localName.contains(":");
+    localName = hasPrefix ? localName.substring(localName.indexOf(':') + 1) : localName;
+    final String nsPrefix = hasPrefix ? name.getValue().substring(0, name.getValue().indexOf(':')) : null;
+
+    final XmlFile file = XmlUtil.getContainingFile(xml);
+    if (file == null) return null;
+    final Project project = file.getProject();
+    if (project == null) return null;
+
+    final Set<SchemaTypeInfo> result = new HashSet<SchemaTypeInfo>();
+    final ArrayDeque<SchemaTypeInfo> queue = new ArrayDeque<SchemaTypeInfo>();
+
+    String nsUri;
+    if (! hasPrefix) {
+      nsUri = getDefaultNs(file);
+    } else {
+      nsUri = XmlUtil.findNamespaceByPrefix(nsPrefix, file.getRootTag());
+    }
+    if (nsUri == null) return null;
+
+    queue.add(new SchemaTypeInfo(localName, true, nsUri));
+
+    final PairConvertor<String,String,List<Set<SchemaTypeInfo>>> worker =
+      SchemaTypeInheritanceIndex.getWorker(project, file.getContainingFile().getVirtualFile());
+    while (! queue.isEmpty()) {
+      final SchemaTypeInfo info = queue.removeFirst();
+      final List<Set<SchemaTypeInfo>> childrenOfType = worker.convert(info.getNamespaceUri(), info.getTagName());
+      for (Set<SchemaTypeInfo> infos : childrenOfType) {
+        for (SchemaTypeInfo typeInfo : infos) {
+          if (typeInfo.isIsTypeName()) {
+            queue.add(typeInfo);
+          }
+          result.add(typeInfo);
+        }
+      }
+    }
+    return result;
+  }
+
+  public static XmlAttribute getNameAttr(XmlTagImpl xml) {
+    XmlAttribute name = xml.getAttribute("name", XmlUtil.XML_SCHEMA_URI);
+    name = name == null ? xml.getAttribute("name") : name;
+    return name;
+  }
+
+  private String getDefaultNs(final XmlFile file) {
+    return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+      @Override
+      public String compute() {
+        String nsUri;
+        final XmlTag tag = file.getDocument().getRootTag();
+        XmlAttribute xmlns = tag.getAttribute("xmlns", XmlUtil.XML_SCHEMA_URI);
+        xmlns = xmlns == null ? tag.getAttribute("xmlns") : xmlns;
+        nsUri = xmlns == null ? null : xmlns.getValue();
+        return nsUri;
+      }
+    });
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/SchemaNSDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/SchemaNSDescriptor.java
new file mode 100644
index 0000000..c6a29de
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/SchemaNSDescriptor.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.codeInsight.daemon.Validator;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class SchemaNSDescriptor extends XmlNSDescriptorImpl {
+  @NonNls private static final String MIN_OCCURS_ATTR_NAME = "minOccurs";
+  @NonNls private static final String MAX_OCCURS_ATTR_VALUE = "maxOccurs";
+  @NonNls private static final String MAX_OCCURS_ATTR_NAME = MAX_OCCURS_ATTR_VALUE;
+  @NonNls private static final String ID_ATTR_NAME = "id";
+  @NonNls private static final String REF_ATTR_NAME = "ref";
+  @NonNls private static final String DEFAULT_ATTR_NAME = "default";
+  @NonNls private static final String FIXED_ATTR_NAME = "fixed";
+
+  @NonNls private static final String NAME_ATTR_NAME = "name";
+
+  private static final Validator<XmlTag> ELEMENT_VALIDATOR = new Validator<XmlTag>() {
+    public void validate(@NotNull final XmlTag tag, @NotNull ValidationHost host) {
+      if (!isFromSchemaNs(tag)) return;
+      final boolean hasRefAttribute = tag.getAttributeValue(REF_ATTR_NAME) != null;
+
+      if (hasRefAttribute) {
+        for(XmlAttribute attr:tag.getAttributes()) {
+          final String name = attr.getName();
+
+          if (name.indexOf(':') == -1 &&
+              !MIN_OCCURS_ATTR_NAME.equals(name) &&
+              !MAX_OCCURS_ATTR_NAME.equals(name) &&
+              !ID_ATTR_NAME.equals(name) &&
+              !REF_ATTR_NAME.equals(name)) {
+            host.addMessage(
+              attr,
+              XmlBundle.message("xml.schema.validation.attr.not.allowed.with.ref", name),
+              ValidationHost.ERROR
+            );
+          }
+        }
+      }
+
+      final String minOccursValue = tag.getAttributeValue("minOccurs");
+      final String maxOccursValue = tag.getAttributeValue(MAX_OCCURS_ATTR_VALUE);
+
+      if (minOccursValue != null && maxOccursValue != null) {
+        try {
+          final int minOccurs = Integer.parseInt(minOccursValue);
+          final int maxOccurs = Integer.parseInt(maxOccursValue);
+          if (maxOccurs < minOccurs) {
+            host.addMessage(
+              tag.getAttribute(MAX_OCCURS_ATTR_VALUE, null).getValueElement(),
+              XmlBundle.message("xml.schema.validation.max.occurs.should.be.not.less.than.min.occurs"),
+              Validator.ValidationHost.ERROR
+            );
+          }
+        }
+        catch (NumberFormatException e) {
+          // this schema will be reported by xerces validation
+        }
+      }
+
+      if (!hasRefAttribute && tag.getAttributeValue(NAME_ATTR_NAME) == null) {
+        host.addMessage(
+          tag,
+          XmlBundle.message("xml.schema.validation.name.or.ref.should.present"),
+          Validator.ValidationHost.ERROR
+        );
+      }
+    }
+  };
+
+  private static final Validator<XmlTag> ATTRIBUTE_VALIDATOR = new Validator<XmlTag>() {
+    public void validate(@NotNull final XmlTag tag, @NotNull ValidationHost host) {
+      if (!isFromSchemaNs(tag)) return;
+
+      if (tag.getAttributeValue(REF_ATTR_NAME) == null && tag.getAttributeValue(NAME_ATTR_NAME) == null) {
+        host.addMessage(
+          tag,
+          XmlBundle.message("xml.schema.validation.name.or.ref.should.present"),
+          Validator.ValidationHost.ERROR
+        );
+      }
+
+      if (tag.getAttributeValue(DEFAULT_ATTR_NAME) != null && tag.getAttributeValue(FIXED_ATTR_NAME) != null) {
+        host.addMessage(
+          tag.getAttribute(DEFAULT_ATTR_NAME, null),
+          XmlBundle.message("xml.schema.validation.default.or.fixed.should.be.specified.but.not.both"),
+          Validator.ValidationHost.ERROR
+        );
+
+        host.addMessage(
+          tag.getAttribute(FIXED_ATTR_NAME, null),
+          XmlBundle.message("xml.schema.validation.default.or.fixed.should.be.specified.but.not.both"),
+          Validator.ValidationHost.ERROR
+        );
+      }
+    }
+  };
+
+  private static final XmlUtil.DuplicationInfoProvider<XmlTag> SCHEMA_ATTR_DUP_INFO_PROVIDER = new XmlUtil.DuplicationInfoProvider<XmlTag>() {
+    public String getName(@NotNull final XmlTag t) {
+      return t.getAttributeValue(NAME_ATTR_NAME);
+    }
+
+    @NotNull
+    public String getNameKey(@NotNull final XmlTag t, @NotNull String name) {
+      return name;
+    }
+
+    @NotNull
+    public PsiElement getNodeForMessage(@NotNull final XmlTag t) {
+      return t.getAttribute(NAME_ATTR_NAME, null).getValueElement();
+    }
+  };
+
+  private static final Validator<XmlTag> ELEMENT_AND_ATTR_VALIDATOR = new Validator<XmlTag>() {
+    public void validate(@NotNull final XmlTag tag, @NotNull ValidationHost host) {
+      if (!isFromSchemaNs(tag)) return;
+      final String nsPrefix = tag.getNamespacePrefix();
+      final XmlTag[] attrDeclTags = tag.findSubTags((nsPrefix.length() > 0 ? nsPrefix + ":" : "") + "attribute");
+
+      XmlUtil.doDuplicationCheckForElements(
+        attrDeclTags,
+        new HashMap<String, XmlTag>(attrDeclTags.length),
+        SCHEMA_ATTR_DUP_INFO_PROVIDER,
+        host
+      );
+
+      final XmlTag[] elementDeclTags = tag.findSubTags((nsPrefix.length() > 0 ? nsPrefix + ":" : "") + "element");
+
+      XmlUtil.doDuplicationCheckForElements(
+        elementDeclTags,
+        new HashMap<String, XmlTag>(elementDeclTags.length),
+        SCHEMA_ATTR_DUP_INFO_PROVIDER,
+        host
+      );
+    }
+  };
+
+  private static boolean isFromSchemaNs(final XmlTag tag) {
+    return XmlUtil.XML_SCHEMA_URI.equals(tag.getNamespace());
+  }
+
+  protected XmlElementDescriptor createElementDescriptor(final XmlTag tag) {
+    final XmlElementDescriptor descriptor = super.createElementDescriptor(tag);
+    String localName = tag.getAttributeValue(NAME_ATTR_NAME);
+    if (ELEMENT_TAG_NAME.equals(localName)) {
+      ((XmlElementDescriptorImpl)descriptor).setValidator(ELEMENT_VALIDATOR);
+    } else if (COMPLEX_TYPE_TAG_NAME.equals(localName) || SCHEMA_TAG_NAME.equals(localName) || SEQUENCE_TAG_NAME.equals(localName)) {
+      ((XmlElementDescriptorImpl)descriptor).setValidator(ELEMENT_AND_ATTR_VALIDATOR);
+    } else if (ATTRIBUTE_TAG_NAME.equals(localName)) {
+      ((XmlElementDescriptorImpl)descriptor).setValidator(ATTRIBUTE_VALIDATOR);
+    }
+    return descriptor;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/SimpleTypeDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/SimpleTypeDescriptor.java
new file mode 100644
index 0000000..b6dc92d
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/SimpleTypeDescriptor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.xml.XmlTag;
+
+/**
+ * @author Mike
+ */
+class SimpleTypeDescriptor extends TypeDescriptor {
+  public SimpleTypeDescriptor(XmlTag tag) {
+    super();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/StdTypeDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/StdTypeDescriptor.java
new file mode 100644
index 0000000..0893e23
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/StdTypeDescriptor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.xml.XmlTag;
+
+/**
+ * @author Mike
+ */
+class StdTypeDescriptor extends TypeDescriptor {
+  public StdTypeDescriptor(String name) {
+    super();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/TypeDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/TypeDescriptor.java
new file mode 100644
index 0000000..0cfd6f7
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/TypeDescriptor.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+/**
+ * @author Mike
+ */
+public abstract class TypeDescriptor {
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
new file mode 100644
index 0000000..24591d3
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.meta.PsiWritableMetaData;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+
+/**
+ * @author Mike
+ */
+public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor implements PsiWritableMetaData {
+  private XmlTag myTag;
+  String myUse;
+  @NonNls
+  public static final String REQUIRED_ATTR_VALUE = "required";
+  @NonNls
+  public static final String QUALIFIED_ATTR_VALUE = "qualified";
+
+  public XmlAttributeDescriptorImpl(XmlTag tag) {
+    myTag = tag;
+    myUse = myTag.getAttributeValue("use");
+  }
+
+  public XmlAttributeDescriptorImpl() {}
+
+  public PsiElement getDeclaration(){
+    return myTag;
+  }
+
+  public String getName() {
+    return myTag.getAttributeValue("name");
+  }
+
+  public void init(PsiElement element){
+    myTag = (XmlTag) element;
+    myUse = myTag.getAttributeValue("use");
+  }
+
+  public Object[] getDependences(){
+    return ArrayUtil.EMPTY_OBJECT_ARRAY;
+  }
+
+  public boolean isRequired() {
+    return REQUIRED_ATTR_VALUE.equals(myUse);
+  }
+
+  public boolean isFixed() {
+    return myTag.getAttributeValue("fixed") != null;
+  }
+
+  private boolean hasSimpleSchemaType(@NonNls String type) {
+    final String attributeValue = getType();
+
+    if (attributeValue != null) {
+      if (attributeValue.endsWith(type)) {
+        final String namespacePrefix = myTag.getNamespacePrefix();
+
+        if (namespacePrefix.length() > 0) {
+          return attributeValue.equals(namespacePrefix+":"+type);
+        } else {
+          return attributeValue.equals(type);
+        }
+      }
+    }
+
+    return false;
+  }
+
+  @Nullable
+  public String getType() {
+    return myTag.getAttributeValue("type");
+  }
+
+  public boolean hasIdType() {
+    return hasSimpleSchemaType("ID");
+  }
+
+  public boolean hasIdRefType() {
+    return hasSimpleSchemaType("IDREF");
+  }
+
+  public String getDefaultValue() {
+    if (isFixed()) {
+      return myTag.getAttributeValue("fixed");
+    }
+
+    return myTag.getAttributeValue("default");
+  }
+
+  public boolean isEnumerated(@Nullable XmlElement context) {
+    final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(
+      myTag,
+      context != null ?PsiTreeUtil.getContextOfType(context, XmlTag.class, true):null
+    );
+
+    if (elementDescriptor != null &&
+        elementDescriptor.getType() instanceof ComplexTypeDescriptor) {
+      final EnumerationData data = getEnumeratedValuesImpl(((ComplexTypeDescriptor)elementDescriptor.getType()).getDeclaration());
+      return data != null && data.exaustive;
+    }
+
+    return false;
+  }
+
+  public boolean isEnumerated() {
+    return isEnumerated(null);
+  }
+
+  public String[] getEnumeratedValues() {
+    return getEnumeratedValues(null);
+  }
+
+  public String[] getEnumeratedValues(XmlElement context) {
+    final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(
+      myTag,
+      context != null ?PsiTreeUtil.getContextOfType(context, XmlTag.class, true):null
+    );
+
+    if (elementDescriptor!=null && elementDescriptor.getType() instanceof ComplexTypeDescriptor) {
+      final EnumerationData data = getEnumeratedValuesImpl(((ComplexTypeDescriptor)elementDescriptor.getType()).getDeclaration());
+      final String s = getDefaultValue();
+
+      if (s != null && s.length() > 0 && data == null) {
+        return new String[] {s};
+      }
+      return data != null? data.enumeratedValues:ArrayUtil.EMPTY_STRING_ARRAY;
+    }
+
+    final String namespacePrefix = myTag.getNamespacePrefix();
+    XmlTag type = myTag.findFirstSubTag(
+      ((namespacePrefix.length() > 0)?namespacePrefix+":":"")+"simpleType"
+    );
+
+    if (type != null) {
+      final EnumerationData data = getEnumeratedValuesImpl(type);
+      return data != null? data.enumeratedValues:ArrayUtil.EMPTY_STRING_ARRAY;
+    }
+
+    return ArrayUtil.EMPTY_STRING_ARRAY;
+  }
+
+  static class EnumerationData {
+    final String[] enumeratedValues;
+    final boolean exaustive;
+
+    EnumerationData(@NotNull String[] _values, boolean _exaustive) {
+      enumeratedValues = _values;
+      exaustive = _exaustive;
+    }
+  }
+
+  private static EnumerationData getEnumeratedValuesImpl(final XmlTag declaration) {
+    if ("boolean".equals(declaration.getAttributeValue("name"))) {
+      return new EnumerationData(new String[] {"true", "false"}, true);
+    }
+
+    final HashSet<String> variants = new HashSet<String>();
+    final boolean exaustive = XmlUtil.collectEnumerationValues(declaration, variants);
+
+    if (variants.size() > 0) {
+      return new EnumerationData(ArrayUtil.toStringArray(variants), exaustive);
+    }
+    return null;
+  }
+
+  public String getName(PsiElement context) {
+
+    if (context == null) {
+      return getName();
+    }
+    final String form = myTag.getAttributeValue("form");
+    boolean isQualifiedAttr = QUALIFIED_ATTR_VALUE.equals(form);
+
+    final XmlTag rootTag = (((XmlFile) myTag.getContainingFile())).getRootTag();
+    assert rootTag != null;
+    String targetNs = rootTag.getAttributeValue("targetNamespace");
+    XmlTag contextTag = (XmlTag)context;
+    String name = getName();
+
+    boolean attributeShouldBeQualified = false;
+
+    String contextNs = contextTag.getNamespace();
+    if (targetNs != null && !contextNs.equals(targetNs)) {
+      final XmlElementDescriptor xmlElementDescriptor = contextTag.getDescriptor();
+
+      if (xmlElementDescriptor instanceof XmlElementDescriptorImpl) {
+        final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)xmlElementDescriptor;
+        final TypeDescriptor type = elementDescriptor.getType();
+
+        if (type instanceof ComplexTypeDescriptor) {
+          final ComplexTypeDescriptor typeDescriptor = (ComplexTypeDescriptor)type;
+          attributeShouldBeQualified = typeDescriptor.canContainAttribute(targetNs, null) != ComplexTypeDescriptor.CanContainAttributeType.CanNotContain;
+        }
+
+        if (!attributeShouldBeQualified && contextNs.length() == 0 && targetNs.length() > 0) {
+          attributeShouldBeQualified = !targetNs.equals(elementDescriptor.getNamespace());
+        }
+      }
+    }
+
+    if (targetNs != null &&
+        ( isQualifiedAttr ||
+          QUALIFIED_ATTR_VALUE.equals(rootTag.getAttributeValue("attributeFormDefault")) ||
+          attributeShouldBeQualified
+        )
+      ) {
+      final String prefixByNamespace = contextTag.getPrefixByNamespace(targetNs);
+      if (prefixByNamespace!= null && prefixByNamespace.length() > 0) {
+        name = prefixByNamespace + ":" + name;
+      }
+    }
+
+    return name;
+  }
+
+  public void setName(String name) throws IncorrectOperationException {
+    NamedObjectDescriptor.setName(myTag, name);
+  }
+
+  @Override
+  public String toString() {
+    return getName();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorByType.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorByType.java
new file mode 100644
index 0000000..1289008
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorByType.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * @author ik
+ */
+public class XmlElementDescriptorByType extends XmlElementDescriptorImpl {
+  private ComplexTypeDescriptor myType;
+  @NonNls
+  public static final String QUALIFIED_ATTR_VALUE = "qualified";
+
+  public XmlElementDescriptorByType(XmlTag instanceTag, ComplexTypeDescriptor descriptor) {
+    myDescriptorTag = instanceTag;
+    myType = descriptor;
+  }
+
+  public XmlElementDescriptorByType() {}
+
+  public PsiElement getDeclaration(){
+    return myDescriptorTag;
+  }
+
+  public String getName(PsiElement context){
+    return myDescriptorTag.getName();
+  }
+
+  public XmlNSDescriptor getNSDescriptor() {
+    XmlNSDescriptor nsDescriptor = NSDescriptor;
+    if (nsDescriptor ==null) {
+      final XmlFile file = XmlUtil.getContainingFile(getType(null).getDeclaration());
+      if(file == null) return null;
+      final XmlDocument document = file.getDocument();
+      if(document == null) return null;
+      NSDescriptor = nsDescriptor = (XmlNSDescriptor)document.getMetaData();
+    }
+
+    return nsDescriptor;
+  }
+
+  public ComplexTypeDescriptor getType(XmlElement context) {
+    return myType;
+  }
+
+  public String getDefaultName() {
+    XmlTag rootTag = ((XmlFile)getType(null).getDeclaration().getContainingFile()).getDocument().getRootTag();
+
+    if (QUALIFIED_ATTR_VALUE.equals(rootTag.getAttributeValue("elementFormDefault"))) {
+      return getQualifiedName();
+    }
+
+    return getName();
+  }
+  
+  protected boolean askParentDescriptorViaXsi() {
+    return false;
+  }
+
+  public boolean equals(final Object o) {
+    if (this == o) return true;
+    if (!(o instanceof XmlElementDescriptorByType)) return false;
+
+    final XmlElementDescriptorByType that = (XmlElementDescriptorByType)o;
+
+    if (myType != null ? !myType.equals(that.myType) : that.myType != null) return false;
+
+    return true;
+  }
+
+  public int hashCode() {
+    return (myType != null ? myType.hashCode() : 0);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java
new file mode 100644
index 0000000..6434705
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java
@@ -0,0 +1,532 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.codeInsight.daemon.Validator;
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.meta.PsiWritableMetaData;
+import com.intellij.psi.util.*;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.*;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Mike
+ */
+public class XmlElementDescriptorImpl implements XmlElementDescriptor, PsiWritableMetaData, Validator<XmlTag>,
+                                                 XmlElementDescriptorAwareAboutChildren {
+  protected XmlTag myDescriptorTag;
+  protected volatile XmlNSDescriptor NSDescriptor;
+  private volatile @Nullable Validator<XmlTag> myValidator;
+
+  @NonNls
+  public static final String QUALIFIED_ATTR_VALUE = "qualified";
+  @NonNls
+  public static final String NONQUALIFIED_ATTR_VALUE = "unqualified";
+  @NonNls
+  private static final String ELEMENT_FORM_DEFAULT = "elementFormDefault";
+  private static final Key<ParameterizedCachedValue<XmlAttributeDescriptor[], XmlTag>> ATTRS_KEY = Key.create("attributes");
+  private ParameterizedCachedValueProvider<XmlAttributeDescriptor[],XmlTag> myCachedValueProvider;
+
+  public XmlElementDescriptorImpl(@Nullable XmlTag descriptorTag) {
+    myDescriptorTag = descriptorTag;
+  }
+
+  public XmlElementDescriptorImpl() {}
+
+  public PsiElement getDeclaration(){
+    return myDescriptorTag;
+  }
+
+  public String getName(PsiElement context){
+    String value = myDescriptorTag.getAttributeValue("name");
+
+    if(context instanceof XmlElement){
+      final String namespace = getNamespaceByContext(context);
+      final XmlTag tag = PsiTreeUtil.getParentOfType(context, XmlTag.class, false);
+
+      if(tag != null){
+        final String namespacePrefix = tag.getPrefixByNamespace(namespace);
+
+        if (namespacePrefix != null && namespacePrefix.length() > 0) {
+          final XmlTag rootTag = ((XmlFile)myDescriptorTag.getContainingFile()).getRootTag();
+          String elementFormDefault;
+
+          if (rootTag != null && 
+              ( NONQUALIFIED_ATTR_VALUE.equals(elementFormDefault = rootTag.getAttributeValue(ELEMENT_FORM_DEFAULT)) || elementFormDefault == null /*unqualified is default*/) &&
+              tag.getNamespaceByPrefix("").isEmpty()
+            && myDescriptorTag.getParentTag() != rootTag
+             ) {
+            value = XmlUtil.findLocalNameByQualifiedName(value);
+          } else {
+            value = namespacePrefix + ":" + XmlUtil.findLocalNameByQualifiedName(value);
+          }
+        }
+      }
+    }
+    return value;
+  }
+
+  /** getter for _local_ name */
+  public String getName() {
+    return XmlUtil.findLocalNameByQualifiedName(getName(null));
+  }
+
+  public String getNamespaceByContext(PsiElement context){
+    //while(context != null){
+    //  if(context instanceof XmlTag){
+    //    final XmlTag contextTag = ((XmlTag)context);
+    //    final XmlNSDescriptorImpl schemaDescriptor = XmlUtil.findXmlNSDescriptorByType(contextTag);
+    //    if (schemaDescriptor != null) {
+    //      return schemaDescriptor.getDefaultNamespace();
+    //    }
+    //  }
+    //  context = context.getContext();
+    //}
+    return getNamespace();
+  }
+
+  public String getNamespace(){
+    String name = getName();
+    if (name == null) return XmlUtil.EMPTY_URI;
+    final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(name);
+    final XmlNSDescriptorImpl xmlNSDescriptor = (XmlNSDescriptorImpl)getNSDescriptor();
+    if(xmlNSDescriptor == null || myDescriptorTag == null) return XmlUtil.EMPTY_URI;
+    return "".equals(namespacePrefix) ?
+           xmlNSDescriptor.getDefaultNamespace() :
+           myDescriptorTag.getNamespaceByPrefix(namespacePrefix);
+  }
+
+  public void init(PsiElement element){
+    if (myDescriptorTag!=element && myDescriptorTag!=null) {
+      NSDescriptor = null;
+    }
+    myDescriptorTag = (XmlTag) element;
+  }
+
+  public Object[] getDependences(){
+    return new Object[]{myDescriptorTag};
+  }
+
+  private XmlNSDescriptor getNSDescriptor(XmlElement context) {
+    XmlNSDescriptor nsDescriptor = getNSDescriptor();
+    if (context instanceof XmlTag && nsDescriptor instanceof XmlNSDescriptorImpl) {
+      final String defaultNamespace = ((XmlNSDescriptorImpl)nsDescriptor).getDefaultNamespace();
+      if (XmlUtil.XML_SCHEMA_URI.equals(defaultNamespace)) return nsDescriptor; // do not check for overriden for efficiency
+
+      final XmlTag tag = (XmlTag)context;
+      final String tagNs = tag.getNamespace();
+      if (tagNs.equals(defaultNamespace)) {
+        XmlNSDescriptor previousDescriptor = nsDescriptor;
+        nsDescriptor = tag.getNSDescriptor(tagNs, true);
+        if (nsDescriptor == null) nsDescriptor = previousDescriptor;
+      }
+    }
+    
+    return nsDescriptor;
+  }
+
+  public XmlNSDescriptor getNSDescriptor() {
+    XmlNSDescriptor nsDescriptor = NSDescriptor;
+    if (nsDescriptor == null || !NSDescriptor.getDeclaration().isValid()) {
+      final XmlFile file = XmlUtil.getContainingFile(getDeclaration());
+      if(file == null) return null;
+      final XmlDocument document = file.getDocument();
+      if(document == null) return null;
+      NSDescriptor = nsDescriptor = (XmlNSDescriptor)document.getMetaData();
+    }
+
+    return nsDescriptor;
+  }
+
+  @Override
+  public XmlElementsGroup getTopGroup() {
+    TypeDescriptor type = getType();
+    return type instanceof ComplexTypeDescriptor ? ((ComplexTypeDescriptor)type).getTopGroup() : null;
+  }
+
+  @Nullable
+  public TypeDescriptor getType() {
+    return getType(null);
+  }
+
+  @Nullable
+  public TypeDescriptor getType(XmlElement context) {
+    final XmlNSDescriptor nsDescriptor = getNSDescriptor(context);
+    if (!(nsDescriptor instanceof XmlNSTypeDescriptorProvider)) return null;
+
+    TypeDescriptor type = ((XmlNSTypeDescriptorProvider) nsDescriptor).getTypeDescriptor(myDescriptorTag);
+    if (type == null) {
+      String substAttr = myDescriptorTag.getAttributeValue("substitutionGroup");
+      if (substAttr != null) {
+        final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(substAttr);
+        final String namespace = "".equals(namespacePrefix) ?
+                                 ((XmlNSDescriptorImpl)getNSDescriptor()).getDefaultNamespace() :
+                                 myDescriptorTag.getNamespaceByPrefix(namespacePrefix);
+        final String local = XmlUtil.findLocalNameByQualifiedName(substAttr);
+        final XmlElementDescriptorImpl originalElement = (XmlElementDescriptorImpl)((XmlNSDescriptorImpl)getNSDescriptor()).getElementDescriptor(local, namespace);
+        if (originalElement != null) {
+          type = originalElement.getType(context);
+        }
+      }
+    }
+    return type;
+  }
+
+  public XmlElementDescriptor[] getElementsDescriptors(XmlTag context) {
+    if (context != null) {
+      final XmlElementDescriptor parentDescriptorByType = XmlUtil.findXmlDescriptorByType(context);
+      if (parentDescriptorByType != null && !parentDescriptorByType.equals(this)) {
+        return parentDescriptorByType.getElementsDescriptors(context);
+      }
+    }
+
+    XmlElementDescriptor[] elementsDescriptors = getElementsDescriptorsImpl(context);
+
+    final TypeDescriptor type = getType(context);
+
+    if (type instanceof ComplexTypeDescriptor) {
+      final ComplexTypeDescriptor descriptor = (ComplexTypeDescriptor)type;
+      String contextNs;
+      PsiFile containingFile = context != null ? context.getContainingFile():null;
+
+      if (context != null && !containingFile.isPhysical()) {
+        containingFile = containingFile.getOriginalFile();
+        //context = context.getParentTag();
+      }
+
+      if (context != null &&
+          ( descriptor.canContainTag(context.getLocalName(), contextNs = context.getNamespace(), context ) &&
+            (!contextNs.equals(getNamespace()) || descriptor.hasAnyInContentModel())
+          ) ) {
+        final XmlNSDescriptor nsDescriptor = getNSDescriptor();
+
+        if (nsDescriptor != null) {
+          elementsDescriptors = ArrayUtil.mergeArrays(
+            elementsDescriptors,
+            nsDescriptor.getRootElementsDescriptors(((XmlFile)containingFile).getDocument())
+          );
+        }
+      }
+    }
+
+    return elementsDescriptors;
+  }
+
+  private XmlElementDescriptor[] getElementsDescriptorsImpl(XmlElement context) {
+    TypeDescriptor type = getType(context);
+
+    if (type instanceof ComplexTypeDescriptor) {
+      ComplexTypeDescriptor typeDescriptor = (ComplexTypeDescriptor)type;
+
+      return typeDescriptor.getElements(context);
+    }
+
+    return EMPTY_ARRAY;
+  }
+
+  public XmlAttributeDescriptor[] getAttributesDescriptors(final XmlTag context) {
+
+    TypeDescriptor type = getType(context);
+
+    if (type instanceof ComplexTypeDescriptor) {
+      ComplexTypeDescriptor typeDescriptor = (ComplexTypeDescriptor)type;
+      XmlAttributeDescriptor[] attributeDescriptors = typeDescriptor.getAttributes(context);
+
+      if (context != null) {
+        final String contextNs = context.getNamespace();
+
+        boolean seenXmlNs = false;
+        for(String ns:context.knownNamespaces()) {
+          if (!contextNs.equals(ns) && ns.length() > 0) {
+            seenXmlNs |= XmlUtil.XML_NAMESPACE_URI.equals(ns);
+            attributeDescriptors = updateAttributeDescriptorsFromAny(context, typeDescriptor, attributeDescriptors, ns);
+          }
+        }
+
+        if (!seenXmlNs) {
+          attributeDescriptors = updateAttributeDescriptorsFromAny(context, typeDescriptor, attributeDescriptors, XmlUtil.XML_NAMESPACE_URI);
+        }
+      }
+      return attributeDescriptors;
+    }
+
+    return XmlAttributeDescriptor.EMPTY;
+  }
+
+  /** <xsd:anyAttribute> directive processed here */
+  private static XmlAttributeDescriptor[] updateAttributeDescriptorsFromAny(final XmlTag context,
+                                                                            final ComplexTypeDescriptor typeDescriptor,
+                                                                            XmlAttributeDescriptor[] attributeDescriptors,
+                                                                            final String ns) {
+    if (typeDescriptor.canContainAttribute(ns, null) != ComplexTypeDescriptor.CanContainAttributeType.CanNotContain) {
+      // anyAttribute found
+      final XmlNSDescriptor descriptor = context.getNSDescriptor(ns, true);
+
+      if (descriptor instanceof XmlNSDescriptorImpl) {
+        XmlAttributeDescriptor[] rootDescriptors = ((XmlNSDescriptorImpl)descriptor).getRootAttributeDescriptors(context);
+        attributeDescriptors = ArrayUtil.mergeArrays(attributeDescriptors, rootDescriptors);
+      }
+    }
+    return attributeDescriptors;
+  }
+
+  public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, final XmlTag context){
+    return getAttributeDescriptorImpl(attributeName,context);
+  }
+
+  @Nullable
+  private XmlAttributeDescriptor getAttributeDescriptorImpl(final String attributeName, XmlTag context) {
+    final String localName = XmlUtil.findLocalNameByQualifiedName(attributeName);
+    final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(attributeName);
+    final XmlNSDescriptorImpl xmlNSDescriptor = (XmlNSDescriptorImpl)getNSDescriptor();
+    final String namespace = namespacePrefix != null && namespacePrefix.isEmpty() ?
+                             ((xmlNSDescriptor != null)?xmlNSDescriptor.getDefaultNamespace():"") :
+                             context.getNamespaceByPrefix(namespacePrefix);
+
+    XmlAttributeDescriptor attribute = getAttribute(localName, namespace, context, attributeName);
+    
+    if (attribute instanceof AnyXmlAttributeDescriptor && namespace.length() > 0) {
+      final XmlNSDescriptor candidateNSDescriptor = context.getNSDescriptor(namespace, true);
+
+      if (candidateNSDescriptor instanceof XmlNSDescriptorImpl) {
+        final XmlNSDescriptorImpl nsDescriptor = (XmlNSDescriptorImpl)candidateNSDescriptor;
+
+        final XmlAttributeDescriptor xmlAttributeDescriptor = nsDescriptor.getAttribute(localName, namespace, context);
+        if (xmlAttributeDescriptor != null) return xmlAttributeDescriptor;
+        else {
+          final ComplexTypeDescriptor.CanContainAttributeType containAttributeType =
+            ((AnyXmlAttributeDescriptor)attribute).getCanContainAttributeType();
+          if (containAttributeType == ComplexTypeDescriptor.CanContainAttributeType.CanContainButDoNotSkip) {
+            attribute = null;
+          }
+        }
+      }
+    }
+    return attribute;
+  }
+
+  public XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attribute){
+    return getAttributeDescriptorImpl(attribute.getName(),attribute.getParent());
+  }
+
+  @Nullable
+  private XmlAttributeDescriptor getAttribute(String attributeName, String namespace, XmlTag context, String qName) {
+    XmlAttributeDescriptor[] descriptors = getAttributesDescriptors(context);
+
+    for (XmlAttributeDescriptor descriptor : descriptors) {
+      if (descriptor.getName().equals(attributeName) &&
+          descriptor.getName(context).equals(qName)
+         ) {
+        return descriptor;
+      }
+    }
+
+    TypeDescriptor type = getType(context);
+    if (type instanceof ComplexTypeDescriptor) {
+      ComplexTypeDescriptor descriptor = (ComplexTypeDescriptor)type;
+      final ComplexTypeDescriptor.CanContainAttributeType containAttributeType = descriptor.canContainAttribute(namespace, qName);
+
+      if (containAttributeType != ComplexTypeDescriptor.CanContainAttributeType.CanNotContain) {
+        return new AnyXmlAttributeDescriptor(attributeName, containAttributeType);
+      }
+    }
+
+    return null;
+  }
+
+  public int getContentType() {
+    TypeDescriptor type = getType();
+
+    if (type instanceof ComplexTypeDescriptor) {
+      return ((ComplexTypeDescriptor)type).getContentType();
+    }
+
+    return CONTENT_TYPE_MIXED;
+  }
+
+  @Override
+  public String getDefaultValue() {
+    return myDescriptorTag.getAttributeValue("default");
+  }
+
+  @Nullable
+  public XmlElementDescriptor getElementDescriptor(final String name) {
+      final String localName = XmlUtil.findLocalNameByQualifiedName(name);
+      final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(name);
+      final String namespace = "".equals(namespacePrefix) ?
+                               ((XmlNSDescriptorImpl)getNSDescriptor()).getDefaultNamespace() :
+                               myDescriptorTag.getNamespaceByPrefix(namespacePrefix);
+    return getElementDescriptor(localName, namespace, null, name);
+  }
+
+  @Nullable
+  protected XmlElementDescriptor getElementDescriptor(final String localName, final String namespace, XmlElement context, String fullName) {
+    XmlElementDescriptor[] elements = getElementsDescriptorsImpl(context);
+
+    for (XmlElementDescriptor element1 : elements) {
+      final XmlElementDescriptorImpl element = (XmlElementDescriptorImpl)element1;
+      final String namespaceByContext = element.getNamespaceByContext(context);
+
+      if (element.getName().equals(localName)) {
+        if (namespace == null ||
+            namespace.equals(namespaceByContext) ||
+            namespaceByContext.equals(XmlUtil.EMPTY_URI) ||
+            element.getName(context).equals(fullName) || (namespace.length() == 0) &&
+                                                         element.getDefaultName().equals(fullName)
+           ) {
+          return element;
+        }
+        else {
+          final XmlNSDescriptor descriptor = context instanceof XmlTag? ((XmlTag)context).getNSDescriptor(namespace, true) : null;
+
+          // schema's targetNamespace could be different from file systemId used as NS
+          if (descriptor instanceof XmlNSDescriptorImpl &&
+              ((XmlNSDescriptorImpl)descriptor).getDefaultNamespace().equals(namespaceByContext)
+             ) {
+            return element;
+          }
+        }
+      }
+    }
+
+    TypeDescriptor type = getType(context);
+    if (type instanceof ComplexTypeDescriptor) {
+      ComplexTypeDescriptor descriptor = (ComplexTypeDescriptor)type;
+      if (descriptor.canContainTag(localName, namespace, context)) {
+        return new AnyXmlElementDescriptor(this, getNSDescriptor());
+      }
+    }
+
+    return null;
+  }
+
+  public XmlElementDescriptor getElementDescriptor(XmlTag element, XmlTag contextTag){
+    final XmlElement context = (XmlElement)element.getParent();
+
+    XmlElementDescriptor elementDescriptor = getElementDescriptor(
+      element.getLocalName(),
+      element.getNamespace(), context,
+      element.getName()
+    );
+
+    if(elementDescriptor == null || element.getAttributeValue("xsi:type") != null){
+      final XmlElementDescriptor xmlDescriptorByType = XmlUtil.findXmlDescriptorByType(element);
+
+      if (xmlDescriptorByType != null) elementDescriptor = xmlDescriptorByType;
+      else if (context instanceof XmlTag && ((XmlTag)context).getAttributeValue("xsi:type") != null && askParentDescriptorViaXsi()) {
+        final XmlElementDescriptor parentXmlDescriptorByType = XmlUtil.findXmlDescriptorByType(((XmlTag)context));
+        if (parentXmlDescriptorByType != null) {
+          elementDescriptor = parentXmlDescriptorByType.getElementDescriptor(element, contextTag);
+        }
+      }
+    }
+    return elementDescriptor;
+  }
+
+  protected boolean askParentDescriptorViaXsi() {
+    return true;
+  }
+
+  public String getQualifiedName() {
+    if (!"".equals(getNS())) {
+      return getNS() + ":" + getName();
+    }
+
+    return getName();
+  }
+
+  @Nullable
+  private String getNS(){
+    return XmlUtil.findNamespacePrefixByURI((XmlFile) myDescriptorTag.getContainingFile(), getNamespace());
+  }
+
+  public String getDefaultName() {
+    final PsiFile psiFile = myDescriptorTag.getContainingFile();
+    XmlTag rootTag = psiFile instanceof XmlFile ?((XmlFile)psiFile).getRootTag():null;
+
+    if (rootTag != null && QUALIFIED_ATTR_VALUE.equals(rootTag.getAttributeValue(ELEMENT_FORM_DEFAULT))) {
+      return getQualifiedName();
+    }
+
+    return getName();
+  }
+
+  public boolean isAbstract() {
+    return isAbstractDeclaration(myDescriptorTag);
+  }
+
+  public static Boolean isAbstractDeclaration(final XmlTag descriptorTag) {
+    return Boolean.valueOf(descriptorTag.getAttributeValue("abstract"));
+  }
+
+  public void setName(String name) throws IncorrectOperationException {
+    NamedObjectDescriptor.setName(myDescriptorTag, name);
+  }
+
+  public void setValidator(final Validator<XmlTag> validator) {
+    myValidator = validator;
+  }
+
+  public void validate(@NotNull XmlTag context, @NotNull ValidationHost host) {
+    Validator<XmlTag> validator = myValidator;
+    if (validator != null) {
+      validator.validate(context, host);
+    }
+  }
+
+  public boolean allowElementsFromNamespace(final String namespace, final XmlTag context) {
+    final TypeDescriptor type = getType(context);
+    
+    if (type instanceof ComplexTypeDescriptor) {
+      final ComplexTypeDescriptor typeDescriptor = (ComplexTypeDescriptor)type;
+      return typeDescriptor.canContainTag("a", namespace, context) ||
+             typeDescriptor.getNsDescriptors().hasSubstitutions() ||
+             XmlUtil.nsFromTemplateFramework(namespace)
+        ;
+    }
+    return false;
+  }
+
+  @Override
+  public String toString() {
+    return getName() + " (" + getNamespace() + ")";
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    XmlElementDescriptorImpl that = (XmlElementDescriptorImpl)o;
+
+    if (myDescriptorTag != null ? !myDescriptorTag.equals(that.myDescriptorTag) : that.myDescriptorTag != null) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return myDescriptorTag != null ? myDescriptorTag.hashCode() : 0;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupBase.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupBase.java
new file mode 100644
index 0000000..0280f97
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupBase.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementsGroup;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public abstract class XmlElementsGroupBase implements XmlElementsGroup {
+
+  protected final XmlTag myTag;
+  private final XmlElementsGroup myParent;
+  private final XmlTag myRef;
+
+  public XmlElementsGroupBase(XmlTag tag, XmlElementsGroup parent, XmlTag ref) {
+    myTag = tag;
+    myParent = parent;
+    myRef = ref;
+  }
+
+  @Override
+  public int getMinOccurs() {
+    return getMinOccursImpl(myRef) * getMinOccursImpl(myTag);
+  }
+
+  private static int getMinOccursImpl(XmlTag tag) {
+    if (tag == null) return 1;
+    String value = tag.getAttributeValue("minOccurs");
+    try {
+      return value == null ? 1 : Integer.parseInt(value);
+    }
+    catch (NumberFormatException e) {
+      return 1;
+    }
+  }
+
+  @Override
+  public int getMaxOccurs() {
+    return getMaxOccursImpl(myRef) * getMaxOccursImpl(myTag);
+  }
+
+  private static int getMaxOccursImpl(XmlTag tag) {
+    if (tag == null) return 1;
+    String value = tag.getAttributeValue("maxOccurs");
+    if (value == null) return 1;
+    if ("unbounded".equals(value)) return Integer.MAX_VALUE;
+    try {
+      return Integer.parseInt(value);
+    }
+    catch (NumberFormatException e) {
+      return 1;
+    }
+  }
+
+  @Override
+  public XmlElementsGroup getParentGroup() {
+    return myParent;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupImpl.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupImpl.java
new file mode 100644
index 0000000..a4ea363
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupImpl.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlElementsGroupImpl extends XmlElementsGroupBase {
+
+  private final static Map<String, Type> TYPES = new HashMap<String, Type>();
+  static {
+    TYPES.put("sequence", Type.SEQUENCE);
+    TYPES.put("choice", Type.CHOICE);
+    TYPES.put("all", Type.ALL);
+    TYPES.put("group", Type.GROUP);
+  }
+
+  private final List<XmlElementsGroup> mySubGroups = new ArrayList<XmlElementsGroup>();
+
+  public XmlElementsGroupImpl(XmlTag tag, XmlElementsGroup parent, XmlTag ref) {
+    super(tag, parent, ref);
+  }
+
+  @Override
+  public Type getGroupType() {
+    return getTagType(myTag);
+  }
+
+  public static Type getTagType(XmlTag tag) {
+    return TYPES.get(tag.getLocalName());
+  }
+
+  @Override
+  public List<XmlElementsGroup> getSubGroups() {
+    return mySubGroups;
+  }
+
+  @Override
+  public XmlElementDescriptor getLeafDescriptor() {
+    throw new RuntimeException("not a leaf group");
+  }
+
+  public void addSubGroup(XmlElementsGroup group) {
+    mySubGroups.add(group);
+  }
+
+  @Override
+  public String toString() {
+    return getGroupType().toString();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupLeaf.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupLeaf.java
new file mode 100644
index 0000000..691f74d
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupLeaf.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlElementsGroup;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlElementsGroupLeaf extends XmlElementsGroupBase {
+
+  private final XmlElementDescriptor myDescriptor;
+
+  public XmlElementsGroupLeaf(XmlTag tag, XmlElementDescriptor descriptor, XmlElementsGroup parent, XmlTag ref) {
+    super(tag, parent, ref);
+    myDescriptor = descriptor;
+  }
+
+  @Override
+  public Type getGroupType() {
+    return Type.LEAF;
+  }
+
+  @Override
+  public List<XmlElementsGroup> getSubGroups() {
+    return Collections.emptyList();
+  }
+
+  @Override
+  public XmlElementDescriptor getLeafDescriptor() {
+    return myDescriptor;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupProcessor.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupProcessor.java
new file mode 100644
index 0000000..e89ca81
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlElementsGroupProcessor.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementsGroup;
+
+import java.util.Stack;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlElementsGroupProcessor extends XmlSchemaTagsProcessor {
+
+  final Stack<XmlElementsGroup> myGroups = new Stack<XmlElementsGroup>();
+
+  public static XmlElementsGroup computeGroups(XmlNSDescriptorImpl descriptor, XmlTag tag) {
+    XmlElementsGroupProcessor processor = new XmlElementsGroupProcessor(descriptor);
+    processor.startProcessing(tag);
+    return processor.getRootGroup();
+  }
+
+  private XmlElementsGroup getRootGroup() {
+    return myGroups.get(0);
+  }
+
+  private XmlElementsGroupProcessor(XmlNSDescriptorImpl nsDescriptor) {
+    super(nsDescriptor, "attribute");
+    myGroups.push(new XmlElementsGroupImpl(null, null, null) {
+      @Override
+      public Type getGroupType() {
+        return Type.GROUP;
+      }
+
+      @Override
+      public String toString() {
+        return "root";
+      }
+    });
+  }
+
+  @Override
+  protected void tagStarted(XmlTag tag, String tagName, XmlTag context, XmlTag ref) {
+    XmlElementsGroup.Type type = XmlElementsGroupImpl.getTagType(tag);
+    if (type != null) {
+      XmlElementsGroupImpl group = new XmlElementsGroupImpl(tag, myGroups.peek(), ref);
+      addSubGroup(group);
+      myGroups.push(group);
+    }
+    else if ("element".equals(tagName)) {
+      XmlElementsGroup group = new XmlElementsGroupLeaf(tag, myNsDescriptor.createElementDescriptor(tag), myGroups.peek(), ref);
+      if (!myGroups.empty()) {
+        addSubGroup(group);
+      }
+      else {
+        myGroups.push(group);
+      }
+    }
+  }
+
+  @Override
+  protected void tagFinished(XmlTag tag) {
+    if (!myGroups.empty() && XmlElementsGroupImpl.getTagType(tag) != null) {
+      myGroups.pop();
+    }
+  }
+
+  private void addSubGroup(XmlElementsGroup group) {
+    if (!myGroups.empty()) {
+      XmlElementsGroup last = myGroups.peek();
+      if (last instanceof XmlElementsGroupImpl) {
+        ((XmlElementsGroupImpl)last).addSubGroup(group);
+      }
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
new file mode 100644
index 0000000..8c1582f
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
@@ -0,0 +1,1026 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.codeInsight.daemon.Validator;
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.XmlNSDescriptorEx;
+import com.intellij.xml.impl.ExternalDocumentValidator;
+import com.intellij.xml.util.XmlUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Mike
+ */
+@SuppressWarnings({"HardCodedStringLiteral"})
+public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocument>, DumbAware, XmlNSTypeDescriptorProvider {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.impl.schema.XmlNSDescriptorImpl");
+  @NonNls private static final Set<String> STD_TYPES = new HashSet<String>();
+  private static final Set<String> UNDECLARED_STD_TYPES = new HashSet<String>();
+  private XmlFile myFile;
+  private XmlTag myTag;
+  private String myTargetNamespace;
+  @NonNls
+  public static final String XSD_PREFIX = "xsd";
+  
+  @NonNls static final String ELEMENT_TAG_NAME = "element";
+  @NonNls static final String ATTRIBUTE_TAG_NAME = "attribute";
+  @NonNls static final String COMPLEX_TYPE_TAG_NAME = "complexType";
+  @NonNls static final String SEQUENCE_TAG_NAME = "sequence";
+  @NonNls static final String SCHEMA_TAG_NAME = "schema";
+  @NonNls private static final String INCLUDE_TAG_NAME = "include";
+  @NonNls private static final String IMPORT_TAG_NAME = "import";
+  @NonNls private static final String REDEFINE_TAG_NAME = "redefine";
+
+  public XmlNSDescriptorImpl(XmlFile file) {
+    init(file.getDocument());
+  }
+                                          
+  public XmlNSDescriptorImpl() {
+  }
+
+  private Object[] dependencies;
+
+  private static final ThreadLocal<Set<PsiFile>> myRedefinedDescriptorsInProcessing = new ThreadLocal<Set<PsiFile>>();
+
+  private static void collectDependencies(@Nullable XmlTag myTag, @NotNull XmlFile myFile, @NotNull Set<PsiFile> visited) {
+    if (visited.contains(myFile)) return;
+    visited.add( myFile );
+
+    if (myTag == null) return;
+    XmlTag[] tags = myTag.getSubTags();
+
+    for (final XmlTag tag : tags) {
+      if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
+          equalsToSchemaName(tag, IMPORT_TAG_NAME)
+        ) {
+        final XmlAttribute schemaLocation = tag.getAttribute("schemaLocation");
+        if (schemaLocation != null) {
+          final XmlFile xmlFile = XmlUtil.findNamespace(myFile, schemaLocation.getValue());
+          addDependency(xmlFile, visited);
+        }
+      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
+        myRedefinedDescriptorsInProcessing.set(visited);
+        try {
+          final XmlFile file = getRedefinedElementDescriptorFile(tag);
+          addDependency(file, visited);
+        } finally {
+          myRedefinedDescriptorsInProcessing.set(null);
+        }
+      }
+    }
+
+    final String schemaLocationDeclaration = myTag.getAttributeValue("schemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI);
+    if(schemaLocationDeclaration != null) {
+      final StringTokenizer tokenizer = new StringTokenizer(schemaLocationDeclaration);
+
+      while(tokenizer.hasMoreTokens()){
+        final String uri = tokenizer.nextToken();
+
+        if(tokenizer.hasMoreTokens()){
+          PsiFile resourceLocation = ExternalResourceManager.getInstance().getResourceLocation(tokenizer.nextToken(), myFile, null);
+          if (resourceLocation == null && uri != null) resourceLocation = ExternalResourceManager.getInstance().getResourceLocation(uri, myFile, null);
+
+          if (resourceLocation instanceof XmlFile) addDependency((XmlFile)resourceLocation, visited);
+        }
+      }
+    }
+  }
+
+  private static void addDependency(final XmlFile file, final Set<PsiFile> visited) {
+    if (file != null) {
+      final XmlDocument document = file.getDocument();
+      collectDependencies(document != null ? document.getRootTag():null, file, visited);
+    }
+  }
+
+  public XmlFile getDescriptorFile() {
+    return myFile;
+  }
+
+  public boolean isHierarhyEnabled() {
+    return true;
+  }
+
+  public String getDefaultNamespace(){
+    return myTargetNamespace != null ? myTargetNamespace : "";
+  }
+
+  static class QNameKey extends Pair<String, String>{
+     QNameKey(String name, String namespace) {
+      super(name, namespace);
+    }
+  }
+  private final Map<QNameKey, CachedValue<XmlElementDescriptor>> myDescriptorsMap = Collections.synchronizedMap(new HashMap<QNameKey, CachedValue<XmlElementDescriptor>>());
+  private final Map<Pair<QNameKey, XmlTag>, CachedValue<TypeDescriptor>> myTypesMap = Collections.synchronizedMap(new HashMap<Pair<QNameKey,XmlTag>, CachedValue<TypeDescriptor>>());
+
+  @Nullable
+  public XmlElementDescriptor getElementDescriptor(String localName, String namespace) {
+    return getElementDescriptor(localName, namespace, new HashSet<XmlNSDescriptorImpl>(),false);
+  }
+
+  @Nullable
+  public XmlElementDescriptor getElementDescriptor(String localName, String namespace, Set<XmlNSDescriptorImpl> visited, boolean reference) {
+    if(visited.contains(this)) return null;
+
+    final QNameKey pair = new QNameKey(namespace, localName);
+    final CachedValue<XmlElementDescriptor> descriptor = myDescriptorsMap.get(pair);
+    if(descriptor != null) {
+      final XmlElementDescriptor value = descriptor.getValue();
+      if (value == null || value.getDeclaration().isValid()) return value;
+    }
+
+    final XmlTag rootTag = myTag;
+    if (rootTag == null) return null;
+    XmlTag[] tags = rootTag.getSubTags();
+    visited.add( this );
+
+    LOG.assertTrue(rootTag.isValid());
+    for (final XmlTag tag : tags) {
+      if (equalsToSchemaName(tag, ELEMENT_TAG_NAME)) {
+        String name = tag.getAttributeValue("name");
+
+        if (name != null) {
+          if (checkElementNameEquivalence(localName, namespace, name, tag)) {
+            final CachedValue<XmlElementDescriptor> cachedValue = CachedValuesManager.getManager(tag.getProject()).createCachedValue(new CachedValueProvider<XmlElementDescriptor>() {
+                public Result<XmlElementDescriptor> compute() {
+                  final String name = tag.getAttributeValue("name");
+
+                  if (name != null && !name.equals(pair.second)) {
+                    myDescriptorsMap.remove(pair);
+                    return new Result<XmlElementDescriptor>(null);
+                  }
+                  final XmlElementDescriptor xmlElementDescriptor = createElementDescriptor(tag);
+                  return new Result<XmlElementDescriptor>(xmlElementDescriptor, xmlElementDescriptor.getDependences());
+                }
+              }, false);
+            myDescriptorsMap.put(pair, cachedValue);
+            return cachedValue.getValue();
+          }
+        }
+      }
+      else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
+               (reference &&
+                equalsToSchemaName(tag, IMPORT_TAG_NAME) &&
+                ( namespace.equals(tag.getAttributeValue("namespace")) ||
+                  namespace.length() == 0 && tag.getAttributeValue("namespace") == null
+                )
+               )
+        ) {
+        final XmlAttribute schemaLocation = tag.getAttribute("schemaLocation");
+        if (schemaLocation != null) {
+          final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation.getValue());
+          if (xmlFile != null) {
+            final XmlDocument includedDocument = xmlFile.getDocument();
+            if (includedDocument != null) {
+              final PsiMetaData data = includedDocument.getMetaData();
+              if (data instanceof XmlNSDescriptorImpl) {
+                final XmlElementDescriptor elementDescriptor =
+                  ((XmlNSDescriptorImpl)data).getElementDescriptor(localName, namespace, visited, reference);
+                if (elementDescriptor != null) {
+                  //final CachedValue<XmlElementDescriptor> value = includedDocument.getManager().getCachedValuesManager()
+                  //  .createCachedValue(new CachedValueProvider<XmlElementDescriptor>() {
+                  //    public Result<XmlElementDescriptor> compute() {
+                  //      return new Result<XmlElementDescriptor>(elementDescriptor, elementDescriptor.getDependences());
+                  //    }
+                  //  }, false);
+                  //return value.getValue();
+                  return elementDescriptor;
+                }
+              }
+            }
+          }
+        }
+      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
+        final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag);
+        if (nsDescriptor != null) {
+          final XmlElementDescriptor xmlElementDescriptor = nsDescriptor.getElementDescriptor(localName, namespace, visited, reference);
+          if (xmlElementDescriptor instanceof XmlElementDescriptorImpl) {
+            return new RedefinedElementDescriptor((XmlElementDescriptorImpl)xmlElementDescriptor, this);
+          }
+        }
+      }
+    }
+
+    return null;
+  }
+
+  protected XmlElementDescriptor createElementDescriptor(final XmlTag tag) {
+    return new XmlElementDescriptorImpl(tag);
+  }
+
+  private boolean checkElementNameEquivalence(String localName, String namespace, String fqn, XmlTag context){
+    final String localAttrName = XmlUtil.findLocalNameByQualifiedName(fqn);
+    if (!localAttrName.equals(localName)) return false;
+    final String attrNamespace = context.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(fqn));
+    if (attrNamespace.equals(namespace)) return true;
+
+    if(myTargetNamespace == null){
+      if(XmlUtil.EMPTY_URI.equals(attrNamespace))
+        return true;
+    }
+    else {
+      final boolean b = myTargetNamespace.equals(namespace);
+      if (b) return b;
+      return context.getNSDescriptor(namespace, true) == this; // schema's targetNamespace could be different from file systemId
+    }
+    return false;
+  }
+
+  @Nullable
+  public XmlAttributeDescriptor getAttribute(String localName, String namespace, final XmlTag context) {
+    return getAttributeImpl(localName, namespace, null);
+  }
+
+  @Nullable
+  private XmlAttributeDescriptor getAttributeImpl(String localName, String namespace, @Nullable Set<XmlTag> visited) {
+    if (myTag == null) return null;
+
+    XmlNSDescriptorImpl nsDescriptor = (XmlNSDescriptorImpl)myTag.getNSDescriptor(namespace, true);
+
+    if (nsDescriptor != this && nsDescriptor != null) {
+      return nsDescriptor.getAttributeImpl(
+        localName,
+        namespace,
+        visited
+      );
+    }
+
+    if (visited == null) visited = new HashSet<XmlTag>(1);
+    else if(visited.contains(myTag)) return null;
+    visited.add(myTag);
+    XmlTag[] tags = myTag.getSubTags();
+
+    for (XmlTag tag : tags) {
+      if (equalsToSchemaName(tag, ATTRIBUTE_TAG_NAME)) {
+        String name = tag.getAttributeValue("name");
+
+        if (name != null) {
+          if (checkElementNameEquivalence(localName, namespace, name, tag)) {
+            return createAttributeDescriptor(tag);
+          }
+        }
+      } else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
+                 (equalsToSchemaName(tag, IMPORT_TAG_NAME) &&
+                  namespace.equals(tag.getAttributeValue("namespace"))
+                 )
+        ) {
+        final XmlAttribute schemaLocation = tag.getAttribute("schemaLocation");
+
+        if (schemaLocation != null) {
+          final XmlFile xmlFile = XmlUtil.findNamespace(myTag.getContainingFile(), schemaLocation.getValue());
+
+          if (xmlFile != null) {
+
+            final XmlDocument includedDocument = xmlFile.getDocument();
+            if (includedDocument != null) {
+              final PsiMetaData data = includedDocument.getMetaData();
+
+              if(data instanceof XmlNSDescriptorImpl){
+                final XmlAttributeDescriptor attributeDescriptor = ((XmlNSDescriptorImpl)data).getAttributeImpl(localName, namespace,visited);
+
+                if(attributeDescriptor != null){
+                  final CachedValue<XmlAttributeDescriptor> value = CachedValuesManager.getManager(includedDocument.getProject()).createCachedValue(
+                    new CachedValueProvider<XmlAttributeDescriptor>(){
+                      public Result<XmlAttributeDescriptor> compute() {
+                        return new Result<XmlAttributeDescriptor>(attributeDescriptor, attributeDescriptor.getDependences());
+                      }
+                    },
+                    false
+                  );
+                  return value.getValue();
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return null;
+  }
+
+  protected XmlAttributeDescriptorImpl createAttributeDescriptor(final XmlTag tag) {
+    return new XmlAttributeDescriptorImpl(tag);
+  }
+
+  public TypeDescriptor getTypeDescriptor(XmlTag descriptorTag) {
+    String type = descriptorTag.getAttributeValue("type");
+
+    if (type != null) {
+      return getTypeDescriptor(type, descriptorTag);
+    }
+
+    return findTypeDescriptorImpl(descriptorTag, null, null, null);
+  }
+
+  public TypeDescriptor getTypeDescriptor(final String name, XmlTag context) {
+    if(checkSchemaNamespace(name, context)){
+      final String localNameByQualifiedName = XmlUtil.findLocalNameByQualifiedName(name);
+      
+      if (STD_TYPES.contains(localNameByQualifiedName) &&
+          ( name.length() == localNameByQualifiedName.length() ||
+            UNDECLARED_STD_TYPES.contains(localNameByQualifiedName)
+          )
+         )
+        return new StdTypeDescriptor(localNameByQualifiedName);
+    }
+
+    return findTypeDescriptor(name, context);
+  }
+
+  @Nullable
+  public XmlElementDescriptor getDescriptorByType(String qName, XmlTag instanceTag){
+    if(myTag == null) return null;
+    final TypeDescriptor typeDescriptor = findTypeDescriptor(qName, instanceTag);
+    if(!(typeDescriptor instanceof ComplexTypeDescriptor)) return null;
+    return new XmlElementDescriptorByType(instanceTag, (ComplexTypeDescriptor)typeDescriptor);
+  }
+
+  private static boolean checkSchemaNamespace(String name, XmlTag context){
+    final String namespace = context.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(name));
+    if(namespace.length() > 0){
+      return checkSchemaNamespace(namespace);
+    }
+    return XSD_PREFIX.equals(XmlUtil.findPrefixByQualifiedName(name));
+  }
+
+  public static boolean checkSchemaNamespace(String namespace) {
+    return XmlUtil.XML_SCHEMA_URI.equals(namespace) ||
+           XmlUtil.XML_SCHEMA_URI2.equals(namespace) ||
+           XmlUtil.XML_SCHEMA_URI3.equals(namespace);
+  }
+
+  public static boolean checkSchemaNamespace(XmlTag context) {
+    LOG.assertTrue(context.isValid());
+    final String namespace = context.getNamespace();
+    if (namespace.length() > 0) {
+      return checkSchemaNamespace(namespace);
+    }
+    return StringUtil.startsWithConcatenationOf(context.getName(), XSD_PREFIX, ":");
+  }
+
+  static @NotNull XmlNSDescriptorImpl getNSDescriptorToSearchIn(XmlTag rootTag, final String name, XmlNSDescriptorImpl defaultNSDescriptor) {
+    if (name == null) return defaultNSDescriptor;
+    final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(name);
+
+    if (namespacePrefix != null && namespacePrefix.length() > 0) {
+      final String namespace = rootTag.getNamespaceByPrefix(namespacePrefix);
+      final XmlNSDescriptor nsDescriptor = rootTag.getNSDescriptor(namespace, true);
+
+      if (nsDescriptor instanceof XmlNSDescriptorImpl) {
+        return (XmlNSDescriptorImpl)nsDescriptor;
+      }
+    }
+
+    return defaultNSDescriptor;
+  }
+
+  @Nullable
+  protected TypeDescriptor findTypeDescriptor(final String qname) {
+    return findTypeDescriptor(qname, myTag);
+  }
+
+  @Nullable
+  protected TypeDescriptor findTypeDescriptor(final String qname, XmlTag context) {
+    String namespace = context.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(qname));
+    return findTypeDescriptor(XmlUtil.findLocalNameByQualifiedName(qname), namespace);
+  }
+
+  @Nullable
+  private TypeDescriptor findTypeDescriptor(String localName, String namespace) {
+    return findTypeDescriptorImpl(myTag, localName, namespace, null);
+  }
+
+  @Nullable
+  protected TypeDescriptor findTypeDescriptorImpl(XmlTag rootTag, final String name, String namespace, Set<XmlTag> visited) {
+    XmlNSDescriptorImpl responsibleDescriptor = this;
+    if (namespace != null && namespace.length() != 0 && !namespace.equals(getDefaultNamespace())) {
+      final XmlNSDescriptor nsDescriptor = rootTag.getNSDescriptor(namespace, true);
+
+      if (nsDescriptor instanceof XmlNSDescriptorImpl) {
+        responsibleDescriptor = (XmlNSDescriptorImpl)nsDescriptor;
+      }
+    }
+
+    if (responsibleDescriptor != this) {
+      return responsibleDescriptor.findTypeDescriptor(XmlUtil.findLocalNameByQualifiedName(name));
+    }
+
+    if (rootTag == null) return null;
+    if (visited != null) {
+      if (visited.contains(rootTag)) return null;
+      visited.add(rootTag);
+    }
+
+    final Pair<QNameKey, XmlTag> pair = new Pair<QNameKey, XmlTag>(new QNameKey(name, namespace), rootTag);
+
+    final CachedValue<TypeDescriptor> descriptor = myTypesMap.get(pair);
+    if(descriptor != null) {
+      TypeDescriptor value = descriptor.getValue();
+      if (value == null ||
+          ( value instanceof ComplexTypeDescriptor &&
+            ((ComplexTypeDescriptor)value).getDeclaration().isValid()
+          )
+         )
+      return value;
+    }
+
+    XmlTag[] tags = rootTag.getSubTags();
+
+    if (visited == null) {
+      visited = new HashSet<XmlTag>(1);
+      visited.add(rootTag);
+    }
+
+    return doFindIn(tags, name, namespace, pair, rootTag, visited);
+  }
+
+  private TypeDescriptor doFindIn(final XmlTag[] tags, final String name, final String namespace, final Pair<QNameKey, XmlTag> pair, final XmlTag rootTag, final Set<XmlTag> visited) {
+    for (final XmlTag tag : tags) {
+      if (equalsToSchemaName(tag, "complexType")) {
+        if (name == null) {
+          CachedValue<TypeDescriptor> value = createAndPutTypesCachedValue(tag, pair);
+          return value.getValue();
+        }
+
+        String nameAttribute = tag.getAttributeValue("name");
+
+        if (isSameName(name, namespace, nameAttribute)) {
+          CachedValue<TypeDescriptor> cachedValue = createAndPutTypesCachedValue(tag, pair);
+          return cachedValue.getValue();
+        }
+      }
+      else if (equalsToSchemaName(tag, "simpleType")) {
+
+        if (name == null) {
+          CachedValue<TypeDescriptor> value = createAndPutTypesCachedValueSimpleType(tag, pair);
+          return value.getValue();
+        }
+
+        String nameAttribute = tag.getAttributeValue("name");
+
+        if (isSameName(name, namespace, nameAttribute)) {
+          CachedValue<TypeDescriptor> cachedValue = createAndPutTypesCachedValue(tag, pair);
+          return cachedValue.getValue();
+        }
+      }
+      else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
+               ( equalsToSchemaName(tag, IMPORT_TAG_NAME) &&
+                 (namespace == null || !namespace.equals(getDefaultNamespace()))
+               )
+              ) {
+        final String schemaLocation = tag.getAttributeValue("schemaLocation");
+        if (schemaLocation != null) {
+          final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation);
+
+          if (xmlFile != null) {
+            final XmlDocument document = xmlFile.getDocument();
+
+            if (document != null) {
+
+              final CachedValue<TypeDescriptor> value = CachedValuesManager.getManager(tag.getProject()).createCachedValue(new CachedValueProvider<TypeDescriptor>() {
+                  public Result<TypeDescriptor> compute() {
+                    final String currentName = tag.getAttributeValue("name");
+
+                    if (( currentName != null &&
+                          !currentName.equals(XmlUtil.findLocalNameByQualifiedName(name)) ) ||
+                         !xmlFile.isValid() ||
+                         xmlFile.getDocument() == null
+                       ) {
+                      myTypesMap.remove(pair);
+                      return new Result<TypeDescriptor>(null);
+                    }
+
+                    final XmlDocument document = xmlFile.getDocument();
+                    final XmlNSDescriptorImpl nsDescriptor = findNSDescriptor(tag, document);
+
+                    if (nsDescriptor == null) {
+                      myTypesMap.remove(pair);
+                      return new Result<TypeDescriptor>(null);
+                    }
+
+                    final XmlTag rTag = document.getRootTag();
+
+                    final TypeDescriptor complexTypeDescriptor = nsDescriptor.findTypeDescriptorImpl(rTag, name, namespace, visited);
+                    return new Result<TypeDescriptor>(complexTypeDescriptor, rTag);
+                  }
+                }, false
+              );
+
+              if (value.getValue() != null) {
+                myTypesMap.put(pair, value);
+                return value.getValue();
+              }
+            }
+          }
+        }
+      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
+        final XmlTag[] subTags = tag.getSubTags();
+        TypeDescriptor descriptor = doFindIn(subTags, name, namespace, pair, rootTag, visited);
+        if (descriptor != null) return descriptor;
+
+        final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag);
+        if (nsDescriptor != null) {
+          final XmlTag redefinedRootTag = ((XmlDocument)nsDescriptor.getDeclaration()).getRootTag();
+          descriptor = doFindIn(redefinedRootTag.getSubTags(), name, namespace, pair, redefinedRootTag, visited);
+          if (descriptor != null) return descriptor;
+        }
+      }
+    }
+    return null;
+  }
+
+  private boolean isSameName(@NotNull String name, String namespace, String nameAttribute) {
+    return nameAttribute != null &&
+           (nameAttribute.equals(name) || (name.indexOf(":") >= 0 && nameAttribute.equals(name.substring(name.indexOf(":") + 1)))) &&
+           (namespace == null || namespace.length() == 0 || namespace.equals(getDefaultNamespace()))
+      ;
+  }
+
+  private XmlNSDescriptorImpl findNSDescriptor(final XmlTag tag, final XmlDocument document) {
+    final XmlNSDescriptorImpl nsDescriptor;
+    if(IMPORT_TAG_NAME.equals(tag.getLocalName())) {
+      final XmlNSDescriptor importedDescriptor = (XmlNSDescriptor)document.getMetaData();
+      nsDescriptor = (importedDescriptor instanceof XmlNSDescriptorImpl) ?
+                     (XmlNSDescriptorImpl)importedDescriptor:
+                     this;
+    }
+    else {
+      nsDescriptor = this;
+    }
+    return nsDescriptor;
+  }
+
+  private CachedValue<TypeDescriptor> createAndPutTypesCachedValueSimpleType(final XmlTag tag, final Pair<QNameKey, XmlTag> pair) {
+    final CachedValue<TypeDescriptor> value = CachedValuesManager.getManager(tag.getProject()).createCachedValue(new CachedValueProvider<TypeDescriptor>() {
+      public CachedValueProvider.Result<TypeDescriptor> compute() {
+        final SimpleTypeDescriptor simpleTypeDescriptor = new SimpleTypeDescriptor(tag);
+        return new Result<TypeDescriptor>(simpleTypeDescriptor, tag);
+      }
+    }, false);
+    myTypesMap.put(pair, value);
+    return value;
+  }
+
+  private CachedValue<TypeDescriptor> createAndPutTypesCachedValue(final XmlTag tag, final Pair<QNameKey, XmlTag> pair) {
+    final CachedValue<TypeDescriptor> value = CachedValuesManager.getManager(tag.getProject()).createCachedValue(new CachedValueProvider<TypeDescriptor>() {
+      public CachedValueProvider.Result<TypeDescriptor> compute() {
+        final String name = tag.getAttributeValue("name");
+        
+        if (name != null &&
+            pair.first != null &&
+            pair.first.first != null &&
+            !name.equals(XmlUtil.findLocalNameByQualifiedName(pair.first.first))
+           ) {
+          myTypesMap.remove(pair);
+          return new Result<TypeDescriptor>(null);
+        }
+        final ComplexTypeDescriptor complexTypeDescriptor = new ComplexTypeDescriptor(XmlNSDescriptorImpl.this, tag); 
+        return new Result<TypeDescriptor>(complexTypeDescriptor, tag);
+      }
+    }, false);
+    myTypesMap.put(pair, value);
+    return value;
+  }
+
+  public XmlElementDescriptor getElementDescriptor(@NotNull XmlTag tag) {
+    PsiElement parent = tag.getParent();
+    final String namespace = tag.getNamespace();
+    while(parent instanceof XmlTag && !namespace.equals(((XmlTag)parent).getNamespace()))
+      parent = parent.getContext();
+    if (parent instanceof XmlTag) {
+      final XmlTag parentTag = (XmlTag)parent;
+      final XmlElementDescriptor parentDescriptor = parentTag.getDescriptor();
+
+      if(parentDescriptor != null){
+        XmlElementDescriptor elementDescriptorFromParent = parentDescriptor.getElementDescriptor(tag, parentTag);
+
+        if (elementDescriptorFromParent == null) {
+          elementDescriptorFromParent = getDescriptorFromParent(tag, elementDescriptorFromParent);
+        }
+        if (elementDescriptorFromParent instanceof AnyXmlElementDescriptor) {
+          final XmlElementDescriptor elementDescriptor = getElementDescriptor(tag.getLocalName(), namespace);
+          if (elementDescriptor != null) return elementDescriptor;
+        }
+        return elementDescriptorFromParent;
+      }
+      else{
+        return null;
+      }
+    }
+    else {
+      XmlElementDescriptor elementDescriptor = getElementDescriptor(tag.getLocalName(), tag.getNamespace());
+      
+      if (elementDescriptor == null) {
+        elementDescriptor = getDescriptorFromParent(tag, elementDescriptor);
+      }
+
+      return elementDescriptor;
+    }
+  }
+
+  @Nullable
+  private static XmlElementDescriptor getDescriptorFromParent(final XmlTag tag, XmlElementDescriptor elementDescriptor) {
+    final PsiElement parent = tag.getParent();
+    if (parent instanceof XmlTag) {
+      final XmlElementDescriptor descriptor = ((XmlTag)parent).getDescriptor();
+      if (descriptor != null) elementDescriptor = descriptor.getElementDescriptor(tag, (XmlTag)parent);
+    }
+    return elementDescriptor;
+  }
+
+  @NotNull
+  public XmlElementDescriptor[] getRootElementsDescriptors(@Nullable final XmlDocument doc) {
+    class CollectElementsProcessor implements PsiElementProcessor<XmlTag> {
+      final List<XmlElementDescriptor> result = new ArrayList<XmlElementDescriptor>();
+      
+      public boolean execute(@NotNull final XmlTag element) {
+        result.add(getElementDescriptor(element.getAttributeValue("name"),getDefaultNamespace()));
+        return true;
+      }
+    }
+    
+    CollectElementsProcessor processor = new CollectElementsProcessor() {
+      public boolean execute(@NotNull final XmlTag element) {
+        if (!XmlElementDescriptorImpl.isAbstractDeclaration(element)) return super.execute(element);
+        return true;
+      }
+    };
+    processTagsInNamespace(myTag, new String[] {ELEMENT_TAG_NAME}, processor);
+
+    return processor.result.toArray(new XmlElementDescriptor[processor.result.size()]);
+  }
+
+  public XmlAttributeDescriptor[] getRootAttributeDescriptors(final XmlTag context) {
+    class CollectAttributesProcessor implements PsiElementProcessor<XmlTag> {
+      final List<XmlAttributeDescriptor> result = new ArrayList<XmlAttributeDescriptor>();
+
+      public boolean execute(@NotNull final XmlTag element) {
+        result.add(createAttributeDescriptor(element));
+        return true;
+      }
+    }
+
+    CollectAttributesProcessor processor = new CollectAttributesProcessor();
+    processTagsInNamespace(myTag, new String[] {ATTRIBUTE_TAG_NAME}, processor);
+
+    return processor.result.toArray(new XmlAttributeDescriptor[processor.result.size()]);
+  }
+
+  public static boolean processTagsInNamespace(@NotNull final XmlTag rootTag, String[] tagNames, PsiElementProcessor<XmlTag> processor) {
+    return processTagsInNamespaceInner(rootTag, tagNames, processor, null);
+  }
+
+  private static boolean processTagsInNamespaceInner(@NotNull final XmlTag rootTag, final String[] tagNames,
+                                                     final PsiElementProcessor<XmlTag> processor, Set<XmlTag> visitedTags) {
+    if (visitedTags == null) visitedTags = new HashSet<XmlTag>(3);
+    else if (visitedTags.contains(rootTag)) return true;
+
+    visitedTags.add(rootTag);
+    XmlTag[] tags = rootTag.getSubTags();
+
+    NextTag:
+    for (XmlTag tag : tags) {
+      for(String tagName:tagNames) {
+        if (equalsToSchemaName(tag, tagName)) {
+          final String name = tag.getAttributeValue("name");
+
+          if (name != null) {
+            if (!processor.execute(tag)) {
+              return false;
+            }
+          }
+
+          continue NextTag;
+        }
+      }
+
+      if (equalsToSchemaName(tag, INCLUDE_TAG_NAME)) {
+        final String schemaLocation = tag.getAttributeValue("schemaLocation");
+
+        if (schemaLocation != null) {
+          final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation);
+
+          if (xmlFile != null) {
+            final XmlDocument includedDocument = xmlFile.getDocument();
+
+            if (includedDocument != null) {
+              if (!processTagsInNamespaceInner(includedDocument.getRootTag(), tagNames, processor, visitedTags)) return false;
+            }
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  protected static boolean equalsToSchemaName(XmlTag tag, @NonNls String schemaName) {
+    return schemaName.equals(tag.getLocalName()) && checkSchemaNamespace(tag);
+  }
+
+  private static @Nullable XmlTag findSpecialTag(@NonNls String name, @NonNls String specialName, XmlTag rootTag, XmlNSDescriptorImpl descriptor,
+                                       HashSet<XmlTag> visited) {
+    XmlNSDescriptorImpl nsDescriptor = getNSDescriptorToSearchIn(rootTag, name, descriptor);
+
+    if (nsDescriptor != descriptor) {
+      final XmlDocument document = nsDescriptor.getDescriptorFile() != null ? nsDescriptor.getDescriptorFile().getDocument():null;
+      if (document == null) return null;
+
+      return findSpecialTag(
+        XmlUtil.findLocalNameByQualifiedName(name),
+        specialName,
+        document.getRootTag(),
+        nsDescriptor,
+        visited
+      );
+    }
+
+    if (visited == null) visited = new HashSet<XmlTag>(1);
+    else if (visited.contains(rootTag)) return null;
+    visited.add(rootTag);
+
+    XmlTag[] tags = rootTag.getSubTags();
+
+    return findSpecialTagIn(tags, specialName, name, rootTag, descriptor, visited);
+  }
+
+  private static XmlTag findSpecialTagIn(final XmlTag[] tags,
+                                         final String specialName,
+                                         final String name,
+                                         final XmlTag rootTag,
+                                         final XmlNSDescriptorImpl descriptor, final HashSet<XmlTag> visited) {
+    for (XmlTag tag : tags) {
+      if (equalsToSchemaName(tag, specialName)) {
+        String attribute = tag.getAttributeValue("name");
+
+        if (name.equals(attribute)
+            || name.indexOf(":") >= 0 && name.substring(name.indexOf(":") + 1).equals(attribute)) {
+          return tag;
+        }
+      } else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
+                 ( equalsToSchemaName(tag, IMPORT_TAG_NAME) &&
+                   rootTag.getNamespaceByPrefix(
+                     XmlUtil.findPrefixByQualifiedName(name)
+                   ).equals(tag.getAttributeValue("namespace"))
+                 )
+         ) {
+        final String schemaLocation = tag.getAttributeValue("schemaLocation");
+
+        if (schemaLocation != null) {
+          final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation);
+
+          if (xmlFile != null) {
+            final XmlDocument document = xmlFile.getDocument();
+            if (document != null) {
+              final XmlTag rTag = findSpecialTag(name, specialName, document.getRootTag(), descriptor, visited);
+
+              if (rTag != null) return rTag;
+            }
+          }
+        }
+      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
+        XmlTag rTag = findSpecialTagIn(tag.getSubTags(), specialName, name, rootTag, descriptor, visited);
+        if (rTag != null) return rTag;
+
+        final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag);
+        if (nsDescriptor != null) {
+          final XmlTag redefinedRootTag = ((XmlDocument)nsDescriptor.getDeclaration()).getRootTag();
+
+          rTag = findSpecialTagIn(redefinedRootTag.getSubTags(), specialName, name, redefinedRootTag, nsDescriptor, visited);
+          if (rTag != null) return rTag;
+        }
+      }
+    }
+
+    return null;
+  }
+
+  @Nullable
+  public XmlTag findGroup(String name) {
+    return findSpecialTag(name,"group",myTag, this, null);
+  }
+
+  @Nullable
+  public XmlTag findAttributeGroup(String name) {
+    return findSpecialTag(name,"attributeGroup",myTag,this, null);
+  }
+
+  private Map<String,List<XmlTag>> mySubstitutions;
+
+  public XmlElementDescriptor[] getSubstitutes(String localName, String namespace) {
+    List<XmlElementDescriptor> result = new ArrayList<XmlElementDescriptor>();
+
+    initSubstitutes();
+
+    List<XmlTag> substitutions = mySubstitutions.get(localName);
+    if (substitutions==null) return XmlElementDescriptor.EMPTY_ARRAY;
+    for (XmlTag tag : substitutions) {
+      final String substAttr = tag.getAttributeValue("substitutionGroup");
+      if (substAttr != null && checkElementNameEquivalence(localName, namespace, substAttr, tag)) {
+        result.add(createElementDescriptor(tag));
+      }
+    }
+
+    return result.toArray(new XmlElementDescriptor[result.size()]);
+  }
+
+  private void initSubstitutes() {
+    if (mySubstitutions ==null) {
+      mySubstitutions = new HashMap<String, List<XmlTag>>();
+
+      XmlTag[] tags = myTag.getSubTags();
+
+      for (XmlTag tag : tags) {
+        if (equalsToSchemaName(tag, ELEMENT_TAG_NAME)) {
+          final String substAttr = tag.getAttributeValue("substitutionGroup");
+          if (substAttr != null) {
+            String substLocalName = XmlUtil.findLocalNameByQualifiedName(substAttr);
+            List<XmlTag> list = mySubstitutions.get(substLocalName);
+            if (list == null) {
+              list = new LinkedList<XmlTag>();
+              mySubstitutions.put(substLocalName, list);
+            }
+            list.add(tag);
+          }
+        }
+      }
+    }
+  }
+
+  public PsiElement getDeclaration(){
+    return myFile.getDocument();
+  }
+
+  public String getName(PsiElement context){
+    return getName();
+  }
+
+  public String getName(){
+    return "";
+  }
+
+  public void init(PsiElement element){
+    myFile = (XmlFile) element.getContainingFile();
+    
+    if (element instanceof XmlTag) {
+      myTag = (XmlTag)element;
+    } else {
+      final XmlDocument document = myFile.getDocument();
+
+      if (document != null) {
+        myTag = document.getRootTag();
+      }
+    }
+
+    if (myTag != null) {
+      myTargetNamespace = myTag.getAttributeValue("targetNamespace");
+    }
+
+    final THashSet<PsiFile> dependenciesSet = new THashSet<PsiFile>();
+    final Set<PsiFile> redefineProcessingSet = myRedefinedDescriptorsInProcessing.get();
+    if (redefineProcessingSet != null) {
+      dependenciesSet.addAll(redefineProcessingSet);
+    }
+    collectDependencies(myTag, myFile, dependenciesSet);
+    dependencies = ArrayUtil.toObjectArray(dependenciesSet);
+  }
+
+  public Object[] getDependences() {
+    if (dependencies == null) dependencies = new Object[] {myFile}; // init was not called
+    return dependencies;
+  }
+
+  static {
+    STD_TYPES.add("string");
+    STD_TYPES.add("normalizedString");
+    STD_TYPES.add("token");
+    STD_TYPES.add("byte");
+    STD_TYPES.add("unsignedByte");
+    STD_TYPES.add("base64Binary");
+    STD_TYPES.add("hexBinary");
+    STD_TYPES.add("integer");
+    STD_TYPES.add("positiveInteger");
+    STD_TYPES.add("negativeInteger");
+    STD_TYPES.add("nonNegativeInteger");
+    STD_TYPES.add("nonPositiveInteger");
+    STD_TYPES.add("int");
+    STD_TYPES.add("unsignedInt");
+    STD_TYPES.add("long");
+    STD_TYPES.add("unsignedLong");
+    STD_TYPES.add("short");
+    STD_TYPES.add("unsignedShort");
+    STD_TYPES.add("decimal");
+    STD_TYPES.add("float");
+    STD_TYPES.add("double");
+    STD_TYPES.add("boolean");
+    STD_TYPES.add("time");
+    STD_TYPES.add("dateTime");
+    STD_TYPES.add("duration");
+    STD_TYPES.add("date");
+    STD_TYPES.add("gMonth");
+    STD_TYPES.add("gYear");
+    STD_TYPES.add("gYearMonth");
+    STD_TYPES.add("gDay");
+    STD_TYPES.add("gMonthDay");
+    STD_TYPES.add("Name");
+    STD_TYPES.add("QName");
+    STD_TYPES.add("NCName");
+    STD_TYPES.add("anyURI");
+    STD_TYPES.add("language");
+    STD_TYPES.add("ID");
+    STD_TYPES.add("IDREF");
+    STD_TYPES.add("IDREFS");
+    STD_TYPES.add("ENTITY");
+    STD_TYPES.add("ENTITIES");
+    STD_TYPES.add("NOTATION");
+    STD_TYPES.add("NMTOKEN");
+    STD_TYPES.add("NMTOKENS");
+    STD_TYPES.add("anySimpleType");
+    
+    UNDECLARED_STD_TYPES.add("anySimpleType");
+  }
+
+  public void validate(@NotNull XmlDocument context, @NotNull Validator.ValidationHost host) {
+    ExternalDocumentValidator.doValidation(context,host);
+  }
+
+  public XmlTag getTag() {
+    return myTag;
+  }
+
+  public static XmlNSDescriptorImpl getRedefinedElementDescriptor(final XmlTag parentTag) {
+    XmlFile file = getRedefinedElementDescriptorFile(parentTag);
+    if (file != null) {
+      final XmlDocument document = file.getDocument();
+      final PsiMetaData metaData = document != null ? document.getMetaData():null;
+      if (metaData instanceof XmlNSDescriptorImpl) return (XmlNSDescriptorImpl)metaData;
+    }
+    return null;
+  }
+
+  public static XmlFile getRedefinedElementDescriptorFile(final XmlTag parentTag) {
+    final String schemaL = parentTag.getAttributeValue(XmlUtil.SCHEMA_LOCATION_ATT);
+
+    if (schemaL != null) {
+      final PsiReference[] references = parentTag.getAttribute(XmlUtil.SCHEMA_LOCATION_ATT, null).getValueElement().getReferences();
+
+      if (references.length > 0) {
+        final PsiElement psiElement = references[references.length - 1].resolve();
+
+        if (psiElement instanceof XmlFile) {
+          return ((XmlFile)psiElement);
+        }
+      }
+    }
+    return null;
+  }
+
+  public boolean hasSubstitutions() {
+    initSubstitutes();
+    return mySubstitutions != null && mySubstitutions.size() > 0;
+  }
+
+  public boolean isValid() {
+    return myFile != null && getDeclaration().isValid();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlNSTypeDescriptorProvider.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlNSTypeDescriptorProvider.java
new file mode 100644
index 0000000..1d82db0
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlNSTypeDescriptorProvider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public interface XmlNSTypeDescriptorProvider {
+  @Nullable
+  TypeDescriptor getTypeDescriptor(String name, XmlTag context);
+
+  @Nullable
+  TypeDescriptor getTypeDescriptor(XmlTag descriptorTag);
+}
diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java
new file mode 100644
index 0000000..3a703c1
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.impl.schema;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public abstract class XmlSchemaTagsProcessor {
+
+  private final Set<XmlTag> myVisited = new HashSet<XmlTag>();
+  protected final XmlNSDescriptorImpl myNsDescriptor;
+  private final String[] myTagsToIgnore;
+
+  public XmlSchemaTagsProcessor(XmlNSDescriptorImpl nsDescriptor, String... tagsToIgnore) {
+    myNsDescriptor = nsDescriptor;
+    myTagsToIgnore = ArrayUtil.append(tagsToIgnore, "annotation");
+  }
+
+  public final void startProcessing(XmlTag tag) {
+    processTag(tag, null);
+  }
+
+  public void processTag(XmlTag tag, @Nullable XmlTag context) {
+
+    if (myVisited.contains(tag)) return;
+    myVisited.add(tag);
+
+    if (!XmlNSDescriptorImpl.checkSchemaNamespace(tag)) {
+      processTagWithSubTags(tag, context, null);
+      return;
+    }
+
+    String tagName = tag.getLocalName();
+    if (checkTagName(tagName, "element", "attribute")) {
+      XmlAttribute ref = tag.getAttribute("ref");
+      if (ref != null) {
+        XmlTag resolved = resolveTagReference(ref);
+        if (resolved != null) {
+          tagStarted(resolved, resolved.getLocalName(), tag, tag);
+        }
+      }
+      else {
+        tagStarted(tag, tag.getLocalName(), context, null);
+      }
+    }
+    else if (checkTagName(tagName, "group")) {
+      String value = tag.getAttributeValue("ref");
+      if (value != null) {
+        XmlTag group = myNsDescriptor.findGroup(value);
+        if (group == null) group = resolveTagReference(tag.getAttribute("ref"));
+        processTagWithSubTags(group, tag, tag);
+      }
+    }
+    else if (checkTagName(tagName, "attributeGroup")) {
+      String ref = tag.getAttributeValue("ref");
+      if (ref == null) return;
+      XmlTag group;
+      XmlTag parentTag = tag.getParentTag();
+      if (XmlNSDescriptorImpl.equalsToSchemaName(parentTag, "attributeGroup") &&
+        ref.equals(parentTag.getAttributeValue("name"))) {
+        group = resolveTagReference(tag.getAttribute("ref"));
+        if (group == null) group = myNsDescriptor.findAttributeGroup(ref);
+      }
+      else {
+        group =  myNsDescriptor.findAttributeGroup(ref);
+        if (group == null) group = resolveTagReference(tag.getAttribute("ref"));
+      }
+      processTagWithSubTags(group, tag, null);
+    }
+    else if (checkTagName(tagName, "restriction", "extension")) {
+      processTagWithSubTags(resolveTagReference(tag.getAttribute("base")), tag, null);
+      processTagWithSubTags(tag, context, null);
+    }
+    else if (!checkTagName(tagName, myTagsToIgnore)) {
+      processTagWithSubTags(tag, context, null);
+    }
+  }
+
+  private void processTagWithSubTags(@Nullable XmlTag tag, XmlTag ctx, @Nullable XmlTag ref) {
+    if (tag == null) return;
+    tagStarted(tag, tag.getLocalName(), ctx, ref);
+    XmlTag[] subTags = tag.getSubTags();
+    for (XmlTag subTag : subTags) {
+      processTag(subTag, tag);
+    }
+    tagFinished(tag);
+  }
+
+  protected abstract void tagStarted(XmlTag tag, String tagName, XmlTag context, @Nullable XmlTag ref);
+
+  protected void tagFinished(XmlTag tag) {}
+
+  @Nullable
+  private static XmlTag resolveTagReference(XmlAttribute ref) {
+    PsiElement element = resolveReference(ref);
+    return element instanceof XmlTag ? (XmlTag)element : null;
+  }
+
+  @Nullable
+  static PsiElement resolveReference(XmlAttribute ref) {
+    if (ref != null) {
+      XmlAttributeValue value = ref.getValueElement();
+      if (value != null) {
+        return value.getReferences()[0].resolve();
+      }
+    }
+    return null;
+  }
+
+  protected static boolean checkTagName(String tagName, String... names) {
+    return ArrayUtil.contains(tagName, names);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/index/IndexedRelevantResource.java b/xml/impl/src/com/intellij/xml/index/IndexedRelevantResource.java
new file mode 100644
index 0000000..5b62a6a
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/index/IndexedRelevantResource.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.index;
+
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.NullableFunction;
+import com.intellij.util.indexing.AdditionalIndexedRootsScope;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.ID;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class IndexedRelevantResource<K, V extends Comparable> implements Comparable<IndexedRelevantResource<K, V>> {
+
+  public static <K, V extends Comparable> List<IndexedRelevantResource<K, V>> getResources(ID<K, V> indexId,
+                                                                                           final K key,
+                                                                                           @Nullable final Module module,
+                                                                                           @NotNull Project project,
+                                                                                           @Nullable final GlobalSearchScope additionalScope) {
+
+    if (project.isDefault()) return Collections.emptyList();
+    final ArrayList<IndexedRelevantResource<K, V>> resources = new ArrayList<IndexedRelevantResource<K, V>>();
+    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
+    FileBasedIndex.getInstance().processValues(indexId, key, null, new FileBasedIndex.ValueProcessor<V>() {
+      public boolean process(VirtualFile file, V value) {
+        ResourceRelevance relevance = ResourceRelevance.getRelevance(file, module, fileIndex, additionalScope);
+        if (relevance != ResourceRelevance.NONE) {
+          resources.add(new IndexedRelevantResource<K, V>(file, key, value, relevance));
+        }
+        return true;
+      }
+    }, new AdditionalIndexedRootsScope(GlobalSearchScope.allScope(project)));
+    return resources;
+  }
+
+  public static <K, V extends Comparable> List<IndexedRelevantResource<K, V>> getAllResources(ID<K, V> indexId,
+                                                                                              @Nullable final Module module,
+                                                                                              @NotNull Project project,
+                                                                                              @Nullable NullableFunction<List<IndexedRelevantResource<K, V>>, IndexedRelevantResource<K, V>> chooser) {
+    ArrayList<IndexedRelevantResource<K, V>> all = new ArrayList<IndexedRelevantResource<K, V>>();
+    Collection<K> allKeys = FileBasedIndex.getInstance().getAllKeys(indexId, project);
+    for (K key : allKeys) {
+      List<IndexedRelevantResource<K, V>> resources = getResources(indexId, key, module, project, null);
+      if (!resources.isEmpty()) {
+        if (chooser == null) {
+          all.add(resources.get(0));
+        }
+        else {
+          IndexedRelevantResource<K, V> resource = chooser.fun(resources);
+          if (resource != null) {
+            all.add(resource);
+          }
+        }
+      }
+    }
+    return all;
+  }
+
+  private final VirtualFile myFile;
+  private final K myKey;
+  private final V myValue;
+  private final ResourceRelevance myRelevance;
+
+  public IndexedRelevantResource(VirtualFile file, K key, V value, ResourceRelevance relevance) {
+    myFile = file;
+    myKey = key;
+    myValue = value;
+    myRelevance = relevance;
+  }
+
+  public VirtualFile getFile() {
+    return myFile;
+  }
+
+  public V getValue() {
+    return myValue;
+  }
+
+  public ResourceRelevance getRelevance() {
+    return myRelevance;
+  }
+
+  public int compareTo(IndexedRelevantResource<K, V> o) {
+    int i = myRelevance.compareTo(o.getRelevance());
+    return i == 0 ? myValue.compareTo(o.getValue()) : i;
+  }
+
+  public K getKey() {
+    return myKey;
+  }
+
+  @Override
+  public String toString() {
+    return "IndexedRelevantResource{" +
+           "myRelevance=" +
+           myRelevance +
+           ", myKey=" +
+           myKey +
+           ", myValue=" +
+           myValue +
+           ", myFile=" +
+           myFile +
+           '}';
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/index/ResourceRelevance.java b/xml/impl/src/com/intellij/xml/index/ResourceRelevance.java
new file mode 100644
index 0000000..834478d
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/index/ResourceRelevance.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.index;
+
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.javaee.ExternalResourceManagerImpl;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public enum ResourceRelevance {
+
+  NONE,
+  STANDARD,
+  LIBRARY,
+  SOURCE,
+  MAPPED;
+
+  public static ResourceRelevance getRelevance(VirtualFile resource,
+                                               @Nullable Module module,
+                                               ProjectFileIndex fileIndex,
+                                               @Nullable GlobalSearchScope additionalScope) {
+    boolean inTest = fileIndex.isInTestSourceContent(resource);
+    if (module != null) {
+      GlobalSearchScope scope = module.getModuleRuntimeScope(inTest);
+      Module resourceModule = fileIndex.getModuleForFile(resource);
+      if (resourceModule != null &&
+          (resourceModule == module || scope.isSearchInModuleContent(resourceModule)) ||
+        scope.contains(resource) || (additionalScope != null && additionalScope.contains(resource))) {
+        return inTest || fileIndex.isInSource(resource) ? SOURCE : LIBRARY;
+      }
+    }
+    else if (inTest ||  fileIndex.isInSource(resource)) {
+      return SOURCE;
+    }
+    else if (fileIndex.isInLibraryClasses(resource)) {
+      return LIBRARY;
+    }
+    ExternalResourceManagerImpl resourceManager = (ExternalResourceManagerImpl)ExternalResourceManager.getInstance();
+    if (resourceManager.isUserResource(resource)) {
+      return MAPPED;
+    }
+    if (ExternalResourceManagerImpl.isStandardResource(resource)) {
+      return STANDARD;
+    }
+    return NONE;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/index/SchemaTypeInfo.java b/xml/impl/src/com/intellij/xml/index/SchemaTypeInfo.java
new file mode 100644
index 0000000..9d857a0
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/index/SchemaTypeInfo.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.index;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 7/4/12
+ * Time: 7:14 PM
+ */
+public class SchemaTypeInfo implements Comparable<SchemaTypeInfo> {
+  private final String myTagName;
+  private final String myNamespaceUri;
+//  private final String myFileUrl;
+  private final boolean myIsTypeName; // false -> enclosing element name
+
+  public SchemaTypeInfo(String tagName, final boolean isTypeName, String namespace) {
+    myNamespaceUri = namespace;
+    myTagName = tagName;
+    myIsTypeName = isTypeName;
+  }
+
+  public String getTagName() {
+    return myTagName;
+  }
+
+  public String getNamespaceUri() {
+    return myNamespaceUri;
+  }
+
+  public boolean isIsTypeName() {
+    return myIsTypeName;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    SchemaTypeInfo info = (SchemaTypeInfo)o;
+
+    if (myIsTypeName != info.myIsTypeName) return false;
+    if (myNamespaceUri != null ? !myNamespaceUri.equals(info.myNamespaceUri) : info.myNamespaceUri != null) return false;
+    if (!myTagName.equals(info.myTagName)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myTagName.hashCode();
+    result = 31 * result + (myNamespaceUri != null ? myNamespaceUri.hashCode() : 0);
+    result = 31 * result + (myIsTypeName ? 1 : 0);
+    return result;
+  }
+
+  @Override
+  public int compareTo(SchemaTypeInfo o) {
+    return myTagName.compareTo(o.getTagName());
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/index/SchemaTypeInheritanceIndex.java b/xml/impl/src/com/intellij/xml/index/SchemaTypeInheritanceIndex.java
new file mode 100644
index 0000000..5155221
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/index/SchemaTypeInheritanceIndex.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.index;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.PairConvertor;
+import com.intellij.util.containers.EncoderDecoder;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.containers.hash.HashMap;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.FileContent;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.text.CharArrayUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 7/4/12
+ * Time: 6:29 PM
+ *
+ * map: tag name->file url
+ */
+public class SchemaTypeInheritanceIndex extends XmlIndex<Set<SchemaTypeInfo>> {
+  private static final ID<String, Set<SchemaTypeInfo>> NAME = ID.create("SchemaTypeInheritance");
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.index.SchemaTypeInheritanceIndex");
+
+  private static List<Set<SchemaTypeInfo>> getDirectChildrenOfType(final Project project,
+                                                                  final String ns,
+                                                                  final String name) {
+    GlobalSearchScope filter = createFilter(project);
+    final List<Set<SchemaTypeInfo>>
+      list = FileBasedIndex.getInstance().getValues(NAME, NsPlusTag.INSTANCE.encode(Pair.create(ns, name)), filter);
+    return list;
+  }
+
+  public static PairConvertor<String, String, List<Set<SchemaTypeInfo>>> getWorker(final Project project, final VirtualFile currentFile) {
+    return new MyWorker(currentFile, project);
+  }
+
+  private static class MyWorker implements PairConvertor<String, String, List<Set<SchemaTypeInfo>>> {
+    private final Project myProject;
+    private final VirtualFile myCurrentFile;
+    private final GlobalSearchScope myFilter;
+    private final boolean myShouldParseCurrent;
+    private MultiMap<SchemaTypeInfo,SchemaTypeInfo> myMap;
+
+    private MyWorker(VirtualFile currentFile, Project project) {
+      myCurrentFile = currentFile;
+      myProject = project;
+
+      myFilter = createFilter(project);
+      myShouldParseCurrent = (myCurrentFile != null && ! myFilter.contains(myCurrentFile));
+    }
+
+    @Override
+    public List<Set<SchemaTypeInfo>> convert(String ns, String name) {
+      List<Set<SchemaTypeInfo>> type = getDirectChildrenOfType(myProject, ns, name);
+      if (myShouldParseCurrent) {
+        if (myMap == null) {
+          try {
+            myMap = XsdComplexTypeInfoBuilder.parse(CharArrayUtil.readerFromCharSequence(VfsUtil.loadText(myCurrentFile)));
+            type.add(new HashSet<SchemaTypeInfo>(myMap.get(new SchemaTypeInfo(name, true, ns))));
+          }
+          catch (IOException e) {
+            LOG.info(e);
+          }
+        }
+      }
+      return type;
+    }
+  }
+
+  @Override
+  public boolean dependsOnFileContent() {
+    return true;
+  }
+
+  @Override
+  public int getVersion() {
+    return 0;
+  }
+
+  @NotNull
+  @Override
+  public ID<String, Set<SchemaTypeInfo>> getName() {
+    return NAME;
+  }
+
+  @NotNull
+  @Override
+  public DataIndexer<String, Set<SchemaTypeInfo>, FileContent> getIndexer() {
+    return new DataIndexer<String, Set<SchemaTypeInfo>, FileContent>() {
+      @NotNull
+      @Override
+      public Map<String, Set<SchemaTypeInfo>> map(FileContent inputData) {
+        final Map<String, Set<SchemaTypeInfo>> map = new HashMap<String, Set<SchemaTypeInfo>>();
+        final MultiMap<SchemaTypeInfo,SchemaTypeInfo> multiMap =
+          XsdComplexTypeInfoBuilder.parse(CharArrayUtil.readerFromCharSequence(inputData.getContentAsText()));
+        for (SchemaTypeInfo key : multiMap.keySet()) {
+          map.put(NsPlusTag.INSTANCE.encode(Pair.create(key.getNamespaceUri(), key.getTagName())), new HashSet<SchemaTypeInfo>(multiMap.get(key)));
+        }
+        return map;
+      }
+    };
+  }
+
+  @Override
+  public DataExternalizer<Set<SchemaTypeInfo>> getValueExternalizer() {
+    return new DataExternalizer<Set<SchemaTypeInfo>>() {
+      @Override
+      public void save(DataOutput out, Set<SchemaTypeInfo> value) throws IOException {
+        out.writeInt(value.size());
+        for (SchemaTypeInfo key : value) {
+          out.writeUTF(key.getNamespaceUri());
+          out.writeUTF(key.getTagName());
+          out.writeBoolean(key.isIsTypeName());
+        }
+      }
+
+      @Override
+      public Set<SchemaTypeInfo> read(DataInput in) throws IOException {
+        final Set<SchemaTypeInfo> set = new HashSet<SchemaTypeInfo>();
+        final int size = in.readInt();
+        for (int i = 0; i < size; i++) {
+          final String nsUri = in.readUTF();
+          final String tagName = in.readUTF();
+          final boolean isType = in.readBoolean();
+          set.add(new SchemaTypeInfo(tagName, isType, nsUri));
+        }
+        return set;
+      }
+    };
+  }
+
+  private static class NsPlusTag implements EncoderDecoder<Pair<String, String>, String> {
+    private final static NsPlusTag INSTANCE = new NsPlusTag();
+    private final static char ourSeparator = ':';
+
+    @Override
+    public String encode(Pair<String, String> pair) {
+      return pair.getFirst() + ourSeparator + pair.getSecond();
+    }
+
+    @Override
+    public Pair<String, String> decode(String s) {
+      final int i = s.indexOf(ourSeparator);
+      return i <= 0 ? Pair.create("", s) : Pair.create(s.substring(0, i), s.substring(i + 1));
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/index/XmlIndex.java b/xml/impl/src/com/intellij/xml/index/XmlIndex.java
new file mode 100644
index 0000000..dcfbb77
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/index/XmlIndex.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.index;
+
+import com.intellij.ide.highlighter.DTDFileType;
+import com.intellij.ide.highlighter.XmlFileType;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.OrderEntry;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileFilter;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.FileBasedIndexExtension;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public abstract class XmlIndex<V> extends FileBasedIndexExtension<String, V> {
+
+  protected static final EnumeratorStringDescriptor KEY_DESCRIPTOR = new EnumeratorStringDescriptor();
+
+  private static final FileBasedIndex.InputFilter INPUT_FILTER = new FileBasedIndex.InputFilter() {
+    public boolean acceptInput(final VirtualFile file) {
+      FileType fileType = file.getFileType();
+      final String extension = file.getExtension();
+      return XmlFileType.INSTANCE.equals(fileType) && "xsd".equals(extension) ||
+             DTDFileType.INSTANCE.equals(fileType) && "dtd".equals(extension);
+    }
+  };
+
+  protected static GlobalSearchScope createFilter(final Project project) {
+    final GlobalSearchScope projectScope = GlobalSearchScope.allScope(project);
+    return new GlobalSearchScope(project) {
+      public int compare(VirtualFile file1, VirtualFile file2) {
+        return projectScope.compare(file1, file2);
+      }
+
+      public boolean isSearchInModuleContent(@NotNull Module aModule) {
+        return true;
+      }
+
+      @Override
+      public boolean contains(VirtualFile file) {
+        final VirtualFile parent = file.getParent();
+        return parent != null && (parent.getName().equals("standardSchemas") || projectScope.contains(file));
+      }
+
+      @Override
+      public boolean isSearchInLibraries() {
+        return true;
+      }
+    };
+  }
+
+
+  protected static VirtualFileFilter createFilter(@NotNull final Module module) {
+
+    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(module.getProject()).getFileIndex();
+    return new VirtualFileFilter() {
+      public boolean accept(final VirtualFile file) {
+        Module moduleForFile = fileIndex.getModuleForFile(file);
+        if (moduleForFile != null) { // in module content
+          return module.equals(moduleForFile);
+        }
+        if (fileIndex.isInLibraryClasses(file)) {
+          List<OrderEntry> orderEntries = fileIndex.getOrderEntriesForFile(file);
+          if (orderEntries.isEmpty()) {
+            return false;
+          }
+          for (OrderEntry orderEntry : orderEntries) {
+            Module ownerModule = orderEntry.getOwnerModule();
+            if (ownerModule.equals(module)) {
+              return true;
+            }
+          }
+        }
+        final VirtualFile parent = file.getParent();
+        assert parent != null;
+        return parent.getName().equals("standardSchemas");
+      }
+    };
+  }
+
+  public KeyDescriptor<String> getKeyDescriptor() {
+    return KEY_DESCRIPTOR;
+  }
+
+  public FileBasedIndex.InputFilter getInputFilter() {
+    return INPUT_FILTER;
+  }
+
+  public boolean dependsOnFileContent() {
+    return true;
+  }
+
+  public int getVersion() {
+    return 0;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java b/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java
new file mode 100644
index 0000000..6e07c94
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.index;
+
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.util.NullableFunction;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.FileContent;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.text.CharArrayUtil;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlNamespaceIndex extends XmlIndex<XsdNamespaceBuilder> {
+
+  @Nullable
+  public static String getNamespace(@NotNull VirtualFile file, final Project project, PsiFile context) {
+    if (DumbService.isDumb(project) || (context != null && XmlUtil.isStubBuilding(context))) {
+      try {
+        return XsdNamespaceBuilder.computeNamespace(file.getInputStream());
+      }
+      catch (IOException e) {
+        return null;
+      }
+    }
+    final List<XsdNamespaceBuilder> list = FileBasedIndex.getInstance().getValues(NAME, file.getUrl(), createFilter(project));
+    return list.size() == 0 ? null : list.get(0).getNamespace();
+  }
+
+  public static List<IndexedRelevantResource<String, XsdNamespaceBuilder>> getResourcesByNamespace(String namespace,
+                                                                                                   @NotNull Project project,
+                                                                                                   @Nullable Module module) {
+    List<IndexedRelevantResource<String, XsdNamespaceBuilder>> resources =
+      IndexedRelevantResource.getResources(NAME, namespace, module, project, null);
+    Collections.sort(resources);
+    return resources;
+  }
+
+  public static List<IndexedRelevantResource<String, XsdNamespaceBuilder>> getAllResources(@Nullable final Module module,
+                                                                                           @NotNull Project project,
+                                                                                           @Nullable NullableFunction<List<IndexedRelevantResource<String, XsdNamespaceBuilder>>, IndexedRelevantResource<String, XsdNamespaceBuilder>> chooser) {
+    return IndexedRelevantResource.getAllResources(NAME, module, project, chooser);
+  }
+  
+  private static final ID<String,XsdNamespaceBuilder> NAME = ID.create("XmlNamespaces");
+
+  @Override
+  @NotNull
+  public ID<String, XsdNamespaceBuilder> getName() {
+    return NAME;
+  }
+
+  @Override
+  @NotNull
+  public DataIndexer<String, XsdNamespaceBuilder, FileContent> getIndexer() {
+    return new DataIndexer<String, XsdNamespaceBuilder, FileContent>() {
+      @Override
+      @NotNull
+      public Map<String, XsdNamespaceBuilder> map(final FileContent inputData) {
+        final XsdNamespaceBuilder builder;
+        if ("dtd".equals(inputData.getFile().getExtension())) {
+          builder = new XsdNamespaceBuilder(inputData.getFileName(), "", Collections.<String>emptyList());
+        }
+        else {
+          builder = XsdNamespaceBuilder.computeNamespace(CharArrayUtil.readerFromCharSequence(inputData.getContentAsText()));
+        }
+        final HashMap<String, XsdNamespaceBuilder> map = new HashMap<String, XsdNamespaceBuilder>(2);
+        String namespace = builder.getNamespace();
+        if (namespace != null) {
+          map.put(namespace, builder);
+        }
+        // so that we could get ns by file url (see getNamespace method above)
+        map.put(inputData.getFile().getUrl(), builder);
+        return map;
+      }
+    };
+  }
+
+  @Override
+  public DataExternalizer<XsdNamespaceBuilder> getValueExternalizer() {
+    return new DataExternalizer<XsdNamespaceBuilder>() {
+      @Override
+      public void save(DataOutput out, XsdNamespaceBuilder value) throws IOException {
+        out.writeUTF(value.getNamespace() == null ? "" : value.getNamespace());
+        out.writeUTF(value.getVersion() == null ? "" : value.getVersion());
+        out.writeInt(value.getTags().size());
+        for (String s : value.getTags()) {
+          out.writeUTF(s);
+        }
+      }
+
+      @Override
+      public XsdNamespaceBuilder read(DataInput in) throws IOException {
+
+        int count;
+        XsdNamespaceBuilder builder = new XsdNamespaceBuilder(in.readUTF(), in.readUTF(), new ArrayList<String>(count = in.readInt()));
+        for (int i = 0; i < count; i++) {
+          builder.getTags().add(in.readUTF());
+        }
+        return builder;
+      }
+    };
+  }
+
+  @Override
+  public int getVersion() {
+    return 2;
+  }
+
+  @Nullable
+  public static IndexedRelevantResource<String, XsdNamespaceBuilder> guessSchema(String namespace,
+                                                                                 @Nullable final String tagName,
+                                                                                 @Nullable final String version,
+                                                                                 @Nullable Module module) {
+
+    if (module == null) return null;
+
+    Project project = module.getProject();
+    final List<IndexedRelevantResource<String, XsdNamespaceBuilder>>
+      resources = getResourcesByNamespace(namespace, project, module);
+
+    if (resources.isEmpty()) return null;
+
+    return Collections
+      .max(resources, new Comparator<IndexedRelevantResource<String, XsdNamespaceBuilder>>() {
+        @Override
+        public int compare(IndexedRelevantResource<String, XsdNamespaceBuilder> o1,
+                           IndexedRelevantResource<String, XsdNamespaceBuilder> o2) {
+
+          int i = o1.getValue().getRating(tagName, version) - o2.getValue().getRating(tagName, version);
+          return i == 0 ? o1.compareTo(o2) : i;
+        }
+      });
+  }
+
+  @Nullable
+  public static XmlFile guessSchema(String namespace,
+                                    @Nullable final String tagName,
+                                    @Nullable final String version,
+                                    @NotNull PsiFile file) {
+
+    if (DumbService.isDumb(file.getProject()) || XmlUtil.isStubBuilding(file)) return null;
+
+    IndexedRelevantResource<String,XsdNamespaceBuilder> resource =
+      guessSchema(namespace, tagName, version, ModuleUtilCore.findModuleForPsiElement(file));
+    if (resource == null) return null;
+    return findSchemaFile(resource.getFile(), file);
+  }
+
+  @Nullable
+  private static XmlFile findSchemaFile(VirtualFile resourceFile, PsiFile baseFile) {
+    PsiFile psiFile = baseFile.getManager().findFile(resourceFile);
+    return psiFile instanceof XmlFile ? (XmlFile)psiFile : null;
+  }
+
+  @Nullable
+  public static XmlFile guessDtd(String dtdUri, @NotNull PsiFile baseFile) {
+
+    if (!dtdUri.endsWith(".dtd") ||
+        DumbService.isDumb(baseFile.getProject()) ||
+        XmlUtil.isStubBuilding(baseFile)) return null;
+
+    String dtdFileName = new File(dtdUri).getName();
+    List<IndexedRelevantResource<String, XsdNamespaceBuilder>>
+      list = getResourcesByNamespace(dtdFileName, baseFile.getProject(), ModuleUtilCore.findModuleForPsiElement(baseFile));
+    return list.isEmpty() ? null : findSchemaFile(list.get(0).getFile(), baseFile);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java b/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java
new file mode 100644
index 0000000..97fb7c0
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.indexing.*;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.text.CharArrayUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlTagNamesIndex extends XmlIndex<Void> {
+
+  public static Collection<VirtualFile> getFilesByTagName(String tagName, final Project project) {
+    return FileBasedIndex.getInstance().getContainingFiles(NAME, tagName, createFilter(project));
+  }
+
+  public static Collection<String> getAllTagNames(Project project) {
+    return FileBasedIndex.getInstance().getAllKeys(NAME, project);
+  }
+
+  static final ID<String,Void> NAME = ID.create("XmlTagNames");
+
+  @Override
+  @NotNull
+  public ID<String, Void> getName() {
+    return NAME;
+  }
+
+  @Override
+  @NotNull
+  public DataIndexer<String, Void, FileContent> getIndexer() {
+    return new DataIndexer<String, Void, FileContent>() {
+      @Override
+      @NotNull
+      public Map<String, Void> map(final FileContent inputData) {
+        final Collection<String> tags = XsdTagNameBuilder.computeTagNames(CharArrayUtil.readerFromCharSequence(inputData.getContentAsText()));
+        if (tags != null && !tags.isEmpty()) {
+          final HashMap<String, Void> map = new HashMap<String, Void>(tags.size());
+          for (String tag : tags) {
+            map.put(tag, null);
+          }
+          return map;
+        }
+        else {
+          return Collections.emptyMap();
+        }
+      }
+    };
+  }
+
+  @Override
+  public DataExternalizer<Void> getValueExternalizer() {
+    return ScalarIndexExtension.VOID_DATA_EXTERNALIZER;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/index/XsdComplexTypeInfoBuilder.java b/xml/impl/src/com/intellij/xml/index/XsdComplexTypeInfoBuilder.java
new file mode 100644
index 0000000..75b8dd3
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/index/XsdComplexTypeInfoBuilder.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.index;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.containers.hash.HashMap;
+import com.intellij.util.xml.NanoXmlUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Map;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 7/4/12
+ * Time: 6:37 PM
+ */
+public class XsdComplexTypeInfoBuilder extends NanoXmlUtil.IXMLBuilderAdapter {
+  private final static String SIGN = "";
+  public static final String HTTP_WWW_W3_ORG_2001_XMLSCHEMA = "http://www.w3.org/2001/XMLSchema";
+  // base type -> inherited types
+  private final MultiMap<SchemaTypeInfo, SchemaTypeInfo> myMap;
+  private NameSpaceHelper myNameSpaceHelper;
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.index.XsdComplexTypeInfoBuilder");
+
+  public void setNameSpaceHelper(NameSpaceHelper nameSpaceHelper) {
+    myNameSpaceHelper = nameSpaceHelper;
+  }
+
+  public static MultiMap<SchemaTypeInfo, SchemaTypeInfo> parse(final InputStream is) {
+    return parse(new InputStreamReader(is));
+  }
+
+  public static MultiMap<SchemaTypeInfo, SchemaTypeInfo> parse(final Reader reader) {
+    try {
+      final XsdComplexTypeInfoBuilder builder = new XsdComplexTypeInfoBuilder();
+      final NameSpaceHelper helper = new NameSpaceHelper();
+      builder.setNameSpaceHelper(helper);
+      NanoXmlUtil.parse(reader, builder, helper);
+      final MultiMap<SchemaTypeInfo,SchemaTypeInfo> map = builder.getMap();
+      return map;
+    } finally {
+      try {
+        if (reader != null) {
+          reader.close();
+        }
+      }
+      catch (IOException e) {
+        // can never happen
+      }
+    }
+  }
+
+  private XsdComplexTypeInfoBuilder() {
+    myMap = new MultiMap<SchemaTypeInfo, SchemaTypeInfo>();
+  }
+
+  public MultiMap<SchemaTypeInfo, SchemaTypeInfo> getMap() {
+    return myMap;
+  }
+
+  // todo work with substitution groups also!
+
+  private String myCurrentElementName;
+  private String myCurrentElementNsName;
+  private String myCurrentComplexTypeName;
+  private String myCurrentComplexTypeNsName;
+  private String myCurrentSimpleTypeName;
+  private String myCurrentSimpleTypeNsName;
+
+  private boolean myInsideSchema;
+  private boolean myInsideRestriction;
+  private boolean myInsideExtension;
+  private boolean myInsideContent;
+
+  @Override
+  public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr) throws Exception {
+    if (! HTTP_WWW_W3_ORG_2001_XMLSCHEMA.equals(nsURI)) return;
+    myInsideSchema = false;
+    if ("schema".equals(name)) {
+      myInsideSchema = true;
+    } else if ("complexType".equals(name)) {
+      myCurrentComplexTypeName = SIGN;
+      myCurrentComplexTypeNsName = nsURI;
+    } else if ("simpleType".equals(name)) {
+      myCurrentSimpleTypeName = SIGN;
+      myCurrentSimpleTypeNsName = nsURI;
+    } else if ("element".equals(name)) {
+      myCurrentElementNsName = nsURI;
+      myCurrentElementName = SIGN;
+    } else if ("restriction".equals(name)) {
+      myInsideRestriction = true;
+    } else if ("extension".equals(name)) {
+      myInsideExtension = true;
+    } else if ("simpleContent".equals(name) || "complexContent".equals(name)) {
+      myInsideContent = true;
+    }
+  }
+
+  @Override
+  public void endElement(String name, String nsPrefix, String nsURI) throws Exception {
+    if (! HTTP_WWW_W3_ORG_2001_XMLSCHEMA.equals(nsURI)) return;
+    if ("schema".equals(name)) {
+      myInsideSchema = false;
+    } else if ("complexType".equals(name)) {
+      myCurrentComplexTypeName = null;
+      myCurrentComplexTypeNsName = null;
+    } else if ("simpleType".equals(name)) {
+      myCurrentSimpleTypeName = null;
+      myCurrentSimpleTypeNsName = null;
+    } else if ("element".equals(name)) {
+      myCurrentElementNsName = null;
+      myCurrentElementName = null;
+    } else if ("restriction".equals(name)) {
+      myInsideRestriction = false;
+    } else if ("extension".equals(name)) {
+      myInsideExtension = false;
+    } else if ("simpleContent".equals(name) || "complexContent".equals(name)) {
+      myInsideContent = false;
+    }
+  }
+
+  @Override
+  public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type) throws Exception {
+    if (! StringUtil.isEmptyOrSpaces(nsURI) && ! HTTP_WWW_W3_ORG_2001_XMLSCHEMA.equals(nsURI)) return;
+    if ("base".equals(key)) {
+      if (myCurrentComplexTypeName != null && myInsideContent && (myInsideExtension || myInsideRestriction)) {
+        putTypeDataToMap(nsURI, value, myCurrentComplexTypeName, myCurrentComplexTypeNsName);
+      } else if (myCurrentSimpleTypeName != null && myInsideRestriction) {
+        putTypeDataToMap(nsURI, value, myCurrentSimpleTypeName, myCurrentSimpleTypeNsName);
+      }
+    } else if (myInsideSchema) {
+    } else if ("name".equals(key) || "ref".equals(key)) {
+      if (SIGN.equals(myCurrentElementName) && ! myInsideContent && ! myInsideExtension && ! myInsideRestriction && ! myInsideSchema &&
+        myCurrentComplexTypeName == null && myCurrentSimpleTypeName == null) {
+        myCurrentElementName = value;
+      } else if (SIGN.equals(myCurrentComplexTypeName) && ! myInsideContent && ! myInsideExtension && ! myInsideRestriction && ! myInsideSchema &&
+              myCurrentSimpleTypeName == null) {
+        myCurrentComplexTypeName = value;
+      } else if (SIGN.equals(myCurrentSimpleTypeName) && ! myInsideContent && ! myInsideExtension && ! myInsideRestriction && ! myInsideSchema &&
+                 myCurrentComplexTypeName == null) {
+        myCurrentSimpleTypeName = value;
+      }
+    }
+  }
+
+  private void putTypeDataToMap(String nsURI, String value, final String typeName, final String typeNamespace) {
+    /*final int separatorIdx = value.indexOf(':');
+    final String ns = separatorIdx <= 0 ? "" : new String(value.substring(0, separatorIdx));
+    final String element = separatorIdx <= 0 ? value : new String(value.substring(separatorIdx + 1));
+    String nsUri = myNameSpaceHelper.getNamespaces().get(ns);
+    nsUri = (nsUri == null ? ns : nsURI);*/
+
+    final boolean isAnonymous = SIGN.equals(typeName);
+    if (isAnonymous && myCurrentElementName != null) {
+      myMap.putValue(createSchemaTypeInfo(value, true), createSchemaTypeInfo(myCurrentElementName, false));
+    } else {
+      myMap.putValue(createSchemaTypeInfo(value, true), createSchemaTypeInfo(typeName, true));
+      //myMap.putValue(new SchemaTypeInfo(element, true, nsURI), new SchemaTypeInfo(typeName, true, typeNamespace));
+    }
+  }
+
+  private SchemaTypeInfo createSchemaTypeInfo(final String value, final boolean isType) {
+    final int separatorIdx = value.indexOf(':');
+    final String ns = separatorIdx <= 0 ? "" : new String(value.substring(0, separatorIdx));
+    final String element = separatorIdx <= 0 ? value : new String(value.substring(separatorIdx + 1));
+    String nsUri = myNameSpaceHelper.getNamespaces().get(ns);
+    nsUri = nsUri == null ? ns : nsUri;
+    return new SchemaTypeInfo(element, isType, nsUri);
+  }
+
+  private static class NameSpaceHelper extends NanoXmlUtil.EmptyValidator {
+    public static final String XMLNS = "xmlns";
+    public static final String XMLNS_ = "xmlns:";
+    private boolean myInSchema;
+    private final Map<String, String> myNamespaces;
+
+    private NameSpaceHelper() {
+      myNamespaces = new HashMap<String, String>();
+    }
+
+    @Override
+    public void attributeAdded(String key, String value, String systemId, int lineNr) {
+      super.attributeAdded(key, value, systemId, lineNr);
+      if (myInSchema) {
+        if (key.startsWith(XMLNS)) {
+          if (key.length() == XMLNS.length()) {
+            myNamespaces.put("", value);
+          } else if (key.startsWith(XMLNS_)) {
+            final String prefix = new String(key.substring(XMLNS_.length()));
+            myNamespaces.put(prefix, value);
+          }
+        }
+      }
+    }
+
+    @Override
+    public void elementStarted(String name, String systemId, int lineNr) {
+      super.elementStarted(name, systemId, lineNr);
+      myInSchema = "schema".equals(name) || name.endsWith(":schema");
+    }
+
+    public Map<String, String> getNamespaces() {
+      return myNamespaces;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/index/XsdTagNameBuilder.java b/xml/impl/src/com/intellij/xml/index/XsdTagNameBuilder.java
new file mode 100644
index 0000000..1754fbd
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/index/XsdTagNameBuilder.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.index;
+
+import com.intellij.util.xml.NanoXmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XsdTagNameBuilder extends NanoXmlUtil.IXMLBuilderAdapter {
+
+  @Nullable
+  public static Collection<String> computeTagNames(final InputStream is) {
+    return computeTagNames(new InputStreamReader(is));
+  }
+
+  @Nullable
+  public static Collection<String> computeTagNames(final Reader reader) {
+    try {
+      final XsdTagNameBuilder builder = new XsdTagNameBuilder();
+      NanoXmlUtil.parse(reader, builder);
+      return builder.myTagNames;
+    }
+    finally {
+      try {
+        if (reader != null) {
+          reader.close();
+        }
+      }
+      catch (IOException e) {
+        // can never happen
+      }
+    }
+  }
+
+  private final Collection<String> myTagNames = new ArrayList<String>();
+  private boolean myElementStarted;
+
+  public void startElement(@NonNls final String name, @NonNls final String nsPrefix, @NonNls final String nsURI, final String systemID, final int lineNr)
+      throws Exception {
+
+    myElementStarted = nsPrefix != null && nsURI.equals("http://www.w3.org/2001/XMLSchema") && name.equals("element");
+  }
+
+  public void addAttribute(@NonNls final String key, final String nsPrefix, final String nsURI, final String value, final String type)
+      throws Exception {
+    if (myElementStarted && key.equals("name")) {
+      myTagNames.add(value);
+      myElementStarted = false;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/refactoring/SchemaPrefixRenameHandler.java b/xml/impl/src/com/intellij/xml/refactoring/SchemaPrefixRenameHandler.java
new file mode 100644
index 0000000..4e478dd
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/refactoring/SchemaPrefixRenameHandler.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.refactoring;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.source.xml.PossiblePrefixReference;
+import com.intellij.psi.impl.source.xml.SchemaPrefix;
+import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler;
+import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class SchemaPrefixRenameHandler extends VariableInplaceRenameHandler {
+  
+  @Override
+  protected boolean isAvailable(PsiElement element, Editor editor, PsiFile file) {
+    PossiblePrefixReference ref = getReference(file, editor);
+    return ref != null && ref.resolve() instanceof SchemaPrefix;
+  }
+
+  @Nullable
+  private static PossiblePrefixReference getReference(PsiFile file, Editor editor) {
+    if (file != null && editor != null) {
+      int offset = editor.getCaretModel().getOffset();
+      PsiReference reference = file.findReferenceAt(offset);
+      if (reference instanceof PossiblePrefixReference) {
+        return (PossiblePrefixReference)reference;
+      }
+    }
+    return null;
+
+  }
+
+  @Override
+  protected VariableInplaceRenamer createRenamer(@NotNull PsiElement elementToRename, Editor editor) {
+    PossiblePrefixReference reference = getReference(elementToRename.getContainingFile(), editor);
+    if (reference != null) {
+      PsiElement prefix = reference.resolve();
+      if (prefix instanceof SchemaPrefix) {
+        return new VariableInplaceRenamer((PsiNamedElement)prefix, editor) {
+          @Override
+          protected void addReferenceAtCaret(Collection<PsiReference> refs) {}
+
+        };
+      }
+    }
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      System.out.println("Reference: " + reference);
+      if (reference != null) {
+        System.out.println("Resolved: " + reference.resolve());
+      }
+    }
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/refactoring/XmlInlineHandler.java b/xml/impl/src/com/intellij/xml/refactoring/XmlInlineHandler.java
new file mode 100644
index 0000000..bd3b6b0
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/refactoring/XmlInlineHandler.java
@@ -0,0 +1,24 @@
+package com.intellij.xml.refactoring;
+
+import com.intellij.lang.refactoring.InlineHandler;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class XmlInlineHandler implements InlineHandler {
+  @Override
+  public Settings prepareInlineElement(PsiElement element, Editor editor, boolean invokedOnReference) {
+    return null;
+  }
+
+  @Override
+  public void removeDefinition(PsiElement element, Settings settings) {
+  }
+
+  @Override
+  public Inliner createInliner(PsiElement element, Settings settings) {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/refactoring/XmlTagInplaceRenamer.java b/xml/impl/src/com/intellij/xml/refactoring/XmlTagInplaceRenamer.java
new file mode 100644
index 0000000..9585643
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/refactoring/XmlTagInplaceRenamer.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: spleaner
+ * Date: Aug 8, 2007
+ * Time: 2:20:33 PM
+ */
+package com.intellij.xml.refactoring;
+
+import com.intellij.codeInsight.daemon.impl.quickfix.EmptyExpression;
+import com.intellij.codeInsight.highlighting.HighlightManager;
+import com.intellij.codeInsight.template.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.colors.EditorColors;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.markup.RangeHighlighter;
+import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.refactoring.util.CommonRefactoringUtil;
+import com.intellij.util.PairProcessor;
+import com.intellij.util.containers.Stack;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class XmlTagInplaceRenamer {
+  @NonNls private static final String PRIMARY_VARIABLE_NAME = "PrimaryVariable";
+  @NonNls private static final String OTHER_VARIABLE_NAME = "OtherVariable";
+
+  private final Editor myEditor;
+
+  private final static Stack<XmlTagInplaceRenamer> ourRenamersStack = new Stack<XmlTagInplaceRenamer>();
+  private ArrayList<RangeHighlighter> myHighlighters;
+
+  private XmlTagInplaceRenamer(@NotNull final Editor editor) {
+    myEditor = editor;
+  }
+
+  public static void rename(final Editor editor, @NotNull final XmlTag tag) {
+    if (!ourRenamersStack.isEmpty()) {
+      ourRenamersStack.peek().finish();
+    }
+
+    final XmlTagInplaceRenamer renamer = new XmlTagInplaceRenamer(editor);
+    ourRenamersStack.push(renamer);
+    renamer.rename(tag);
+  }
+
+  private void rename(@NotNull final XmlTag tag) {
+    final Pair<ASTNode, ASTNode> pair = getNamePair(tag);
+    if (pair == null) return;
+
+    final Project project = myEditor.getProject();
+    if (project != null) {
+
+      final List<TextRange> highlightRanges = new ArrayList<TextRange>();
+      highlightRanges.add(pair.first.getTextRange());
+      if (pair.second != null) {
+        highlightRanges.add(pair.second.getTextRange());
+      }
+
+      if (!CommonRefactoringUtil.checkReadOnlyStatus(project, tag)) {
+        return;
+      }
+
+      myHighlighters = new ArrayList<RangeHighlighter>();
+
+      CommandProcessor.getInstance().executeCommand(project, new Runnable() {
+        public void run() {
+          ApplicationManager.getApplication().runWriteAction(new Runnable() {
+            public void run() {
+              final int offset = myEditor.getCaretModel().getOffset();
+              myEditor.getCaretModel().moveToOffset(tag.getTextOffset());
+
+              final Template t = buildTemplate(tag, pair);
+              TemplateManager.getInstance(project).startTemplate(myEditor, t, new TemplateEditingAdapter() {
+                public void templateFinished(final Template template, boolean brokenOff) {
+                  finish();
+                }
+
+                public void templateCancelled(final Template template) {
+                  finish();
+                }
+              }, new PairProcessor<String, String>() {
+                public boolean process(final String variableName, final String value) {
+                  return value.length() == 0 || value.charAt(value.length() - 1) != ' ';
+                }
+              });
+
+              // restore old offset
+              myEditor.getCaretModel().moveToOffset(offset);
+
+              addHighlights(highlightRanges, myEditor, myHighlighters);
+            }
+          });
+        }
+      }, RefactoringBundle.message("rename.title"), null);
+    }
+  }
+
+  private void finish() {
+    ourRenamersStack.pop();
+
+    if (myHighlighters != null) {
+      final HighlightManager highlightManager = HighlightManager.getInstance(myEditor.getProject());
+      for (final RangeHighlighter highlighter : myHighlighters) {
+        highlightManager.removeSegmentHighlighter(myEditor, highlighter);
+      }
+    }
+  }
+
+  private Pair<ASTNode, ASTNode> getNamePair(@NotNull final XmlTag tag) {
+    final int offset = myEditor.getCaretModel().getOffset();
+
+    final ASTNode node = tag.getNode();
+    assert node != null;
+
+    final ASTNode startTagName = XmlChildRole.START_TAG_NAME_FINDER.findChild(node);
+    if (startTagName == null) return null;
+
+    final ASTNode endTagName = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(node);
+
+    final ASTNode selected = (endTagName == null ||
+                              startTagName.getTextRange().contains(offset) ||
+                              startTagName.getTextRange().contains(offset - 1))
+                             ? startTagName
+                             : endTagName;
+    final ASTNode other = (selected == startTagName) ? endTagName : startTagName;
+
+    return new Pair<ASTNode, ASTNode>(selected, other);
+  }
+
+  private static Template buildTemplate(@NotNull final XmlTag tag, @NotNull final Pair<ASTNode, ASTNode> pair) {
+    final TemplateBuilderImpl builder = new TemplateBuilderImpl(tag);
+
+    final ASTNode selected = pair.first;
+    final ASTNode other = pair.second;
+
+    builder.replaceElement(selected.getPsi(), PRIMARY_VARIABLE_NAME, new EmptyExpression() {
+      public Result calculateQuickResult(final ExpressionContext context) {
+        return new TextResult(selected.getText());
+      }
+
+      public Result calculateResult(final ExpressionContext context) {
+        return new TextResult(selected.getText());
+      }
+    }, true);
+
+    if (other != null) {
+      builder.replaceElement(other.getPsi(), OTHER_VARIABLE_NAME, PRIMARY_VARIABLE_NAME, false);
+    }
+
+    return builder.buildInlineTemplate();
+  }
+
+  private static void addHighlights(List<TextRange> ranges, Editor editor, ArrayList<RangeHighlighter> highlighters) {
+    EditorColorsManager colorsManager = EditorColorsManager.getInstance();
+    final TextAttributes attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES);
+
+    final HighlightManager highlightManager = HighlightManager.getInstance(editor.getProject());
+    for (final TextRange range : ranges) {
+      highlightManager.addOccurrenceHighlight(editor, range.getStartOffset(), range.getEndOffset(), attributes, 0, highlighters, null);
+    }
+
+    for (RangeHighlighter highlighter : highlighters) {
+      highlighter.setGreedyToLeft(true);
+      highlighter.setGreedyToRight(true);
+    }
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/refactoring/XmlTagRenameDialog.java b/xml/impl/src/com/intellij/xml/refactoring/XmlTagRenameDialog.java
new file mode 100644
index 0000000..342a2e5
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/refactoring/XmlTagRenameDialog.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: spleaner
+ * Date: Aug 9, 2007
+ * Time: 4:45:40 PM
+ */
+package com.intellij.xml.refactoring;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupManager;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileTypes.FileTypes;
+import com.intellij.openapi.help.HelpManager;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.source.xml.TagNameReference;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.refactoring.ui.NameSuggestionsField;
+import com.intellij.refactoring.ui.RefactoringDialog;
+import com.intellij.ui.IdeBorderFactory;
+import com.intellij.usageView.UsageViewUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+public class XmlTagRenameDialog extends RefactoringDialog {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.refactoring.XmlTagRenameDialog");
+  private static final String REFACTORING_NAME = RefactoringBundle.message("rename.title");
+
+  private final PsiElement myElement;
+  private final Editor myEditor;
+  private JLabel myTitleLabel;
+  private NameSuggestionsField myNameSuggestionsField;
+  private String myHelpID;
+  private final XmlTag myTag;
+  private NameSuggestionsField.DataChanged myNameChangedListener;
+
+  public XmlTagRenameDialog(@NotNull final Editor editor, @NotNull final PsiElement element, @NotNull final XmlTag tag) {
+    super(element.getProject(), true);
+
+    myEditor = editor;
+    myElement = element;
+    myTag = tag;
+
+    setTitle(REFACTORING_NAME);
+    createNewNameComponent();
+
+    init();
+
+    myTitleLabel.setText(XmlBundle.message("rename.current.tag", getFullName(tag)));
+
+    validateButtons();
+  }
+
+  protected void dispose() {
+    myNameSuggestionsField.removeDataChangedListener(myNameChangedListener);
+    super.dispose();
+  }
+
+  protected boolean hasHelpAction() {
+    return false;
+  }
+
+  private static String getFullName(@NotNull final XmlTag tag) {
+    final String name = UsageViewUtil.getDescriptiveName(tag);
+    return (UsageViewUtil.getType(tag) + " " + name).trim();
+  }
+
+  public static void renameXmlTag(final Editor editor, @NotNull final PsiElement element, @NotNull final XmlTag tag) {
+    final XmlTagRenameDialog dialog = new XmlTagRenameDialog(editor, element, tag);
+    dialog.show();
+  }
+
+  private void createNewNameComponent() {
+    myNameSuggestionsField = new NameSuggestionsField(new String[] { myTag.getName() }, myProject, FileTypes.PLAIN_TEXT, myEditor);
+    myNameChangedListener = new NameSuggestionsField.DataChanged() {
+      public void dataChanged() {
+        validateButtons();
+      }
+    };
+    myNameSuggestionsField.addDataChangedListener(myNameChangedListener);
+
+    myNameSuggestionsField.getComponent().registerKeyboardAction(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        completeVariable(myNameSuggestionsField.getEditor());
+      }
+    }, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);
+  }
+
+  private void completeVariable(final Editor editor) {
+    String prefix = myNameSuggestionsField.getEnteredName();
+
+    final PsiReference reference = myTag.getReference();
+    if (reference instanceof TagNameReference) {
+      LookupElement[] lookupItems = ((TagNameReference)reference).getVariants();
+      editor.getCaretModel().moveToOffset(prefix.length());
+      editor.getSelectionModel().removeSelection();
+      LookupManager.getInstance(getProject()).showLookup(editor, lookupItems, prefix);
+    }
+  }
+
+  protected void doAction() {
+    LOG.assertTrue(myElement.isValid());
+
+    CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+      public void run() {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          public void run() {
+            try {
+              myTag.setName(getNewName());
+            }
+            catch (IncorrectOperationException e) {
+              LOG.error(e);
+            }
+          }
+        });
+      }
+    }, RefactoringBundle.message("rename.title"), null);
+
+    close(DialogWrapper.OK_EXIT_CODE);
+  }
+
+  @Nullable
+  protected JComponent createCenterPanel() {
+    return null;
+  }
+
+  public JComponent getPreferredFocusedComponent() {
+    return myNameSuggestionsField.getFocusableComponent();
+  }
+
+  protected JComponent createNorthPanel() {
+    final JPanel panel = new JPanel();
+    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+    panel.setBorder(BorderFactory.createEmptyBorder(4, 8, 4, 8));
+
+    myTitleLabel = new JLabel();
+    panel.add(myTitleLabel);
+    panel.add(Box.createVerticalStrut(8));
+    panel.add(myNameSuggestionsField.getComponent());
+
+    return panel;
+  }
+
+  protected void doHelpAction() {
+    HelpManager.getInstance().invokeHelp(myHelpID);
+  }
+
+  public String getNewName() {
+    return myNameSuggestionsField.getEnteredName().trim();
+  }
+
+  protected void validateButtons() {
+    super.validateButtons();
+
+    getPreviewAction().setEnabled(false);
+  }
+
+  protected boolean areButtonsValid() {
+    final String newName = getNewName();
+    return !StringUtil.containsAnyChar(newName, "\t ;*'\"\\/,()^&<>={}"); // RenameUtil.isValidName(myProject, myTag, newName); // IDEADEV-34531
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/refactoring/XmlTagRenameHandler.java b/xml/impl/src/com/intellij/xml/refactoring/XmlTagRenameHandler.java
new file mode 100644
index 0000000..e2531e7
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/refactoring/XmlTagRenameHandler.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: spleaner
+ * Date: Aug 7, 2007
+ * Time: 2:44:37 PM
+ */
+package com.intellij.xml.refactoring;
+
+import com.intellij.featureStatistics.FeatureUsageTracker;
+import com.intellij.ide.TitledHandler;
+import com.intellij.lang.Language;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.util.PsiUtilBase;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.refactoring.actions.BaseRefactoringAction;
+import com.intellij.refactoring.rename.PsiElementRenameHandler;
+import com.intellij.refactoring.rename.RenameHandler;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class XmlTagRenameHandler implements RenameHandler, TitledHandler {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.refactoring.XmlTagRenameHandler");
+
+
+  public boolean isAvailableOnDataContext(final DataContext dataContext) {
+    final PsiElement element = getElement(dataContext);
+    if (element == null || PsiElementRenameHandler.isVetoed(element)) return false;
+    PsiElement parent = element.getParent();
+    if (!(parent instanceof XmlTag)) {
+      return false;
+    }
+    XmlTag tag = (XmlTag)parent;
+    String prefix = tag.getNamespacePrefix();
+    if (StringUtil.isNotEmpty(prefix)) {
+      Editor editor = getEditor(dataContext);
+      assert editor != null;
+      int offset = editor.getCaretModel().getOffset();
+      if (offset <= element.getTextRange().getStartOffset() + prefix.length()) {
+        return false;
+      }
+    }
+    //noinspection ConstantConditions
+    return isDeclarationOutOfProjectOrAbsent(element.getProject(), dataContext);
+  }
+
+  public boolean isRenaming(final DataContext dataContext) {
+    return isAvailableOnDataContext(dataContext);
+  }
+
+  @Override
+  public String getActionTitle() {
+    return "Rename XML tag";
+  }
+
+  private static boolean isInplaceRenameAvailable(final Editor editor) {
+    return editor.getSettings().isVariableInplaceRenameEnabled();
+  }
+
+  private static boolean isDeclarationOutOfProjectOrAbsent(@NotNull final Project project, final DataContext context) {
+    final PsiElement[] elements = BaseRefactoringAction.getPsiElementArray(context);
+    return elements.length == 0 || elements.length == 1 && shouldBeRenamedInplace(project, elements);
+  }
+
+  private static boolean shouldBeRenamedInplace(Project project, PsiElement[] elements) {
+    boolean inProject = PsiManager.getInstance(project).isInProject(elements[0]);
+    if (inProject && elements[0] instanceof XmlTag) {
+      XmlElementDescriptor descriptor = ((XmlTag)elements[0]).getDescriptor();
+      return descriptor instanceof AnyXmlElementDescriptor;
+    }
+    return !inProject;
+  }
+
+  @Nullable
+  private static Editor getEditor(@Nullable DataContext context) {
+    return PlatformDataKeys.EDITOR.getData(context);
+  }
+
+  @Nullable
+  private static PsiElement getElement(@Nullable final DataContext context) {
+    if (context != null) {
+      final Editor editor = getEditor(context);
+      if (editor != null) {
+        final int offset = editor.getCaretModel().getOffset();
+        final PsiFile file = LangDataKeys.PSI_FILE.getData(context);
+        if (file instanceof XmlFile) {
+          return file.getViewProvider().findElementAt(offset);
+        }
+        if (file != null) {
+          final Language language = PsiUtilBase.getLanguageAtOffset(file, offset);
+          if (language != file.getLanguage()) {
+            final PsiFile psiAtOffset = file.getViewProvider().getPsi(language);
+            if (psiAtOffset instanceof XmlFile) {
+              return psiAtOffset.findElementAt(offset);
+            }
+          }
+        }
+      }
+    }
+
+    return null;
+  }
+
+  private void invoke(@Nullable final Editor editor, @NotNull final PsiElement element, @Nullable final DataContext context) {
+    if (!isRenaming(context)) {
+      return;
+    }
+
+    FeatureUsageTracker.getInstance().triggerFeatureUsed("refactoring.rename");
+
+    if (isInplaceRenameAvailable(editor)) {
+      XmlTagInplaceRenamer.rename(editor, (XmlTag)element.getParent());
+    }
+    else {
+      XmlTagRenameDialog.renameXmlTag(editor, element, (XmlTag)element.getParent());
+    }
+  }
+
+  public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file, @Nullable final DataContext dataContext) {
+    if (!isRenaming(dataContext)) {
+      return;
+    }
+
+    final PsiElement element = getElement(dataContext);
+    assert element != null;
+
+    invoke(editor, element, dataContext);
+  }
+
+  public void invoke(@NotNull final Project project, @NotNull final PsiElement[] elements, @Nullable final DataContext dataContext) {
+    PsiElement element = elements.length == 1 ? elements[0] : null;
+    if (element == null) {
+      element = getElement(dataContext);
+    }
+
+    LOG.assertTrue(element != null);
+    invoke(getEditor(dataContext), element, dataContext);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/AnchorPathReferenceProvider.java b/xml/impl/src/com/intellij/xml/util/AnchorPathReferenceProvider.java
new file mode 100644
index 0000000..74030d7
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/AnchorPathReferenceProvider.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.openapi.paths.PathReference;
+import com.intellij.openapi.paths.PathReferenceProvider;
+import com.intellij.openapi.paths.DynamicContextProvider;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.ElementManipulators;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class AnchorPathReferenceProvider implements PathReferenceProvider {
+
+  public boolean createReferences(@NotNull final PsiElement psiElement, final @NotNull List<PsiReference> references, final boolean soft) {
+
+    final TextRange range = ElementManipulators.getValueTextRange(psiElement);
+    final String elementText = psiElement.getText();
+    final int anchorOffset = elementText.indexOf('#');
+    if (anchorOffset == -1) {
+      return false;
+    }
+    final boolean dynamic = isDynamic(psiElement, anchorOffset + 1, elementText);
+    if (dynamic) {
+      return false;
+    }
+
+    FileReference fileReference = null;
+    if (range.getStartOffset() != anchorOffset) {
+      fileReference = findFileReference(references);
+      if (fileReference == null || fileReference.resolve() == null) {
+        return false;
+      }
+    }
+    final int pos = elementText.indexOf('?', anchorOffset);
+    final String anchor;
+    try {
+      int endIndex = pos != -1 ? pos : range.getEndOffset();
+      if (endIndex <= anchorOffset) {
+        endIndex = anchorOffset + 1;
+      }
+      anchor = elementText.substring(anchorOffset + 1, endIndex);
+    }
+    catch (StringIndexOutOfBoundsException e) {      
+      throw new RuntimeException(elementText, e);
+    }
+    final AnchorReference anchorReference = new AnchorReference(anchor, fileReference, psiElement, anchorOffset + 1, soft);
+    references.add(anchorReference);
+    return false;
+  }
+
+  private static boolean isDynamic(final PsiElement psiElement, final int offset, final String elementText) {
+    for (DynamicContextProvider provider: Extensions.getExtensions(DynamicContextProvider.EP_NAME)) {
+      final int dynamicOffset = provider.getOffset(psiElement, offset, elementText);
+      if (dynamicOffset != offset) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Nullable
+  private static FileReference findFileReference(final List<PsiReference> references) {
+    FileReference fileReference = null;
+    for (PsiReference reference : references) {
+      if (reference instanceof FileReference) {
+        fileReference = ((FileReference)reference).getFileReferenceSet().getLastReference();
+        break;
+      }
+    }
+    return fileReference;
+  }
+
+  public PathReference getPathReference(@NotNull final String path, @NotNull final PsiElement element) {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/AnchorReference.java b/xml/impl/src/com/intellij/xml/util/AnchorReference.java
new file mode 100644
index 0000000..65e0c1a
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/AnchorReference.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.ElementManipulators;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.HashMap;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlExtension;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class AnchorReference implements PsiReference, EmptyResolveMessageProvider {
+  private final String myAnchor;
+  private final FileReference myFileReference;
+  private final PsiElement myElement;
+  private final int myOffset;
+  private final boolean mySoft;
+  @NonNls
+  private static final String ANCHOR_ELEMENT_NAME = "a";
+  private static final String MAP_ELEMENT_NAME = "map";
+  private static final Key<CachedValue<Map<String,XmlTag>>> ourCachedIdsKey = Key.create("cached.ids");
+
+  AnchorReference(final String anchor, @Nullable final FileReference psiReference, final PsiElement element, final int offset,
+                  final boolean soft) {
+
+    myAnchor = anchor;
+    myFileReference = psiReference;
+    myElement = element;
+    myOffset = offset;
+    mySoft = soft;
+  }
+
+  public PsiElement getElement() {
+    return myElement;
+  }
+
+  public TextRange getRangeInElement() {
+    return new TextRange(myOffset,myOffset+myAnchor.length());
+  }
+
+  public PsiElement resolve() {
+    if (myAnchor.length() == 0) {
+      return myElement;
+    }
+    Map<String,XmlTag> map = getIdMap();
+    final XmlTag tag = map != null ? map.get(myAnchor):null;
+    if (tag != null) {
+      XmlAttribute attribute = tag.getAttribute("id");
+      if (attribute==null) attribute = tag.getAttribute("name");
+
+      if (attribute == null && MAP_ELEMENT_NAME.equalsIgnoreCase(tag.getName())) {
+        attribute = tag.getAttribute("usemap");
+      }
+
+      assert attribute != null;
+      return attribute.getValueElement();
+    }
+
+    return null;
+  }
+
+  private static boolean processXmlElements(XmlTag element, PsiElementProcessor<XmlTag> processor) {
+    if (!_processXmlElements(element,processor)) return false;
+
+    for(PsiElement next = element.getNextSibling(); next != null; next = next.getNextSibling()) {
+      if (next instanceof XmlTag) {
+        if (!_processXmlElements((XmlTag)next,processor)) return false;
+      }
+    }
+
+    return true;
+  }
+
+  static boolean _processXmlElements(XmlTag element, PsiElementProcessor<XmlTag> processor) {
+    if (!processor.execute(element)) return false;
+    final XmlTag[] subTags = element.getSubTags();
+
+    for (XmlTag subTag : subTags) {
+      if (!_processXmlElements(subTag, processor)) return false;
+    }
+
+    return true;
+  }
+
+  @Nullable
+  private Map<String,XmlTag> getIdMap() {
+    final XmlFile file = getFile();
+
+    if (file != null) {
+      CachedValue<Map<String, XmlTag>> value = file.getUserData(ourCachedIdsKey);
+      if (value == null) {
+        value = CachedValuesManager.getManager(file.getProject()).createCachedValue(new MapCachedValueProvider(file), false);
+        file.putUserData(ourCachedIdsKey, value);
+      }
+
+      return value.getValue();
+    }
+    return null;
+  }
+
+  @Nullable
+  private static String getAnchorValue(final XmlTag xmlTag) {
+    final String attributeValue = xmlTag.getAttributeValue("id");
+
+    if (attributeValue!=null) {
+      return attributeValue;
+    }
+
+    if (ANCHOR_ELEMENT_NAME.equalsIgnoreCase(xmlTag.getName())) {
+      final String attributeValue2 = xmlTag.getAttributeValue("name");
+      if (attributeValue2!=null) {
+        return attributeValue2;
+      }
+    }
+
+    if (MAP_ELEMENT_NAME.equalsIgnoreCase(xmlTag.getName())) {
+      final String map_anchor = xmlTag.getAttributeValue("name");
+      if (map_anchor != null) {
+        return map_anchor;
+      }
+    }
+
+    return null;
+  }
+
+  @NotNull
+  public String getCanonicalText() {
+    return myAnchor;
+  }
+
+  public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+    return ElementManipulators.getManipulator(myElement).handleContentChange(
+      myElement,
+      getRangeInElement(),
+      newElementName
+    );
+  }
+
+  @Nullable
+  public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+    return null;
+  }
+
+  public boolean isReferenceTo(PsiElement element) {
+    if (!(element instanceof XmlAttributeValue)) return false;
+    return myElement.getManager().areElementsEquivalent(element,resolve());
+  }
+
+  @NotNull
+  public Object[] getVariants() {
+    final Map<String, XmlTag> idMap = getIdMap();
+    if (idMap == null) return ArrayUtil.EMPTY_OBJECT_ARRAY;
+
+    String[] variants = idMap.keySet().toArray(new String[idMap.size()]);
+    LookupElement[] elements = new LookupElement[variants.length];
+    for (int i = 0, variantsLength = variants.length; i < variantsLength; i++) {
+      elements[i] = LookupElementBuilder.create(variants[i]).withCaseSensitivity(true);
+    }
+    return elements;
+  }
+
+  @Nullable
+  private XmlFile getFile() {
+    if (myFileReference != null) {
+      final PsiElement psiElement = myFileReference.resolve();
+      return psiElement instanceof XmlFile ? (XmlFile)psiElement:null;
+    }
+
+    final PsiFile containingFile = myElement.getContainingFile();
+    if (containingFile instanceof XmlFile) {
+      return (XmlFile)containingFile;
+    }
+    else {
+      final XmlExtension extension = XmlExtension.getExtensionByElement(myElement);
+      return extension == null ? null : extension.getContainingFile(myElement);
+    }
+  }
+
+  public boolean isSoft() {
+    return mySoft;
+  }
+
+  public String getUnresolvedMessagePattern() {
+    final XmlFile xmlFile = getFile();
+    return xmlFile == null ? 
+           XmlBundle.message("cannot.resolve.anchor", myAnchor) :
+           XmlBundle.message("cannot.resolve.anchor.in.file", myAnchor, xmlFile.getName());
+  }
+
+  // separate static class to avoid memory leak via this$0
+  private static class MapCachedValueProvider implements CachedValueProvider<Map<String, XmlTag>> {
+    private final XmlFile myFile;
+
+    public MapCachedValueProvider(XmlFile file) {
+      myFile = file;
+    }
+
+    public Result<Map<String, XmlTag>> compute() {
+      final Map<String,XmlTag> resultMap = new HashMap<String, XmlTag>();
+      XmlDocument document = HtmlUtil.getRealXmlDocument(myFile.getDocument());
+      final XmlTag rootTag = document != null ? document.getRootTag():null;
+
+      if (rootTag != null) {
+        processXmlElements(rootTag,
+          new PsiElementProcessor<XmlTag>() {
+            public boolean execute(@NotNull final XmlTag element) {
+              final String anchorValue = getAnchorValue(element);
+
+              if (anchorValue!=null) {
+                resultMap.put(anchorValue, element);
+              }
+              return true;
+            }
+          }
+        );
+      }
+      return new Result<Map<String, XmlTag>>(resultMap, myFile);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/CheckDtdReferencesInspection.java b/xml/impl/src/com/intellij/xml/util/CheckDtdReferencesInspection.java
new file mode 100644
index 0000000..5ce4df8
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/CheckDtdReferencesInspection.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.xml.util;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
+import com.intellij.codeInsight.template.Template;
+import com.intellij.codeInsight.template.TemplateManager;
+import com.intellij.codeInspection.*;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.containers.HashMap;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.PropertyKey;
+
+import java.util.Map;
+
+/**
+ * @author Maxim Mossienko
+ */
+public class CheckDtdReferencesInspection extends XmlSuppressableInspectionTool {
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+
+  @NotNull
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
+    return new XmlElementVisitor() {
+
+      private Map<PsiFile, Boolean> myDoctypeMap = new HashMap<PsiFile, Boolean>();
+
+      @Override
+      public void visitXmlElement(final XmlElement element) {
+        if (isHtml5Doctype(element)) {
+          return;
+        }
+
+        if (element instanceof XmlElementContentSpec ||
+            element instanceof XmlEntityRef
+          ) {
+          doCheckRefs(element, holder);
+        }
+      }
+
+      private boolean isHtml5Doctype(XmlElement element) {
+        if (HtmlUtil.isHtml5Context(element)) {
+          return true;
+        }
+
+        PsiFile file = element.getContainingFile();
+        if (file instanceof XmlFile) {
+          if (!myDoctypeMap.containsKey(file)) {
+            myDoctypeMap.put(file, computeHtml5Doctype((XmlFile)file));
+          }
+          return myDoctypeMap.get(file);
+        }
+        return false;
+      }
+
+      private Boolean computeHtml5Doctype(XmlFile file) {
+        XmlDoctype doctype = null;
+        //Search for doctypes from providers
+        for (HtmlDoctypeProvider provider : HtmlDoctypeProvider.EP_NAME.getExtensions()) {
+          doctype = provider.getDoctype(file);
+          if (doctype != null) {
+            break;
+          }
+        }
+
+        if (doctype != null && HtmlUtil.isHtml5Doctype(doctype)) {
+          return true;
+        }
+
+        return false;
+      }
+    };
+  }
+
+  private static void doCheckRefs(final XmlElement element, final ProblemsHolder holder) {
+    for (PsiReference ref : element.getReferences()) {
+      ProgressManager.checkCanceled();
+      if (XmlHighlightVisitor.hasBadResolve(ref, true)) {
+        if (ref.getElement() instanceof XmlElementContentSpec) {
+          final String image = ref.getCanonicalText();
+          if (image.equals("-") || image.equals("O")) continue;
+        }
+        holder.registerProblem(ref);
+      }
+    }
+  }
+
+  @NotNull
+  public HighlightDisplayLevel getDefaultLevel() {
+    return HighlightDisplayLevel.ERROR;
+  }
+
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlInspectionGroupNames.XML_INSPECTIONS;
+  }
+
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("xml.inspections.check.dtd.references");
+  }
+
+  @NotNull
+  @NonNls
+  public String getShortName() {
+    return "CheckDtdRefs";
+  }
+
+  public static class AddDtdDeclarationFix implements LocalQuickFix {
+    private final String myMessageKey;
+    private final String myElementDeclarationName;
+    private final String myReference;
+
+    public AddDtdDeclarationFix(
+      @PropertyKey(resourceBundle = XmlBundle.PATH_TO_BUNDLE) String messageKey,
+      @NotNull String elementDeclarationName,
+      @NotNull PsiReference reference) {
+      myMessageKey = messageKey;
+      myElementDeclarationName = elementDeclarationName;
+      myReference = reference.getCanonicalText();
+    }
+
+    @NotNull
+    public String getName() {
+      return XmlBundle.message(myMessageKey, myReference);
+    }
+
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+
+    public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+      final PsiElement element = descriptor.getPsiElement();
+      final PsiFile containingFile = element.getContainingFile();
+      if (!CodeInsightUtilBase.prepareFileForWrite(containingFile)) return;
+
+      @NonNls String prefixToInsert = "";
+      @NonNls String suffixToInsert = "";
+
+      final int UNDEFINED_OFFSET = -1;
+      int anchorOffset = UNDEFINED_OFFSET;
+      PsiElement anchor =
+        PsiTreeUtil.getParentOfType(element, XmlElementDecl.class, XmlAttlistDecl.class, XmlEntityDecl.class, XmlConditionalSection.class);
+      if (anchor != null) anchorOffset = anchor.getTextRange().getStartOffset();
+
+      if (anchorOffset == UNDEFINED_OFFSET && containingFile.getLanguage() == XMLLanguage.INSTANCE) {
+        XmlFile file = (XmlFile)containingFile;
+        final XmlProlog prolog = file.getDocument().getProlog();
+        assert prolog != null;
+
+        final XmlDoctype doctype = prolog.getDoctype();
+        final XmlMarkupDecl markupDecl;
+
+        if (doctype != null) {
+          markupDecl = doctype.getMarkupDecl();
+        }
+        else {
+          markupDecl = null;
+        }
+
+        if (doctype == null) {
+          final XmlTag rootTag = file.getDocument().getRootTag();
+          prefixToInsert = "<!DOCTYPE " + ((rootTag != null) ? rootTag.getName() : "null");
+          suffixToInsert = ">\n";
+        }
+        if (markupDecl == null) {
+          prefixToInsert += " [\n";
+          suffixToInsert = "]" + suffixToInsert;
+
+          if (doctype != null) {
+            anchorOffset = doctype.getTextRange().getEndOffset() - 1; // just before last '>'
+          }
+          else {
+            anchorOffset = prolog.getTextRange().getEndOffset();
+          }
+        }
+      }
+
+      if (anchorOffset == UNDEFINED_OFFSET) anchorOffset = element.getTextRange().getStartOffset();
+
+      OpenFileDescriptor openDescriptor = new OpenFileDescriptor(project, containingFile.getVirtualFile(), anchorOffset);
+      final Editor editor = FileEditorManager.getInstance(project).openTextEditor(openDescriptor, true);
+      final TemplateManager templateManager = TemplateManager.getInstance(project);
+      final Template t = templateManager.createTemplate("", "");
+
+      if (prefixToInsert.length() > 0) t.addTextSegment(prefixToInsert);
+      t.addTextSegment("<!" + myElementDeclarationName + " " + myReference + " ");
+      t.addEndVariable();
+      t.addTextSegment(">\n");
+      if (suffixToInsert.length() > 0) t.addTextSegment(suffixToInsert);
+      templateManager.startTemplate(editor, t);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java b/xml/impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java
new file mode 100644
index 0000000..ed169c7
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.xml.util;
+
+import com.intellij.codeInspection.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.ReadonlyStatusHandler;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlBundle;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.Set;
+
+/**
+ * @author Maxim Mossienko
+ */
+public class CheckEmptyTagInspection extends XmlSuppressableInspectionTool {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.CheckEmptyTagInspection");
+  @NonNls private static final String SCRIPT_TAG_NAME = "script";
+  private static final Set<String> ourTagsWithEmptyEndsNotAllowed = new THashSet<String>(Arrays.asList(SCRIPT_TAG_NAME, "div", "iframe"));
+
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+
+  @NotNull
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
+    return new XmlElementVisitor() {
+      @Override public void visitXmlTag(final XmlTag tag) {
+        if (!isTagWithEmptyEndNotAllowed(tag)) {
+          return;
+        }
+        final ASTNode child = XmlChildRole.EMPTY_TAG_END_FINDER.findChild(tag.getNode());
+
+        if (child == null) {
+          return;
+        }
+
+        final LocalQuickFix fix = new MyLocalQuickFix();
+
+        holder.registerProblem(tag,
+                               XmlBundle.message("html.inspections.check.empty.script.message"),
+                               tag.getContainingFile().getContext() != null ?
+                               ProblemHighlightType.INFORMATION:
+                               ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+                               fix);
+      }
+    };
+  }
+
+  static boolean isTagWithEmptyEndNotAllowed(final XmlTag tag) {
+    String tagName = tag.getName();
+    if (tag instanceof HtmlTag) tagName = tagName.toLowerCase();
+
+    Language language = tag.getLanguage();
+    return ourTagsWithEmptyEndsNotAllowed.contains(tagName) && language != XMLLanguage.INSTANCE ||
+           language == HTMLLanguage.INSTANCE && !HtmlUtil.isSingleHtmlTagL(tagName) && tagName.indexOf(':') == -1;
+  }
+
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlInspectionGroupNames.HTML_INSPECTIONS;
+  }
+
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("html.inspections.check.empty.tag");
+  }
+
+  @NotNull
+  @NonNls
+  public String getShortName() {
+    return "CheckEmptyScriptTag";
+  }
+
+  private static class MyLocalQuickFix implements LocalQuickFix {
+    @NotNull
+    public String getName() {
+      return XmlBundle.message("html.inspections.check.empty.script.tag.fix.message");
+    }
+
+    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+      final XmlTag tag = (XmlTag)descriptor.getPsiElement();
+      if (tag == null) return;
+      final PsiFile psiFile = tag.getContainingFile();
+
+      if (psiFile == null) return;
+      ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(psiFile.getVirtualFile());
+
+      try {
+        XmlUtil.expandTag(tag);
+      }
+      catch (IncorrectOperationException e) {
+        LOG.error(e);
+      }
+    }
+
+    //to appear in "Apply Fix" statement when multiple Quick Fixes exist
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/CheckTagEmptyBodyInspection.java b/xml/impl/src/com/intellij/xml/util/CheckTagEmptyBodyInspection.java
new file mode 100644
index 0000000..59646d4
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/CheckTagEmptyBodyInspection.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInspection.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Maxim Mossienko
+ */
+public class CheckTagEmptyBodyInspection extends XmlSuppressableInspectionTool {
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+
+  @NotNull
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
+    return new XmlElementVisitor() {
+      @Override public void visitXmlTag(final XmlTag tag) {
+        if (!CheckEmptyTagInspection.isTagWithEmptyEndNotAllowed(tag)) {
+          final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode());
+
+          if (child != null) {
+            final ASTNode node = child.getTreeNext();
+
+            if (node != null &&
+                node.getElementType() == XmlTokenType.XML_END_TAG_START) {
+              final LocalQuickFix localQuickFix = new ReplaceEmptyTagBodyByEmptyEndFix();
+              holder.registerProblem(
+                tag,
+                XmlBundle.message("xml.inspections.tag.empty.body"),
+                isCollapsableTag(tag) ? localQuickFix : null
+              );
+            }
+          }
+        }
+      }
+    };
+  }
+
+  @SuppressWarnings({"HardCodedStringLiteral"})
+  private static boolean isCollapsableTag(final XmlTag tag) {
+    final String name = tag.getName().toLowerCase();
+    return tag.getLanguage() == XMLLanguage.INSTANCE ||
+           "link".equals(name) || "br".equals(name) || "meta".equals(name) || "img".equals(name) || "input".equals(name) || "hr".equals(name);
+  }
+
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlInspectionGroupNames.XML_INSPECTIONS;
+  }
+
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("xml.inspections.check.tag.empty.body");
+  }
+
+  @NotNull
+  @NonNls
+  public String getShortName() {
+    return "CheckTagEmptyBody";
+  }
+
+  private static class ReplaceEmptyTagBodyByEmptyEndFix implements LocalQuickFix {
+    @NotNull
+    public String getName() {
+      return XmlBundle.message("xml.inspections.replace.tag.empty.body.with.empty.end");
+    }
+
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+
+    public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+      final PsiElement tag = descriptor.getPsiElement();
+      if (!CodeInsightUtilBase.prepareFileForWrite(tag.getContainingFile())) {
+        return;
+      }
+
+      PsiDocumentManager.getInstance(project).commitAllDocuments();
+
+      final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode());
+      if (child == null) return;
+      final int offset = child.getTextRange().getStartOffset();
+      VirtualFile file = tag.getContainingFile().getVirtualFile();
+      final Document document = FileDocumentManager.getInstance().getDocument(file);
+
+      new WriteCommandAction(project) {
+        protected void run(final Result result) throws Throwable {
+          document.replaceString(offset, tag.getTextRange().getEndOffset(),"/>");
+        }
+      }.execute();
+    }
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/util/CheckValidXmlInScriptBodyInspection.java b/xml/impl/src/com/intellij/xml/util/CheckValidXmlInScriptBodyInspection.java
new file mode 100644
index 0000000..5487ef1
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/CheckValidXmlInScriptBodyInspection.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: Maxim.Mossienko
+ * Date: Jun 29, 2006
+ * Time: 6:09:35 PM
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInspection.*;
+import com.intellij.lexer.Lexer;
+import com.intellij.lexer.XmlLexer;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.XmlElementVisitor;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.impl.source.tree.TreeUtil;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTagValue;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Maxim Mossienko
+ */
+public class CheckValidXmlInScriptBodyInspection extends XmlSuppressableInspectionTool {
+  @NonNls
+  private static final String SCRIPT_TAG_NAME = "script";
+  private Lexer myXmlLexer;
+  @NonNls
+  private static final String AMP_ENTITY_REFERENCE = "&amp;";
+  @NonNls
+  private static final String LT_ENTITY_REFERENCE = "&lt;";
+
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+
+  @NotNull
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
+    return new XmlElementVisitor() {
+      @Override public void visitXmlTag(final XmlTag tag) {
+        if (SCRIPT_TAG_NAME.equals(tag.getName()) ||
+            (tag instanceof HtmlTag && SCRIPT_TAG_NAME.equalsIgnoreCase(tag.getName()))
+           ) {
+          final PsiFile psiFile = tag.getContainingFile();
+          final FileType fileType = psiFile.getFileType();
+
+          if (fileType == StdFileTypes.XHTML || fileType == StdFileTypes.JSPX) {
+            synchronized(CheckValidXmlInScriptBodyInspection.class) {
+              if (myXmlLexer == null) myXmlLexer = new XmlLexer();
+              final XmlTagValue tagValue = tag.getValue();
+              final String tagBodyText = tagValue.getText();
+
+              if (tagBodyText.length() > 0) {
+                myXmlLexer.start(tagBodyText);
+
+                while(myXmlLexer.getTokenType() != null) {
+                  IElementType tokenType = myXmlLexer.getTokenType();
+
+                  if (tokenType == XmlTokenType.XML_CDATA_START) {
+                    while(tokenType != null && tokenType != XmlTokenType.XML_CDATA_END) {
+                      myXmlLexer.advance();
+                      tokenType = myXmlLexer.getTokenType();
+                    }
+                    if (tokenType == null) break;
+                  }
+                  if (( tokenType == XmlTokenType.XML_BAD_CHARACTER &&
+                        "&".equals(TreeUtil.getTokenText(myXmlLexer))
+                      ) ||
+                      tokenType == XmlTokenType.XML_START_TAG_START
+                    ) {
+                    final int valueStart = tagValue.getTextRange().getStartOffset();
+                    final int offset = valueStart + myXmlLexer.getTokenStart();
+                    final PsiElement psiElement = psiFile.findElementAt(offset);
+                    final TextRange elementRange = psiElement.getTextRange();
+
+                    final int offsetInElement = offset - elementRange.getStartOffset();
+                    holder.registerProblem(
+                      psiElement,
+                      XmlBundle.message("unescaped.xml.character"),
+                      ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+                      new InsertQuotedCharacterQuickFix(
+                        psiFile,
+                        psiElement,
+                        offsetInElement
+                      )
+                    );
+
+                    int endOfElementInScriptTag = elementRange.getEndOffset() - valueStart;
+                    while(myXmlLexer.getTokenEnd() < endOfElementInScriptTag) {
+                      myXmlLexer.advance();
+                      if (myXmlLexer.getTokenType() == null) break;
+                    }
+                  }
+                  myXmlLexer.advance();
+                }
+              }
+            }
+          }
+        }
+      }
+    };
+  }
+
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlInspectionGroupNames.HTML_INSPECTIONS;
+  }
+
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("html.inspections.check.valid.script.tag");
+  }
+
+  @NotNull
+  @NonNls
+  public String getShortName() {
+    return "CheckValidXmlInScriptTagBody";
+  }
+
+  private static class InsertQuotedCharacterQuickFix implements LocalQuickFix {
+    private final PsiFile psiFile;
+    private final PsiElement psiElement;
+    private final int startInElement;
+
+    public InsertQuotedCharacterQuickFix(PsiFile psiFile, PsiElement psiElement, int startInElement) {
+      this.psiFile = psiFile;
+      this.psiElement = psiElement;
+      this.startInElement = startInElement;
+    }
+
+    @NotNull
+    public String getName() {
+      final String character = getXmlCharacter();
+
+      return XmlBundle.message(
+        "unescaped.xml.character.fix.message",
+        character.equals("&") ?
+          XmlBundle.message("unescaped.xml.character.fix.message.parameter"):
+          character
+      );
+    }
+
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+
+    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor problemDescriptor) {
+      if ( !CodeInsightUtilBase.prepareFileForWrite(psiFile)) return;
+      final TextRange range = psiElement.getTextRange();
+      OpenFileDescriptor descriptor = new OpenFileDescriptor(
+        project,
+        psiFile.getVirtualFile(),
+        range.getStartOffset() + startInElement
+      );
+
+      final Editor editor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
+      if (editor == null) return;
+
+      final String xmlCharacter = getXmlCharacter();
+      String replacement = xmlCharacter.equals("&") ? AMP_ENTITY_REFERENCE : LT_ENTITY_REFERENCE;
+      replacement = psiElement.getText().replace(xmlCharacter,replacement);
+
+      editor.getDocument().replaceString(
+        range.getStartOffset(),
+        range.getEndOffset(),
+        replacement
+      );
+    }
+
+    private String getXmlCharacter() {
+      return psiElement.getText().substring(startInElement, startInElement + 1);
+    }
+  }
+
+  @NotNull
+  public HighlightDisplayLevel getDefaultLevel() {
+    return HighlightDisplayLevel.ERROR;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/CheckXmlFileWithXercesValidatorInspection.java b/xml/impl/src/com/intellij/xml/util/CheckXmlFileWithXercesValidatorInspection.java
new file mode 100644
index 0000000..8a664c5
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/CheckXmlFileWithXercesValidatorInspection.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.xml.util;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInspection.XmlSuppressableInspectionTool;
+import com.intellij.codeInspection.XmlInspectionGroupNames;
+import com.intellij.codeInspection.ex.UnfairLocalInspectionTool;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Maxim Mossienko
+ * @see com.intellij.xml.impl.ExternalDocumentValidator
+ */
+public class CheckXmlFileWithXercesValidatorInspection extends XmlSuppressableInspectionTool implements UnfairLocalInspectionTool {
+  public static final @NonNls String SHORT_NAME = "CheckXmlFileWithXercesValidator";
+
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+
+  @NotNull
+  public HighlightDisplayLevel getDefaultLevel() {
+    return HighlightDisplayLevel.ERROR;
+  }
+
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlInspectionGroupNames.XML_INSPECTIONS;
+  }
+
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("xml.inspections.check.file.with.xerces");
+  }
+
+  @NotNull
+  @NonNls
+  public String getShortName() {
+    return SHORT_NAME;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/util/ColorIconCache.java b/xml/impl/src/com/intellij/xml/util/ColorIconCache.java
new file mode 100644
index 0000000..15b3171
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/ColorIconCache.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.SoftFactoryMap;
+import com.intellij.util.containers.WeakFactoryMap;
+import com.intellij.util.ui.EmptyIcon;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Map;
+
+/**
+ * @author spleaner
+ */
+public class ColorIconCache {
+  private static final ColorIconCache INSTANCE = new ColorIconCache();
+  private static final SoftFactoryMap<Color, Map<Integer, Icon>> ourCache = new SoftFactoryMap<Color, Map<Integer, Icon>>() {
+    @Override
+    protected Map<Integer, Icon> create(Color key) {
+      return new HashMap<Integer, Icon>();
+    }
+  };
+
+  private ColorIconCache() {
+  }
+
+  public static ColorIconCache getIconCache() {
+    return INSTANCE;
+  }
+
+  @SuppressWarnings({"MethodMayBeStatic"})
+  public Icon getIcon(@NotNull final Color color, final int size) {
+    Icon icon = ourCache.get(color).get(size);
+    if (icon == null) {
+      icon = new ColorIcon(size, color);
+      ourCache.get(color).put(size, icon);
+    }
+
+    return icon;
+  }
+
+  public static class ColorIcon extends EmptyIcon {
+    private Color myColor;
+    private Color[] myColours;
+
+    public ColorIcon(final int size, final Color color) {
+      super(size);
+      myColor = color;
+    }
+
+    public ColorIcon(final int size, final Color[] colours) {
+      super(size);
+      myColours = colours;
+    }
+
+    @Override
+    public void paintIcon(final Component component, final Graphics g, final int i, final int j) {
+      final int iconWidth = getIconWidth();
+      final int iconHeight = getIconHeight();
+      if (myColor != null) {
+        g.setColor(myColor);
+        g.fillRect(i, j, iconWidth, iconHeight);
+      }
+      else if (myColours != null) {
+        final Color top = myColours[0];
+        g.setColor(top);
+        g.fillRect(i, j, iconWidth, 2);
+
+        final Color right = myColours[1];
+        g.setColor(right);
+        g.fillRect(i + iconWidth / 2, j + 2, iconWidth / 2, iconHeight / 2);
+
+        final Color bottom = myColours[2];
+        g.setColor(bottom);
+        g.fillRect(i, j + iconHeight - 2, iconWidth, 2);
+
+        final Color left = myColours[3];
+        g.setColor(left);
+        g.fillRect(i, j + 2, iconWidth / 2, iconHeight / 2);
+      }
+
+      final Composite old = ((Graphics2D)g).getComposite();
+      ((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f));
+      g.setColor(Color.BLACK);
+      g.drawRect(i, j, iconWidth-1, iconHeight-1);
+      ((Graphics2D)g).setComposite(old);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java b/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java
new file mode 100644
index 0000000..6f0cfe5
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java
@@ -0,0 +1,500 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.lookup.DeferredUserLookupValue;
+import com.intellij.codeInsight.lookup.LookupItem;
+import com.intellij.codeInsight.lookup.LookupValueWithPriority;
+import com.intellij.codeInsight.lookup.LookupValueWithUIHint;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Iconable;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.ui.ColorUtil;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+/**
+ * @author maxim
+ */
+public class ColorSampleLookupValue implements LookupValueWithUIHint, DeferredUserLookupValue, Iconable, LookupValueWithPriority {
+  private static volatile ColorSampleLookupValue[] ourColors;
+  private static Map<String, String> ourColorNameToHexCodeMap;
+  private static Map<String, String> ourHexCodeToColorNameMap;
+
+  @NonNls private static final String BR = "<br>";
+
+  @NonNls private static final String systemColorsString = "ActiveBorder\n" +
+                                                           "    Active window border.\n" +
+                                                           "ActiveCaption\n" +
+                                                           "    Active window caption.\n" +
+                                                           "AppWorkspace\n" +
+                                                           "    Background color of multiple document interface.\n" +
+                                                           "Background\n" +
+                                                           "    Desktop background.\n" +
+                                                           "ButtonFace\n" +
+                                                           "    Face color for three-dimensional display elements.\n" +
+                                                           "ButtonHighlight\n" +
+                                                           "    Highlight color for three-dimensional display elements (for edges facing away from the light source).\n" +
+                                                           "ButtonShadow\n" +
+                                                           "    Shadow color for three-dimensional display elements.\n" +
+                                                           "ButtonText\n" +
+                                                           "    Text on push buttons.\n" +
+                                                           "CaptionText\n" +
+                                                           "    Text in caption, size box, and scrollbar arrow box.\n" +
+                                                           "GrayText\n" +
+                                                           "    Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.\n" +
+                                                           "Highlight\n" +
+                                                           "    Item(s) selected in a control.\n" +
+                                                           "HighlightText\n" +
+                                                           "    Text of item(s) selected in a control.\n" +
+                                                           "InactiveBorder\n" +
+                                                           "    Inactive window border.\n" +
+                                                           "InactiveCaption\n" +
+                                                           "    Inactive window caption.\n" +
+                                                           "InactiveCaptionText\n" +
+                                                           "    Color of text in an inactive caption.\n" +
+                                                           "InfoBackground\n" +
+                                                           "    Background color for tooltip controls.\n" +
+                                                           "InfoText\n" +
+                                                           "    Text color for tooltip controls.\n" +
+                                                           "Menu\n" +
+                                                           "    Menu background.\n" +
+                                                           "MenuText\n" +
+                                                           "    Text in menus.\n" +
+                                                           "Scrollbar\n" +
+                                                           "    Scroll bar gray area.\n" +
+                                                           "ThreeDDarkShadow\n" +
+                                                           "    Dark shadow for three-dimensional display elements.\n" +
+                                                           "ThreeDFace\n" +
+                                                           "    Face color for three-dimensional display elements.\n" +
+                                                           "ThreeDHighlight\n" +
+                                                           "    Highlight color for three-dimensional display elements.\n" +
+                                                           "ThreeDLightShadow\n" +
+                                                           "    Light color for three-dimensional display elements (for edges facing the light source).\n" +
+                                                           "ThreeDShadow\n" +
+                                                           "    Dark shadow for three-dimensional display elements.\n" +
+                                                           "Window\n" +
+                                                           "    Window background.\n" +
+                                                           "WindowFrame\n" +
+                                                           "    Window frame.\n" +
+                                                           "WindowText\n" +
+                                                           "    Text in windows. ";
+  @NonNls private static final String standardColorsString = "maroon #800000 red #ff0000 orange #ffA500 yellow #ffff00 olive #808000\n" +
+                                                             "purple #800080 fuchsia #ff00ff white #ffffff lime #00ff00 green #008000\n" +
+                                                             "navy #000080 blue #0000ff aqua #00ffff teal #008080\n" +
+                                                             "black #000000 silver #c0c0c0 gray #808080";
+  @NonNls private static final String colorsString = "aliceblue \t#f0f8ff \t240,248,255\n" +
+                                                     "  \t  \tantiquewhite \t#faebd7 \t250,235,215\n" +
+                                                     "  \t  \taqua \t#00ffff \t0,255,255\n" +
+                                                     "  \t  \taquamarine \t#7fffd4 \t127,255,212\n" +
+                                                     "  \t  \tazure \t#f0ffff \t240,255,255\n" +
+                                                     "  \t  \tbeige \t#f5f5dc \t245,245,220\n" +
+                                                     "  \t  \tbisque \t#ffe4c4 \t255,228,196\n" +
+                                                     "  \t  \tblack \t#000000 \t0,0,0\n" +
+                                                     "  \t  \tblanchedalmond \t#ffebcd \t255,235,205\n" +
+                                                     "  \t  \tblue \t#0000ff \t0,0,255\n" +
+                                                     "  \t  \tblueviolet \t#8a2be2 \t138,43,226\n" +
+                                                     "  \t  \tbrown \t#a52a2a \t165,42,42\n" +
+                                                     "  \t  \tburlywood \t#deb887 \t222,184,135\n" +
+                                                     "  \t  \tcadetblue \t#5f9ea0 \t95,158,160\n" +
+                                                     "  \t  \tchartreuse \t#7fff00 \t127,255,0\n" +
+                                                     "  \t  \tchocolate \t#d2691e \t210,105,30\n" +
+                                                     "  \t  \tcoral \t#ff7f50 \t255,127,80\n" +
+                                                     "  \t  \tcornflowerblue \t#6495ed \t100,149,237\n" +
+                                                     "  \t  \tcornsilk \t#fff8dc \t255,248,220\n" +
+                                                     "  \t  \tcrimson \t#dc143c \t220,20,60\n" +
+                                                     "  \t  \tcyan \t#00ffff \t0,255,255\n" +
+                                                     "  \t  \tdarkblue \t#00008b \t0,0,139\n" +
+                                                     "  \t  \tdarkcyan \t#008b8b \t0,139,139\n" +
+                                                     "  \t  \tdarkgoldenrod \t#b8860b \t184,134,11\n" +
+                                                     "  \t  \tdarkgray \t#a9a9a9 \t169,169,169\n" +
+                                                     "  \t  \tdarkgrey \t#a9a9a9 \t169,169,169\n" +
+                                                     "  \t  \tdarkgreen \t#006400 \t0,100,0\n" +
+                                                     "  \t  \tdarkkhaki \t#bdb76b \t189,183,107\n" +
+                                                     "  \t  \tdarkmagenta \t#8b008b \t139,0,139\n" +
+                                                     "  \t  \tdarkolivegreen \t#556b2f \t85,107,47\n" +
+                                                     "  \t  \tdarkorange \t#ff8c00 \t255,140,0\n" +
+                                                     "  \t  \tdarkorchid \t#9932cc \t153,50,204\n" +
+                                                     "  \t  \tdarkred \t#8b0000 \t139,0,0\n" +
+                                                     "  \t  \tdarksalmon \t#e9967a \t233,150,122\n" +
+                                                     "  \t  \tdarkseagreen \t#8fbc8f \t143,188,143\n" +
+                                                     "  \t  \tdarkslateblue \t#483d8b \t72,61,139\n" +
+                                                     "  \t  \tdarkslategray \t#2f4f4f \t47,79,79\n" +
+                                                     "  \t  \tdarkslategrey \t#2f4f4f \t47,79,79\n" +
+                                                     "  \t  \tdarkturquoise \t#00ced1 \t0,206,209\n" +
+                                                     "  \t  \tdarkviolet \t#9400d3 \t148,0,211\n" +
+                                                     "  \t  \tdeeppink \t#ff1493 \t255,20,147\n" +
+                                                     "  \t  \tdeepskyblue \t#00bfff \t0,191,255\n" +
+                                                     "  \t  \tdimgray \t#696969 \t105,105,105\n" +
+                                                     "  \t  \tdimgrey \t#696969 \t105,105,105\n" +
+                                                     "  \t  \tdodgerblue \t#1e90ff \t30,144,255\n" +
+                                                     "  \t  \tfirebrick \t#b22222 \t178,34,34\n" +
+                                                     "  \t  \tfloralwhite \t#fffaf0 \t255,250,240\n" +
+                                                     "  \t  \tforestgreen \t#228b22 \t34,139,34\n" +
+                                                     "  \t  \tfuchsia \t#ff00ff \t255,0,255\n" +
+                                                     "  \t  \tgainsboro \t#dcdcdc \t220,220,220\n" +
+                                                     "  \t  \tghostwhite \t#f8f8ff \t248,248,255\n" +
+                                                     "  \t  \tgold \t#ffd700 \t255,215,0\n" +
+                                                     "  \t  \tgoldenrod \t#daa520 \t218,165,32\n" +
+                                                     "  \t  \tgray \t#808080 \t128,128,128\n" +
+                                                     "  \t  \tgrey \t#808080 \t128,128,128\n" +
+                                                     "  \t  \tgreen \t#008000 \t0,128,0\n" +
+                                                     "  \t  \tgreenyellow \t#adff2f \t173,255,47\n" +
+                                                     "  \t  \thoneydew \t#f0fff0 \t240,255,240\n" +
+                                                     "  \t  \thotpink \t#ff69b4 \t255,105,180\n" +
+                                                     "  \t  \tindianred \t#cd5c5c \t205,92,92\n" +
+                                                     "  \t  \tindigo \t#4b0082 \t75,0,130\n" +
+                                                     "  \t  \tivory \t#fffff0 \t255,255,240\n" +
+                                                     "  \t  \tkhaki \t#f0e68c \t240,230,140\n" +
+                                                     "  \t  \tlavender \t#e6e6fa \t230,230,250\n" +
+                                                     "  \t  \tlavenderblush \t#fff0f5 \t255,240,245\n" +
+                                                     "  \t  \tlawngreen \t#7cfc00 \t124,252,0\n" +
+                                                     "  \t  \tlemonchiffon \t#fffacd \t255,250,205\n" +
+                                                     "  \t  \tlightblue \t#add8e6 \t173,216,230\n" +
+                                                     "  \t  \tlightcoral \t#f08080 \t240,128,128\n" +
+                                                     "  \t  \tlightcyan \t#e0ffff \t224,255,255\n" +
+                                                     "  \t  \tlightgoldenrodyellow \t#fafad2 \t250,250,210\n" +
+                                                     "  \t  \tlightgray \t#d3d3d3 \t211,211,211\n" +
+                                                     "  \t  \tlightgrey \t#d3d3d3 \t211,211,211\n" +
+                                                     "  \t  \tlightgreen \t#90ee90 \t144,238,144\n" +
+                                                     "  \t  \tlightpink \t#ffb6c1 \t255,182,193\n" +
+                                                     "  \t  \tlightsalmon \t#ffa07a \t255,160,122\n" +
+                                                     "  \t  \tlightseagreen \t#20b2aa \t32,178,170\n" +
+                                                     "  \t  \tlightskyblue \t#87cefa \t135,206,250\n" +
+                                                     "  \t  \tlightslategray \t#778899 \t119,136,153\n" +
+                                                     "  \t  \tlightslategrey \t#778899 \t119,136,153\n" +
+                                                     "  \t  \tlightsteelblue \t#b0c4de \t176,196,222\n" +
+                                                     "  \t  \tlightyellow \t#ffffe0 \t255,255,224\n" +
+                                                     "  \t  \tlime \t#00ff00 \t0,255,0\n" +
+                                                     "  \t  \tlimegreen \t#32cd32 \t50,205,50\n" +
+                                                     "  \t  \tlinen \t#faf0e6 \t250,240,230\n" +
+                                                     "  \t  \tmagenta \t#ff00ff \t255,0,255\n" +
+                                                     "  \t  \tmaroon \t#800000 \t128,0,0\n" +
+                                                     "  \t  \tmediumaquamarine \t#66cdaa \t102,205,170\n" +
+                                                     "  \t  \tmediumblue \t#0000cd \t0,0,205\n" +
+                                                     "  \t  \tmediumorchid \t#ba55d3 \t186,85,211\n" +
+                                                     "  \t  \tmediumpurple \t#9370db \t147,112,219\n" +
+                                                     "  \t  \tmediumseagreen \t#3cb371 \t60,179,113\n" +
+                                                     "  \t  \tmediumslateblue \t#7b68ee \t123,104,238\n" +
+                                                     "  \t  \tmediumspringgreen \t#00fa9a \t0,250,154\n" +
+                                                     "  \t  \tmediumturquoise \t#48d1cc \t72,209,204\n" +
+                                                     "  \t  \tmediumvioletred \t#c71585 \t199,21,133\n" +
+                                                     "  \t  \tmidnightblue \t#191970 \t25,25,112\n" +
+                                                     "  \t  \tmintcream \t#f5fffa \t245,255,250\n" +
+                                                     "  \t  \tmistyrose \t#ffe4e1 \t255,228,225\n" +
+                                                     "  \t  \tmoccasin \t#ffe4b5 \t255,228,181\n" +
+                                                     "  \t  \tnavajowhite \t#ffdead \t255,222,173\n" +
+                                                     "  \t  \tnavy \t#000080 \t0,0,128\n" +
+                                                     "  \t  \toldlace \t#fdf5e6 \t253,245,230\n" +
+                                                     "  \t  \tolive \t#808000 \t128,128,0\n" +
+                                                     "  \t  \tolivedrab \t#6b8e23 \t107,142,35\n" +
+                                                     "  \t  \torange \t#ffa500 \t255,165,0\n" +
+                                                     "  \t  \torangered \t#ff4500 \t255,69,0\n" +
+                                                     "  \t  \torchid \t#da70d6 \t218,112,214\n" +
+                                                     "  \t  \tpalegoldenrod \t#eee8aa \t238,232,170\n" +
+                                                     "  \t  \tpalegreen \t#98fb98 \t152,251,152\n" +
+                                                     "  \t  \tpaleturquoise \t#afeeee \t175,238,238\n" +
+                                                     "  \t  \tpalevioletred \t#db7093 \t219,112,147\n" +
+                                                     "  \t  \tpapayawhip \t#ffefd5 \t255,239,213\n" +
+                                                     "  \t  \tpeachpuff \t#ffdab9 \t255,218,185\n" +
+                                                     "  \t  \tperu \t#cd853f \t205,133,63\n" +
+                                                     "  \t  \tpink \t#ffc0cb \t255,192,203\n" +
+                                                     "  \t  \tplum \t#dda0dd \t221,160,221\n" +
+                                                     "  \t  \tpowderblue \t#b0e0e6 \t176,224,230\n" +
+                                                     "  \t  \tpurple \t#800080 \t128,0,128\n" +
+                                                     "  \t  \tred \t#ff0000 \t255,0,0\n" +
+                                                     "  \t  \trosybrown \t#bc8f8f \t188,143,143\n" +
+                                                     "  \t  \troyalblue \t#4169e1 \t65,105,225\n" +
+                                                     "  \t  \tsaddlebrown \t#8b4513 \t139,69,19\n" +
+                                                     "  \t  \tsalmon \t#fa8072 \t250,128,114\n" +
+                                                     "  \t  \tsandybrown \t#f4a460 \t244,164,96\n" +
+                                                     "  \t  \tseagreen \t#2e8b57 \t46,139,87\n" +
+                                                     "  \t  \tseashell \t#fff5ee \t255,245,238\n" +
+                                                     "  \t  \tsienna \t#a0522d \t160,82,45\n" +
+                                                     "  \t  \tsilver \t#c0c0c0 \t192,192,192\n" +
+                                                     "  \t  \tskyblue \t#87ceeb \t135,206,235\n" +
+                                                     "  \t  \tslateblue \t#6a5acd \t106,90,205\n" +
+                                                     "  \t  \tslategray \t#708090 \t112,128,144\n" +
+                                                     "  \t  \tslategrey \t#708090 \t112,128,144\n" +
+                                                     "  \t  \tsnow \t#fffafa \t255,250,250\n" +
+                                                     "  \t  \tspringgreen \t#00ff7f \t0,255,127\n" +
+                                                     "  \t  \tsteelblue \t#4682b4 \t70,130,180\n" +
+                                                     "  \t  \ttan \t#d2b48c \t210,180,140\n" +
+                                                     "  \t  \tteal \t#008080 \t0,128,128\n" +
+                                                     "  \t  \tthistle \t#d8bfd8 \t216,191,216\n" +
+                                                     "  \t  \ttomato \t#ff6347 \t255,99,71\n" +
+                                                     "  \t  \tturquoise \t#40e0d0 \t64,224,208\n" +
+                                                     "  \t  \tviolet \t#ee82ee \t238,130,238\n" +
+                                                     "  \t  \twheat \t#f5deb3 \t245,222,179\n" +
+                                                     "  \t  \twhite \t#ffffff \t255,255,255\n" +
+                                                     "  \t  \twhitesmoke \t#f5f5f5 \t245,245,245\n" +
+                                                     "  \t  \tyellow \t#ffff00 \t255,255,0\n" +
+                                                     "  \t  \tyellowgreen \t#9acd32 \t154,205,50";
+  private final boolean myIsStandard;
+  private final String myName;
+  private final String myValue;
+  private Color myColor;
+  private static final ArrayList<String> ourSystemColors;
+  private static final List<String> ourStandardColors;
+
+  static {
+    ourSystemColors = new ArrayList<String>();
+    StringTokenizer tokenizer = new StringTokenizer(systemColorsString, "\n");
+
+    while (tokenizer.hasMoreTokens()) {
+      String name = tokenizer.nextToken();
+      ourSystemColors.add(name.toLowerCase());
+      tokenizer.nextToken();
+    }
+
+    ourStandardColors = new ArrayList<String>();
+    tokenizer = new StringTokenizer(standardColorsString, ", \n");
+    
+    while (tokenizer.hasMoreTokens()) {
+      String name = tokenizer.nextToken();
+      ourStandardColors.add(name);
+      tokenizer.nextToken();
+    }
+  }
+
+  public ColorSampleLookupValue(String name, String value, boolean isStandard) {
+    myName = name;
+    myValue = value;
+    myIsStandard = isStandard;
+  }
+
+  public String getPresentation() {
+    return myName != null ? myName : myValue;
+  }
+
+  public String getValue() {
+    return myValue;
+  }
+
+  public boolean isIsStandard() {
+    return myIsStandard;
+  }
+
+  public Icon getIcon(int flags) {
+    if (myColor == null) {
+      if (myValue.startsWith("#")) {
+        try {
+          myColor = Color.decode("0x" + myValue.substring(1));
+        }
+        catch (NumberFormatException e) {
+          return null;
+        }
+      }
+    }
+
+    if (myColor != null) {
+      return ColorIconCache.getIconCache().getIcon(myColor, 32);
+    }
+
+    return null;
+  }
+
+  public boolean handleUserSelection(LookupItem item, Project project) {
+    if (!myIsStandard) {
+      item.setLookupString(myValue);
+    }
+    return true;
+  }
+
+  public static boolean isSystemColorName(@NotNull @NonNls final String s) {
+    return ourSystemColors.contains(s);
+  }
+
+  public static boolean isStandardColor(@NotNull @NonNls final String s) {
+    return ourStandardColors.contains(s);
+  }
+
+  public static ColorSampleLookupValue[] getColors() {
+    if (ourColors == null) {
+      synchronized (ColorSampleLookupValue.class) {
+        if (ourColors == null) {
+          ourColorNameToHexCodeMap = new HashMap<String, String>(25);
+          ourHexCodeToColorNameMap = new HashMap<String, String>(25);
+          List<ColorSampleLookupValue> colorsList = new LinkedList<ColorSampleLookupValue>();
+          StringTokenizer tokenizer = new StringTokenizer(systemColorsString, "\n");
+
+          while (tokenizer.hasMoreTokens()) {
+            String name = tokenizer.nextToken();
+            colorsList.add(new ColorSampleLookupValue(name, name, false));
+            tokenizer.nextToken();
+          }
+
+          tokenizer = new StringTokenizer(standardColorsString, ", \n");
+          HashMap<String, String> standardColors = new HashMap<String, String>();
+
+          while (tokenizer.hasMoreTokens()) {
+            String name = tokenizer.nextToken();
+            String value = tokenizer.nextToken();
+            standardColors.put(name, name);
+            ourColorNameToHexCodeMap.put(name, value);
+            ourHexCodeToColorNameMap.put(value, name);
+
+            colorsList.add(new ColorSampleLookupValue(name, value, true));
+          }
+
+          tokenizer = new StringTokenizer(colorsString, " \t\n");
+
+          while (tokenizer.hasMoreTokens()) {
+            String name = tokenizer.nextToken();
+            String hexValue = tokenizer.nextToken();
+
+            tokenizer.nextToken(); // skip rgb
+
+            if (!standardColors.containsKey(name)) {
+              colorsList.add(new ColorSampleLookupValue(name, hexValue, false));
+              ourColorNameToHexCodeMap.put(name, hexValue);
+              ourHexCodeToColorNameMap.put(hexValue, name);
+            }
+          }
+
+          colorsList.toArray(ourColors = new ColorSampleLookupValue[colorsList.size()]);
+        }
+      }
+    }
+    return ourColors;
+  }
+
+  @Nullable
+  public String getTypeHint() {
+    return myValue != null && myValue.charAt(0) == '#' ? myValue : null;
+  }
+
+  @Nullable
+  public Color getColorHint() {
+    return null;
+  }
+
+  public boolean isBold() {
+    return false;
+  }
+
+  public String getName() {
+    return myName;
+  }
+
+  public int getPriority() {
+    return myName == null || Character.isLowerCase(myName.charAt(0)) ? HIGHER : NORMAL;
+  }
+
+  public static synchronized String getHexCodeForColorName(String colorName) {
+    getColors(); // to guarantee initialization
+    return ourColorNameToHexCodeMap.get(colorName);
+  }
+
+  public static synchronized String getColorNameForHexCode(String colorName) {
+    getColors(); // to guarantee initialization
+    return ourHexCodeToColorNameMap.get(colorName);
+  }
+
+  public static void addColorPreviewAndCodeToLookup(final PsiElement currentElement, final StringBuilder buf) {
+    final Color colorFromElement = UserColorLookup.getColorFromElement(currentElement);
+
+    if (colorFromElement != null) {
+      addColorPreviewAndCodeToLookup(colorFromElement, buf);
+    }
+  }
+
+  private static String toHex(@NotNull final Color color) {
+    final StringBuilder sb = new StringBuilder();
+    for (int i = 0; i < 3; i++) {
+      String s = Integer.toHexString(i == 0 ? color.getRed() : i == 1 ? color.getGreen() : color.getBlue());
+      if (s.length() < 2) {
+        sb.append('0');
+      }
+
+      sb.append(s);
+    }
+
+    return sb.toString();
+  }
+
+  public static void addColorPreviewAndCodeToLookup(final Color color, final StringBuilder buf) {
+    if (color == null) return;
+    final String code = '#' + toHex(color);
+    final String colorName = getColorNameForHexCode(code);
+    if (colorName != null) {
+      buf.append(XmlBundle.message("color.name", colorName)).append(BR);
+    }
+
+    String colorBox = "<div style=\"border: 1px solid #000000; width: 50px; height: 20px; background-color:" + code + "\"></div>";
+    buf.append(XmlBundle.message("color.preview", colorBox)).append(BR);
+  }
+
+  public static Color getColor(String text) {
+    if (StringUtil.isEmptyOrSpaces(text)) {
+      return null;
+    }
+    String hexValue = text.charAt(0) == '#' ? text : getHexCodeForColorName(text.toLowerCase());
+    if (hexValue != null) {
+      return ColorUtil.fromHex(hexValue, null);
+    }
+    return null;
+  }
+
+  @Override
+  public String toString() {
+    return myName == null ? myValue : myValue + " " + myName;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof ColorSampleLookupValue)) {
+      return false;
+    }
+
+    ColorSampleLookupValue value = (ColorSampleLookupValue)o;
+
+    if (myIsStandard != value.myIsStandard) {
+      return false;
+    }
+    if (myColor != null ? !myColor.equals(value.myColor) : value.myColor != null) {
+      return false;
+    }
+    if (myName != null ? !myName.equals(value.myName) : value.myName != null) {
+      return false;
+    }
+    if (myValue != null ? !myValue.equals(value.myValue) : value.myValue != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = (myIsStandard ? 1 : 0);
+    result = 31 * result + (myName != null ? myName.hashCode() : 0);
+    result = 31 * result + (myValue != null ? myValue.hashCode() : 0);
+    result = 31 * result + (myColor != null ? myColor.hashCode() : 0);
+    return result;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/HtmlDoctypeProvider.java b/xml/impl/src/com/intellij/xml/util/HtmlDoctypeProvider.java
new file mode 100644
index 0000000..003bcf6
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/HtmlDoctypeProvider.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.impl.source.html.HtmlFileImpl;
+import com.intellij.psi.xml.XmlDoctype;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlElementDescriptor;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author traff
+ */
+public interface HtmlDoctypeProvider {
+  ExtensionPointName<HtmlDoctypeProvider> EP_NAME = ExtensionPointName.create("com.intellij.xml.util.htmlDoctypeProvider");
+
+
+  @Nullable
+  XmlDoctype getDoctype(XmlFile file);
+}
diff --git a/xml/impl/src/com/intellij/xml/util/HtmlUtil.java b/xml/impl/src/com/intellij/xml/util/HtmlUtil.java
new file mode 100644
index 0000000..653ad70
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/HtmlUtil.java
@@ -0,0 +1,646 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInspection.InspectionProfile;
+import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.codeInspection.htmlInspections.HtmlUnknownAttributeInspection;
+import com.intellij.codeInspection.htmlInspections.HtmlUnknownTagInspection;
+import com.intellij.codeInspection.htmlInspections.XmlEntitiesInspection;
+import com.intellij.ide.highlighter.HtmlFileType;
+import com.intellij.javaee.ExternalResourceManagerEx;
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.*;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.impl.source.html.HtmlDocumentImpl;
+import com.intellij.psi.impl.source.parsing.xml.HtmlBuilderDriver;
+import com.intellij.psi.impl.source.parsing.xml.XmlBuilder;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.psi.impl.source.xml.XmlAttributeImpl;
+import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
+import com.intellij.psi.templateLanguages.TemplateLanguageUtil;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.Html5SchemaProvider;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.impl.schema.XmlAttributeDescriptorImpl;
+import com.intellij.xml.impl.schema.XmlElementDescriptorImpl;
+import com.intellij.xml.util.documentation.HtmlDescriptorsTable;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class HtmlUtil {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.HtmlUtil");
+
+  @NonNls private static final String JSFC = "jsfc";
+  @NonNls private static final String CHARSET_PREFIX = "charset=";
+  @NonNls private static final String HTML5_DATA_ATTR_PREFIX = "data-";
+
+  public static final String[] CONTENT_TYPES =
+    {"application/activemessage", "application/andrew-inset", "application/applefile", "application/atomicmail", "application/dca-rft",
+      "application/dec-dx", "application/mac-binhex40"
+      , "application/mac-compactpro", "application/macwriteii", "application/msword", "application/news-message-id",
+      "application/news-transmission", "application/octet-stream"
+      , "application/oda", "application/pdf", "application/postscript", "application/powerpoint", "application/remote-printing",
+      "application/rtf"
+      , "application/slate", "application/wita", "application/wordperfect5.1", "application/x-bcpio", "application/x-cdlink",
+      "application/x-compress"
+      , "application/x-cpio", "application/x-csh", "application/x-director", "application/x-dvi", "application/x-gtar", "application/x-gzip"
+      , "application/x-hdf", "application/x-httpd-cgi", "application/x-koan", "application/x-latex", "application/x-mif",
+      "application/x-netcdf"
+      , "application/x-sh", "application/x-shar", "application/x-stuffit", "application/x-sv4cpio", "application/x-sv4crc",
+      "application/x-tar"
+      , "application/x-tcl", "application/x-tex", "application/x-texinfo", "application/x-troff", "application/x-troff-man",
+      "application/x-troff-me"
+      , "application/x-troff-ms", "application/x-ustar", "application/x-wais-source", "application/zip", "audio/basic", "audio/mpeg"
+      , "audio/x-aiff", "audio/x-pn-realaudio", "audio/x-pn-realaudio-plugin", "audio/x-realaudio", "audio/x-wav", "chemical/x-pdb"
+      , "image/gif", "image/ief", "image/jpeg", "image/png", "image/tiff", "image/x-cmu-raster"
+      , "image/x-portable-anymap", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap", "image/x-rgb",
+      "image/x-xbitmap"
+      , "image/x-xpixmap", "image/x-xwindowdump", "message/external-body", "message/news", "message/partial", "message/rfc822"
+      , "multipart/alternative", "multipart/appledouble", "multipart/digest", "multipart/mixed", "multipart/parallel", "text/html"
+      , "text/plain", "text/richtext", "text/tab-separated-values", "text/x-setext", "text/x-sgml", "video/mpeg"
+      , "video/quicktime", "video/x-msvideo", "video/x-sgi-movie", "x-conference/x-cooltalk", "x-world/x-vrml"};
+  @NonNls public static final String LINK = "link";
+
+  @NonNls public static final String MATH_ML_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
+  @NonNls public static final String SVG_NAMESPACE = "http://www.w3.org/2000/svg";
+
+  private HtmlUtil() {
+  }
+
+  @NonNls private static final String[] EMPTY_TAGS = {
+    "base", "hr", "meta", "link", "frame", "br", "basefont", "param", "img", "area", "input", "isindex", "col", /*html 5*/ "source", "wbr"
+  };
+  private static final Set<String> EMPTY_TAGS_MAP = new THashSet<String>();
+  @NonNls private static final String[] OPTIONAL_END_TAGS = {
+    //"html",
+    "head",
+    //"body",
+    "p", "li", "dd", "dt", "thead", "tfoot", "tbody", "colgroup", "tr", "th", "td", "option", "embed", "noembed"
+  };
+  private static final Set<String> OPTIONAL_END_TAGS_MAP = new THashSet<String>();
+
+  @NonNls private static final String[] BLOCK_TAGS = {"p", "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol", "dir", "menu", "pre",
+    "dl", "div", "center", "noscript", "noframes", "blockquote", "form", "isindex", "hr", "table", "fieldset", "address",
+    // nonexplicitly specified
+    "map",
+    // flow elements
+    "body", "object", "applet", "ins", "del", "dd", "li", "button", "th", "td", "iframe", "comment", "nobr"
+  };
+
+  // flow elements are block or inline, so they shuld not close <p> for example
+  @NonNls private static final String[] POSSIBLY_INLINE_TAGS = {"object", "applet", "ins", "del", "button", "nobr"};
+
+  private static final Set<String> BLOCK_TAGS_MAP = new THashSet<String>();
+
+  @NonNls private static final String[] INLINE_ELEMENTS_CONTAINER = {"p", "h1", "h2", "h3", "h4", "h5", "h6", "pre", "dt"};
+  private static final Set<String> INLINE_ELEMENTS_CONTAINER_MAP = new THashSet<String>();
+
+  @NonNls private static final String[] EMPTY_ATTRS =
+    {"nowrap", "compact", "disabled", "readonly", "selected", "multiple", "nohref", "ismap", "declare", "noshade", "checked"};
+  private static final Set<String> EMPTY_ATTRS_MAP = new THashSet<String>();
+
+  private static final Set<String> POSSIBLY_INLINE_TAGS_MAP = new THashSet<String>();
+
+  @NonNls private static final String[] HTML5_TAGS = {
+    "article", "aside", "audio", "canvas", "command", "datalist", "details", "embed", "figcaption", "figure", "footer", "header", "hgroup",
+    "keygen", "mark", "meter", "nav", "output", "progress", "rp", "rt", "ruby", "section", "source", "summary", "time", "video", "wbr"
+  };
+  private static final Set<String> HTML5_TAGS_SET = new THashSet<String>();
+
+  static {
+    ContainerUtil.addAll(EMPTY_TAGS_MAP, EMPTY_TAGS);
+    ContainerUtil.addAll(EMPTY_ATTRS_MAP, EMPTY_ATTRS);
+    ContainerUtil.addAll(OPTIONAL_END_TAGS_MAP, OPTIONAL_END_TAGS);
+    ContainerUtil.addAll(BLOCK_TAGS_MAP, BLOCK_TAGS);
+    ContainerUtil.addAll(INLINE_ELEMENTS_CONTAINER_MAP, INLINE_ELEMENTS_CONTAINER);
+    ContainerUtil.addAll(POSSIBLY_INLINE_TAGS_MAP, POSSIBLY_INLINE_TAGS);
+    ContainerUtil.addAll(HTML5_TAGS_SET, HTML5_TAGS);
+  }
+
+  public static boolean isSingleHtmlTag(String tagName) {
+    return EMPTY_TAGS_MAP.contains(tagName.toLowerCase());
+  }
+
+  public static boolean isSingleHtmlTagL(String tagName) {
+    return EMPTY_TAGS_MAP.contains(tagName);
+  }
+
+  public static boolean isOptionalEndForHtmlTag(String tagName) {
+    return OPTIONAL_END_TAGS_MAP.contains(tagName.toLowerCase());
+  }
+
+  public static boolean isOptionalEndForHtmlTagL(String tagName) {
+    return OPTIONAL_END_TAGS_MAP.contains(tagName);
+  }
+
+  public static boolean isSingleHtmlAttribute(String attrName) {
+    return EMPTY_ATTRS_MAP.contains(attrName.toLowerCase());
+  }
+
+  public static boolean isHtmlBlockTag(String tagName) {
+    return BLOCK_TAGS_MAP.contains(tagName.toLowerCase());
+  }
+
+  public static boolean isPossiblyInlineTag(String tagName) {
+    return POSSIBLY_INLINE_TAGS_MAP.contains(tagName);
+  }
+
+  public static boolean isHtmlBlockTagL(String tagName) {
+    return BLOCK_TAGS_MAP.contains(tagName);
+  }
+
+  public static boolean isInlineTagContainer(String tagName) {
+    return INLINE_ELEMENTS_CONTAINER_MAP.contains(tagName.toLowerCase());
+  }
+
+  public static boolean isInlineTagContainerL(String tagName) {
+    return INLINE_ELEMENTS_CONTAINER_MAP.contains(tagName);
+  }
+
+  public static void addHtmlSpecificCompletions(final XmlElementDescriptor descriptor,
+                                                final XmlTag element,
+                                                final List<XmlElementDescriptor> variants) {
+    // add html block completions for tags with optional ends!
+    String name = descriptor.getName(element);
+
+    if (name != null && isOptionalEndForHtmlTag(name)) {
+      PsiElement parent = element.getParent();
+
+      if (parent != null) {
+        // we need grand parent since completion already uses parent's descriptor
+        parent = parent.getParent();
+      }
+
+      if (parent instanceof HtmlTag) {
+        final XmlElementDescriptor parentDescriptor = ((HtmlTag)parent).getDescriptor();
+
+        if (parentDescriptor != descriptor && parentDescriptor != null) {
+          for (final XmlElementDescriptor elementsDescriptor : parentDescriptor.getElementsDescriptors((XmlTag)parent)) {
+            if (isHtmlBlockTag(elementsDescriptor.getName())) {
+              variants.add(elementsDescriptor);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  @Nullable
+  public static XmlDocument getRealXmlDocument(@Nullable XmlDocument doc) {
+    if (doc == null) return null;
+    final PsiFile containingFile = doc.getContainingFile();
+
+    final PsiFile templateFile = TemplateLanguageUtil.getTemplateFile(containingFile);
+    if (templateFile instanceof XmlFile) {
+      return ((XmlFile)templateFile).getDocument();
+    }
+    return doc;
+  }
+
+  public static String[] getHtmlTagNames() {
+    return HtmlDescriptorsTable.getHtmlTagNames();
+  }
+
+  public static XmlAttributeDescriptor[] getCustomAttributeDescriptors(XmlElement context) {
+    String entitiesString = getEntitiesString(context, XmlEntitiesInspection.UNKNOWN_ATTRIBUTE);
+    if (entitiesString == null) return XmlAttributeDescriptor.EMPTY;
+
+    StringTokenizer tokenizer = new StringTokenizer(entitiesString, ",");
+    XmlAttributeDescriptor[] descriptors = new XmlAttributeDescriptor[tokenizer.countTokens()];
+    int index = 0;
+
+    while (tokenizer.hasMoreElements()) {
+      final String customName = tokenizer.nextToken();
+      if (customName.length() == 0) continue;
+
+      descriptors[index++] = new XmlAttributeDescriptorImpl() {
+        public String getName(PsiElement context) {
+          return customName;
+        }
+
+        public String getName() {
+          return customName;
+        }
+      };
+    }
+
+    return descriptors;
+  }
+
+  public static XmlElementDescriptor[] getCustomTagDescriptors(XmlElement context) {
+    String entitiesString = getEntitiesString(context, XmlEntitiesInspection.UNKNOWN_TAG);
+    if (entitiesString == null) return XmlElementDescriptor.EMPTY_ARRAY;
+
+    StringTokenizer tokenizer = new StringTokenizer(entitiesString, ",");
+    XmlElementDescriptor[] descriptors = new XmlElementDescriptor[tokenizer.countTokens()];
+    int index = 0;
+
+    while (tokenizer.hasMoreElements()) {
+      final String tagName = tokenizer.nextToken();
+      if (tagName.length() == 0) continue;
+
+      descriptors[index++] = new XmlElementDescriptorImpl(context instanceof XmlTag ? (XmlTag)context : null) {
+        public String getName(PsiElement context) {
+          return tagName;
+        }
+
+        public String getDefaultName() {
+          return tagName;
+        }
+
+        public boolean allowElementsFromNamespace(final String namespace, final XmlTag context) {
+          return true;
+        }
+      };
+    }
+
+    return descriptors;
+  }
+
+  @Nullable
+  public static String getEntitiesString(XmlElement context, int type) {
+    if (context == null) return null;
+    PsiFile containingFile = context.getContainingFile().getOriginalFile();
+
+    final InspectionProfile profile = InspectionProjectProfileManager.getInstance(context.getProject()).getInspectionProfile();
+
+    switch (type) {
+      case XmlEntitiesInspection.UNKNOWN_TAG:
+        LocalInspectionToolWrapper wrapper = (LocalInspectionToolWrapper)profile.getInspectionTool(HtmlUnknownTagInspection.TAG_SHORT_NAME,
+                                                                                                   containingFile);
+        HtmlUnknownTagInspection unknownTagInspection = wrapper != null ? (HtmlUnknownTagInspection)wrapper.getTool() : null;
+        if (unknownTagInspection != null) {
+          return unknownTagInspection.getAdditionalEntries();
+        }
+        break;
+      case XmlEntitiesInspection.UNKNOWN_ATTRIBUTE:
+        LocalInspectionToolWrapper wrapper1 =
+          (LocalInspectionToolWrapper)profile.getInspectionTool(HtmlUnknownAttributeInspection.ATTRIBUTE_SHORT_NAME,
+                                                                containingFile);
+        HtmlUnknownAttributeInspection unknownAttributeInspection =
+          wrapper1 != null ? (HtmlUnknownAttributeInspection)wrapper1.getTool() : null;
+        if (unknownAttributeInspection != null) {
+          return unknownAttributeInspection.getAdditionalEntries();
+        }
+        break;
+    }
+
+    return null;
+  }
+
+  public static XmlAttributeDescriptor[] appendHtmlSpecificAttributeCompletions(final XmlTag declarationTag,
+                                                                                XmlAttributeDescriptor[] descriptors,
+                                                                                final XmlAttributeImpl context) {
+    if (declarationTag instanceof HtmlTag) {
+      descriptors = ArrayUtil.mergeArrays(
+        descriptors,
+        getCustomAttributeDescriptors(context)
+      );
+      return descriptors;
+    }
+
+    if (declarationTag.getPrefixByNamespace(XmlUtil.JSF_HTML_URI) != null &&
+        declarationTag.getNSDescriptor(XmlUtil.XHTML_URI, true) != null &&
+        !XmlUtil.JSP_URI.equals(declarationTag.getNamespace())) {
+
+      descriptors = ArrayUtil.append(
+        descriptors,
+        new XmlAttributeDescriptorImpl() {
+          public String getName(PsiElement context) {
+            return JSFC;
+          }
+
+          public String getName() {
+            return JSFC;
+          }
+        }
+      );
+    }
+    return descriptors;
+  }
+
+  public static boolean isHtml5Document(XmlDocument doc) {
+    if (doc == null) {
+      return false;
+    }
+    XmlProlog prolog = doc.getProlog();
+    XmlDoctype doctype = prolog != null ? prolog.getDoctype() : null;
+    if (!isHtmlTagContainingFile(doc)) {
+      return false;
+    }
+
+    final PsiFile htmlFile = doc.getContainingFile();
+
+    final String htmlFileFullName;
+    if (htmlFile != null) {
+      final VirtualFile vFile = htmlFile.getVirtualFile();
+      if (vFile != null) {
+        htmlFileFullName = vFile.getPath();
+      }
+      else {
+        htmlFileFullName = htmlFile.getName();
+      }
+    }
+    else {
+      htmlFileFullName = "unknown";
+    }
+
+    if (doctype == null) {
+      LOG.debug("DOCTYPE for " + htmlFileFullName + " is null");
+      return Html5SchemaProvider.HTML5_SCHEMA_LOCATION
+        .equals(ExternalResourceManagerEx.getInstanceEx().getDefaultHtmlDoctype(doc.getProject()));
+    }
+
+    final boolean html5Doctype = isHtml5Doctype(doctype);
+    final String doctypeDescription = "text: " + doctype.getText() +
+                                      ", dtdUri: " + doctype.getDtdUri() +
+                                      ", publicId: " + doctype.getPublicId() +
+                                      ", markupDecl: " + doctype.getMarkupDecl();
+    LOG.debug("DOCTYPE for " + htmlFileFullName + "; " + doctypeDescription + "; HTML5: " + html5Doctype);
+    return html5Doctype;
+  }
+
+  public static boolean isHtml5Doctype(XmlDoctype doctype) {
+    return doctype.getDtdUri() == null && doctype.getPublicId() == null && doctype.getMarkupDecl() == null;
+  }
+
+  public static boolean isHtml5Context(XmlElement context) {
+    XmlDocument doc = PsiTreeUtil.getParentOfType(context, XmlDocument.class);
+    return isHtml5Document(doc);
+  }
+
+  public static boolean hasNonHtml5Doctype(XmlElement context) {
+    XmlDocument doc = PsiTreeUtil.getParentOfType(context, XmlDocument.class);
+    if (doc == null) {
+      return false;
+    }
+    XmlProlog prolog = doc.getProlog();
+    XmlDoctype doctype = prolog != null ? prolog.getDoctype() : null;
+    return doctype != null && !isHtml5Doctype(doctype);
+  }
+
+  public static boolean isHtml5Tag(String tagName) {
+    return HTML5_TAGS_SET.contains(tagName);
+  }
+
+  public static boolean isCustomHtml5Attribute(String attributeName) {
+    return attributeName.startsWith(HTML5_DATA_ATTR_PREFIX);
+  }
+
+  public static void processLinks(@NotNull final XmlFile xhtmlFile,
+                                  @NotNull Processor<XmlTag> tagProcessor) {
+    final XmlDocument doc = getRealXmlDocument(xhtmlFile.getDocument());
+    if (doc == null) return;
+
+    final XmlTag rootTag = doc.getRootTag();
+    if (rootTag == null) return;
+
+    if (LINK.equalsIgnoreCase(rootTag.getName())) {
+      tagProcessor.process(rootTag);
+    }
+    else {
+      findLinkStylesheets(rootTag, tagProcessor);
+    }
+  }
+
+  public static void findLinkStylesheets(@NotNull final XmlTag tag,
+                                         @NotNull Processor<XmlTag> tagProcessor) {
+    processInjectedContent(tag, tagProcessor);
+
+    for (XmlTag subTag : tag.getSubTags()) {
+      findLinkStylesheets(subTag, tagProcessor);
+    }
+
+    if (LINK.equalsIgnoreCase(tag.getName())) {
+      tagProcessor.process(tag);
+    }
+  }
+
+  public static void processInjectedContent(final XmlTag element,
+                                            @NotNull final Processor<XmlTag> tagProcessor) {
+    final PsiLanguageInjectionHost.InjectedPsiVisitor injectedPsiVisitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {
+      public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
+        if (injectedPsi instanceof XmlFile) {
+          final XmlDocument injectedDocument = ((XmlFile)injectedPsi).getDocument();
+          if (injectedDocument != null) {
+            final XmlTag rootTag = injectedDocument.getRootTag();
+            if (rootTag != null) {
+              for (PsiElement element = rootTag; element != null; element = element.getNextSibling()) {
+                if (element instanceof XmlTag) {
+                  final XmlTag tag = (XmlTag)element;
+                  String tagName = tag.getLocalName();
+                  if (element instanceof HtmlTag || tag.getNamespacePrefix().length() > 0) tagName = tagName.toLowerCase();
+                  if (LINK.equalsIgnoreCase(tagName)) {
+                    tagProcessor.process((XmlTag)element);
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    };
+
+    final XmlText[] texts = PsiTreeUtil.getChildrenOfType(element, XmlText.class);
+    if (texts != null && texts.length > 0) {
+      for (final XmlText text : texts) {
+        for (PsiElement _element : text.getChildren()) {
+          if (_element instanceof PsiLanguageInjectionHost) {
+            InjectedLanguageUtil.enumerate(_element, injectedPsiVisitor);
+          }
+        }
+      }
+    }
+
+    final XmlComment[] comments = PsiTreeUtil.getChildrenOfType(element, XmlComment.class);
+    if (comments != null && comments.length > 0) {
+      for (final XmlComment comment : comments) {
+        if (comment instanceof PsiLanguageInjectionHost) {
+          InjectedLanguageUtil.enumerate(comment, injectedPsiVisitor);
+        }
+      }
+    }
+  }
+
+  private static class TerminateException extends RuntimeException {
+    private static final TerminateException INSTANCE = new TerminateException();
+  }
+
+  public static Charset detectCharsetFromMetaHttpEquiv(@NotNull String content) {
+    final Ref<String> charsetNameRef = new Ref<String>();
+    try {
+      new HtmlBuilderDriver(content).build(new XmlBuilder() {
+        @NonNls final Set<String> inTag = new THashSet<String>();
+        boolean metHttpEquiv = false;
+
+        public void doctype(@Nullable final CharSequence publicId,
+                            @Nullable final CharSequence systemId,
+                            final int startOffset,
+                            final int endOffset) {
+        }
+
+        public ProcessingOrder startTag(final CharSequence localName, final String namespace, final int startoffset, final int endoffset,
+                                        final int headerEndOffset) {
+          @NonNls String name = localName.toString().toLowerCase();
+          inTag.add(name);
+          if (!inTag.contains("head") && !"html".equals(name)) terminate();
+          return ProcessingOrder.TAGS_AND_ATTRIBUTES;
+        }
+
+        private void terminate() {
+          throw TerminateException.INSTANCE;
+        }
+
+        public void endTag(final CharSequence localName, final String namespace, final int startoffset, final int endoffset) {
+          @NonNls final String name = localName.toString().toLowerCase();
+          if ("meta".equals(name) && metHttpEquiv && contentAttributeValue != null) {
+            int start = contentAttributeValue.indexOf(CHARSET_PREFIX);
+            if (start == -1) return;
+            start += CHARSET_PREFIX.length();
+            int end = contentAttributeValue.indexOf(';', start);
+            if (end == -1) end = contentAttributeValue.length();
+            String charsetName = contentAttributeValue.substring(start, end);
+            charsetNameRef.set(charsetName);
+            terminate();
+          }
+          if ("head".equals(name)) {
+            terminate();
+          }
+          inTag.remove(name);
+          metHttpEquiv = false;
+          contentAttributeValue = null;
+        }
+
+        private String contentAttributeValue;
+
+        public void attribute(final CharSequence localName, final CharSequence v, final int startoffset, final int endoffset) {
+          @NonNls final String name = localName.toString().toLowerCase();
+          if (inTag.contains("meta")) {
+            @NonNls String value = v.toString().toLowerCase();
+            if (name.equals("http-equiv")) {
+              metHttpEquiv |= value.equals("content-type");
+            }
+            if (name.equals("content")) {
+              contentAttributeValue = value;
+            }
+          }
+        }
+
+        public void textElement(final CharSequence display, final CharSequence physical, final int startoffset, final int endoffset) {
+        }
+
+        public void entityRef(final CharSequence ref, final int startOffset, final int endOffset) {
+        }
+
+        public void error(String message, int startOffset, int endOffset) {
+        }
+      });
+    }
+    catch (TerminateException e) {
+      //ignore
+    }
+    catch (Exception e) {
+      // some weird things can happen, like unbalanaced tree
+    }
+
+    String name = charsetNameRef.get();
+    return CharsetToolkit.forName(name);
+  }
+
+  public static boolean isTagWithoutAttributes(@NonNls String tagName) {
+    return tagName != null && "br".equalsIgnoreCase(tagName);
+  }
+
+  public static boolean hasHtml(PsiFile file) {
+    return isHtmlFile(file) || file.getViewProvider() instanceof TemplateLanguageFileViewProvider;
+  }
+
+  public static boolean isHtmlFile(PsiElement element) {
+    Language language = element.getLanguage();
+    return language == HTMLLanguage.INSTANCE || language == XHTMLLanguage.INSTANCE;
+  }
+
+  public static boolean isHtmlTagContainingFile(PsiElement element) {
+    if (element == null) {
+      return false;
+    }
+    final PsiFile containingFile = element.getContainingFile();
+    if (containingFile != null) {
+      final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class, false);
+      if (tag instanceof HtmlTag) {
+        return true;
+      }
+      final XmlDocument document = PsiTreeUtil.getParentOfType(element, XmlDocument.class, false);
+      if (document instanceof HtmlDocumentImpl) {
+        return true;
+      }
+      final FileViewProvider provider = containingFile.getViewProvider();
+      Language language;
+      if (provider instanceof TemplateLanguageFileViewProvider) {
+        language = ((TemplateLanguageFileViewProvider)provider).getTemplateDataLanguage();
+      }
+      else {
+        language = provider.getBaseLanguage();
+      }
+
+      return language == XHTMLLanguage.INSTANCE;
+    }
+    return false;
+  }
+
+  public static boolean isHtmlTagContainingFile(final Editor editor, final PsiFile file) {
+    if (editor == null || file == null || !(file instanceof XmlFile)) {
+      return false;
+    }
+    final int offset = editor.getCaretModel().getOffset();
+    final PsiElement element = file.findElementAt(offset);
+    return isHtmlTagContainingFile(element);
+  }
+
+  public static boolean isPureHtmlFile(@NotNull PsiFile file) {
+    FileType fileTypeByName = FileTypeManager.getInstance().getFileTypeByFileName(file.getName());
+    return file.getLanguage() == HTMLLanguage.INSTANCE &&
+        fileTypeByName == HtmlFileType.INSTANCE &&
+        !(file.getViewProvider() instanceof MultiplePsiFilesPerDocumentFileViewProvider);
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/util/IncludedXmlAttribute.java b/xml/impl/src/com/intellij/xml/util/IncludedXmlAttribute.java
new file mode 100644
index 0000000..988b7d0
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/IncludedXmlAttribute.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlAttributeDescriptor;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author peter
+ */
+public class IncludedXmlAttribute extends IncludedXmlElement<XmlAttribute> implements XmlAttribute {
+
+  public IncludedXmlAttribute(@NotNull XmlAttribute original, @Nullable XmlTag parent) {
+    super(original, parent);
+  }
+
+  @Override
+  @NonNls
+  @NotNull
+  public String getName() {
+    return getOriginal().getName();
+  }
+
+  @Override
+  public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
+    throw new UnsupportedOperationException("Can't modify included elements");
+  }
+
+  @NonNls
+  @NotNull
+  public String getLocalName() {
+    return getOriginal().getLocalName();
+  }
+
+  @NonNls
+  @NotNull
+  public String getNamespace() {
+    return getOriginal().getNamespace();
+  }
+
+  @NonNls
+  @NotNull
+  public String getNamespacePrefix() {
+    return getOriginal().getNamespacePrefix();
+  }
+
+  public XmlTag getParent() {
+    return (XmlTag)super.getParent();
+  }
+
+  public String getValue() {
+    return getOriginal().getValue();
+  }
+
+  public String getDisplayValue() {
+    return getOriginal().getDisplayValue();
+  }
+
+  public int physicalToDisplay(int offset) {
+    return getOriginal().physicalToDisplay(offset);
+  }
+
+  public int displayToPhysical(int offset) {
+    return getOriginal().displayToPhysical(offset);
+  }
+
+  public TextRange getValueTextRange() {
+    return getOriginal().getValueTextRange();
+  }
+
+  public boolean isNamespaceDeclaration() {
+    return getOriginal().isNamespaceDeclaration();
+  }
+
+  @Nullable
+  public XmlAttributeDescriptor getDescriptor() {
+    return getOriginal().getDescriptor();
+  }
+
+  @Nullable
+  public XmlAttributeValue getValueElement() {
+    return getOriginal().getValueElement();
+  }
+
+  public void setValue(String value) throws IncorrectOperationException {
+    throw new UnsupportedOperationException("Can't modify included elements");
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/IncludedXmlElement.java b/xml/impl/src/com/intellij/xml/util/IncludedXmlElement.java
new file mode 100644
index 0000000..ed92f43
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/IncludedXmlElement.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.psi.PsiAnchor;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiInvalidElementAccessException;
+import com.intellij.psi.impl.light.LightElement;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlText;
+import com.intellij.reference.SoftReference;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author peter
+ */
+public abstract class IncludedXmlElement<T extends XmlElement> extends LightElement implements XmlElement {
+  private final PsiAnchor myOriginal;
+  private SoftReference<T> myRef;
+  private final PsiElement myParent;
+
+  public IncludedXmlElement(@NotNull T original, @Nullable PsiElement parent) {
+    super(original.getManager(), original.getLanguage());
+    //noinspection unchecked
+    T realOriginal = original instanceof IncludedXmlElement ? ((IncludedXmlElement<T>)original).getOriginal() : original;
+    myOriginal = PsiAnchor.create(realOriginal);
+    myRef = new SoftReference<T>(realOriginal);
+    myParent = parent;
+  }
+
+  @Override
+  public boolean isValid() {
+    T t = myRef.get();
+    if (t != null) {
+      return t.isValid();
+    }
+
+    return myOriginal.retrieve() != null;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    IncludedXmlElement element = (IncludedXmlElement)o;
+
+    if (!myParent.equals(element.myParent)) return false;
+    if (!myOriginal.equals(element.myOriginal)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myOriginal.hashCode();
+    result = 31 * result + myParent.hashCode();
+    return result;
+  }
+
+  public T getOriginal() {
+    T element = myRef.get();
+    if (element != null) {
+      return element;
+    }
+
+    element = (T)myOriginal.retrieve();
+    if (element == null) {
+      throw new PsiInvalidElementAccessException(this);
+    }
+    myRef = new SoftReference<T>(element);
+    return element;
+  }
+
+  @NotNull
+  @Override
+  public T getNavigationElement() {
+    return getOriginal();
+  }
+
+  @Override
+  public PsiFile getContainingFile() {
+    return myParent.getContainingFile();
+  }
+
+  @Override
+  public PsiElement getParent() {
+    return myParent;
+  }
+
+  @Override
+  public String toString() {
+    return getClass().getSimpleName();
+  }
+
+  @Override
+  public boolean processElements(final PsiElementProcessor processor, PsiElement place) {
+    final IncludedXmlElement<T> self = this;
+    return getOriginal().processElements(new PsiElementProcessor() {
+      @SuppressWarnings("unchecked")
+      @Override
+      public boolean execute(@NotNull PsiElement element) {
+        if (element instanceof XmlTag) {
+          XmlTag theirParent = ((XmlTag)element).getParentTag();
+          PsiElement parent = getOriginal().equals(theirParent) ? (XmlTag)self : theirParent;
+          return processor.execute(new IncludedXmlTag((XmlTag)element, parent));
+        }
+        if (element instanceof XmlAttribute) {
+          XmlTag theirParent = ((XmlAttribute)element).getParent();
+          XmlTag parent = getOriginal().equals(theirParent) ? (XmlTag)self : theirParent;
+          return processor.execute(new IncludedXmlAttribute((XmlAttribute)element, parent));
+        }
+        if (element instanceof XmlText) {
+          XmlTag theirParent = ((XmlText)element).getParentTag();
+          XmlTag parent = getOriginal().equals(theirParent) ? (XmlTag)self : theirParent;
+          return processor.execute(new IncludedXmlText((XmlText)element, parent));
+        }
+        return processor.execute(element);
+      }
+    }, place);
+  }
+
+
+}
diff --git a/xml/impl/src/com/intellij/xml/util/IncludedXmlTag.java b/xml/impl/src/com/intellij/xml/util/IncludedXmlTag.java
new file mode 100644
index 0000000..22481b1
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/IncludedXmlTag.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.source.xml.XmlTagValueImpl;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTagChild;
+import com.intellij.psi.xml.XmlTagValue;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+/**
+ * @author peter
+ */
+public class IncludedXmlTag extends IncludedXmlElement<XmlTag> implements XmlTag {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.IncludedXmlTag");
+  public IncludedXmlTag(@NotNull XmlTag original, @Nullable PsiElement parent) {
+    super(original, parent);
+  }
+
+  @Override
+  @Nullable
+  public XmlTag getParentTag() {
+    return getParent() instanceof XmlTag ? (XmlTag)getParent() : null;
+  }
+
+  @Override
+  @NotNull
+  @NonNls
+  public String getName() {
+    return getOriginal().getName();
+  }
+
+  @Override
+  public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
+    throw new UnsupportedOperationException("Can't modify included tags");
+  }
+
+  @Override
+  @NotNull
+  @NonNls
+  public String getNamespace() {
+    XmlTag original = getOriginal();
+    LOG.assertTrue(original.isValid());
+    return original.getNamespace();
+  }
+
+  @Override
+  @NotNull
+  @NonNls
+  public String getLocalName() {
+    return getOriginal().getLocalName();
+  }
+
+  @Override
+  @Nullable
+  public XmlElementDescriptor getDescriptor() {
+    return getOriginal().getDescriptor();
+  }
+
+  @Override
+  @NotNull
+  public XmlAttribute[] getAttributes() {
+    XmlAttribute[] original = getOriginal().getAttributes();
+    XmlAttribute[] attributes = new XmlAttribute[original.length];
+    for (int i = 0; i < original.length; i++) {
+      XmlAttribute attribute = original[i];
+      attributes[i] = new IncludedXmlAttribute(attribute, this);
+    }
+    return attributes;
+  }
+
+  @Override
+  @Nullable
+  public XmlAttribute getAttribute(@NonNls String name, @NonNls String namespace) {
+    XmlAttribute attribute = getOriginal().getAttribute(name, namespace);
+    return attribute == null ? null : new IncludedXmlAttribute(attribute, this);
+  }
+
+  @Override
+  @Nullable
+  public XmlAttribute getAttribute(@NonNls String qname) {
+    XmlAttribute attribute = getOriginal().getAttribute(qname);
+    return attribute == null ? null : new IncludedXmlAttribute(attribute, this);
+  }
+
+  @Override
+  @Nullable
+  public String getAttributeValue(@NonNls String name, @NonNls String namespace) {
+    return getOriginal().getAttributeValue(name, namespace);
+  }
+
+  @Override
+  @Nullable
+  public String getAttributeValue(@NonNls String qname) {
+    return getOriginal().getAttributeValue(qname);
+  }
+
+  @Override
+  public XmlAttribute setAttribute(@NonNls String name, @NonNls String namespace, @NonNls String value) throws IncorrectOperationException {
+    throw new UnsupportedOperationException("Can't modify included tags");
+  }
+
+  @Override
+  public XmlAttribute setAttribute(@NonNls String qname, @NonNls String value) throws IncorrectOperationException {
+    throw new UnsupportedOperationException("Can't modify included tags");
+  }
+
+  @Override
+  public XmlTag createChildTag(@NonNls String localName,
+                               @NonNls String namespace,
+                               @Nullable @NonNls String bodyText,
+                               boolean enforceNamespacesDeep) {
+    return getOriginal().createChildTag(localName, namespace, bodyText, enforceNamespacesDeep);
+  }
+
+  @Override
+  public XmlTag addSubTag(XmlTag subTag, boolean first) {
+    throw new UnsupportedOperationException("Can't modify included tags");
+  }
+
+  @Override
+  @NotNull
+  public XmlTag[] getSubTags() {
+    return wrapTags(getOriginal().getSubTags());
+  }
+
+  private XmlTag[] wrapTags(XmlTag[] original) {
+    XmlTag[] result = new XmlTag[original.length];
+    for (int i = 0; i < original.length; i++) {
+      result[i] = new IncludedXmlTag(original[i], this);
+    }
+    return result;
+  }
+
+  @Override
+  @NotNull
+  public XmlTag[] findSubTags(@NonNls String qname) {
+    return wrapTags(getOriginal().findSubTags(qname));
+  }
+
+  @Override
+  @NotNull
+  public XmlTag[] findSubTags(@NonNls String localName, @NonNls String namespace) {
+    return wrapTags(getOriginal().findSubTags(localName, namespace));
+  }
+
+  @Override
+  @Nullable
+  public XmlTag findFirstSubTag(@NonNls String qname) {
+    XmlTag tag = getOriginal().findFirstSubTag(qname);
+    return tag == null ? null : new IncludedXmlTag(tag, this);
+  }
+
+  @Override
+  @NotNull
+  @NonNls
+  public String getNamespacePrefix() {
+    return getOriginal().getNamespacePrefix();
+  }
+
+  @Override
+  @NotNull
+  @NonNls
+  public String getNamespaceByPrefix(@NonNls String prefix) {
+    return getOriginal().getNamespaceByPrefix(prefix);
+  }
+
+  @Override
+  @Nullable
+  public String getPrefixByNamespace(@NonNls String namespace) {
+    return getOriginal().getPrefixByNamespace(namespace);
+  }
+
+  @Override
+  public String[] knownNamespaces() {
+    return getOriginal().knownNamespaces();
+  }
+
+  @Override
+  public boolean hasNamespaceDeclarations() {
+    return getOriginal().hasNamespaceDeclarations();
+  }
+
+  @Override
+  @NotNull
+  public Map<String, String> getLocalNamespaceDeclarations() {
+    return getOriginal().getLocalNamespaceDeclarations();
+  }
+
+  @Override
+  @NotNull
+  public XmlTagValue getValue() {
+    return XmlTagValueImpl.createXmlTagValue(this);
+  }
+
+  @Override
+  @Nullable
+  public XmlNSDescriptor getNSDescriptor(@NonNls String namespace, boolean strict) {
+    return getOriginal().getNSDescriptor(namespace, strict);
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return getOriginal().isEmpty();
+  }
+
+  @Override
+  public void collapseIfEmpty() {
+    throw new UnsupportedOperationException("Can't modify included tags");
+  }
+
+  @Override
+  @Nullable
+  @NonNls
+  public String getSubTagText(@NonNls String qname) {
+    return getOriginal().getSubTagText(qname);
+  }
+
+  @Override
+  public PsiMetaData getMetaData() {
+    return null;
+  }
+
+  @Override
+  public XmlTagChild getNextSiblingInTag() {
+    return null;
+  }
+
+  @Override
+  public XmlTagChild getPrevSiblingInTag() {
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/IncludedXmlText.java b/xml/impl/src/com/intellij/xml/util/IncludedXmlText.java
new file mode 100644
index 0000000..b98a360
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/IncludedXmlText.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlTagChild;
+import com.intellij.psi.xml.XmlText;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author peter
+ */
+public class IncludedXmlText extends IncludedXmlElement<XmlText> implements XmlText {
+  public IncludedXmlText(@NotNull XmlText original, @Nullable XmlTag parent) {
+    super(original, parent);
+  }
+
+  @Override
+  public XmlTag getParentTag() {
+    return (XmlTag)getParent();
+  }
+
+  @Override
+  public XmlTagChild getNextSiblingInTag() {
+    return null;
+  }
+
+  @Override
+  public XmlTagChild getPrevSiblingInTag() {
+    return null;
+  }
+
+  @Override
+  public String getText() {
+    return getOriginal().getText();
+  }
+
+  public String getValue() {
+    return getOriginal().getValue();
+  }
+
+  public void setValue(String s) throws IncorrectOperationException {
+    throw new UnsupportedOperationException("Can't modify included elements");
+  }
+
+  public XmlElement insertAtOffset(XmlElement element, int displayOffset) throws IncorrectOperationException {
+    throw new UnsupportedOperationException("Can't modify included elements");
+  }
+
+  public void insertText(String text, int displayOffset) throws IncorrectOperationException {
+    throw new UnsupportedOperationException("Can't modify included elements");
+  }
+
+  public void removeText(int displayStart, int displayEnd) throws IncorrectOperationException {
+    throw new UnsupportedOperationException("Can't modify included elements");
+  }
+
+  public int physicalToDisplay(int offset) {
+    return getOriginal().physicalToDisplay(offset);
+  }
+
+  public int displayToPhysical(int offset) {
+    return getOriginal().displayToPhysical(offset);
+  }
+
+  @Nullable
+  public XmlText split(int displayIndex) {
+    throw new UnsupportedOperationException("Can't modify included elements");
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/InclusionProvider.java b/xml/impl/src/com/intellij/xml/util/InclusionProvider.java
new file mode 100644
index 0000000..9f637d5
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/InclusionProvider.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.openapi.util.NullableComputable;
+import com.intellij.openapi.util.RecursionManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiModificationTracker;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.xmlb.JDOMXIncluder;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.regex.Matcher;
+
+/**
+* @author peter
+*/
+class InclusionProvider implements CachedValueProvider<PsiElement[]> {
+  private final XmlTag myXincludeTag;
+
+  public InclusionProvider(XmlTag xincludeTag) {
+    myXincludeTag = xincludeTag;
+  }
+
+  @NotNull
+  public static PsiElement[] getIncludedTags(XmlTag xincludeTag) {
+    return CachedValuesManager.getManager(xincludeTag.getProject()).getCachedValue(xincludeTag, new InclusionProvider(xincludeTag));
+  }
+
+  public Result<PsiElement[]> compute() {
+    PsiElement[] result = RecursionManager.doPreventingRecursion(myXincludeTag, true, new NullableComputable<PsiElement[]>() {
+      @Override
+      public PsiElement[] compute() {
+        return computeInclusion(myXincludeTag);
+      }
+    });
+    return Result.create(result == null ? PsiElement.EMPTY_ARRAY : result, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
+  }
+
+  private static XmlTag[] extractXpointer(@NotNull XmlTag rootTag, @Nullable final String xpointer) {
+    if (xpointer != null) {
+      Matcher matcher = JDOMXIncluder.XPOINTER_PATTERN.matcher(xpointer);
+      if (matcher.matches()) {
+        String pointer = matcher.group(1);
+        matcher = JDOMXIncluder.CHILDREN_PATTERN.matcher(pointer);
+        if (matcher.matches() && matcher.group(1).equals(rootTag.getName())) {
+          return rootTag.getSubTags();
+        }
+      }
+    }
+
+    return new XmlTag[]{rootTag};
+  }
+
+  @Nullable
+  private static PsiElement[] computeInclusion(final XmlTag xincludeTag) {
+    final XmlFile included = XmlIncludeHandler.resolveXIncludeFile(xincludeTag);
+    final XmlDocument document = included != null ? included.getDocument() : null;
+    final XmlTag rootTag = document != null ? document.getRootTag() : null;
+    if (rootTag != null) {
+      final String xpointer = xincludeTag.getAttributeValue("xpointer", XmlUtil.XINCLUDE_URI);
+      final XmlTag[] includeTag = extractXpointer(rootTag, xpointer);
+      PsiElement[] result = new PsiElement[includeTag.length];
+      for (int i = 0; i < includeTag.length; i++) {
+        result[i] = new IncludedXmlTag(includeTag[i], xincludeTag.getParentTag());
+      }
+      return result;
+    }
+
+    return null;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/util/TagSetRuleProvider.java b/xml/impl/src/com/intellij/xml/util/TagSetRuleProvider.java
new file mode 100644
index 0000000..e4e20b9
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/TagSetRuleProvider.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public abstract class TagSetRuleProvider extends XmlTagRuleProviderBase {
+
+  private final Map<String, TagsRuleMap> map = Collections.synchronizedMap(new HashMap<String, TagsRuleMap>());
+
+  @Nullable
+  protected abstract String getNamespace(@NotNull XmlTag tag);
+
+  protected abstract void initMap(TagsRuleMap map, @NotNull String version);
+
+  @Override
+  public Rule[] getTagRule(@NotNull XmlTag tag) {
+    String namespace = getNamespace(tag);
+    if (namespace == null) return Rule.EMPTY_ARRAY;
+
+    return getTagRule(tag, namespace);
+  }
+
+  public Rule[] getTagRule(@NotNull XmlTag tag, String namespace) {
+    TagsRuleMap ruleMap = map.get(namespace);
+    if (ruleMap == null) {
+      ruleMap = new TagsRuleMap();
+      initMap(ruleMap, namespace);
+      map.put(namespace, ruleMap);
+    }
+
+    String tagName = tag.getLocalName();
+    Rule[] rules = ruleMap.get(tagName);
+    if (rules == null) return Rule.EMPTY_ARRAY;
+
+    return rules;
+  }
+
+  protected static class TagsRuleMap extends HashMap<String, Rule[]> {
+    public void add(String tagName, Rule ... rules) {
+      assert rules.length > 0;
+      Rule[] oldValue = put(tagName, rules);
+      assert oldValue == null;
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/UserColorLookup.java b/xml/impl/src/com/intellij/xml/util/UserColorLookup.java
new file mode 100644
index 0000000..b43aed5
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/UserColorLookup.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.completion.InsertHandler;
+import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.completion.PrioritizedLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.codeInsight.lookup.LookupElementDecorator;
+import com.intellij.codeInsight.lookup.LookupValueWithPriority;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.ui.ColorChooser;
+import com.intellij.ui.ColorPickerListener;
+import com.intellij.ui.ColorPickerListenerFactory;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+
+/**
+ * @author maxim
+ */
+public class UserColorLookup extends LookupElementDecorator<LookupElement> {
+  private static final String COLOR_STRING = XmlBundle.message("choose.color.in.color.lookup");
+
+  public UserColorLookup() {
+    super(PrioritizedLookupElement.withPriority(LookupElementBuilder.create(COLOR_STRING).withInsertHandler(
+      new InsertHandler<LookupElement>() {
+        @Override
+        public void handleInsert(InsertionContext context, LookupElement item) {
+          handleUserSelection(context);
+        }
+      }), LookupValueWithPriority.HIGH));
+  }
+
+  private static void handleUserSelection(InsertionContext context) {
+    Color myColorAtCaret = null;
+
+    Editor selectedTextEditor = context.getEditor();
+    PsiElement element = context.getFile().findElementAt(selectedTextEditor.getCaretModel().getOffset());
+
+    if (element instanceof XmlToken) {
+      myColorAtCaret = getColorFromElement(element);
+    }
+
+    context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
+
+    ColorPickerListener[] listeners = ColorPickerListenerFactory.createListenersFor(element);
+    Color color = ColorChooser.chooseColor(WindowManager.getInstance().suggestParentWindow(context.getProject()),
+                                           XmlBundle.message("choose.color.dialog.title"), myColorAtCaret, true, listeners);
+
+    if (color != null) {
+      String s = Integer.toHexString(color.getRGB() & 0xFFFFFF);
+      if (s.length() != 6) {
+        StringBuilder buf = new StringBuilder(s);
+        for (int i = 6 - buf.length(); i > 0; --i) {
+          buf.insert(0, '0');
+        }
+        s = buf.toString();
+      }
+      s = "#" + s;
+      context.getDocument().insertString(context.getStartOffset(), s);
+      context.getEditor().getCaretModel().moveToOffset(context.getTailOffset());
+    }
+  }
+
+  @Nullable
+  public static Color getColorFromElement(final PsiElement element) {
+    if (!(element instanceof XmlToken)) return null;
+
+    return ColorSampleLookupValue.getColor(element.getText());
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XIncludeProvider.java b/xml/impl/src/com/intellij/xml/util/XIncludeProvider.java
new file mode 100644
index 0000000..5edaeca
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XIncludeProvider.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.ide.highlighter.XmlFileType;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.ProjectCoreUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.impl.include.FileIncludeInfo;
+import com.intellij.psi.impl.include.FileIncludeProvider;
+import com.intellij.util.indexing.FileContent;
+import com.intellij.util.text.CharArrayUtil;
+import com.intellij.util.xml.NanoXmlUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XIncludeProvider extends FileIncludeProvider {
+  @NotNull
+  @Override
+  public String getId() {
+    return "XInclude";
+  }
+
+  @Override
+  public boolean acceptFile(VirtualFile file) {
+    final FileType fileType = file.getFileType();
+    return fileType == XmlFileType.INSTANCE && !ProjectCoreUtil.isProjectOrWorkspaceFile(file, fileType);
+  }
+
+  @NotNull
+  @Override
+  public FileIncludeInfo[] getIncludeInfos(FileContent content) {
+    CharSequence contentAsText = content.getContentAsText();
+    if (CharArrayUtil.indexOf(contentAsText, XmlUtil.XINCLUDE_URI, 0) == -1) return FileIncludeInfo.EMPTY;
+    final ArrayList<FileIncludeInfo> infos = new ArrayList<FileIncludeInfo>();
+    NanoXmlUtil.parse(CharArrayUtil.readerFromCharSequence(contentAsText), new NanoXmlUtil.IXMLBuilderAdapter() {
+
+      boolean isXInclude;
+      @Override
+      public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr) throws Exception {
+        isXInclude = XmlUtil.XINCLUDE_URI.equals(nsURI) && "include".equals(name);
+      }
+
+      @Override
+      public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type) throws Exception {
+        if (isXInclude && "href".equals(key)) {
+          infos.add(new FileIncludeInfo(value));
+        }
+      }
+
+      @Override
+      public void endElement(String name, String nsPrefix, String nsURI) throws Exception {
+        isXInclude = false;
+      }
+    });
+    return infos.toArray(new FileIncludeInfo[infos.size()]);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlApplicationComponent.java b/xml/impl/src/com/intellij/xml/util/XmlApplicationComponent.java
new file mode 100644
index 0000000..764db5a
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlApplicationComponent.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.html.impl.RelaxedHtmlFromSchemaNSDescriptor;
+import com.intellij.psi.filters.*;
+import com.intellij.psi.filters.position.NamespaceFilter;
+import com.intellij.psi.filters.position.TargetNamespaceFilter;
+import com.intellij.psi.meta.MetaDataContributor;
+import com.intellij.psi.meta.MetaDataRegistrar;
+import com.intellij.psi.xml.*;
+import com.intellij.xml.impl.dtd.XmlNSDescriptorImpl;
+import com.intellij.xml.impl.schema.NamedObjectDescriptor;
+import com.intellij.xml.impl.schema.SchemaNSDescriptor;
+import com.intellij.xml.impl.schema.XmlAttributeDescriptorImpl;
+import com.intellij.xml.impl.schema.XmlElementDescriptorImpl;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class XmlApplicationComponent implements MetaDataContributor {
+  public void contributeMetaData(final MetaDataRegistrar registrar) {
+    {
+      registrar.registerMetaData(
+          new AndFilter(
+              new NamespaceFilter(XmlUtil.SCHEMA_URIS),
+              new ClassFilter(XmlDocument.class)
+          ),
+          SchemaNSDescriptor.class
+      );
+
+      registrar.registerMetaData(
+          new AndFilter(XmlTagFilter.INSTANCE, new NamespaceFilter(XmlUtil.SCHEMA_URIS), new XmlTextFilter("schema")),
+          SchemaNSDescriptor.class
+      );
+    }
+    {
+      registrar.registerMetaData(
+          new OrFilter(
+              new AndFilter(
+                  new ContentFilter(
+                    new OrFilter(
+                      new ClassFilter(XmlElementDecl.class),
+                      new ClassFilter(XmlEntityDecl.class),
+                      new ClassFilter(XmlConditionalSection.class),
+                      new ClassFilter(XmlEntityRef.class)
+                    )
+                  ),
+                  new ClassFilter(XmlDocument.class)
+              ),
+              new ClassFilter(XmlMarkupDecl.class)
+          ),
+          XmlNSDescriptorImpl.class
+      );
+    }
+
+    {
+      registrar.registerMetaData(new AndFilter(XmlTagFilter.INSTANCE, new NamespaceFilter(XmlUtil.SCHEMA_URIS), new XmlTextFilter("element")),
+                         XmlElementDescriptorImpl.class);
+    }
+
+    {
+      registrar.registerMetaData(
+          new AndFilter(XmlTagFilter.INSTANCE, new NamespaceFilter(XmlUtil.SCHEMA_URIS), new XmlTextFilter("attribute")),
+          XmlAttributeDescriptorImpl.class
+      );
+    }
+
+    {
+      registrar.registerMetaData(
+          new ClassFilter(XmlElementDecl.class),
+          com.intellij.xml.impl.dtd.XmlElementDescriptorImpl.class
+      );
+    }
+
+    {
+      registrar.registerMetaData(
+          new ClassFilter(XmlAttributeDecl.class),
+          com.intellij.xml.impl.dtd.XmlAttributeDescriptorImpl.class
+      );
+    }
+
+    {
+      registrar.registerMetaData(
+          new AndFilter(
+              new ClassFilter(XmlDocument.class),
+              new TargetNamespaceFilter(XmlUtil.XHTML_URI),
+              new NamespaceFilter(XmlUtil.SCHEMA_URIS)),
+          RelaxedHtmlFromSchemaNSDescriptor.class
+      );
+    }
+
+    {
+      registrar.registerMetaData(new AndFilter(XmlTagFilter.INSTANCE, new NamespaceFilter(XmlUtil.SCHEMA_URIS), new XmlTextFilter("complexType",
+                                                                                                                                  "simpleType", "group",
+                                                                                                                                  "attributeGroup")),
+                         NamedObjectDescriptor.class);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlDeclareIdInCommentAction.java b/xml/impl/src/com/intellij/xml/util/XmlDeclareIdInCommentAction.java
new file mode 100644
index 0000000..4f7bec5
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlDeclareIdInCommentAction.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.lang.Commenter;
+import com.intellij.lang.Language;
+import com.intellij.lang.LanguageCommenters;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author spleaner
+ */
+public class XmlDeclareIdInCommentAction implements LocalQuickFix {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.XmlDeclareIdInCommentAction");
+
+  private final String myId;
+
+  public XmlDeclareIdInCommentAction(@NotNull final String id) {
+    myId = id;
+  }
+
+  @NotNull
+  public String getName() {
+    return XmlErrorMessages.message("declare.id.in.comment.quickfix");
+  }
+
+  @NotNull
+  public String getFamilyName() {
+    return getName();
+  }
+
+  @Nullable
+  public static String getImplicitlyDeclaredId(@NotNull final PsiComment comment) {
+    final String text = getUncommentedText(comment);
+    if (text == null) return null;
+
+    if (text.startsWith("@declare id=\"")) {
+      final String result = text.substring("@declare id=\"".length() - 1);
+      return StringUtil.unquoteString(result);
+    }
+
+    return null;
+  }
+
+  @Nullable
+  private static String getUncommentedText(@NotNull final PsiComment comment) {
+    final PsiFile psiFile = comment.getContainingFile();
+    final Language language = psiFile.getViewProvider().getBaseLanguage();
+    final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(language);
+    if (commenter != null) {
+      String text = comment.getText();
+
+      final String prefix = commenter.getBlockCommentPrefix();
+      if (prefix != null && text.startsWith(prefix)) {
+        text = text.substring(prefix.length());
+        final String suffix = commenter.getBlockCommentSuffix();
+        if (suffix != null && text.length() > suffix.length()) {
+          return text.substring(0, text.length() - suffix.length()).trim();
+        }
+      }
+    }
+
+    return null;
+  }
+
+  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+    final PsiElement psiElement = descriptor.getPsiElement();
+    final PsiFile psiFile = psiElement.getContainingFile();
+
+    new WriteCommandAction(project, psiFile) {
+      protected void run(final Result result) throws Throwable {
+        final XmlTag tag = PsiTreeUtil.getParentOfType(psiElement, XmlTag.class);
+        if (tag == null) return;
+
+        final Language language = psiFile.getViewProvider().getBaseLanguage();
+        final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(language);
+        if (commenter == null) return;
+
+        final PsiFile tempFile = PsiFileFactory.getInstance(project).createFileFromText("dummy", language.getAssociatedFileType(),
+            commenter.getBlockCommentPrefix() +
+                "@declare id=\"" +
+                myId +
+                "\"" +
+                commenter.getBlockCommentSuffix() +
+                "\n");
+
+        final XmlTag parent = tag.getParentTag();
+        if (parent != null && parent.isValid()) {
+          final XmlTag[] tags = parent.getSubTags();
+          if (tags.length > 0) {
+            final PsiFile psi = tempFile.getViewProvider().getPsi(language);
+            if (psi != null) {
+              final PsiElement element = psi.findElementAt(1);
+              if (element instanceof PsiComment) {
+                parent.getNode().addChild(element.getNode(), tags[0].getNode());
+              }
+            }
+          }
+        }
+      }
+    }.execute();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlDuplicatedIdInspection.java b/xml/impl/src/com/intellij/xml/util/XmlDuplicatedIdInspection.java
new file mode 100644
index 0000000..e0a1854
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlDuplicatedIdInspection.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.psi.*;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlDuplicatedIdInspection extends LocalInspectionTool {
+
+  @NotNull
+  @Override
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+    return new XmlElementVisitor() {
+      @Override
+      public void visitXmlAttributeValue(final XmlAttributeValue value) {
+        if (value.getTextRange().isEmpty()) {
+          return;
+        }
+        final PsiFile file = value.getContainingFile();
+        if (!(file instanceof XmlFile)) {
+          return;
+        }
+        final XmlRefCountHolder refHolder = XmlRefCountHolder.getRefCountHolder(value);
+        if (refHolder == null) return;
+
+        final PsiElement parent = value.getParent();
+        if (!(parent instanceof XmlAttribute)) return;
+
+        final XmlTag tag = (XmlTag)parent.getParent();
+        if (tag == null) return;
+
+        if (refHolder.isValidatable(tag.getParent()) && refHolder.isDuplicateIdAttributeValue(value)) {
+          holder.registerProblem(value, XmlErrorMessages.message("duplicate.id.reference"), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
+        }
+
+        String idRef = XmlHighlightVisitor.getUnquotedValue(value, tag);
+
+        if (tag instanceof HtmlTag) {
+          idRef = idRef.toLowerCase();
+        }
+
+        if (XmlUtil.isSimpleXmlAttributeValue(idRef, value) && refHolder.isIdReferenceValue(value)) {
+          boolean hasIdDeclaration = refHolder.hasIdDeclaration(idRef);
+          if (!hasIdDeclaration && tag instanceof HtmlTag) {
+            hasIdDeclaration = refHolder.hasIdDeclaration(value.getValue());
+          }
+
+          if (!hasIdDeclaration) {
+            for(XmlIdContributor contributor: Extensions.getExtensions(XmlIdContributor.EP_NAME)) {
+              if (contributor.suppressExistingIdValidation((XmlFile)file)) {
+                return;
+              }
+            }
+
+            final FileViewProvider viewProvider = tag.getContainingFile().getViewProvider();
+            if (viewProvider instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
+              holder.registerProblem(value, XmlErrorMessages.message("invalid.id.reference"), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL,
+                                     new XmlDeclareIdInCommentAction(idRef));
+
+            }
+            else {
+              holder.registerProblem(value, XmlErrorMessages.message("invalid.id.reference"), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
+            }
+          }
+        }
+      }
+    };
+  }
+
+  public boolean runForWholeFile() {
+    return false;
+  }
+
+  @NotNull
+  public HighlightDisplayLevel getDefaultLevel() {
+    return HighlightDisplayLevel.ERROR;
+  }
+
+  public boolean isEnabledByDefault() {
+    return true;
+  }
+
+  @NotNull
+  public String getGroupDisplayName() {
+    return XmlBundle.message("xml.inspections.group.name");
+  }
+
+  @NotNull
+  public String getDisplayName() {
+    return XmlBundle.message("xml.inspections.duplicate.id");
+  }
+
+  @NotNull
+  @NonNls
+  public String getShortName() {
+    return "XmlDuplicatedId";
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlIconProvider.java b/xml/impl/src/com/intellij/xml/util/XmlIconProvider.java
new file mode 100644
index 0000000..e12801d
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlIconProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.IconProvider;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.ElementBase;
+import com.intellij.psi.xml.XmlFile;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author peter
+ */
+public class XmlIconProvider extends IconProvider implements DumbAware {
+  @NonNls private static final String XSD_FILE_EXTENSION = "xsd";
+  @NonNls private static final String WSDL_FILE_EXTENSION = "wsdl";
+
+  @Nullable
+  public Icon getIcon(@NotNull final PsiElement element, final int _flags) {
+    if (element instanceof XmlFile) {
+      final VirtualFile vf = ((XmlFile)element).getVirtualFile();
+      if (vf != null) {
+        final String extension = vf.getExtension();
+        
+        if (XSD_FILE_EXTENSION.equals(extension)) {
+          return ElementBase.createLayeredIcon(element, AllIcons.FileTypes.XsdFile, ElementBase.transformFlags(element, _flags));
+        }
+        if (WSDL_FILE_EXTENSION.equals(extension)) {
+          return ElementBase.createLayeredIcon(element, AllIcons.FileTypes.WsdlFile, ElementBase.transformFlags(element, _flags));
+        }
+      }
+    }
+    return null;
+  }
+
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlIdContributor.java b/xml/impl/src/com/intellij/xml/util/XmlIdContributor.java
new file mode 100644
index 0000000..d4ff3dc
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlIdContributor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.xml.XmlFile;
+
+/**
+ * @author yole
+ */
+public interface XmlIdContributor {
+  ExtensionPointName<XmlIdContributor> EP_NAME = ExtensionPointName.create("com.intellij.xml.idContributor");
+
+  boolean suppressExistingIdValidation(XmlFile file);
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlIncludeHandler.java b/xml/impl/src/com/intellij/xml/util/XmlIncludeHandler.java
new file mode 100644
index 0000000..6827379
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlIncludeHandler.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
+import com.intellij.psi.xml.*;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author mike
+ */
+public class XmlIncludeHandler {
+  @NonNls private static final String INCLUDE_TAG_NAME = "include";
+  public static boolean isXInclude(PsiElement element) {
+    if (element instanceof XmlTag) {
+      XmlTag xmlTag = (XmlTag)element;
+
+      if (xmlTag.getParent() instanceof XmlDocument) return false;
+
+      if (xmlTag.getLocalName().equals(INCLUDE_TAG_NAME) && xmlTag.getAttributeValue("href") != null) {
+        if (xmlTag.getNamespace().equals(XmlUtil.XINCLUDE_URI)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  @Nullable
+  public static XmlFile resolveXIncludeFile(XmlTag xincludeTag) {
+    final XmlAttribute hrefAttribute = xincludeTag.getAttribute("href", null);
+    if (hrefAttribute == null) return null;
+
+    final XmlAttributeValue xmlAttributeValue = hrefAttribute.getValueElement();
+    if (xmlAttributeValue == null) return null;
+
+    final FileReferenceSet referenceSet = FileReferenceSet.createSet(xmlAttributeValue, false, true, false);
+
+    final PsiReference reference = referenceSet.getLastReference();
+    if (reference == null) return null;
+
+    final PsiElement target = reference.resolve();
+
+    if (!(target instanceof XmlFile)) return null;
+    return (XmlFile)target;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlNSDescriptorSequence.java b/xml/impl/src/com/intellij/xml/util/XmlNSDescriptorSequence.java
new file mode 100644
index 0000000..06ab056
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlNSDescriptorSequence.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ik
+ * Date: 08.09.2003
+ * Time: 17:27:43
+ * To change this template use Options | File Templates.
+ */
+public class XmlNSDescriptorSequence implements XmlNSDescriptor{
+  final List<XmlNSDescriptor> sequence = new ArrayList<XmlNSDescriptor>();
+
+  public XmlNSDescriptorSequence(){
+  }
+
+  public XmlNSDescriptorSequence(XmlNSDescriptor[] descriptors){
+    for(int i = 0; i < descriptors.length; i++){
+      final XmlNSDescriptor descriptor = descriptors[i];
+      add(descriptor);
+    }
+  }
+
+  public void add(XmlNSDescriptor descriptor){
+    sequence.add(descriptor);
+  }
+
+  public XmlElementDescriptor getElementDescriptor(@NotNull XmlTag tag){
+    final Iterator iterator = sequence.iterator();
+    while(iterator.hasNext()){
+      final XmlNSDescriptor descriptor = (XmlNSDescriptor) iterator.next();
+      final XmlElementDescriptor elementDescriptor = descriptor.getElementDescriptor(tag);
+      if(elementDescriptor != null) return elementDescriptor;
+    }
+    return null;
+  }
+
+  @NotNull
+  public XmlElementDescriptor[] getRootElementsDescriptors(@Nullable final XmlDocument document) {
+    final List<XmlElementDescriptor> descriptors = new ArrayList<XmlElementDescriptor>();
+    final Iterator iterator = sequence.iterator();
+    while(iterator.hasNext()) {
+      final XmlNSDescriptor descriptor = (XmlNSDescriptor)iterator.next();
+      ContainerUtil.addAll(descriptors, descriptor.getRootElementsDescriptors(document));
+    }
+
+    return descriptors.toArray(new XmlElementDescriptor[descriptors.size()]);
+  }
+
+  public XmlFile getDescriptorFile(){
+    final Iterator iterator = sequence.iterator();
+    while(iterator.hasNext()){
+      final XmlNSDescriptor descriptor = (XmlNSDescriptor) iterator.next();
+      final XmlFile file = descriptor.getDescriptorFile();
+      if(file != null) return file;
+    }
+    return null;
+  }
+
+  public List<XmlNSDescriptor> getSequence(){
+    return sequence;
+  }
+
+  public boolean isHierarhyEnabled() {
+    final Iterator iterator = sequence.iterator();
+    while(iterator.hasNext()){
+      final XmlNSDescriptor descriptor = (XmlNSDescriptor) iterator.next();
+      if(descriptor.isHierarhyEnabled()) return true;
+    }
+    return false;
+  }
+
+  public PsiElement getDeclaration(){
+    final Iterator iterator = sequence.iterator();
+    while(iterator.hasNext()){
+      final XmlNSDescriptor descriptor = (XmlNSDescriptor) iterator.next();
+      final PsiElement declaration = descriptor.getDeclaration();
+      if(declaration != null) return declaration;
+    }
+    return null;
+  }
+
+  public String getName(PsiElement context){
+    final Iterator iterator = sequence.iterator();
+    while(iterator.hasNext()){
+      final XmlNSDescriptor descriptor = (XmlNSDescriptor) iterator.next();
+      final String name = descriptor.getName(context);
+      if(name != null) return name;
+    }
+    return null;
+  }
+
+  public String getName(){
+    final Iterator iterator = sequence.iterator();
+    while(iterator.hasNext()){
+      final XmlNSDescriptor descriptor = (XmlNSDescriptor) iterator.next();
+      final String name = descriptor.getName();
+      if(name != null) return name;
+    }
+    return null;
+  }
+
+  public void init(PsiElement element){
+    final Iterator iterator = sequence.iterator();
+    while(iterator.hasNext()){
+      final XmlNSDescriptor descriptor = (XmlNSDescriptor) iterator.next();
+      descriptor.init(element);
+    }
+  }
+
+  public Object[] getDependences(){
+    final List<Object> ret = new ArrayList<Object>();
+    final Iterator iterator = sequence.iterator();
+    while(iterator.hasNext()) {
+      final XmlNSDescriptor descriptor = (XmlNSDescriptor)iterator.next();
+      ContainerUtil.addAll(ret, descriptor.getDependences());
+    }
+    return ret.toArray();
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java b/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java
new file mode 100644
index 0000000..f1b8294
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java
@@ -0,0 +1,50 @@
+package com.intellij.xml.util;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.impl.source.xml.SchemaPrefixReference;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ProcessingContext;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.impl.schema.XmlAttributeDescriptorImpl;
+import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XmlPrefixReferenceProvider extends PsiReferenceProvider {
+
+  @NotNull
+  @Override
+  public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
+    XmlAttributeValue attributeValue = (XmlAttributeValue)element;
+    PsiElement parent = attributeValue.getParent();
+    if (parent instanceof XmlAttribute && !XmlNSDescriptorImpl.checkSchemaNamespace(((XmlAttribute)parent).getParent())) {
+      XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
+      if (descriptor instanceof XmlAttributeDescriptorImpl) {
+        String type = ((XmlAttributeDescriptorImpl)descriptor).getType();
+        if (type != null && type.endsWith(":QName")) {
+          String prefix = XmlUtil.findPrefixByQualifiedName(type);
+          String ns = ((XmlTag)descriptor.getDeclaration()).getNamespaceByPrefix(prefix);
+          if (XmlNSDescriptorImpl.checkSchemaNamespace(ns)) {
+            String value = attributeValue.getValue();
+            if (value != null) {
+              int i = value.indexOf(':');
+              if (i > 0) {
+                return new PsiReference[] {
+                  new SchemaPrefixReference(attributeValue, TextRange.from(1, i), value.substring(0, i), null)
+                };
+              }
+            }
+          }
+        }
+      }
+    }
+    return PsiReference.EMPTY_ARRAY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlRefCountHolder.java b/xml/impl/src/com/intellij/xml/util/XmlRefCountHolder.java
new file mode 100644
index 0000000..0a43ad1
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlRefCountHolder.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
+import com.intellij.lang.Language;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.UserDataCache;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.IdReferenceProvider;
+import com.intellij.psi.impl.source.xml.PossiblePrefixReference;
+import com.intellij.psi.impl.source.xml.SchemaPrefix;
+import com.intellij.psi.impl.source.xml.SchemaPrefixReference;
+import com.intellij.psi.templateLanguages.OuterLanguageElement;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.NullableFunction;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author spleaner
+ */
+public class XmlRefCountHolder {
+  private static final Key<CachedValue<XmlRefCountHolder>> xmlRefCountHolderKey = Key.create("xml ref count holder");
+
+  private final static UserDataCache<CachedValue<XmlRefCountHolder>, XmlFile, Object> CACHE =
+    new UserDataCache<CachedValue<XmlRefCountHolder>, XmlFile, Object>() {
+      protected CachedValue<XmlRefCountHolder> compute(final XmlFile file, final Object p) {
+        return CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<XmlRefCountHolder>() {
+          public Result<XmlRefCountHolder> compute() {
+            final XmlRefCountHolder holder = new XmlRefCountHolder();
+            final Language language = file.getViewProvider().getBaseLanguage();
+            final PsiFile psiFile = file.getViewProvider().getPsi(language);
+            assert psiFile != null;
+            psiFile.accept(new IdGatheringRecursiveVisitor(holder));
+            return new Result<XmlRefCountHolder>(holder, file);
+          }
+        }, false);
+      }
+    };
+
+  private final Map<String, List<Pair<XmlAttributeValue, Boolean>>> myId2AttributeListMap = new HashMap<String, List<Pair<XmlAttributeValue, Boolean>>>();
+  private final Set<XmlAttributeValue> myPossiblyDuplicateIds = new HashSet<XmlAttributeValue>();
+  private final List<XmlAttributeValue> myIdReferences = new ArrayList<XmlAttributeValue>();
+  private final Set<String> myAdditionallyDeclaredIds = new HashSet<String>();
+  private final Set<PsiElement> myDoNotValidateParentsList = new HashSet<PsiElement>();
+  private final Set<String> myUsedPrefixes = new HashSet<String>();
+  private final Set<String> myUsedNamespaces = new HashSet<String>();
+
+  @Nullable
+  public static XmlRefCountHolder getRefCountHolder(final XmlElement element) {
+    PsiFile file = element.getContainingFile();
+    return file instanceof XmlFile ? CACHE.get(xmlRefCountHolderKey, (XmlFile)file, null).getValue() : null;
+  }
+
+  private XmlRefCountHolder() {
+  }
+
+
+  public boolean isDuplicateIdAttributeValue(@NotNull final XmlAttributeValue value) {
+    return myPossiblyDuplicateIds.contains(value);
+  }
+
+  public boolean isValidatable(@Nullable final PsiElement element) {
+    return !myDoNotValidateParentsList.contains(element);
+  }
+
+  public boolean hasIdDeclaration(@NotNull final String idRef) {
+    return myId2AttributeListMap.get(idRef) != null || myAdditionallyDeclaredIds.contains(idRef);
+  }
+
+  public boolean isIdReferenceValue(@NotNull final XmlAttributeValue value) {
+    return myIdReferences.contains(value);
+  }
+
+  private void registerId(@NotNull final String id, @NotNull final XmlAttributeValue attributeValue, final boolean soft) {
+    List<Pair<XmlAttributeValue, Boolean>> list = myId2AttributeListMap.get(id);
+    if (list == null) {
+      list = new ArrayList<Pair<XmlAttributeValue, Boolean>>();
+      myId2AttributeListMap.put(id, list);
+    }
+    else if (!soft) {
+      // mark as duplicate
+      List<XmlAttributeValue> notSoft = ContainerUtil.mapNotNull(list, new NullableFunction<Pair<XmlAttributeValue, Boolean>, XmlAttributeValue>() {
+        @Override
+        public XmlAttributeValue fun(Pair<XmlAttributeValue, Boolean> pair) {
+          return pair.second ? null : pair.first;
+        }
+      });
+      if (!notSoft.isEmpty()) {
+        myPossiblyDuplicateIds.addAll(notSoft);
+        myPossiblyDuplicateIds.add(attributeValue);
+      }
+    }
+
+    list.add(new Pair<XmlAttributeValue, Boolean>(attributeValue, soft));
+  }
+
+  private void registerAdditionalId(@NotNull final String id) {
+    myAdditionallyDeclaredIds.add(id);
+  }
+
+  private void registerIdReference(@NotNull final XmlAttributeValue value) {
+    myIdReferences.add(value);
+  }
+
+  private void registerOuterLanguageElement(@NotNull final PsiElement element) {
+    PsiElement parent = element.getParent();
+
+    if (parent instanceof XmlText) {
+      parent = parent.getParent();
+    }
+
+    myDoNotValidateParentsList.add(parent);
+  }
+
+  public boolean isInUse(String prefix) {
+    return myUsedPrefixes.contains(prefix);
+  }
+
+  public boolean isUsedNamespace(String ns) {
+    return myUsedNamespaces.contains(ns);
+  }
+
+  private static class IdGatheringRecursiveVisitor extends XmlRecursiveElementVisitor {
+    private final XmlRefCountHolder myHolder;
+
+    private IdGatheringRecursiveVisitor(@NotNull XmlRefCountHolder holder) {
+      super(true);
+      myHolder = holder;
+    }
+
+    @Override
+    public void visitElement(final PsiElement element) {
+      if (element instanceof OuterLanguageElement) {
+        visitOuterLanguageElement(element);
+      }
+
+      super.visitElement(element);
+    }
+
+    private void visitOuterLanguageElement(@NotNull final PsiElement element) {
+      myHolder.registerOuterLanguageElement(element);
+      PsiReference[] references = element.getReferences();
+      for (PsiReference reference : references) {
+        if (reference instanceof PossiblePrefixReference && ((PossiblePrefixReference)reference).isPrefixReference()) {
+          PsiElement resolve = reference.resolve();
+          if (resolve instanceof SchemaPrefix) {
+            myHolder.addUsedPrefix(((SchemaPrefix)resolve).getName());
+          }
+        }
+      }
+    }
+
+    @Override
+    public void visitComment(final PsiComment comment) {
+      doVisitAnyComment(comment);
+      super.visitComment(comment);
+    }
+
+    @Override
+    public void visitXmlComment(final XmlComment comment) {
+      doVisitAnyComment(comment);
+      super.visitXmlComment(comment);
+    }
+
+    private void doVisitAnyComment(final PsiComment comment) {
+      final String id = XmlDeclareIdInCommentAction.getImplicitlyDeclaredId(comment);
+      if (id != null) {
+        myHolder.registerAdditionalId(id);
+      }
+    }
+
+    @Override
+    public void visitXmlTag(XmlTag tag) {
+      myHolder.addUsedPrefix(tag.getNamespacePrefix());
+      myHolder.addUsedNamespace(tag.getNamespace());
+      String text = tag.getValue().getTrimmedText();
+      detectPrefix(text);
+      super.visitXmlTag(tag);
+    }
+
+    @Override
+    public void visitXmlAttribute(XmlAttribute attribute) {
+      if (!attribute.isNamespaceDeclaration()) {
+        myHolder.addUsedPrefix(attribute.getNamespacePrefix());
+      }
+      myHolder.addUsedNamespace(attribute.getNamespace());
+      super.visitXmlAttribute(attribute);
+    }
+
+    @Override
+    public void visitXmlAttributeValue(final XmlAttributeValue value) {
+      final PsiElement element = value.getParent();
+      if (!(element instanceof XmlAttribute)) return;
+
+      final XmlAttribute attribute = (XmlAttribute)element;
+
+      final XmlTag tag = attribute.getParent();
+      if (tag == null) return;
+
+      final XmlElementDescriptor descriptor = tag.getDescriptor();
+      if (descriptor == null) return;
+
+      final XmlAttributeDescriptor attributeDescriptor = descriptor.getAttributeDescriptor(attribute);
+      if (attributeDescriptor == null) return;
+
+      if (attributeDescriptor.hasIdType()) {
+        updateMap(attribute, value, false);
+      }
+      else {
+        final PsiReference[] references = value.getReferences();
+        for (PsiReference r : references) {
+          if (r instanceof IdReferenceProvider.GlobalAttributeValueSelfReference /*&& !r.isSoft()*/) {
+            updateMap(attribute, value, r.isSoft());
+          }
+          else if (r instanceof SchemaPrefixReference) {
+            SchemaPrefix prefix = ((SchemaPrefixReference)r).resolve();
+            if (prefix != null) {
+              myHolder.addUsedPrefix(prefix.getName());
+            }
+          }
+        }
+      }
+
+      if (attributeDescriptor.hasIdRefType() && PsiTreeUtil.getChildOfType(value, OuterLanguageElement.class) == null) {
+        myHolder.registerIdReference(value);
+      }
+
+      String s = value.getValue();
+      detectPrefix(s);
+      super.visitXmlAttributeValue(value);
+    }
+
+    private void detectPrefix(String s) {
+      if (s != null) {
+        int pos = s.indexOf(':');
+        if (pos > 0) {
+          myHolder.addUsedPrefix(s.substring(0, pos));
+        }
+      }
+    }
+
+    private void updateMap(@NotNull final XmlAttribute attribute, @NotNull final XmlAttributeValue value, final boolean soft) {
+      final String id = XmlHighlightVisitor.getUnquotedValue(value, attribute.getParent());
+      if (XmlUtil.isSimpleXmlAttributeValue(id, value) &&
+          PsiTreeUtil.getChildOfType(value, OuterLanguageElement.class) == null) {
+        myHolder.registerId(id, value, soft);
+      }
+    }
+  }
+
+  private void addUsedPrefix(String prefix) {
+    myUsedPrefixes.add(prefix);
+  }
+
+  private void addUsedNamespace(String ns) {
+    myUsedNamespaces.add(ns);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
new file mode 100644
index 0000000..872d174
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
@@ -0,0 +1,86 @@
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.daemon.impl.analysis.encoding.XmlEncodingReferenceProvider;
+import com.intellij.patterns.PlatformPatterns;
+import com.intellij.patterns.XmlPatterns;
+import com.intellij.psi.PsiReferenceContributor;
+import com.intellij.psi.PsiReferenceRegistrar;
+import com.intellij.psi.filters.*;
+import com.intellij.psi.filters.position.NamespaceFilter;
+import com.intellij.psi.filters.position.ParentElementFilter;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.DtdReferencesProvider;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.IdReferenceProvider;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaReferencesProvider;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.URIReferenceProvider;
+import com.intellij.psi.xml.*;
+
+import static com.intellij.patterns.StandardPatterns.string;
+import static com.intellij.patterns.XmlPatterns.*;
+
+/**
+ * @author peter
+ */
+public class XmlReferenceContributor extends PsiReferenceContributor {
+  public void registerReferenceProviders(final PsiReferenceRegistrar registrar) {
+
+    final IdReferenceProvider idReferenceProvider = new IdReferenceProvider();
+
+    XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, idReferenceProvider.getIdForAttributeNames(),
+                                                       idReferenceProvider.getIdForFilter(), true, idReferenceProvider,
+                                                       PsiReferenceRegistrar.DEFAULT_PRIORITY);
+
+    final DtdReferencesProvider dtdReferencesProvider = new DtdReferencesProvider();
+    //registerReferenceProvider(null, XmlEntityDecl.class,dtdReferencesProvider);
+    registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlEntityRef.class), dtdReferencesProvider);
+    registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlDoctype.class), dtdReferencesProvider);
+    registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlElementDecl.class), dtdReferencesProvider);
+    registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlAttlistDecl.class), dtdReferencesProvider);
+    registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlElementContentSpec.class), dtdReferencesProvider);
+    registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlToken.class), dtdReferencesProvider);
+
+    URIReferenceProvider uriProvider = new URIReferenceProvider();
+    XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, null, dtdReferencesProvider.getSystemReferenceFilter(), uriProvider);
+
+
+    XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, new String[] { "href" }, new ScopeFilter(
+      new ParentElementFilter(
+        new AndFilter(
+          new AndFilter(XmlTagFilter.INSTANCE, new XmlTextFilter("include")),
+          new NamespaceFilter(XmlUtil.XINCLUDE_URI)
+        ),
+        2
+      )
+    ), true, uriProvider);
+
+    final SchemaReferencesProvider schemaReferencesProvider = new SchemaReferencesProvider();
+
+    XmlUtil.registerXmlAttributeValueReferenceProvider(registrar,
+      schemaReferencesProvider.getCandidateAttributeNamesForSchemaReferences(),
+      new ScopeFilter(
+        new ParentElementFilter(
+          new NamespaceFilter(XmlUtil.SCHEMA_URIS), 2
+        )
+      ),
+      schemaReferencesProvider
+    );
+
+    registrar.registerReferenceProvider(xmlAttributeValue(xmlAttribute().withNamespace(XmlUtil.XML_SCHEMA_INSTANCE_URI)).
+      withLocalName("type"), schemaReferencesProvider);
+
+    registrar.registerReferenceProvider(xmlAttributeValue(xmlAttribute().withNamespace(XmlUtil.XML_SCHEMA_INSTANCE_URI)).
+      withLocalName("noNamespaceSchemaLocation", "schemaLocation"), uriProvider);
+
+    registrar.registerReferenceProvider(
+      xmlAttributeValue().withLocalName("schemaLocation","namespace").
+        withSuperParent(2,
+                        xmlTag().withNamespace(XmlUtil.SCHEMA_URIS).withLocalName(string().oneOf("import", "include","redefine"))),
+      uriProvider);
+
+    XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, null, URIReferenceProvider.ELEMENT_FILTER, true, uriProvider);
+
+    XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, new String[] {"encoding"}, new ScopeFilter(new ParentElementFilter(new ClassFilter(XmlProcessingInstruction.class))), true,
+                                                       new XmlEncodingReferenceProvider());
+
+    registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue(), new XmlPrefixReferenceProvider());
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlResourceResolver.java b/xml/impl/src/com/intellij/xml/util/XmlResourceResolver.java
new file mode 100644
index 0000000..018aee2
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlResourceResolver.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.javaee.ExternalResourceManagerEx;
+import com.intellij.javaee.UriUtil;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.openapi.vfs.ex.http.HttpFileSystem;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.URIReferenceProvider;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.actions.ValidateXmlActionHandler;
+import com.intellij.xml.index.XmlNamespaceIndex;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLInputSource;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+import org.xml.sax.SAXParseException;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Maxim.Mossienko
+ */
+public class XmlResourceResolver implements XMLEntityResolver {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.XmlResourceResolver");
+  private final XmlFile myFile;
+  private final Project myProject;
+  private final Map<String,String> myExternalResourcesMap = new HashMap<String, String>(1);
+  private boolean myStopOnUnDeclaredResource;
+  @NonNls
+  public static final String HONOUR_ALL_SCHEMA_LOCATIONS_PROPERTY_KEY = "idea.xml.honour.all.schema.locations";
+  private final ValidateXmlActionHandler.ErrorReporter myErrorReporter;
+
+  public XmlResourceResolver(XmlFile _xmlFile, Project _project, final ValidateXmlActionHandler.ErrorReporter errorReporter) {
+    myFile = _xmlFile;
+    myProject = _project;
+    myErrorReporter = errorReporter;
+  }
+
+  public String getPathByPublicId(String baseId) {
+    return myExternalResourcesMap.get(baseId);
+  }
+
+  public String[] getResourcePaths() {
+    return myExternalResourcesMap.values().toArray(new String[myExternalResourcesMap.size()]);
+  }
+
+  @Nullable
+  public PsiFile resolve(@Nullable final String baseSystemId, final String _systemId) {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("enter: resolveEntity(baseSystemId='" + baseSystemId + "' systemId='" + _systemId + "," + super.toString() + "')");
+    }
+
+    if (_systemId == null) return null;
+    if (myStopOnUnDeclaredResource &&
+        ExternalResourceManagerEx.getInstanceEx().isIgnoredResource(_systemId)) {
+      throw new IgnoredResourceException();
+    }
+
+    final int length = URIReferenceProvider.getPrefixLength(_systemId);
+    final String systemId = _systemId.substring(length);
+
+    final PsiFile[] result = new PsiFile[] { null };
+    final Runnable action = new Runnable() {
+      public void run() {
+        PsiFile baseFile = null;
+        VirtualFile vFile = null;
+
+        if (baseSystemId != null) {
+          baseFile = resolve(null,baseSystemId);
+
+          if (baseFile == null) {
+              // Find relative to myFile
+            File workingFile = new File("");
+            String workingDir = workingFile.getAbsoluteFile().getAbsolutePath().replace(File.separatorChar, '/');
+            String id = StringUtil.replace(baseSystemId, workingDir, myFile.getVirtualFile().getParent().getPath());
+            vFile = UriUtil.findRelative(id, myFile);
+
+            if (vFile == null) {
+              vFile = UriUtil.findRelative(baseSystemId, myFile);
+
+              if (vFile == null) {
+                try {
+                  vFile = VfsUtil.findFileByURL(new URL(baseSystemId));
+                } catch(MalformedURLException ignore) {}
+              }
+            }
+          }
+
+          if (vFile != null && !vFile.isDirectory() && !(vFile.getFileSystem() instanceof HttpFileSystem)) {
+            baseFile = PsiManager.getInstance(myProject).findFile(vFile);
+          }
+        }
+        if (baseFile == null) {
+          baseFile = myFile;
+        }
+
+        String version = null;
+        String tagName = null;
+        if (baseFile == myFile) {
+          XmlTag rootTag = myFile.getRootTag();
+          if (rootTag != null) {
+            tagName = rootTag.getLocalName();
+            version = rootTag.getAttributeValue("version");
+          }
+        }
+        
+        PsiFile psiFile = ExternalResourceManager.getInstance().getResourceLocation(systemId, baseFile, version);
+        if (psiFile == null) {
+          psiFile = XmlUtil.findXmlFile(baseFile, systemId);
+        }
+        // autodetection
+        if (psiFile == null) {
+          psiFile = XmlNamespaceIndex.guessSchema(systemId, tagName, version, myFile);
+          if (psiFile == null) {
+            psiFile = XmlNamespaceIndex.guessDtd(systemId, myFile);
+          }
+        }
+
+        if (psiFile == null && baseSystemId != null) {
+          String fullUrl = baseSystemId.substring( 0, baseSystemId.lastIndexOf('/') + 1 ) + systemId;
+          psiFile = XmlUtil.findXmlFile(baseFile,fullUrl);
+        }
+
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("before relative file checking:"+psiFile+","+systemId+","+ baseSystemId+")");
+        }
+        if (psiFile == null && baseSystemId == null) { // entity file
+          File workingFile = new File("");
+          String workingDir = workingFile.getAbsoluteFile().getAbsolutePath().replace(File.separatorChar, '/') + "/";
+
+          String relativePath = StringUtil.replace(
+            systemId,
+            workingDir,
+            ""
+          );
+
+          if (relativePath.equals(systemId)) {
+            // on Windows systemId consisting of idea install path could become encoded DOS short name (e.g. idea%7f1.504)
+            // I am not aware how to get such name from 'workingDir' so let just pickup filename from there
+            relativePath = systemId.substring(systemId.lastIndexOf('/') + 1);
+          }
+
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("next to relative file checking:"+relativePath+","+myExternalResourcesMap.size()+")");
+          }
+
+          for(String path:getResourcePaths()) {
+            if (LOG.isDebugEnabled()) {
+              LOG.debug("Finding file by url:" + path);
+            }
+            VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(path);
+            if (file == null) continue;
+            if (LOG.isDebugEnabled()) {
+              LOG.debug("Finding "+relativePath+" relative to:"+file.getPath());
+            }
+            final VirtualFile relativeFile = UriUtil.findRelativeFile(relativePath, file);
+            if (LOG.isDebugEnabled()) {
+              LOG.debug("Found "+(relativeFile != null ? relativeFile.getPath():"null"));
+            }
+
+            if (relativeFile != null) {
+              psiFile = PsiManager.getInstance(myProject).findFile(relativeFile);
+              if (psiFile != null) break;
+            }
+          }
+        }
+
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("resolveEntity: psiFile='" + (psiFile != null ? psiFile.getVirtualFile() : null) + "'");
+        }
+        result[0] = psiFile;
+      }
+    };
+    ApplicationManager.getApplication().runReadAction(action);
+
+    final PsiFile psiFile = result[0];
+    if (psiFile != null) {
+      final VirtualFile file = psiFile.getVirtualFile();
+      if (file != null) {
+        final String url = file.getUrl();
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Adding external resource ref:"+systemId+","+url+","+super.toString());
+        }
+        myExternalResourcesMap.put(systemId,url);
+      }
+    }
+    return psiFile;
+  }
+
+  @Nullable
+  public XMLInputSource resolveEntity(XMLResourceIdentifier xmlResourceIdentifier) throws XNIException, IOException {
+    String publicId  = xmlResourceIdentifier.getLiteralSystemId() != null ?
+                  xmlResourceIdentifier.getLiteralSystemId():
+                  xmlResourceIdentifier.getNamespace();
+
+    PsiFile psiFile = resolve(xmlResourceIdentifier.getBaseSystemId(), publicId);
+    if (psiFile == null && xmlResourceIdentifier.getBaseSystemId() != null) {
+        psiFile = ExternalResourceManager.getInstance().getResourceLocation(xmlResourceIdentifier.getBaseSystemId(), myFile, null);
+    }
+    if (psiFile==null && xmlResourceIdentifier.getLiteralSystemId()!=null && xmlResourceIdentifier.getNamespace()!=null) {
+      psiFile = resolve(
+        xmlResourceIdentifier.getBaseSystemId(),
+        publicId = xmlResourceIdentifier.getNamespace()
+      );
+    }
+
+    if (psiFile == null) {
+      if (publicId != null && publicId.indexOf(":/") != -1) {
+        myErrorReporter.processError(
+          new SAXParseException(XmlBundle.message("xml.validate.external.resource.is.not.registered", publicId), publicId, null, 0,0), false);
+        final XMLInputSource source = new XMLInputSource(xmlResourceIdentifier);
+        source.setPublicId(publicId);
+        source.setCharacterStream(new StringReader(""));
+        return source;
+      }
+      return null;
+    }
+
+    XMLInputSource source = new XMLInputSource(xmlResourceIdentifier);
+    if (xmlResourceIdentifier.getLiteralSystemId() == null) {
+      VirtualFile virtualFile = psiFile.getVirtualFile();
+      if (virtualFile != null) {
+        final String url = VfsUtil.fixIDEAUrl(virtualFile.getUrl());
+        source.setBaseSystemId(url);
+        source.setSystemId(url);
+      }
+    }
+    source.setPublicId(publicId);
+    source.setCharacterStream(new StringReader(psiFile.getText()));
+
+    return source;
+  }
+
+  public void setStopOnUnDeclaredResource(final boolean stopOnUnDeclaredResource) {
+    myStopOnUnDeclaredResource = stopOnUnDeclaredResource;
+  }
+
+  public static class IgnoredResourceException extends RuntimeException {
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlTagRuleProviderBase.java b/xml/impl/src/com/intellij/xml/util/XmlTagRuleProviderBase.java
new file mode 100644
index 0000000..c5953c4
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlTagRuleProviderBase.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.daemon.impl.analysis.InsertRequiredAttributeFix;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.codeInspection.htmlInspections.RemoveAttributeIntentionAction;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.RoleFinder;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlChildRole;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlTagRuleProvider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class XmlTagRuleProviderBase extends XmlTagRuleProvider {
+
+  public static RequireAttributeOneOf requireAttr(String ... attributeNames) {
+    return new RequireAttributeOneOf(attributeNames);
+  }
+
+  public static ShouldHaveParams shouldHaveParams() {
+    return new ShouldHaveParams();
+  }
+
+  public static Rule unusedIfPresent(String attrPresent, String ... attrUnused) {
+    Effect[] effects = new Effect[attrUnused.length];
+    for (int i = 0; i < effects.length; i++) {
+      effects[i] = unused(attrUnused[i], "The attribute '" + attrUnused[i] + "' is unused because the attribute '" + attrPresent + "' is present");
+    }
+
+    return new ConditionRule(ifAttrPresent(attrPresent), effects);
+  }
+
+  public static Rule unusedAllIfPresent(String attrPresent, String ... attrUnused) {
+    return new ConditionRule(ifAttrPresent(attrPresent),
+                             new InvalidAllExpectSome("The attribute is unused because the attribute " + attrPresent + " is present",
+                                                      ProblemHighlightType.LIKE_UNUSED_SYMBOL,
+                                                      ArrayUtil.append(attrUnused, attrPresent)));
+  }
+
+  public static Effect invalid(String attrName, String text) {
+    return new InvalidAttrEffect(attrName, text, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
+  }
+
+  public static Effect unused(String attrName) {
+    return new InvalidAttrEffect(attrName, "Attribute '" + attrName + "' is unused", ProblemHighlightType.LIKE_UNUSED_SYMBOL);
+  }
+
+  public static Effect unused(String attrName, String text) {
+    return new InvalidAttrEffect(attrName, text, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
+  }
+
+  public static Effect unusedAll(String text, String... attrNames) {
+    return new InvalidAllExpectSome(text, ProblemHighlightType.LIKE_UNUSED_SYMBOL, attrNames);
+  }
+
+  public static Rule rule(Condition<XmlTag> condition, Effect ... effect) {
+    return new ConditionRule(condition, effect);
+  }
+
+  @Nullable
+  public static PsiElement getXmlElement(RoleFinder roleFinder, XmlElement tag) {
+    ASTNode tagNode = tag.getNode();
+    if (tagNode == null) return null;
+
+    ASTNode nameElement = roleFinder.findChild(tagNode);
+    if (nameElement == null) return null;
+
+    return nameElement.getPsi();
+  }
+
+  @Nullable
+  public static PsiElement getTagNameElement(XmlTag tag) {
+    return getXmlElement(XmlChildRole.START_TAG_NAME_FINDER, tag);
+  }
+
+  @Nullable
+  public static PsiElement getAttributeNameElement(XmlAttribute attribute) {
+    return getXmlElement(XmlChildRole.ATTRIBUTE_NAME_FINDER, attribute);
+  }
+
+  public static boolean isClosedTag(XmlTag tag) {
+    return getXmlElement(XmlChildRole.EMPTY_TAG_END_FINDER, tag) != null || getXmlElement(XmlChildRole.CLOSING_TAG_START_FINDER, tag) != null;
+  }
+
+  public static Condition<XmlTag> ifAttrPresent(final String attrName) {
+    return new Condition<XmlTag>() {
+      @Override
+      public boolean value(XmlTag tag) {
+        return tag.getAttribute(attrName) != null;
+      }
+    };
+  }
+
+  // ---=== Classes ===---
+
+  public static abstract class Effect {
+    public abstract void annotate(@NotNull XmlTag tag, ProblemsHolder holder);
+  }
+
+  public static class InvalidAttrEffect extends Effect {
+    private final String myAttrName;
+    private final String myText;
+    private final ProblemHighlightType myType;
+
+    public InvalidAttrEffect(String attrName, String text, ProblemHighlightType type) {
+      myAttrName = attrName;
+      myText = text;
+      myType = type;
+    }
+
+    @Override
+    public void annotate(@NotNull XmlTag tag, ProblemsHolder holder) {
+      XmlAttribute attribute = tag.getAttribute(myAttrName);
+      if (attribute != null) {
+        PsiElement attributeNameElement = getAttributeNameElement(attribute);
+        if (attributeNameElement != null) {
+          holder.registerProblem(attributeNameElement, myText, myType, new RemoveAttributeIntentionAction(myAttrName));
+        }
+      }
+    }
+  }
+
+  public static class InvalidAllExpectSome extends Effect {
+    private final String[] myAttrNames;
+    private final String myText;
+    private final ProblemHighlightType myType;
+
+    public InvalidAllExpectSome(String text, ProblemHighlightType type, String... attrNames) {
+      myAttrNames = attrNames;
+      myText = text;
+      myType = type;
+    }
+
+    @Override
+    public void annotate(@NotNull XmlTag tag, ProblemsHolder holder) {
+      for (XmlAttribute xmlAttribute : tag.getAttributes()) {
+        String attrName = xmlAttribute.getName();
+        if (!ArrayUtil.contains(attrName, myAttrNames)) {
+          PsiElement attributeNameElement = getAttributeNameElement(xmlAttribute);
+          if (attributeNameElement != null) {
+            holder.registerProblem(attributeNameElement, myText, myType, new RemoveAttributeIntentionAction(attrName));
+          }
+        }
+      }
+    }
+  }
+
+  public static class ConditionRule extends Rule {
+    private final Condition<XmlTag> myCondition;
+    private final Effect[] myEffect;
+
+    public ConditionRule(Condition<XmlTag> condition, Effect ... effect) {
+      this.myCondition = condition;
+      this.myEffect = effect;
+    }
+
+    @Override
+    public void annotate(@NotNull XmlTag tag, ProblemsHolder holder) {
+      if (myCondition.value(tag)) {
+        for (Effect effect : myEffect) {
+          effect.annotate(tag, holder);
+        }
+      }
+    }
+  }
+
+  public static class ShouldHaveParams extends Rule {
+    @Override
+    public boolean needAtLeastOneAttribute(@NotNull XmlTag tag) {
+      return true;
+    }
+  }
+
+  public static class RequireAttributeOneOf extends ShouldHaveParams {
+    private final String[] myAttributeNames;
+    private final ProblemHighlightType myProblemHighlightType;
+
+    public RequireAttributeOneOf(String ... attributeNames) {
+      myAttributeNames = attributeNames;
+      myProblemHighlightType = ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+    }
+
+    public RequireAttributeOneOf(@NotNull ProblemHighlightType problemHighlightType, String... attributeNames) {
+      assert attributeNames.length > 0;
+      myAttributeNames = attributeNames;
+      myProblemHighlightType = problemHighlightType;
+    }
+
+    public String[] getAttributeNames() {
+      return myAttributeNames;
+    }
+
+    @Override
+    public void annotate(@NotNull XmlTag tag, ProblemsHolder holder) {
+      for (String attributeName : myAttributeNames) {
+        if (tag.getAttribute(attributeName) != null) {
+          return;
+        }
+      }
+
+      if (!isClosedTag(tag)) return;
+
+      PsiElement tagNameElement = getTagNameElement(tag);
+      if (tagNameElement == null) return;
+
+      LocalQuickFix[] fixes = new LocalQuickFix[myAttributeNames.length];
+      for (int i = 0; i < myAttributeNames.length; i++) {
+        fixes[i] = new InsertRequiredAttributeFix(tag, myAttributeNames[i], null);
+      }
+
+      holder.registerProblem(tagNameElement, "Tag should have one of following attributes: " + StringUtil.join(myAttributeNames, ", "),
+                             myProblemHighlightType,
+                             fixes);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlUtil.java b/xml/impl/src/com/intellij/xml/util/XmlUtil.java
new file mode 100644
index 0000000..fec8120
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlUtil.java
@@ -0,0 +1,1595 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.completion.CompletionUtil;
+import com.intellij.codeInsight.daemon.Validator;
+import com.intellij.javaee.ExternalResourceManager;
+import com.intellij.javaee.ExternalResourceManagerEx;
+import com.intellij.javaee.ExternalResourceManagerImpl;
+import com.intellij.javaee.UriUtil;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.*;
+import com.intellij.patterns.StandardPatterns;
+import com.intellij.patterns.StringPattern;
+import com.intellij.patterns.XmlPatterns;
+import com.intellij.psi.*;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.filters.ElementFilter;
+import com.intellij.psi.filters.XmlTagFilter;
+import com.intellij.psi.filters.position.FilterPattern;
+import com.intellij.psi.impl.source.html.HtmlDocumentImpl;
+import com.intellij.psi.impl.source.tree.CompositeElement;
+import com.intellij.psi.impl.source.tree.LeafElement;
+import com.intellij.psi.impl.source.xml.XmlEntityRefImpl;
+import com.intellij.psi.scope.processor.FilterElementProcessor;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.*;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.text.XmlCharsetDetector;
+import com.intellij.xml.*;
+import com.intellij.xml.impl.schema.ComplexTypeDescriptor;
+import com.intellij.xml.impl.schema.TypeDescriptor;
+import com.intellij.xml.impl.schema.XmlElementDescriptorImpl;
+import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
+import com.intellij.xml.index.IndexedRelevantResource;
+import com.intellij.xml.index.XmlNamespaceIndex;
+import com.intellij.xml.index.XsdNamespaceBuilder;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * @author Mike
+ */
+public class XmlUtil {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.XmlUtil");
+
+  @NonNls public static final String TAGLIB_1_2_URI = "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd";
+
+  @NonNls public static final String XML_SCHEMA_URI = "http://www.w3.org/2001/XMLSchema";
+  @NonNls public static final String XML_SCHEMA_URI2 = "http://www.w3.org/1999/XMLSchema";
+  @NonNls public static final String XML_SCHEMA_URI3 = "http://www.w3.org/2000/10/XMLSchema";
+  public static final String[] SCHEMA_URIS = {XML_SCHEMA_URI, XML_SCHEMA_URI2, XML_SCHEMA_URI3};
+  @NonNls public static final String XML_SCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";
+
+  @NonNls public static final String XSLT_URI = "http://www.w3.org/1999/XSL/Transform";
+  @NonNls public static final String XINCLUDE_URI = "http://www.w3.org/2001/XInclude";
+
+  @NonNls public static final String ANT_URI = "http://ant.apache.org/schema.xsd";
+  @NonNls public static final String XHTML_URI = "http://www.w3.org/1999/xhtml";
+  @NonNls public static final String HTML_URI = "http://www.w3.org/1999/html";
+  @NonNls public static final String EMPTY_URI = "";
+  @NonNls public static final Key<String> TEST_PATH = Key.create("TEST PATH");
+  @NonNls public static final String JSP_URI = "http://java.sun.com/JSP/Page";
+  @NonNls public static final String ANY_URI = "http://www.intellij.net/ns/any";
+
+  @NonNls public static final String JSTL_CORE_URI = "http://java.sun.com/jsp/jstl/core";
+  @NonNls public static final String JSTL_CORE_URI2 = "http://java.sun.com/jstl/core";
+  @NonNls public static final String JSTL_CORE_URI3 = "http://java.sun.com/jstl/core_rt";
+  @NonNls public static final String[] JSTL_CORE_URIS = {JSTL_CORE_URI, JSTL_CORE_URI2, JSTL_CORE_URI3};
+
+  @NonNls public static final String JSF_HTML_URI = "http://java.sun.com/jsf/html";
+  @NonNls public static final String JSF_CORE_URI = "http://java.sun.com/jsf/core";
+
+  @NonNls public static final String JSTL_FORMAT_URI = "http://java.sun.com/jsp/jstl/fmt";
+  @NonNls public static final String JSTL_FORMAT_URI2 = "http://java.sun.com/jstl/fmt";
+  @NonNls private static final String JSTL_FORMAT_URI3 = "http://java.sun.com/jstl/fmt_rt";
+  @NonNls public static final String[] JSTL_FORMAT_URIS = {JSTL_FORMAT_URI, JSTL_FORMAT_URI2, JSTL_FORMAT_URI3};
+
+  @NonNls public static final String SPRING_URI = "http://www.springframework.org/tags";
+  @NonNls public static final String SPRING_FORMS_URI = "http://www.springframework.org/tags/form";
+  @NonNls public static final String STRUTS_BEAN_URI = "http://struts.apache.org/tags-bean";
+  @NonNls public static final String STRUTS_BEAN_URI2 = "http://jakarta.apache.org/struts/tags-bean";
+  @NonNls public static final String APACHE_I18N_URI = "http://jakarta.apache.org/taglibs/i18n-1.0";
+  @NonNls public static final String STRUTS_LOGIC_URI = "http://struts.apache.org/tags-logic";
+  @NonNls public static final String STRUTS_HTML_URI = "http://struts.apache.org/tags-html";
+  @NonNls public static final String STRUTS_HTML_URI2 = "http://jakarta.apache.org/struts/tags-html";
+
+  @NonNls public static final String APACHE_TRINIDAD_URI = "http://myfaces.apache.org/trinidad";
+  @NonNls public static final String APACHE_TRINIDAD_HTML_URI = "http://myfaces.apache.org/trinidad/html";
+
+  @NonNls public static final String XSD_SIMPLE_CONTENT_TAG = "simpleContent";
+  @NonNls public static final String NO_NAMESPACE_SCHEMA_LOCATION_ATT = "noNamespaceSchemaLocation";
+  @NonNls public static final String SCHEMA_LOCATION_ATT = "schemaLocation";
+  @NonNls public static final String[] WEB_XML_URIS =
+    {"http://java.sun.com/xml/ns/j2ee", "http://java.sun.com/xml/ns/javaee", "http://java.sun.com/dtd/web-app_2_3.dtd",
+      "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"};
+  @NonNls public static final String FACELETS_URI = "http://java.sun.com/jsf/facelets";
+  @NonNls public static final String JSTL_FUNCTIONS_URI = "http://java.sun.com/jsp/jstl/functions";
+  @NonNls public static final String JSTL_FUNCTIONS_URI2 = "http://java.sun.com/jstl/functions";
+  @NonNls public static final String JSTL_FN_FACELET_URI = "com.sun.facelets.tag.jstl.fn.JstlFnLibrary";
+  @NonNls public static final String JSTL_CORE_FACELET_URI = "com.sun.facelets.tag.jstl.core.JstlCoreLibrary";
+  @NonNls public static final String TARGET_NAMESPACE_ATTR_NAME = "targetNamespace";
+  @NonNls public static final String XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
+  public static final List<String> ourSchemaUrisList = Arrays.asList(SCHEMA_URIS);
+  public static final Key<Boolean> ANT_FILE_SIGN = new Key<Boolean>("FORCED ANT FILE");
+  @NonNls public static final String TAG_DIR_NS_PREFIX = "urn:jsptagdir:";
+  @NonNls public static final String VALUE_ATTR_NAME = "value";
+  @NonNls public static final String ENUMERATION_TAG_NAME = "enumeration";
+  @NonNls public static final String HTML4_LOOSE_URI = "http://www.w3.org/TR/html4/loose.dtd";
+  @NonNls public static final String WSDL_SCHEMA_URI = "http://schemas.xmlsoap.org/wsdl/";
+  public static final Key<PsiAnchor> ORIGINAL_ELEMENT = Key.create("ORIGINAL_ELEMENT");
+
+  public static final String XHTML4_SCHEMA_LOCATION;
+  public final static Key<Boolean> BUILDING_DOM_STUBS = Key.create("building dom stubs...");
+
+  private XmlUtil() {
+  }
+
+  static {
+    final URL xhtml4SchemaLocationUrl = XmlUtil.class.getResource(ExternalResourceManagerImpl.STANDARD_SCHEMAS + "xhtml1-transitional.xsd");
+    XHTML4_SCHEMA_LOCATION = VfsUtilCore.urlToPath(VfsUtil.fixURLforIDEA(FileUtil.unquote(xhtml4SchemaLocationUrl.toExternalForm())));
+  }
+
+  @Nullable
+  public static String getSchemaLocation(XmlTag tag, String namespace) {
+    final String uri = ExternalResourceManagerEx.getInstanceEx().getResourceLocation(namespace, tag.getProject());
+    if (uri != null && !uri.equals(namespace)) return uri;
+
+    while (true) {
+      if (namespace.isEmpty()) {
+        final String attributeValue = tag.getAttributeValue("noNamespaceSchemaLocation", XML_SCHEMA_INSTANCE_URI);
+        if (attributeValue != null) return attributeValue;
+      }
+      else {
+        String schemaLocation = tag.getAttributeValue("schemaLocation", XML_SCHEMA_INSTANCE_URI);
+        if (schemaLocation != null) {
+          int start = schemaLocation.indexOf(namespace);
+          if (start >= 0) {
+            start += namespace.length();
+            final StringTokenizer tokenizer = new StringTokenizer(schemaLocation.substring(start + 1));
+            if (tokenizer.hasMoreTokens()) {
+              return tokenizer.nextToken();
+            }
+            else {
+              return null;
+            }
+          }
+        }
+      }
+      if (tag.getParent() instanceof XmlTag) {
+        tag = (XmlTag)tag.getParent();
+      }
+      else {
+        break;
+      }
+    }
+    return null;
+  }
+
+  @Nullable
+  public static String findNamespacePrefixByURI(XmlFile file, @NonNls String uri) {
+    final XmlTag tag = file.getRootTag();
+    if (tag == null) return null;
+
+    for (XmlAttribute attribute : tag.getAttributes()) {
+      if (attribute.getName().startsWith("xmlns:") && attribute.getValue().equals(uri)) {
+        return attribute.getName().substring("xmlns:".length());
+      }
+      if ("xmlns".equals(attribute.getName()) && attribute.getValue().equals(uri)) return "";
+    }
+
+    return null;
+  }
+
+  public static String[] findNamespacesByURI(XmlFile file, String uri) {
+    if (file == null) return ArrayUtil.EMPTY_STRING_ARRAY;
+    final XmlDocument document = file.getDocument();
+    if (document == null) return ArrayUtil.EMPTY_STRING_ARRAY;
+    final XmlTag tag = document.getRootTag();
+    if (tag == null) return ArrayUtil.EMPTY_STRING_ARRAY;
+    XmlAttribute[] attributes = tag.getAttributes();
+
+
+    List<String> result = new ArrayList<String>();
+
+    for (XmlAttribute attribute : attributes) {
+      if (attribute.getName().startsWith("xmlns:") && attribute.getValue().equals(uri)) {
+        result.add(attribute.getName().substring("xmlns:".length()));
+      }
+      if ("xmlns".equals(attribute.getName()) && attribute.getValue().equals(uri)) result.add("");
+    }
+
+    return ArrayUtil.toStringArray(result);
+  }
+
+  @Nullable
+  public static String getXsiNamespace(XmlFile file) {
+    return findNamespacePrefixByURI(file, XML_SCHEMA_INSTANCE_URI);
+  }
+
+  @Nullable
+  public static XmlFile findNamespace(@NotNull PsiFile base, @NotNull String nsLocation) {
+    final String location = ExternalResourceManager.getInstance().getResourceLocation(nsLocation, base.getProject());
+    if (!location.equals(nsLocation)) { // is mapped
+      return findXmlFile(base, location);
+    }
+    final XmlFile xmlFile = XmlSchemaProvider.findSchema(location, base);
+    return xmlFile == null ? findXmlFile(base, location) : xmlFile;
+  }
+
+  @Nullable
+  public static XmlFile findNamespaceByLocation(@NotNull PsiFile base, @NotNull String nsLocation) {
+    final String location = ExternalResourceManager.getInstance().getResourceLocation(nsLocation, base.getProject());
+    return findXmlFile(base, location);
+  }
+
+  public static Collection<XmlFile> findNSFilesByURI(String namespace, final Project project, Module module) {
+    final List<IndexedRelevantResource<String,XsdNamespaceBuilder>>
+      resources = XmlNamespaceIndex.getResourcesByNamespace(namespace, project, module);
+    final PsiManager psiManager = PsiManager.getInstance(project);
+    return ContainerUtil.mapNotNull(resources, new NullableFunction<IndexedRelevantResource<String, XsdNamespaceBuilder>, XmlFile>() {
+      public XmlFile fun(IndexedRelevantResource<String, XsdNamespaceBuilder> resource) {
+        PsiFile file = psiManager.findFile(resource.getFile());
+        return file instanceof XmlFile ? (XmlFile)file : null;
+      }
+    });
+  }
+
+  @Nullable
+  public static XmlFile findXmlFile(PsiFile base, @NotNull String uri) {
+    PsiFile result = null;
+
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      String data = base.getOriginalFile().getUserData(TEST_PATH);
+
+      if (data != null) {
+        String filePath = data + "/" + uri;
+        final VirtualFile path = LocalFileSystem.getInstance().findFileByPath(filePath.replace(File.separatorChar, '/'));
+        if (path != null) {
+          result = base.getManager().findFile(path);
+        }
+      }
+    }
+    if (result == null) {
+      result = findRelativeFile(uri, base);
+    }
+
+    if (result instanceof XmlFile) {
+      return (XmlFile)result;
+    }
+
+    return null;
+  }
+
+  @Nullable
+  public static XmlToken getTokenOfType(PsiElement element, IElementType type) {
+    if (element == null) {
+      return null;
+    }
+
+    PsiElement[] children = element.getChildren();
+
+    for (PsiElement child : children) {
+      if (child instanceof XmlToken) {
+        XmlToken token = (XmlToken)child;
+
+        if (token.getTokenType() == type) {
+          return token;
+        }
+      }
+    }
+
+    return null;
+  }
+
+  public static boolean processXmlElements(XmlElement element, PsiElementProcessor processor, boolean deepFlag) {
+    return processXmlElements(element, processor, deepFlag, false);
+  }
+
+  public static boolean processXmlElements(XmlElement element, PsiElementProcessor processor, boolean deepFlag, boolean wideFlag) {
+    if (element == null) return true;
+    PsiFile baseFile = element.isValid() ? element.getContainingFile() : null;
+    return processXmlElements(element, processor, deepFlag, wideFlag, baseFile);
+  }
+
+  public static boolean processXmlElements(final XmlElement element,
+                                           final PsiElementProcessor processor,
+                                           final boolean deepFlag,
+                                           final boolean wideFlag,
+                                           final PsiFile baseFile) {
+    return processXmlElements(element, processor, deepFlag, wideFlag, baseFile, true);
+  }
+
+  public static boolean processXmlElements(final XmlElement element,
+                                           final PsiElementProcessor processor,
+                                           final boolean deepFlag,
+                                           final boolean wideFlag,
+                                           final PsiFile baseFile,
+                                           boolean processIncludes) {
+    return new XmlElementProcessor(processor, baseFile).processXmlElements(element, deepFlag, wideFlag, processIncludes);
+  }
+
+  public static boolean processXmlElementChildren(final XmlElement element, final PsiElementProcessor processor, final boolean deepFlag) {
+    final XmlElementProcessor p = new XmlElementProcessor(processor, element.getContainingFile());
+
+    final boolean wideFlag = false;
+    for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
+      if (!p.processElement(child, deepFlag, wideFlag, true) && !wideFlag) return false;
+    }
+
+    return true;
+  }
+
+  public static boolean tagFromTemplateFramework(@NotNull final XmlTag tag) {
+    final String ns = tag.getNamespace();
+    return nsFromTemplateFramework(ns);
+  }
+
+  public static boolean nsFromTemplateFramework(final String ns) {
+    return XSLT_URI.equals(ns) || XINCLUDE_URI.equals(ns);
+  }
+
+
+  public static char getCharFromEntityRef(@NonNls String text) {
+    //LOG.assertTrue(text.startsWith("&#") && text.endsWith(";"));
+    if (text.charAt(1) != '#') {
+      try {
+        text = text.substring(1, text.length() - 1);
+      }
+      catch (StringIndexOutOfBoundsException e) {
+        LOG.error("Cannot parse ref: '" + text + "'", e);
+      }
+      return XmlTagUtil.getCharacterByEntityName(text);
+    }
+    text = text.substring(2, text.length() - 1);
+    try {
+      int code;
+      if (StringUtil.startsWithChar(text, 'x')) {
+        text = text.substring(1);
+        code = Integer.parseInt(text, 16);
+      }
+      else {
+        code = Integer.parseInt(text);
+      }
+      return (char)code;
+    }
+    catch (NumberFormatException e) {
+      return 0;
+    }
+  }
+
+  public static boolean attributeFromTemplateFramework(@NonNls final String name, final XmlTag tag) {
+    return "jsfc".equals(name) && tag.getNSDescriptor(JSF_HTML_URI, true) != null;
+  }
+
+  @Nullable
+  public static String getTargetSchemaNsFromTag(@Nullable final XmlTag xmlTag) {
+    if (xmlTag == null) return null;
+    String targetNamespace = xmlTag.getAttributeValue(TARGET_NAMESPACE_ATTR_NAME, XML_SCHEMA_URI);
+    if (targetNamespace == null) targetNamespace = xmlTag.getAttributeValue(TARGET_NAMESPACE_ATTR_NAME, XML_SCHEMA_URI2);
+    if (targetNamespace == null) targetNamespace = xmlTag.getAttributeValue(TARGET_NAMESPACE_ATTR_NAME, XML_SCHEMA_URI3);
+    return targetNamespace;
+  }
+
+  @Nullable
+  public static XmlTag getSchemaSimpleContent(@NotNull XmlTag tag) {
+    XmlElementDescriptor descriptor = tag.getDescriptor();
+
+    if (descriptor instanceof XmlElementDescriptorImpl) {
+      final TypeDescriptor type = ((XmlElementDescriptorImpl)descriptor).getType(tag);
+
+      if (type instanceof ComplexTypeDescriptor) {
+        final XmlTag[] simpleContent = new XmlTag[1];
+
+        processXmlElements(((ComplexTypeDescriptor)type).getDeclaration(), new PsiElementProcessor() {
+          public boolean execute(@NotNull final PsiElement element) {
+            if (element instanceof XmlTag) {
+              final XmlTag tag = (XmlTag)element;
+              @NonNls final String s = ((XmlTag)element).getLocalName();
+
+              if ((s.equals(XSD_SIMPLE_CONTENT_TAG) ||
+                   s.equals("restriction") && "string".equals(findLocalNameByQualifiedName(tag.getAttributeValue("base")))) &&
+                  tag.getNamespace().equals(XML_SCHEMA_URI)) {
+                simpleContent[0] = tag;
+                return false;
+              }
+            }
+
+            return true;
+          }
+        }, true);
+
+        return simpleContent[0];
+      }
+    }
+    return null;
+  }
+
+  public static <T extends PsiElement> void doDuplicationCheckForElements(final T[] elements,
+                                                                          final Map<String, T> presentNames,
+                                                                          DuplicationInfoProvider<T> provider,
+                                                                          final Validator.ValidationHost host) {
+    for (T t : elements) {
+      final String name = provider.getName(t);
+      if (name == null) continue;
+
+      final String nameKey = provider.getNameKey(t, name);
+
+      if (presentNames.containsKey(nameKey)) {
+        final T psiElement = presentNames.get(nameKey);
+        final String message = XmlBundle.message("duplicate.declaration", nameKey);
+
+        if (psiElement != null) {
+          presentNames.put(nameKey, null);
+
+          host.addMessage(provider.getNodeForMessage(psiElement), message, Validator.ValidationHost.ERROR);
+        }
+
+        host.addMessage(provider.getNodeForMessage(t), message, Validator.ValidationHost.ERROR);
+      }
+      else {
+        presentNames.put(nameKey, t);
+      }
+    }
+  }
+
+  public static String getEntityValue(final XmlEntityRef entityRef) {
+    final XmlEntityDecl decl = entityRef.resolve(entityRef.getContainingFile());
+    if (decl != null) {
+      final XmlAttributeValue valueElement = decl.getValueElement();
+      if (valueElement != null) {
+        final String value = valueElement.getValue();
+        if (value != null) {
+          return value;
+        }
+      }
+    }
+    return entityRef.getText();
+  }
+
+  public static boolean isAntFile(final PsiFile file) {
+    if (file instanceof XmlFile) {
+      final XmlFile xmlFile = (XmlFile)file;
+      final XmlDocument document = xmlFile.getDocument();
+      if (document != null) {
+        final XmlTag tag = document.getRootTag();
+        if (tag != null && "project".equals(tag.getName()) && tag.getContext() instanceof XmlDocument) {
+          if (tag.getAttributeValue("default") != null) {
+            return true;
+          }
+          VirtualFile vFile = xmlFile.getOriginalFile().getVirtualFile();
+          if (vFile != null && vFile.getUserData(ANT_FILE_SIGN) != null) {
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  @Nullable
+  public static PsiFile findRelativeFile(String uri, PsiElement base) {
+    if (base instanceof PsiFile) {
+      PsiFile baseFile = (PsiFile)base;
+      VirtualFile file = UriUtil.findRelative(uri, baseFile.getOriginalFile());
+      if (file == null) return null;
+      return base.getManager().findFile(file);
+    }
+    else if (base instanceof PsiDirectory) {
+      PsiDirectory baseDir = (PsiDirectory)base;
+      VirtualFile file = UriUtil.findRelative(uri, baseDir);
+      if (file == null) return null;
+      return base.getManager().findFile(file);
+    }
+
+    return null;
+  }
+
+  @Nullable
+  public static String getCommentText(XmlComment comment) {
+    final PsiElement firstChild = comment.getFirstChild();
+    if (firstChild != null) {
+      final PsiElement nextSibling = firstChild.getNextSibling();
+      if (nextSibling instanceof XmlToken) {
+        final XmlToken token = (XmlToken)nextSibling;
+        if (token.getTokenType() == XmlTokenType.XML_COMMENT_CHARACTERS) {
+          return token.getText();
+        }
+      }
+    }
+    return null;
+  }
+
+  @Nullable
+  public static PsiElement findNamespaceDeclaration(XmlElement xmlElement, String nsName) {
+    while (! (xmlElement instanceof XmlTag) && xmlElement != null) {
+      final PsiElement parent = xmlElement.getParent();
+      if (!(parent instanceof XmlElement)) return null;
+      xmlElement = (XmlElement)parent;
+    }
+    if (xmlElement != null) {
+      XmlTag tag = (XmlTag)xmlElement;
+      while (tag != null) {
+        for (XmlAttribute attribute : tag.getAttributes()) {
+          if (attribute.isNamespaceDeclaration() && attribute.getLocalName().equals(nsName)) {
+            return attribute;
+          }
+        }
+        tag = tag.getParentTag();
+      }
+    }
+    return null;
+  }
+
+  public static void reformatTagStart(XmlTag tag) {
+    ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode());
+    if (child == null) {
+      CodeStyleManager.getInstance(tag.getProject()).reformat(tag);
+    }
+    else {
+      CodeStyleManager.getInstance(tag.getProject()).reformatRange(tag, tag.getTextRange().getStartOffset(), child.getTextRange().getEndOffset());
+    }
+  }
+
+  @Nullable
+  public static XmlElementDescriptor getDescriptorFromContext(@NotNull XmlTag tag) {
+    PsiElement parent = tag.getParent();
+    if (parent instanceof XmlTag) {
+      XmlTag parentTag = (XmlTag)parent;
+      final XmlElementDescriptor parentDescriptor = parentTag.getDescriptor();
+
+      if (parentDescriptor != null) {
+        return XmlExtension.getExtension(tag.getContainingFile()).getElementDescriptor(tag, parentTag, parentDescriptor);
+      }
+    }
+    return null;
+  }
+
+  public static void expandTag(@NotNull XmlTag tag) {
+    XmlTag newTag = XmlElementFactory.getInstance(tag.getProject()).createTagFromText('<' + tag.getName() + "></" + tag.getName() + '>');
+
+    ASTNode node = tag.getNode();
+    if (!(node instanceof CompositeElement)) return;
+    CompositeElement compositeElement = (CompositeElement)node;
+
+    final LeafElement emptyTagEnd = (LeafElement)XmlChildRole.EMPTY_TAG_END_FINDER.findChild(compositeElement);
+    if (emptyTagEnd == null) return;
+
+    compositeElement.removeChild(emptyTagEnd);
+    PsiElement[] children = newTag.getChildren();
+
+    compositeElement.addChildren(children[2].getNode(), null, null);
+  }
+
+  public static String getDefaultXhtmlNamespace(Project project) {
+    final String doctype = ExternalResourceManagerEx.getInstanceEx().getDefaultHtmlDoctype(project);
+    return Html5SchemaProvider.HTML5_SCHEMA_LOCATION.equals(doctype)
+           ? Html5SchemaProvider.XHTML5_SCHEMA_LOCATION
+           : doctype;
+  }
+
+  public static CharSequence getLocalName(final CharSequence tagName) {
+    int pos = StringUtil.indexOf(tagName, ':');
+    if (pos == -1) {
+      return tagName;
+    }
+    return tagName.subSequence(pos + 1, tagName.length());
+  }
+
+  public static boolean isStubBuilding(PsiFile file) {
+    return Boolean.TRUE.equals(file.getUserData(BUILDING_DOM_STUBS));
+  }
+
+  private static class XmlElementProcessor {
+    private final PsiElementProcessor processor;
+    private final PsiFile targetFile;
+
+    XmlElementProcessor(PsiElementProcessor _processor, PsiFile _targetFile) {
+      processor = _processor;
+      targetFile = _targetFile;
+    }
+
+    private boolean processXmlElements(PsiElement element, boolean deepFlag, boolean wideFlag, boolean processIncludes) {
+      if (deepFlag) if (!processor.execute(element)) return false;
+
+      PsiElement startFrom = element.getFirstChild();
+
+      if (element instanceof XmlEntityRef) {
+        XmlEntityRef ref = (XmlEntityRef)element;
+
+        PsiElement newElement = parseEntityRef(targetFile, ref);
+
+        while (newElement != null) {
+          if (!processElement(newElement, deepFlag, wideFlag, processIncludes)) return false;
+          newElement = newElement.getNextSibling();
+        }
+
+        return true;
+      }
+      else if (element instanceof XmlConditionalSection) {
+        XmlConditionalSection xmlConditionalSection = (XmlConditionalSection)element;
+        if (!xmlConditionalSection.isIncluded(targetFile)) return true;
+        startFrom = xmlConditionalSection.getBodyStart();
+      }
+      else if (processIncludes && XmlIncludeHandler.isXInclude(element)) {
+        for (PsiElement psiElement : InclusionProvider.getIncludedTags((XmlTag)element)) {
+          if (!processElement(psiElement, deepFlag, wideFlag, true)) return false;
+        }
+      }
+
+      for (PsiElement child = startFrom; child != null; child = child.getNextSibling()) {
+        if (!processElement(child, deepFlag, wideFlag, processIncludes) && !wideFlag) return false;
+      }
+
+      return true;
+    }
+
+    private boolean processElement(PsiElement child, boolean deepFlag, boolean wideFlag, boolean processIncludes) {
+      if (deepFlag) {
+        if (!processXmlElements(child, true, wideFlag, processIncludes)) {
+          return false;
+        }
+      }
+      else {
+        if (child instanceof XmlEntityRef) {
+          if (!processXmlElements(child, false, wideFlag, processIncludes)) return false;
+        }
+        else if (child instanceof XmlConditionalSection) {
+          if (!processXmlElements(child, false, wideFlag, processIncludes)) return false;
+        }
+        else if (processIncludes && XmlIncludeHandler.isXInclude(child)) {
+          if (!processXmlElements(child, false, wideFlag, processIncludes)) return false;
+        }
+        else if (!processor.execute(child)) return false;
+      }
+      if (targetFile != null && child instanceof XmlEntityDecl) {
+        XmlEntityDecl xmlEntityDecl = (XmlEntityDecl)child;
+        XmlEntityRefImpl.cacheParticularEntity(targetFile, xmlEntityDecl);
+      }
+      return true;
+    }
+  }
+
+  private static PsiElement parseEntityRef(PsiFile targetFile, XmlEntityRef ref) {
+    XmlEntityDecl.EntityContextType type = getContextType(ref);
+
+    {
+      final XmlEntityDecl entityDecl = ref.resolve(targetFile);
+      if (entityDecl != null) return parseEntityDecl(entityDecl, targetFile, type, ref);
+    }
+
+    PsiElement e = ref;
+    while (e != null) {
+      if (e.getUserData(XmlElement.INCLUDING_ELEMENT) != null) {
+        e = e.getUserData(XmlElement.INCLUDING_ELEMENT);
+        final PsiFile f = e.getContainingFile();
+        if (f != null) {
+          final XmlEntityDecl entityDecl = ref.resolve(targetFile);
+          if (entityDecl != null) return parseEntityDecl(entityDecl, targetFile, type, ref);
+        }
+
+        continue;
+      }
+      if (e instanceof PsiFile) {
+        PsiFile refFile = (PsiFile)e;
+        final XmlEntityDecl entityDecl = ref.resolve(refFile);
+        if (entityDecl != null) return parseEntityDecl(entityDecl, targetFile, type, ref);
+        break;
+      }
+
+      e = e.getParent();
+    }
+
+    final PsiElement element = ref.getUserData(XmlElement.DEPENDING_ELEMENT);
+    if (element instanceof XmlFile) {
+      final XmlEntityDecl entityDecl = ref.resolve((PsiFile)element);
+      if (entityDecl != null) return parseEntityDecl(entityDecl, targetFile, type, ref);
+    }
+
+    return null;
+  }
+
+  private static XmlEntityDecl.EntityContextType getContextType(XmlEntityRef ref) {
+    XmlEntityDecl.EntityContextType type = XmlEntityDecl.EntityContextType.GENERIC_XML;
+    PsiElement temp = ref;
+    while (temp != null) {
+      if (temp instanceof XmlAttributeDecl) {
+        type = XmlEntityDecl.EntityContextType.ATTRIBUTE_SPEC;
+      }
+      else if (temp instanceof XmlElementDecl) {
+        type = XmlEntityDecl.EntityContextType.ELEMENT_CONTENT_SPEC;
+      }
+      else if (temp instanceof XmlAttlistDecl) {
+        type = XmlEntityDecl.EntityContextType.ATTLIST_SPEC;
+      }
+      else if (temp instanceof XmlEntityDecl) {
+        type = XmlEntityDecl.EntityContextType.ENTITY_DECL_CONTENT;
+      }
+      else if (temp instanceof XmlEnumeratedType) {
+        type = XmlEntityDecl.EntityContextType.ENUMERATED_TYPE;
+      }
+      else if (temp instanceof XmlAttributeValue) {
+        type = XmlEntityDecl.EntityContextType.ATTR_VALUE;
+      }
+      else {
+        temp = temp.getContext();
+        continue;
+      }
+      break;
+    }
+    return type;
+  }
+
+  private static final Key<CachedValue<PsiElement>> PARSED_DECL_KEY = Key.create("PARSED_DECL_KEY");
+
+  private static PsiElement parseEntityDecl(final XmlEntityDecl entityDecl,
+                                            final PsiFile targetFile,
+                                            final XmlEntityDecl.EntityContextType type,
+                                            final XmlEntityRef entityRef) {
+    synchronized (PsiLock.LOCK) { // we depend on targetFile and entityRef
+      CachedValue<PsiElement> value = entityRef.getUserData(PARSED_DECL_KEY);
+      //    return entityDecl.parse(targetFile, type);
+
+      if (value == null) {
+        value = CachedValuesManager.getManager(entityDecl.getProject()).createCachedValue(new CachedValueProvider<PsiElement>() {
+          public Result<PsiElement> compute() {
+            final PsiElement res = entityDecl.parse(targetFile, type, entityRef);
+            if (res == null) return new Result<PsiElement>(res, targetFile);
+            if (!entityDecl.isInternalReference()) XmlEntityRefImpl.copyEntityCaches(res.getContainingFile(), targetFile);
+            return new Result<PsiElement>(res, res.getUserData(XmlElement.DEPENDING_ELEMENT), entityDecl, targetFile, entityRef);
+          }
+        }, false);
+        entityRef.putUserData(PARSED_DECL_KEY, value);
+      }
+
+      return value.getValue();
+    }
+  }
+
+  /**
+   * add child to the parent according to DTD/Schema element ordering
+   *
+   * @return newly added child
+   */
+  public static XmlTag addChildTag(XmlTag parent, XmlTag child) throws IncorrectOperationException {
+    return addChildTag(parent, child, -1);
+  }
+
+  public static XmlTag addChildTag(XmlTag parent, XmlTag child, int index) throws IncorrectOperationException {
+
+    // bug in PSI: cannot add child to <tag/>
+    if (parent.getSubTags().length == 0 && parent.getText().endsWith("/>")) {
+      final XmlElementFactory factory = XmlElementFactory.getInstance(parent.getProject());
+      final String name = parent.getName();
+      final String text = parent.getText();
+      final XmlTag tag = factory.createTagFromText(text.substring(0, text.length() - 2) + "></" + name + ">");
+      parent = (XmlTag)parent.replace(tag);
+    }
+
+    final XmlElementDescriptor parentDescriptor = parent.getDescriptor();
+    final XmlTag[] subTags = parent.getSubTags();
+    if (parentDescriptor == null || subTags.length == 0) return (XmlTag)parent.add(child);
+    int subTagNum = -1;
+
+    for (XmlElementDescriptor childElementDescriptor : parentDescriptor.getElementsDescriptors(parent)) {
+      final String childElementName = childElementDescriptor.getName();
+      int prevSubTagNum = subTagNum;
+      while (subTagNum < subTags.length - 1 && subTags[subTagNum + 1].getName().equals(childElementName)) {
+        subTagNum++;
+      }
+      if (childElementName.equals(child.getLocalName())) {
+        // insert child just after anchor
+        // insert into the position specified by index
+        subTagNum = index == -1 || index > subTagNum - prevSubTagNum ? subTagNum : prevSubTagNum + index;
+        return (XmlTag)(subTagNum == -1 ? parent.addBefore(child, subTags[0]) : parent.addAfter(child, subTags[subTagNum]));
+      }
+    }
+    return (XmlTag)parent.add(child);
+  }
+
+  /**
+   * @see XmlTag#getAttributeValue(String)
+   */
+  @Nullable
+  @Deprecated
+  public static String getAttributeValue(XmlTag tag, String name) {
+    for (XmlAttribute attribute : tag.getAttributes()) {
+      if (name.equals(attribute.getName())) return attribute.getValue();
+    }
+    return null;
+  }
+
+  // Read the function name and parameter names to find out what this function does... :-)
+  @Nullable
+  public static XmlTag find(String subTag, String withValue, String forTag, XmlTag insideRoot) {
+    final XmlTag[] forTags = insideRoot.findSubTags(forTag);
+
+    for (XmlTag tag : forTags) {
+      final XmlTag[] allTags = tag.findSubTags(subTag);
+
+      for (XmlTag curTag : allTags) {
+        if (curTag.getName().equals(subTag) && curTag.getValue().getTrimmedText().equalsIgnoreCase(withValue)) {
+          return tag;
+        }
+      }
+    }
+
+    return null;
+  }
+
+  @Nullable
+  @NonNls
+  public static String[][] getDefaultNamespaces(final XmlDocument document) {
+    final XmlFile file = getContainingFile(document);
+
+    final XmlTag tag = document.getRootTag();
+    if (tag == null) return null;
+
+    if (file != null) {
+      @NotNull final XmlFileNSInfoProvider[] nsProviders = Extensions.getExtensions(XmlFileNSInfoProvider.EP_NAME);
+
+      NextProvider:
+      for (XmlFileNSInfoProvider nsProvider : nsProviders) {
+        final String[][] pairs = nsProvider.getDefaultNamespaces(file);
+        if (pairs != null && pairs.length > 0) {
+
+          for (final String[] nsMapping : pairs) {
+            if (nsMapping == null || nsMapping.length != 2 || nsMapping[0] == null || nsMapping[1] == null) {
+              LOG.debug("NSInfoProvider " + nsProvider + " gave wrong info about " + file.getVirtualFile());
+              continue NextProvider;
+            }
+          }
+          return pairs;
+        }
+      }
+    }
+
+    String namespace = getDtdUri(document);
+
+    if (namespace != null) {
+      boolean overrideNamespaceFromDocType = false;
+
+      if (file != null) {
+        final FileType fileType = file.getFileType();
+        overrideNamespaceFromDocType =
+          fileType == StdFileTypes.HTML || fileType == StdFileTypes.XHTML || fileType == StdFileTypes.JSPX || fileType == StdFileTypes.JSP;
+      }
+
+      if (!overrideNamespaceFromDocType) return new String[][]{new String[]{"", namespace}};
+    }
+
+    if ("taglib".equals(tag.getName())) {
+      return new String[][]{new String[]{"", TAGLIB_1_2_URI}};
+    }
+
+    if (file != null) {
+
+      final Language language = file.getLanguage();
+      if (language == HTMLLanguage.INSTANCE || language == XHTMLLanguage.INSTANCE) {
+        return new String[][]{new String[]{"", XHTML_URI}};
+        }
+      }
+
+    return null;
+  }
+  
+  @Nullable
+  public static String getDtdUri(XmlDocument document) {
+    XmlProlog prolog = document.getProlog();
+    if (prolog != null) {
+      return getDtdUri( prolog.getDoctype() );
+    }
+    return null;
+  }
+
+  @Nullable
+  public static String getDtdUri(XmlDoctype doctype) {
+    if (doctype != null) {
+      String docType = doctype.getDtdUri();
+      if (docType == null) {
+        final String publicId = doctype.getPublicId();
+        if (PsiTreeUtil.getParentOfType(doctype, XmlDocument.class) instanceof HtmlDocumentImpl &&
+            publicId != null &&
+            publicId.indexOf("-//W3C//DTD HTML") != -1) {
+          return HTML4_LOOSE_URI;
+        }
+        else if (HtmlUtil.isHtml5Doctype(doctype)) {
+          docType = doctype.getLanguage() instanceof HTMLLanguage
+                    ? Html5SchemaProvider.HTML5_SCHEMA_LOCATION
+                    : Html5SchemaProvider.XHTML5_SCHEMA_LOCATION;
+        }
+      }
+      return docType;
+    }
+    return null;
+  }
+
+  private static void computeTag(XmlTag tag,
+                                 final Map<String, List<String>> tagsMap,
+                                 final Map<String, List<MyAttributeInfo>> attributesMap,
+                                 final boolean processIncludes) {
+    if (tag == null) {
+      return;
+    }
+    final String tagName = tag.getName();
+
+    List<MyAttributeInfo> list = attributesMap.get(tagName);
+    if (list == null) {
+      list = new ArrayList<MyAttributeInfo>();
+      final XmlAttribute[] attributes = tag.getAttributes();
+      for (final XmlAttribute attribute : attributes) {
+        list.add(new MyAttributeInfo(attribute.getName()));
+      }
+    }
+    else {
+      final XmlAttribute[] attributes = tag.getAttributes();
+      ContainerUtil.sort(list);
+      Arrays.sort(attributes, new Comparator<XmlAttribute>() {
+        public int compare(XmlAttribute attr1, XmlAttribute attr2) {
+          return attr1.getName().compareTo(attr2.getName());
+        }
+      });
+
+      final Iterator<MyAttributeInfo> iter = list.iterator();
+      list = new ArrayList<MyAttributeInfo>();
+      int index = 0;
+      while (iter.hasNext()) {
+        final MyAttributeInfo info = iter.next();
+        boolean requiredFlag = false;
+        while (attributes.length > index) {
+          if (info.compareTo(attributes[index]) != 0) {
+            if (info.compareTo(attributes[index]) < 0) {
+              break;
+            }
+            if (attributes[index].getValue() != null) list.add(new MyAttributeInfo(attributes[index].getName(), false));
+            index++;
+          }
+          else {
+            requiredFlag = true;
+            index++;
+            break;
+          }
+        }
+        info.myRequired &= requiredFlag;
+        list.add(info);
+      }
+      while (attributes.length > index) {
+        if (attributes[index].getValue() != null) {
+          list.add(new MyAttributeInfo(attributes[index++].getName(), false));
+        }
+        else {
+          index++;
+        }
+      }
+    }
+    attributesMap.put(tagName, list);
+    final List<String> tags = tagsMap.get(tagName) != null ? tagsMap.get(tagName) : new ArrayList<String>();
+    tagsMap.put(tagName, tags);
+    PsiFile file = tag.isValid() ? tag.getContainingFile() : null;
+    processXmlElements(tag, new FilterElementProcessor(XmlTagFilter.INSTANCE) {
+      public void add(PsiElement element) {
+        XmlTag tag = (XmlTag)element;
+        if (!tags.contains(tag.getName())) {
+          tags.add(tag.getName());
+        }
+        computeTag(tag, tagsMap, attributesMap, processIncludes);
+      }
+    }, false, false, file, processIncludes);
+    /*tag.processElements(new FilterElementProcessor(XmlTagFilter.INSTANCE) {
+      public void add(PsiElement element) {
+        XmlTag tag = (XmlTag)element;
+        if (!tags.contains(tag.getName())) {
+          tags.add(tag.getName());
+        }
+        computeTag(tag, tagsMap, attributesMap);
+      }
+    }, tag);*/
+  }
+
+  @Nullable
+  public static XmlElementDescriptor findXmlDescriptorByType(final XmlTag xmlTag) {
+    return findXmlDescriptorByType(xmlTag, null);
+  }
+
+  @Nullable
+  public static XmlElementDescriptor findXmlDescriptorByType(final XmlTag xmlTag, @Nullable XmlTag context) {
+    String type = xmlTag.getAttributeValue("type", XML_SCHEMA_INSTANCE_URI);
+
+    if (type == null) {
+      String ns = xmlTag.getNamespace();
+      if (ourSchemaUrisList.indexOf(ns) >= 0) {
+        type = xmlTag.getAttributeValue("type", null);
+      }
+    }
+
+    XmlElementDescriptor elementDescriptor = null;
+    if (type != null) {
+      final String namespaceByPrefix = findNamespaceByPrefix(findPrefixByQualifiedName(type), xmlTag);
+      XmlNSDescriptor typeDecr = xmlTag.getNSDescriptor(namespaceByPrefix, true);
+
+      if (typeDecr == null && namespaceByPrefix.length() == 0) {
+        if (context != null) typeDecr = context.getNSDescriptor("", true);
+
+        if (typeDecr == null) {
+          final PsiFile containingFile = xmlTag.getContainingFile();
+          if (containingFile instanceof XmlFile) {
+            final XmlDocument document = ((XmlFile)containingFile).getDocument();
+            if (document != null) typeDecr = (XmlNSDescriptor)document.getMetaData();
+          }
+        }
+      }
+
+      if (typeDecr instanceof XmlNSDescriptorImpl) {
+        final XmlNSDescriptorImpl schemaDescriptor = (XmlNSDescriptorImpl)typeDecr;
+        elementDescriptor = schemaDescriptor.getDescriptorByType(type, xmlTag);
+      }
+    }
+
+    return elementDescriptor;
+  }
+
+  public static boolean collectEnumerationValues(final XmlTag element, final HashSet<String> variants) {
+    return processEnumerationValues(element, new Processor<XmlTag>() {
+      public boolean process(XmlTag xmlTag) {
+        variants.add(xmlTag.getAttributeValue(VALUE_ATTR_NAME));
+        return true;
+      }
+    });
+  }
+
+  public static boolean processEnumerationValues(final XmlTag element, final Processor<XmlTag> tagProcessor) {
+    boolean exaustiveEnum = true;
+
+    for (final XmlTag tag : element.getSubTags()) {
+      @NonNls final String localName = tag.getLocalName();
+
+      if (localName.equals(ENUMERATION_TAG_NAME)) {
+        final String attributeValue = tag.getAttributeValue(VALUE_ATTR_NAME);
+        if (attributeValue != null) tagProcessor.process(tag);
+      }
+      else if (localName.equals("union")) {
+        exaustiveEnum = false;
+        processEnumerationValues(tag, tagProcessor);
+      }
+      else if (!localName.equals("annotation")) {
+        // don't go into annotation
+        exaustiveEnum &= processEnumerationValues(tag, tagProcessor);
+      }
+    }
+    return exaustiveEnum;
+  }
+
+  /**
+   *
+   * @param xmlTag
+   * @param localName
+   * @param namespace
+   * @param bodyText pass null to create collapsed tag, empty string means creating expanded one
+   * @param enforceNamespacesDeep
+   * @return
+   */
+  public static XmlTag createChildTag(final XmlTag xmlTag,
+                                      String localName,
+                                      String namespace,
+                                      @Nullable String bodyText,
+                                      boolean enforceNamespacesDeep) {
+    String qname;
+    final String prefix = xmlTag.getPrefixByNamespace(namespace);
+    if (prefix != null && prefix.length() > 0) {
+      qname = prefix + ":" + localName;
+    }
+    else {
+      qname = localName;
+    }
+    try {
+      @NonNls StringBuilder tagStartBuilder = StringBuilderSpinAllocator.alloc();
+      String tagStart;
+      try {
+        tagStartBuilder.append(qname);
+        if (!StringUtil.isEmpty(namespace) && xmlTag.getPrefixByNamespace(namespace) == null &&
+            !(StringUtil.isEmpty(xmlTag.getNamespacePrefix()) && namespace.equals(xmlTag.getNamespace()))) {
+          tagStartBuilder.append(" xmlns=\"");
+          tagStartBuilder.append(namespace);
+          tagStartBuilder.append("\"");
+        }
+        tagStart = tagStartBuilder.toString();
+      }
+      finally {
+        StringBuilderSpinAllocator.dispose(tagStartBuilder);
+      }
+      Language language = xmlTag.getLanguage();
+      if (!(language instanceof HTMLLanguage)) language = StdFileTypes.XML.getLanguage();
+      XmlTag retTag;
+      if (bodyText != null) {
+        retTag = XmlElementFactory.getInstance(xmlTag.getProject())
+          .createTagFromText("<" + tagStart + ">" + bodyText + "</" + qname + ">", language);
+        if (enforceNamespacesDeep) {
+          retTag.acceptChildren(new XmlRecursiveElementVisitor() {
+            @Override
+            public void visitXmlTag(XmlTag tag) {
+              final String namespacePrefix = tag.getNamespacePrefix();
+              if (namespacePrefix.length() == 0) {
+                String qname;
+                if (prefix != null && prefix.length() > 0) {
+                  qname = prefix + ":" + tag.getLocalName();
+                }
+                else {
+                  qname = tag.getLocalName();
+                }
+                try {
+                  tag.setName(qname);
+                }
+                catch (IncorrectOperationException e) {
+                  LOG.error(e);
+                }
+              }
+              super.visitXmlTag(tag);
+            }
+          });
+        }
+      }
+      else {
+        retTag = XmlElementFactory.getInstance(xmlTag.getProject()).createTagFromText("<" + tagStart + "/>", language);
+      }
+      return retTag;
+    }
+    catch (IncorrectOperationException e) {
+      LOG.error(e);
+    }
+    return null;
+  }
+
+  @Nullable
+  public static Pair<XmlTagChild, XmlTagChild> findTagChildrenInRange(final PsiFile file, int startOffset, int endOffset) {
+    PsiElement elementAtStart = file.findElementAt(startOffset);
+    PsiElement elementAtEnd = file.findElementAt(endOffset - 1);
+    if (elementAtStart instanceof PsiWhiteSpace) {
+      startOffset = elementAtStart.getTextRange().getEndOffset();
+      elementAtStart = file.findElementAt(startOffset);
+    }
+    if (elementAtEnd instanceof PsiWhiteSpace) {
+      endOffset = elementAtEnd.getTextRange().getStartOffset();
+      elementAtEnd = file.findElementAt(endOffset - 1);
+    }
+    if (elementAtStart == null || elementAtEnd == null) return null;
+
+    XmlTagChild first = PsiTreeUtil.getParentOfType(elementAtStart, XmlTagChild.class);
+    if (first == null) return null;
+
+    if (first.getTextRange().getStartOffset() != startOffset) {
+      //Probably 'first' starts with whitespace
+      PsiElement elementAt = file.findElementAt(first.getTextRange().getStartOffset());
+      if (!(elementAt instanceof PsiWhiteSpace) || elementAt.getTextRange().getEndOffset() != startOffset) return null;
+    }
+
+    XmlTagChild last = first;
+    while (last != null && last.getTextRange().getEndOffset() < endOffset) {
+      last = PsiTreeUtil.getNextSiblingOfType(last, XmlTagChild.class);
+    }
+
+    if (last == null) return null;
+    if (last.getTextRange().getEndOffset() != elementAtEnd.getTextRange().getEndOffset()) {
+      //Probably 'last' ends with whitespace
+      PsiElement elementAt = file.findElementAt(last.getTextRange().getEndOffset() - 1);
+      if (!(elementAt instanceof PsiWhiteSpace) || elementAt.getTextRange().getStartOffset() != endOffset) {
+        return null;
+      }
+    }
+
+    return new Pair<XmlTagChild, XmlTagChild>(first, last);
+  }
+
+  public static boolean isSimpleXmlAttributeValue(final String unquotedValue, final XmlAttributeValue context) {
+    for (int i = 0; i < unquotedValue.length(); ++i) {
+      final char ch = unquotedValue.charAt(i);
+      if (!Character.isJavaIdentifierPart(ch) && ch != ':' && ch != '-') {
+        final XmlFile file = PsiTreeUtil.getParentOfType(context, XmlFile.class);
+        return file != null && !tagFromTemplateFramework(file.getRootTag());
+      }
+    }
+    return true;
+  }
+
+  public static boolean toCode(String str) {
+    for (int i = 0; i < str.length(); i++) {
+      if (toCode(str.charAt(i))) return true;
+    }
+    return false;
+  }
+
+  public static boolean toCode(char ch) {
+    return "<&>\u00a0".indexOf(ch) >= 0;
+  }
+
+  @Nullable
+  public static PsiNamedElement findRealNamedElement(@NotNull final PsiNamedElement _element) {
+    PsiElement currentElement = _element;
+    final XmlEntityRef lastEntityRef = PsiTreeUtil.getParentOfType(currentElement, XmlEntityRef.class);
+
+    while (!(currentElement instanceof XmlFile)) {
+      PsiElement dependingElement = currentElement.getUserData(XmlElement.DEPENDING_ELEMENT);
+      if (dependingElement == null) dependingElement = currentElement.getContext();
+      currentElement = dependingElement;
+      if (dependingElement == null) break;
+    }
+
+    if (currentElement != null) {
+      final String name = _element.getName();
+      if (_element instanceof XmlEntityDecl) {
+        final XmlEntityDecl cachedEntity = XmlEntityRefImpl.getCachedEntity((PsiFile)currentElement, name);
+        if (cachedEntity != null) return cachedEntity;
+      }
+
+      final PsiNamedElement[] result = new PsiNamedElement[1];
+
+      processXmlElements((XmlFile)currentElement, new PsiElementProcessor() {
+        public boolean execute(@NotNull final PsiElement element) {
+          if (element instanceof PsiNamedElement) {
+            final String elementName = ((PsiNamedElement)element).getName();
+
+            if (elementName.equals(name) && _element.getClass().isInstance(element)
+                || lastEntityRef != null && element instanceof XmlEntityDecl &&
+                   elementName.equals(lastEntityRef.getText().substring(1, lastEntityRef.getTextLength() - 1))) {
+              result[0] = (PsiNamedElement)element;
+              return false;
+            }
+          }
+
+          return true;
+        }
+      }, true);
+
+      return result[0];
+    }
+
+    return null;
+  }
+
+  private static class MyAttributeInfo implements Comparable {
+    boolean myRequired = true;
+    String myName = null;
+
+    MyAttributeInfo(String name) {
+      myName = name;
+    }
+
+    MyAttributeInfo(String name, boolean flag) {
+      myName = name;
+      myRequired = flag;
+    }
+
+    public int compareTo(Object o) {
+      if (o instanceof MyAttributeInfo) {
+        return myName.compareTo(((MyAttributeInfo)o).myName);
+      }
+      else if (o instanceof XmlAttribute) {
+        return myName.compareTo(((XmlAttribute)o).getName());
+      }
+      return -1;
+    }
+  }
+
+  public static String generateDocumentDTD(XmlDocument doc, boolean full) {
+    final Map<String, List<String>> tags = new LinkedHashMap<String, List<String>>();
+    final Map<String, List<MyAttributeInfo>> attributes = new LinkedHashMap<String, List<MyAttributeInfo>>();
+
+    try {
+      XmlEntityRefImpl.setNoEntityExpandOutOfDocument(doc, true);
+      final XmlTag rootTag = doc.getRootTag();
+      computeTag(rootTag, tags, attributes, full);
+
+      // For supporting not well-formed XML
+      for (PsiElement element = rootTag != null ? rootTag.getNextSibling() : null; element != null; element = element.getNextSibling()) {
+        if (element instanceof XmlTag) {
+          computeTag((XmlTag)element, tags, attributes, full);
+        }
+      }
+    }
+    finally {
+      XmlEntityRefImpl.setNoEntityExpandOutOfDocument(doc, false);
+    }
+
+    final StringBuilder buffer = new StringBuilder();
+    for (final String tagName : tags.keySet()) {
+      buffer.append(generateElementDTD(tagName, tags.get(tagName), attributes.get(tagName)));
+    }
+    return buffer.toString();
+  }
+
+  public static String generateElementDTD(String name, List<String> tags, List<MyAttributeInfo> attributes) {
+    if (name == null || "".equals(name)) return "";
+    if (name.contains(CompletionUtil.DUMMY_IDENTIFIER_TRIMMED)) return "";
+
+    @NonNls final StringBuilder buffer = StringBuilderSpinAllocator.alloc();
+    try {
+      buffer.append("<!ELEMENT ").append(name).append(" ");
+      if (tags.isEmpty()) {
+        buffer.append("(#PCDATA)>\n");
+      }
+      else {
+        buffer.append("(");
+        final Iterator<String> iter = tags.iterator();
+        while (iter.hasNext()) {
+          final String tagName = iter.next();
+          buffer.append(tagName);
+          if (iter.hasNext()) {
+            buffer.append("|");
+          }
+          else {
+            buffer.append(")*");
+          }
+        }
+        buffer.append(">\n");
+      }
+      if (!attributes.isEmpty()) {
+        buffer.append("<!ATTLIST ").append(name);
+        for (final MyAttributeInfo info : attributes) {
+          buffer.append("\n    ").append(generateAttributeDTD(info));
+        }
+        buffer.append(">\n");
+      }
+      return buffer.toString();
+    }
+    finally {
+      StringBuilderSpinAllocator.dispose(buffer);
+    }
+  }
+
+  private static String generateAttributeDTD(MyAttributeInfo info) {
+    if (info.myName.contains(CompletionUtil.DUMMY_IDENTIFIER_TRIMMED)) return "";
+    @NonNls final StringBuilder buffer = StringBuilderSpinAllocator.alloc();
+    try {
+      buffer.append(info.myName).append(" ");
+      //if ("id".equals(info.myName)) {
+      //  buffer.append("ID");
+      //}
+      //else if ("ref".equals(info.myName)) {
+      //  buffer.append("IDREF");
+      //} else {
+      buffer.append("CDATA");
+      //}
+      if (info.myRequired) {
+        buffer.append(" #REQUIRED");
+      }
+      else {
+        buffer.append(" #IMPLIED");
+      }
+      return buffer.toString();
+    }
+    finally {
+      StringBuilderSpinAllocator.dispose(buffer);
+    }
+  }
+
+  @Nullable
+  public static String trimLeadingSpacesInMultilineTagValue(@NonNls String tagValue) {
+    return tagValue == null ? null : tagValue.replaceAll("\n\\s*", "\n");
+  }
+
+  public static String findNamespaceByPrefix(final String prefix, XmlTag contextTag) {
+    return contextTag.getNamespaceByPrefix(prefix);
+  }
+
+  public static String findPrefixByQualifiedName(@NotNull String name) {
+    final int prefixEnd = name.indexOf(':');
+    if (prefixEnd > 0) {
+      return name.substring(0, prefixEnd);
+    }
+    return "";
+  }
+
+  @Nullable
+  public static String findLocalNameByQualifiedName(String name) {
+    return name == null ? null : name.substring(name.indexOf(':') + 1);
+  }
+
+
+  public static XmlFile getContainingFile(PsiElement element) {
+    while (!(element instanceof XmlFile) && element != null) {
+      final PsiElement context = element.getContext();
+      if (context == null) {
+        //todo Dmitry Avdeev: either XmlExtension should work on any PsiFile (not just XmlFile), or you need to handle elements from JspJavaFile in some other way
+        final XmlExtension extension = XmlExtension.getExtensionByElement(element);
+        if (extension != null) {
+          element = extension.getContainingFile(element);
+        }
+      }
+      else {
+        if (element == context) {
+          LOG.error("Context==element: " + element.getClass());
+          return null;
+        }
+        element = context;
+      }
+    }
+    return (XmlFile)element;
+  }
+
+  @Nullable
+  public static String getSubTagValue(XmlTag tag, final String subTagName) {
+    final XmlTag subTag = tag.findFirstSubTag(subTagName);
+    if (subTag != null) {
+      return subTag.getValue().getTrimmedText();
+    }
+    return null;
+  }
+
+  public static int getStartOffsetInFile(XmlTag xmlTag) {
+    int off = 0;
+    while (true) {
+      off += xmlTag.getStartOffsetInParent();
+      final PsiElement parent = xmlTag.getParent();
+      if (!(parent instanceof XmlTag)) break;
+      xmlTag = (XmlTag)parent;
+    }
+    return off;
+  }
+
+  public static XmlElement setNewValue(XmlElement tag, String value) throws IncorrectOperationException {
+    if (tag instanceof XmlTag) {
+      ((XmlTag)tag).getValue().setText(value);
+      return tag;
+    }
+    else if (tag instanceof XmlAttribute) {
+      XmlAttribute attr = (XmlAttribute)tag;
+      attr.setValue(value);
+      return attr;
+    }
+    else {
+      throw new IncorrectOperationException();
+    }
+  }
+
+  public static String decode(@NonNls String text) {
+    if (text.length() == 0) return text;
+    if (text.charAt(0) != '&' || text.length() < 3) {
+      if (text.indexOf('<') < 0 && text.indexOf('>') < 0) return text;
+      return text.replaceAll("<!\\[CDATA\\[", "").replaceAll("\\]\\]>", "");
+    }
+
+    if (text.equals("&lt;")) {
+      return "<";
+    }
+    if (text.equals("&gt;")) {
+      return ">";
+    }
+    if (text.equals("&nbsp;")) {
+      return "\u00a0";
+    }
+    if (text.equals("&amp;")) {
+      return "&";
+    }
+    if (text.equals("&apos;")) {
+      return "'";
+    }
+    if (text.equals("&quot;")) {
+      return "\"";
+    }
+    if (text.startsWith("&quot;") && text.endsWith("&quot;")) {
+      return "\"" + text.substring(6, text.length() - 6) + "\"";
+    }
+    if (text.startsWith("&#")) {
+      text = text.substring(3, text.length() - 1);
+      try {
+        return String.valueOf((char)Integer.parseInt(text));
+      }
+      catch (NumberFormatException e) {
+        // ignore
+      }
+    }
+
+    return text;
+  }
+
+  public static String unescape(String text) {
+    return StringUtil.unescapeXml(text);
+  }
+
+  public static String escape(String text) {
+    return StringUtil.escapeXml(text);
+  }
+
+  @Nullable
+  public static String extractXmlEncodingFromProlog(final byte[] content) {
+    return XmlCharsetDetector.extractXmlEncodingFromProlog(content);
+  }
+
+  @Nullable
+  public static String extractXmlEncodingFromProlog(String text) {
+    return XmlCharsetDetector.extractXmlEncodingFromProlog(text);
+  }
+
+  public static void registerXmlAttributeValueReferenceProvider(PsiReferenceRegistrar registrar,
+                                                                @Nullable @NonNls String[] attributeNames,
+                                                                @Nullable ElementFilter elementFilter,
+                                                                @NotNull PsiReferenceProvider provider) {
+    registerXmlAttributeValueReferenceProvider(registrar, attributeNames, elementFilter, true, provider);
+  }
+
+  public static void registerXmlAttributeValueReferenceProvider(PsiReferenceRegistrar registrar,
+                                                                @Nullable @NonNls String[] attributeNames,
+                                                                @Nullable ElementFilter elementFilter,
+                                                                boolean caseSensitive,
+                                                                @NotNull PsiReferenceProvider provider) {
+    registerXmlAttributeValueReferenceProvider(registrar, attributeNames, elementFilter, caseSensitive, provider,
+                                               PsiReferenceRegistrar.DEFAULT_PRIORITY);
+  }
+
+  public static void registerXmlAttributeValueReferenceProvider(PsiReferenceRegistrar registrar,
+                                                                @Nullable @NonNls String[] attributeNames,
+                                                                @Nullable ElementFilter elementFilter,
+                                                                boolean caseSensitive,
+                                                                @NotNull PsiReferenceProvider provider,
+                                                                double priority) {
+    if (attributeNames == null) {
+      registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().and(new FilterPattern(elementFilter)), provider, priority);
+      return;
+    }
+
+    final StringPattern namePattern = caseSensitive
+                                      ? StandardPatterns.string().oneOf(attributeNames)
+                                      : StandardPatterns.string().oneOfIgnoreCase(attributeNames);
+    registrar
+      .registerReferenceProvider(XmlPatterns.xmlAttributeValue().withLocalName(namePattern).and(new FilterPattern(elementFilter)), provider,
+                                 priority);
+  }
+
+  public static void registerXmlTagReferenceProvider(PsiReferenceRegistrar registrar,
+                                                     @NonNls String[] names,
+                                                     @Nullable ElementFilter elementFilter,
+                                                     boolean caseSensitive,
+                                                     @NotNull PsiReferenceProvider provider) {
+    if (names == null) {
+      registrar.registerReferenceProvider(XmlPatterns.xmlTag().and(new FilterPattern(elementFilter)), provider,
+                                          PsiReferenceRegistrar.DEFAULT_PRIORITY);
+      return;
+    }
+
+
+    final StringPattern namePattern =
+      caseSensitive ? StandardPatterns.string().oneOf(names) : StandardPatterns.string().oneOfIgnoreCase(names);
+    registrar.registerReferenceProvider(XmlPatterns.xmlTag().withLocalName(namePattern).and(new FilterPattern(elementFilter)), provider,
+                                        PsiReferenceRegistrar.DEFAULT_PRIORITY);
+  }
+
+  public interface DuplicationInfoProvider<T extends PsiElement> {
+    @Nullable
+    String getName(@NotNull T t);
+
+    @NotNull
+    String getNameKey(@NotNull T t, @NotNull String name);
+
+    @NotNull
+    PsiElement getNodeForMessage(@NotNull T t);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/CompositeAttributeTagDescriptor.java b/xml/impl/src/com/intellij/xml/util/documentation/CompositeAttributeTagDescriptor.java
new file mode 100644
index 0000000..53fdca8
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/CompositeAttributeTagDescriptor.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util.documentation;
+
+import com.intellij.psi.xml.XmlTag;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author maxim
+ */
+class CompositeAttributeTagDescriptor extends HtmlAttributeDescriptor {
+  List<HtmlAttributeDescriptor> attributes = new LinkedList<HtmlAttributeDescriptor>();
+
+  HtmlAttributeDescriptor findHtmlAttributeInContext(XmlTag tag) {
+    if (tag == null) return null;
+    String contextName = tag.getName();
+
+    for (final HtmlAttributeDescriptor attributeDescriptor : attributes) {
+      if (attributeDescriptor.isValidParentTagName(contextName)) {
+        return attributeDescriptor;
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/EntityDescriptor.java b/xml/impl/src/com/intellij/xml/util/documentation/EntityDescriptor.java
new file mode 100644
index 0000000..21c0b46
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/EntityDescriptor.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util.documentation;
+
+/**
+ * @author maxim
+ */
+class EntityDescriptor {
+  private String description;
+  private String helpRef;
+  private String name;
+  private char dtd;
+
+  static final char LOOSE_DTD = 'L';
+  static final char FRAME_DTD = 'D';
+
+  char getDtd() {
+    return dtd;
+  }
+
+  void setDtd(char dtd) {
+    this.dtd = dtd;
+  }
+
+  String getDescription() {
+    return description;
+  }
+
+  void setDescription(String description) {
+    this.description = description;
+  }
+
+  String getHelpRef() {
+    return helpRef;
+  }
+
+  void setHelpRef(String helpRef) {
+    this.helpRef = helpRef;
+  }
+
+  String getName() {
+    return name;
+  }
+
+  void setName(String name) {
+    this.name = name;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/HtmlAttributeDescriptor.java b/xml/impl/src/com/intellij/xml/util/documentation/HtmlAttributeDescriptor.java
new file mode 100644
index 0000000..1cc3e6f
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/HtmlAttributeDescriptor.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util.documentation;
+
+import java.util.Arrays;
+
+/**
+ * @author maxim
+ */
+class HtmlAttributeDescriptor extends EntityDescriptor {
+  private String myType;
+  private boolean myHasDefaultValue;
+  private String[] mySetOfParentTags;
+  private boolean myParentSetIsExclusionSet;
+
+  boolean isValidParentTagName(String str) {
+    boolean containsInSet = Arrays.binarySearch(mySetOfParentTags, str) >= 0;
+    return containsInSet == !myParentSetIsExclusionSet;
+  }
+
+  String getType() {
+    return myType;
+  }
+
+  void setType(String type) {
+    this.myType = type;
+  }
+
+  boolean isHasDefaultValue() {
+    return myHasDefaultValue;
+  }
+
+  void setHasDefaultValue(boolean hasDefaultValue) {
+    this.myHasDefaultValue = hasDefaultValue;
+  }
+
+  String[] getSetOfParentTags() {
+    return mySetOfParentTags;
+  }
+
+  boolean isParentSetIsExclusionSet() {
+    return myParentSetIsExclusionSet;
+  }
+
+  void setParentSetIsExclusionSet(boolean _parentSetIsExclusionSet) {
+    myParentSetIsExclusionSet = _parentSetIsExclusionSet;
+  }
+
+  void setSetOfParentTags(String[] _setOfParentTags) {
+    mySetOfParentTags = _setOfParentTags;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/HtmlDescriptorsTable.java b/xml/impl/src/com/intellij/xml/util/documentation/HtmlDescriptorsTable.java
new file mode 100644
index 0000000..35e5675
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/HtmlDescriptorsTable.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util.documentation;
+
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.HashSet;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jetbrains.annotations.NonNls;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author maxim
+ */
+public class HtmlDescriptorsTable {
+  private static final HashMap<String,HtmlTagDescriptor> ourTagTable = new HashMap<String, HtmlTagDescriptor>();
+  private static final HashMap<String,HtmlAttributeDescriptor> ourAttributeTable = new HashMap<String, HtmlAttributeDescriptor>();
+  private static String[] ourHtmlTagNames;
+
+  @NonNls
+  public static final String HTMLTABLE_RESOURCE_NAME = "htmltable.xml";
+
+  @NonNls
+  public static final String HTML5TABLE_RESOURCE_NAME = "html5table.xml";
+
+  @NonNls
+  private static final String MATHML_RESOURCE_NAME = "mathmltable.xml";
+
+  @NonNls
+  private static final String SVG_RESOURCE_NAME = "svgtable.xml";
+
+  @NonNls
+  public static final String TAG_ELEMENT_NAME = "tag";
+
+  @NonNls
+  public static final String BASE_HELP_REF_ATTR = "baseHelpRef";
+
+  @NonNls
+  public static final String NAME_ATTR = "name";
+
+  @NonNls
+  public static final String HELPREF_ATTR = "helpref";
+
+  @NonNls
+  public static final String DESCRIPTION_ATTR = "description";
+
+  @NonNls public static final String STARTTAG_ATTR = "startTag";
+
+  @NonNls public static final String ENDTAG_ATTR = "endTag";
+
+  @NonNls public static final String EMPTY_ATTR = "empty";
+
+  @NonNls public static final String DTD_ATTR = "dtd";
+
+  @NonNls public static final String ATTRIBUTE_ELEMENT_NAME = "attribute";
+
+  @NonNls public static final String TYPE_ATTR = "type";
+
+  @NonNls public static final String DEFAULT_ATTR = "default";
+
+  @NonNls public static final String RELATED_TAGS_ATTR = "relatedTags";
+
+  private HtmlDescriptorsTable() {
+  }
+
+  static {
+    try {
+      Set<String> htmlTagNames = new HashSet<String>();
+
+      loadHtmlElements(HTMLTABLE_RESOURCE_NAME, htmlTagNames);
+
+      loadHtmlElements(HTML5TABLE_RESOURCE_NAME, htmlTagNames);
+
+      loadHtmlElements(MATHML_RESOURCE_NAME, htmlTagNames);
+
+      loadHtmlElements(SVG_RESOURCE_NAME, htmlTagNames);
+
+      ourHtmlTagNames = ArrayUtil.toStringArray(htmlTagNames);
+
+    } catch (Exception ex) {
+      ex.printStackTrace();
+      ourHtmlTagNames = ArrayUtil.EMPTY_STRING_ARRAY;
+    }
+  }
+
+  private static void loadHtmlElements(final String resourceName, Collection<String> htmlTagNames) throws JDOMException, IOException {
+    final Document document = JDOMUtil.loadDocument(HtmlDescriptorsTable.class.getResourceAsStream(resourceName));
+    final List elements = document.getRootElement().getChildren(TAG_ELEMENT_NAME);
+    final String baseHtmlExtDocUrl = document.getRootElement().getAttribute(BASE_HELP_REF_ATTR).getValue();
+
+    for (Object object : elements) {
+      final Element element = (Element)object;
+      String htmlTagName = element.getAttributeValue(NAME_ATTR);
+      htmlTagNames.add(htmlTagName);
+
+      HtmlTagDescriptor value = new HtmlTagDescriptor();
+      ourTagTable.put(htmlTagName, value);
+      value.setHelpRef(baseHtmlExtDocUrl + element.getAttributeValue(HELPREF_ATTR));
+      value.setDescription(element.getAttributeValue(DESCRIPTION_ATTR));
+      value.setName(htmlTagName);
+
+      value.setHasStartTag(element.getAttribute(STARTTAG_ATTR).getBooleanValue());
+      value.setHasEndTag(element.getAttribute(ENDTAG_ATTR).getBooleanValue());
+      value.setEmpty(element.getAttribute(EMPTY_ATTR).getBooleanValue());
+
+      String attributeValue = element.getAttributeValue(DTD_ATTR);
+      if (attributeValue.length() > 0) {
+        value.setDtd(attributeValue.charAt(0));
+      }
+    }
+
+    final List attributes = document.getRootElement().getChildren(ATTRIBUTE_ELEMENT_NAME);
+    for (Object attribute : attributes) {
+      final Element element = (Element)attribute;
+      String attrName = element.getAttributeValue(NAME_ATTR);
+
+      HtmlAttributeDescriptor value = new HtmlAttributeDescriptor();
+      HtmlAttributeDescriptor previousDescriptor = ourAttributeTable.get(attrName);
+
+      if (previousDescriptor == null) {
+        ourAttributeTable.put(attrName, value);
+      }
+      else {
+        CompositeAttributeTagDescriptor parentDescriptor;
+
+        if (!(previousDescriptor instanceof CompositeAttributeTagDescriptor)) {
+          parentDescriptor = new CompositeAttributeTagDescriptor();
+          ourAttributeTable.put(attrName, parentDescriptor);
+          parentDescriptor.attributes.add(previousDescriptor);
+        }
+        else {
+          parentDescriptor = (CompositeAttributeTagDescriptor)previousDescriptor;
+        }
+
+        parentDescriptor.attributes.add(value);
+      }
+
+      value.setHelpRef(element.getAttributeValue(HELPREF_ATTR));
+      value.setDescription(element.getAttributeValue(DESCRIPTION_ATTR));
+      value.setName(attrName);
+
+      String attributeValue = element.getAttributeValue(DTD_ATTR);
+      if (attributeValue.length() > 0) {
+        value.setDtd(attributeValue.charAt(0));
+      }
+
+      value.setType(element.getAttributeValue(TYPE_ATTR));
+      value.setHasDefaultValue(element.getAttribute(DEFAULT_ATTR).getBooleanValue());
+
+      StringTokenizer tokenizer = new StringTokenizer(element.getAttributeValue(RELATED_TAGS_ATTR), ",");
+      int tokenCount = tokenizer.countTokens();
+
+      for (int i = 0; i < tokenCount; ++i) {
+        final String s = tokenizer.nextToken();
+
+        if (s.equals("!")) {
+          value.setParentSetIsExclusionSet(true);
+        }
+        else {
+          if (value.getSetOfParentTags() == null) {
+            value.setSetOfParentTags(new String[tokenCount - (value.isParentSetIsExclusionSet() ? 1 : 0)]);
+          }
+          value.getSetOfParentTags()[i - (value.isParentSetIsExclusionSet() ? 1 : 0)] = s;
+        }
+      }
+
+      Arrays.sort(value.getSetOfParentTags());
+    }
+  }
+
+  static HtmlTagDescriptor getTagDescriptor(String tagName) {
+    return ourTagTable.get(tagName);
+  }
+
+  static HtmlAttributeDescriptor getAttributeDescriptor(String attributeName) {
+    return ourAttributeTable.get(attributeName);
+  }
+
+  public static String[] getHtmlTagNames() {
+    return ourHtmlTagNames;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java b/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java
new file mode 100644
index 0000000..34e9b5b
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util.documentation;
+
+import com.intellij.lang.documentation.DocumentationProvider;
+import com.intellij.lang.documentation.DocumentationUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.impl.source.xml.SchemaPrefix;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.util.ColorSampleLookupValue;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author maxim
+ */
+public class HtmlDocumentationProvider implements DocumentationProvider {
+  private static DocumentationProvider ourStyleProvider;
+  private static DocumentationProvider ourScriptProvider;
+
+  @NonNls public static final String ELEMENT_ELEMENT_NAME = "element";
+  @NonNls public static final String NBSP = ":&nbsp;";
+  @NonNls public static final String BR = "<br>";
+
+  public static void registerStyleDocumentationProvider(DocumentationProvider documentationProvider) {
+    ourStyleProvider = documentationProvider;
+  }
+
+  @Nullable
+  public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) {
+    if (element instanceof SchemaPrefix) {
+      return ((SchemaPrefix)element).getQuickNavigateInfo();
+    }
+    return null;
+  }
+
+  public List<String> getUrlFor(PsiElement element, PsiElement originalElement) {
+    String result = getUrlForHtml(element, PsiTreeUtil.getParentOfType(originalElement,XmlTag.class,false));
+
+    if (result == null && ourStyleProvider !=null) {
+      return ourStyleProvider.getUrlFor(element, originalElement);
+    }
+
+    return result != null ? Collections.singletonList(result) : null;
+  }
+
+  public static String getUrlForHtml(PsiElement element, XmlTag context) {
+    final EntityDescriptor descriptor = findDocumentationDescriptor(element, context);
+
+    if (descriptor!=null) {
+      return descriptor.getHelpRef();
+    } else {
+      return null;
+    }
+  }
+
+  private static EntityDescriptor findDocumentationDescriptor(PsiElement element, XmlTag context) {
+    boolean isTag = true;
+    PsiElement nameElement = null;
+    String key = null;
+
+    if (element instanceof XmlElementDecl) {
+      nameElement = ((XmlElementDecl)element).getNameElement();
+    } else if (element instanceof XmlAttributeDecl) {
+      nameElement = ((XmlAttributeDecl)element).getNameElement();
+      isTag = false;
+    } else if (element instanceof XmlTag) {
+      final XmlTag xmlTag = ((XmlTag)element);
+      final PsiMetaData metaData = xmlTag.getMetaData();
+      key = (metaData!=null)?metaData.getName():null;
+      isTag = xmlTag.getLocalName().equals(ELEMENT_ELEMENT_NAME);
+    } else if (element.getParent() instanceof XmlAttributeValue) {
+      isTag = false;
+      key = ((XmlAttribute)element.getParent().getParent()).getName();
+    } else if (element instanceof XmlAttributeValue) {
+      isTag = false;
+      final XmlAttribute xmlAttribute = (XmlAttribute)element.getParent();
+      key = xmlAttribute.getName();
+    } else if (element instanceof XmlAttribute) {
+      final XmlAttribute xmlAttribute = (XmlAttribute)element;
+      isTag = false;
+      key = xmlAttribute.getName();
+    } else {
+      nameElement = element;
+      isTag = !(element.getParent() instanceof XmlAttribute);
+    }
+
+    if (nameElement!=null) {
+      key = nameElement.getText();
+    }
+
+    key = (key != null)?key.toLowerCase():"";
+
+    if (isTag) {
+      return HtmlDescriptorsTable.getTagDescriptor(key);
+    } else {
+      return getDescriptor(key, context);
+    }
+  }
+
+  private static HtmlAttributeDescriptor getDescriptor(String name, XmlTag context) {
+
+    HtmlAttributeDescriptor attributeDescriptor = HtmlDescriptorsTable.getAttributeDescriptor(name);
+    if (attributeDescriptor instanceof CompositeAttributeTagDescriptor) {
+      return ((CompositeAttributeTagDescriptor)attributeDescriptor).findHtmlAttributeInContext(context);
+    }
+
+    return attributeDescriptor;
+  }
+
+  public String generateDoc(PsiElement element, PsiElement originalElement) {
+    final XmlTag tag = PsiTreeUtil.getParentOfType(originalElement, XmlTag.class, false);
+    String result = generateDocForHtml(element, false, tag, originalElement);
+
+    if (result == null && ourStyleProvider !=null) {
+      result = ourStyleProvider.generateDoc(element, originalElement);
+    }
+    
+    if (result == null && ourScriptProvider !=null) {
+      result = ourScriptProvider.generateDoc(element, originalElement);
+    }
+    
+    if (result == null && element instanceof XmlAttributeValue) {
+      result = generateDocForHtml(element.getParent(), false, tag, originalElement);
+    }
+
+    return result;
+  }
+
+  public String generateDocForHtml(PsiElement element) {
+    return generateDocForHtml(element,true, null, null);
+  }
+
+  protected String generateDocForHtml(PsiElement element, boolean ommitHtmlSpecifics, XmlTag context, PsiElement originalElement) {
+    final EntityDescriptor descriptor = findDocumentationDescriptor(element,context);
+
+    if (descriptor!=null) {
+      return generateJavaDoc(descriptor, ommitHtmlSpecifics, originalElement);
+    }
+    if (element instanceof XmlEntityDecl) {
+      final XmlEntityDecl entityDecl = (XmlEntityDecl)element;
+
+      return new XmlDocumentationProvider().findDocRightAfterElement(element, entityDecl.getName());
+    }
+    return null;
+  }
+
+  private static String generateJavaDoc(EntityDescriptor descriptor, boolean ommitHtmlSpecifics, PsiElement element) {
+    StringBuilder buf = new StringBuilder();
+    final boolean istag = descriptor instanceof HtmlTagDescriptor;
+    
+    if (istag) {
+      DocumentationUtil.formatEntityName(XmlBundle.message("xml.javadoc.tag.name.message"),descriptor.getName(),buf);
+    } else {
+      DocumentationUtil.formatEntityName(XmlBundle.message("xml.javadoc.attribute.name.message"),descriptor.getName(),buf);
+    }
+
+    buf.append(XmlBundle.message("xml.javadoc.description.message")).append(NBSP).append(descriptor.getDescription()).append(BR);
+
+    if (istag) {
+      final HtmlTagDescriptor tagDescriptor = (HtmlTagDescriptor)descriptor;
+
+      if (!ommitHtmlSpecifics) {
+        boolean hasStartTag = tagDescriptor.isHasStartTag();
+        if (!hasStartTag) {
+          buf.append(XmlBundle.message("xml.javadoc.start.tag.could.be.omitted.message")).append(BR);
+        }
+        if (!tagDescriptor.isEmpty() && !tagDescriptor.isHasEndTag()) {
+          buf.append(XmlBundle.message("xml.javadoc.end.tag.could.be.omitted.message")).append(BR);
+        }
+      }
+
+      if (tagDescriptor.isEmpty()) {
+        buf.append(XmlBundle.message("xml.javadoc.is.empty.message")).append(BR);
+      }
+    } else {
+      final HtmlAttributeDescriptor attributeDescriptor = (HtmlAttributeDescriptor)descriptor;
+
+      buf.append(XmlBundle.message("xml.javadoc.attr.type.message", attributeDescriptor.getType())).append(BR);
+      if (!attributeDescriptor.isHasDefaultValue())
+        buf.append(XmlBundle.message("xml.javadoc.attr.default.required.message")).append(BR);
+    }
+
+    char dtdId = descriptor.getDtd();
+    boolean deprecated = dtdId == HtmlTagDescriptor.LOOSE_DTD;
+    if (deprecated) {
+      buf.append(XmlBundle.message("xml.javadoc.deprecated.message", deprecated)).append(BR);
+    }
+
+    if (dtdId == HtmlTagDescriptor.LOOSE_DTD) {
+      buf.append(XmlBundle.message("xml.javadoc.defined.in.loose.dtd.message"));
+    }
+    else if (dtdId == HtmlTagDescriptor.FRAME_DTD) {
+      buf.append(XmlBundle.message("xml.javadoc.defined.in.frameset.dtd.message"));
+    }
+    else {
+      buf.append(XmlBundle.message("xml.javadoc.defined.in.any.dtd.message"));
+    }
+
+    if (!istag) {
+      ColorSampleLookupValue.addColorPreviewAndCodeToLookup(element,buf);
+    }
+
+    if (element != null) {
+      buf.append(XmlDocumentationProvider.generateHtmlAdditionalDocTemplate(element));
+    }
+
+    return buf.toString();
+  }
+
+  public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) {
+    PsiElement result = createNavigationElementHTML(psiManager, object.toString(),element);
+
+    if (result== null && ourStyleProvider !=null) {
+      result = ourStyleProvider.getDocumentationElementForLookupItem(psiManager, object, element);
+    }
+    if (result== null && ourScriptProvider !=null) {
+      result = ourScriptProvider.getDocumentationElementForLookupItem(psiManager, object, element);
+    }
+    if (result == null && object instanceof String && element != null) {
+      result = XmlDocumentationProvider.findDeclWithName((String)object, element);
+    }
+    return result;
+  }
+
+  public PsiElement getDocumentationElementForLink(PsiManager psiManager, String link, PsiElement context) {
+    PsiElement result = createNavigationElementHTML(psiManager, link, context);
+
+    if (result== null && ourStyleProvider !=null) {
+      result = ourStyleProvider.getDocumentationElementForLink(psiManager, link,context);
+    }
+    if (result== null && ourScriptProvider !=null) {
+      result = ourScriptProvider.getDocumentationElementForLink(psiManager, link,context);
+    }
+    return result;
+  }
+
+  public PsiElement createNavigationElementHTML(PsiManager psiManager, String text, PsiElement context) {
+    String key = text.toLowerCase();
+    final HtmlTagDescriptor descriptor = HtmlDescriptorsTable.getTagDescriptor(key);
+
+    if (descriptor != null && !isAttributeContext(context) ) {
+      try {
+        final XmlTag tagFromText = XmlElementFactory.getInstance(psiManager.getProject()).createTagFromText("<"+ key + " xmlns=\"" + XmlUtil.XHTML_URI + "\"/>");
+        final XmlElementDescriptor tagDescriptor = tagFromText.getDescriptor();
+        return tagDescriptor != null ? tagDescriptor.getDeclaration() : null;
+      }
+      catch(IncorrectOperationException ignore) {
+      }
+    }
+    else {
+      XmlTag tagContext = findTagContext(context);
+      HtmlAttributeDescriptor myAttributeDescriptor = getDescriptor(key,tagContext);
+
+      if (myAttributeDescriptor != null && tagContext != null) {
+        XmlElementDescriptor tagDescriptor = tagContext.getDescriptor();
+        XmlAttributeDescriptor attributeDescriptor = tagDescriptor != null ? tagDescriptor.getAttributeDescriptor(text, tagContext): null;
+
+        return (attributeDescriptor != null)?attributeDescriptor.getDeclaration():null;
+      }
+    }
+    return null;
+  }
+
+  protected boolean isAttributeContext(PsiElement context) {
+    if(context instanceof XmlAttribute) return true;
+
+    if (context instanceof PsiWhiteSpace) {
+      PsiElement prevSibling = context.getPrevSibling();
+      if (prevSibling instanceof XmlAttribute)
+        return true;
+    }
+
+    return false;
+  }
+
+  protected XmlTag findTagContext(PsiElement context) {
+    if (context instanceof PsiWhiteSpace) {
+      PsiElement prevSibling = context.getPrevSibling();
+      if (prevSibling instanceof XmlTag)
+        return (XmlTag)prevSibling;
+    }
+
+    return PsiTreeUtil.getParentOfType(context,XmlTag.class,false);
+  }
+
+  public static void registerScriptDocumentationProvider(final DocumentationProvider provider) {
+    ourScriptProvider = provider;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/HtmlTagDescriptor.java b/xml/impl/src/com/intellij/xml/util/documentation/HtmlTagDescriptor.java
new file mode 100644
index 0000000..ae0d8b4
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/HtmlTagDescriptor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util.documentation;
+
+/**
+ * @author maxim
+ */
+class HtmlTagDescriptor extends EntityDescriptor {
+  boolean isHasStartTag() {
+    return hasStartTag;
+  }
+
+  void setHasStartTag(boolean hasStartTag) {
+    this.hasStartTag = hasStartTag;
+  }
+
+  boolean isHasEndTag() {
+    return hasEndTag;
+  }
+
+  void setHasEndTag(boolean hasEndTag) {
+    this.hasEndTag = hasEndTag;
+  }
+
+  boolean isEmpty() {
+    return empty;
+  }
+
+  void setEmpty(boolean empty) {
+    this.empty = empty;
+  }
+
+  private boolean hasStartTag;
+  private boolean hasEndTag;
+  private boolean empty;
+}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/XHtmlDocumentationProvider.java b/xml/impl/src/com/intellij/xml/util/documentation/XHtmlDocumentationProvider.java
new file mode 100644
index 0000000..f03f8d7
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/XHtmlDocumentationProvider.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util.documentation;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlText;
+
+/**
+ * @author maxim
+ */
+public class XHtmlDocumentationProvider extends HtmlDocumentationProvider {
+
+  protected String generateDocForHtml(PsiElement element, boolean ommitHtmlSpecifics, XmlTag context, PsiElement originalElement) {
+    return super.generateDocForHtml(element, true, context, originalElement);
+  }
+
+  protected XmlTag findTagContext(PsiElement context) {
+    XmlTag tagBeforeWhiteSpace = findTagBeforeWhiteSpace(context);
+    if (tagBeforeWhiteSpace != null) return tagBeforeWhiteSpace;
+    return super.findTagContext(context);
+  }
+
+  private static XmlTag findTagBeforeWhiteSpace(PsiElement context) {
+    if (context instanceof PsiWhiteSpace) {
+      PsiElement parent = context.getParent();
+      if (parent instanceof XmlText) {
+        PsiElement prevSibling = parent.getPrevSibling();
+        if (prevSibling instanceof XmlTag) return (XmlTag)prevSibling;
+      }
+      else if (parent instanceof XmlTag) {
+        return (XmlTag)parent;
+      }
+    }
+
+    return null;
+  }
+
+  protected boolean isAttributeContext(PsiElement context) {
+    if (findTagBeforeWhiteSpace(context) != null) return false;
+
+    return super.isAttributeContext(context);
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java b/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java
new file mode 100644
index 0000000..8af0acc
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java
@@ -0,0 +1,528 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util.documentation;
+
+import com.intellij.codeInsight.completion.XmlCompletionData;
+import com.intellij.lang.Language;
+import com.intellij.lang.documentation.DocumentationProvider;
+import com.intellij.lang.documentation.DocumentationUtil;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.html.HtmlTag;
+import com.intellij.psi.impl.source.xml.SchemaPrefix;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.Processor;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.impl.schema.*;
+import com.intellij.xml.util.XmlUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author maxim
+ */
+public class XmlDocumentationProvider implements DocumentationProvider {
+  private static final Key<XmlElementDescriptor> DESCRIPTOR_KEY = Key.create("Original element");
+
+  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.documentation.XmlDocumentationProvider");
+
+  @NonNls private static final String NAME_ATTR_NAME = "name";
+  @NonNls private static final String BASE_SITEPOINT_URL = "http://reference.sitepoint.com/html/";
+
+
+  @Nullable
+  public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) {
+    if (element instanceof SchemaPrefix) {
+      return ((SchemaPrefix)element).getQuickNavigateInfo();
+    }
+    return null;
+  }
+
+  public List<String> getUrlFor(PsiElement element, PsiElement originalElement) {
+    if (element instanceof XmlTag) {
+      XmlTag tag = (XmlTag)element;
+
+      MyPsiElementProcessor processor = new MyPsiElementProcessor();
+      XmlUtil.processXmlElements(tag,processor, true);
+
+      if (processor.url == null) {
+        XmlTag declaration = getComplexOrSimpleTypeDefinition(element, originalElement);
+
+        if (declaration != null) {
+          XmlUtil.processXmlElements(declaration,processor, true);
+        }
+      }
+
+      return processor.url != null ? Collections.singletonList(processor.url) : null;
+    }
+    return null;
+  }
+
+  public String generateDoc(PsiElement element, final PsiElement originalElement) {
+    if (element instanceof XmlElementDecl) {
+      PsiElement curElement = findPreviousComment(element);
+
+      if (curElement!=null) {
+        return formatDocFromComment(curElement, ((XmlElementDecl)element).getNameElement().getText());
+      }
+    } else if (element instanceof XmlTag) {
+      XmlTag tag = (XmlTag)element;
+      MyPsiElementProcessor processor = new MyPsiElementProcessor();
+      String name = tag.getAttributeValue(NAME_ATTR_NAME);
+      String typeName = null;
+
+      if (originalElement != null && originalElement.getParent() instanceof XmlAttributeValue) {
+        XmlAttributeValue value = (XmlAttributeValue)originalElement.getParent();
+        String toSearch = value.getValue();
+        XmlTag enumerationTag;
+        
+        if (XmlUtil.ENUMERATION_TAG_NAME.equals(tag.getLocalName())) {
+          enumerationTag = tag;
+          name = enumerationTag.getAttributeValue(XmlUtil.VALUE_ATTR_NAME);
+        } else {
+          enumerationTag = findEnumerationValue(toSearch, tag);
+          name = toSearch;
+        }
+
+        if (enumerationTag != null) {
+          XmlUtil.processXmlElements(enumerationTag,processor, true);
+
+          if (processor.result != null) {
+            typeName = XmlBundle.message("xml.javadoc.enumeration.value.message");
+          }
+        }
+      }
+
+      if (processor.result == null) XmlUtil.processXmlElements(tag,processor, true);
+
+      if (processor.result == null) {
+        XmlTag declaration = getComplexOrSimpleTypeDefinition(element, originalElement);
+
+        if (declaration != null) {
+          XmlUtil.processXmlElements(declaration,processor, true);
+          name = declaration.getAttributeValue(NAME_ATTR_NAME);
+          typeName = XmlBundle.message("xml.javadoc.complex.type.message");
+        }
+      }
+      if (processor.result == null) {
+        final PsiElement comment = findPreviousComment(element);
+        if (comment != null) {
+          return formatDocFromComment(comment, ((XmlTag)element).getName());
+        }
+      }
+
+      String doc = generateDoc(processor.result, name, typeName, processor.version);
+      if (doc != null && originalElement != null) {
+        doc += generateHtmlAdditionalDocTemplate(originalElement);
+      }
+      return doc;
+
+    } else if (element instanceof XmlAttributeDecl) {
+      // Check for comment before attlist, it should not be right after previous declaration
+      final PsiElement parent = element.getParent();
+      final PsiElement previousComment = findPreviousComment(parent);
+      final String referenceName = ((XmlAttributeDecl)element).getNameElement().getText();
+
+      if (previousComment instanceof PsiComment) {
+        final PsiElement prevSibling = previousComment.getPrevSibling();
+
+        if (prevSibling == null ||
+            ( prevSibling instanceof PsiWhiteSpace &&
+              prevSibling.getText().indexOf('\n') >= 0
+            )
+           ) {
+          return formatDocFromComment(previousComment, referenceName);
+        }
+      }
+
+      return findDocRightAfterElement(parent, referenceName);
+    } else if (element instanceof XmlEntityDecl) {
+      final XmlEntityDecl entityDecl = (XmlEntityDecl)element;
+
+      return findDocRightAfterElement(element, entityDecl.getName());
+    }
+
+    return null;
+  }
+
+  private static XmlTag findEnumerationValue(final String text, XmlTag tag) {
+    final Ref<XmlTag> enumerationTag = new Ref<XmlTag>();
+
+    Processor<XmlTag> processor = new Processor<XmlTag>() {
+      public boolean process(XmlTag xmlTag) {
+        if (text.equals(xmlTag.getAttributeValue(XmlUtil.VALUE_ATTR_NAME))) {
+          enumerationTag.set(xmlTag);
+        }
+        return true;
+      }
+    };
+    XmlUtil.processEnumerationValues(tag, processor);
+
+    if (enumerationTag.get() == null) {
+      final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(
+        tag,
+        null
+      );
+
+      TypeDescriptor type = elementDescriptor != null ? elementDescriptor.getType():null;
+      if (type instanceof ComplexTypeDescriptor) {
+        XmlUtil.processEnumerationValues(((ComplexTypeDescriptor)type).getDeclaration(), processor);
+      }
+    }
+    return enumerationTag.get();
+  }
+
+  static String generateHtmlAdditionalDocTemplate(@NotNull PsiElement element) {
+    StringBuilder buf = new StringBuilder();
+    final PsiFile containingFile = element.getContainingFile();
+    if (containingFile != null) {
+      final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class, false);
+      boolean append;
+      if (tag instanceof HtmlTag) {
+        append = true;
+      }
+      else {
+        final FileViewProvider provider = containingFile.getViewProvider();
+        Language language;
+        if (provider instanceof TemplateLanguageFileViewProvider) {
+          language = ((TemplateLanguageFileViewProvider)provider).getTemplateDataLanguage();
+        }
+        else {
+          language = provider.getBaseLanguage();
+        }
+
+        append = language == XHTMLLanguage.INSTANCE;
+      }
+
+      if (tag != null) {
+        EntityDescriptor descriptor = HtmlDescriptorsTable.getTagDescriptor(tag.getName());
+        if (descriptor != null && append) {
+          buf.append("<br>");
+          buf.append(XmlBundle.message("html.quickdoc.additional.template",
+                                       descriptor.getHelpRef(),
+                                       BASE_SITEPOINT_URL + tag.getName()));
+        }
+      }
+    }
+
+    return buf.toString();
+  }
+
+  public String findDocRightAfterElement(final PsiElement parent, final String referenceName) {
+    // Check for comment right after the xml attlist decl
+    PsiElement uncleElement = parent.getNextSibling();
+    if (uncleElement instanceof PsiWhiteSpace && uncleElement.getText().indexOf('\n') == -1) uncleElement = uncleElement.getNextSibling();
+    if (uncleElement instanceof PsiComment) {
+      return formatDocFromComment(uncleElement, referenceName);
+    }
+    return null;
+  }
+
+  @Nullable
+  public static PsiElement findPreviousComment(final PsiElement element) {
+    PsiElement curElement = element;
+
+    while(curElement!=null && !(curElement instanceof XmlComment)) {
+      curElement = curElement.getPrevSibling();
+      if (curElement instanceof XmlText && StringUtil.isEmptyOrSpaces(curElement.getText())) {
+        continue;
+      }
+      if (!(curElement instanceof PsiWhiteSpace) &&
+          !(curElement instanceof XmlProlog) &&
+          !(curElement instanceof XmlComment)
+         ) {
+        curElement = null; // finding comment fails, we found another similar declaration
+        break;
+      }
+    }
+    return curElement;
+  }
+
+  private String formatDocFromComment(final PsiElement curElement, final String name) {
+    String text = curElement.getText();
+    text = text.substring("<!--".length(),text.length()-"-->".length()).trim();
+    text = escapeDocumentationTextText(text);
+    return generateDoc(text, name,null, null);
+  }
+
+  private XmlTag getComplexOrSimpleTypeDefinition(PsiElement element, PsiElement originalElement) {
+    XmlElementDescriptor descriptor = element.getUserData(DESCRIPTOR_KEY);
+
+    XmlTag contextTag = null;
+
+    XmlAttribute contextAttribute;
+
+    if (descriptor == null &&
+        originalElement != null &&
+        (contextAttribute = PsiTreeUtil.getParentOfType(originalElement, XmlAttribute.class)) != null) {
+      final XmlAttributeDescriptor attributeDescriptor = contextAttribute.getDescriptor();
+
+      if (attributeDescriptor instanceof XmlAttributeDescriptorImpl) {
+        final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(
+          (XmlTag)attributeDescriptor.getDeclaration(),
+          contextAttribute.getParent()
+        );
+
+        TypeDescriptor type = elementDescriptor != null ? elementDescriptor.getType(contextAttribute) : null;
+
+        if (type instanceof ComplexTypeDescriptor) {
+          return ((ComplexTypeDescriptor)type).getDeclaration();
+        }
+      }
+    }
+
+    if (descriptor == null &&
+        originalElement != null &&
+        (contextTag = PsiTreeUtil.getParentOfType(originalElement, XmlTag.class)) != null) {
+      descriptor = contextTag.getDescriptor();
+    }
+
+    if (descriptor instanceof XmlElementDescriptorImpl) {
+      TypeDescriptor type = ((XmlElementDescriptorImpl)descriptor).getType(contextTag);
+
+      if (type instanceof ComplexTypeDescriptor) {
+        return ((ComplexTypeDescriptor)type).getDeclaration();
+      }
+    }
+
+    return null;
+  }
+
+  protected String generateDoc(String str, String name, String typeName, String version) {
+    if (str == null) return null;
+    StringBuilder buf = new StringBuilder(str.length() + 20);
+
+    DocumentationUtil.formatEntityName(typeName == null ? XmlBundle.message("xml.javadoc.tag.name.message"):typeName,name,buf);
+
+    final String indent = "  ";
+    final StringBuilder builder = buf.append(XmlBundle.message("xml.javadoc.description.message")).append(indent).
+        append(HtmlDocumentationProvider.NBSP).append(str);
+    if (version != null) {
+      builder.append(HtmlDocumentationProvider.BR).append(XmlBundle.message("xml.javadoc.version.message")).append(indent)
+          .append(HtmlDocumentationProvider.NBSP).append(version);
+    }
+    return builder.toString();
+  }
+
+  public PsiElement getDocumentationElementForLookupItem(final PsiManager psiManager, Object object, PsiElement element) {
+    final PsiElement originalElement = element;
+    boolean isAttrCompletion = element instanceof XmlAttribute;
+
+    if (!isAttrCompletion && element instanceof XmlToken) {
+      final IElementType tokenType = ((XmlToken)element).getTokenType();
+
+      if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END || tokenType == XmlTokenType.XML_TAG_END) {
+        isAttrCompletion = true;
+      } else if (element.getParent() instanceof XmlAttribute) {
+        isAttrCompletion = true;
+      }
+    }
+
+    element = PsiTreeUtil.getParentOfType(element, XmlTag.class, false);
+
+    if (element instanceof XmlTag) {
+      XmlTag xmlTag = (XmlTag)element;
+      XmlElementDescriptor elementDescriptor;
+
+      if (isAttrCompletion && object instanceof String) {
+        elementDescriptor = xmlTag.getDescriptor();
+
+        if (elementDescriptor != null) {
+          final XmlAttributeDescriptor attributeDescriptor = elementDescriptor.getAttributeDescriptor((String)object, xmlTag);
+          if (attributeDescriptor != null) {
+            final PsiElement declaration = attributeDescriptor.getDeclaration();
+            if (declaration != null) return declaration;
+          }
+        }
+      }
+
+      if (object == null) return null;
+      try {
+        @NonNls StringBuffer tagText = new StringBuffer(object.toString());
+        String namespacePrefix = XmlUtil.findPrefixByQualifiedName(object.toString());
+        String namespace = xmlTag.getNamespaceByPrefix(namespacePrefix);
+
+        if (namespace!=null && namespace.length() > 0) {
+          tagText.append(" xmlns");
+          if (namespacePrefix.length() > 0) tagText.append(":").append(namespacePrefix);
+          tagText.append("=\"").append(namespace).append("\"");
+        }
+
+        XmlTag tagFromText = XmlElementFactory.getInstance(xmlTag.getProject()).createTagFromText("<" + tagText +"/>");
+        XmlElementDescriptor parentDescriptor = xmlTag.getDescriptor();
+        elementDescriptor = (parentDescriptor!=null)?parentDescriptor.getElementDescriptor(tagFromText, xmlTag):null;
+
+        if (elementDescriptor==null) {
+          PsiElement parent = xmlTag.getParent();
+          if (parent instanceof XmlTag) {
+            parentDescriptor = ((XmlTag)parent).getDescriptor();
+            elementDescriptor = (parentDescriptor!=null)?parentDescriptor.getElementDescriptor(tagFromText, (XmlTag)parent):null;
+          }
+        }
+
+        if (elementDescriptor instanceof AnyXmlElementDescriptor) {
+          final XmlNSDescriptor nsDescriptor = xmlTag.getNSDescriptor(xmlTag.getNamespaceByPrefix(namespacePrefix), true);
+          elementDescriptor = (nsDescriptor != null)?nsDescriptor.getElementDescriptor(tagFromText):null;
+        }
+
+        // The very special case of xml file
+        final PsiFile containingFile = xmlTag.getContainingFile();
+        final XmlFile xmlFile = XmlUtil.getContainingFile(xmlTag);
+        if (xmlFile != containingFile) {
+          final XmlTag rootTag = xmlFile.getDocument().getRootTag();
+          if (rootTag != null) {
+            final XmlNSDescriptor nsDescriptor = rootTag.getNSDescriptor(rootTag.getNamespaceByPrefix(namespacePrefix), true);
+            elementDescriptor = (nsDescriptor != null) ? nsDescriptor.getElementDescriptor(tagFromText) : null;
+          }
+        }
+
+        if (elementDescriptor != null) {
+          PsiElement declaration = elementDescriptor.getDeclaration();
+          if (declaration!=null) declaration.putUserData(DESCRIPTOR_KEY,elementDescriptor);
+          return declaration;
+        }
+      }
+      catch (IncorrectOperationException e) {
+        LOG.error(e);
+      }
+    }
+
+    if (object instanceof String && originalElement != null) {
+      PsiElement result = findDeclWithName((String)object, originalElement);
+
+      PsiElement originalElementParent;
+      if (result == null && element instanceof XmlTag && (originalElementParent = originalElement.getParent()) instanceof XmlAttributeValue) {
+        PsiElement originalElementGrandParent = originalElementParent.getParent();
+        XmlAttributeDescriptor descriptor = originalElementGrandParent instanceof XmlAttribute ?
+                                            ((XmlAttribute)originalElementGrandParent).getDescriptor():null;
+
+        if (descriptor != null && descriptor.getDeclaration() instanceof XmlTag) {
+          result = findEnumerationValue((String)object, (XmlTag)descriptor.getDeclaration());
+        }
+      }
+      return result;
+    }
+    if (object instanceof XmlElementDescriptor) {
+      return ((XmlElementDescriptor)object).getDeclaration();
+    }
+    return null;
+  }
+
+  public static PsiElement findDeclWithName(final String name, final @NotNull PsiElement element) {
+    final XmlFile containingXmlFile = XmlUtil.getContainingFile(element);
+    final XmlTag nearestTag = PsiTreeUtil.getParentOfType(element, XmlTag.class, false);
+    final XmlFile xmlFile = nearestTag != null? XmlCompletionData.findDescriptorFile(nearestTag, containingXmlFile):containingXmlFile;
+
+    if (xmlFile != null) {
+      final PsiElement[] result = new PsiElement[1];
+
+      XmlUtil.processXmlElements(
+        xmlFile,
+        new PsiElementProcessor() {
+          public boolean execute(@NotNull final PsiElement element) {
+            if (element instanceof XmlEntityDecl) {
+              final XmlEntityDecl entityDecl = (XmlEntityDecl)element;
+              if (entityDecl.isInternalReference() && name.equals(entityDecl.getName())) {
+                result[0] = entityDecl;
+                return false;
+              }
+            } else if (element instanceof XmlElementDecl) {
+              final XmlElementDecl entityDecl = (XmlElementDecl)element;
+              if (name.equals(entityDecl.getName())) {
+                result[0] = entityDecl;
+                return false;
+              }
+            }
+            return true;
+          }
+        },
+        true
+      );
+
+      return result[0];
+    }
+    return null;
+  }
+
+  public PsiElement getDocumentationElementForLink(final PsiManager psiManager, String link, PsiElement context) {
+    return null;
+  }
+
+  private static class MyPsiElementProcessor implements PsiElementProcessor {
+    String result;
+    String version;
+    String url;
+    @NonNls public static final String DOCUMENTATION_ELEMENT_LOCAL_NAME = "documentation";
+    private @NonNls static final String CDATA_PREFIX = "<![CDATA[";
+    private @NonNls static final String CDATA_SUFFIX = "]]>";
+
+    public boolean execute(@NotNull PsiElement element) {
+      if (element instanceof XmlTag &&
+          ((XmlTag)element).getLocalName().equals(DOCUMENTATION_ELEMENT_LOCAL_NAME)
+      ) {
+        final XmlTag tag = ((XmlTag)element);
+        result = tag.getValue().getText().trim();
+        boolean withCData = false;
+
+        if (result.startsWith(CDATA_PREFIX)) {
+          result = result.substring(CDATA_PREFIX.length());
+          withCData = true;
+        }
+
+        if (result.endsWith(CDATA_SUFFIX)) {
+          result = result.substring(0, result.length() - CDATA_SUFFIX.length());
+        }
+        result = result.trim();
+
+        if (withCData) {
+          result = escapeDocumentationTextText(result);
+        }
+
+        final @NonNls String s = tag.getAttributeValue("source");
+        if (s != null) {
+          if (s.startsWith("http:")) url = s;
+          else if ("version".equals(s)) {
+            version = result;
+            result = null;
+            return true;
+          }
+        }
+        return false;
+      }
+      return true;
+    }
+  }
+
+  private static String escapeDocumentationTextText(final String result) {
+    return StringUtil.escapeXml(result).replaceAll("&apos;","'").replaceAll("\n","<br>\n");
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/attributes.html b/xml/impl/src/com/intellij/xml/util/documentation/attributes.html
new file mode 100644
index 0000000..5a56faa
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/attributes.html
@@ -0,0 +1,2683 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html lang="en">
+<!-- $Id: attributes.html,v 1.1 2004/12/24 21:53:29 Maxim.Mossienko Exp $ -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Index of the HTML 4 Attributes</title>
+<link rel="previous" href="elements.html">
+<link rel="next" href="list.html">
+<link rel="contents" href="../cover.html#toc">
+<link rel="stylesheet" type="text/css" href= 
+"http://www.w3.org/StyleSheets/TR/W3C-REC">
+<link rel="STYLESHEET" href="../style/default.css" type="text/css">
+</head>
+<body>
+<div class="navbar" align="center">&nbsp;<a href="elements.html">previous</a>
+&nbsp; <a href="list.html">next</a> &nbsp; <a href="../cover.html#minitoc">
+contents</a> &nbsp; <a href="elements.html">elements</a> &nbsp; <a href= 
+"list.html">index</a> 
+
+<hr></div>
+
+<h1 align="center">Index of Attributes<a name="h-3">&nbsp;</a></h1>
+
+<p><em>Legend: <b>D</b>eprecated, <b>L</b>oose DTD, <b>F</b>rameset
+DTD</em></p>
+
+<table summary="Attribute index. Columns are: name, related elements, type of 
+value, default value, deprecated, which DTD, and comment" border="1" align= 
+"center">
+<tr align="center">
+<th>Name</th>
+<th>Related Elements</th>
+<th>Type</th>
+<th>Default</th>
+<th>Depr.</th>
+<th>DTD</th>
+<th>Comment</th>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-abbr">abbr</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Text">%Text;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">abbreviation for header cell</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-accept-charset">
+accept-charset</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-FORM" class="noxref">FORM</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Charsets">
+%Charsets;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">list of supported charsets</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-accept">accept</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-FORM" class="noxref">FORM</a>, <a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#ContentTypes">
+%ContentTypes;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">list of MIME types for file upload</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-accesskey">
+accesskey</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a>, <a href= 
+"../interact/forms.html#edef-BUTTON" class="noxref">BUTTON</a>, <a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../interact/forms.html#edef-LABEL" class="noxref">LABEL</a>, <a href= 
+"../interact/forms.html#edef-LEGEND" class="noxref">LEGEND</a>, <a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Character">
+%Character;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">accessibility key character</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-action">action</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-FORM" class="noxref">FORM</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">server-side form handler</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-align-CAPTION">
+align</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-CAPTION" class="noxref">CAPTION</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#CAlign">
+%CAlign;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">relative to table</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-align-IMG">align</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a>, <a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#IAlign">
+%IAlign;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">vertical or horizontal alignment</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-align-LEGEND">
+align</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-LEGEND" class="noxref">LEGEND</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#LAlign">
+%LAlign;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">relative to fieldset</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-align-TABLE">
+align</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TABLE" class="noxref">TABLE</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#TAlign">
+%TAlign;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">table position relative to window</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-align-HR">
+align</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/graphics.html#edef-HR" class="noxref">HR</a></td>
+<td align="center" title="Type">(left | center | right)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-align">align</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-DIV" class="noxref">DIV</a>, <a href= 
+"../struct/global.html#edef-H1" class="noxref">H1</a>, <a href= 
+"../struct/global.html#edef-H2" class="noxref">H2</a>, <a href= 
+"../struct/global.html#edef-H3" class="noxref">H3</a>, <a href= 
+"../struct/global.html#edef-H4" class="noxref">H4</a>, <a href= 
+"../struct/global.html#edef-H5" class="noxref">H5</a>, <a href= 
+"../struct/global.html#edef-H6" class="noxref">H6</a>, <a href= 
+"../struct/text.html#edef-P" class="noxref">P</a></td>
+<td align="center" title="Type">(left | center | right | justify)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">align, text alignment</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-align-TD">align</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-COL" class="noxref">COL</a>, <a href= 
+"../struct/tables.html#edef-COLGROUP" class="noxref">COLGROUP</a>, <a href= 
+"../struct/tables.html#edef-TBODY" class="noxref">TBODY</a>, <a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TFOOT" class="noxref">TFOOT</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a>, <a href= 
+"../struct/tables.html#edef-THEAD" class="noxref">THEAD</a>, <a href= 
+"../struct/tables.html#edef-TR" class="noxref">TR</a></td>
+<td align="center" title="Type">(left | center | right | justify | char)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-alink">alink</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-BODY" class="noxref">BODY</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Color">
+%Color;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">color of selected links</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-alt">alt</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Text">
+%Text;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">short description</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-alt">alt</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a>, <a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Text">%Text;</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">short description</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-alt">alt</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">short description</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-archive-APPLET">
+archive</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">comma-separated archive list</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-archive-OBJECT">
+archive</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">space-separated list of URIs</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-axis">axis</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">comma-separated list of related headers</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-background">
+background</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-BODY" class="noxref">BODY</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#URI">
+%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">texture tile for document background</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-bgcolor">
+bgcolor</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TABLE" class="noxref">TABLE</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Color">
+%Color;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">background color for cells</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-bgcolor">
+bgcolor</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TR" class="noxref">TR</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Color">
+%Color;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">background color for row</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-bgcolor">
+bgcolor</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Color">
+%Color;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">cell background color</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-bgcolor">
+bgcolor</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-BODY" class="noxref">BODY</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Color">
+%Color;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">document background color</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-border-TABLE">
+border</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TABLE" class="noxref">TABLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Pixels">
+%Pixels;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">controls frame width around table</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-border-IMG">
+border</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a>, <a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Pixels">
+%Pixels;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">link border width</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-cellpadding">
+cellpadding</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TABLE" class="noxref">TABLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">spacing within cells</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-cellspacing">
+cellspacing</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TABLE" class="noxref">TABLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">spacing between cells</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-char">char</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-COL" class="noxref">COL</a>, <a href= 
+"../struct/tables.html#edef-COLGROUP" class="noxref">COLGROUP</a>, <a href= 
+"../struct/tables.html#edef-TBODY" class="noxref">TBODY</a>, <a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TFOOT" class="noxref">TFOOT</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a>, <a href= 
+"../struct/tables.html#edef-THEAD" class="noxref">THEAD</a>, <a href= 
+"../struct/tables.html#edef-TR" class="noxref">TR</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Character">
+%Character;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">alignment char, e.g. char=':'</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-charoff">charoff</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-COL" class="noxref">COL</a>, <a href= 
+"../struct/tables.html#edef-COLGROUP" class="noxref">COLGROUP</a>, <a href= 
+"../struct/tables.html#edef-TBODY" class="noxref">TBODY</a>, <a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TFOOT" class="noxref">TFOOT</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a>, <a href= 
+"../struct/tables.html#edef-THEAD" class="noxref">THEAD</a>, <a href= 
+"../struct/tables.html#edef-TR" class="noxref">TR</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">offset for alignment char</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#adef-charset">charset</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/links.html#edef-LINK" class="noxref">LINK</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Charset">
+%Charset;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">char encoding of linked resource</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-checked">checked</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type">(checked)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for radio buttons and check boxes</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#adef-cite-Q">cite</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/text.html#edef-BLOCKQUOTE" class="noxref">BLOCKQUOTE</a>, <a href= 
+"../struct/text.html#edef-Q" class="noxref">Q</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">URI for source document or msg</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#adef-cite-INS">cite</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/text.html#edef-del" class="noxref">DEL</a>, <a href= 
+"../struct/text.html#edef-ins" class="noxref">INS</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">info on reason for change</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-class">class</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href="../struct/links.html#edef-BASE"
+class="noxref">BASE</a>, <a href="../present/graphics.html#edef-BASEFONT"
+class="noxref">BASEFONT</a>, <a href="../struct/global.html#edef-HEAD" class= 
+"noxref">HEAD</a>, <a href="../struct/global.html#edef-HTML" class="noxref">
+HTML</a>, <a href="../struct/global.html#edef-META" class="noxref">META</a>, <a
+href="../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">space-separated list of classes</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-classid">classid</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">identifies an implementation</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-clear">clear</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/text.html#edef-BR" class="noxref">BR</a></td>
+<td align="center" title="Type">(left | all | right | none)</td>
+<td align="center" title="Default">none</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">control of text flow</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-code">code</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">applet class file</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-codebase-OBJECT">
+codebase</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">base URI for classid, data, archive</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-codebase-APPLET">
+codebase</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#URI">
+%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">optional base URI for applet</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-codetype">
+codetype</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#ContentType">
+%ContentType;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">content type for code</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-color-FONT">
+color</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Color">
+%Color;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">text color</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-cols-FRAMESET">
+cols</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#MultiLengths">
+%MultiLengths;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">list of lengths, default: 100% (1 col)</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-cols-TEXTAREA">
+cols</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-colspan">colspan</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">1</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">number of cols spanned by cell</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#adef-compact">compact</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/lists.html#edef-DIR" class="noxref">DIR</a>, <a href= 
+"../struct/lists.html#edef-DL" class="noxref">DL</a>, <a href= 
+"../struct/lists.html#edef-MENU" class="noxref">MENU</a>, <a href= 
+"../struct/lists.html#edef-OL" class="noxref">OL</a>, <a href= 
+"../struct/lists.html#edef-UL" class="noxref">UL</a></td>
+<td align="center" title="Type">(compact)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">reduced interitem spacing</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-content">content</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-META" class="noxref">META</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">associated information</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-coords">coords</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Coords">
+%Coords;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">comma-separated list of lengths</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-coords">coords</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Coords">
+%Coords;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for use with client-side image maps</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-data">data</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">reference to object's data</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#adef-datetime">datetime</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/text.html#edef-del" class="noxref">DEL</a>, <a href= 
+"../struct/text.html#edef-ins" class="noxref">INS</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Datetime">
+%Datetime;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">date and time of change</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-declare">declare</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type">(declare)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">declare but don't instantiate flag</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-defer">defer</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a></td>
+<td align="center" title="Type">(defer)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">UA may defer execution of script</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/dirlang.html#adef-dir">dir</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a></td>
+<td align="center" title="Type">(ltr | rtl)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">direction for weak/neutral text</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/dirlang.html#adef-dir-BDO">dir</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a></td>
+<td align="center" title="Type">(ltr | rtl)</td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">directionality</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-disabled">
+disabled</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-BUTTON" class="noxref">BUTTON</a>, <a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../interact/forms.html#edef-OPTGROUP" class="noxref">OPTGROUP</a>, <a href= 
+"../interact/forms.html#edef-OPTION" class="noxref">OPTION</a>, <a href= 
+"../interact/forms.html#edef-SELECT" class="noxref">SELECT</a>, <a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type">(disabled)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">unavailable in this context</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-enctype">enctype</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-FORM" class="noxref">FORM</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#ContentType">
+%ContentType;</a></td>
+<td align="center" title="Default">"application/x-www- form-urlencoded"</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-face-FONT">
+face</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">comma-separated list of font names</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-for">for</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-LABEL" class="noxref">LABEL</a></td>
+<td align="center" title="Type"><a href="../types.html#type-idref">
+IDREF</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">matches field ID value</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-frame">frame</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TABLE" class="noxref">TABLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#TFrame">
+%TFrame;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">which parts of frame to render</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-frameborder">
+frameborder</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a></td>
+<td align="center" title="Type">(1 | 0)</td>
+<td align="center" title="Default">1</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">request frame borders?</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-headers">headers</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type"><a href="../types.html#type-idrefs">
+IDREFS</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">list of id's for header cells</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-height-IFRAME">
+height</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">frame height</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-height-TH">height</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">height for cell</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-height-IMG">
+height</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a>, <a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">override height</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-height-APPLET">
+height</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">initial height</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#adef-href">href</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a>, <a href= 
+"../struct/links.html#edef-LINK" class="noxref">LINK</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">URI for linked resource</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#adef-href-BASE">href</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">URI that acts as base URI</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#adef-hreflang">hreflang</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/links.html#edef-LINK" class="noxref">LINK</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#LanguageCode">
+%LanguageCode;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">language code</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-hspace">hspace</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a>, <a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Pixels">
+%Pixels;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">horizontal gutter</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-http-equiv">
+http-equiv</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-META" class="noxref">META</a></td>
+<td align="center" title="Type"><a href="../types.html#type-name">NAME</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">HTTP response header name</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-id">id</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href="../struct/links.html#edef-BASE"
+class="noxref">BASE</a>, <a href="../struct/global.html#edef-HEAD" class=
+"noxref">HEAD</a>, <a href="../struct/global.html#edef-HTML" class="noxref">
+HTML</a>, <a href="../struct/global.html#edef-META" class="noxref">META</a>, <a
+href="../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../types.html#type-id">ID</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">document-wide unique id</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-ismap">ismap</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a>, <a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type">(ismap)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">use server-side image map</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-label-OPTION">
+label</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-OPTION" class="noxref">OPTION</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Text">%Text;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for use in hierarchical menus</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-label-OPTGROUP">
+label</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-OPTGROUP" class="noxref">OPTGROUP</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Text">%Text;</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for use in hierarchical menus</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/dirlang.html#adef-lang">lang</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#LanguageCode">
+%LanguageCode;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">language code</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-language">
+language</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">predefined script language name</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-link">link</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-BODY" class="noxref">BODY</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Color">
+%Color;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">color of links</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-longdesc-IMG">
+longdesc</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">link to long description (complements
+alt)</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-longdesc-FRAME">
+longdesc</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">link to long description (complements
+title)</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-marginheight">
+marginheight</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Pixels">
+%Pixels;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">margin height in pixels</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-marginwidth">
+marginwidth</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Pixels">
+%Pixels;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">margin widths in pixels</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-maxlength">
+maxlength</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">max chars for text fields</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/styles.html#adef-media">media</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#MediaDesc">
+%MediaDesc;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">designed for use with these media</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/styles.html#adef-media">media</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/links.html#edef-LINK" class="noxref">LINK</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#MediaDesc">
+%MediaDesc;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for rendering on these media</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-method">method</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-FORM" class="noxref">FORM</a></td>
+<td align="center" title="Type">(GET | POST)</td>
+<td align="center" title="Default">GET</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">HTTP method used to submit the form</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-multiple">
+multiple</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-SELECT" class="noxref">SELECT</a></td>
+<td align="center" title="Type">(multiple)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">default is single selection</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-name-BUTTON">
+name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-BUTTON" class="noxref">BUTTON</a>, <a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-name-APPLET">
+name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">allows applets to find each other</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-name-SELECT">
+name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-SELECT" class="noxref">SELECT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">field name</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-name-FORM">name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-FORM" class="noxref">FORM</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">name of form for scripting</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-name-FRAME">name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">name of frame for targetting</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-name-IMG">name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">name of image for scripting</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#adef-name-A">name</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">named link end</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-name-INPUT">name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">submit as part of form</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-name-MAP">name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-MAP" class="noxref">MAP</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for reference by usemap</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-name-PARAM">name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">property name</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-name-META">name</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-META" class="noxref">META</a></td>
+<td align="center" title="Type"><a href="../types.html#type-name">NAME</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">metainformation name</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-nohref">nohref</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a></td>
+<td align="center" title="Type">(nohref)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">this region has no action</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-noresize">
+noresize</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a></td>
+<td align="center" title="Type">(noresize)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">allow users to resize frames?</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-noshade">
+noshade</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/graphics.html#edef-HR" class="noxref">HR</a></td>
+<td align="center" title="Type">(noshade)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-nowrap">nowrap</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type">(nowrap)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">suppress word wrap</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-object">object</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">serialized applet file</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onblur">onblur</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a>, <a href= 
+"../interact/forms.html#edef-BUTTON" class="noxref">BUTTON</a>, <a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../interact/forms.html#edef-LABEL" class="noxref">LABEL</a>, <a href= 
+"../interact/forms.html#edef-SELECT" class="noxref">SELECT</a>, <a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">the element lost the focus</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onchange">
+onchange</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../interact/forms.html#edef-SELECT" class="noxref">SELECT</a>, <a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">the element value was changed</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onclick">
+onclick</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a pointer button was clicked</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-ondblclick">
+ondblclick</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a pointer button was double clicked</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onfocus">
+onfocus</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a>, <a href= 
+"../interact/forms.html#edef-BUTTON" class="noxref">BUTTON</a>, <a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../interact/forms.html#edef-LABEL" class="noxref">LABEL</a>, <a href= 
+"../interact/forms.html#edef-SELECT" class="noxref">SELECT</a>, <a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">the element got the focus</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onkeydown">
+onkeydown</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a key was pressed down</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onkeypress">
+onkeypress</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a key was pressed and released</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onkeyup">
+onkeyup</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a key was released</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onload">onload</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">all the frames have been loaded</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onload">onload</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-BODY" class="noxref">BODY</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">the document has been loaded</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onmousedown">
+onmousedown</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a pointer button was pressed down</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onmousemove">
+onmousemove</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a pointer was moved within</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onmouseout">
+onmouseout</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a pointer was moved away</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onmouseover">
+onmouseover</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a pointer was moved onto</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onmouseup">
+onmouseup</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href=
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a>, <a href= 
+"../struct/dirlang.html#edef-BDO" class="noxref">BDO</a>, <a href= 
+"../struct/text.html#edef-BR" class="noxref">BR</a>, <a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a>, <a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a>, <a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a>, <a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a>, <a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a>, <a href= 
+"../struct/global.html#edef-META" class="noxref">META</a>, <a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">a pointer button was released</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onreset">
+onreset</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-FORM" class="noxref">FORM</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">the form was reset</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onselect">
+onselect</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">some text was selected</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onsubmit">
+onsubmit</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-FORM" class="noxref">FORM</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">the form was submitted</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onunload">
+onunload</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">all the frames have been removed</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-onunload">
+onunload</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-BODY" class="noxref">BODY</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Script">
+%Script;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">the document has been removed</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-profile">profile</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-HEAD" class="noxref">HEAD</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">named dictionary of meta info</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-prompt">prompt</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-ISINDEX" class="noxref">ISINDEX</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Text">
+%Text;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">prompt message</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-readonly">
+readonly</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type">(readonly)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-readonly">
+readonly</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type">(readonly)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for text and passwd</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#adef-rel">rel</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/links.html#edef-LINK" class="noxref">LINK</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#LinkTypes">
+%LinkTypes;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">forward link types</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#adef-rev">rev</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/links.html#edef-LINK" class="noxref">LINK</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#LinkTypes">
+%LinkTypes;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">reverse link types</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-rows-FRAMESET">
+rows</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAMESET" class="noxref">FRAMESET</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#MultiLengths">
+%MultiLengths;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">list of lengths, default: 100% (1 row)</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-rows-TEXTAREA">
+rows</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-rowspan">rowspan</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">1</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">number of rows spanned by cell</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-rules">rules</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TABLE" class="noxref">TABLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#TRules">
+%TRules;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">rulings between rows and cols</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-scheme">scheme</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-META" class="noxref">META</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">select form of content</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-scope">scope</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Scope">
+%Scope;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">scope covered by header cells</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-scrolling">
+scrolling</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a></td>
+<td align="center" title="Type">(yes | no | auto)</td>
+<td align="center" title="Default">auto</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">scrollbar or none</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-selected">
+selected</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-OPTION" class="noxref">OPTION</a></td>
+<td align="center" title="Type">(selected)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-shape">shape</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Shape">
+%Shape;</a></td>
+<td align="center" title="Default">rect</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">controls interpretation of coords</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-shape">shape</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Shape">
+%Shape;</a></td>
+<td align="center" title="Default">rect</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for use with client-side image maps</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-size-HR">size</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/graphics.html#edef-HR" class="noxref">HR</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Pixels">
+%Pixels;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-size-FONT">
+size</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/graphics.html#edef-FONT" class="noxref">FONT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">[+|-]nn e.g. size="+1", size="4"</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-size-INPUT">size</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">specific to each type of field</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-size-BASEFONT">
+size</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/graphics.html#edef-BASEFONT" class="noxref">BASEFONT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">base font size for FONT elements</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-size-SELECT">
+size</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-SELECT" class="noxref">SELECT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">rows visible</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-span-COL">span</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-COL" class="noxref">COL</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">1</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">COL attributes affect N columns</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-span-COLGROUP">
+span</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-COLGROUP" class="noxref">COLGROUP</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">1</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">default number of columns in group</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-src-SCRIPT">
+src</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">URI for an external script</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-src">src</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for fields with images</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-src-FRAME">src</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-FRAME" class="noxref">FRAME</a>, <a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Comment">source of frame content</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-src-IMG">src</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">URI of image to embed</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-standby">standby</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Text">%Text;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">message to show while loading</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#adef-start">start</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/lists.html#edef-OL" class="noxref">OL</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">starting sequence number</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/styles.html#adef-style">style</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href="../struct/links.html#edef-BASE"
+class="noxref">BASE</a>, <a href="../present/graphics.html#edef-BASEFONT"
+class="noxref">BASEFONT</a>, <a href="../struct/global.html#edef-HEAD" class= 
+"noxref">HEAD</a>, <a href="../struct/global.html#edef-HTML" class="noxref">
+HTML</a>, <a href="../struct/global.html#edef-META" class="noxref">META</a>, <a
+href="../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#StyleSheet">
+%StyleSheet;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">associated style info</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-summary">summary</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TABLE" class="noxref">TABLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Text">%Text;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">purpose/structure for speech output</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-tabindex">
+tabindex</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a>, <a href= 
+"../interact/forms.html#edef-BUTTON" class="noxref">BUTTON</a>, <a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a>, <a href= 
+"../interact/forms.html#edef-SELECT" class="noxref">SELECT</a>, <a href= 
+"../interact/forms.html#edef-TEXTAREA" class="noxref">TEXTAREA</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">position in tabbing order</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-target">target</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/objects.html#edef-AREA" class="noxref">AREA</a>, <a href= 
+"../struct/links.html#edef-BASE" class="noxref">BASE</a>, <a href= 
+"../interact/forms.html#edef-FORM" class="noxref">FORM</a>, <a href= 
+"../struct/links.html#edef-LINK" class="noxref">LINK</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#FrameTarget">
+%FrameTarget;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">render in this frame</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-text">text</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-BODY" class="noxref">BODY</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Color">
+%Color;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">document text color</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-title">title</a></td>
+<td align="center" title="Related Elements"><a href="../index/elements.html"
+class="noxref">All elements</a> but <a href="../struct/links.html#edef-BASE"
+class="noxref">BASE</a>, <a href="../present/graphics.html#edef-BASEFONT"
+class="noxref">BASEFONT</a>, <a href="../struct/global.html#edef-HEAD" class= 
+"noxref">HEAD</a>, <a href="../struct/global.html#edef-HTML" class="noxref">
+HTML</a>, <a href="../struct/global.html#edef-META" class="noxref">META</a>, <a
+href="../struct/objects.html#edef-PARAM" class="noxref">PARAM</a>, <a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a>, <a href= 
+"../struct/global.html#edef-TITLE" class="noxref">TITLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Text">%Text;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">advisory title</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#adef-type-A">type</a></td>
+<td align="center" title="Related Elements"><a href=
+"../struct/links.html#edef-A" class="noxref">A</a>, <a href= 
+"../struct/links.html#edef-LINK" class="noxref">LINK</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#ContentType">
+%ContentType;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">advisory content type</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-type-OBJECT">
+type</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#ContentType">
+%ContentType;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">content type for data</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-type-PARAM">type</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#ContentType">
+%ContentType;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">content type for value when
+valuetype=ref</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#adef-type-SCRIPT">
+type</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/scripts.html#edef-SCRIPT" class="noxref">SCRIPT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#ContentType">
+%ContentType;</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">content type of script language</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/styles.html#adef-type-STYLE">type</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/styles.html#edef-STYLE" class="noxref">STYLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#ContentType">
+%ContentType;</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">content type of style language</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-type-INPUT">type</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#InputType">
+%InputType;</a></td>
+<td align="center" title="Default">TEXT</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">what kind of widget is needed</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#adef-type-LI">type</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/lists.html#edef-LI" class="noxref">LI</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#LIStyle">
+%LIStyle;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">list item style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#adef-type-OL">type</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/lists.html#edef-OL" class="noxref">OL</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#OLStyle">
+%OLStyle;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">numbering style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#adef-type-UL">type</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/lists.html#edef-UL" class="noxref">UL</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#ULStyle">
+%ULStyle;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">bullet style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-type-BUTTON">
+type</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-BUTTON" class="noxref">BUTTON</a></td>
+<td align="center" title="Type">(button | submit | reset)</td>
+<td align="center" title="Default">submit</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">for use as form button</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-usemap">usemap</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a>, <a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a>, <a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#URI">%URI;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">use client-side image map</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-valign">valign</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-COL" class="noxref">COL</a>, <a href= 
+"../struct/tables.html#edef-COLGROUP" class="noxref">COLGROUP</a>, <a href= 
+"../struct/tables.html#edef-TBODY" class="noxref">TBODY</a>, <a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TFOOT" class="noxref">TFOOT</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a>, <a href= 
+"../struct/tables.html#edef-THEAD" class="noxref">THEAD</a>, <a href= 
+"../struct/tables.html#edef-TR" class="noxref">TR</a></td>
+<td align="center" title="Type">(top | middle | bottom | baseline)</td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">vertical alignment in cells</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-value-INPUT">
+value</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-INPUT" class="noxref">INPUT</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">Specify for radio buttons and
+checkboxes</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-value-OPTION">
+value</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-OPTION" class="noxref">OPTION</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">defaults to element content</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-value-PARAM">
+value</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">property value</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#adef-value-BUTTON">
+value</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../interact/forms.html#edef-BUTTON" class="noxref">BUTTON</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">sent to server when submitted</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#adef-value-LI">value</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/lists.html#edef-LI" class="noxref">LI</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">reset sequence number</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-valuetype">
+valuetype</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-PARAM" class="noxref">PARAM</a></td>
+<td align="center" title="Type">(DATA | REF | OBJECT)</td>
+<td align="center" title="Default">DATA</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">How to interpret value</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-version">version</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-HTML" class="noxref">HTML</a></td>
+<td align="center" title="Type"><a href="../types.html#type-cdata">
+CDATA</a></td>
+<td align="center" title="Default"><a href=
+"../sgml/loosedtd.html#HTML.Version">%HTML.Version;</a></td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">Constant</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#adef-vlink">vlink</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/global.html#edef-BODY" class="noxref">BODY</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Color">
+%Color;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">color of visited links</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-vspace">vspace</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a>, <a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a>, <a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Pixels">
+%Pixels;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">vertical gutter</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#adef-width-HR">
+width</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/graphics.html#edef-HR" class="noxref">HR</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#adef-width-IFRAME">
+width</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../present/frames.html#edef-IFRAME" class="noxref">IFRAME</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">frame width</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-width-IMG">width</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-IMG" class="noxref">IMG</a>, <a href= 
+"../struct/objects.html#edef-OBJECT" class="noxref">OBJECT</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">override width</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-width-TABLE">
+width</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TABLE" class="noxref">TABLE</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">table width</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-width-TH">width</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-TD" class="noxref">TD</a>, <a href= 
+"../struct/tables.html#edef-TH" class="noxref">TH</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">width for cell</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#adef-width-APPLET">
+width</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/objects.html#edef-APPLET" class="noxref">APPLET</a></td>
+<td align="center" title="Type"><a href="../sgml/loosedtd.html#Length">
+%Length;</a></td>
+<td align="center" title="Default">#REQUIRED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">initial width</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-width-COL">width</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-COL" class="noxref">COL</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#MultiLength">
+%MultiLength;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">column width specification</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#adef-width-COLGROUP">
+width</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/tables.html#edef-COLGROUP" class="noxref">COLGROUP</a></td>
+<td align="center" title="Type"><a href="../sgml/dtd.html#MultiLength">
+%MultiLength;</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Comment">default width for enclosed COLs</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#adef-width-PRE">width</a></td>
+<td align="center" title="Related Elements"><a href= 
+"../struct/text.html#edef-PRE" class="noxref">PRE</a></td>
+<td align="center" title="Type"><a href="../types.html#type-number">
+NUMBER</a></td>
+<td align="center" title="Default">#IMPLIED</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Comment">&nbsp;</td>
+</tr>
+</table>
+
+<div class="navbar" align="center">
+<hr><a href="elements.html">previous</a> &nbsp; <a href="list.html">next</a>
+&nbsp; <a href="../cover.html#minitoc">contents</a> &nbsp; <a href= 
+"elements.html">elements</a> &nbsp; <a href="list.html">index</a></div>
+</body>
+</html>
+
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/elements.html b/xml/impl/src/com/intellij/xml/util/documentation/elements.html
new file mode 100644
index 0000000..527bf9b
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/elements.html
@@ -0,0 +1,970 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html lang="en">
+<!-- $Id: elements.html,v 1.1 2004/12/24 21:53:29 Maxim.Mossienko Exp $ -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Index of the HTML 4 Elements</title>
+<link rel="previous" href="../references.html">
+<link rel="next" href="attributes.html">
+<link rel="contents" href="../cover.html#toc">
+<link rel="stylesheet" type="text/css" href= 
+"http://www.w3.org/StyleSheets/TR/W3C-REC">
+<link rel="STYLESHEET" href="../style/default.css" type="text/css">
+</head>
+<body>
+<div class="navbar" align="center">&nbsp;<a href="../references.html">
+previous</a> &nbsp; <a href="attributes.html">next</a> &nbsp; <a href= 
+"../cover.html#minitoc">contents</a> &nbsp; <a href="attributes.html">
+attributes</a> &nbsp; <a href="list.html">index</a> 
+
+<hr></div>
+
+<h1 align="center">Index of Elements<a name="h-2">&nbsp;</a></h1>
+
+<p><em>Legend: <b>O</b>ptional, <b>F</b>orbidden, <b>E</b>mpty, <b>
+D</b>eprecated, <b>L</b>oose DTD, <b>F</b>rameset DTD</em></p>
+
+<table summary="Element index. Columns are: Name, start tag required, end tag 
+required, empty, deprecated, which DTD, and description" border="1" align= 
+"center">
+<tr align="center">
+<th>Name</th>
+<th>Start Tag</th>
+<th>End Tag</th>
+<th>Empty</th>
+<th>Depr.</th>
+<th>DTD</th>
+<th>Description</th>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#edef-A">A</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">anchor</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-ABBR">ABBR</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">abbreviated form (e.g., WWW, HTTP,etc.)</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-ACRONYM">ACRONYM</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-ADDRESS">ADDRESS</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">information on author</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#edef-APPLET">APPLET</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">Java applet</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#edef-AREA">AREA</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">client-side image map area</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-B">B</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">bold text style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#edef-BASE">BASE</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">document base URI</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-BASEFONT">
+BASEFONT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">base font size</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/dirlang.html#edef-BDO">BDO</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">I18N BiDi over-ride</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-BIG">BIG</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">large text style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-BLOCKQUOTE">
+BLOCKQUOTE</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">long quotation</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-BODY">BODY</a></td>
+<td align="center" title="Start Tag">O</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">document body</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-BR">BR</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">forced line break</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-BUTTON">BUTTON</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">push button</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-CAPTION">CAPTION</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">table caption</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-CENTER">CENTER</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">shorthand for DIV align=center</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-CITE">CITE</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">citation</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-CODE">CODE</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">computer code fragment</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-COL">COL</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">table column</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-COLGROUP">
+COLGROUP</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">table column group</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#edef-DD">DD</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">definition description</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-del">DEL</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">deleted text</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-DFN">DFN</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">instance definition</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#edef-DIR">DIR</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">directory list</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-DIV">DIV</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">generic language/style container</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#edef-DL">DL</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">definition list</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#edef-DT">DT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">definition term</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-EM">EM</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">emphasis</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-FIELDSET">
+FIELDSET</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">form control group</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-FONT">FONT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">local change to font</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-FORM">FORM</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">interactive form</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#edef-FRAME">FRAME</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Description">subwindow</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#edef-FRAMESET">
+FRAMESET</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Description">window subdivision</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-H1">H1</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">heading</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-H2">H2</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">heading</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-H3">H3</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">heading</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-H4">H4</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">heading</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-H5">H5</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">heading</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-H6">H6</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">heading</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-HEAD">HEAD</a></td>
+<td align="center" title="Start Tag">O</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">document head</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-HR">HR</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">horizontal rule</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-HTML">HTML</a></td>
+<td align="center" title="Start Tag">O</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">document root element</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-I">I</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">italic text style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#edef-IFRAME">IFRAME</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">inline subwindow</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#edef-IMG">IMG</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">Embedded image</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-INPUT">INPUT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">form control</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-ins">INS</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">inserted text</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-ISINDEX">ISINDEX</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">single line prompt</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-KBD">KBD</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">text to be entered by the user</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-LABEL">LABEL</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">form field label text</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-LEGEND">LEGEND</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">fieldset legend</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#edef-LI">LI</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">list item</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/links.html#edef-LINK">LINK</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">a media-independent link</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#edef-MAP">MAP</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">client-side image map</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#edef-MENU">MENU</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">menu list</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-META">META</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">generic metainformation</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/frames.html#edef-NOFRAMES">
+NOFRAMES</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">F</td>
+<td align="center" title="Description">alternate content container for non
+frame-based rendering</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#edef-NOSCRIPT">
+NOSCRIPT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">alternate content container for non
+script-based rendering</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#edef-OBJECT">OBJECT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">generic embedded object</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#edef-OL">OL</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">ordered list</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-OPTGROUP">
+OPTGROUP</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">option group</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-OPTION">OPTION</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">selectable choice</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-P">P</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">paragraph</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/objects.html#edef-PARAM">PARAM</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">named property value</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-PRE">PRE</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">preformatted text</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-Q">Q</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">short inline quotation</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-S">S</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">strike-through text style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-SAMP">SAMP</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">sample program output, scripts,
+etc.</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/scripts.html#edef-SCRIPT">SCRIPT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">script statements</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-SELECT">SELECT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">option selector</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-SMALL">SMALL</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">small text style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-SPAN">SPAN</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">generic language/style container</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-STRIKE">STRIKE</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">strike-through text</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-STRONG">STRONG</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">strong emphasis</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/styles.html#edef-STYLE">STYLE</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">style info</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-SUB">SUB</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">subscript</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-SUP">SUP</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">superscript</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-TABLE">TABLE</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">&nbsp;</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-TBODY">TBODY</a></td>
+<td align="center" title="Start Tag">O</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">table body</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-TD">TD</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">table data cell</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../interact/forms.html#edef-TEXTAREA">
+TEXTAREA</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">multi-line text field</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-TFOOT">TFOOT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">table footer</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-TH">TH</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">table header cell</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-THEAD">THEAD</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">table header</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-TITLE">TITLE</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">document title</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/tables.html#edef-TR">TR</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">table row</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-TT">TT</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">teletype or monospaced text style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../present/graphics.html#edef-U">U</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">D</td>
+<td align="center" title="DTD">L</td>
+<td align="center" title="Description">underlined text style</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/lists.html#edef-UL">UL</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">unordered list</td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/text.html#edef-VAR">VAR</a></td>
+<td align="center" title="Start Tag">&nbsp;</td>
+<td align="center" title="End Tag">&nbsp;</td>
+<td align="center" title="Empty">&nbsp;</td>
+<td align="center" title="Depr.">&nbsp;</td>
+<td align="center" title="DTD">&nbsp;</td>
+<td align="center" title="Description">instance of a variable or program
+argument</td>
+</tr>
+</table>
+
+<div class="navbar" align="center">
+<hr><a href="../references.html">previous</a> &nbsp; <a href="attributes.html">
+next</a> &nbsp; <a href="../cover.html#minitoc">contents</a> &nbsp; <a href= 
+"attributes.html">attributes</a> &nbsp; <a href="list.html">index</a></div>
+</body>
+</html>
+
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml b/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml
new file mode 100644
index 0000000..94c2e45
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml
@@ -0,0 +1,522 @@
+<html-property-table baseHelpRef="http://dev.w3.org/html5/spec/">
+<tag name        = "section"
+     helpref     = "sections.html#the-section-element"
+     description = "generic document or application section"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "article"
+     helpref     = "sections.html#the-article-element"
+     description = "self-contained composition in a document, page, application, or site and that is intended to be independently distributable or reusable, e.g. in syndication"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "aside"
+     helpref     = "sections.html#the-aside-element"
+     description = "a section of a page that consists of content that is tangentially related to the content around the aside element, and which could be considered separate from that content"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "hgroup"
+     helpref     = "sections.html#the-hgroup-element"
+     description = "heading of a section"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "header"
+     helpref     = "sections.html#the-header-element"
+     description = "group of introductory or navigational aids"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "footer"
+     helpref     = "sections.html#the-footer-element"
+     description = "a footer for its nearest ancestor sectioning content or sectioning root element"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "nav"
+     helpref     = "sections.html#the-nav-element"
+     description = "section of a page that links to other pages or to parts within the page"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "figure"
+     helpref     = "grouping-content.html#the-figure-element"
+     description = "some flow content, optionally with a caption, that is self-contained and is typically referenced as a single unit from the main flow of the document"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "figcaption"
+     helpref     = "grouping-content.html#the-figcaption-element"
+     description = "a caption or legend for the rest of the contents of the figcaption element's parent figure element, if any"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "video"
+     helpref     = "video.html#video"
+     description = "used for playing videos or movies"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "audio"
+     helpref     = "video.html#audio"
+     description = "a sound or audio stream"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "embed"
+     helpref     = "the-iframe-element.html#the-embed-element"
+     description = "integration point for an external application or interactive content"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "mark"
+     helpref     = "text-level-semantics.html#the-mark-element"
+     description = "a run of text in one document marked or highlighted for reference purposes, due to its relevance in another context"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "progress"
+     helpref     = "the-button-element.html#the-progress-element"
+     description = "the completion progress of a task"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "meter"
+     helpref     = "the-button-element.html#the-meter-element"
+     description = "a scalar measurement within a known range, or a fractional value"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "time"
+     helpref     = "rendering.html#the-time-element-0"
+     description = "either a time on a 24 hour clock, or a precise date in the proleptic Gregorian calendar, optionally with a time and a time-zone offset"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "ruby"
+     helpref     = "text-level-semantics.html#the-ruby-element"
+     description = "allows one or more spans of phrasing content to be marked with ruby annotation"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "rt"
+     helpref     = "text-level-semantics.html#the-rt-element"
+     description = "marks the ruby text component of a ruby annotation"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "rp"
+     helpref     = "text-level-semantics.html#the-rp-element"
+     description = "can be used to provide parentheses around a ruby text component of a ruby annotation, to be shown by user agents that don't support ruby annotations"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "canvas"
+     helpref     = "the-canvas-element.html#the-canvas-element"
+     description = "provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, or other visual images on the fly"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "command"
+     helpref     = "interactive-elements.html#the-command"
+     description = "provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, or other visual images on the fly"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "datalist"
+     helpref     = "the-button-element.html#the-datalist-element"
+     description = "a set of option elements that represent predefined options for other controls"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "keygen"
+     helpref     = "the-button-element.html#the-keygen-element"
+     description = "a key pair generator control"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "output"
+     helpref     = "the-button-element.html#the-output-element"
+     description = "the result of a calculation"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<attribute name        = "media"
+           helpref     = "links.html#attr-hyperlink-media"
+           description = "suppress word wrap"
+           relatedTags = "a,area"
+           dtd         = ""
+           type        = "common.data.mediaquery"
+           default     = "false"
+/>
+<attribute name        = "ping"
+           helpref     = ""
+           description = "a space-separated list of URLs which have to be pinged when the hyperlink is followed"
+           relatedTags = "a,area"
+           dtd         = ""
+           type        = "common.data.uris"
+           default     = "true"
+/>
+<attribute name        = "hreflang"
+           helpref     = "links.html#attr-hyperlink-hreflang"
+           description = "gives the language of the linked resource"
+           relatedTags = "area"
+           dtd         = ""
+           type        = "common.data.langcode"
+           default     = "false"
+/>
+<attribute name        = "rel"
+           helpref     = "links.html#attr-hyperlink-rel"
+           description = ""
+           relatedTags = "area"
+           dtd         = ""
+           type        = "common.data.tokens"
+           default     = "false"
+/>
+<attribute name        = "charset"
+           helpref     = "semantics.html#attr-meta-charset"
+           description = "the character encoding used by the document"
+           relatedTags = "meta"
+           dtd         = ""
+           type        = "common.data.charset"
+           default     = "false"
+/>
+<attribute name        = "autofocus"
+           helpref     = "association-of-controls-and-forms.html#attr-fe-autofocus"
+           description = "allows the user to indicate that a control is to be focused as soon as the page is loaded, allowing the user to just start typing without having to manually focus the main control"
+           relatedTags = "input,select,textarea,button"
+           dtd         = ""
+           type        = "(autofocus)"
+           default     = "true"
+/>
+<attribute name        = "placeholder"
+           helpref     = "common-input-element-attributes.html#attr-input-placeholder"
+           description = "short hint (a word or short phrase) intended to aid the user with data entry"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "string"
+           default     = "true"
+/>
+<attribute name        = "placeholder"
+           helpref     = "the-button-element.html#attr-textarea-placeholder"
+           description = "a hint (a word or short phrase) intended to aid the user with data entry"
+           relatedTags = "textarea"
+           dtd         = ""
+           type        = "string"
+           default     = "false"
+/>
+<attribute name        = "form"
+           helpref     = "association-of-controls-and-forms.html#attr-fae-form"
+           description = ""
+           relatedTags = "input,output,select,textarea,button,fieldset"
+           dtd         = ""
+           type        = "common.data.idref"
+           default     = "true"
+/>
+<attribute name        = "required"
+           helpref     = "common-input-element-attributes.html#attr-input-required"
+           description = "when specified, the element is required"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "(required)"
+           default     = "true"
+/>
+<attribute name        = "required"
+           helpref     = "the-button-element.html#attr-textarea-required"
+           description = "when specified, the user will be required to enter a value before submitting the form"
+           relatedTags = "textarea"
+           dtd         = ""
+           type        = "(required)"
+           default     = "false"
+/>
+<attribute name        = "disabled"
+           helpref     = ""
+           description = "disabling all its contents when specified"
+           relatedTags = "fieldset"
+           dtd         = ""
+           type        = "(disabled)"
+           default     = "false"
+/>
+<attribute name        = "autocomplete"
+           helpref     = "common-input-element-attributes.html#attr-input-autocomplete"
+           description = "autocompletion state"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "(on | off)"
+           default     = "true"
+/>
+<attribute name        = "min"
+           helpref     = "common-input-element-attributes.html#attr-input-min"
+           description = "indicate the allowed range of values for the element"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "common.data.datetime"
+           default     = "true"
+/>
+<attribute name        = "max"
+           helpref     = "common-input-element-attributes.html#attr-input-max"
+           description = "indicate the allowed range of values for the element"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "common.data.datetime"
+           default     = "true"
+/>
+<attribute name        = "multiple"
+           helpref     = "common-input-element-attributes.html#attr-input-multiple"
+           description = "whether the user is to be allowed to specify more than one value"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "(multiple)"
+           default     = "false"
+/>
+<attribute name        = "pattern"
+           helpref     = "common-input-element-attributes.html#attr-input-pattern"
+           description = "regular expression against which the control's value is to be checked"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "form.data.pattern"
+           default     = "true"
+/>
+<attribute name        = "step"
+           helpref     = "common-input-element-attributes.html#attr-input-step"
+           description = "the granularity that is expected (and required) of the value, by limiting the allowed values"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "string"
+           default     = "true"
+/>
+<attribute name        = "list"
+           helpref     = "common-input-element-attributes.html#attr-input-list"
+           description = "element that lists predefined options suggested to the user"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "common.data.idref"
+           default     = "true"
+/>
+<attribute name        = "novalidate"
+           helpref     = "association-of-controls-and-forms.html#attr-fs-novalidate"
+           description = "if the form is not to be validated during submission"
+           relatedTags = "form"
+           dtd         = ""
+           type        = "(novalidate)"
+           default     = "true"
+/>
+<attribute name        = "formnovalidate"
+           helpref     = "association-of-controls-and-forms.html#attr-fs-formnovalidate"
+           description = "if the form is not to be validated during submission"
+           relatedTags = "input,button"
+           dtd         = ""
+           type        = "(formnovalidate)"
+           default     = "true"
+/>
+<attribute name        = "formaction"
+           helpref     = "association-of-controls-and-forms.html#attr-fs-formaction"
+           description = "server-side form handler"
+           relatedTags = "input,button"
+           dtd         = ""
+           type        = "common.data.uri"
+           default     = "true"
+/>
+<attribute name        = "formenctype"
+           helpref     = "association-of-controls-and-forms.html#attr-fs-formenctype"
+           description = ""
+           relatedTags = "input,button"
+           dtd         = ""
+           type        = "shared-form.attrs.formenctype.data"
+           default     = "true"
+/>
+<attribute name        = "formmethod"
+           helpref     = "association-of-controls-and-forms.html#attr-fs-formmethod"
+           description = "HTTP method used to submit the form"
+           relatedTags = "input,button"
+           dtd         = ""
+           type        = "(GET | POST)"
+           default     = "true"
+/>
+<attribute name        = "formtarget"
+           helpref     = "association-of-controls-and-forms.html#attr-fs-formtarget"
+           description = "render in this frame"
+           relatedTags = "input,button"
+           dtd         = ""
+           type        = "common.data.browsing-context-or-keyword"
+           default     = "true"
+/>
+<attribute name        = "type"
+           helpref     = "interactive-elements.html#attr-menu-type"
+           description = "kind of menu being declared"
+           relatedTags = "menu"
+           dtd         = ""
+           type        = "(toolbar | context)"
+           default     = "false"
+/>
+<attribute name        = "label"
+           helpref     = "interactive-elements.html#attr-menu-label"
+           description = "label of the menu"
+           relatedTags = "menu"
+           dtd         = ""
+           type        = "string"
+           default     = "false"
+/>
+<attribute name        = "scoped"
+           helpref     = "interactive-elements.html#attr-menu-label"
+           description = "enables scoped style sheets"
+           relatedTags = "style"
+           dtd         = ""
+           type        = "(scoped)"
+           default     = "true"
+/>
+<attribute name        = "async"
+           helpref     = "scripting-1.html#attr-script-async"
+           description = "influences script loading and execution"
+           relatedTags = "script"
+           dtd         = ""
+           type        = "(async)"
+           default     = "true"
+/>
+<attribute name        = "manifest"
+           helpref     = "semantics.html#attr-html-manifest"
+           description = "address of the document's application cache manifest"
+           relatedTags = "html"
+           dtd         = ""
+           type        = "common.data.uri"
+           default     = "true"
+/>
+<attribute name        = "sizes"
+           helpref     = "links.html#attr-link-sizes"
+           description = "the size of the referenced icon"
+           relatedTags = "link"
+           dtd         = ""
+           type        = "string"
+           default     = "true"
+/>
+<attribute name        = "reversed"
+           helpref     = "grouping-content.html#attr-ol-reversed"
+           description = "if the list order is descending when present"
+           relatedTags = "ol"
+           dtd         = ""
+           type        = "(reversed)"
+           default     = "true"
+/>
+<attribute name        = "sandbox"
+           helpref     = "the-iframe-element.html#attr-iframe-sandbox"
+           description = "enables a set of extra restrictions on any content hosted by the iframe"
+           relatedTags = "iframe"
+           dtd         = ""
+           type        = "SandboxType"
+           default     = "true"
+/>
+<attribute name        = "seamless"
+           helpref     = "the-iframe-element.html#attr-iframe-seamless"
+           description = ""
+           relatedTags = "iframe"
+           dtd         = ""
+           type        = "(seamless)"
+           default     = "true"
+/>
+<attribute name        = "srcdoc"
+           helpref     = "the-iframe-element.html#attr-iframe-srcdoc"
+           description = "content of the page that the nested browsing context is to contain"
+           relatedTags = "iframe"
+           dtd         = ""
+           type        = "string"
+           default     = "true"
+/>
+<tag name        = "bdi"
+     helpref     = "text-level-semantics.html#the-bdi-element"
+     description = "represents a span of text that is to be isolated from its surroundings for the purposes of bidirectional text formatting"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "details"
+     helpref     = "interactive-elements.html#the-details-element"
+     description = "represents a disclosure widget from which the user can obtain additional information or controls"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "source"
+     helpref     = "video.html#the-source-element"
+     description = "allows authors to specify multiple alternative media resources for media elements. It does not represent anything on its own"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "summary"
+     helpref     = "interactive-elements.html#the-summary-element"
+     description = "represents a summary, caption, or legend for the rest of the contents of the summary element's parent details element, if any"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "track"
+     helpref     = "video.html#the-track-element"
+     description = "allows authors to specify explicit external timed text tracks for media elements. It does not represent anything on its own"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "wbr"
+     helpref     = "text-level-semantics.html#the-wbr-element"
+     description = "represents a line break opportunity"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+</html-property-table>
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/htmlTagTableGen.pl b/xml/impl/src/com/intellij/xml/util/documentation/htmlTagTableGen.pl
new file mode 100644
index 0000000..65918b3
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/htmlTagTableGen.pl
@@ -0,0 +1,233 @@
+
+open(I,"elements.html");
+
+$tagname = "";
+$helpref = "";
+$description = "";
+$startTag="";
+
+$endTag="";
+$empty ="";
+$dtd="";
+
+open(O,">htmltable.xml");
+$basehref="http://www.w3.org/TR/HTML4/";
+print O  "<html-property-table version=\"4_01\" generator-version=\"1\" baseHelpRef=\"$basehref\">\n";
+$expectedName = 0;
+
+while(<I>) {
+  if ($_ =~ /<td title="Name">(.*)<\/td>/i ||
+    ( $expectedName == 1 &&
+      $_ =~ /(.*)<\/a><\/td>/i  #accept-charset</a></td>
+    )
+   ) {
+    $value = $1;
+
+    if (length ($tagname) > 0) {
+      printTagInfo($tagname, $helpref, $description, $startTag, $endTag, $empty,
+        $dtd
+      );
+    }
+
+    $tagname = $value;
+    $tagname =~ s/<a href="([^"]*)">(.*?)<\/a>/$2/i;
+    if ($expectedName == 0) {
+      $helpref = substr($1,3,length($1)-3);
+    }
+
+    $tagname = lc($tagname);
+    $expectedName = 0;
+  } else {
+    if ($_ =~ /<td title="Name">(.*)>/i) { #<td title="Name"><a href="../interact/forms.html#adef-accept-charset">
+        if (length ($tagname) > 0) {
+          printTagInfo($tagname, $helpref, $description, $startTag, $endTag, $empty,
+            $dtd
+          );
+        }
+
+        $tagname="";
+        $expectedName=1;
+        $helpref = $1;
+
+        $helpref =~ s/<a href="([^"]*)"/$1/i; #<a href="../interact/forms.html#adef-accept-charset"
+        $helpref = substr($helpref,3,length($helpref)-3);
+      }
+      elsif ($_ =~ /<td align="center" title="Description">(.*)<\/td>/i) {
+      $description = $1;
+    } elsif ($_ =~ /<td align="center" title="Start Tag">(.*)<\/td>/i) {
+      $startTag = $1;
+      if ($startTag eq "O") { $startTag = "false"; }
+    } elsif ($_ =~ /<td align="center" title="End Tag">(.*)<\/td>/i) {
+      $endTag = $1;
+      if ($endTag eq "O") { $endTag = "false"; }
+      elsif ($endTag eq "F") { $endTag = "true"; }
+    } elsif ($_ =~ /<td align="center" title="Empty">(.*)<\/td>/i) {
+      $empty = $1;
+      if ($empty eq "E") { $empty = "true"; }
+    } elsif ($_ =~ /<td align="center" title="DTD">(.*)<\/td>/i) {
+      $dtd = $1;
+    }
+  }
+}
+
+if (length ($tagname) > 0) {
+  printTagInfo($tagname, $helpref, $description, $startTag, $endTag, $empty,
+    $dtd
+  );
+}
+
+close(I);
+open(I,"attributes.html");
+
+$attributeName = "";
+$processingRelated = 0;
+$expectedName = 0;
+
+while(<I>) {
+  if (!$processingRelated) {
+    if ($_ =~ /<td title="Name">(.*)<\/td>/i || #<td title="Name"><a href="../struct/tables.html#adef-abbr">abbr</a></td>
+        ( $expectedName == 1 &&
+          $_ =~ /(.*)<\/a><\/td>/i  #accept-charset</a></td>
+        )
+       ) {
+      $value = $1;
+
+      if (length ($attributeName) > 0) {
+        printAttributeInfo($attributeName, $helpref, $description, $relatedTags, $dtd, $type, $default);
+      }
+
+      $attributeName = $value;
+      $attributeName =~ s/<a href="([^"]*)">(.*)<\/a>/$2/i;
+      if ($expectedName == 0) {
+        $helpref = substr($1,3,length($1)-3);
+      }
+
+      $attributeName = lc($attributeName);
+      $expectedName = 0;
+    } else {
+      if ($_ =~ /<td title="Name">(.*)>/i) { #<td title="Name"><a href="../interact/forms.html#adef-accept-charset">
+        if (length ($attributeName) > 0) {
+          printAttributeInfo($attributeName, $helpref, $description, $relatedTags, $dtd, $type, $default);
+        }
+
+        $attributeName="";
+        $expectedName=1;
+        $helpref = $1;
+        
+        $helpref =~ s/<a href="([^"]*)"/$1/i; #<a href="../interact/forms.html#adef-accept-charset"
+        $helpref = substr($helpref,3,length($helpref)-3);
+      } 
+      elsif ($_ =~ /<td align="center" title="Comment">(.*)<\/td>/i) {
+        $description = $1;
+        $description =~ s/"/&quot;/g;
+      } elsif ($_ =~ /<td align="center" title="Related Elements">/i) {	
+        $relatedTags = "";
+        $processingRelated=1;
+      } elsif ($_ =~ /<td align="center" title="DTD">(.*)<\/td>/i) {
+        $dtd = $1;
+      } elsif ($_ =~ /<td align="center" title="Type">(.*)<\/td>/i) {
+        $type = $1;
+        #<a href="../sgml/dtd.html#URI">%URI;</a> -> %URI;
+        $type =~ s/<a href="([^"]*)">(.*)<\/a>/$2/i;
+        $type =~ s/%(.*);/$1/i;
+      } elsif ($_ =~ /<td align="center" title="Default">(.*)<\/td>/i) {
+        $default = $1;
+        if ($default eq "#REQUIRED") { $default="false"; }
+        else { $default="true"; }
+      } elsif ($_ =~ /<td align="center" title="Type"><a href="[^"]*">/i) {
+        $expectedType = 1;
+      } elsif ( $expectedType == 1 &&
+        $_ =~ /(.*)<\/a><\/td>/i
+      ) {
+        $expectedType = 0;
+        $type = $1;
+        $type =~ s/%(.*);/$1/i;
+      }
+    }
+  } else {
+    $newRelTags = extractRelatedTag($_);
+    if(defined($newRelTags)) {
+      if(length($relatedTags) != 0) {
+        $relatedTags = "$relatedTags,"; 
+      }
+      $relatedTags = "$relatedTags$newRelTags";
+    }
+ 
+    if(/.*<\/td>$/i) {
+      $processingRelated=0;
+    }
+  }
+}
+
+if (length ($attributeName) > 0) {
+  printAttributeInfo($attributeName, $helpref, $description, $relatedTags, $dtd, $type, $default);
+}
+
+sub extractRelatedTag {
+  my $a = $_[0];
+  my $result;
+  my $other;
+
+  if($a =~ /^.*?([ \w]+)<\/a>(.*)/i) {
+    $result = lc($1);
+    $result = "!" if $result eq "all elements";
+
+    $other = extractRelatedTag($2);
+
+    return $result if (!defined($other));
+    return "$result,$other";
+  }
+
+  return undef;
+}
+sub printTagInfo {
+  my ($name,$helpref,$description,$startTag,$endTag,$empty,$dtd) = @_;
+
+  $description = &fixNbspEqualToDefault($description,"");
+  $startTag = &fixNbspEqualToDefault($startTag,"true");
+  $endTag = &fixNbspEqualToDefault($endTag,"true");
+  $empty = &fixNbspEqualToDefault($empty,"false");
+  $dtd = &fixNbspEqualToDefault($dtd,"");
+
+  print O <<END
+<tag name        = "$name"
+     helpref     = "$helpref"
+     description = "$description"
+     startTag    = "$startTag"
+     endTag      = "$endTag"
+     empty       = "$empty"
+     dtd         = "$dtd"
+/>
+END
+}
+
+sub printAttributeInfo {
+  my ($name,$helpref,$description,$relatedTags,$dtd,$type, $default) = @_;
+
+  $description = &fixNbspEqualToDefault($description,"");
+  $dtd = &fixNbspEqualToDefault($dtd,"");
+
+  print O <<END2
+<attribute name        = "$name"
+           helpref     = "$helpref"
+           description = "$description"
+           relatedTags = "$relatedTags"
+           dtd         = "$dtd"
+           type        = "$type"
+           default     = "$default"
+/>
+END2
+}
+
+sub fixNbspEqualToDefault {
+  if ( $_[0] =~ /&nbsp;/ ) {
+    return $_[1];
+  } else {
+    return $_[0];
+  }
+}
+
+print O  "</html-property-table>";
+
+close(I);
+close(O);
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/htmltable.xml b/xml/impl/src/com/intellij/xml/util/documentation/htmltable.xml
new file mode 100644
index 0000000..6a76727
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/htmltable.xml
@@ -0,0 +1,2234 @@
+<html-property-table version="4_01" generator-version="1" baseHelpRef="http://www.w3.org/TR/HTML4/">
+<tag name        = "a"
+     helpref     = "struct/links.html#edef-A"
+     description = "anchor"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "abbr"
+     helpref     = "struct/text.html#edef-ABBR"
+     description = "abbreviated form (e.g., WWW, HTTP,etc.)"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "acronym"
+     helpref     = "struct/text.html#edef-ACRONYM"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "address"
+     helpref     = "struct/global.html#edef-ADDRESS"
+     description = "information on author"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "applet"
+     helpref     = "struct/objects.html#edef-APPLET"
+     description = "Java applet"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "L"
+/>
+<tag name        = "area"
+     helpref     = "struct/objects.html#edef-AREA"
+     description = "client-side image map area"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "b"
+     helpref     = "present/graphics.html#edef-B"
+     description = "bold text style"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "base"
+     helpref     = "struct/links.html#edef-BASE"
+     description = "document base URI"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "basefont"
+     helpref     = "present/graphics.html#edef-BASEFONT"
+     description = "base font size"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = "L"
+/>
+<tag name        = "bdo"
+     helpref     = "struct/dirlang.html#edef-BDO"
+     description = "I18N BiDi over-ride"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "big"
+     helpref     = "present/graphics.html#edef-BIG"
+     description = "large text style"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "blockquote"
+     helpref     = "struct/text.html#edef-BLOCKQUOTE"
+     description = "long quotation"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "body"
+     helpref     = "struct/global.html#edef-BODY"
+     description = "document body"
+     startTag    = "false"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "br"
+     helpref     = "struct/text.html#edef-BR"
+     description = "forced line break"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "button"
+     helpref     = "interact/forms.html#edef-BUTTON"
+     description = "push button"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "caption"
+     helpref     = "struct/tables.html#edef-CAPTION"
+     description = "table caption"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "center"
+     helpref     = "present/graphics.html#edef-CENTER"
+     description = "shorthand for DIV align=center"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "L"
+/>
+<tag name        = "cite"
+     helpref     = "struct/text.html#edef-CITE"
+     description = "citation"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "code"
+     helpref     = "struct/text.html#edef-CODE"
+     description = "computer code fragment"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "col"
+     helpref     = "struct/tables.html#edef-COL"
+     description = "table column"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "colgroup"
+     helpref     = "struct/tables.html#edef-COLGROUP"
+     description = "table column group"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "dd"
+     helpref     = "struct/lists.html#edef-DD"
+     description = "definition description"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "del"
+     helpref     = "struct/text.html#edef-del"
+     description = "deleted text"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "dfn"
+     helpref     = "struct/text.html#edef-DFN"
+     description = "instance definition"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "dir"
+     helpref     = "struct/lists.html#edef-DIR"
+     description = "directory list"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "L"
+/>
+<tag name        = "div"
+     helpref     = "struct/global.html#edef-DIV"
+     description = "generic language/style container"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "dl"
+     helpref     = "struct/lists.html#edef-DL"
+     description = "definition list"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "dt"
+     helpref     = "struct/lists.html#edef-DT"
+     description = "definition term"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "em"
+     helpref     = "struct/text.html#edef-EM"
+     description = "emphasis"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "fieldset"
+     helpref     = "interact/forms.html#edef-FIELDSET"
+     description = "form control group"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "font"
+     helpref     = "present/graphics.html#edef-FONT"
+     description = "local change to font"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "L"
+/>
+<tag name        = "form"
+     helpref     = "interact/forms.html#edef-FORM"
+     description = "interactive form"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "frame"
+     helpref     = "present/frames.html#edef-FRAME"
+     description = "subwindow"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = "F"
+/>
+<tag name        = "frameset"
+     helpref     = "present/frames.html#edef-FRAMESET"
+     description = "window subdivision"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "F"
+/>
+<tag name        = "h1"
+     helpref     = "struct/global.html#edef-H1"
+     description = "heading"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "h2"
+     helpref     = "struct/global.html#edef-H2"
+     description = "heading"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "h3"
+     helpref     = "struct/global.html#edef-H3"
+     description = "heading"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "h4"
+     helpref     = "struct/global.html#edef-H4"
+     description = "heading"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "h5"
+     helpref     = "struct/global.html#edef-H5"
+     description = "heading"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "h6"
+     helpref     = "struct/global.html#edef-H6"
+     description = "heading"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "head"
+     helpref     = "struct/global.html#edef-HEAD"
+     description = "document head"
+     startTag    = "false"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "hr"
+     helpref     = "present/graphics.html#edef-HR"
+     description = "horizontal rule"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "html"
+     helpref     = "struct/global.html#edef-HTML"
+     description = "document root element"
+     startTag    = "false"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "i"
+     helpref     = "present/graphics.html#edef-I"
+     description = "italic text style"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "iframe"
+     helpref     = "present/frames.html#edef-IFRAME"
+     description = "inline subwindow"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "L"
+/>
+<tag name        = "img"
+     helpref     = "struct/objects.html#edef-IMG"
+     description = "Embedded image"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "input"
+     helpref     = "interact/forms.html#edef-INPUT"
+     description = "form control"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "ins"
+     helpref     = "struct/text.html#edef-ins"
+     description = "inserted text"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "isindex"
+     helpref     = "interact/forms.html#edef-ISINDEX"
+     description = "single line prompt"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = "L"
+/>
+<tag name        = "kbd"
+     helpref     = "struct/text.html#edef-KBD"
+     description = "text to be entered by the user"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "label"
+     helpref     = "interact/forms.html#edef-LABEL"
+     description = "form field label text"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "legend"
+     helpref     = "interact/forms.html#edef-LEGEND"
+     description = "fieldset legend"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "li"
+     helpref     = "struct/lists.html#edef-LI"
+     description = "list item"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "link"
+     helpref     = "struct/links.html#edef-LINK"
+     description = "a media-independent link"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "map"
+     helpref     = "struct/objects.html#edef-MAP"
+     description = "client-side image map"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "menu"
+     helpref     = "struct/lists.html#edef-MENU"
+     description = "menu list"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "L"
+/>
+<tag name        = "meta"
+     helpref     = "struct/global.html#edef-META"
+     description = "generic metainformation"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "noframes"
+     helpref     = "present/frames.html#edef-NOFRAMES"
+     description = "generic metainformation"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "F"
+/>
+<tag name        = "noscript"
+     helpref     = "interact/scripts.html#edef-NOSCRIPT"
+     description = "generic metainformation"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "object"
+     helpref     = "struct/objects.html#edef-OBJECT"
+     description = "generic embedded object"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "ol"
+     helpref     = "struct/lists.html#edef-OL"
+     description = "ordered list"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "optgroup"
+     helpref     = "interact/forms.html#edef-OPTGROUP"
+     description = "option group"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "option"
+     helpref     = "interact/forms.html#edef-OPTION"
+     description = "selectable choice"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "p"
+     helpref     = "struct/text.html#edef-P"
+     description = "paragraph"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "param"
+     helpref     = "struct/objects.html#edef-PARAM"
+     description = "named property value"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "pre"
+     helpref     = "struct/text.html#edef-PRE"
+     description = "preformatted text"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "q"
+     helpref     = "struct/text.html#edef-Q"
+     description = "short inline quotation"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "s"
+     helpref     = "present/graphics.html#edef-S"
+     description = "strike-through text style"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "L"
+/>
+<tag name        = "samp"
+     helpref     = "struct/text.html#edef-SAMP"
+     description = "strike-through text style"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "script"
+     helpref     = "interact/scripts.html#edef-SCRIPT"
+     description = "script statements"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "select"
+     helpref     = "interact/forms.html#edef-SELECT"
+     description = "option selector"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "small"
+     helpref     = "present/graphics.html#edef-SMALL"
+     description = "small text style"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "span"
+     helpref     = "struct/global.html#edef-SPAN"
+     description = "generic language/style container"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "strike"
+     helpref     = "present/graphics.html#edef-STRIKE"
+     description = "strike-through text"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "L"
+/>
+<tag name        = "strong"
+     helpref     = "struct/text.html#edef-STRONG"
+     description = "strong emphasis"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "style"
+     helpref     = "present/styles.html#edef-STYLE"
+     description = "style info"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "sub"
+     helpref     = "struct/text.html#edef-SUB"
+     description = "subscript"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "sup"
+     helpref     = "struct/text.html#edef-SUP"
+     description = "superscript"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "table"
+     helpref     = "struct/tables.html#edef-TABLE"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "tbody"
+     helpref     = "struct/tables.html#edef-TBODY"
+     description = "table body"
+     startTag    = "false"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "td"
+     helpref     = "struct/tables.html#edef-TD"
+     description = "table data cell"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "textarea"
+     helpref     = "interact/forms.html#edef-TEXTAREA"
+     description = "multi-line text field"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "tfoot"
+     helpref     = "struct/tables.html#edef-TFOOT"
+     description = "table footer"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "th"
+     helpref     = "struct/tables.html#edef-TH"
+     description = "table header cell"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "thead"
+     helpref     = "struct/tables.html#edef-THEAD"
+     description = "table header"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "title"
+     helpref     = "struct/global.html#edef-TITLE"
+     description = "document title"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "tr"
+     helpref     = "struct/tables.html#edef-TR"
+     description = "table row"
+     startTag    = "true"
+     endTag      = "false"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "tt"
+     helpref     = "present/graphics.html#edef-TT"
+     description = "teletype or monospaced text style"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "u"
+     helpref     = "present/graphics.html#edef-U"
+     description = "underlined text style"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = "L"
+/>
+<tag name        = "ul"
+     helpref     = "struct/lists.html#edef-UL"
+     description = "unordered list"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "var"
+     helpref     = "struct/text.html#edef-VAR"
+     description = "unordered list"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<attribute name        = "abbr"
+           helpref     = "struct/tables.html#adef-abbr"
+           description = "abbreviation for header cell"
+           relatedTags = "td,th"
+           dtd         = ""
+           type        = "Text"
+           default     = "true"
+/>
+<attribute name        = "accept-charset"
+           helpref     = "interact/forms.html#adef-accept-charset"
+           description = "list of supported charsets"
+           relatedTags = "form"
+           dtd         = ""
+           type        = "Charsets"
+           default     = "true"
+/>
+<attribute name        = "accept"
+           helpref     = "interact/forms.html#adef-accept"
+           description = "list of MIME types for file upload"
+           relatedTags = "form,input"
+           dtd         = ""
+           type        = "ContentTypes"
+           default     = "true"
+/>
+<attribute name        = "accesskey"
+           helpref     = "interact/forms.html#adef-accesskey"
+           description = "accessibility key character"
+           relatedTags = "a,area,button,input,label,legend,textarea"
+           dtd         = ""
+           type        = "Character"
+           default     = "true"
+/>
+<attribute name        = "action"
+           helpref     = "interact/forms.html#adef-action"
+           description = "server-side form handler"
+           relatedTags = "form"
+           dtd         = ""
+           type        = "URI"
+           default     = "false"
+/>
+<attribute name        = "align"
+           helpref     = "struct/tables.html#adef-align-CAPTION"
+           description = "relative to table"
+           relatedTags = "caption"
+           dtd         = "L"
+           type        = "CAlign"
+           default     = "true"
+/>
+<attribute name        = "align"
+           helpref     = "struct/objects.html#adef-align-IMG"
+           description = "vertical or horizontal alignment"
+           relatedTags = "applet,iframe,img,input,object"
+           dtd         = "L"
+           type        = "IAlign"
+           default     = "true"
+/>
+<attribute name        = "align"
+           helpref     = "interact/forms.html#adef-align-LEGEND"
+           description = "relative to fieldset"
+           relatedTags = "legend"
+           dtd         = "L"
+           type        = "LAlign"
+           default     = "true"
+/>
+<attribute name        = "align"
+           helpref     = "struct/tables.html#adef-align-TABLE"
+           description = "table position relative to window"
+           relatedTags = "table"
+           dtd         = "L"
+           type        = "TAlign"
+           default     = "true"
+/>
+<attribute name        = "align"
+           helpref     = "present/graphics.html#adef-align-HR"
+           description = ""
+           relatedTags = "hr"
+           dtd         = "L"
+           type        = "(left | center | right)"
+           default     = "true"
+/>
+<attribute name        = "align"
+           helpref     = "present/graphics.html#adef-align"
+           description = "align, text alignment"
+           relatedTags = "div,h1,h2,h3,h4,h5,h6,p"
+           dtd         = "L"
+           type        = "(left | center | right | justify)"
+           default     = "true"
+/>
+<attribute name        = "align"
+           helpref     = "struct/tables.html#adef-align-TD"
+           description = ""
+           relatedTags = "col,colgroup,tbody,td,tfoot,th,thead,tr"
+           dtd         = ""
+           type        = "(left | center | right | justify | char)"
+           default     = "true"
+/>
+<attribute name        = "alink"
+           helpref     = "struct/global.html#adef-alink"
+           description = "color of selected links"
+           relatedTags = "body"
+           dtd         = "L"
+           type        = "Color"
+           default     = "true"
+/>
+<attribute name        = "alt"
+           helpref     = "struct/objects.html#adef-alt"
+           description = "short description"
+           relatedTags = "applet"
+           dtd         = "L"
+           type        = "Text"
+           default     = "true"
+/>
+<attribute name        = "alt"
+           helpref     = "struct/objects.html#adef-alt"
+           description = "short description"
+           relatedTags = "area,img"
+           dtd         = ""
+           type        = "Text"
+           default     = "false"
+/>
+<attribute name        = "alt"
+           helpref     = "struct/objects.html#adef-alt"
+           description = "short description"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "archive"
+           helpref     = "struct/objects.html#adef-archive-APPLET"
+           description = "comma-separated archive list"
+           relatedTags = "applet"
+           dtd         = "L"
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "archive"
+           helpref     = "struct/objects.html#adef-archive-OBJECT"
+           description = "space-separated list of URIs"
+           relatedTags = "object"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "axis"
+           helpref     = "struct/tables.html#adef-axis"
+           description = "comma-separated list of related headers"
+           relatedTags = "td,th"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "background"
+           helpref     = "struct/global.html#adef-background"
+           description = "texture tile for document background"
+           relatedTags = "body"
+           dtd         = "L"
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "bgcolor"
+           helpref     = "present/graphics.html#adef-bgcolor"
+           description = "background color for cells"
+           relatedTags = "table"
+           dtd         = "L"
+           type        = "Color"
+           default     = "true"
+/>
+<attribute name        = "bgcolor"
+           helpref     = "present/graphics.html#adef-bgcolor"
+           description = "background color for row"
+           relatedTags = "tr"
+           dtd         = "L"
+           type        = "Color"
+           default     = "true"
+/>
+<attribute name        = "bgcolor"
+           helpref     = "present/graphics.html#adef-bgcolor"
+           description = "cell background color"
+           relatedTags = "td,th"
+           dtd         = "L"
+           type        = "Color"
+           default     = "true"
+/>
+<attribute name        = "bgcolor"
+           helpref     = "present/graphics.html#adef-bgcolor"
+           description = "document background color"
+           relatedTags = "body"
+           dtd         = "L"
+           type        = "Color"
+           default     = "true"
+/>
+<attribute name        = "border"
+           helpref     = "struct/tables.html#adef-border-TABLE"
+           description = "controls frame width around table"
+           relatedTags = "table"
+           dtd         = ""
+           type        = "Pixels"
+           default     = "true"
+/>
+<attribute name        = "border"
+           helpref     = "struct/objects.html#adef-border-IMG"
+           description = "link border width"
+           relatedTags = "img,object"
+           dtd         = "L"
+           type        = "Pixels"
+           default     = "true"
+/>
+<attribute name        = "cellpadding"
+           helpref     = "struct/tables.html#adef-cellpadding"
+           description = "spacing within cells"
+           relatedTags = "table"
+           dtd         = ""
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "cellspacing"
+           helpref     = "struct/tables.html#adef-cellspacing"
+           description = "spacing between cells"
+           relatedTags = "table"
+           dtd         = ""
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "char"
+           helpref     = "struct/tables.html#adef-char"
+           description = "alignment char, e.g. char=':'"
+           relatedTags = "col,colgroup,tbody,td,tfoot,th,thead,tr"
+           dtd         = ""
+           type        = "Character"
+           default     = "true"
+/>
+<attribute name        = "charoff"
+           helpref     = "struct/tables.html#adef-charoff"
+           description = "offset for alignment char"
+           relatedTags = "col,colgroup,tbody,td,tfoot,th,thead,tr"
+           dtd         = ""
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "charset"
+           helpref     = "struct/links.html#adef-charset"
+           description = "char encoding of linked resource"
+           relatedTags = "a,link,script"
+           dtd         = ""
+           type        = "Charset"
+           default     = "true"
+/>
+<attribute name        = "checked"
+           helpref     = "interact/forms.html#adef-checked"
+           description = "for radio buttons and check boxes"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "(checked)"
+           default     = "true"
+/>
+<attribute name        = "cite"
+           helpref     = "struct/text.html#adef-cite-Q"
+           description = "URI for source document or msg"
+           relatedTags = "blockquote,q"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "cite"
+           helpref     = "struct/text.html#adef-cite-INS"
+           description = "info on reason for change"
+           relatedTags = "del,ins"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "class"
+           helpref     = "struct/global.html#adef-class"
+           description = "space-separated list of classes"
+           relatedTags = "!,base,basefont,head,html,meta,param,script,style,title"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "classid"
+           helpref     = "struct/objects.html#adef-classid"
+           description = "identifies an implementation"
+           relatedTags = "object"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "clear"
+           helpref     = "present/graphics.html#adef-clear"
+           description = "control of text flow"
+           relatedTags = "br"
+           dtd         = "L"
+           type        = "(left | all | right | none)"
+           default     = "true"
+/>
+<attribute name        = "code"
+           helpref     = "struct/objects.html#adef-code"
+           description = "applet class file"
+           relatedTags = "applet"
+           dtd         = "L"
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "codebase"
+           helpref     = "struct/objects.html#adef-codebase-OBJECT"
+           description = "base URI for classid, data, archive"
+           relatedTags = "object"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "codebase"
+           helpref     = "struct/objects.html#adef-codebase-APPLET"
+           description = "optional base URI for applet"
+           relatedTags = "applet"
+           dtd         = "L"
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "codetype"
+           helpref     = "struct/objects.html#adef-codetype"
+           description = "content type for code"
+           relatedTags = "object"
+           dtd         = ""
+           type        = "ContentType"
+           default     = "true"
+/>
+<attribute name        = "color"
+           helpref     = "present/graphics.html#adef-color-FONT"
+           description = "text color"
+           relatedTags = "basefont,font"
+           dtd         = "L"
+           type        = "Color"
+           default     = "true"
+/>
+<attribute name        = "cols"
+           helpref     = "present/frames.html#adef-cols-FRAMESET"
+           description = "list of lengths, default: 100% (1 col)"
+           relatedTags = "frameset"
+           dtd         = "F"
+           type        = "MultiLengths"
+           default     = "true"
+/>
+<attribute name        = "cols"
+           helpref     = "interact/forms.html#adef-cols-TEXTAREA"
+           description = ""
+           relatedTags = "textarea"
+           dtd         = ""
+           type        = "NUMBER"
+           default     = "false"
+/>
+<attribute name        = "colspan"
+           helpref     = "struct/tables.html#adef-colspan"
+           description = "number of cols spanned by cell"
+           relatedTags = "td,th"
+           dtd         = ""
+           type        = "NUMBER"
+           default     = "true"
+/>
+<attribute name        = "compact"
+           helpref     = "struct/lists.html#adef-compact"
+           description = "reduced interitem spacing"
+           relatedTags = "dir,dl,menu,ol,ul"
+           dtd         = "L"
+           type        = "(compact)"
+           default     = "true"
+/>
+<attribute name        = "content"
+           helpref     = "struct/global.html#adef-content"
+           description = "associated information"
+           relatedTags = "meta"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "false"
+/>
+<attribute name        = "coords"
+           helpref     = "struct/objects.html#adef-coords"
+           description = "comma-separated list of lengths"
+           relatedTags = "area"
+           dtd         = ""
+           type        = "Coords"
+           default     = "true"
+/>
+<attribute name        = "coords"
+           helpref     = "struct/objects.html#adef-coords"
+           description = "for use with client-side image maps"
+           relatedTags = "a"
+           dtd         = ""
+           type        = "Coords"
+           default     = "true"
+/>
+<attribute name        = "data"
+           helpref     = "struct/objects.html#adef-data"
+           description = "reference to object's data"
+           relatedTags = "object"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "datetime"
+           helpref     = "struct/text.html#adef-datetime"
+           description = "date and time of change"
+           relatedTags = "del,ins"
+           dtd         = ""
+           type        = "Datetime"
+           default     = "true"
+/>
+<attribute name        = "declare"
+           helpref     = "struct/objects.html#adef-declare"
+           description = "declare but don't instantiate flag"
+           relatedTags = "object"
+           dtd         = ""
+           type        = "(declare)"
+           default     = "true"
+/>
+<attribute name        = "defer"
+           helpref     = "interact/scripts.html#adef-defer"
+           description = "UA may defer execution of script"
+           relatedTags = "script"
+           dtd         = ""
+           type        = "(defer)"
+           default     = "true"
+/>
+<attribute name        = "dir"
+           helpref     = "struct/dirlang.html#adef-dir"
+           description = "direction for weak/neutral text"
+           relatedTags = "!,applet,base,basefont,bdo,br,frame,frameset,iframe,param,script"
+           dtd         = ""
+           type        = "(ltr | rtl)"
+           default     = "true"
+/>
+<attribute name        = "dir"
+           helpref     = "struct/dirlang.html#adef-dir-BDO"
+           description = "directionality"
+           relatedTags = "bdo"
+           dtd         = ""
+           type        = "(ltr | rtl)"
+           default     = "false"
+/>
+<attribute name        = "disabled"
+           helpref     = "interact/forms.html#adef-disabled"
+           description = "unavailable in this context"
+           relatedTags = "button,input,optgroup,option,select,textarea"
+           dtd         = ""
+           type        = "(disabled)"
+           default     = "true"
+/>
+<attribute name        = "enctype"
+           helpref     = "interact/forms.html#adef-enctype"
+           description = ""
+           relatedTags = "form"
+           dtd         = ""
+           type        = "ContentType"
+           default     = "true"
+/>
+<attribute name        = "face"
+           helpref     = "present/graphics.html#adef-face-FONT"
+           description = "comma-separated list of font names"
+           relatedTags = "basefont,font"
+           dtd         = "L"
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "for"
+           helpref     = "interact/forms.html#adef-for"
+           description = "matches field ID value"
+           relatedTags = "label"
+           dtd         = ""
+           type        = "IDREF"
+           default     = "true"
+/>
+<attribute name        = "frame"
+           helpref     = "struct/tables.html#adef-frame"
+           description = "which parts of frame to render"
+           relatedTags = "table"
+           dtd         = ""
+           type        = "TFrame"
+           default     = "true"
+/>
+<attribute name        = "frameborder"
+           helpref     = "present/frames.html#adef-frameborder"
+           description = "request frame borders?"
+           relatedTags = "frame,iframe"
+           dtd         = "F"
+           type        = "(1 | 0)"
+           default     = "true"
+/>
+<attribute name        = "headers"
+           helpref     = "struct/tables.html#adef-headers"
+           description = "list of id's for header cells"
+           relatedTags = "td,th"
+           dtd         = ""
+           type        = "IDREFS"
+           default     = "true"
+/>
+<attribute name        = "height"
+           helpref     = "present/frames.html#adef-height-IFRAME"
+           description = "frame height"
+           relatedTags = "iframe"
+           dtd         = "L"
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "height"
+           helpref     = "struct/tables.html#adef-height-TH"
+           description = "height for cell"
+           relatedTags = "td,th"
+           dtd         = "L"
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "height"
+           helpref     = "struct/objects.html#adef-height-IMG"
+           description = "override height"
+           relatedTags = "img,object"
+           dtd         = ""
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "height"
+           helpref     = "struct/objects.html#adef-height-APPLET"
+           description = "initial height"
+           relatedTags = "applet"
+           dtd         = "L"
+           type        = "Length"
+           default     = "false"
+/>
+<attribute name        = "href"
+           helpref     = "struct/links.html#adef-href"
+           description = "URI for linked resource"
+           relatedTags = "a,area,link"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "href"
+           helpref     = "struct/links.html#adef-href-BASE"
+           description = "URI that acts as base URI"
+           relatedTags = "base"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "hreflang"
+           helpref     = "struct/links.html#adef-hreflang"
+           description = "language code"
+           relatedTags = "a,link"
+           dtd         = ""
+           type        = "LanguageCode"
+           default     = "true"
+/>
+<attribute name        = "hspace"
+           helpref     = "struct/objects.html#adef-hspace"
+           description = "horizontal gutter"
+           relatedTags = "applet,img,object"
+           dtd         = "L"
+           type        = "Pixels"
+           default     = "true"
+/>
+<attribute name        = "http-equiv"
+           helpref     = "struct/global.html#adef-http-equiv"
+           description = "HTTP response header name"
+           relatedTags = "meta"
+           dtd         = ""
+           type        = "NAME"
+           default     = "true"
+/>
+<attribute name        = "id"
+           helpref     = "struct/global.html#adef-id"
+           description = "document-wide unique id"
+           relatedTags = "!,base,head,html,meta,script,style,title"
+           dtd         = ""
+           type        = "ID"
+           default     = "true"
+/>
+<attribute name        = "ismap"
+           helpref     = "struct/objects.html#adef-ismap"
+           description = "use server-side image map"
+           relatedTags = "img,input"
+           dtd         = ""
+           type        = "(ismap)"
+           default     = "true"
+/>
+<attribute name        = "label"
+           helpref     = "interact/forms.html#adef-label-OPTION"
+           description = "for use in hierarchical menus"
+           relatedTags = "option"
+           dtd         = ""
+           type        = "Text"
+           default     = "true"
+/>
+<attribute name        = "label"
+           helpref     = "interact/forms.html#adef-label-OPTGROUP"
+           description = "for use in hierarchical menus"
+           relatedTags = "optgroup"
+           dtd         = ""
+           type        = "Text"
+           default     = "false"
+/>
+<attribute name        = "lang"
+           helpref     = "struct/dirlang.html#adef-lang"
+           description = "language code"
+           relatedTags = "!,applet,base,basefont,br,frame,frameset,iframe,param,script"
+           dtd         = ""
+           type        = "LanguageCode"
+           default     = "true"
+/>
+<attribute name        = "language"
+           helpref     = "interact/scripts.html#adef-language"
+           description = "predefined script language name"
+           relatedTags = "script"
+           dtd         = "L"
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "link"
+           helpref     = "struct/global.html#adef-link"
+           description = "color of links"
+           relatedTags = "body"
+           dtd         = "L"
+           type        = "Color"
+           default     = "true"
+/>
+<attribute name        = "longdesc"
+           helpref     = "struct/objects.html#adef-longdesc-IMG"
+           description = "color of links"
+           relatedTags = "img"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "longdesc"
+           helpref     = "present/frames.html#adef-longdesc-FRAME"
+           description = "color of links"
+           relatedTags = "frame,iframe"
+           dtd         = "F"
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "marginheight"
+           helpref     = "present/frames.html#adef-marginheight"
+           description = "margin height in pixels"
+           relatedTags = "frame,iframe"
+           dtd         = "F"
+           type        = "Pixels"
+           default     = "true"
+/>
+<attribute name        = "marginwidth"
+           helpref     = "present/frames.html#adef-marginwidth"
+           description = "margin widths in pixels"
+           relatedTags = "frame,iframe"
+           dtd         = "F"
+           type        = "Pixels"
+           default     = "true"
+/>
+<attribute name        = "maxlength"
+           helpref     = "interact/forms.html#adef-maxlength"
+           description = "max chars for text fields"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "NUMBER"
+           default     = "true"
+/>
+<attribute name        = "media"
+           helpref     = "present/styles.html#adef-media"
+           description = "designed for use with these media"
+           relatedTags = "style"
+           dtd         = ""
+           type        = "MediaDesc"
+           default     = "true"
+/>
+<attribute name        = "media"
+           helpref     = "present/styles.html#adef-media"
+           description = "for rendering on these media"
+           relatedTags = "link"
+           dtd         = ""
+           type        = "MediaDesc"
+           default     = "true"
+/>
+<attribute name        = "method"
+           helpref     = "interact/forms.html#adef-method"
+           description = "HTTP method used to submit the form"
+           relatedTags = "form"
+           dtd         = ""
+           type        = "(GET | POST)"
+           default     = "true"
+/>
+<attribute name        = "multiple"
+           helpref     = "interact/forms.html#adef-multiple"
+           description = "default is single selection"
+           relatedTags = "select"
+           dtd         = ""
+           type        = "(multiple)"
+           default     = "true"
+/>
+<attribute name        = "name"
+           helpref     = "interact/forms.html#adef-name-BUTTON"
+           description = ""
+           relatedTags = "button,textarea"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "name"
+           helpref     = "struct/objects.html#adef-name-APPLET"
+           description = "allows applets to find each other"
+           relatedTags = "applet"
+           dtd         = "L"
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "name"
+           helpref     = "interact/forms.html#adef-name-SELECT"
+           description = "field name"
+           relatedTags = "select"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "name"
+           helpref     = "interact/forms.html#adef-name-FORM"
+           description = "name of form for scripting"
+           relatedTags = "form"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "name"
+           helpref     = "present/frames.html#adef-name-FRAME"
+           description = "name of frame for targetting"
+           relatedTags = "frame,iframe"
+           dtd         = "F"
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "name"
+           helpref     = "struct/objects.html#adef-name-IMG"
+           description = "name of image for scripting"
+           relatedTags = "img"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "name"
+           helpref     = "struct/links.html#adef-name-A"
+           description = "named link end"
+           relatedTags = "a"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "name"
+           helpref     = "interact/forms.html#adef-name-INPUT"
+           description = "submit as part of form"
+           relatedTags = "input,object"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "name"
+           helpref     = "struct/objects.html#adef-name-MAP"
+           description = "for reference by usemap"
+           relatedTags = "map"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "false"
+/>
+<attribute name        = "name"
+           helpref     = "struct/objects.html#adef-name-PARAM"
+           description = "property name"
+           relatedTags = "param"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "false"
+/>
+<attribute name        = "name"
+           helpref     = "struct/global.html#adef-name-META"
+           description = "metainformation name"
+           relatedTags = "meta"
+           dtd         = ""
+           type        = "NAME"
+           default     = "true"
+/>
+<attribute name        = "nohref"
+           helpref     = "struct/objects.html#adef-nohref"
+           description = "this region has no action"
+           relatedTags = "area"
+           dtd         = ""
+           type        = "(nohref)"
+           default     = "true"
+/>
+<attribute name        = "noresize"
+           helpref     = "present/frames.html#adef-noresize"
+           description = "allow users to resize frames?"
+           relatedTags = "frame"
+           dtd         = "F"
+           type        = "(noresize)"
+           default     = "true"
+/>
+<attribute name        = "noshade"
+           helpref     = "present/graphics.html#adef-noshade"
+           description = ""
+           relatedTags = "hr"
+           dtd         = "L"
+           type        = "(noshade)"
+           default     = "true"
+/>
+<attribute name        = "nowrap"
+           helpref     = "struct/tables.html#adef-nowrap"
+           description = "suppress word wrap"
+           relatedTags = "td,th"
+           dtd         = "L"
+           type        = "(nowrap)"
+           default     = "true"
+/>
+<attribute name        = "object"
+           helpref     = "struct/objects.html#adef-object"
+           description = "serialized applet file"
+           relatedTags = "applet"
+           dtd         = "L"
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "onblur"
+           helpref     = "interact/scripts.html#adef-onblur"
+           description = "the element lost the focus"
+           relatedTags = "a,area,button,input,label,select,textarea"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onchange"
+           helpref     = "interact/scripts.html#adef-onchange"
+           description = "the element value was changed"
+           relatedTags = "input,select,textarea"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onclick"
+           helpref     = "interact/scripts.html#adef-onclick"
+           description = "a pointer button was clicked"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "ondblclick"
+           helpref     = "interact/scripts.html#adef-ondblclick"
+           description = "a pointer button was double clicked"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onfocus"
+           helpref     = "interact/scripts.html#adef-onfocus"
+           description = "the element got the focus"
+           relatedTags = "a,area,button,input,label,select,textarea"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onkeydown"
+           helpref     = "interact/scripts.html#adef-onkeydown"
+           description = "a key was pressed down"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onkeypress"
+           helpref     = "interact/scripts.html#adef-onkeypress"
+           description = "a key was pressed and released"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onkeyup"
+           helpref     = "interact/scripts.html#adef-onkeyup"
+           description = "a key was released"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onload"
+           helpref     = "interact/scripts.html#adef-onload"
+           description = "all the frames have been loaded"
+           relatedTags = "frameset"
+           dtd         = "F"
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onload"
+           helpref     = "interact/scripts.html#adef-onload"
+           description = "the document has been loaded"
+           relatedTags = "body"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onmousedown"
+           helpref     = "interact/scripts.html#adef-onmousedown"
+           description = "a pointer button was pressed down"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onmousemove"
+           helpref     = "interact/scripts.html#adef-onmousemove"
+           description = "a pointer was moved within"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onmouseout"
+           helpref     = "interact/scripts.html#adef-onmouseout"
+           description = "a pointer was moved away"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onmouseover"
+           helpref     = "interact/scripts.html#adef-onmouseover"
+           description = "a pointer was moved onto"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onmouseup"
+           helpref     = "interact/scripts.html#adef-onmouseup"
+           description = "a pointer button was released"
+           relatedTags = "!,applet,base,basefont,bdo,br,font,frame,frameset,head,html,iframe,isindex,meta,param,script,style,title"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onreset"
+           helpref     = "interact/scripts.html#adef-onreset"
+           description = "the form was reset"
+           relatedTags = "form"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onselect"
+           helpref     = "interact/scripts.html#adef-onselect"
+           description = "some text was selected"
+           relatedTags = "input,textarea"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onsubmit"
+           helpref     = "interact/scripts.html#adef-onsubmit"
+           description = "the form was submitted"
+           relatedTags = "form"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onunload"
+           helpref     = "interact/scripts.html#adef-onunload"
+           description = "all the frames have been removed"
+           relatedTags = "frameset"
+           dtd         = "F"
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "onunload"
+           helpref     = "interact/scripts.html#adef-onunload"
+           description = "the document has been removed"
+           relatedTags = "body"
+           dtd         = ""
+           type        = "Script"
+           default     = "true"
+/>
+<attribute name        = "profile"
+           helpref     = "struct/global.html#adef-profile"
+           description = "named dictionary of meta info"
+           relatedTags = "head"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "prompt"
+           helpref     = "interact/forms.html#adef-prompt"
+           description = "prompt message"
+           relatedTags = "isindex"
+           dtd         = "L"
+           type        = "Text"
+           default     = "true"
+/>
+<attribute name        = "readonly"
+           helpref     = "interact/forms.html#adef-readonly"
+           description = ""
+           relatedTags = "textarea"
+           dtd         = ""
+           type        = "(readonly)"
+           default     = "true"
+/>
+<attribute name        = "readonly"
+           helpref     = "interact/forms.html#adef-readonly"
+           description = "for text and passwd"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "(readonly)"
+           default     = "true"
+/>
+<attribute name        = "rel"
+           helpref     = "struct/links.html#adef-rel"
+           description = "forward link types"
+           relatedTags = "a,link"
+           dtd         = ""
+           type        = "LinkTypes"
+           default     = "true"
+/>
+<attribute name        = "rev"
+           helpref     = "struct/links.html#adef-rev"
+           description = "reverse link types"
+           relatedTags = "a,link"
+           dtd         = ""
+           type        = "LinkTypes"
+           default     = "true"
+/>
+<attribute name        = "rows"
+           helpref     = "present/frames.html#adef-rows-FRAMESET"
+           description = "list of lengths, default: 100% (1 row)"
+           relatedTags = "frameset"
+           dtd         = "F"
+           type        = "MultiLengths"
+           default     = "true"
+/>
+<attribute name        = "rows"
+           helpref     = "interact/forms.html#adef-rows-TEXTAREA"
+           description = ""
+           relatedTags = "textarea"
+           dtd         = ""
+           type        = "NUMBER"
+           default     = "false"
+/>
+<attribute name        = "rowspan"
+           helpref     = "struct/tables.html#adef-rowspan"
+           description = "number of rows spanned by cell"
+           relatedTags = "td,th"
+           dtd         = ""
+           type        = "NUMBER"
+           default     = "true"
+/>
+<attribute name        = "rules"
+           helpref     = "struct/tables.html#adef-rules"
+           description = "rulings between rows and cols"
+           relatedTags = "table"
+           dtd         = ""
+           type        = "TRules"
+           default     = "true"
+/>
+<attribute name        = "scheme"
+           helpref     = "struct/global.html#adef-scheme"
+           description = "select form of content"
+           relatedTags = "meta"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "scope"
+           helpref     = "struct/tables.html#adef-scope"
+           description = "scope covered by header cells"
+           relatedTags = "td,th"
+           dtd         = ""
+           type        = "Scope"
+           default     = "true"
+/>
+<attribute name        = "scrolling"
+           helpref     = "present/frames.html#adef-scrolling"
+           description = "scrollbar or none"
+           relatedTags = "frame,iframe"
+           dtd         = "F"
+           type        = "(yes | no | auto)"
+           default     = "true"
+/>
+<attribute name        = "selected"
+           helpref     = "interact/forms.html#adef-selected"
+           description = ""
+           relatedTags = "option"
+           dtd         = ""
+           type        = "(selected)"
+           default     = "true"
+/>
+<attribute name        = "shape"
+           helpref     = "struct/objects.html#adef-shape"
+           description = "controls interpretation of coords"
+           relatedTags = "area"
+           dtd         = ""
+           type        = "Shape"
+           default     = "true"
+/>
+<attribute name        = "shape"
+           helpref     = "struct/objects.html#adef-shape"
+           description = "for use with client-side image maps"
+           relatedTags = "a"
+           dtd         = ""
+           type        = "Shape"
+           default     = "true"
+/>
+<attribute name        = "size"
+           helpref     = "present/graphics.html#adef-size-HR"
+           description = ""
+           relatedTags = "hr"
+           dtd         = "L"
+           type        = "Pixels"
+           default     = "true"
+/>
+<attribute name        = "size"
+           helpref     = "present/graphics.html#adef-size-FONT"
+           description = "[+|-]nn e.g. size=&quot;+1&quot;, size=&quot;4&quot;"
+           relatedTags = "font"
+           dtd         = "L"
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "size"
+           helpref     = "interact/forms.html#adef-size-INPUT"
+           description = "specific to each type of field"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "size"
+           helpref     = "present/graphics.html#adef-size-BASEFONT"
+           description = "base font size for FONT elements"
+           relatedTags = "basefont"
+           dtd         = "L"
+           type        = "CDATA"
+           default     = "false"
+/>
+<attribute name        = "size"
+           helpref     = "interact/forms.html#adef-size-SELECT"
+           description = "rows visible"
+           relatedTags = "select"
+           dtd         = ""
+           type        = "NUMBER"
+           default     = "true"
+/>
+<attribute name        = "span"
+           helpref     = "struct/tables.html#adef-span-COL"
+           description = "COL attributes affect N columns"
+           relatedTags = "col"
+           dtd         = ""
+           type        = "NUMBER"
+           default     = "true"
+/>
+<attribute name        = "span"
+           helpref     = "struct/tables.html#adef-span-COLGROUP"
+           description = "default number of columns in group"
+           relatedTags = "colgroup"
+           dtd         = ""
+           type        = "NUMBER"
+           default     = "true"
+/>
+<attribute name        = "src"
+           helpref     = "interact/scripts.html#adef-src-SCRIPT"
+           description = "URI for an external script"
+           relatedTags = "script"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "src"
+           helpref     = "interact/forms.html#adef-src"
+           description = "for fields with images"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "src"
+           helpref     = "present/frames.html#adef-src-FRAME"
+           description = "source of frame content"
+           relatedTags = "frame,iframe"
+           dtd         = "F"
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "src"
+           helpref     = "struct/objects.html#adef-src-IMG"
+           description = "URI of image to embed"
+           relatedTags = "img"
+           dtd         = ""
+           type        = "URI"
+           default     = "false"
+/>
+<attribute name        = "standby"
+           helpref     = "struct/objects.html#adef-standby"
+           description = "message to show while loading"
+           relatedTags = "object"
+           dtd         = ""
+           type        = "Text"
+           default     = "true"
+/>
+<attribute name        = "start"
+           helpref     = "struct/lists.html#adef-start"
+           description = "starting sequence number"
+           relatedTags = "ol"
+           dtd         = "L"
+           type        = "NUMBER"
+           default     = "true"
+/>
+<attribute name        = "style"
+           helpref     = "present/styles.html#adef-style"
+           description = "associated style info"
+           relatedTags = "!,base,basefont,head,html,meta,param,script,style,title"
+           dtd         = ""
+           type        = "StyleSheet"
+           default     = "true"
+/>
+<attribute name        = "summary"
+           helpref     = "struct/tables.html#adef-summary"
+           description = "purpose/structure for speech output"
+           relatedTags = "table"
+           dtd         = ""
+           type        = "Text"
+           default     = "true"
+/>
+<attribute name        = "tabindex"
+           helpref     = "interact/forms.html#adef-tabindex"
+           description = "position in tabbing order"
+           relatedTags = "a,area,button,input,object,select,textarea"
+           dtd         = ""
+           type        = "NUMBER"
+           default     = "true"
+/>
+<attribute name        = "target"
+           helpref     = "present/frames.html#adef-target"
+           description = "render in this frame"
+           relatedTags = "a,area,base,form,link"
+           dtd         = "L"
+           type        = "FrameTarget"
+           default     = "true"
+/>
+<attribute name        = "text"
+           helpref     = "struct/global.html#adef-text"
+           description = "document text color"
+           relatedTags = "body"
+           dtd         = "L"
+           type        = "Color"
+           default     = "true"
+/>
+<attribute name        = "title"
+           helpref     = "struct/global.html#adef-title"
+           description = "advisory title"
+           relatedTags = "!,base,basefont,head,html,meta,param,script,title"
+           dtd         = ""
+           type        = "Text"
+           default     = "true"
+/>
+<attribute name        = "type"
+           helpref     = "struct/links.html#adef-type-A"
+           description = "advisory content type"
+           relatedTags = "a,link"
+           dtd         = ""
+           type        = "ContentType"
+           default     = "true"
+/>
+<attribute name        = "type"
+           helpref     = "struct/objects.html#adef-type-OBJECT"
+           description = "content type for data"
+           relatedTags = "object"
+           dtd         = ""
+           type        = "ContentType"
+           default     = "true"
+/>
+<attribute name        = "type"
+           helpref     = "struct/objects.html#adef-type-PARAM"
+           description = "content type for data"
+           relatedTags = "param"
+           dtd         = ""
+           type        = "ContentType"
+           default     = "true"
+/>
+<attribute name        = "type"
+           helpref     = "interact/scripts.html#adef-type-SCRIPT"
+           description = "content type of script language"
+           relatedTags = "script"
+           dtd         = ""
+           type        = "ContentType"
+           default     = "false"
+/>
+<attribute name        = "type"
+           helpref     = "present/styles.html#adef-type-STYLE"
+           description = "content type of style language"
+           relatedTags = "style"
+           dtd         = ""
+           type        = "ContentType"
+           default     = "false"
+/>
+<attribute name        = "type"
+           helpref     = "interact/forms.html#adef-type-INPUT"
+           description = "what kind of widget is needed"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "InputType"
+           default     = "true"
+/>
+<attribute name        = "type"
+           helpref     = "struct/lists.html#adef-type-LI"
+           description = "list item style"
+           relatedTags = "li"
+           dtd         = "L"
+           type        = "LIStyle"
+           default     = "true"
+/>
+<attribute name        = "type"
+           helpref     = "struct/lists.html#adef-type-OL"
+           description = "numbering style"
+           relatedTags = "ol"
+           dtd         = "L"
+           type        = "OLStyle"
+           default     = "true"
+/>
+<attribute name        = "type"
+           helpref     = "struct/lists.html#adef-type-UL"
+           description = "bullet style"
+           relatedTags = "ul"
+           dtd         = "L"
+           type        = "ULStyle"
+           default     = "true"
+/>
+<attribute name        = "type"
+           helpref     = "interact/forms.html#adef-type-BUTTON"
+           description = "for use as form button"
+           relatedTags = "button"
+           dtd         = ""
+           type        = "(button | submit | reset)"
+           default     = "true"
+/>
+<attribute name        = "usemap"
+           helpref     = "struct/objects.html#adef-usemap"
+           description = "use client-side image map"
+           relatedTags = "img,input,object"
+           dtd         = ""
+           type        = "URI"
+           default     = "true"
+/>
+<attribute name        = "valign"
+           helpref     = "struct/tables.html#adef-valign"
+           description = "vertical alignment in cells"
+           relatedTags = "col,colgroup,tbody,td,tfoot,th,thead,tr"
+           dtd         = ""
+           type        = "(top | middle | bottom | baseline)"
+           default     = "true"
+/>
+<attribute name        = "value"
+           helpref     = "interact/forms.html#adef-value-INPUT"
+           description = "vertical alignment in cells"
+           relatedTags = "input"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "value"
+           helpref     = "interact/forms.html#adef-value-OPTION"
+           description = "defaults to element content"
+           relatedTags = "option"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "value"
+           helpref     = "struct/objects.html#adef-value-PARAM"
+           description = "property value"
+           relatedTags = "param"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "value"
+           helpref     = "interact/forms.html#adef-value-BUTTON"
+           description = "sent to server when submitted"
+           relatedTags = "button"
+           dtd         = ""
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "value"
+           helpref     = "struct/lists.html#adef-value-LI"
+           description = "reset sequence number"
+           relatedTags = "li"
+           dtd         = "L"
+           type        = "NUMBER"
+           default     = "true"
+/>
+<attribute name        = "valuetype"
+           helpref     = "struct/objects.html#adef-valuetype"
+           description = "How to interpret value"
+           relatedTags = "param"
+           dtd         = ""
+           type        = "(DATA | REF | OBJECT)"
+           default     = "true"
+/>
+<attribute name        = "version"
+           helpref     = "struct/global.html#adef-version"
+           description = "Constant"
+           relatedTags = "html"
+           dtd         = "L"
+           type        = "CDATA"
+           default     = "true"
+/>
+<attribute name        = "vlink"
+           helpref     = "struct/global.html#adef-vlink"
+           description = "color of visited links"
+           relatedTags = "body"
+           dtd         = "L"
+           type        = "Color"
+           default     = "true"
+/>
+<attribute name        = "vspace"
+           helpref     = "struct/objects.html#adef-vspace"
+           description = "vertical gutter"
+           relatedTags = "applet,img,object"
+           dtd         = "L"
+           type        = "Pixels"
+           default     = "true"
+/>
+<attribute name        = "width"
+           helpref     = "present/graphics.html#adef-width-HR"
+           description = ""
+           relatedTags = "hr"
+           dtd         = "L"
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "width"
+           helpref     = "present/frames.html#adef-width-IFRAME"
+           description = "frame width"
+           relatedTags = "iframe"
+           dtd         = "L"
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "width"
+           helpref     = "struct/objects.html#adef-width-IMG"
+           description = "override width"
+           relatedTags = "img,object"
+           dtd         = ""
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "width"
+           helpref     = "struct/tables.html#adef-width-TABLE"
+           description = "table width"
+           relatedTags = "table"
+           dtd         = ""
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "width"
+           helpref     = "struct/tables.html#adef-width-TH"
+           description = "width for cell"
+           relatedTags = "td,th"
+           dtd         = "L"
+           type        = "Length"
+           default     = "true"
+/>
+<attribute name        = "width"
+           helpref     = "struct/objects.html#adef-width-APPLET"
+           description = "initial width"
+           relatedTags = "applet"
+           dtd         = "L"
+           type        = "Length"
+           default     = "false"
+/>
+<attribute name        = "width"
+           helpref     = "struct/tables.html#adef-width-COL"
+           description = "column width specification"
+           relatedTags = "col"
+           dtd         = ""
+           type        = "MultiLength"
+           default     = "true"
+/>
+<attribute name        = "width"
+           helpref     = "struct/tables.html#adef-width-COLGROUP"
+           description = "default width for enclosed COLs"
+           relatedTags = "colgroup"
+           dtd         = ""
+           type        = "MultiLength"
+           default     = "true"
+/>
+<attribute name        = "width"
+           helpref     = "struct/text.html#adef-width-PRE"
+           description = ""
+           relatedTags = "pre"
+           dtd         = "L"
+           type        = "NUMBER"
+           default     = "true"
+/>
+</html-property-table>
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/mathmltable.xml b/xml/impl/src/com/intellij/xml/util/documentation/mathmltable.xml
new file mode 100644
index 0000000..6e659cc
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/mathmltable.xml
@@ -0,0 +1,210 @@
+<html-property-table baseHelpRef="http://www.w3.org/TR/mathml-for-css/">
+<tag name        = "mi"
+     helpref     = "#mi"
+     description = "represents a mathematical identifier; its rendering consists of the text content displayed in a typeface corresponding to the mathvariant attribute"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mn"
+     helpref     = "#mn"
+     description = "represents a numeric literal or other data that should be rendered as a numeric literal"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mo"
+     helpref     = "#mo"
+     description = "represents an operator or anything that should be rendered as an operator"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mtext"
+     helpref     = "#mtext"
+     description = "intended to denote commentary text"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mspace"
+     helpref     = "#mspace"
+     description = "represents a blank space of any desired size, as set by its attributes"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "true"
+     dtd         = ""
+/>
+<tag name        = "ms"
+     helpref     = "#ms"
+     description = "used to represent string literals in expressions meant to be interpreted by computer algebra systems or other systems containing programming languages"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mfrac"
+     helpref     = "#mfrac"
+     description = "used for fractions"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "msqrt"
+     helpref     = "#msqrt"
+     description = "used for square roots"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mroot"
+     helpref     = "#mroot"
+     description = "used to draw radicals with indices"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "merror"
+     helpref     = "#merror"
+     description = "displays its contents as an error message"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mphantom"
+     helpref     = "#mphantom"
+     description = "renders its content as invisible, but with the same size and other dimensions, including baseline position, that its contents would have if they were rendered normally"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mfenced"
+     helpref     = "#mfenced"
+     description = "provides a convenient way of expressing common constructs involving fences (i.e., braces, brackets, and parentheses)"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "menclose"
+     helpref     = "#menclose"
+     description = "renders its content inside the enclosing notation specified by its notation attribute, menclose accepts any number of arguments"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "msup"
+     helpref     = "#msup"
+     description = "used to attach a superscript to a base"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "msubsup"
+     helpref     = "#msubsup"
+     description = "used to attach both a subscript and a superscript to a base expression"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "munder"
+     helpref     = "#munder"
+     description = "used to attach an underscript below a base"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mover"
+     helpref     = "#mover"
+     description = "used to attach an overscript over a base"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "munderover"
+     helpref     = "#munderover"
+     description = "used to attach both an underscript and an overscript to a base"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mmultiscripts"
+     helpref     = "#mmultiscripts"
+     description = "allows adding pairs of prescripts to one base expression"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mtable"
+     helpref     = "#mtable"
+     description = "a matrix or table is specified using the mtable element"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mtr"
+     helpref     = "#mtr"
+     description = "represents one row in a table or matrix"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mtd"
+     helpref     = "#mtd"
+     description = "represents one entry, or cell, in a table or matrix"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mrow"
+     helpref     = "#mrow"
+     description = "used to add operator before last operand in elementary math notations such as 2D addition, subtraction and multiplication"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mlongdiv"
+     helpref     = "#mlongdiv"
+     description = "elementary math notations for long division can be produced using mlongdiv layout schemata"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "maction"
+     helpref     = "#maction"
+     description = "to provide a mechanism for binding actions to expressions, MathML provides the maction element"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "semantics"
+     helpref     = "#semantics"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+</html-property-table>
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/svgtable.xml b/xml/impl/src/com/intellij/xml/util/documentation/svgtable.xml
new file mode 100644
index 0000000..414169b
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/svgtable.xml
@@ -0,0 +1,531 @@
+<html-property-table baseHelpRef="http://www.w3.org/TR/SVG/">
+<tag name        = "altGlyph"
+     helpref     = "text.html#AltGlyphElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "altGlyphDef"
+     helpref     = "text.html#AltGlyphDefElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "altGlyphItem"
+     helpref     = "text.html#AltGlyphItemElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "animate"
+     helpref     = "animate.html#AnimateElement"
+     description = "heading"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "animateColor"
+     helpref     = "text.html#AnimateColorElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "animateMotion"
+     helpref     = "text.html#AnimateMotionElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "animateTransform"
+     helpref     = "text.html#AnimateTransformElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "circle"
+     helpref     = "shapes.html#CircleElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "clipPath"
+     helpref     = "masking.html#ClipPathElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "color-profile"
+     helpref     = "color.html#ColorProfileElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "cursor"
+     helpref     = "interact.html#CursorElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "defs"
+     helpref     = "struct.html#DefsElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "desc"
+     helpref     = "struct.html#DescElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "ellipse"
+     helpref     = "shapes.html#EllipseElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feBlend"
+     helpref     = "filters.html#feBlendElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feColorMatrix"
+     helpref     = "filters.html#feColorMatrixElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feComponentTransfer"
+     helpref     = "filters.html#feComponentTransferElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feComposite"
+     helpref     = "filters.html#feCompositeElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feConvolveMatrix"
+     helpref     = "filters.html#feConvolveMatrixElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feDiffuseLightingElement"
+     helpref     = "filters.html#feDiffuseLightingElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feDisplacementMapElement"
+     helpref     = "filters.html#feDisplacementMapElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feDistantLight"
+     helpref     = "filters.html#feDistantLightElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feFlood"
+     helpref     = "filters.html#feFloodElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feFuncA"
+     helpref     = "filters.html#feFuncAElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feFuncB"
+     helpref     = "filters.html#feFuncBElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feFuncG"
+     helpref     = "filters.html#feFuncGElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feFuncR"
+     helpref     = "filters.html#feFuncRElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feGaussianBlur"
+     helpref     = "filters.html#feGaussianBlurElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feImage"
+     helpref     = "filters.html#feImageElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feMerge"
+     helpref     = "filters.html#feMergeElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feMergeNode"
+     helpref     = "filters.html#feMergeNodeElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feMorphology"
+     helpref     = "filters.html#feMorphologyElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feOffset"
+     helpref     = "filters.html#feOffsetElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "fePointLight"
+     helpref     = "filters.html#fePointLightElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feSpecularLighting"
+     helpref     = "filters.html#feSpecularLightingElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feSpotLight"
+     helpref     = "filters.html#feSpotLightElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feTile"
+     helpref     = "filters.html#feTileElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "feTurbulence"
+     helpref     = "filters.html#feTurbulenceElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "filter"
+     helpref     = "filters.html#FilterElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "g"
+     helpref     = "struct.html#GElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+/>
+<tag name        = "glyph"
+     helpref     = "fonts.html#GlyphElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "glyphRef"
+     helpref     = "text.html#GlyphRefElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "hkern"
+     helpref     = "fonts.html#HKernElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "image"
+     helpref     = "struct.html#ImageElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "line"
+     helpref     = "shapes.html#LineElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "linearGradient"
+     helpref     = "pservers.html#LinearGradientElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "marker"
+     helpref     = "painting.html#MarkerElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mask"
+     helpref     = "masking.html#MaskElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "metadata"
+     helpref     = "metadata.html#MetadataElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "missing-glyph"
+     helpref     = "fonts.html#MissingGlyphElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "mpath"
+     helpref     = "animate.html#MPathElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "foreignObject"
+     helpref     = "extend.html#ForeignObjectElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "path"
+     helpref     = "paths.html#PathElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "pattern"
+     helpref     = "pservers.html#PatternElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "polygon"
+     helpref     = "shapes.html#PolygonElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "polyline"
+     helpref     = "shapes.html#PolylineElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "radialGradient"
+     helpref     = "pservers.html#RadialGradientElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "rect"
+     helpref     = "shapes.html#RectElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "set"
+     helpref     = "animate.html#SetElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "stop"
+     helpref     = "pservers.html#StopElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "svg"
+     helpref     = "struct.html#SVGElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "switch"
+     helpref     = "struct.html#SwitchElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "symbol"
+     helpref     = "struct.html#SymbolElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "switch"
+     helpref     = "struct.html#SwitchElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "tspan"
+     helpref     = "text.html#TSpanElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+<tag name        = "vkern"
+     helpref     = "fonts.html#VKernElement"
+     description = ""
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
+</html-property-table>
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/util/htmlreferencetable.xml b/xml/impl/src/com/intellij/xml/util/htmlreferencetable.xml
new file mode 100644
index 0000000..52089a7
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/htmlreferencetable.xml
@@ -0,0 +1,7 @@
+<dd>
+  <tag name="a">
+    <atttribute name="href">
+      <reference type="WebFileReference"/>
+    </atttribute>
+  </tag>
+</dd>
\ No newline at end of file
diff --git a/xml/impl/xml.iml b/xml/impl/xml.iml
new file mode 100644
index 0000000..0395394
--- /dev/null
+++ b/xml/impl/xml.iml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module relativePaths="true" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="module" module-name="xml-openapi" exported="" />
+    <orderEntry type="library" name="Xerces" level="project" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="platform-impl" />
+    <orderEntry type="module" module-name="lang-impl" />
+    <orderEntry type="module" module-name="icons" />
+    <orderEntry type="library" name="XmlBeans" level="project" />
+    <orderEntry type="module" module-name="platform-resources" />
+    <orderEntry type="module" module-name="vcs-api" />
+  </component>
+  <component name="copyright">
+    <Base>
+      <setting name="state" value="1" />
+    </Base>
+  </component>
+</module>
+