You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by eh...@apache.org on 2002/05/24 17:47:57 UTC
cvs commit: jakarta-ant/src/testcases/org/apache/tools/ant/types XMLCatalogTest.java
ehatcher 02/05/24 08:47:57
Modified: src/main/org/apache/tools/ant/types Tag: ANT_15_BRANCH
XMLCatalog.java
docs/manual/CoreTasks Tag: ANT_15_BRANCH style.html
docs/manual/OptionalTasks Tag: ANT_15_BRANCH
xmlvalidate.html
src/testcases/org/apache/tools/ant/taskdefs/optional Tag:
ANT_15_BRANCH XmlValidateTest.java
src/etc/testcases/taskdefs/optional Tag: ANT_15_BRANCH
xmlvalidate.xml
src/main/org/apache/tools/ant/taskdefs Tag: ANT_15_BRANCH
XSLTProcess.java
src/main/org/apache/tools/ant/taskdefs/optional Tag:
ANT_15_BRANCH TraXLiaison.java
docs/manual/CoreTypes Tag: ANT_15_BRANCH xmlcatalog.html
Added: src/testcases/org/apache/tools/ant/types Tag: ANT_15_BRANCH
XMLCatalogTest.java
Log:
patch submitted by Craeg K Strong. Mostly doc patches, but also added capability to set a URIResolver as well as an EntityResolver.
Note: commented out some asserts that were failing for me in XMLCatalogTest - looks like minor path issues.
Revision Changes Path
No revision
No revision
1.9.2.2 +371 -94 jakarta-ant/src/main/org/apache/tools/ant/types/XMLCatalog.java
Index: XMLCatalog.java
===================================================================
RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/types/XMLCatalog.java,v
retrieving revision 1.9.2.1
retrieving revision 1.9.2.2
diff -u -r1.9.2.1 -r1.9.2.2
--- XMLCatalog.java 20 May 2002 18:44:38 -0000 1.9.2.1
+++ XMLCatalog.java 24 May 2002 15:47:56 -0000 1.9.2.2
@@ -58,17 +58,30 @@
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
+import java.io.FileNotFoundException;
import java.net.URL;
+import java.net.MalformedURLException;
import java.util.Enumeration;
+import java.util.Stack;
import java.util.Vector;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.URIResolver;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.util.FileUtils;
+
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
-import org.apache.tools.ant.util.LoaderUtils;
-import org.apache.tools.ant.util.FileUtils;
+import org.xml.sax.XMLReader;
+
+
/**
* This data type provides a catalog of DTD locations.
@@ -83,7 +96,7 @@
* </code>
* <p>
* The object implemention <code>sometask</code> must provide a method called
- * <code>createXMLCatalog</code> which returns an instance of
+ * <code>createXMLCatalog</code> which returns an instance of
* <code>XMLCatalog</code>. Nested DTD and entity definitions are handled by
* the XMLCatalog object and must be labeled <code>dtd</code> and
* <code>entity</code> respectively.</p>
@@ -93,21 +106,21 @@
*
* @author dIon Gillard
* @author Erik Hatcher
- * @version $Id: XMLCatalog.java,v 1.9.2.1 2002/05/20 18:44:38 ehatcher Exp $
+ * @version $Id: XMLCatalog.java,v 1.9.2.2 2002/05/24 15:47:56 ehatcher Exp $
*/
public class XMLCatalog extends DataType implements Cloneable, EntityResolver {
/** File utilities instance */
private FileUtils fileUtils = FileUtils.newFileUtils();
-
+
//-- Fields ----------------------------------------------------------------
-
+
/** holds dtd/entity objects until needed */
private Vector elements = new Vector();
private Path classpath;
//-- Methods ---------------------------------------------------------------
-
+
/**
* @return the elements of the catalog - DTDLocation objects
*/
@@ -116,6 +129,8 @@
}
/**
+ * Returns the classpath in which to attempt to resolve resources.
+ *
* @return the classpath
*/
private Path getClasspath() {
@@ -123,25 +138,22 @@
}
/**
- * Set the list of DTDLocation object sin the catalog
+ * Set the list of DTDLocation objects in the catalog. Not
+ * allowed if this catalog is itself a reference to another
+ * catalog -- that is, a catalog cannot both refer to another
+ * <em>and</em> contain elements or other attributes.
*
* @param aVector the new list of DTD Locations to use in the catalog.
*/
private void setElements(Vector aVector) {
elements = aVector;
}
-
- /**
- * Add a DTD Location to the catalog
- *
- * @param aDTD the DTDLocation instance to be aded to the catalog
- */
- private void addElement(DTDLocation aDTD) {
- getElements().addElement(aDTD);
- }
/**
- * Allows nested classpath elements
+ * Allows nested classpath elements. Not allowed if this catalog
+ * is itself a reference to another catalog -- that is, a catalog
+ * cannot both refer to another <em>and</em> contain elements or
+ * other attributes.
*/
public Path createClasspath() {
if (isReference()) {
@@ -150,11 +162,15 @@
if (this.classpath == null) {
this.classpath = new Path(getProject());
}
+ checked = false;
return this.classpath.createPath();
}
/**
- * Allows simple classpath string
+ * Allows simple classpath string. Not allowed if this catalog is
+ * itself a reference to another catalog -- that is, a catalog
+ * cannot both refer to another <em>and</em> contain elements or
+ * other attributes.
*/
public void setClasspath(Path classpath) {
if (isReference()) {
@@ -165,23 +181,32 @@
} else {
this.classpath.append(classpath);
}
+ checked = false;
}
/**
- * Allows classpath reference
+ * Allows classpath reference. Not allowed if this catalog is
+ * itself a reference to another catalog -- that is, a catalog
+ * cannot both refer to another <em>and</em> contain elements or
+ * other attributes.
*/
public void setClasspathRef(Reference r) {
if (isReference()) {
throw tooManyAttributes();
}
createClasspath().setRefid(r);
+ checked = false;
}
/**
- * Creates the nested <code><dtd></code> element.
+ * Creates the nested <code><dtd></code> element. Not
+ * allowed if this catalog is itself a reference to another
+ * catalog -- that is, a catalog cannot both refer to another
+ * <em>and</em> contain elements or other attributes.
*
- * @param dtd the infromation about the DTD to be added to the catalog
- * @exception BuildException if this is a reference and no nested
+ * @param dtd the information about the PUBLIC resource mapping to
+ * be added to the catalog
+ * @exception BuildException if this is a reference and no nested
* elements are allowed.
*/
public void addDTD(DTDLocation dtd) throws BuildException {
@@ -190,13 +215,18 @@
}
getElements().addElement(dtd);
+ checked = false;
}
-
+
/**
- * Creates the nested <code><entity></code> element
+ * Creates the nested <code><entity></code> element. Not
+ * allowed if this catalog is itself a reference to another
+ * catalog -- that is, a catalog cannot both refer to another
+ * <em>and</em> contain elements or other attributes.
*
- * @param dtd the infromation about the DTD to be added to the catalog
- * @exception BuildException if this is a reference and no nested
+ * @param dtd the information about the URI resource mapping to be
+ * added to the catalog
+ * @exception BuildException if this is a reference and no nested
* elements are allowed.
*/
public void addEntity(DTDLocation dtd) throws BuildException {
@@ -204,7 +234,10 @@
}
/**
- * Loads a nested XMLCatalog into our definition
+ * Loads a nested <code><xmlcatalog></code> into our
+ * definition. Not allowed if this catalog is itself a reference
+ * to another catalog -- that is, a catalog cannot both refer to
+ * another <em>and</em> contain elements or other attributes.
*
* @param catalog Nested XMLCatalog
*/
@@ -224,15 +257,19 @@
// Append the classpath of the nested catalog
Path nestedClasspath = catalog.getClasspath();
createClasspath().append(nestedClasspath);
+ checked = false;
}
/**
- * Makes this instance in effect a reference to another XCatalog instance.
+ * Makes this instance in effect a reference to another XMLCatalog
+ * instance.
*
- * <p>You must not set another attribute or nest elements inside
- * this element if you make it a reference.</p>
+ * <p>You must not set another attribute or nest elements inside *
+ * this element if you make it a reference. That is, a catalog
+ * cannot both refer to another <em>and</em> contain elements or
+ * attributes.</p>
*
- * @param r the reference to which this catalogi instance is associated
+ * @param r the reference to which this catalog instance is associated
* @exception BuildException if this instance already has been configured.
*/
public void setRefid(Reference r) throws BuildException {
@@ -241,7 +278,7 @@
}
// change this to get the objects from the other reference
Object o = r.getReferencedObject(getProject());
- // we only support references to other XCatalogs
+ // we only support references to other XMLCatalogs
if (o instanceof XMLCatalog) {
// set all elements from referenced catalog to this one
XMLCatalog catalog = (XMLCatalog) o;
@@ -250,81 +287,81 @@
String msg = r.getRefId() + " does not refer to an XMLCatalog";
throw new BuildException(msg);
}
-
super.setRefid(r);
}
/**
+ * Implements the EntityResolver.resolveEntity() interface method.
+ *
* @see org.xml.sax.EntityResolver#resolveEntity
*/
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
- InputSource source = null;
- DTDLocation matchingDTD = findMatchingDTD(publicId);
- if (matchingDTD != null) {
- // check if publicId is mapped to a file
- log("Matching DTD found for publicId: '" + publicId +
- "' location: '" + matchingDTD.getLocation() + "'",
- Project.MSG_DEBUG);
- File dtdFile = project.resolveFile(matchingDTD.getLocation());
- if (dtdFile.exists() && dtdFile.canRead()) {
- source = new InputSource(new FileInputStream(dtdFile));
- URL dtdFileURL = fileUtils.getFileURL(dtdFile);
- source.setSystemId(dtdFileURL.toExternalForm());
- log("matched a readable file", Project.MSG_DEBUG);
- } else {
- // check if publicId is a resource
-
- AntClassLoader loader = null;
- if (classpath != null) {
- loader = new AntClassLoader(project, classpath);
- } else {
- loader = new AntClassLoader(project, Path.systemClasspath);
- }
- InputStream is
- = loader.getResourceAsStream(matchingDTD.getLocation());
- if (is != null) {
- source = new InputSource(is);
- source.setSystemId(loader.getResource(
- matchingDTD.getLocation()).toExternalForm());
- log("matched a resource", Project.MSG_DEBUG);
- } else {
- // check if it's a URL
- try {
- URL dtdUrl = new URL(matchingDTD.getLocation());
- InputStream dtdIs = dtdUrl.openStream();
- if (dtdIs != null) {
- source = new InputSource(dtdIs);
- source.setSystemId(dtdUrl.toExternalForm());
- log("matched as a URL", Project.MSG_DEBUG);
- } else {
- log("No match, parser will use: '" + systemId + "'",
- Project.MSG_DEBUG);
- }
- } catch (IOException ioe) {
- //ignore
- }
- }
- }
- } else {
- log("No match, parser will use: '" + systemId + "'",
- Project.MSG_DEBUG);
+ if (!checked) {
+ // make sure we don't have a circular reference here
+ Stack stk = new Stack();
+ stk.push(this);
+ dieOnCircularReference(stk, getProject());
+ }
+
+ log("resolveEntity: '" + publicId + "': '" + systemId + "'",
+ Project.MSG_DEBUG);
+
+ InputSource inputSource = resolveEntityImpl(publicId, systemId);
+
+ if (inputSource == null) {
+ log("No matching catalog entry found, parser will use: '" +
+ systemId + "'", Project.MSG_DEBUG);
}
- // else let the parser handle it as a URI as we don't know what to
- // do with it
+
+ return inputSource;
+ }
+
+ /**
+ * Implements the URIResolver.resolve() interface method.
+ *
+ * @see javax.xml.transform.URIResolver#resolve
+ */
+ public Source resolve(String href, String base)
+ throws TransformerException {
+
+ if (!checked) {
+ // make sure we don't have a circular reference here
+ Stack stk = new Stack();
+ stk.push(this);
+ dieOnCircularReference(stk, getProject());
+ }
+
+ SAXSource source = null;
+ InputSource inputSource = null;
+
+ String uri = removeFragment(href);
+
+ log("resolve: '" + uri + "' with base: '" + base + "'", Project.MSG_DEBUG);
+
+ source = resolveImpl(uri, base);
+
+ if (source == null) {
+ log("No matching catalog entry found, parser will use: '" +
+ href + "'", Project.MSG_DEBUG);
+ }
+ else {
+ setEntityResolver(source);
+ }
+
return source;
}
-
+
/**
* Find a DTDLocation instance for the given publicId.
*
- * @param publicId the publicId of the DTD for which local information is
- * required
- * @return a DTDLocation instance with information on the local location
- * of the DTD or null if no such information is available
+ * @param publicId the publicId of the Resource for which local information
+ * is required
+ * @return a DTDLocation instance with information on the local location
+ * of the Resource or null if no such information is available
*/
- private DTDLocation findMatchingDTD(String publicId) {
+ private DTDLocation findMatchingEntry(String publicId) {
Enumeration elements = getElements().elements();
DTDLocation element = null;
while (elements.hasMoreElements()) {
@@ -335,6 +372,246 @@
}
return null;
}
-
-}
+ /**
+ * <p>This is called from the URIResolver to set an EntityResolver
+ * on the SAX parser to be used for new XML documents that are
+ * encountered as a result of the document() function, xsl:import,
+ * or xsl:include. This is done because the XSLT processor calls
+ * out to the SAXParserFactory itself to create a new SAXParser to
+ * parse the new document. The new parser does not automatically
+ * inherit the EntityResolver of the original (although arguably
+ * it should). See below:</p>
+ *
+ * <tt>"If an application wants to set the ErrorHandler or
+ * EntityResolver for an XMLReader used during a transformation,
+ * it should use a URIResolver to return the SAXSource which
+ * provides (with getXMLReader) a reference to the XMLReader"</tt>
+ *
+ * <p>...quoted from page 118 of the Java API for XML
+ * Processing 1.1 specification</p>
+ *
+ */
+ private void setEntityResolver(SAXSource source) throws TransformerException {
+
+ XMLReader reader = source.getXMLReader();
+ if (reader == null) {
+ SAXParserFactory spFactory = SAXParserFactory.newInstance();
+ spFactory.setNamespaceAware(true);
+ try {
+ reader = spFactory.newSAXParser().getXMLReader();
+ }
+ catch (ParserConfigurationException ex) {
+ throw new TransformerException(ex);
+ }
+ catch (SAXException ex) {
+ throw new TransformerException(ex);
+ }
+ }
+ reader.setEntityResolver(this);
+ source.setXMLReader(reader);
+ }
+
+ /**
+ * Utility method to remove trailing fragment from a URI.
+ * For example,
+ * <code>http://java.sun.com/index.html#chapter1</code>
+ * would return <code>http://java.sun.com/index.html</code>.
+ *
+ * @param uri The URI to process. It may or may not contain a
+ * fragment.
+ * @return The URI sans fragment.
+ */
+ private String removeFragment(String uri) {
+ String result = uri;
+ String fragment = null;
+ int hashPos = uri.indexOf("#");
+ if (hashPos >= 0) {
+ result = uri.substring(0, hashPos);
+ fragment = uri.substring(hashPos+1);
+ }
+ return result;
+ }
+
+ /**
+ * Utility method to lookup a DTDLocation in the filesystem.
+ *
+ * @return An InputSource for reading the file, or <code>null</code>
+ * if the file does not exist or is not readable.
+ */
+ private InputSource filesystemLookup(DTDLocation matchingEntry) {
+
+ String uri = matchingEntry.getLocation();
+ File basedir = null;
+
+ //
+ // The DTDLocation may specify a relative path for its
+ // location attribute. This is resolved using the appropriate
+ // base.
+ //
+ File resFile = project.resolveFile(uri);
+ InputSource source = null;
+
+ if (resFile.exists() && resFile.canRead()) {
+ try {
+ source = new InputSource(new FileInputStream(resFile));
+ URL resFileURL = fileUtils.getFileURL(resFile);
+ String sysid = resFileURL.toExternalForm();
+ source.setSystemId(sysid);
+ log("catalog entry matched a readable file: '" +
+ sysid + "'", Project.MSG_DEBUG);
+ } catch(FileNotFoundException ex) {
+ // ignore
+ } catch(MalformedURLException ex) {
+ // ignore
+ } catch(IOException ex) {
+ // ignore
+ }
+ }
+
+ return source;
+ }
+
+ /**
+ * Utility method to lookup a DTDLocation in the classpath.
+ *
+ * @return An InputSource for reading the resource, or <code>null</code>
+ * if the resource does not exist in the classpath or is not readable.
+ */
+ private InputSource classpathLookup(DTDLocation matchingEntry) {
+
+ InputSource source = null;
+
+ AntClassLoader loader = null;
+ if (classpath != null) {
+ loader = new AntClassLoader(project, classpath);
+ } else {
+ loader = new AntClassLoader(project, Path.systemClasspath);
+ }
+
+ //
+ // for classpath lookup we ignore the base directory
+ //
+ InputStream is
+ = loader.getResourceAsStream(matchingEntry.getLocation());
+
+ if (is != null) {
+ source = new InputSource(is);
+ URL entryURL = loader.getResource(matchingEntry.getLocation());
+ String sysid = entryURL.toExternalForm();
+ source.setSystemId(sysid);
+ log("catalog entry matched a resource in the classpath: '" +
+ sysid + "'", Project.MSG_DEBUG);
+ }
+
+ return source;
+ }
+
+ /**
+ * Utility method to lookup a DTDLocation in URL-space.
+ *
+ * @return An InputSource for reading the resource, or <code>null</code>
+ * if the resource does not identify a valid URL or is not readable.
+ */
+ private InputSource urlLookup(String uri, String base) {
+
+ InputSource source = null;
+ URL url = null;
+
+ try {
+ if (base == null) {
+ url = new URL(uri);
+ }
+ else {
+ URL baseURL = new URL(base);
+ url = (uri.length() == 0 ? baseURL : new URL(baseURL, uri));
+ }
+ }
+ catch (MalformedURLException ex) {
+ // ignore
+ }
+
+ if (url != null) {
+ try {
+ InputStream is = url.openStream();
+ if (is != null) {
+ source = new InputSource(is);
+ String sysid = url.toExternalForm();
+ source.setSystemId(sysid);
+ log("catalog entry matched as a URL: '" +
+ sysid + "'", Project.MSG_DEBUG);
+ }
+ } catch(IOException ex) {
+ // ignore
+ }
+ }
+
+ return source;
+
+ }
+
+ /**
+ * Implements the guts of the resolveEntity() lookup strategy.
+ */
+ private InputSource resolveEntityImpl(String publicId,
+ String systemId) {
+
+ InputSource result = null;
+
+ DTDLocation matchingEntry = findMatchingEntry(publicId);
+
+ if (matchingEntry != null) {
+
+ log("Matching catalog entry found for publicId: '" +
+ matchingEntry.getPublicId() + "' location: '" +
+ matchingEntry.getLocation() + "'",
+ Project.MSG_DEBUG);
+
+ result = filesystemLookup(matchingEntry);
+
+ if (result == null) {
+ result = classpathLookup(matchingEntry);
+ }
+
+ if (result == null) {
+ result = urlLookup(matchingEntry.getLocation(), null);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Implements the guts of the resolve() lookup strategy.
+ */
+ private SAXSource resolveImpl(String href, String base)
+ throws TransformerException {
+
+ SAXSource result = null;
+ InputSource source = null;
+
+ DTDLocation matchingEntry = findMatchingEntry(href);
+
+ if (matchingEntry != null) {
+
+ log("Matching catalog entry found for uri: '" +
+ matchingEntry.getPublicId() + "' location: '" +
+ matchingEntry.getLocation() + "'",
+ Project.MSG_DEBUG);
+
+ source = filesystemLookup(matchingEntry);
+
+ if (source == null) {
+ source = classpathLookup(matchingEntry);
+ }
+
+ if (source == null) {
+ source = urlLookup(matchingEntry.getLocation(), base);
+ }
+
+ if (source != null) {
+ result = new SAXSource(source);
+ }
+ }
+ return result;
+ }
+}
No revision
No revision
1.18.2.2 +21 -2 jakarta-ant/docs/manual/CoreTasks/style.html
Index: style.html
===================================================================
RCS file: /home/cvs/jakarta-ant/docs/manual/CoreTasks/style.html,v
retrieving revision 1.18.2.1
retrieving revision 1.18.2.2
diff -u -r1.18.2.1 -r1.18.2.2
--- style.html 3 May 2002 09:40:29 -0000 1.18.2.1
+++ style.html 24 May 2002 15:47:57 -0000 1.18.2.2
@@ -27,8 +27,10 @@
attributes of <code><fileset></code> (<code>dir</code> becomes <code>basedir</code>)
as well as the nested <code><include></code>, <code><exclude></code>
and <code><patternset></code> elements.</p>
-<p>Style supports the use of a <param> element which is used to pass values
+<p>This task supports the use of a nested <param> element which is used to pass values
to an <xsl:param> declaration.</p>
+<p>This task supports the use of a nested <a href="../CoreTypes/xmlcatalog.html">xmlcatalog</a>
+element which is used to perform Entity and URI resolution</p>
<p><i><style> and <xslt> refer to the same Ant task and can be used interchangeably.</i></p>
<p>If you want to use Xalan-J 1 or XSL:P, you also need Ant's optional.jar</p>
<h3>Parameters</h3>
@@ -161,6 +163,9 @@
<p>The classpath to load the processor from can be specified via a
nested <code><classpath></code>, as well - that is, a
<a href="../using.html#path">path</a>-like structure.</p>
+<h4>xmlcatalog</h4>
+<p>The <a href="../CoreTypes/xmlcatalog.html">xmlcatalog</a>
+element is used to perform Entity and URI resolution.</p>
<h4>param</h4>
<p>Param is used to pass a parameter to the XSL stylesheet.</p>
<h4>Parameters</h4>
@@ -187,8 +192,22 @@
<pre>
<style basedir="doc" destdir="build/doc"
extension=".html" style="style/apache.xsl"/></pre>
- <h4>Using XSL parameters</h4>
+ <h4>Using an xmlcatalog</h4>
<pre><xslt basedir="doc" destdir="build/doc"
+ extension=".html" style="style/apache.xsl">
+ <xmlcatalog refid="mycatalog"/>
+</xslt>
+
+<xslt basedir="doc" destdir="build/doc"
+ extension=".html" style="style/apache.xsl">
+ <xmlcatalog>
+ <dtd
+ publicId="-//ArielPartners//DTD XML Article V1.0//EN"
+ location="com/arielpartners/knowledgebase/dtd/article.dtd"/>
+ </xmlcatalog>
+</xslt></pre>
+ <h4>Using XSL parameters</h4>
+<pre><xslt basedir="doc" destdir="build/doc"
extension=".html" style="style/apache.xsl">
<param name="date" expression="07-01-2000"/>
</xslt></pre>
No revision
No revision
1.4.2.1 +21 -0 jakarta-ant/docs/manual/OptionalTasks/xmlvalidate.html
Index: xmlvalidate.html
===================================================================
RCS file: /home/cvs/jakarta-ant/docs/manual/OptionalTasks/xmlvalidate.html,v
retrieving revision 1.4
retrieving revision 1.4.2.1
diff -u -r1.4 -r1.4.2.1
--- xmlvalidate.html 22 Apr 2002 08:56:13 -0000 1.4
+++ xmlvalidate.html 24 May 2002 15:47:57 -0000 1.4.2.1
@@ -14,6 +14,10 @@
(probably the one that is used by Ant itself), but one can specify any
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
+<dtd> elements which are used to resolve DTDs and entities.</p>
+
<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -77,6 +81,9 @@
<td align="center" valign="top">Yes</td>
</tr>
</table>
+<h4>xmlcatalog</h4>
+<p>The <a href="../CoreTypes/xmlcatalog.html">xmlcatalog</a>
+element is used to perform Entity resolution.</p>
<h3>Examples</h3>
@@ -92,6 +99,20 @@
<xmlvalidate file="struts-config.xml" warn="false">
<dtd publicId="-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
location="struts-config_1_0.dtd"/>
+</xmlvalidate>
+
+<xmlvalidate failonerror="no">
+ <fileset dir="${project.dir}" includes="**/*.xml"/>
+ <xmlcatalog refid="mycatalog"/>
+</xmlvalidate>
+
+<xmlvalidate failonerror="no">
+ <fileset dir="${project.dir}" includes="**/*.xml"/>
+ <xmlcatalog>
+ <dtd
+ publicId="-//ArielPartners//DTD XML Article V1.0//EN"
+ location="com/arielpartners/knowledgebase/dtd/article.dtd"/>
+ </xmlcatalog>
</xmlvalidate>
</pre></blockquote>
<hr>
No revision
No revision
1.2.2.1 +7 -1 jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java
Index: XmlValidateTest.java
===================================================================
RCS file: /home/cvs/jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -r1.2 -r1.2.2.1
--- XmlValidateTest.java 20 Apr 2002 16:15:11 -0000 1.2
+++ XmlValidateTest.java 24 May 2002 15:47:57 -0000 1.2.2.1
@@ -118,5 +118,11 @@
public void testXmlCatalog() {
executeTarget("xmlcatalog");
}
-}
+ /**
+ * Test nested xmlcatalog definitions
+ */
+ public void testXmlCatalogNested() {
+ executeTarget("xmlcatalognested");
+ }
+}
No revision
No revision
1.2.2.1 +14 -0 jakarta-ant/src/etc/testcases/taskdefs/optional/xmlvalidate.xml
Index: xmlvalidate.xml
===================================================================
RCS file: /home/cvs/jakarta-ant/src/etc/testcases/taskdefs/optional/xmlvalidate.xml,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -r1.2 -r1.2.2.1
--- xmlvalidate.xml 20 Apr 2002 16:15:10 -0000 1.2
+++ xmlvalidate.xml 24 May 2002 15:47:57 -0000 1.2.2.1
@@ -24,5 +24,19 @@
</xmlcatalog>
</xmlvalidate>
</target>
+
+ <target name="xmlcatalognested">
+ <xmlvalidate warn="false">
+ <fileset dir="xml" includes="**/about.xml"/>
+ <xmlcatalog classpath="xml">
+ <entity publicID = "bogusImage"
+ location = "/i/dont/exist.jpg"/>
+ <xmlcatalog>
+ <dtd publicID="-//stevo//DTD doc 1.0//EN"
+ location="doc.dtd"/>
+ </xmlcatalog>
+ </xmlcatalog>
+ </xmlvalidate>
+ </target>
</project>
No revision
No revision
1.43.2.1 +12 -6 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
Index: XSLTProcess.java
===================================================================
RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java,v
retrieving revision 1.43
retrieving revision 1.43.2.1
diff -u -r1.43 -r1.43.2.1
--- XSLTProcess.java 20 Apr 2002 16:11:34 -0000 1.43
+++ XSLTProcess.java 24 May 2002 15:47:57 -0000 1.43.2.1
@@ -67,12 +67,13 @@
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.types.XMLCatalog;
import org.xml.sax.EntityResolver;
+import javax.xml.transform.URIResolver;
/**
* A Task to process via XSLT a set of XML documents. This is
* useful for building views of XML based documentation.
*
- * @version $Revision: 1.43 $
+ * @version $Revision: 1.43.2.1 $
*
* @author <a href="mailto:kvisco@exoffice.com">Keith Visco</a>
* @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a>
@@ -662,14 +663,19 @@
liaison.addParam(p.getName(), p.getExpression());
}
// if liaison is a TraxLiason, use XMLCatalog as the entity
- // resolver
+ // resolver and URI resolver
if (liaison.getClass().getName().equals(TRAX_LIAISON_CLASS) &&
xmlCatalog != null) {
- log("Configuring TraxLiaison and calling entity resolver",
- Project.MSG_DEBUG);
+ log("Configuring TraxLiaison: setting entity resolver " +
+ "and setting URI resolver", Project.MSG_DEBUG);
Method resolver = liaison.getClass()
- .getDeclaredMethod("setEntityResolver",
- new Class[] {EntityResolver.class});
+ .getDeclaredMethod("setEntityResolver",
+ new Class[] {EntityResolver.class});
+ resolver.invoke(liaison, new Object[] {xmlCatalog});
+
+ resolver = liaison.getClass()
+ .getDeclaredMethod("setURIResolver",
+ new Class[] {URIResolver.class});
resolver.invoke(liaison, new Object[] {xmlCatalog});
}
} catch (Exception ex) {
No revision
No revision
1.17.2.1 +17 -4 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java
Index: TraXLiaison.java
===================================================================
RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java,v
retrieving revision 1.17
retrieving revision 1.17.2.1
diff -u -r1.17 -r1.17.2.1
--- TraXLiaison.java 15 Apr 2002 12:11:47 -0000 1.17
+++ TraXLiaison.java 24 May 2002 15:47:57 -0000 1.17.2.1
@@ -80,6 +80,7 @@
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
+import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXSource;
@@ -108,7 +109,10 @@
private XSLTLogger logger;
/** possible resolver for publicIds */
- private EntityResolver resolver;
+ private EntityResolver entityResolver;
+
+ /** possible resolver for URIs */
+ private URIResolver uriResolver;
public TraXLiaison() throws Exception {
tfactory = TransformerFactory.newInstance();
@@ -145,12 +149,12 @@
// FIXME: need to use a SAXSource as the source for the transform
// so we can plug in our own entity resolver
Source src = null;
- if (resolver != null) {
+ if (entityResolver != null) {
if (tfactory.getFeature(SAXSource.FEATURE)) {
SAXParserFactory spFactory = SAXParserFactory.newInstance();
spFactory.setNamespaceAware(true);
XMLReader reader = spFactory.newSAXParser().getXMLReader();
- reader.setEntityResolver(resolver);
+ reader.setEntityResolver(entityResolver);
src = new SAXSource(reader, new InputSource(fis));
} else {
throw new IllegalStateException("xcatalog specified, but " +
@@ -164,6 +168,9 @@
// not sure what could be the need of this...
res.setSystemId(getSystemId(outfile));
+ if (uriResolver != null)
+ transformer.setURIResolver(uriResolver);
+
transformer.transform(src, res);
} finally {
// make sure to close all handles, otherwise the garbage
@@ -263,7 +270,13 @@
/** Set the class to resolve entities during the transformation
*/
public void setEntityResolver(EntityResolver aResolver) throws Exception {
- resolver = aResolver;
+ entityResolver = aResolver;
+ }
+
+ /** Set the class to resolve URIs during the transformation
+ */
+ public void setURIResolver(URIResolver aResolver) throws Exception {
+ uriResolver = aResolver;
}
} //-- TraXLiaison
No revision
No revision
1.1.2.1 +127 -31 jakarta-ant/docs/manual/CoreTypes/xmlcatalog.html
Index: xmlcatalog.html
===================================================================
RCS file: /home/cvs/jakarta-ant/docs/manual/CoreTypes/xmlcatalog.html,v
retrieving revision 1.1
retrieving revision 1.1.2.1
diff -u -r1.1 -r1.1.2.1
--- xmlcatalog.html 21 Mar 2002 08:58:09 -0000 1.1
+++ xmlcatalog.html 24 May 2002 15:47:57 -0000 1.1.2.1
@@ -8,38 +8,112 @@
<body>
<h2><a name="XMLCatalog">XMLCatalog</a></h2>
-<p>An XMLCatalog is a catalog of public resources such as DTDs or entities
-that
-are referenced in an XML document and are available locally.</p>
-<p>This allows the XML Parser, XSL Processor or other consumer of XML
+
+<p>An XMLCatalog is a catalog of public resources such as DTDs or
+entities that are referenced in an XML document. Catalogs are
+typically used to make web references to resources point to a locally
+cached copy of the resource.</p>
+
+<p>This allows the XML Parser, XSLT Processor or other consumer of XML
documents
to efficiently allow a local substitution for a resource available on the
web.
</p>
+<p>This data type provides a catalog of resource locations based
+on the <a
+href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
+OASIS "Open Catalog" standard</a>. The catalog entries are used
+both for Entity resolution and URI resolution, in accordance with
+the <code>org.xml.sax.EntityResolver</code> and <code>
+javax.xml.transform.URIResolver</code> interfaces as defined
+in the <a href="http://java.sun.com/xml/jaxp">Java API for XML
+Processing (JAXP) Specification</a>.</p>
<p>For example, in a <code>web.xml</code> file, the DTD is referenced as:
<pre>
-<!DOCTYPE web-app
- PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application
-2.2//EN"
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
</pre>
The XML processor, without XMLCatalog support, would need to retrieve the
DTD from
the URL specified whenever validation of the document was required.
</p>
-<p>This can be very time consuming during the build process, especially
-where
-network throughput is limited.</p>
+<p>This can be very time consuming during the build process,
+especially where network throughput is limited. Alternatively, you
+can do the following:
+<ol>
+<li>Copy <code>web-app_2_2.dtd</code> onto your local disk somewhere (either in the
+filesystem or even embedded inside a jar or zip file on the classpath).</li>
+<li>Create an <code><xmlcatalog></code> with a <code><dtd></code>
+element whose <code>location</code> attribute points to the file.</li>
+<li>Success! The XML processor will now use the local copy instead of calling out
+to the internet.</li>
+</ol>
</p>
<p>XMLCatalogs can appear inside tasks
that support this feature or at the same level as <code>target</code>
- i.e., as children of <code>project</code> for reuse across different
tasks,
-e.g. XML Validation and XSL Translation.</p>
+e.g. XML Validation and XSLT Transformation. The XML Validate task
+uses XMLCatalogs for entity resolution. The XSLT Transformation
+task uses XMLCatalogs for both entity and URI resolution.</p>
<p>XMLCatalogs are specified as either a reference to another XMLCatalog,
defined
previously in a build file, or as a list of <code>dtd</code> or
-<code>entity</code> locations.</p>
+<code>entity</code> locations. A separate classpath for entity resolution
+may be specified inline via nested <code>classpath</code> elements;
+otherwise the system classpath is used for this as well.</p>
+<p>XMLCatalogs can also be nested inside other XMLCatalogs. For
+example, a "superset" XMLCatalog could be made by including several
+nested XMLCatalogs that referred to other, previously defined
+XMLCatalogs.</p>
+<p>Currently, only <code><dtd></code> and
+<code><entity></code> elements may be specified inline; these
+roughly correspond to OASIS catalog entry types <code>PUBLIC</code> and
+<code>URI</code> respectively.</p>
+<h3><a name="ResolverAlgorithm">Entity/DTD/URI Resolution Algorithm</a></h3>
+
+When an entity, DTD, or URI is looked up by the XML processor, the
+XMLCatalog searches its list of entries to see if any match. That is,
+it attempts to match the <code>publicId</code> attribute of each entry
+with the PublicID or URI of the entity to be resolved. Assuming a
+matching entry is found, XMLCatalog then executes the following steps:
+
+<h4>1. Filesystem lookup</h4>
+
+<p>The <code>location</code> is first looked up in the filesystem. If
+the <code>location</code> is a relative path, the ant project basedir
+attribute is used as the base directory. If the <code>location</code>
+specifies an absolute path, it is used as is. Once we have an
+absolute path in hand, we check to see if a valid and readable file
+exists at that path. If so, we are done. If not, we proceed to the
+next step.</p>
+
+<h4>2. Classpath lookup</h4>
+
+<p>The <code>location</code> is next looked up in the classpath.
+Recall that jar files are merely fancy zip files. For classpath
+lookup, the <code>location</code> is used as is (no base is
+prepended). We use a Classloader to attempt to load the resource from
+the classpath. For example, if hello.jar is in the classpath and it
+contains <code>foo/bar/blat.dtd</code> it will resolve an entity whose
+<code>location</code> is <code>foo/bar/blat.dtd</code>. Of course, it
+will <em>not</em> resolve an entity whose <code>location</code> is
+<code>blat.dtd</code>.
+
+
+<h4>3. URL-space lookup</h4>
+
+<p>Finally, we attempt to make a URL out of the <code>location</code>.
+At first this may seem like this would defeat the purpose of
+XMLCatalogs -- why go back out to the internet? But in fact, this can
+be used to (in a sense) implement HTTP redirects, substituting one URL
+for another. The mapped-to URL might also be served by a local web
+server. If the URL resolves to a valid and readable resource, we are
+done. Otherwise, we give up. In this case, the XML processor will
+perform its normal resolution algorithm. Depending on the processor
+configuration, further resolution failures may or may not result in
+fatal (i.e. build-ending) errors.</p>
+
<h3>XMLCatalog attributes</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -64,6 +138,7 @@
</table>
<h3>XMLCatalog nested elements</h3>
+<h4>dtd/entity</h4>
<p>The <code>dtd</code> and <code>entity</code> elements used to specify
XMLCatalogs are identical in their structure</p>
<table border="1" cellpadding="2" cellspacing="0">
@@ -84,46 +159,67 @@
<tr>
<td valign="top">location</td>
<td valign="top">The location of the local replacement to be used for
-the
- public identifier specified. This may be specified as a file name,
-resource
- name found on the classpath, or a URL
+the public identifier specified. This may be specified as a file name,
+resource name found on the classpath, or a URL. Relative paths will
+be resolved according to the base, which by default is the Ant project
+basedir.
</td>
<td valign="top" align="center">Yes</td>
</tr>
</table>
-<h3>Examples</h4>
+<h4>classpath</h4>
+<p>The classpath to use for <a href="#ResolverAlgorithm">entity
+resolution</a>. The nested <code><classpath></code> is a
+<a href="../using.html#path">path</a>-like structure.</p>
+<h3>Examples</h3>
<p>Set up an XMLCatalog with a single dtd referenced locally in a user's
home
directory:</p>
<blockquote><pre>
<xmlcatalog>
- <dtd publicId="-//OASIS//DTD DocBook XML V4.1.2//EN"
- location="/home/dion/downloads/docbook/docbookx.dtd"/>
+ <dtd
+ publicId="-//OASIS//DTD DocBook XML V4.1.2//EN"
+ location="/home/dion/downloads/docbook/docbookx.dtd"/>
</xmlcatalog>
</pre></blockquote>
-<p>Set up an XMLCatalog with a multiple dtds referenced locally in a
-user's home
-directory:</p>
+<p>Set up an XMLCatalog with a multiple dtds to be found either in the
+filesystem (relative to the Ant project basedir) or in the classpath:
+</p>
<blockquote><pre>
<xmlcatalog id="commonDTDs">
- <dtd publicId="-//OASIS//DTD DocBook XML V4.1.2//EN"
- location="/home/dion/downloads/docbook/docbookx.dtd"/>
- <dtd publicId="-//Sun Microsystems, Inc.//DTD Web
-Application 2.2//EN"
- location="/home/dion/web-app_2_2.dtd"/>
+ <dtd
+ publicId="-//OASIS//DTD DocBook XML V4.1.2//EN"
+ location="docbook/docbookx.dtd"/>
+ <dtd
+ publicId="-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
+ location="web-app_2_2.dtd"/>
+ </xmlcatalog>
+</pre></blockquote>
+
+<p>Set up an XMLCatalog with a combination of DTDs and entities as
+well as a nested XMLCatalog:</p>
+
+<blockquote><pre>
+ <xmlcatalog id="allcatalogs">
+ <dtd
+ publicId="-//ArielPartners//DTD XML Article V1.0//EN"
+ location="com/arielpartners/knowledgebase/dtd/article.dtd"/>
+ <entity
+ publicId="LargeLogo"
+ location="com/arielpartners/images/ariel-logo-large.gif"/>
+ <xmlcatalog refid="commonDTDs"/>
</xmlcatalog>
</pre></blockquote>
-<p>To reference the above xmlcatalog in a style task:<p>
+<p>To reference the above XMLCatalog in an <code>xslt</code> task:<p>
<blockquote><pre>
- <style basedir="${source.doc}"
+ <xslt basedir="${source.doc}"
destdir="${dest.xdocs}"
extension=".xml"
style="${source.xsl.converter.docbook}"
includes="**/*.xml"
force="true">
- <xmlcatalog refid="commonDTDs"/>
- </style>
+ <xmlcatalog refid="allcatalogs"/>
+ </xslt>
</pre></blockquote>
<hr>
No revision
No revision
1.1.2.1 +484 -0 jakarta-ant/src/testcases/org/apache/tools/ant/types/Attic/XMLCatalogTest.java
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>