diff --git a/README.md b/README.md
index 3e2cf6ad7..5eaea5e7b 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@ Continue reading the **full documentation** at http://phax.github.io/ph-schematr
* Improved support for `base-uri()` XPath function when using the pure implementation (#47)
* Fixed issue with `role` attribute in SVRL when using pure implementation (#54)
* Updated to Saxon-HE 9.8.0-6
+ * Added ANT task property `failOnError` (#57)
* v4.3.4 - 2017-07-27
* Added new class `SchematronDebug` that centrally manages the debug flags for logging etc.
* v4.3.3 - 2017-07-27
@@ -211,6 +212,7 @@ The `schematron` element allows for the following attributes:
* `String` **phaseName** - The optional Schematron phase to be used. Note: this is only available when using the processing engine `pure` or `schematron`. For engine `xslt` this is not available because this was defined when the XSLT was created.
* `String` **languageCode** - The optional language code to be used. Note: this is only available when using the processing engine `schematron`. For engine `xslt` this is not available because this was defined when the XSLT was created. Default is English (en). Supported language codes are: cs, de, en, fr, nl.
* `boolean` **expectSuccess** - `true` to expect successful validation, `false` to expect validation errors. If the expectation is incorrect, the build will fail.
+ * `boolean` **failOnError** (since v5.0.0) - `true` to break the build if an error occurred, `false` to continue with the following tasks on error.
Additionally you can use an `XMLCatalog` that acts as an Entity and URI resolver both for the Schematron and the XML files to be validated! See https://ant.apache.org/manual/Types/xmlcatalog.html for details on the XML catalog. Here is an example that shows how to use an inline XML catalog:
@@ -263,6 +265,7 @@ The `schematron` element allows for the following attributes:
* `boolean` **keepDiagnostics** - `true` to keep `<diagnostic>`-elements, `false` to delete them. Default is `false`.
* `boolean` **keepReports** - `true` to keep `<report>`-elements, `false` to change them to `<assert>`-elements. Default is `false`.
* `boolean` **keepEmptyPatterns** - `true` to keep `<pattern>`-elements without rules, `false` to delete them. Default is `true`.
+ * `boolean` **failOnError** - `true` to break the build if an error occurred, `false` to continue with the following tasks on error.
---
diff --git a/ph-schematron-ant-task/src/main/java/com/helger/schematron/ant/Schematron.java b/ph-schematron-ant-task/src/main/java/com/helger/schematron/ant/Schematron.java
index ac547eef4..4af12450e 100644
--- a/ph-schematron-ant-task/src/main/java/com/helger/schematron/ant/Schematron.java
+++ b/ph-schematron-ant-task/src/main/java/com/helger/schematron/ant/Schematron.java
@@ -111,10 +111,16 @@ public class Schematron extends Task
/**
* true
if the XMLs are supposed to be valid, false
- * otherwise.
+ * otherwise. Defaults to true
.
*/
private boolean m_bExpectSuccess = true;
+ /**
+ * true
if the build should fail if any error occurs. Defaults to
+ * true
. Since v5.0.0.
+ */
+ private boolean m_bFailOnError = true;
+
/**
* For resolving entities such as DTDs. This is used both for the Schematron
* file as well as for the XML files to be validated.
@@ -188,6 +194,13 @@ public void setExpectSuccess (final boolean bExpectSuccess)
Project.MSG_DEBUG);
}
+ public void setFailOnError (final boolean bFailOnError)
+ {
+ m_bFailOnError = bFailOnError;
+
+ log (bFailOnError ? "Will fail on error" : "Will not fail on error", Project.MSG_DEBUG);
+ }
+
/**
* Add the catalog to our internal catalog
*
@@ -238,6 +251,18 @@ private static File _getKeyFile (final File f)
return f != null ? f : NULL_FILE_PLACEHOLDER;
}
+ private void _buildError (@Nonnull final String sMsg)
+ {
+ _buildError (sMsg, null);
+ }
+
+ private void _buildError (@Nonnull final String sMsg, @Nullable final Throwable t)
+ {
+ if (m_bFailOnError)
+ throw new BuildException (sMsg, t);
+ log (sMsg, t, Project.MSG_ERR);
+ }
+
private void _performValidation (@Nonnull final ISchematronResource aSch,
@Nonnull final ICommonsList aResCollections,
@Nullable final File aSVRLDirectory,
@@ -248,35 +273,38 @@ private void _performValidation (@Nonnull final ISchematronResource aSch,
for (final ResourceCollection aResCollection : aResCollections)
{
if (!aResCollection.isFilesystemOnly ())
- throw new BuildException ("Only FileSystem resources are supported.");
-
- for (final Resource aRes : aResCollection)
- {
- if (!aRes.isExists ())
- throw new BuildException ("Could not find resource " + aRes.toLongString () + " to copy.");
-
- File baseDir = NULL_FILE_PLACEHOLDER;
- String name = aRes.getName ();
- final FileProvider fp = aRes.as (FileProvider.class);
- if (fp != null)
+ _buildError ("Only FileSystem resources are supported.");
+ else
+ for (final Resource aRes : aResCollection)
{
- final FileResource fr = ResourceUtils.asFileResource (fp);
- baseDir = _getKeyFile (fr.getBaseDir ());
- if (baseDir == NULL_FILE_PLACEHOLDER)
- name = fr.getFile ().getAbsolutePath ();
- }
+ if (!aRes.isExists ())
+ {
+ _buildError ("Could not find resource " + aRes.toLongString () + " to copy.");
+ continue;
+ }
- if ((aRes.isDirectory () || fp != null) && name != null)
- {
- final DirectoryData aBaseDir = aFiles.computeIfAbsent (_getKeyFile (baseDir), k -> new DirectoryData (k));
- if (aRes.isDirectory ())
- aBaseDir.addDir (name);
+ File baseDir = NULL_FILE_PLACEHOLDER;
+ String name = aRes.getName ();
+ final FileProvider fp = aRes.as (FileProvider.class);
+ if (fp != null)
+ {
+ final FileResource fr = ResourceUtils.asFileResource (fp);
+ baseDir = _getKeyFile (fr.getBaseDir ());
+ if (baseDir == NULL_FILE_PLACEHOLDER)
+ name = fr.getFile ().getAbsolutePath ();
+ }
+
+ if ((aRes.isDirectory () || fp != null) && name != null)
+ {
+ final DirectoryData aBaseDir = aFiles.computeIfAbsent (_getKeyFile (baseDir), k -> new DirectoryData (k));
+ if (aRes.isDirectory ())
+ aBaseDir.addDir (name);
+ else
+ aBaseDir.addFile (name);
+ }
else
- aBaseDir.addFile (name);
+ _buildError ("Could not resolve resource " + aRes.toLongString () + " to a file.");
}
- else
- throw new BuildException ("Could not resolve resource " + aRes.toLongString () + " to a file.");
- }
}
for (final DirectoryData aBaseDir : aFiles.values ())
@@ -350,10 +378,12 @@ private void _performValidation (@Nonnull final ISchematronResource aSch,
for (final AbstractSVRLMessage aMsg : aMessages)
{
- log (ErrorTextProvider.DEFAULT.getErrorText (aMsg.getAsResourceError (aXMLFile.getPath ()), Locale.US),
+ log (ErrorTextProvider.DEFAULT.getErrorText (aMsg.getAsResourceError (aXMLFile.getPath ()),
+ Locale.US),
aMsg.getFlag ().isError () ? Project.MSG_ERR : Project.MSG_WARN);
}
- throw new BuildException (sMessage);
+ _buildError (sMessage);
+ continue;
}
// Success as expected
@@ -375,7 +405,8 @@ private void _performValidation (@Nonnull final ISchematronResource aSch,
sMessage += " - only " + sWarnings + " are contained";
log (sMessage, Project.MSG_ERR);
- throw new BuildException (sMessage);
+ _buildError (sMessage);
+ continue;
}
// Success as expected
@@ -405,7 +436,8 @@ private void _performValidation (@Nonnull final ISchematronResource aSch,
" - " +
ex.getMessage ();
log (sMessage, ex, Project.MSG_DEBUG);
- throw new BuildException (sMessage, ex);
+ _buildError (sMessage, ex);
+ continue;
}
}
}
@@ -415,98 +447,111 @@ private void _performValidation (@Nonnull final ISchematronResource aSch,
@Override
public void execute () throws BuildException
{
+ boolean bCanRun = false;
if (m_aSchematronFile == null)
- throw new BuildException ("No Schematron file specified!");
- if (m_aSchematronFile.exists () && !m_aSchematronFile.isFile ())
- throw new BuildException ("The specified Schematron file " + m_aSchematronFile + " is not a file!");
- if (m_eSchematronProcessingEngine == null)
- throw new BuildException ("An invalid Schematron processing instance is specified! Only one of the following values is allowed: " +
- StringHelper.getImplodedMapped (", ",
- ESchematronMode.values (),
- x -> "'" + x.getID () + "'"));
- if (m_aResCollections.isEmpty ())
- throw new BuildException ("No XML resources to be validated specified! Add e.g. a element.");
-
- if (m_aSvrlDirectory != null)
- {
- if (!m_aSvrlDirectory.exists () && !m_aSvrlDirectory.mkdirs ())
- throw new BuildException ("Failed to create the SVRL directory " + m_aSvrlDirectory);
- }
+ _buildError ("No Schematron file specified!");
+ else
+ if (m_aSchematronFile.exists () && !m_aSchematronFile.isFile ())
+ _buildError ("The specified Schematron file " + m_aSchematronFile + " is not a file!");
+ else
+ if (m_eSchematronProcessingEngine == null)
+ _buildError ("An invalid Schematron processing instance is specified! Only one of the following values is allowed: " +
+ StringHelper.getImplodedMapped (", ", ESchematronMode.values (), x -> "'" + x.getID () + "'"));
+ else
+ if (m_aResCollections.isEmpty ())
+ _buildError ("No XML resources to be validated specified! Add e.g. a element.");
+ else
+ if (m_aSvrlDirectory != null)
+ {
+ if (!m_aSvrlDirectory.exists () && !m_aSvrlDirectory.mkdirs ())
+ _buildError ("Failed to create the SVRL directory " + m_aSvrlDirectory);
+ }
+ else
+ bCanRun = true;
- // 1. Parse Schematron file
- final Locale aDisplayLocale = Locale.US;
- ISchematronResource aSch;
- IErrorList aSCHErrors;
- switch (m_eSchematronProcessingEngine)
+ if (bCanRun)
{
- case PURE:
- {
- // pure
- final CollectingPSErrorHandler aErrorHdl = new CollectingPSErrorHandler ();
- final SchematronResourcePure aRealSCH = new SchematronResourcePure (new FileSystemResource (m_aSchematronFile));
- aRealSCH.setPhase (m_sPhaseName);
- aRealSCH.setErrorHandler (aErrorHdl);
- aRealSCH.setEntityResolver (getEntityResolver ());
- aRealSCH.validateCompletely ();
-
- aSch = aRealSCH;
- aSCHErrors = aErrorHdl.getAllErrors ();
- break;
- }
- case SCHEMATRON:
+ // 1. Parse Schematron file
+ final Locale aDisplayLocale = Locale.US;
+ ISchematronResource aSch = null;
+ IErrorList aSCHErrors = null;
+ switch (m_eSchematronProcessingEngine)
{
- // SCH
- final CollectingTransformErrorListener aErrorHdl = new CollectingTransformErrorListener ();
- final SchematronResourceSCH aRealSCH = new SchematronResourceSCH (new FileSystemResource (m_aSchematronFile));
- aRealSCH.setPhase (m_sPhaseName);
- aRealSCH.setLanguageCode (m_sLanguageCode);
- aRealSCH.setErrorListener (aErrorHdl);
- aRealSCH.setURIResolver (getURIResolver ());
- aRealSCH.setEntityResolver (getEntityResolver ());
- aRealSCH.isValidSchematron ();
-
- aSch = aRealSCH;
- aSCHErrors = aErrorHdl.getErrorList ();
- break;
+ case PURE:
+ {
+ // pure
+ final CollectingPSErrorHandler aErrorHdl = new CollectingPSErrorHandler ();
+ final SchematronResourcePure aRealSCH = new SchematronResourcePure (new FileSystemResource (m_aSchematronFile));
+ aRealSCH.setPhase (m_sPhaseName);
+ aRealSCH.setErrorHandler (aErrorHdl);
+ aRealSCH.setEntityResolver (getEntityResolver ());
+ aRealSCH.validateCompletely ();
+
+ aSch = aRealSCH;
+ aSCHErrors = aErrorHdl.getAllErrors ();
+ break;
+ }
+ case SCHEMATRON:
+ {
+ // SCH
+ final CollectingTransformErrorListener aErrorHdl = new CollectingTransformErrorListener ();
+ final SchematronResourceSCH aRealSCH = new SchematronResourceSCH (new FileSystemResource (m_aSchematronFile));
+ aRealSCH.setPhase (m_sPhaseName);
+ aRealSCH.setLanguageCode (m_sLanguageCode);
+ aRealSCH.setErrorListener (aErrorHdl);
+ aRealSCH.setURIResolver (getURIResolver ());
+ aRealSCH.setEntityResolver (getEntityResolver ());
+ aRealSCH.isValidSchematron ();
+
+ aSch = aRealSCH;
+ aSCHErrors = aErrorHdl.getErrorList ();
+ break;
+ }
+ case XSLT:
+ {
+ // SCH
+ final CollectingTransformErrorListener aErrorHdl = new CollectingTransformErrorListener ();
+ final SchematronResourceXSLT aRealSCH = new SchematronResourceXSLT (new FileSystemResource (m_aSchematronFile));
+ // phase and language are ignored because this was decided when the
+ // XSLT
+ // was created
+ aRealSCH.setErrorListener (aErrorHdl);
+ aRealSCH.setURIResolver (getURIResolver ());
+ aRealSCH.setEntityResolver (getEntityResolver ());
+ aRealSCH.isValidSchematron ();
+
+ aSch = aRealSCH;
+ aSCHErrors = aErrorHdl.getErrorList ();
+ break;
+ }
+ default:
+ _buildError ("No handler for processing engine '" + m_eSchematronProcessingEngine + "'");
+ break;
}
- case XSLT:
+ if (aSCHErrors != null)
{
- // SCH
- final CollectingTransformErrorListener aErrorHdl = new CollectingTransformErrorListener ();
- final SchematronResourceXSLT aRealSCH = new SchematronResourceXSLT (new FileSystemResource (m_aSchematronFile));
- // phase and language are ignored because this was decided when the XSLT
- // was created
- aRealSCH.setErrorListener (aErrorHdl);
- aRealSCH.setURIResolver (getURIResolver ());
- aRealSCH.setEntityResolver (getEntityResolver ());
- aRealSCH.isValidSchematron ();
-
- aSch = aRealSCH;
- aSCHErrors = aErrorHdl.getErrorList ();
- break;
- }
- default:
- throw new BuildException ("No handler for processing engine '" + m_eSchematronProcessingEngine + "'");
- }
- if (aSCHErrors != null)
- {
- // Error validating the Schematrons!!
- boolean bAnyError = false;
- for (final IError aError : aSCHErrors)
- if (aError.getErrorLevel ().isGE (EErrorLevel.ERROR))
+ // Error validating the Schematrons!!
+ boolean bAnyParsingError = false;
+ for (final IError aError : aSCHErrors)
+ if (aError.getErrorLevel ().isGE (EErrorLevel.ERROR))
+ {
+ log ("Error in Schematron: " + aError.getAsString (aDisplayLocale), Project.MSG_ERR);
+ bAnyParsingError = true;
+ }
+ else
+ if (aError.getErrorLevel ().isGE (EErrorLevel.WARN))
+ log ("Warning in Schematron: " + aError.getAsString (aDisplayLocale), Project.MSG_WARN);
+
+ if (bAnyParsingError)
+ _buildError ("The provided Schematron file contains errors. See log for details.");
+ else
{
- log ("Error in Schematron: " + aError.getAsString (aDisplayLocale), Project.MSG_ERR);
- bAnyError = true;
+ log ("Successfully parsed Schematron file '" + m_aSchematronFile.getPath () + "'", Project.MSG_INFO);
+
+ // 2. for all XML files that match the pattern
+ _performValidation (aSch, m_aResCollections, m_aSvrlDirectory, m_bExpectSuccess);
}
- else
- if (aError.getErrorLevel ().isGE (EErrorLevel.WARN))
- log ("Warning in Schematron: " + aError.getAsString (aDisplayLocale), Project.MSG_WARN);
- if (bAnyError)
- throw new BuildException ("The provided Schematron file contains errors. See log for details.");
+ }
}
- log ("Successfully parsed Schematron file '" + m_aSchematronFile.getPath () + "'", Project.MSG_INFO);
-
- // 2. for all XML files that match the pattern
- _performValidation (aSch, m_aResCollections, m_aSvrlDirectory, m_bExpectSuccess);
}
}
diff --git a/ph-schematron-ant-task/src/main/java/com/helger/schematron/ant/SchematronPreprocess.java b/ph-schematron-ant-task/src/main/java/com/helger/schematron/ant/SchematronPreprocess.java
index f45053bf2..3fcfbd44e 100644
--- a/ph-schematron-ant-task/src/main/java/com/helger/schematron/ant/SchematronPreprocess.java
+++ b/ph-schematron-ant-task/src/main/java/com/helger/schematron/ant/SchematronPreprocess.java
@@ -19,6 +19,7 @@
import java.io.File;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
@@ -79,6 +80,12 @@ public class SchematronPreprocess extends Task
*/
private boolean m_bKeepEmptyPatterns = PSPreprocessor.DEFAULT_KEEP_EMPTY_PATTERNS;
+ /**
+ * true
if the build should fail if any error occurs. Defaults to
+ * true
.
+ */
+ private boolean m_bFailOnError = true;
+
public SchematronPreprocess ()
{}
@@ -124,42 +131,68 @@ public void setKeepEmptyPatterns (final boolean bKeepEmptyPatterns)
Project.MSG_DEBUG);
}
+ public void setFailOnError (final boolean bFailOnError)
+ {
+ m_bFailOnError = bFailOnError;
+
+ log (bFailOnError ? "Will fail on error" : "Will not fail on error", Project.MSG_DEBUG);
+ }
+
+ private void _buildError (@Nonnull final String sMsg)
+ {
+ _buildError (sMsg, null);
+ }
+
+ private void _buildError (@Nonnull final String sMsg, @Nullable final Throwable t)
+ {
+ if (m_bFailOnError)
+ throw new BuildException (sMsg, t);
+ log (sMsg, t, Project.MSG_ERR);
+ }
+
@Override
public void execute () throws BuildException
{
+ boolean bCanRun = false;
if (m_aSrcFile == null)
- throw new BuildException ("No source Schematron file specified!");
- if (m_aSrcFile.exists () && !m_aSrcFile.isFile ())
- throw new BuildException ("The specified source Schematron file " + m_aSrcFile + " is not a file!");
- if (m_aDstFile == null)
- throw new BuildException ("No destination Schematron file specified!");
- if (m_aDstFile.exists () && !m_aDstFile.isFile ())
- throw new BuildException ("The specified destination Schematron file " + m_aDstFile + " is not a file!");
-
- try
- {
- // Read source
- final PSSchema aSchema = new PSReader (new FileSystemResource (m_aSrcFile)).readSchema ();
-
- // Setup preprocessor
- final PSPreprocessor aPreprocessor = new PSPreprocessor (PSXPathQueryBinding.getInstance ());
- aPreprocessor.setKeepTitles (m_bKeepTitles);
- aPreprocessor.setKeepDiagnostics (m_bKeepDiagnostics);
- aPreprocessor.setKeepReports (m_bKeepReports);
- aPreprocessor.setKeepEmptyPatterns (m_bKeepEmptyPatterns);
- aPreprocessor.setKeepEmptySchema (true);
-
- // Main pre-processing
- final PSSchema aPreprocessedSchema = aPreprocessor.getAsPreprocessedSchema (aSchema);
-
- // Write the result file
- new PSWriter (new PSWriterSettings ().setXMLWriterSettings (new XMLWriterSettings ())).writeToFile (aPreprocessedSchema,
- m_aDstFile);
- log ("Successfully pre-processed Schematron " + m_aSrcFile + " to " + m_aDstFile);
- }
- catch (final SchematronReadException | SchematronPreprocessException ex)
- {
- throw new BuildException (ex);
- }
+ _buildError ("No source Schematron file specified!");
+ else
+ if (m_aSrcFile.exists () && !m_aSrcFile.isFile ())
+ _buildError ("The specified source Schematron file " + m_aSrcFile + " is not a file!");
+ else
+ if (m_aDstFile == null)
+ _buildError ("No destination Schematron file specified!");
+ else
+ if (m_aDstFile.exists () && !m_aDstFile.isFile ())
+ _buildError ("The specified destination Schematron file " + m_aDstFile + " is not a file!");
+ else
+ bCanRun = true;
+
+ if (bCanRun)
+ try
+ {
+ // Read source
+ final PSSchema aSchema = new PSReader (new FileSystemResource (m_aSrcFile)).readSchema ();
+
+ // Setup preprocessor
+ final PSPreprocessor aPreprocessor = new PSPreprocessor (PSXPathQueryBinding.getInstance ());
+ aPreprocessor.setKeepTitles (m_bKeepTitles);
+ aPreprocessor.setKeepDiagnostics (m_bKeepDiagnostics);
+ aPreprocessor.setKeepReports (m_bKeepReports);
+ aPreprocessor.setKeepEmptyPatterns (m_bKeepEmptyPatterns);
+ aPreprocessor.setKeepEmptySchema (true);
+
+ // Main pre-processing
+ final PSSchema aPreprocessedSchema = aPreprocessor.getAsPreprocessedSchema (aSchema);
+
+ // Write the result file
+ new PSWriter (new PSWriterSettings ().setXMLWriterSettings (new XMLWriterSettings ())).writeToFile (aPreprocessedSchema,
+ m_aDstFile);
+ log ("Successfully pre-processed Schematron " + m_aSrcFile + " to " + m_aDstFile);
+ }
+ catch (final SchematronReadException | SchematronPreprocessException ex)
+ {
+ _buildError ("Error processing Schemtron " + m_aSrcFile.getAbsolutePath (), ex);
+ }
}
}