Browse Source

Add ability to set parser features in <xmlvalidate>.

Submitted by:	Nick Pellow <nick.pellow at mindmatics.de>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@273345 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 23 years ago
parent
commit
9b7f00ab24
4 changed files with 171 additions and 43 deletions
  1. +39
    -4
      docs/manual/OptionalTasks/xmlvalidate.html
  2. +19
    -15
      src/etc/testcases/taskdefs/optional/xmlvalidate.xml
  3. +96
    -24
      src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
  4. +17
    -0
      src/testcases/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java

+ 39
- 4
docs/manual/OptionalTasks/xmlvalidate.html View File

@@ -14,9 +14,11 @@ task uses the SAX2 parser implementation provided by JAXP by default
(probably the one that is used by Ant itself), but one can specify any (probably the one that is used by Ant itself), but one can specify any
SAX1/2 parser if needed.</p> SAX1/2 parser if needed.</p>


<p>This task supports the use of nested <a
href="../CoreTypes/xmlcatalog.html">xmlcatalog</a> elements and/or nested
<tt>&lt;dtd&gt;</tt> elements which are used to resolve DTDs and entities.</p>
<p>This task supports the use of nested
<li/><a href="../CoreTypes/xmlcatalog.html"><tt>&lt;xmlcatalog&gt;</tt></a> elements
<li/><tt>&lt;dtd&gt;</tt> elements which are used to resolve DTDs and entities.
<li/><tt>&lt;attribute&gt;</tt> elements which are used to set features on the parser. These can be any number of <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description">http://xml.org/sax/features/</a> or other features that your parser may support.
</p>


<h3>Parameters</h3> <h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0"> <table border="1" cellpadding="2" cellspacing="0">
@@ -84,6 +86,30 @@ href="../CoreTypes/xmlcatalog.html">xmlcatalog</a> elements and/or nested
<h4>xmlcatalog</h4> <h4>xmlcatalog</h4>
<p>The <a href="../CoreTypes/xmlcatalog.html">xmlcatalog</a> <p>The <a href="../CoreTypes/xmlcatalog.html">xmlcatalog</a>
element is used to perform Entity resolution.</p> element is used to perform Entity resolution.</p>
<h4>attribute</h4>
<p>The attribute element is used to set SAX Parser features.
There can an arbitrary amount of attribute set as defined here:
<a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description">http://xml.org/sax/features/</a>
A feature essentialy changes the mode of the parser.
&lt;attribute&gt; an attribute is used to set specific features on the parser.
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td width="12%" valign="top"><b>Attribute</b></td>
<td width="78%" valign="top"><b>Description</b></td>
<td width="10%" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">name</td>
<td valign="top">The name of the feature</td>
<td align="center" valign="top">Yes</td>
</tr>
<tr>
<td valign="top">value</td>
<td valign="top">The boolean value of the feature</td>
<td align="center" valign="top">Yes</td>
</tr>
</table>
</p>




<h3>Examples</h3> <h3>Examples</h3>
@@ -128,8 +154,17 @@ Scan all XML files in the project, using a predefined catalog to map URIs to loc
&lt;/xmlvalidate&gt; &lt;/xmlvalidate&gt;
</pre> </pre>
Scan all XML files in the project, using the catalog defined inline. Scan all XML files in the project, using the catalog defined inline.
<hr>


<pre>
&lt;xmlvalidate failonerror="yes" lenient="no" warn="yes"&gt;
&lt;fileset dir="xml" includes="**/*.xml"/&gt;
&lt;attribute name="http://xml.org/sax/features/validation" value="true"/&gt;
&lt;attribute name="http://apache.org/xml/features/validation/schema" value="true"/&gt;
&lt;/xmlvalidate&gt;
</pre>
Validate all .xml files in xml directory with the parser configured to perform schema validation. Note: The parser must support the <pre>http://apache.org/xml/features/validation/schema</pre> feature.
<br>
<hr>
<p align="center">Copyright &copy; 2001-2002 Apache Software Foundation. All rights <p align="center">Copyright &copy; 2001-2002 Apache Software Foundation. All rights
Reserved.</p> Reserved.</p>




+ 19
- 15
src/etc/testcases/taskdefs/optional/xmlvalidate.xml View File

@@ -38,25 +38,29 @@
</xmlcatalog> </xmlcatalog>
</xmlvalidate> </xmlvalidate>
</target> </target>

<!-- <target name="testSchemaGood">
<xmlvalidate warn="false">
<fileset dir="xml" includes="endpiece.xml"/>
<feature name="http://xml.org/sax/features/validation" value="true"/>
<feature name="http://apache.org/xml/features/validation/schema" value="true"/>
<xmlcatalog >
<entity publicID = "nap:Massive+Attack+Mezzanine"
location = "xml/doc.xsd"/>
</xmlcatalog>
<target name="testSchemaGood">
<xmlvalidate warn="false" lenient="no" >
<fileset dir="xml" includes="endpiece.xml"/>
<attribute name="http://xml.org/sax/features/validation"
value="false"/>
<attribute name="http://apache.org/xml/features/validation/schema"
value="false"/>
</xmlvalidate> </xmlvalidate>
</target> </target>
-->
<!-- <target name="testSchGemaBad">
<target name="testSchemaBad">
<xmlvalidate warn="false"> <xmlvalidate warn="false">
<fileset dir="xml" includes="endpiece2.xml"/>
<feature name="http://xml.org/sax/features/validation" value="true"/>
<feature name="http://apache.org/xml/features/validation/schema" value="true"/>
<fileset dir="xml" includes="endpiece2.xml"/>
<attribute name="http://xml.org/sax/features/validation"
value="true"/>
<attribute name="http://apache.org/xml/features/validation/schema"
value="true"/>
</xmlvalidate> </xmlvalidate>
</target> -->
</target>
</project> </project>

+ 96
- 24
src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java View File

@@ -58,9 +58,8 @@ import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector; import java.util.Vector;

import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.DirectoryScanner;
@@ -89,10 +88,11 @@ import org.xml.sax.helpers.ParserAdapter;
* (probably the one that is used by Ant itself), but one can specify any * (probably the one that is used by Ant itself), but one can specify any
* SAX1/2 parser if needed * SAX1/2 parser if needed
* @author Raphael Pierquin <a href="mailto:raphael.pierquin@agisphere.com">raphael.pierquin@agisphere.com</a> * @author Raphael Pierquin <a href="mailto:raphael.pierquin@agisphere.com">raphael.pierquin@agisphere.com</a>
* @author Nick Pellow <a href="mailto:nick@svana.org">nick@svana.org</a>
*/ */
public class XMLValidateTask extends Task { public class XMLValidateTask extends Task {


protected static String INIT_FAILED_MSG =
protected static String INIT_FAILED_MSG =
"Could not start xml validation: "; "Could not start xml validation: ";


// ant task properties // ant task properties
@@ -116,15 +116,18 @@ public class XMLValidateTask extends Task {
protected XMLReader xmlReader = null; // XMLReader used to validation process protected XMLReader xmlReader = null; // XMLReader used to validation process
protected ValidatorErrorHandler errorHandler protected ValidatorErrorHandler errorHandler
= new ValidatorErrorHandler(); // to report sax parsing errors = new ValidatorErrorHandler(); // to report sax parsing errors
protected Hashtable features = new Hashtable();

/** The vector to store all attributes (features) to be set on the parser. **/
private Vector attributeList = new Vector();



private XMLCatalog xmlCatalog = new XMLCatalog(); private XMLCatalog xmlCatalog = new XMLCatalog();


/** /**
* Specify how parser error are to be handled.
* Specify how parser error are to be handled.
* Optional, default is <code>true</code>. * Optional, default is <code>true</code>.
* <p> * <p>
* If set to <code>true</code> (default), throw a buildException if the
* If set to <code>true</code> (default), throw a buildException if the
* parser yields an error. * parser yields an error.
*/ */
public void setFailOnError(boolean fail) { public void setFailOnError(boolean fail) {
@@ -194,7 +197,7 @@ public class XMLValidateTask extends Task {
} }


/** /**
* Where to find the parser class; optional.
* Where to find the parser class; optional.
* @see #setClasspath * @see #setClasspath
*/ */
public void setClasspathRef(Reference r) { public void setClasspathRef(Reference r) {
@@ -222,6 +225,19 @@ public class XMLValidateTask extends Task {
filesets.addElement(set); filesets.addElement(set);
} }


/**
* Add an attribute nested element. This is used for setting arbitrary
* features of the SAX parser.
* Valid attributes
* <a href=http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description">include</a>
* @since ant1.6
*/
public Attribute createAttribute() {
final Attribute feature = new Attribute();
attributeList.addElement(feature);
return feature;
}

public void init() throws BuildException { public void init() throws BuildException {
super.init(); super.init();
xmlCatalog.setProject(getProject()); xmlCatalog.setProject(getProject());
@@ -294,7 +310,7 @@ public class XMLValidateTask extends Task {
reader = JAXPUtils.getParser(); reader = JAXPUtils.getParser();
} }
} else { } else {
Class readerClass = null; Class readerClass = null;
try { try {
// load the parser class // load the parser class
@@ -318,15 +334,15 @@ public class XMLValidateTask extends Task {


// then check it implements XMLReader // then check it implements XMLReader
if (reader instanceof XMLReader) { if (reader instanceof XMLReader) {
xmlReader = (XMLReader) reader;
log("Using SAX2 reader " + reader.getClass().getName(),
xmlReader = (XMLReader) reader;
log("Using SAX2 reader " + reader.getClass().getName(),
Project.MSG_VERBOSE); Project.MSG_VERBOSE);
} else { } else {


// see if it is a SAX1 Parser // see if it is a SAX1 Parser
if (reader instanceof Parser) { if (reader instanceof Parser) {
xmlReader = new ParserAdapter((Parser) reader); xmlReader = new ParserAdapter((Parser) reader);
log("Using SAX1 parser " + reader.getClass().getName(),
log("Using SAX1 parser " + reader.getClass().getName(),
Project.MSG_VERBOSE); Project.MSG_VERBOSE);
} else { } else {
throw new BuildException(INIT_FAILED_MSG + readerClassName throw new BuildException(INIT_FAILED_MSG + readerClassName
@@ -347,18 +363,23 @@ public class XMLValidateTask extends Task {
+ " doesn't provide validation"); + " doesn't provide validation");
} }
} }
// set other features
Enumeration enum = features.keys();
while (enum.hasMoreElements()) {
String featureId = (String) enum.nextElement();
setFeature(featureId, ((Boolean) features.get(featureId)).booleanValue(), true);
// set the feature from the attribute list
for (int i = 0; i < attributeList.size(); i++) {
Attribute feature = (Attribute) attributeList.elementAt(i);
setFeature(feature.getName(),
feature.getValue(),
true);

} }
} }
} }


/** /**
* set a feature on the parser.
* @todo find a way to set any feature from build.xml
* Set a feature on the parser.
* @param feature the name of the feature to set
* @param value the value of the feature
* @param warn whether to war if the parser does not support the feature

*/ */
private boolean setFeature(String feature, boolean value, boolean warn) { private boolean setFeature(String feature, boolean value, boolean warn) {


@@ -370,20 +391,22 @@ public class XMLValidateTask extends Task {
if (warn) { if (warn) {
log("Could not set feature '" log("Could not set feature '"
+ feature + feature
+ "' because the parser doesn't recognize it",
+ "' because the '" +
readerClassName + "' parser doesn't recognize it",
Project.MSG_WARN); Project.MSG_WARN);
} }
} catch (SAXNotSupportedException e) { } catch (SAXNotSupportedException e) {
if (warn) { if (warn) {
log("Could not set feature '" log("Could not set feature '"
+ feature + feature
+ "' because the parser doesn't support it",
+ "' because the '" +
readerClassName + "' parser doesn't support it",
Project.MSG_WARN); Project.MSG_WARN);
} }
} }
return toReturn; return toReturn;
} }
/** /**
* parse the file * parse the file
*/ */
@@ -395,18 +418,18 @@ public class XMLValidateTask extends Task {
String uri = "file:" + afile.getAbsolutePath().replace('\\', '/'); String uri = "file:" + afile.getAbsolutePath().replace('\\', '/');
for (int index = uri.indexOf('#'); index != -1; for (int index = uri.indexOf('#'); index != -1;
index = uri.indexOf('#')) { index = uri.indexOf('#')) {
uri = uri.substring(0, index) + "%23"
uri = uri.substring(0, index) + "%23"
+ uri.substring(index + 1); + uri.substring(index + 1);
} }
is.setSystemId(uri); is.setSystemId(uri);
xmlReader.parse(is); xmlReader.parse(is);
} catch (SAXException ex) { } catch (SAXException ex) {
if (failOnError) { if (failOnError) {
throw new BuildException("Could not validate document "
throw new BuildException("Could not validate document "
+ afile); + afile);
} }
} catch (IOException ex) { } catch (IOException ex) {
throw new BuildException("Could not validate document " + afile,
throw new BuildException("Could not validate document " + afile,
ex); ex);
} }


@@ -482,4 +505,53 @@ public class XMLValidateTask extends Task {
return e.getMessage(); return e.getMessage();
} }
} }

/**
* The class to create to set a feature of the parser.
* @since ant1.6
* @author <a href="mailto:nick@svana.org">Nick Pellow</a>
*/
public class Attribute {
/** The name of the attribute to set.
*
* Valid attributes <a href=http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description">include.</a>
*/
private String attributeName = null;

/**
* The value of the feature.
**/
private boolean attributeValue;

/**
* Set the feature name.
* @param name the name to set
*/
public void setName(String name) {
attributeName = name;
}
/**
* Set the feature value to true or false.
* @param value
*/
public void setValue(boolean value) {
attributeValue = value;
}

/**
* Gets the attribute name.
* @return the feature name
*/
public String getName() {
return attributeName;
}

/**
* Gets the attribute value.
* @return the featuree value
*/
public boolean getValue() {
return attributeValue;
}
}
} }

+ 17
- 0
src/testcases/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java View File

@@ -94,6 +94,7 @@ public class XmlValidateTest extends BuildFileTest {
* The teardown method for JUnit * The teardown method for JUnit
*/ */
public void tearDown() { public void tearDown() {

} }




@@ -125,4 +126,20 @@ public class XmlValidateTest extends BuildFileTest {
public void testXmlCatalogNested() { public void testXmlCatalogNested() {
executeTarget("xmlcatalognested"); executeTarget("xmlcatalognested");
} }

/**
* Test xml schema validation
*/
public void testXmlSchemaGood() {
executeTarget("testSchemaGood");
}
/**
* Test xml schema validation
*/
public void testXmlSchemaBad() {
expectBuildExceptionContaining(
"testSchemaBad",
"Bad Schema Validation", "not a valid XML document");

}
} }

Loading…
Cancel
Save