Skip to content

Commit

Permalink
Disable XSD validation when xsi:schemaLocation doesn't declare the
Browse files Browse the repository at this point in the history
namespace for the document element root.

See #951

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Jan 5, 2021
1 parent c1f855c commit df229d2
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + //
"<setup:Configuration \r\n" + //
" xmi:version=\"2.0\"\r\n" + //
" xmlns:xmi=\"http://www.omg.org/XMI\"\r\n" + //
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \r\n" + //
" xmlns:setup=\"http://www.eclipse.org/oomph/setup/1.0\"\r\n" + //
" xmlns:setup.p2=\"http://www.eclipse.org/oomph/setup/p2/1.0\"\r\n" + //
" xmlns:workbench=\"http://www.eclipse.org/oomph/setup/workbench/1.0\"\r\n" + //
" xsi:schemaLocation=\"http://www.eclipse.org/oomph/setup/workbench/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Workbench.ecore\"\r\n"
+ //
" label=\"Gael Eclipse Installation\"> \r\n" + //
" <installation name=\"com.github.glhez.eclipse.install\" label=\"Gael Eclipse Installation Installation\">\r\n"
+ //
" <setupTask xsi:type=\"setup.p2:P2Task\" label=\"Oomph Setup Task\">\r\n" + //
" <requirement name=\"org.eclipse.oomph.setup.feature.group\"/>\r\n" + //
" <repository url=\"${oomph.update.url}\"/>\r\n" + //
" </setupTask> \r\n" + //
" </installation>\r\n" + //
"</setup:Configuration>";
XMLAssert.testDiagnosticsFor(xml);
}

private static void testDiagnosticsFor(String xml, Diagnostic... expected) {
XMLAssert.testDiagnosticsFor(xml, "src/test/resources/catalogs/catalog.xml", expected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,16 @@ public void schemaWithUrlInvalidPathWithNamespace() throws Exception {

String fileURI = "test.xml";
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + //
"<invoice xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n" + //
" xsi:schemaLocation=\"http://invoice.xsd\">\r\n" + //
"</invoice> \r\n" + //
"";
"<invoice xmlns=\"http://invoice.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n" + //
" xsi:schemaLocation=\"http://invoice.xsd http://invoice.xsd http://invoice2.xsd\">\r\n" + //
"</invoice>";
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 <xsd:schema>.",
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")));
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.",
Expand Down

0 comments on commit df229d2

Please sign in to comment.