diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java
index 6bde7f2f2a..7db972ca87 100644
--- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java
+++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java
@@ -28,6 +28,7 @@
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.dom.DOMDocumentType;
import org.eclipse.lemminx.dom.DOMElement;
+import org.eclipse.lemminx.dom.SchemaLocationHint;
import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager;
import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSyntaxErrorCode;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationSettings;
@@ -82,8 +83,8 @@ public static void doDiagnostics(DOMDocument document, XMLEntityResolver entityR
// Add LSP content handler to stop XML parsing if monitor is canceled.
parser.setContentHandler(new LSPContentHandler(monitor));
- boolean hasSchemaGrammar = document.hasSchemaLocation() || document.hasNoNamespaceSchemaLocation()
- || hasExternalSchemaGrammar(document);
+ boolean hasSchemaGrammar = isValidSchemaLocationForDocumentElement(document)
+ || document.hasNoNamespaceSchemaLocation() || hasExternalSchemaGrammar(document);
boolean hasGrammar = document.hasDTD() || hasSchemaGrammar || document.hasExternalGrammar();
// If diagnostics for Schema preference is enabled
if ((validationSettings == null) || validationSettings.isSchema()) {
@@ -114,6 +115,26 @@ public static void doDiagnostics(DOMDocument document, XMLEntityResolver entityR
}
}
+ /**
+ * Returns true if the given DOM document declares a xsi:schemaLocation hint for
+ * the document element and false otherwise.
+ *
+ * @param document the DOM document.
+ * @return true if the given DOM document declares a xsi:schemaLocation hint for
+ * the document element and false otherwise.
+ */
+ private static boolean isValidSchemaLocationForDocumentElement(DOMDocument document) {
+ if (!document.hasSchemaLocation()) {
+ return false;
+ }
+ String namespaceURI = document.getNamespaceURI();
+ SchemaLocationHint hint = document.getSchemaLocation().getLocationHint(namespaceURI);
+ if (hint == null) {
+ return false;
+ }
+ return true;
+ }
+
private static boolean hasExternalSchemaGrammar(DOMDocument document) {
if (document.getExternalGrammarFromNamespaceURI() != null) {
return true;
diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaDiagnosticsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaDiagnosticsTest.java
index 0872e7570b..b62e06fad4 100644
--- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaDiagnosticsTest.java
+++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaDiagnosticsTest.java
@@ -1026,6 +1026,32 @@ public void diagnosticsWithCatalogAndXSDInclude() throws BadLocationException {
Diagnostic diagnostic = d(1, 2, 1, 6, XMLSchemaErrorCode.cvc_complex_type_2_4_b);
XMLAssert.testDiagnosticsFor(xml, "src/test/resources/catalogs/include/catalog-include.xml", diagnostic);
}
+
+ @Test
+ public void noHintSchemaLocationForRootElement() {
+ // Here the xsi:schemaLocation doens't declare the hint for
+ // http://www.eclipse.org/oomph/setup/1.0 (used in the root element)
+ String xml = "\r\n" + //
+ " \r\n" + //
+ " \r\n"
+ + //
+ " \r\n" + //
+ " \r\n" + //
+ " \r\n" + //
+ " \r\n" + //
+ " \r\n" + //
+ "";
+ XMLAssert.testDiagnosticsFor(xml);
+ }
private static void testDiagnosticsFor(String xml, Diagnostic... expected) {
XMLAssert.testDiagnosticsFor(xml, "src/test/resources/catalogs/catalog.xml", expected);
diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaPublishDiagnosticsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaPublishDiagnosticsTest.java
index 68a6c3d5eb..4ef5cda9ff 100644
--- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaPublishDiagnosticsTest.java
+++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaPublishDiagnosticsTest.java
@@ -108,14 +108,16 @@ public void schemaWithUrlInvalidPathWithNamespace() throws Exception {
String fileURI = "test.xml";
String xml = "\r\n" + //
- "\r\n" + //
- " \r\n" + //
- "";
+ "\r\n" + //
+ "";
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, configuration, pd(fileURI, //
- new Diagnostic(r(2, 20, 2, 40),
- "SchemaLocation: schemaLocation value = 'http://invoice.xsd' must have even number of URI's.",
+ new Diagnostic(r(2, 20, 2, 79),
+ "SchemaLocation: schemaLocation value = 'http://invoice.xsd http://invoice.xsd http://invoice2.xsd' must have even number of URI's.",
DiagnosticSeverity.Warning, "xml", "SchemaLocation"), //
+ new Diagnostic(r(2, 40, 2, 58),
+ "schema_reference.4: Failed to read schema document 'http://invoice.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not .",
+ DiagnosticSeverity.Warning, "xml", "schema_reference.4"), //
new Diagnostic(r(1, 1, 1, 8), "cvc-elt.1.a: Cannot find the declaration of element 'invoice'.",
DiagnosticSeverity.Error, "xml", "cvc-elt.1.a")));
}
@@ -148,8 +150,10 @@ public void schemaWithUrlWithCache() throws Exception {
pd(fileURI,
new Diagnostic(r(1, 1, 1, 8), "The resource 'http://invoice.xsd' is downloading.",
DiagnosticSeverity.Information, "xml")),
- pd(fileURI, new Diagnostic(r(1, 1, 1, 8), "Error while downloading 'http://invoice.xsd' to "+expectedLocation+".",
- DiagnosticSeverity.Error, "xml")));
+ pd(fileURI,
+ new Diagnostic(r(1, 1, 1, 8),
+ "Error while downloading 'http://invoice.xsd' to " + expectedLocation + ".",
+ DiagnosticSeverity.Error, "xml")));
}
@Test
@@ -187,7 +191,7 @@ public void schemaWithUrlWithCacheAndWithCatalog() throws Exception {
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, configuration, pd(fileURI, //
new Diagnostic(r(3, 8, 3, 26),
- "Content of type 'date' is expected.\n\nThe following content is not a valid type:\n '2017-11-30_INVALID'\n\nCode:",
+ "Content of type 'date' is expected.\n\nThe following content is not a valid type:\n '2017-11-30_INVALID'\n\nCode:",
DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.cvc_datatype_valid_1_2_1.getCode()), //
new Diagnostic(r(3, 8, 3, 26),
"cvc-type.3.1.3: The value '2017-11-30_INVALID' of element 'date' is not valid.",