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 <doctype>.<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="<$TAG$ $ATTRS$>$END$</$TAG_NAME$>">
+ <variable name="TAG" expression="" defaultValue="" alwaysStopAt="true" />
+ <variable name="ATTRS" expression="" defaultValue="""" alwaysStopAt="false" />
+ <variable name="TAG_NAME" expression="firstWord(TAG)" defaultValue="""" 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="<$TAG$>$SELECTION$</$TAGNAME$> ">
+ <variable name="TAG" expression="" defaultValue="" alwaysStopAt="true" />
+ <variable name="SELECTION" expression="" defaultValue="" alwaysStopAt="false" />
+ <variable name="TAGNAME" expression="firstWord(TAG)" 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="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="<$TAG$>$SELECTION$</$TAGNAME$>">
+ <variable name="TAG" expression="" defaultValue="" alwaysStopAt="true" />
+ <variable name="SELECTION" expression="" defaultValue="" alwaysStopAt="false" />
+ <variable name="TAGNAME" expression="firstWord(TAG)" 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="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="<![CDATA[ $SELECTION$ ]]>">
+ <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="<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="$ENV_LANG$"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title></title> </head> <body> $END$ </body> </html>">
+ <variable alwaysStopAt="true" defaultValue=""en"" expression="" name="ENV_LANG"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="html:4t" toReformat="true" toShortenFQNames="true" value="<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="$ENV_LANG$"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title></title> </head> <body> $END$ </body> </html>">
+ <variable alwaysStopAt="true" defaultValue=""en"" expression="" name="ENV_LANG"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="cc:ie6" toReformat="true" toShortenFQNames="true" value="<!--[if lte IE 6]> $END$ <![endif]-->">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="html:4s" toReformat="true" toShortenFQNames="true" value="<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="$ENV_LANG$"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title></title> </head> <body> $END$ </body> </html>">
+ <variable alwaysStopAt="true" defaultValue=""en"" expression="" name="ENV_LANG"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="cc:noie" toReformat="true" toShortenFQNames="true" value="<!--[if !IE]><!--> $END$ <!--<![endif]-->">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="html:5" toReformat="true" toShortenFQNames="true" value="<!DOCTYPE HTML> <html lang="$ENV_LOCALE$"> <head> <meta charset="UTF-8"> <title></title> </head> <body> $END$ </body> </html>">
+ <variable alwaysStopAt="true" defaultValue=""en-US"" expression="" name="ENV_LOCALE"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="cc:ie" toReformat="true" toShortenFQNames="true" value="<!--[if IE]> $END$ <![endif]-->">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="html:xt" toReformat="true" toShortenFQNames="true" value="<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="$ENV_LANG$"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title></title> </head> <body> $END$ </body> </html>">
+ <variable alwaysStopAt="true" defaultValue=""en"" expression="" name="ENV_LANG"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="html:xxs" toReformat="true" toShortenFQNames="true" value="<!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="$ENV_LANG$"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title></title> </head> <body> $END$ </body> </html>">
+ <variable alwaysStopAt="true" defaultValue=""en"" expression="" name="ENV_LANG"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<a href="http://...">...</a>" name="a:link" toReformat="true" toShortenFQNames="true" value="<a href="http://$VAR0$">$END$</a>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="datetime-local" name="..." id="...">" name="input:datetime-local" toReformat="true" toShortenFQNames="true" value="<input type="datetime-local" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="reset" value="...">" name="input:reset" toReformat="true" toShortenFQNames="true" value="<input type="reset" value="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<colgroup>...</colgroup>" name="colg" toReformat="true" toShortenFQNames="true" value="<colgroup>$END$</colgroup>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<style type="text/css">...</style>" name="style" toReformat="true" toShortenFQNames="true" value="<style type="text/css">$END$</style>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<address>...</address>" name="adr" toReformat="true" toShortenFQNames="true" value="<address>$END$</address>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<img src="..." alt="...">" name="img" toReformat="true" toShortenFQNames="true" value="<img src="$VAR0$" alt="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<bdo dir="ltr">...</bdo>" name="bdo:l" toReformat="true" toShortenFQNames="true" value="<bdo dir="ltr">$END$</bdo>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<param name="..." value="...">" name="param" toReformat="true" toShortenFQNames="true" value="<param name="$VAR0$" value="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="colgroup+" toReformat="true" toShortenFQNames="true" value="<colgroup> <col> </colgroup>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<form action="..." method="post">...</form>" name="form:post" toReformat="true" toShortenFQNames="true" value="<form action="$VAR0$" method="post">$END$</form>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<bdo dir="rtl">...</bdo>" name="bdo:r" toReformat="true" toShortenFQNames="true" value="<bdo dir="rtl">$END$</bdo>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<figure>...</figure>" name="fig" toReformat="true" toShortenFQNames="true" value="<figure>$END$</figure>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="radio" name="..." id="...">" name="input:radio" toReformat="true" toShortenFQNames="true" value="<input type="radio" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<link rel="stylesheet" type="text/css" href="...print.css" media="print">" name="link:print" toReformat="true" toShortenFQNames="true" value="<link rel="stylesheet" type="text/css" href="$END$print.css" media="print">">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<option>...</option>" name="opt" toReformat="true" toShortenFQNames="true" value="<option>$END$</option>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="image" src="..." alt="...">" name="input:i" toReformat="true" toShortenFQNames="true" value="<input type="image" src="$VAR0$" alt="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="hidden" name="...">" name="input:h" toReformat="true" toShortenFQNames="true" value="<input type="hidden" name="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="file" name="..." id="...">" name="input:f" toReformat="true" toShortenFQNames="true" value="<input type="file" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="checkbox" name="..." id="...">" name="input:c" toReformat="true" toShortenFQNames="true" value="<input type="checkbox" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="button" value="...">" name="input:b" toReformat="true" toShortenFQNames="true" value="<input type="button" value="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<abbr title="...">...</abbr>" name="abbr" toReformat="true" toShortenFQNames="true" value="<abbr title="$VAR0$">$END$</abbr>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="text" name="..." id="...">" name="input:t" toReformat="true" toShortenFQNames="true" value="<input type="text" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="password" name="..." id="...">" name="input:p" toReformat="true" toShortenFQNames="true" value="<input type="password" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="submit" value="...">" name="input:s" toReformat="true" toShortenFQNames="true" value="<input type="submit" value="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="radio" name="..." id="...">" name="input:r" toReformat="true" toShortenFQNames="true" value="<input type="radio" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<iframe>...</iframe>" name="ifr" toReformat="true" toShortenFQNames="true" value="<iframe>$END$</iframe>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<embed>" name="emb" toReformat="true" toShortenFQNames="true" value="<embed>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="optg+" toReformat="true" toShortenFQNames="true" value="<optgroup> <option value="$VAR0$">$END$</option> </optgroup>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<command>" name="cmd" toReformat="true" toShortenFQNames="true" value="<command>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<link rel="alternate" type="application/atom+xml" title="Atom" href="atom.xml">" name="link:atom" toReformat="true" toShortenFQNames="true" value="<link rel="alternate" type="application/atom+xml" title="Atom" href="atom.xml">">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="table+" toReformat="true" toShortenFQNames="true" value="<table> <tr> <td>$END$</td> </tr> </table>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<article>...</article>" name="art" toReformat="true" toShortenFQNames="true" value="<article>$END$</article>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="search" name="..." id="...">" name="input:search" toReformat="true" toShortenFQNames="true" value="<input type="search" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<area shape="rect" coords="..." href="..." alt="...">" name="area:r" toReformat="true" toShortenFQNames="true" value="<area shape="rect" coords="$VAR0$" href="$VAR1$" alt="$VAR2$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR2"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<area shape="poly" coords="..." href="..." alt="...">" name="area:p" toReformat="true" toShortenFQNames="true" value="<area shape="poly" coords="$VAR0$" href="$VAR1$" alt="$VAR2$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR2"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="date" name="..." id="...">" name="input:date" toReformat="true" toShortenFQNames="true" value="<input type="date" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<video src="...">...</video>" name="video" toReformat="true" toShortenFQNames="true" value="<video src="$VAR0$">$END$</video>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="button" value="...">" name="input:button" toReformat="true" toShortenFQNames="true" value="<input type="button" value="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<area shape="default" href="..." alt="...">" name="area:d" toReformat="true" toShortenFQNames="true" value="<area shape="default" href="$VAR0$" alt="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<area shape="circle" coords="..." href="..." alt="...">" name="area:c" toReformat="true" toShortenFQNames="true" value="<area shape="circle" coords="$VAR0$" href="$VAR1$" alt="$VAR2$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR2"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<output>...</output>" name="out" toReformat="true" toShortenFQNames="true" value="<output>$END$</output>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<footer>...</footer>" name="ftr" toReformat="true" toShortenFQNames="true" value="<footer>$END$</footer>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<dialog>...</dialog>" name="dlg" toReformat="true" toShortenFQNames="true" value="<dialog>$END$</dialog>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<script type="text/javascript" src="...">...</script>" name="script:src" toReformat="true" toShortenFQNames="true" value="<script type="text/javascript" src="$VAR0$">$END$</script>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<form action="..." method="get">...</form>" name="form:get" toReformat="true" toShortenFQNames="true" value="<form action="$VAR0$" method="get">$END$</form>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">" name="meta:utf" toReformat="true" toShortenFQNames="true" value="<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<label for="...">...</label>" name="label" toReformat="true" toShortenFQNames="true" value="<label for="$VAR0$">$END$</label>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="time" name="..." id="...">" name="input:time" toReformat="true" toShortenFQNames="true" value="<input type="time" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<link rel="shortcut icon" type="image/x-icon" href="...favicon.ico">" name="link:favicon" toReformat="true" toShortenFQNames="true" value="<link rel="shortcut icon" type="image/x-icon" href="$END$favicon.ico">">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<menu type="toolbar">...</menu>" name="menu:toolbar" toReformat="true" toShortenFQNames="true" value="<menu type="toolbar">$END$</menu>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<progress>...</progress>" name="prog" toReformat="true" toShortenFQNames="true" value="<progress>$END$</progress>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="email" name="..." id="...">" name="input:email" toReformat="true" toShortenFQNames="true" value="<input type="email" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<optgroup>...</optgroup>" name="optg" toReformat="true" toShortenFQNames="true" value="<optgroup>$END$</optgroup>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<strong>...</strong>" name="str" toReformat="true" toShortenFQNames="true" value="<strong>$END$</strong>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<legend>...</legend>" name="leg" toReformat="true" toShortenFQNames="true" value="<legend>$END$</legend>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<acronym title="...">...</acronym>" name="acronym" toReformat="true" toShortenFQNames="true" value="<acronym title="$VAR0$">$END$</acronym>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="ol+" toReformat="true" toShortenFQNames="true" value="<ol> <li>$END$</li> </ol>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="tr+" toReformat="true" toShortenFQNames="true" value="<tr> <td>$END$</td> </tr>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="optgroup+" toReformat="true" toShortenFQNames="true" value="<optgroup> <option value="$VAR0$">$END$</option> </optgroup>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<base href="...">" name="base" toReformat="true" toShortenFQNames="true" value="<base href="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<blockquote>...</blockquote>" name="bq" toReformat="true" toShortenFQNames="true" value="<blockquote>$END$</blockquote>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<source>...</source>" name="src" toReformat="true" toShortenFQNames="true" value="<source>$END$</source>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<object>...</object>" name="obj" toReformat="true" toShortenFQNames="true" value="<object>$END$</object>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="dl+" toReformat="true" toShortenFQNames="true" value="<dl> <dt>$VAR0$</dt> <dd>$END$</dd> </dl>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<script type="text/javascript">...</script>" name="script" toReformat="true" toShortenFQNames="true" value="<script type="text/javascript">$END$</script>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<acronym>...</acronym>" name="acr" toReformat="true" toShortenFQNames="true" value="<acronym>$END$</acronym>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="password" name="..." id="...">" name="input:password" toReformat="true" toShortenFQNames="true" value="<input type="password" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="file" name="..." id="...">" name="input:file" toReformat="true" toShortenFQNames="true" value="<input type="file" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<textarea>...</textarea>" name="tarea" toReformat="true" toShortenFQNames="true" value="<textarea>$END$</textarea>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<select name="..." id="...">...</select>" name="select" toReformat="true" toShortenFQNames="true" value="<select name="$VAR0$" id="$VAR1$">$END$</select>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="number" name="..." id="...">" name="input:number" toReformat="true" toShortenFQNames="true" value="<input type="number" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="range" name="..." id="...">" name="input:range" toReformat="true" toShortenFQNames="true" value="<input type="range" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<area shape="..." coords="..." href="..." alt="...">" name="area" toReformat="true" toShortenFQNames="true" value="<area shape="$VAR0$" coords="$VAR1$" href="$VAR2$" alt="$VAR3$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR2"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR3"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="image" src="..." alt="...">" name="input:image" toReformat="true" toShortenFQNames="true" value="<input type="image" src="$VAR0$" alt="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="ul+" toReformat="true" toShortenFQNames="true" value="<ul> <li>$END$</li> </ul>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="month" name="..." id="...">" name="input:month" toReformat="true" toShortenFQNames="true" value="<input type="month" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<fieldset>...</fieldset>" name="fset" toReformat="true" toShortenFQNames="true" value="<fieldset>$END$</fieldset>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<meta http-equiv="Content-Type" content="text/html;charset=Win-1251">" name="meta:win" toReformat="true" toShortenFQNames="true" value="<meta http-equiv="Content-Type" content="text/html;charset=Win-1251">">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<menu type="toolbar">...</menu>" name="menu:t" toReformat="true" toShortenFQNames="true" value="<menu type="toolbar">$END$</menu>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<form action="...">...</form>" name="form" toReformat="true" toShortenFQNames="true" value="<form action="$VAR0$">$END$</form>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<menu type="context">...</menu>" name="menu:c" toReformat="true" toShortenFQNames="true" value="<menu type="context">$END$</menu>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<link rel="stylesheet" href="...">" name="link" toReformat="true" toShortenFQNames="true" value="<link rel="stylesheet" href="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="...">" name="input" toReformat="true" toShortenFQNames="true" value="<input type="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<link rel="alternate" type="application/rss+xml" title="RSS" href="...rss.xml">" name="link:rss" toReformat="true" toShortenFQNames="true" value="<link rel="alternate" type="application/rss+xml" title="RSS" href="$END$rss.xml">">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="select+" toReformat="true" toShortenFQNames="true" value="<select name="$VAR0$" id="$VAR1$"> <option value="$VAR2$">$END$</option> </select>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR2"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<header>...</header>" name="hdr" toReformat="true" toShortenFQNames="true" value="<header>$END$</header>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<caption>...</caption>" name="cap" toReformat="true" toShortenFQNames="true" value="<caption>$END$</caption>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<details>...</details>" name="det" toReformat="true" toShortenFQNames="true" value="<details>$END$</details>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<link rel="apple-touch-icon" href="...favicon.png">" name="link:touch" toReformat="true" toShortenFQNames="true" value="<link rel="apple-touch-icon" href="$END$favicon.png">">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<iframe src="..." frameborder="0">...</iframe>" name="iframe" toReformat="true" toShortenFQNames="true" value="<iframe src="$VAR0$" frameborder="0">$END$</iframe>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<link rel="stylesheet" type="text/css" href="....css" media="all">" name="link:css" toReformat="true" toShortenFQNames="true" value="<link rel="stylesheet" type="text/css" href="$END$.css" media="all">">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="week" name="..." id="...">" name="input:week" toReformat="true" toShortenFQNames="true" value="<input type="week" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<embed src="..." type="...">" name="embed" toReformat="true" toShortenFQNames="true" value="<embed src="$VAR0$" type="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<datagrid>...</datagrid>" name="datag" toReformat="true" toShortenFQNames="true" value="<datagrid>$END$</datagrid>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="datetime" name="..." id="...">" name="input:datetime" toReformat="true" toShortenFQNames="true" value="<input type="datetime" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<option value="...">...</option>" name="option" toReformat="true" toShortenFQNames="true" value="<option value="$VAR0$">$END$</option>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<html xmlns="http://www.w3.org/1999/xhtml">...</html>" name="html:xml" toReformat="true" toShortenFQNames="true" value="<html xmlns="http://www.w3.org/1999/xhtml">$END$</html>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<button>...</button>" name="btn" toReformat="true" toShortenFQNames="true" value="<button>$END$</button>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="url" name="..." id="...">" name="input:url" toReformat="true" toShortenFQNames="true" value="<input type="url" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<menu type="context">...</menu>" name="menu:context" toReformat="true" toShortenFQNames="true" value="<menu type="context">$END$</menu>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="colg+" toReformat="true" toShortenFQNames="true" value="<colgroup> <col> </colgroup>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<map name="...">...</map>" name="map" toReformat="true" toShortenFQNames="true" value="<map name="$VAR0$">$END$</map>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="color" name="..." id="...">" name="input:color" toReformat="true" toShortenFQNames="true" value="<input type="color" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<meta http-equiv="X-UA-Compatible" content="IE=7">" name="meta:compat" toReformat="true" toShortenFQNames="true" value="<meta http-equiv="X-UA-Compatible" content="IE=7">">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="hidden" name="...">" name="input:hidden" toReformat="true" toShortenFQNames="true" value="<input type="hidden" name="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<object data="..." type="...">...</object>" name="object" toReformat="true" toShortenFQNames="true" value="<object data="$VAR0$" type="$VAR1$">$END$</object>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<a href="mailto:...">...</a>" name="a:mail" toReformat="true" toShortenFQNames="true" value="<a href="mailto:$VAR0$">$END$</a>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<a href="...">...</a>" name="a" toReformat="true" toShortenFQNames="true" value="<a href="$VAR0$">$END$</a>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<datalist>...</datalist>" name="datal" toReformat="true" toShortenFQNames="true" value="<datalist>$END$</datalist>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<keygen>" name="kg" toReformat="true" toShortenFQNames="true" value="<keygen>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<textarea name="..." id="..." cols="30" rows="10">...</textarea>" name="textarea" toReformat="true" toShortenFQNames="true" value="<textarea name="$VAR0$" id="$VAR1$" cols="30" rows="10">$END$</textarea>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="map+" toReformat="true" toShortenFQNames="true" value="<map name="$VAR0$"> <area shape="$VAR1$" coords="$VAR2$" href="$VAR3$" alt="$VAR4$"> </map>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR2"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR3"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR4"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="submit" value="...">" name="input:submit" toReformat="true" toShortenFQNames="true" value="<input type="submit" value="$VAR0$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="text" name="..." id="...">" name="input:text" toReformat="true" toShortenFQNames="true" value="<input type="text" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<input type="checkbox" name="..." id="...">" name="input:checkbox" toReformat="true" toShortenFQNames="true" value="<input type="checkbox" name="$VAR0$" id="$VAR1$">">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<fieldset>...</fieldset>" name="fst" toReformat="true" toShortenFQNames="true" value="<fieldset>$END$</fieldset>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<section>...</section>" name="sect" toReformat="true" toShortenFQNames="true" value="<section>$END$</section>">
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<audio src="...">...</audio>" name="audio" toReformat="true" toShortenFQNames="true" value="<audio src="$VAR0$">$END$</audio>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="HTML_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<bdo dir="...">...</bdo>" name="bdo" toReformat="true" toShortenFQNames="true" value="<bdo dir="$VAR0$">$END$</bdo>">
+ <variable alwaysStopAt="true" defaultValue="""" 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="<xsl:template match="..." mode="...">...</xsl:template>" name="tmatch" toReformat="true" toShortenFQNames="true" value="<xsl:template match="$VAR0$" mode="$VAR1$">$END$</xsl:template>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:param name="..." select="..." />" name="par" toReformat="true" toShortenFQNames="true" value="<xsl:param name="$VAR0$" select="$VAR1$" />">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:copy-of select="..." />" name="co" toReformat="true" toShortenFQNames="true" value="<xsl:copy-of select="$VAR0$" />">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:attribute name="...">...</xsl:attribute>" name="attr" toReformat="true" toShortenFQNames="true" value="<xsl:attribute name="$VAR0$">$END$</xsl:attribute>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:value-of select="..." />" name="val" toReformat="true" toShortenFQNames="true" value="<xsl:value-of select="$VAR0$" />">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:when test="...">...</xsl:when>" name="xsl:when" toReformat="true" toShortenFQNames="true" value="<xsl:when test="$VAR0$">$END$</xsl:when>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:for-each select="...">...</xsl:for-each>" name="each" toReformat="true" toShortenFQNames="true" value="<xsl:for-each select="$VAR0$">$END$</xsl:for-each>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:variable name="...">...</xsl:variable>" name="var" toReformat="true" toShortenFQNames="true" value="<xsl:variable name="$VAR0$">$END$</xsl:variable>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:when test="...">...</xsl:when>" name="wh" toReformat="true" toShortenFQNames="true" value="<xsl:when test="$VAR0$">$END$</xsl:when>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:template name="...">...</xsl:template>" name="tn" toReformat="true" toShortenFQNames="true" value="<xsl:template name="$VAR0$">$END$</xsl:template>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:apply-templates select="..." mode="..." />" name="ap" toReformat="true" toShortenFQNames="true" value="<xsl:apply-templates select="$VAR0$" mode="$VAR1$" />">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:template match="..." mode="...">...</xsl:template>" name="tm" toReformat="true" toShortenFQNames="true" value="<xsl:template match="$VAR0$" mode="$VAR1$">$END$</xsl:template>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:call-template name="..." />" name="call" toReformat="true" toShortenFQNames="true" value="<xsl:call-template name="$VAR0$" />">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="" name="choose+" toReformat="true" toShortenFQNames="true" value="<xsl:choose> <xsl:when test="$VAR0$">$VAR1$</xsl:when> <xsl:otherwise>$END$</xsl:otherwise> </xsl:choose>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:variable name="..." select="..." />" name="vare" toReformat="true" toShortenFQNames="true" value="<xsl:variable name="$VAR0$" select="$VAR1$" />">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:with-param name="..." select="..." />" name="wp" toReformat="true" toShortenFQNames="true" value="<xsl:with-param name="$VAR0$" select="$VAR1$" />">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR1"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:template name="...">...</xsl:template>" name="tname" toReformat="true" toShortenFQNames="true" value="<xsl:template name="$VAR0$">$END$</xsl:template>">
+ <variable alwaysStopAt="true" defaultValue="""" expression="" name="VAR0"/>
+ <context>
+ <option name="XSL_TEXT" value="true"/>
+ </context>
+ </template>
+ <template description="<xsl:if test="...">...</xsl:if>" name="if" toReformat="true" toShortenFQNames="true" value="<xsl:if test="$VAR0$">$END$</xsl:if>">
+ <variable alwaysStopAt="true" defaultValue="""" 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 <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 <schema> 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 <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
+ <complexContent>
+ <restriction base="xs:anyType">
+ ...
+ </restriction>
+ </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><link type='icon'> 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: <style></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: <style scoped></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: <meta name></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: <meta http-equiv='refresh'></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: <meta http-equiv='default-style'></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: <meta http-equiv='content-language'> (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: <meta charset></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: <li></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: <li></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: <dd></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: <ins></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: <del></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: <object></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: <map></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: <rp></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: <video></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: <audio></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 <input></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: <input type='text'></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: <input type='password'></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: <input type='checkbox'></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: <input type='radio'></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: <input type='button'></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: <input type='submit'></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: <input type='reset'></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: <input type='file'></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: <input type='hidden'></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: <input type='image'></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: <button type='submit'></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: <button type='reset'></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: <button type='button'></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: <input type='datetime'></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: <input type='datetime-local'></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: <input type='date'></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: <input type='month'></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: <input type='time'></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: <input type='week'></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: <input type='number'></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: <input type='range'></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: <input type='email'></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: <input type='url'></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: <input type='search'></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: <input type='tel'></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: <input type='color'></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: <command type='command'></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: <command type='radio'></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: <command type='checkbox'></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: <li></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: <canvas></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 " "> <!-- no-break space = non-breaking space,
+ U+00A0 ISOnum -->
+<!ENTITY iexcl "¡"> <!-- inverted exclamation mark, U+00A1 ISOnum -->
+<!ENTITY cent "¢"> <!-- cent sign, U+00A2 ISOnum -->
+<!ENTITY pound "£"> <!-- pound sign, U+00A3 ISOnum -->
+<!ENTITY curren "¤"> <!-- currency sign, U+00A4 ISOnum -->
+<!ENTITY yen "¥"> <!-- yen sign = yuan sign, U+00A5 ISOnum -->
+<!ENTITY brvbar "¦"> <!-- broken bar = broken vertical bar,
+ U+00A6 ISOnum -->
+<!ENTITY sect "§"> <!-- section sign, U+00A7 ISOnum -->
+<!ENTITY uml "¨"> <!-- diaeresis = spacing diaeresis,
+ U+00A8 ISOdia -->
+<!ENTITY copy "©"> <!-- copyright sign, U+00A9 ISOnum -->
+<!ENTITY ordf "ª"> <!-- feminine ordinal indicator, U+00AA ISOnum -->
+<!ENTITY laquo "«"> <!-- left-pointing double angle quotation mark
+ = left pointing guillemet, U+00AB ISOnum -->
+<!ENTITY not "¬"> <!-- not sign = angled dash,
+ U+00AC ISOnum -->
+<!ENTITY shy "­"> <!-- soft hyphen = discretionary hyphen,
+ U+00AD ISOnum -->
+<!ENTITY reg "®"> <!-- registered sign = registered trade mark sign,
+ U+00AE ISOnum -->
+<!ENTITY macr "¯"> <!-- macron = spacing macron = overline
+ = APL overbar, U+00AF ISOdia -->
+<!ENTITY deg "°"> <!-- degree sign, U+00B0 ISOnum -->
+<!ENTITY plusmn "±"> <!-- plus-minus sign = plus-or-minus sign,
+ U+00B1 ISOnum -->
+<!ENTITY sup2 "²"> <!-- superscript two = superscript digit two
+ = squared, U+00B2 ISOnum -->
+<!ENTITY sup3 "³"> <!-- superscript three = superscript digit three
+ = cubed, U+00B3 ISOnum -->
+<!ENTITY acute "´"> <!-- acute accent = spacing acute,
+ U+00B4 ISOdia -->
+<!ENTITY micro "µ"> <!-- micro sign, U+00B5 ISOnum -->
+<!ENTITY para "¶"> <!-- pilcrow sign = paragraph sign,
+ U+00B6 ISOnum -->
+<!ENTITY middot "·"> <!-- middle dot = Georgian comma
+ = Greek middle dot, U+00B7 ISOnum -->
+<!ENTITY cedil "¸"> <!-- cedilla = spacing cedilla, U+00B8 ISOdia -->
+<!ENTITY sup1 "¹"> <!-- superscript one = superscript digit one,
+ U+00B9 ISOnum -->
+<!ENTITY ordm "º"> <!-- masculine ordinal indicator,
+ U+00BA ISOnum -->
+<!ENTITY raquo "»"> <!-- right-pointing double angle quotation mark
+ = right pointing guillemet, U+00BB ISOnum -->
+<!ENTITY frac14 "¼"> <!-- vulgar fraction one quarter
+ = fraction one quarter, U+00BC ISOnum -->
+<!ENTITY frac12 "½"> <!-- vulgar fraction one half
+ = fraction one half, U+00BD ISOnum -->
+<!ENTITY frac34 "¾"> <!-- vulgar fraction three quarters
+ = fraction three quarters, U+00BE ISOnum -->
+<!ENTITY iquest "¿"> <!-- inverted question mark
+ = turned question mark, U+00BF ISOnum -->
+<!ENTITY Agrave "À"> <!-- latin capital letter A with grave
+ = latin capital letter A grave,
+ U+00C0 ISOlat1 -->
+<!ENTITY Aacute "Á"> <!-- latin capital letter A with acute,
+ U+00C1 ISOlat1 -->
+<!ENTITY Acirc "Â"> <!-- latin capital letter A with circumflex,
+ U+00C2 ISOlat1 -->
+<!ENTITY Atilde "Ã"> <!-- latin capital letter A with tilde,
+ U+00C3 ISOlat1 -->
+<!ENTITY Auml "Ä"> <!-- latin capital letter A with diaeresis,
+ U+00C4 ISOlat1 -->
+<!ENTITY Aring "Å"> <!-- latin capital letter A with ring above
+ = latin capital letter A ring,
+ U+00C5 ISOlat1 -->
+<!ENTITY AElig "Æ"> <!-- latin capital letter AE
+ = latin capital ligature AE,
+ U+00C6 ISOlat1 -->
+<!ENTITY Ccedil "Ç"> <!-- latin capital letter C with cedilla,
+ U+00C7 ISOlat1 -->
+<!ENTITY Egrave "È"> <!-- latin capital letter E with grave,
+ U+00C8 ISOlat1 -->
+<!ENTITY Eacute "É"> <!-- latin capital letter E with acute,
+ U+00C9 ISOlat1 -->
+<!ENTITY Ecirc "Ê"> <!-- latin capital letter E with circumflex,
+ U+00CA ISOlat1 -->
+<!ENTITY Euml "Ë"> <!-- latin capital letter E with diaeresis,
+ U+00CB ISOlat1 -->
+<!ENTITY Igrave "Ì"> <!-- latin capital letter I with grave,
+ U+00CC ISOlat1 -->
+<!ENTITY Iacute "Í"> <!-- latin capital letter I with acute,
+ U+00CD ISOlat1 -->
+<!ENTITY Icirc "Î"> <!-- latin capital letter I with circumflex,
+ U+00CE ISOlat1 -->
+<!ENTITY Iuml "Ï"> <!-- latin capital letter I with diaeresis,
+ U+00CF ISOlat1 -->
+<!ENTITY ETH "Ð"> <!-- latin capital letter ETH, U+00D0 ISOlat1 -->
+<!ENTITY Ntilde "Ñ"> <!-- latin capital letter N with tilde,
+ U+00D1 ISOlat1 -->
+<!ENTITY Ograve "Ò"> <!-- latin capital letter O with grave,
+ U+00D2 ISOlat1 -->
+<!ENTITY Oacute "Ó"> <!-- latin capital letter O with acute,
+ U+00D3 ISOlat1 -->
+<!ENTITY Ocirc "Ô"> <!-- latin capital letter O with circumflex,
+ U+00D4 ISOlat1 -->
+<!ENTITY Otilde "Õ"> <!-- latin capital letter O with tilde,
+ U+00D5 ISOlat1 -->
+<!ENTITY Ouml "Ö"> <!-- latin capital letter O with diaeresis,
+ U+00D6 ISOlat1 -->
+<!ENTITY times "×"> <!-- multiplication sign, U+00D7 ISOnum -->
+<!ENTITY Oslash "Ø"> <!-- latin capital letter O with stroke
+ = latin capital letter O slash,
+ U+00D8 ISOlat1 -->
+<!ENTITY Ugrave "Ù"> <!-- latin capital letter U with grave,
+ U+00D9 ISOlat1 -->
+<!ENTITY Uacute "Ú"> <!-- latin capital letter U with acute,
+ U+00DA ISOlat1 -->
+<!ENTITY Ucirc "Û"> <!-- latin capital letter U with circumflex,
+ U+00DB ISOlat1 -->
+<!ENTITY Uuml "Ü"> <!-- latin capital letter U with diaeresis,
+ U+00DC ISOlat1 -->
+<!ENTITY Yacute "Ý"> <!-- latin capital letter Y with acute,
+ U+00DD ISOlat1 -->
+<!ENTITY THORN "Þ"> <!-- latin capital letter THORN,
+ U+00DE ISOlat1 -->
+<!ENTITY szlig "ß"> <!-- latin small letter sharp s = ess-zed,
+ U+00DF ISOlat1 -->
+<!ENTITY agrave "à"> <!-- latin small letter a with grave
+ = latin small letter a grave,
+ U+00E0 ISOlat1 -->
+<!ENTITY aacute "á"> <!-- latin small letter a with acute,
+ U+00E1 ISOlat1 -->
+<!ENTITY acirc "â"> <!-- latin small letter a with circumflex,
+ U+00E2 ISOlat1 -->
+<!ENTITY atilde "ã"> <!-- latin small letter a with tilde,
+ U+00E3 ISOlat1 -->
+<!ENTITY auml "ä"> <!-- latin small letter a with diaeresis,
+ U+00E4 ISOlat1 -->
+<!ENTITY aring "å"> <!-- latin small letter a with ring above
+ = latin small letter a ring,
+ U+00E5 ISOlat1 -->
+<!ENTITY aelig "æ"> <!-- latin small letter ae
+ = latin small ligature ae, U+00E6 ISOlat1 -->
+<!ENTITY ccedil "ç"> <!-- latin small letter c with cedilla,
+ U+00E7 ISOlat1 -->
+<!ENTITY egrave "è"> <!-- latin small letter e with grave,
+ U+00E8 ISOlat1 -->
+<!ENTITY eacute "é"> <!-- latin small letter e with acute,
+ U+00E9 ISOlat1 -->
+<!ENTITY ecirc "ê"> <!-- latin small letter e with circumflex,
+ U+00EA ISOlat1 -->
+<!ENTITY euml "ë"> <!-- latin small letter e with diaeresis,
+ U+00EB ISOlat1 -->
+<!ENTITY igrave "ì"> <!-- latin small letter i with grave,
+ U+00EC ISOlat1 -->
+<!ENTITY iacute "í"> <!-- latin small letter i with acute,
+ U+00ED ISOlat1 -->
+<!ENTITY icirc "î"> <!-- latin small letter i with circumflex,
+ U+00EE ISOlat1 -->
+<!ENTITY iuml "ï"> <!-- latin small letter i with diaeresis,
+ U+00EF ISOlat1 -->
+<!ENTITY eth "ð"> <!-- latin small letter eth, U+00F0 ISOlat1 -->
+<!ENTITY ntilde "ñ"> <!-- latin small letter n with tilde,
+ U+00F1 ISOlat1 -->
+<!ENTITY ograve "ò"> <!-- latin small letter o with grave,
+ U+00F2 ISOlat1 -->
+<!ENTITY oacute "ó"> <!-- latin small letter o with acute,
+ U+00F3 ISOlat1 -->
+<!ENTITY ocirc "ô"> <!-- latin small letter o with circumflex,
+ U+00F4 ISOlat1 -->
+<!ENTITY otilde "õ"> <!-- latin small letter o with tilde,
+ U+00F5 ISOlat1 -->
+<!ENTITY ouml "ö"> <!-- latin small letter o with diaeresis,
+ U+00F6 ISOlat1 -->
+<!ENTITY divide "÷"> <!-- division sign, U+00F7 ISOnum -->
+<!ENTITY oslash "ø"> <!-- latin small letter o with stroke,
+ = latin small letter o slash,
+ U+00F8 ISOlat1 -->
+<!ENTITY ugrave "ù"> <!-- latin small letter u with grave,
+ U+00F9 ISOlat1 -->
+<!ENTITY uacute "ú"> <!-- latin small letter u with acute,
+ U+00FA ISOlat1 -->
+<!ENTITY ucirc "û"> <!-- latin small letter u with circumflex,
+ U+00FB ISOlat1 -->
+<!ENTITY uuml "ü"> <!-- latin small letter u with diaeresis,
+ U+00FC ISOlat1 -->
+<!ENTITY yacute "ý"> <!-- latin small letter y with acute,
+ U+00FD ISOlat1 -->
+<!ENTITY thorn "þ"> <!-- latin small letter thorn,
+ U+00FE ISOlat1 -->
+<!ENTITY yuml "ÿ"> <!-- 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 " " ><!-- no-break space = non-breaking space, U+00A0 ISOnum -->
+<!ENTITY iexcl "¡" ><!-- inverted exclamation mark, U+00A1 ISOnum -->
+<!ENTITY cent "¢" ><!-- cent sign, U+00A2 ISOnum -->
+<!ENTITY pound "£" ><!-- pound sign, U+00A3 ISOnum -->
+<!ENTITY curren "¤" ><!-- currency sign, U+00A4 ISOnum -->
+<!ENTITY yen "¥" ><!-- yen sign = yuan sign, U+00A5 ISOnum -->
+<!ENTITY brvbar "¦" ><!-- broken bar = broken vertical bar, U+00A6 ISOnum -->
+<!ENTITY sect "§" ><!-- section sign, U+00A7 ISOnum -->
+<!ENTITY uml "¨" ><!-- diaeresis = spacing diaeresis, U+00A8 ISOdia -->
+<!ENTITY copy "©" ><!-- copyright sign, U+00A9 ISOnum -->
+<!ENTITY ordf "ª" ><!-- feminine ordinal indicator, U+00AA ISOnum -->
+<!ENTITY laquo "«" ><!-- left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum -->
+<!ENTITY not "¬" ><!-- not sign, U+00AC ISOnum -->
+<!ENTITY shy "­" ><!-- soft hyphen = discretionary hyphen, U+00AD ISOnum -->
+<!ENTITY reg "®" ><!-- registered sign = registered trade mark sign, U+00AE ISOnum -->
+<!ENTITY macr "¯" ><!-- macron = spacing macron = overline = APL overbar, U+00AF ISOdia -->
+<!ENTITY deg "°" ><!-- degree sign, U+00B0 ISOnum -->
+<!ENTITY plusmn "±" ><!-- plus-minus sign = plus-or-minus sign, U+00B1 ISOnum -->
+<!ENTITY sup2 "²" ><!-- superscript two = superscript digit two = squared, U+00B2 ISOnum -->
+<!ENTITY sup3 "³" ><!-- superscript three = superscript digit three = cubed, U+00B3 ISOnum -->
+<!ENTITY acute "´" ><!-- acute accent = spacing acute, U+00B4 ISOdia -->
+<!ENTITY micro "µ" ><!-- micro sign, U+00B5 ISOnum -->
+<!ENTITY para "¶" ><!-- pilcrow sign = paragraph sign, U+00B6 ISOnum -->
+<!ENTITY middot "·" ><!-- middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum -->
+<!ENTITY cedil "¸" ><!-- cedilla = spacing cedilla, U+00B8 ISOdia -->
+<!ENTITY sup1 "¹" ><!-- superscript one = superscript digit one, U+00B9 ISOnum -->
+<!ENTITY ordm "º" ><!-- masculine ordinal indicator, U+00BA ISOnum -->
+<!ENTITY raquo "»" ><!-- right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum -->
+<!ENTITY frac14 "¼" ><!-- vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum -->
+<!ENTITY frac12 "½" ><!-- vulgar fraction one half = fraction one half, U+00BD ISOnum -->
+<!ENTITY frac34 "¾" ><!-- vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum -->
+<!ENTITY iquest "¿" ><!-- inverted question mark = turned question mark, U+00BF ISOnum -->
+<!ENTITY Agrave "À" ><!-- latin capital A with grave = latin capital A grave, U+00C0 ISOlat1 -->
+<!ENTITY Aacute "Á" ><!-- latin capital A with acute, U+00C1 ISOlat1 -->
+<!ENTITY Acirc "Â" ><!-- latin capital A with circumflex, U+00C2 ISOlat1 -->
+<!ENTITY Atilde "Ã" ><!-- latin capital A with tilde, U+00C3 ISOlat1 -->
+<!ENTITY Auml "Ä" ><!-- latin capital A with diaeresis, U+00C4 ISOlat1 -->
+<!ENTITY Aring "Å" ><!-- latin capital A with ring above = latin capital A ring, U+00C5 ISOlat1 -->
+<!ENTITY AElig "Æ" ><!-- latin capital AE = latin capital ligature AE, U+00C6 ISOlat1 -->
+<!ENTITY Ccedil "Ç" ><!-- latin capital C with cedilla, U+00C7 ISOlat1 -->
+<!ENTITY Egrave "È" ><!-- latin capital E with grave, U+00C8 ISOlat1 -->
+<!ENTITY Eacute "É" ><!-- latin capital E with acute, U+00C9 ISOlat1 -->
+<!ENTITY Ecirc "Ê" ><!-- latin capital E with circumflex, U+00CA ISOlat1 -->
+<!ENTITY Euml "Ë" ><!-- latin capital E with diaeresis, U+00CB ISOlat1 -->
+<!ENTITY Igrave "Ì" ><!-- latin capital I with grave, U+00CC ISOlat1 -->
+<!ENTITY Iacute "Í" ><!-- latin capital I with acute, U+00CD ISOlat1 -->
+<!ENTITY Icirc "Î" ><!-- latin capital I with circumflex, U+00CE ISOlat1 -->
+<!ENTITY Iuml "Ï" ><!-- latin capital I with diaeresis, U+00CF ISOlat1 -->
+<!ENTITY ETH "Ð" ><!-- latin capital ETH, U+00D0 ISOlat1 -->
+<!ENTITY Ntilde "Ñ" ><!-- latin capital N with tilde, U+00D1 ISOlat1 -->
+<!ENTITY Ograve "Ò" ><!-- latin capital O with grave, U+00D2 ISOlat1 -->
+<!ENTITY Oacute "Ó" ><!-- latin capital O with acute, U+00D3 ISOlat1 -->
+<!ENTITY Ocirc "Ô" ><!-- latin capital O with circumflex, U+00D4 ISOlat1 -->
+<!ENTITY Otilde "Õ" ><!-- latin capital O with tilde, U+00D5 ISOlat1 -->
+<!ENTITY Ouml "Ö" ><!-- latin capital O with diaeresis, U+00D6 ISOlat1 -->
+<!ENTITY times "×" ><!-- multiplication sign, U+00D7 ISOnum -->
+<!ENTITY Oslash "Ø" ><!-- latin capital O with stroke = latin capital O slash, U+00D8 ISOlat1 -->
+<!ENTITY Ugrave "Ù" ><!-- latin capital U with grave, U+00D9 ISOlat1 -->
+<!ENTITY Uacute "Ú" ><!-- latin capital U with acute, U+00DA ISOlat1 -->
+<!ENTITY Ucirc "Û" ><!-- latin capital U with circumflex, U+00DB ISOlat1 -->
+<!ENTITY Uuml "Ü" ><!-- latin capital U with diaeresis, U+00DC ISOlat1 -->
+<!ENTITY Yacute "Ý" ><!-- latin capital Y with acute, U+00DD ISOlat1 -->
+<!ENTITY THORN "Þ" ><!-- latin capital THORN, U+00DE ISOlat1 -->
+<!ENTITY szlig "ß" ><!-- latin small sharp s = ess-zed, U+00DF ISOlat1 -->
+<!ENTITY agrave "à" ><!-- latin small a with grave = latin small a grave, U+00E0 ISOlat1 -->
+<!ENTITY aacute "á" ><!-- latin small a with acute, U+00E1 ISOlat1 -->
+<!ENTITY acirc "â" ><!-- latin small a with circumflex, U+00E2 ISOlat1 -->
+<!ENTITY atilde "ã" ><!-- latin small a with tilde, U+00E3 ISOlat1 -->
+<!ENTITY auml "ä" ><!-- latin small a with diaeresis, U+00E4 ISOlat1 -->
+<!ENTITY aring "å" ><!-- latin small a with ring above = latin small a ring, U+00E5 ISOlat1 -->
+<!ENTITY aelig "æ" ><!-- latin small ae = latin small ligature ae, U+00E6 ISOlat1 -->
+<!ENTITY ccedil "ç" ><!-- latin small c with cedilla, U+00E7 ISOlat1 -->
+<!ENTITY egrave "è" ><!-- latin small e with grave, U+00E8 ISOlat1 -->
+<!ENTITY eacute "é" ><!-- latin small e with acute, U+00E9 ISOlat1 -->
+<!ENTITY ecirc "ê" ><!-- latin small e with circumflex, U+00EA ISOlat1 -->
+<!ENTITY euml "ë" ><!-- latin small e with diaeresis, U+00EB ISOlat1 -->
+<!ENTITY igrave "ì" ><!-- latin small i with grave, U+00EC ISOlat1 -->
+<!ENTITY iacute "í" ><!-- latin small i with acute, U+00ED ISOlat1 -->
+<!ENTITY icirc "î" ><!-- latin small i with circumflex, U+00EE ISOlat1 -->
+<!ENTITY iuml "ï" ><!-- latin small i with diaeresis, U+00EF ISOlat1 -->
+<!ENTITY eth "ð" ><!-- latin small eth, U+00F0 ISOlat1 -->
+<!ENTITY ntilde "ñ" ><!-- latin small n with tilde, U+00F1 ISOlat1 -->
+<!ENTITY ograve "ò" ><!-- latin small o with grave, U+00F2 ISOlat1 -->
+<!ENTITY oacute "ó" ><!-- latin small o with acute, U+00F3 ISOlat1 -->
+<!ENTITY ocirc "ô" ><!-- latin small o with circumflex, U+00F4 ISOlat1 -->
+<!ENTITY otilde "õ" ><!-- latin small o with tilde, U+00F5 ISOlat1 -->
+<!ENTITY ouml "ö" ><!-- latin small o with diaeresis, U+00F6 ISOlat1 -->
+<!ENTITY divide "÷" ><!-- division sign, U+00F7 ISOnum -->
+<!ENTITY oslash "ø" ><!-- latin small o with stroke, = latin small o slash, U+00F8 ISOlat1 -->
+<!ENTITY ugrave "ù" ><!-- latin small u with grave, U+00F9 ISOlat1 -->
+<!ENTITY uacute "ú" ><!-- latin small u with acute, U+00FA ISOlat1 -->
+<!ENTITY ucirc "û" ><!-- latin small u with circumflex, U+00FB ISOlat1 -->
+<!ENTITY uuml "ü" ><!-- latin small u with diaeresis, U+00FC ISOlat1 -->
+<!ENTITY yacute "ý" ><!-- latin small y with acute, U+00FD ISOlat1 -->
+<!ENTITY thorn "þ" ><!-- latin small thorn with, U+00FE ISOlat1 -->
+<!ENTITY yuml "ÿ" ><!-- 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 "ƒ" ><!-- latin small f with hook = function
+ = florin, U+0192 ISOtech -->
+
+<!-- Greek -->
+<!ENTITY Alpha "Α" ><!-- greek capital letter alpha, U+0391 -->
+<!ENTITY Beta "Β" ><!-- greek capital letter beta, U+0392 -->
+<!ENTITY Gamma "Γ" ><!-- greek capital letter gamma, U+0393 ISOgrk3 -->
+<!ENTITY Delta "Δ" ><!-- greek capital letter delta, U+0394 ISOgrk3 -->
+<!ENTITY Epsilon "Ε" ><!-- greek capital letter epsilon, U+0395 -->
+<!ENTITY Zeta "Ζ" ><!-- greek capital letter zeta, U+0396 -->
+<!ENTITY Eta "Η" ><!-- greek capital letter eta, U+0397 -->
+<!ENTITY Theta "Θ" ><!-- greek capital letter theta, U+0398 ISOgrk3 -->
+<!ENTITY Iota "Ι" ><!-- greek capital letter iota, U+0399 -->
+<!ENTITY Kappa "Κ" ><!-- greek capital letter kappa, U+039A -->
+<!ENTITY Lambda "Λ" ><!-- greek capital letter lambda, U+039B ISOgrk3 -->
+<!ENTITY Mu "Μ" ><!-- greek capital letter mu, U+039C -->
+<!ENTITY Nu "Ν" ><!-- greek capital letter nu, U+039D -->
+<!ENTITY Xi "Ξ" ><!-- greek capital letter xi, U+039E ISOgrk3 -->
+<!ENTITY Omicron "Ο" ><!-- greek capital letter omicron, U+039F -->
+<!ENTITY Pi "Π" ><!-- greek capital letter pi, U+03A0 ISOgrk3 -->
+<!ENTITY Rho "Ρ" ><!-- greek capital letter rho, U+03A1 -->
+<!-- there is no Sigmaf, and no U+03A2 character either -->
+<!ENTITY Sigma "Σ" ><!-- greek capital letter sigma, U+03A3 ISOgrk3 -->
+<!ENTITY Tau "Τ" ><!-- greek capital letter tau, U+03A4 -->
+<!ENTITY Upsilon "Υ" ><!-- greek capital letter upsilon,
+ U+03A5 ISOgrk3 -->
+<!ENTITY Phi "Φ" ><!-- greek capital letter phi, U+03A6 ISOgrk3 -->
+<!ENTITY Chi "Χ" ><!-- greek capital letter chi, U+03A7 -->
+<!ENTITY Psi "Ψ" ><!-- greek capital letter psi, U+03A8 ISOgrk3 -->
+<!ENTITY Omega "Ω" ><!-- greek capital letter omega, U+03A9 ISOgrk3 -->
+<!ENTITY alpha "α" ><!-- greek small letter alpha, U+03B1 ISOgrk3 -->
+<!ENTITY beta "β" ><!-- greek small letter beta, U+03B2 ISOgrk3 -->
+<!ENTITY gamma "γ" ><!-- greek small letter gamma, U+03B3 ISOgrk3 -->
+<!ENTITY delta "δ" ><!-- greek small letter delta, U+03B4 ISOgrk3 -->
+<!ENTITY epsilon "ε" ><!-- greek small letter epsilon, U+03B5 ISOgrk3 -->
+<!ENTITY zeta "ζ" ><!-- greek small letter zeta, U+03B6 ISOgrk3 -->
+<!ENTITY eta "η" ><!-- greek small letter eta, U+03B7 ISOgrk3 -->
+<!ENTITY theta "θ" ><!-- greek small letter theta, U+03B8 ISOgrk3 -->
+<!ENTITY iota "ι" ><!-- greek small letter iota, U+03B9 ISOgrk3 -->
+<!ENTITY kappa "κ" ><!-- greek small letter kappa, U+03BA ISOgrk3 -->
+<!ENTITY lambda "λ" ><!-- greek small letter lambda, U+03BB ISOgrk3 -->
+<!ENTITY mu "μ" ><!-- greek small letter mu, U+03BC ISOgrk3 -->
+<!ENTITY nu "ν" ><!-- greek small letter nu, U+03BD ISOgrk3 -->
+<!ENTITY xi "ξ" ><!-- greek small letter xi, U+03BE ISOgrk3 -->
+<!ENTITY omicron "ο" ><!-- greek small letter omicron, U+03BF NEW -->
+<!ENTITY pi "π" ><!-- greek small letter pi, U+03C0 ISOgrk3 -->
+<!ENTITY rho "ρ" ><!-- greek small letter rho, U+03C1 ISOgrk3 -->
+<!ENTITY sigmaf "ς" ><!-- greek small letter final sigma, U+03C2 ISOgrk3 -->
+<!ENTITY sigma "σ" ><!-- greek small letter sigma, U+03C3 ISOgrk3 -->
+<!ENTITY tau "τ" ><!-- greek small letter tau, U+03C4 ISOgrk3 -->
+<!ENTITY upsilon "υ" ><!-- greek small letter upsilon, U+03C5 ISOgrk3 -->
+<!ENTITY phi "φ" ><!-- greek small letter phi, U+03C6 ISOgrk3 -->
+<!ENTITY chi "χ" ><!-- greek small letter chi, U+03C7 ISOgrk3 -->
+<!ENTITY psi "ψ" ><!-- greek small letter psi, U+03C8 ISOgrk3 -->
+<!ENTITY omega "ω" ><!-- greek small letter omega, U+03C9 ISOgrk3 -->
+<!ENTITY thetasym "ϑ" ><!-- greek small letter theta symbol, U+03D1 NEW -->
+<!ENTITY upsih "ϒ" ><!-- greek upsilon with hook symbol, U+03D2 NEW -->
+<!ENTITY piv "ϖ" ><!-- greek pi symbol, U+03D6 ISOgrk3 -->
+
+<!-- General Punctuation -->
+<!ENTITY bull "•" ><!-- bullet = black small circle, U+2022 ISOpub -->
+<!-- bullet is NOT the same as bullet operator, U+2219 -->
+<!ENTITY hellip "…" ><!-- horizontal ellipsis = three dot leader, U+2026 ISOpub -->
+<!ENTITY prime "′" ><!-- prime = minutes = feet, U+2032 ISOtech -->
+<!ENTITY Prime "″" ><!-- double prime = seconds = inches, U+2033 ISOtech -->
+<!ENTITY oline "‾" ><!-- overline = spacing overscore, U+203E NEW -->
+<!ENTITY frasl "⁄" ><!-- fraction slash, U+2044 NEW -->
+
+<!-- Letterlike Symbols -->
+<!ENTITY weierp "℘" ><!-- script capital P = power set = Weierstrass p, U+2118 ISOamso -->
+<!ENTITY image "ℑ" ><!-- blackletter capital I = imaginary part, U+2111 ISOamso -->
+<!ENTITY real "ℜ" ><!-- blackletter capital R = real part symbol, U+211C ISOamso -->
+<!ENTITY trade "™" ><!-- trade mark sign, U+2122 ISOnum -->
+<!ENTITY alefsym "ℵ" ><!-- 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 "←" ><!-- leftwards arrow, U+2190 ISOnum -->
+<!ENTITY uarr "↑" ><!-- upwards arrow, U+2191 ISOnum-->
+<!ENTITY rarr "→" ><!-- rightwards arrow, U+2192 ISOnum -->
+<!ENTITY darr "↓" ><!-- downwards arrow, U+2193 ISOnum -->
+<!ENTITY harr "↔" ><!-- left right arrow, U+2194 ISOamsa -->
+<!ENTITY crarr "↵" ><!-- downwards arrow with corner leftwards
+ = carriage return, U+21B5 NEW -->
+<!ENTITY lArr "⇐" ><!-- 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 "⇑" ><!-- upwards double arrow, U+21D1 ISOamsa -->
+<!ENTITY rArr "⇒" ><!-- 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 "⇓" ><!-- downwards double arrow, U+21D3 ISOamsa -->
+<!ENTITY hArr "⇔" ><!-- left right double arrow, U+21D4 ISOamsa -->
+
+<!-- Mathematical Operators -->
+<!ENTITY forall "∀" ><!-- for all, U+2200 ISOtech -->
+<!ENTITY part "∂" ><!-- partial differential, U+2202 ISOtech -->
+<!ENTITY exist "∃" ><!-- there exists, U+2203 ISOtech -->
+<!ENTITY empty "∅" ><!-- empty set = null set = diameter, U+2205 ISOamso -->
+<!ENTITY nabla "∇" ><!-- nabla = backward difference, U+2207 ISOtech -->
+<!ENTITY isin "∈" ><!-- element of, U+2208 ISOtech -->
+<!ENTITY notin "∉" ><!-- not an element of, U+2209 ISOtech -->
+<!ENTITY ni "∋" ><!-- contains as member, U+220B ISOtech -->
+<!-- should there be a more memorable name than 'ni'? -->
+<!ENTITY prod "∏" ><!-- 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 "∑" ><!-- 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 "−" ><!-- minus sign, U+2212 ISOtech -->
+<!ENTITY lowast "∗" ><!-- asterisk operator, U+2217 ISOtech -->
+<!ENTITY radic "√" ><!-- square root = radical sign, U+221A ISOtech -->
+<!ENTITY prop "∝" ><!-- proportional to, U+221D ISOtech -->
+<!ENTITY infin "∞" ><!-- infinity, U+221E ISOtech -->
+<!ENTITY ang "∠" ><!-- angle, U+2220 ISOamso -->
+<!ENTITY and "∧" ><!-- logical and = wedge, U+2227 ISOtech -->
+<!ENTITY or "∨" ><!-- logical or = vee, U+2228 ISOtech -->
+<!ENTITY cap "∩" ><!-- intersection = cap, U+2229 ISOtech -->
+<!ENTITY cup "∪" ><!-- union = cup, U+222A ISOtech -->
+<!ENTITY int "∫" ><!-- integral, U+222B ISOtech -->
+<!ENTITY there4 "∴" ><!-- therefore, U+2234 ISOtech -->
+<!ENTITY sim "∼" ><!-- 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 "≅" ><!-- approximately equal to, U+2245 ISOtech -->
+<!ENTITY asymp "≈" ><!-- almost equal to = asymptotic to, U+2248 ISOamsr -->
+<!ENTITY ne "≠" ><!-- not equal to, U+2260 ISOtech -->
+<!ENTITY equiv "≡" ><!-- identical to, U+2261 ISOtech -->
+<!ENTITY le "≤" ><!-- less-than or equal to, U+2264 ISOtech -->
+<!ENTITY ge "≥" ><!-- greater-than or equal to, U+2265 ISOtech -->
+<!ENTITY sub "⊂" ><!-- subset of, U+2282 ISOtech -->
+<!ENTITY sup "⊃" ><!-- 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 "⊄" ><!-- not a subset of, U+2284 ISOamsn -->
+<!ENTITY sube "⊆" ><!-- subset of or equal to, U+2286 ISOtech -->
+<!ENTITY supe "⊇" ><!-- superset of or equal to, U+2287 ISOtech -->
+<!ENTITY oplus "⊕" ><!-- circled plus = direct sum, U+2295 ISOamsb -->
+<!ENTITY otimes "⊗" ><!-- circled times = vector product, U+2297 ISOamsb -->
+<!ENTITY perp "⊥" ><!-- up tack = orthogonal to = perpendicular, U+22A5 ISOtech -->
+<!ENTITY sdot "⋅" ><!-- dot operator, U+22C5 ISOamsb -->
+<!-- dot operator is NOT the same character as U+00B7 middle dot -->
+
+<!-- Miscellaneous Technical -->
+<!ENTITY lceil "⌈" ><!-- left ceiling = apl upstile, U+2308 ISOamsc -->
+<!ENTITY rceil "⌉" ><!-- right ceiling, U+2309 ISOamsc -->
+<!ENTITY lfloor "⌊" ><!-- left floor = apl downstile, U+230A ISOamsc -->
+<!ENTITY rfloor "⌋" ><!-- right floor, U+230B ISOamsc -->
+<!ENTITY lang "〈" ><!-- 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 "〉" ><!-- 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 "◊" ><!-- lozenge, U+25CA ISOpub -->
+
+<!-- Miscellaneous Symbols -->
+<!ENTITY spades "♠" ><!-- black spade suit, U+2660 ISOpub -->
+<!-- black here seems to mean filled as opposed to hollow -->
+<!ENTITY clubs "♣" ><!-- black club suit = shamrock, U+2663 ISOpub -->
+<!ENTITY hearts "♥" ><!-- black heart suit = valentine, U+2665 ISOpub -->
+<!ENTITY diams "♦" ><!-- 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 ' 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 "&<" ><!-- less-than sign, U+003C ISOnum -->
+<!ENTITY gt ">" ><!-- greater-than sign, U+003E ISOnum -->
+<!ENTITY amp "&&" ><!-- ampersand, U+0026 ISOnum -->
+<!ENTITY apos "'" ><!-- apostrophe, U+0027 ISOnum -->
+<!ENTITY quot """ ><!-- quotation mark = APL quote, U+0022 ISOnum -->
+
+<!-- Latin Extended-A -->
+<!ENTITY OElig "Œ" ><!-- latin capital ligature OE, U+0152 ISOlat2 -->
+<!ENTITY oelig "œ" ><!-- latin small ligature oe, U+0153 ISOlat2 -->
+
+<!-- ligature is a misnomer, this is a separate character in some languages -->
+<!ENTITY Scaron "Š" ><!-- latin capital letter S with caron, U+0160 ISOlat2 -->
+<!ENTITY scaron "š" ><!-- latin small letter s with caron, U+0161 ISOlat2 -->
+<!ENTITY Yuml "Ÿ" ><!-- latin capital letter Y with diaeresis, U+0178 ISOlat2 -->
+
+<!-- Spacing Modifier Letters -->
+<!ENTITY circ "ˆ" ><!-- modifier letter circumflex accent, U+02C6 ISOpub -->
+<!ENTITY tilde "˜" ><!-- small tilde, U+02DC ISOdia -->
+
+<!-- General Punctuation -->
+<!ENTITY ensp " " ><!-- en space, U+2002 ISOpub -->
+<!ENTITY emsp " " ><!-- em space, U+2003 ISOpub -->
+<!ENTITY thinsp " " ><!-- thin space, U+2009 ISOpub -->
+<!ENTITY zwnj "‌" ><!-- zero width non-joiner, U+200C NEW RFC 2070 -->
+<!ENTITY zwj "‍" ><!-- zero width joiner, U+200D NEW RFC 2070 -->
+<!ENTITY lrm "‎" ><!-- left-to-right mark, U+200E NEW RFC 2070 -->
+<!ENTITY rlm "‏" ><!-- right-to-left mark, U+200F NEW RFC 2070 -->
+<!ENTITY ndash "–" ><!-- en dash, U+2013 ISOpub -->
+<!ENTITY mdash "—" ><!-- em dash, U+2014 ISOpub -->
+<!ENTITY lsquo "‘" ><!-- left single quotation mark, U+2018 ISOnum -->
+<!ENTITY rsquo "’" ><!-- right single quotation mark, U+2019 ISOnum -->
+<!ENTITY sbquo "‚" ><!-- single low-9 quotation mark, U+201A NEW -->
+<!ENTITY ldquo "“" ><!-- left double quotation mark, U+201C ISOnum -->
+<!ENTITY rdquo "”" ><!-- right double quotation mark, U+201D ISOnum -->
+<!ENTITY bdquo "„" ><!-- double low-9 quotation mark, U+201E NEW -->
+<!ENTITY dagger "†" ><!-- dagger, U+2020 ISOpub -->
+<!ENTITY Dagger "‡" ><!-- double dagger, U+2021 ISOpub -->
+<!ENTITY permil "‰" ><!-- per mille sign, U+2030 ISOtech -->
+
+<!-- lsaquo is proposed but not yet ISO standardized -->
+<!ENTITY lsaquo "‹" ><!-- single left-pointing angle quotation mark, U+2039 ISO proposed -->
+<!-- rsaquo is proposed but not yet ISO standardized -->
+<!ENTITY rsaquo "›" ><!-- single right-pointing angle quotation mark, U+203A ISO proposed -->
+<!ENTITY euro "€" ><!-- 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;"><!-- ...................................................................... -->
+<!-- XHTMLMP1.2 Forms Module .................................................. -->
+<!-- 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.
+ ....................................................................... -->
+
+<!-- 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 -->
+</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 """> <!-- quotation mark, U+0022 ISOnum -->
+<!ENTITY amp "&#38;"> <!-- ampersand, U+0026 ISOnum -->
+<!ENTITY lt "&#60;"> <!-- less-than sign, U+003C ISOnum -->
+<!ENTITY gt ">"> <!-- greater-than sign, U+003E ISOnum -->
+<!ENTITY apos "'"> <!-- apostrophe = APL quote, U+0027 ISOnum -->
+
+<!-- Latin Extended-A -->
+<!ENTITY OElig "Œ"> <!-- latin capital ligature OE,
+ U+0152 ISOlat2 -->
+<!ENTITY oelig "œ"> <!-- latin small ligature oe, U+0153 ISOlat2 -->
+<!-- ligature is a misnomer, this is a separate character in some languages -->
+<!ENTITY Scaron "Š"> <!-- latin capital letter S with caron,
+ U+0160 ISOlat2 -->
+<!ENTITY scaron "š"> <!-- latin small letter s with caron,
+ U+0161 ISOlat2 -->
+<!ENTITY Yuml "Ÿ"> <!-- latin capital letter Y with diaeresis,
+ U+0178 ISOlat2 -->
+
+<!-- Spacing Modifier Letters -->
+<!ENTITY circ "ˆ"> <!-- modifier letter circumflex accent,
+ U+02C6 ISOpub -->
+<!ENTITY tilde "˜"> <!-- small tilde, U+02DC ISOdia -->
+
+<!-- General Punctuation -->
+<!ENTITY ensp " "> <!-- en space, U+2002 ISOpub -->
+<!ENTITY emsp " "> <!-- em space, U+2003 ISOpub -->
+<!ENTITY thinsp " "> <!-- thin space, U+2009 ISOpub -->
+<!ENTITY zwnj "‌"> <!-- zero width non-joiner,
+ U+200C NEW RFC 2070 -->
+<!ENTITY zwj "‍"> <!-- zero width joiner, U+200D NEW RFC 2070 -->
+<!ENTITY lrm "‎"> <!-- left-to-right mark, U+200E NEW RFC 2070 -->
+<!ENTITY rlm "‏"> <!-- right-to-left mark, U+200F NEW RFC 2070 -->
+<!ENTITY ndash "–"> <!-- en dash, U+2013 ISOpub -->
+<!ENTITY mdash "—"> <!-- em dash, U+2014 ISOpub -->
+<!ENTITY lsquo "‘"> <!-- left single quotation mark,
+ U+2018 ISOnum -->
+<!ENTITY rsquo "’"> <!-- right single quotation mark,
+ U+2019 ISOnum -->
+<!ENTITY sbquo "‚"> <!-- single low-9 quotation mark, U+201A NEW -->
+<!ENTITY ldquo "“"> <!-- left double quotation mark,
+ U+201C ISOnum -->
+<!ENTITY rdquo "”"> <!-- right double quotation mark,
+ U+201D ISOnum -->
+<!ENTITY bdquo "„"> <!-- double low-9 quotation mark, U+201E NEW -->
+<!ENTITY dagger "†"> <!-- dagger, U+2020 ISOpub -->
+<!ENTITY Dagger "‡"> <!-- double dagger, U+2021 ISOpub -->
+<!ENTITY permil "‰"> <!-- per mille sign, U+2030 ISOtech -->
+<!ENTITY lsaquo "‹"> <!-- single left-pointing angle quotation mark,
+ U+2039 ISO proposed -->
+<!-- lsaquo is proposed but not yet ISO standardized -->
+<!ENTITY rsaquo "›"> <!-- single right-pointing angle quotation mark,
+ U+203A ISO proposed -->
+<!-- rsaquo is proposed but not yet ISO standardized -->
+
+<!-- Currency Symbols -->
+<!ENTITY euro "€"> <!-- 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 "ƒ"> <!-- latin small letter f with hook = function
+ = florin, U+0192 ISOtech -->
+
+<!-- Greek -->
+<!ENTITY Alpha "Α"> <!-- greek capital letter alpha, U+0391 -->
+<!ENTITY Beta "Β"> <!-- greek capital letter beta, U+0392 -->
+<!ENTITY Gamma "Γ"> <!-- greek capital letter gamma,
+ U+0393 ISOgrk3 -->
+<!ENTITY Delta "Δ"> <!-- greek capital letter delta,
+ U+0394 ISOgrk3 -->
+<!ENTITY Epsilon "Ε"> <!-- greek capital letter epsilon, U+0395 -->
+<!ENTITY Zeta "Ζ"> <!-- greek capital letter zeta, U+0396 -->
+<!ENTITY Eta "Η"> <!-- greek capital letter eta, U+0397 -->
+<!ENTITY Theta "Θ"> <!-- greek capital letter theta,
+ U+0398 ISOgrk3 -->
+<!ENTITY Iota "Ι"> <!-- greek capital letter iota, U+0399 -->
+<!ENTITY Kappa "Κ"> <!-- greek capital letter kappa, U+039A -->
+<!ENTITY Lambda "Λ"> <!-- greek capital letter lamda,
+ U+039B ISOgrk3 -->
+<!ENTITY Mu "Μ"> <!-- greek capital letter mu, U+039C -->
+<!ENTITY Nu "Ν"> <!-- greek capital letter nu, U+039D -->
+<!ENTITY Xi "Ξ"> <!-- greek capital letter xi, U+039E ISOgrk3 -->
+<!ENTITY Omicron "Ο"> <!-- greek capital letter omicron, U+039F -->
+<!ENTITY Pi "Π"> <!-- greek capital letter pi, U+03A0 ISOgrk3 -->
+<!ENTITY Rho "Ρ"> <!-- greek capital letter rho, U+03A1 -->
+<!-- there is no Sigmaf, and no U+03A2 character either -->
+<!ENTITY Sigma "Σ"> <!-- greek capital letter sigma,
+ U+03A3 ISOgrk3 -->
+<!ENTITY Tau "Τ"> <!-- greek capital letter tau, U+03A4 -->
+<!ENTITY Upsilon "Υ"> <!-- greek capital letter upsilon,
+ U+03A5 ISOgrk3 -->
+<!ENTITY Phi "Φ"> <!-- greek capital letter phi,
+ U+03A6 ISOgrk3 -->
+<!ENTITY Chi "Χ"> <!-- greek capital letter chi, U+03A7 -->
+<!ENTITY Psi "Ψ"> <!-- greek capital letter psi,
+ U+03A8 ISOgrk3 -->
+<!ENTITY Omega "Ω"> <!-- greek capital letter omega,
+ U+03A9 ISOgrk3 -->
+
+<!ENTITY alpha "α"> <!-- greek small letter alpha,
+ U+03B1 ISOgrk3 -->
+<!ENTITY beta "β"> <!-- greek small letter beta, U+03B2 ISOgrk3 -->
+<!ENTITY gamma "γ"> <!-- greek small letter gamma,
+ U+03B3 ISOgrk3 -->
+<!ENTITY delta "δ"> <!-- greek small letter delta,
+ U+03B4 ISOgrk3 -->
+<!ENTITY epsilon "ε"> <!-- greek small letter epsilon,
+ U+03B5 ISOgrk3 -->
+<!ENTITY zeta "ζ"> <!-- greek small letter zeta, U+03B6 ISOgrk3 -->
+<!ENTITY eta "η"> <!-- greek small letter eta, U+03B7 ISOgrk3 -->
+<!ENTITY theta "θ"> <!-- greek small letter theta,
+ U+03B8 ISOgrk3 -->
+<!ENTITY iota "ι"> <!-- greek small letter iota, U+03B9 ISOgrk3 -->
+<!ENTITY kappa "κ"> <!-- greek small letter kappa,
+ U+03BA ISOgrk3 -->
+<!ENTITY lambda "λ"> <!-- greek small letter lamda,
+ U+03BB ISOgrk3 -->
+<!ENTITY mu "μ"> <!-- greek small letter mu, U+03BC ISOgrk3 -->
+<!ENTITY nu "ν"> <!-- greek small letter nu, U+03BD ISOgrk3 -->
+<!ENTITY xi "ξ"> <!-- greek small letter xi, U+03BE ISOgrk3 -->
+<!ENTITY omicron "ο"> <!-- greek small letter omicron, U+03BF NEW -->
+<!ENTITY pi "π"> <!-- greek small letter pi, U+03C0 ISOgrk3 -->
+<!ENTITY rho "ρ"> <!-- greek small letter rho, U+03C1 ISOgrk3 -->
+<!ENTITY sigmaf "ς"> <!-- greek small letter final sigma,
+ U+03C2 ISOgrk3 -->
+<!ENTITY sigma "σ"> <!-- greek small letter sigma,
+ U+03C3 ISOgrk3 -->
+<!ENTITY tau "τ"> <!-- greek small letter tau, U+03C4 ISOgrk3 -->
+<!ENTITY upsilon "υ"> <!-- greek small letter upsilon,
+ U+03C5 ISOgrk3 -->
+<!ENTITY phi "φ"> <!-- greek small letter phi, U+03C6 ISOgrk3 -->
+<!ENTITY chi "χ"> <!-- greek small letter chi, U+03C7 ISOgrk3 -->
+<!ENTITY psi "ψ"> <!-- greek small letter psi, U+03C8 ISOgrk3 -->
+<!ENTITY omega "ω"> <!-- greek small letter omega,
+ U+03C9 ISOgrk3 -->
+<!ENTITY thetasym "ϑ"> <!-- greek theta symbol,
+ U+03D1 NEW -->
+<!ENTITY upsih "ϒ"> <!-- greek upsilon with hook symbol,
+ U+03D2 NEW -->
+<!ENTITY piv "ϖ"> <!-- greek pi symbol, U+03D6 ISOgrk3 -->
+
+<!-- General Punctuation -->
+<!ENTITY bull "•"> <!-- bullet = black small circle,
+ U+2022 ISOpub -->
+<!-- bullet is NOT the same as bullet operator, U+2219 -->
+<!ENTITY hellip "…"> <!-- horizontal ellipsis = three dot leader,
+ U+2026 ISOpub -->
+<!ENTITY prime "′"> <!-- prime = minutes = feet, U+2032 ISOtech -->
+<!ENTITY Prime "″"> <!-- double prime = seconds = inches,
+ U+2033 ISOtech -->
+<!ENTITY oline "‾"> <!-- overline = spacing overscore,
+ U+203E NEW -->
+<!ENTITY frasl "⁄"> <!-- fraction slash, U+2044 NEW -->
+
+<!-- Letterlike Symbols -->
+<!ENTITY weierp "℘"> <!-- script capital P = power set
+ = Weierstrass p, U+2118 ISOamso -->
+<!ENTITY image "ℑ"> <!-- black-letter capital I = imaginary part,
+ U+2111 ISOamso -->
+<!ENTITY real "ℜ"> <!-- black-letter capital R = real part symbol,
+ U+211C ISOamso -->
+<!ENTITY trade "™"> <!-- trade mark sign, U+2122 ISOnum -->
+<!ENTITY alefsym "ℵ"> <!-- 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 "←"> <!-- leftwards arrow, U+2190 ISOnum -->
+<!ENTITY uarr "↑"> <!-- upwards arrow, U+2191 ISOnum-->
+<!ENTITY rarr "→"> <!-- rightwards arrow, U+2192 ISOnum -->
+<!ENTITY darr "↓"> <!-- downwards arrow, U+2193 ISOnum -->
+<!ENTITY harr "↔"> <!-- left right arrow, U+2194 ISOamsa -->
+<!ENTITY crarr "↵"> <!-- downwards arrow with corner leftwards
+ = carriage return, U+21B5 NEW -->
+<!ENTITY lArr "⇐"> <!-- 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 "⇑"> <!-- upwards double arrow, U+21D1 ISOamsa -->
+<!ENTITY rArr "⇒"> <!-- 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 "⇓"> <!-- downwards double arrow, U+21D3 ISOamsa -->
+<!ENTITY hArr "⇔"> <!-- left right double arrow,
+ U+21D4 ISOamsa -->
+
+<!-- Mathematical Operators -->
+<!ENTITY forall "∀"> <!-- for all, U+2200 ISOtech -->
+<!ENTITY part "∂"> <!-- partial differential, U+2202 ISOtech -->
+<!ENTITY exist "∃"> <!-- there exists, U+2203 ISOtech -->
+<!ENTITY empty "∅"> <!-- empty set = null set, U+2205 ISOamso -->
+<!ENTITY nabla "∇"> <!-- nabla = backward difference,
+ U+2207 ISOtech -->
+<!ENTITY isin "∈"> <!-- element of, U+2208 ISOtech -->
+<!ENTITY notin "∉"> <!-- not an element of, U+2209 ISOtech -->
+<!ENTITY ni "∋"> <!-- contains as member, U+220B ISOtech -->
+<!ENTITY prod "∏"> <!-- 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 "∑"> <!-- 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 "−"> <!-- minus sign, U+2212 ISOtech -->
+<!ENTITY lowast "∗"> <!-- asterisk operator, U+2217 ISOtech -->
+<!ENTITY radic "√"> <!-- square root = radical sign,
+ U+221A ISOtech -->
+<!ENTITY prop "∝"> <!-- proportional to, U+221D ISOtech -->
+<!ENTITY infin "∞"> <!-- infinity, U+221E ISOtech -->
+<!ENTITY ang "∠"> <!-- angle, U+2220 ISOamso -->
+<!ENTITY and "∧"> <!-- logical and = wedge, U+2227 ISOtech -->
+<!ENTITY or "∨"> <!-- logical or = vee, U+2228 ISOtech -->
+<!ENTITY cap "∩"> <!-- intersection = cap, U+2229 ISOtech -->
+<!ENTITY cup "∪"> <!-- union = cup, U+222A ISOtech -->
+<!ENTITY int "∫"> <!-- integral, U+222B ISOtech -->
+<!ENTITY there4 "∴"> <!-- therefore, U+2234 ISOtech -->
+<!ENTITY sim "∼"> <!-- 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 "≅"> <!-- approximately equal to, U+2245 ISOtech -->
+<!ENTITY asymp "≈"> <!-- almost equal to = asymptotic to,
+ U+2248 ISOamsr -->
+<!ENTITY ne "≠"> <!-- not equal to, U+2260 ISOtech -->
+<!ENTITY equiv "≡"> <!-- identical to, U+2261 ISOtech -->
+<!ENTITY le "≤"> <!-- less-than or equal to, U+2264 ISOtech -->
+<!ENTITY ge "≥"> <!-- greater-than or equal to,
+ U+2265 ISOtech -->
+<!ENTITY sub "⊂"> <!-- subset of, U+2282 ISOtech -->
+<!ENTITY sup "⊃"> <!-- superset of, U+2283 ISOtech -->
+<!ENTITY nsub "⊄"> <!-- not a subset of, U+2284 ISOamsn -->
+<!ENTITY sube "⊆"> <!-- subset of or equal to, U+2286 ISOtech -->
+<!ENTITY supe "⊇"> <!-- superset of or equal to,
+ U+2287 ISOtech -->
+<!ENTITY oplus "⊕"> <!-- circled plus = direct sum,
+ U+2295 ISOamsb -->
+<!ENTITY otimes "⊗"> <!-- circled times = vector product,
+ U+2297 ISOamsb -->
+<!ENTITY perp "⊥"> <!-- up tack = orthogonal to = perpendicular,
+ U+22A5 ISOtech -->
+<!ENTITY sdot "⋅"> <!-- dot operator, U+22C5 ISOamsb -->
+<!-- dot operator is NOT the same character as U+00B7 middle dot -->
+
+<!-- Miscellaneous Technical -->
+<!ENTITY lceil "⌈"> <!-- left ceiling = APL upstile,
+ U+2308 ISOamsc -->
+<!ENTITY rceil "⌉"> <!-- right ceiling, U+2309 ISOamsc -->
+<!ENTITY lfloor "⌊"> <!-- left floor = APL downstile,
+ U+230A ISOamsc -->
+<!ENTITY rfloor "⌋"> <!-- right floor, U+230B ISOamsc -->
+<!ENTITY lang "〈"> <!-- 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 "〉"> <!-- 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 "◊"> <!-- lozenge, U+25CA ISOpub -->
+
+<!-- Miscellaneous Symbols -->
+<!ENTITY spades "♠"> <!-- black spade suit, U+2660 ISOpub -->
+<!-- black here seems to mean filled as opposed to hollow -->
+<!ENTITY clubs "♣"> <!-- black club suit = shamrock,
+ U+2663 ISOpub -->
+<!ENTITY hearts "♥"> <!-- black heart suit = valentine,
+ U+2665 ISOpub -->
+<!ENTITY diams "♦"> <!-- 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 & 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 & 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 & 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;"><!-- ...................................................................... -->
+<!-- XHTML Simplified Forms Module ....................................... -->
+<!-- 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)
+ ....................................................................... -->
+
+<!-- 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
+ 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
+>
+<!-- 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
+ accesskey %Character.datatype; #IMPLIED
+>
+<!-- end of textarea.attlist -->]]>
+
+<!-- end of xhtml-basic-form-1.mod -->
+</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 " " ><!-- no-break space = non-breaking space, U+00A0 ISOnum -->
+<!ENTITY iexcl "¡" ><!-- inverted exclamation mark, U+00A1 ISOnum -->
+<!ENTITY cent "¢" ><!-- cent sign, U+00A2 ISOnum -->
+<!ENTITY pound "£" ><!-- pound sign, U+00A3 ISOnum -->
+<!ENTITY curren "¤" ><!-- currency sign, U+00A4 ISOnum -->
+<!ENTITY yen "¥" ><!-- yen sign = yuan sign, U+00A5 ISOnum -->
+<!ENTITY brvbar "¦" ><!-- broken bar = broken vertical bar, U+00A6 ISOnum -->
+<!ENTITY sect "§" ><!-- section sign, U+00A7 ISOnum -->
+<!ENTITY uml "¨" ><!-- diaeresis = spacing diaeresis, U+00A8 ISOdia -->
+<!ENTITY copy "©" ><!-- copyright sign, U+00A9 ISOnum -->
+<!ENTITY ordf "ª" ><!-- feminine ordinal indicator, U+00AA ISOnum -->
+<!ENTITY laquo "«" ><!-- left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum -->
+<!ENTITY not "¬" ><!-- not sign, U+00AC ISOnum -->
+<!ENTITY shy "­" ><!-- soft hyphen = discretionary hyphen, U+00AD ISOnum -->
+<!ENTITY reg "®" ><!-- registered sign = registered trade mark sign, U+00AE ISOnum -->
+<!ENTITY macr "¯" ><!-- macron = spacing macron = overline = APL overbar, U+00AF ISOdia -->
+<!ENTITY deg "°" ><!-- degree sign, U+00B0 ISOnum -->
+<!ENTITY plusmn "±" ><!-- plus-minus sign = plus-or-minus sign, U+00B1 ISOnum -->
+<!ENTITY sup2 "²" ><!-- superscript two = superscript digit two = squared, U+00B2 ISOnum -->
+<!ENTITY sup3 "³" ><!-- superscript three = superscript digit three = cubed, U+00B3 ISOnum -->
+<!ENTITY acute "´" ><!-- acute accent = spacing acute, U+00B4 ISOdia -->
+<!ENTITY micro "µ" ><!-- micro sign, U+00B5 ISOnum -->
+<!ENTITY para "¶" ><!-- pilcrow sign = paragraph sign, U+00B6 ISOnum -->
+<!ENTITY middot "·" ><!-- middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum -->
+<!ENTITY cedil "¸" ><!-- cedilla = spacing cedilla, U+00B8 ISOdia -->
+<!ENTITY sup1 "¹" ><!-- superscript one = superscript digit one, U+00B9 ISOnum -->
+<!ENTITY ordm "º" ><!-- masculine ordinal indicator, U+00BA ISOnum -->
+<!ENTITY raquo "»" ><!-- right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum -->
+<!ENTITY frac14 "¼" ><!-- vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum -->
+<!ENTITY frac12 "½" ><!-- vulgar fraction one half = fraction one half, U+00BD ISOnum -->
+<!ENTITY frac34 "¾" ><!-- vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum -->
+<!ENTITY iquest "¿" ><!-- inverted question mark = turned question mark, U+00BF ISOnum -->
+<!ENTITY Agrave "À" ><!-- latin capital A with grave = latin capital A grave, U+00C0 ISOlat1 -->
+<!ENTITY Aacute "Á" ><!-- latin capital A with acute, U+00C1 ISOlat1 -->
+<!ENTITY Acirc "Â" ><!-- latin capital A with circumflex, U+00C2 ISOlat1 -->
+<!ENTITY Atilde "Ã" ><!-- latin capital A with tilde, U+00C3 ISOlat1 -->
+<!ENTITY Auml "Ä" ><!-- latin capital A with diaeresis, U+00C4 ISOlat1 -->
+<!ENTITY Aring "Å" ><!-- latin capital A with ring above = latin capital A ring, U+00C5 ISOlat1 -->
+<!ENTITY AElig "Æ" ><!-- latin capital AE = latin capital ligature AE, U+00C6 ISOlat1 -->
+<!ENTITY Ccedil "Ç" ><!-- latin capital C with cedilla, U+00C7 ISOlat1 -->
+<!ENTITY Egrave "È" ><!-- latin capital E with grave, U+00C8 ISOlat1 -->
+<!ENTITY Eacute "É" ><!-- latin capital E with acute, U+00C9 ISOlat1 -->
+<!ENTITY Ecirc "Ê" ><!-- latin capital E with circumflex, U+00CA ISOlat1 -->
+<!ENTITY Euml "Ë" ><!-- latin capital E with diaeresis, U+00CB ISOlat1 -->
+<!ENTITY Igrave "Ì" ><!-- latin capital I with grave, U+00CC ISOlat1 -->
+<!ENTITY Iacute "Í" ><!-- latin capital I with acute, U+00CD ISOlat1 -->
+<!ENTITY Icirc "Î" ><!-- latin capital I with circumflex, U+00CE ISOlat1 -->
+<!ENTITY Iuml "Ï" ><!-- latin capital I with diaeresis, U+00CF ISOlat1 -->
+<!ENTITY ETH "Ð" ><!-- latin capital ETH, U+00D0 ISOlat1 -->
+<!ENTITY Ntilde "Ñ" ><!-- latin capital N with tilde, U+00D1 ISOlat1 -->
+<!ENTITY Ograve "Ò" ><!-- latin capital O with grave, U+00D2 ISOlat1 -->
+<!ENTITY Oacute "Ó" ><!-- latin capital O with acute, U+00D3 ISOlat1 -->
+<!ENTITY Ocirc "Ô" ><!-- latin capital O with circumflex, U+00D4 ISOlat1 -->
+<!ENTITY Otilde "Õ" ><!-- latin capital O with tilde, U+00D5 ISOlat1 -->
+<!ENTITY Ouml "Ö" ><!-- latin capital O with diaeresis, U+00D6 ISOlat1 -->
+<!ENTITY times "×" ><!-- multiplication sign, U+00D7 ISOnum -->
+<!ENTITY Oslash "Ø" ><!-- latin capital O with stroke = latin capital O slash, U+00D8 ISOlat1 -->
+<!ENTITY Ugrave "Ù" ><!-- latin capital U with grave, U+00D9 ISOlat1 -->
+<!ENTITY Uacute "Ú" ><!-- latin capital U with acute, U+00DA ISOlat1 -->
+<!ENTITY Ucirc "Û" ><!-- latin capital U with circumflex, U+00DB ISOlat1 -->
+<!ENTITY Uuml "Ü" ><!-- latin capital U with diaeresis, U+00DC ISOlat1 -->
+<!ENTITY Yacute "Ý" ><!-- latin capital Y with acute, U+00DD ISOlat1 -->
+<!ENTITY THORN "Þ" ><!-- latin capital THORN, U+00DE ISOlat1 -->
+<!ENTITY szlig "ß" ><!-- latin small sharp s = ess-zed, U+00DF ISOlat1 -->
+<!ENTITY agrave "à" ><!-- latin small a with grave = latin small a grave, U+00E0 ISOlat1 -->
+<!ENTITY aacute "á" ><!-- latin small a with acute, U+00E1 ISOlat1 -->
+<!ENTITY acirc "â" ><!-- latin small a with circumflex, U+00E2 ISOlat1 -->
+<!ENTITY atilde "ã" ><!-- latin small a with tilde, U+00E3 ISOlat1 -->
+<!ENTITY auml "ä" ><!-- latin small a with diaeresis, U+00E4 ISOlat1 -->
+<!ENTITY aring "å" ><!-- latin small a with ring above = latin small a ring, U+00E5 ISOlat1 -->
+<!ENTITY aelig "æ" ><!-- latin small ae = latin small ligature ae, U+00E6 ISOlat1 -->
+<!ENTITY ccedil "ç" ><!-- latin small c with cedilla, U+00E7 ISOlat1 -->
+<!ENTITY egrave "è" ><!-- latin small e with grave, U+00E8 ISOlat1 -->
+<!ENTITY eacute "é" ><!-- latin small e with acute, U+00E9 ISOlat1 -->
+<!ENTITY ecirc "ê" ><!-- latin small e with circumflex, U+00EA ISOlat1 -->
+<!ENTITY euml "ë" ><!-- latin small e with diaeresis, U+00EB ISOlat1 -->
+<!ENTITY igrave "ì" ><!-- latin small i with grave, U+00EC ISOlat1 -->
+<!ENTITY iacute "í" ><!-- latin small i with acute, U+00ED ISOlat1 -->
+<!ENTITY icirc "î" ><!-- latin small i with circumflex, U+00EE ISOlat1 -->
+<!ENTITY iuml "ï" ><!-- latin small i with diaeresis, U+00EF ISOlat1 -->
+<!ENTITY eth "ð" ><!-- latin small eth, U+00F0 ISOlat1 -->
+<!ENTITY ntilde "ñ" ><!-- latin small n with tilde, U+00F1 ISOlat1 -->
+<!ENTITY ograve "ò" ><!-- latin small o with grave, U+00F2 ISOlat1 -->
+<!ENTITY oacute "ó" ><!-- latin small o with acute, U+00F3 ISOlat1 -->
+<!ENTITY ocirc "ô" ><!-- latin small o with circumflex, U+00F4 ISOlat1 -->
+<!ENTITY otilde "õ" ><!-- latin small o with tilde, U+00F5 ISOlat1 -->
+<!ENTITY ouml "ö" ><!-- latin small o with diaeresis, U+00F6 ISOlat1 -->
+<!ENTITY divide "÷" ><!-- division sign, U+00F7 ISOnum -->
+<!ENTITY oslash "ø" ><!-- latin small o with stroke, = latin small o slash, U+00F8 ISOlat1 -->
+<!ENTITY ugrave "ù" ><!-- latin small u with grave, U+00F9 ISOlat1 -->
+<!ENTITY uacute "ú" ><!-- latin small u with acute, U+00FA ISOlat1 -->
+<!ENTITY ucirc "û" ><!-- latin small u with circumflex, U+00FB ISOlat1 -->
+<!ENTITY uuml "ü" ><!-- latin small u with diaeresis, U+00FC ISOlat1 -->
+<!ENTITY yacute "ý" ><!-- latin small y with acute, U+00FD ISOlat1 -->
+<!ENTITY thorn "þ" ><!-- latin small thorn with, U+00FE ISOlat1 -->
+<!ENTITY yuml "ÿ" ><!-- 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 ' 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 "&#60;" ><!-- less-than sign, U+003C ISOnum -->
+<!ENTITY gt ">" ><!-- greater-than sign, U+003E ISOnum -->
+<!ENTITY amp "&#38;" ><!-- ampersand, U+0026 ISOnum -->
+<!ENTITY apos "'" ><!-- The Apostrophe (Apostrophe Quote, APL Quote), U+0027 ISOnum -->
+<!ENTITY quot """ ><!-- quotation mark (Quote Double), U+0022 ISOnum -->
+
+<!-- Latin Extended-A -->
+<!ENTITY OElig "Œ" ><!-- latin capital ligature OE, U+0152 ISOlat2 -->
+<!ENTITY oelig "œ" ><!-- latin small ligature oe, U+0153 ISOlat2 -->
+
+<!-- ligature is a misnomer, this is a separate character in some languages -->
+<!ENTITY Scaron "Š" ><!-- latin capital letter S with caron, U+0160 ISOlat2 -->
+<!ENTITY scaron "š" ><!-- latin small letter s with caron, U+0161 ISOlat2 -->
+<!ENTITY Yuml "Ÿ" ><!-- latin capital letter Y with diaeresis, U+0178 ISOlat2 -->
+
+<!-- Spacing Modifier Letters -->
+<!ENTITY circ "ˆ" ><!-- modifier letter circumflex accent, U+02C6 ISOpub -->
+<!ENTITY tilde "˜" ><!-- small tilde, U+02DC ISOdia -->
+
+<!-- General Punctuation -->
+<!ENTITY ensp " " ><!-- en space, U+2002 ISOpub -->
+<!ENTITY emsp " " ><!-- em space, U+2003 ISOpub -->
+<!ENTITY thinsp " " ><!-- thin space, U+2009 ISOpub -->
+<!ENTITY zwnj "‌" ><!-- zero width non-joiner, U+200C NEW RFC 2070 -->
+<!ENTITY zwj "‍" ><!-- zero width joiner, U+200D NEW RFC 2070 -->
+<!ENTITY lrm "‎" ><!-- left-to-right mark, U+200E NEW RFC 2070 -->
+<!ENTITY rlm "‏" ><!-- right-to-left mark, U+200F NEW RFC 2070 -->
+<!ENTITY ndash "–" ><!-- en dash, U+2013 ISOpub -->
+<!ENTITY mdash "—" ><!-- em dash, U+2014 ISOpub -->
+<!ENTITY lsquo "‘" ><!-- left single quotation mark, U+2018 ISOnum -->
+<!ENTITY rsquo "’" ><!-- right single quotation mark, U+2019 ISOnum -->
+<!ENTITY sbquo "‚" ><!-- single low-9 quotation mark, U+201A NEW -->
+<!ENTITY ldquo "“" ><!-- left double quotation mark, U+201C ISOnum -->
+<!ENTITY rdquo "”" ><!-- right double quotation mark, U+201D ISOnum -->
+<!ENTITY bdquo "„" ><!-- double low-9 quotation mark, U+201E NEW -->
+<!ENTITY dagger "†" ><!-- dagger, U+2020 ISOpub -->
+<!ENTITY Dagger "‡" ><!-- double dagger, U+2021 ISOpub -->
+<!ENTITY permil "‰" ><!-- per mille sign, U+2030 ISOtech -->
+
+<!-- lsaquo is proposed but not yet ISO standardized -->
+<!ENTITY lsaquo "‹" ><!-- single left-pointing angle quotation mark, U+2039 ISO proposed -->
+<!-- rsaquo is proposed but not yet ISO standardized -->
+<!ENTITY rsaquo "›" ><!-- single right-pointing angle quotation mark, U+203A ISO proposed -->
+<!ENTITY euro "€" ><!-- 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 "ƒ" ><!-- latin small f with hook = function
+ = florin, U+0192 ISOtech -->
+
+<!-- Greek -->
+<!ENTITY Alpha "Α" ><!-- greek capital letter alpha, U+0391 -->
+<!ENTITY Beta "Β" ><!-- greek capital letter beta, U+0392 -->
+<!ENTITY Gamma "Γ" ><!-- greek capital letter gamma, U+0393 ISOgrk3 -->
+<!ENTITY Delta "Δ" ><!-- greek capital letter delta, U+0394 ISOgrk3 -->
+<!ENTITY Epsilon "Ε" ><!-- greek capital letter epsilon, U+0395 -->
+<!ENTITY Zeta "Ζ" ><!-- greek capital letter zeta, U+0396 -->
+<!ENTITY Eta "Η" ><!-- greek capital letter eta, U+0397 -->
+<!ENTITY Theta "Θ" ><!-- greek capital letter theta, U+0398 ISOgrk3 -->
+<!ENTITY Iota "Ι" ><!-- greek capital letter iota, U+0399 -->
+<!ENTITY Kappa "Κ" ><!-- greek capital letter kappa, U+039A -->
+<!ENTITY Lambda "Λ" ><!-- greek capital letter lambda, U+039B ISOgrk3 -->
+<!ENTITY Mu "Μ" ><!-- greek capital letter mu, U+039C -->
+<!ENTITY Nu "Ν" ><!-- greek capital letter nu, U+039D -->
+<!ENTITY Xi "Ξ" ><!-- greek capital letter xi, U+039E ISOgrk3 -->
+<!ENTITY Omicron "Ο" ><!-- greek capital letter omicron, U+039F -->
+<!ENTITY Pi "Π" ><!-- greek capital letter pi, U+03A0 ISOgrk3 -->
+<!ENTITY Rho "Ρ" ><!-- greek capital letter rho, U+03A1 -->
+<!-- there is no Sigmaf, and no U+03A2 character either -->
+<!ENTITY Sigma "Σ" ><!-- greek capital letter sigma, U+03A3 ISOgrk3 -->
+<!ENTITY Tau "Τ" ><!-- greek capital letter tau, U+03A4 -->
+<!ENTITY Upsilon "Υ" ><!-- greek capital letter upsilon,
+ U+03A5 ISOgrk3 -->
+<!ENTITY Phi "Φ" ><!-- greek capital letter phi, U+03A6 ISOgrk3 -->
+<!ENTITY Chi "Χ" ><!-- greek capital letter chi, U+03A7 -->
+<!ENTITY Psi "Ψ" ><!-- greek capital letter psi, U+03A8 ISOgrk3 -->
+<!ENTITY Omega "Ω" ><!-- greek capital letter omega, U+03A9 ISOgrk3 -->
+<!ENTITY alpha "α" ><!-- greek small letter alpha, U+03B1 ISOgrk3 -->
+<!ENTITY beta "β" ><!-- greek small letter beta, U+03B2 ISOgrk3 -->
+<!ENTITY gamma "γ" ><!-- greek small letter gamma, U+03B3 ISOgrk3 -->
+<!ENTITY delta "δ" ><!-- greek small letter delta, U+03B4 ISOgrk3 -->
+<!ENTITY epsilon "ε" ><!-- greek small letter epsilon, U+03B5 ISOgrk3 -->
+<!ENTITY zeta "ζ" ><!-- greek small letter zeta, U+03B6 ISOgrk3 -->
+<!ENTITY eta "η" ><!-- greek small letter eta, U+03B7 ISOgrk3 -->
+<!ENTITY theta "θ" ><!-- greek small letter theta, U+03B8 ISOgrk3 -->
+<!ENTITY iota "ι" ><!-- greek small letter iota, U+03B9 ISOgrk3 -->
+<!ENTITY kappa "κ" ><!-- greek small letter kappa, U+03BA ISOgrk3 -->
+<!ENTITY lambda "λ" ><!-- greek small letter lambda, U+03BB ISOgrk3 -->
+<!ENTITY mu "μ" ><!-- greek small letter mu, U+03BC ISOgrk3 -->
+<!ENTITY nu "ν" ><!-- greek small letter nu, U+03BD ISOgrk3 -->
+<!ENTITY xi "ξ" ><!-- greek small letter xi, U+03BE ISOgrk3 -->
+<!ENTITY omicron "ο" ><!-- greek small letter omicron, U+03BF NEW -->
+<!ENTITY pi "π" ><!-- greek small letter pi, U+03C0 ISOgrk3 -->
+<!ENTITY rho "ρ" ><!-- greek small letter rho, U+03C1 ISOgrk3 -->
+<!ENTITY sigmaf "ς" ><!-- greek small letter final sigma, U+03C2 ISOgrk3 -->
+<!ENTITY sigma "σ" ><!-- greek small letter sigma, U+03C3 ISOgrk3 -->
+<!ENTITY tau "τ" ><!-- greek small letter tau, U+03C4 ISOgrk3 -->
+<!ENTITY upsilon "υ" ><!-- greek small letter upsilon, U+03C5 ISOgrk3 -->
+<!ENTITY phi "φ" ><!-- greek small letter phi, U+03C6 ISOgrk3 -->
+<!ENTITY chi "χ" ><!-- greek small letter chi, U+03C7 ISOgrk3 -->
+<!ENTITY psi "ψ" ><!-- greek small letter psi, U+03C8 ISOgrk3 -->
+<!ENTITY omega "ω" ><!-- greek small letter omega, U+03C9 ISOgrk3 -->
+<!ENTITY thetasym "ϑ" ><!-- greek small letter theta symbol, U+03D1 NEW -->
+<!ENTITY upsih "ϒ" ><!-- greek upsilon with hook symbol, U+03D2 NEW -->
+<!ENTITY piv "ϖ" ><!-- greek pi symbol, U+03D6 ISOgrk3 -->
+
+<!-- General Punctuation -->
+<!ENTITY bull "•" ><!-- bullet = black small circle, U+2022 ISOpub -->
+<!-- bullet is NOT the same as bullet operator, U+2219 -->
+<!ENTITY hellip "…" ><!-- horizontal ellipsis = three dot leader, U+2026 ISOpub -->
+<!ENTITY prime "′" ><!-- prime = minutes = feet, U+2032 ISOtech -->
+<!ENTITY Prime "″" ><!-- double prime = seconds = inches, U+2033 ISOtech -->
+<!ENTITY oline "‾" ><!-- overline = spacing overscore, U+203E NEW -->
+<!ENTITY frasl "⁄" ><!-- fraction slash, U+2044 NEW -->
+
+<!-- Letterlike Symbols -->
+<!ENTITY weierp "℘" ><!-- script capital P = power set = Weierstrass p, U+2118 ISOamso -->
+<!ENTITY image "ℑ" ><!-- blackletter capital I = imaginary part, U+2111 ISOamso -->
+<!ENTITY real "ℜ" ><!-- blackletter capital R = real part symbol, U+211C ISOamso -->
+<!ENTITY trade "™" ><!-- trade mark sign, U+2122 ISOnum -->
+<!ENTITY alefsym "ℵ" ><!-- 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 "←" ><!-- leftwards arrow, U+2190 ISOnum -->
+<!ENTITY uarr "↑" ><!-- upwards arrow, U+2191 ISOnum-->
+<!ENTITY rarr "→" ><!-- rightwards arrow, U+2192 ISOnum -->
+<!ENTITY darr "↓" ><!-- downwards arrow, U+2193 ISOnum -->
+<!ENTITY harr "↔" ><!-- left right arrow, U+2194 ISOamsa -->
+<!ENTITY crarr "↵" ><!-- downwards arrow with corner leftwards
+ = carriage return, U+21B5 NEW -->
+<!ENTITY lArr "⇐" ><!-- 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 "⇑" ><!-- upwards double arrow, U+21D1 ISOamsa -->
+<!ENTITY rArr "⇒" ><!-- 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 "⇓" ><!-- downwards double arrow, U+21D3 ISOamsa -->
+<!ENTITY hArr "⇔" ><!-- left right double arrow, U+21D4 ISOamsa -->
+
+<!-- Mathematical Operators -->
+<!ENTITY forall "∀" ><!-- for all, U+2200 ISOtech -->
+<!ENTITY part "∂" ><!-- partial differential, U+2202 ISOtech -->
+<!ENTITY exist "∃" ><!-- there exists, U+2203 ISOtech -->
+<!ENTITY empty "∅" ><!-- empty set = null set, U+2205 ISOamso -->
+<!ENTITY nabla "∇" ><!-- nabla = backward difference, U+2207 ISOtech -->
+<!ENTITY isin "∈" ><!-- element of, U+2208 ISOtech -->
+<!ENTITY notin "∉" ><!-- not an element of, U+2209 ISOtech -->
+<!ENTITY ni "∋" ><!-- contains as member, U+220B ISOtech -->
+<!-- should there be a more memorable name than 'ni'? -->
+<!ENTITY prod "∏" ><!-- 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 "∑" ><!-- 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 "−" ><!-- minus sign, U+2212 ISOtech -->
+<!ENTITY lowast "∗" ><!-- asterisk operator, U+2217 ISOtech -->
+<!ENTITY radic "√" ><!-- square root = radical sign, U+221A ISOtech -->
+<!ENTITY prop "∝" ><!-- proportional to, U+221D ISOtech -->
+<!ENTITY infin "∞" ><!-- infinity, U+221E ISOtech -->
+<!ENTITY ang "∠" ><!-- angle, U+2220 ISOamso -->
+<!ENTITY and "∧" ><!-- logical and = wedge, U+2227 ISOtech -->
+<!ENTITY or "∨" ><!-- logical or = vee, U+2228 ISOtech -->
+<!ENTITY cap "∩" ><!-- intersection = cap, U+2229 ISOtech -->
+<!ENTITY cup "∪" ><!-- union = cup, U+222A ISOtech -->
+<!ENTITY int "∫" ><!-- integral, U+222B ISOtech -->
+<!ENTITY there4 "∴" ><!-- therefore, U+2234 ISOtech -->
+<!ENTITY sim "∼" ><!-- 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 "≅" ><!-- approximately equal to, U+2245 ISOtech -->
+<!ENTITY asymp "≈" ><!-- almost equal to = asymptotic to, U+2248 ISOamsr -->
+<!ENTITY ne "≠" ><!-- not equal to, U+2260 ISOtech -->
+<!ENTITY equiv "≡" ><!-- identical to, U+2261 ISOtech -->
+<!ENTITY le "≤" ><!-- less-than or equal to, U+2264 ISOtech -->
+<!ENTITY ge "≥" ><!-- greater-than or equal to, U+2265 ISOtech -->
+<!ENTITY sub "⊂" ><!-- subset of, U+2282 ISOtech -->
+<!ENTITY sup "⊃" ><!-- 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 "⊄" ><!-- not a subset of, U+2284 ISOamsn -->
+<!ENTITY sube "⊆" ><!-- subset of or equal to, U+2286 ISOtech -->
+<!ENTITY supe "⊇" ><!-- superset of or equal to, U+2287 ISOtech -->
+<!ENTITY oplus "⊕" ><!-- circled plus = direct sum, U+2295 ISOamsb -->
+<!ENTITY otimes "⊗" ><!-- circled times = vector product, U+2297 ISOamsb -->
+<!ENTITY perp "⊥" ><!-- up tack = orthogonal to = perpendicular, U+22A5 ISOtech -->
+<!ENTITY sdot "⋅" ><!-- dot operator, U+22C5 ISOamsb -->
+<!-- dot operator is NOT the same character as U+00B7 middle dot -->
+
+<!-- Miscellaneous Technical -->
+<!ENTITY lceil "⌈" ><!-- left ceiling = apl upstile, U+2308 ISOamsc -->
+<!ENTITY rceil "⌉" ><!-- right ceiling, U+2309 ISOamsc -->
+<!ENTITY lfloor "⌊" ><!-- left floor = apl downstile, U+230A ISOamsc -->
+<!ENTITY rfloor "⌋" ><!-- right floor, U+230B ISOamsc -->
+<!ENTITY lang "〈" ><!-- 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 "〉" ><!-- 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 "◊" ><!-- lozenge, U+25CA ISOpub -->
+
+<!-- Miscellaneous Symbols -->
+<!ENTITY spades "♠" ><!-- black spade suit, U+2660 ISOpub -->
+<!-- black here seems to mean filled as opposed to hollow -->
+<!ENTITY clubs "♣" ><!-- black club suit = shamrock, U+2663 ISOpub -->
+<!ENTITY hearts "♥" ><!-- black heart suit = valentine, U+2665 ISOpub -->
+<!ENTITY diams "♦" ><!-- 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:
+ <schema . . .>
+ . . .
+ <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.
+
+ <type . . .>
+ . . .
+ <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="‰"/>
+ <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="([^\{\}]|\{\{|\}\})*\{([^"'\{\}]|"[^"]*"|'[^']*')+\}([^\{\}]|\{\{|\}\}|\{([^"'\{\}]|"[^"]*"|'[^']*')+\})*"/> -->
+ </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="‰"/>
+ <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 = "&";
+
+ 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("\"", """);
+ }
+}
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("&", "&");
+ s = s.replace("<", "<");
+ s = s.replace(">", ">");
+ 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="&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="&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 ("http://www.w3.org/TR/html4/loose.dtd")"/>
+ </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="&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 "<!–";
+ }
+
+ public String getCommentedBlockCommentSuffix() {
+ return "–>";
+ }
+}
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;}
+}
+
+"<" |
+">" |
+"'" |
+""" |
+" " |
+"&" |
+"&#"{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; }
+
+"<" |
+">" |
+"'" |
+""" |
+" " |
+"&" |
+"&#"{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(" ", " ") + "? · Α </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& ·" +
+ " <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, "\"", """);
+ }
+ 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 = ">";
+ @NonNls private static final String QUOT_ENTITY = """;
+
+ 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, "<");
+ case '\'':
+ return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, "'");
+ case '"':
+ return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, """);
+ case '>':
+ return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, ">");
+ case '&':
+ return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, "&");
+ case '\u00a0':
+ return ASTFactory.leaf(XmlTokenType.XML_CHAR_ENTITY_REF, " ");
+
+ 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("<");
+ result.append(tag.getName());
+ final XmlAttribute[] attributes = tag.getAttributes();
+ for (final XmlAttribute each : attributes) {
+ result.append(" ").append(each.getText());
+ }
+
+ if (tag.isEmpty()) {
+ result.append("/>");
+ }
+ else {
+ result.append(">...</").append(tag.getName()).append(">");
+ }
+
+ 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 = "&";
+ @NonNls
+ private static final String LT_ENTITY_REFERENCE = "<";
+
+ 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("<")) {
+ return "<";
+ }
+ if (text.equals(">")) {
+ return ">";
+ }
+ if (text.equals(" ")) {
+ return "\u00a0";
+ }
+ if (text.equals("&")) {
+ return "&";
+ }
+ if (text.equals("'")) {
+ return "'";
+ }
+ if (text.equals(""")) {
+ return "\"";
+ }
+ if (text.startsWith(""") && text.endsWith(""")) {
+ 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 = ": ";
+ @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("'","'").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"> <a href="elements.html">previous</a>
+ <a href="list.html">next</a> <a href="../cover.html#minitoc">
+contents</a> <a href="elements.html">elements</a> <a href=
+"list.html">index</a>
+
+<hr></div>
+
+<h1 align="center">Index of Attributes<a name="h-3"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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"> </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."> </td>
+<td align="center" title="DTD"> </td>
+<td align="center" title="Comment"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </td>
+<td align="center" title="Comment"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </td>
+<td align="center" title="Comment"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </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."> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </td>
+<td align="center" title="Comment"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </td>
+<td align="center" title="Comment"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </td>
+<td align="center" title="Comment"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </td>
+<td align="center" title="Comment"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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"> </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."> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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."> </td>
+<td align="center" title="DTD"> </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"> </td>
+</tr>
+</table>
+
+<div class="navbar" align="center">
+<hr><a href="elements.html">previous</a> <a href="list.html">next</a>
+ <a href="../cover.html#minitoc">contents</a> <a href=
+"elements.html">elements</a> <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"> <a href="../references.html">
+previous</a> <a href="attributes.html">next</a> <a href=
+"../cover.html#minitoc">contents</a> <a href="attributes.html">
+attributes</a> <a href="list.html">index</a>
+
+<hr></div>
+
+<h1 align="center">Index of Elements<a name="h-2"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </td>
+<td align="center" title="Description"> </td>
+</tr>
+
+<tr>
+<td title="Name"><a href="../struct/global.html#edef-ADDRESS">ADDRESS</a></td>
+<td align="center" title="Start Tag"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">F</td>
+<td align="center" title="Empty">E</td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </td>
+<td align="center" title="Description"> </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"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag">O</td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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"> </td>
+<td align="center" title="End Tag"> </td>
+<td align="center" title="Empty"> </td>
+<td align="center" title="Depr."> </td>
+<td align="center" title="DTD"> </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> <a href="attributes.html">
+next</a> <a href="../cover.html#minitoc">contents</a> <a href=
+"attributes.html">attributes</a> <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/"/"/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] =~ / / ) {
+ 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="+1", size="4""
+ 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>
+