tags:

views:

376

answers:

4

I'm trying to use xmltask for ant to modify a file in a subdirectory:

project/path/to/file.xml

The file refers to a DTD like this:

<!DOCTYPE data SYSTEM "mydtd.dtd">

I don't have the flexibility to change these documents.

This DTD is stored in the same subdirectory, which has always worked fine:

project/path/to/mydtd.dtd

Unfortunately, xmltask is trying to locate the dtd in my project's top-level directory, which is where my build file is located, and where I run from:

[xmltask] java.io.FileNotFoundException: /home/me/project/mydtd.dtd (The system cannot find the file specified)

I see in the xmltask documentation that I can correct this with an xmlcatalog element to tell it where to look up the file. But I need to use a dtd element, and I can only find examples for this element, not documentation; the examples show only a publicId, and if I understand XML correctly this document does not have one. I shouldn't need to specify this, anyway, right, since my document already says my DTD is stored locally and shows right where it is?

Why isn't xmltask finding the DTD correctly? What's the best way to correct or work around this situation?

A: 

Have you tried:

<!DOCTYPE data SYSTEM "./path/to/mydtd.dtd">

? Or an absolute path?

Also, you can find <dtd> description here.

najmeddine
That would wreck all the other handling of these documents, as when they are deployed they are sitting alongside their dtds but not in the same directory where I am trying to edit them at build time.
skiphoppy
The question says "I don't have the flexibility to change these documents."
skaffman
@skaffman, to be fair, it didn't say that when I originally asked, and I added it because of this answer. :)
skiphoppy
Oh, fair enough. Sorry, @najmeddine :)
skaffman
A: 

xmltask isn't finding it because it is looking in the current working directory. Ant allows you to specify a base directory using the basedir attribute of the <target> element. So I suggest you try this:

<target basedir="path/to" ...>
  <xmltask...
</target>

It strikes me that it is not the XML/DTD that you really have the problem with, but getting xmltask to interact with the two of them as you want.

If that fails, you could use the Ant Copy task to copy the XML and DTD to the root folder before processing with xmltask, then copying back again.

David M
Using relative SYSTEM references in this way is bad practise, since resolving them is difficult. Source documents should either use PUBLIC references, or absolute SYSTEM references. Thankfully, XML catalogs (properly applied) can get around this bad design.
skaffman
+2  A: 

An XML Catalog is the way to go here, it just needs a bit more perseverance.

As you correctly pointed out, the standard Ant <XmlCatalog> type only allows you to specify public DTD references when using the inline syntax, which is of no use to you. However, <XmlCatalog> also lets you specify a standard OASIS-syntax catalog, which is far richer, including resolving SYSTEM DTD references.

An OASIS catalog (full spec here) looks like this:

<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">      
  <system systemId="mydtd.dtd" uri="project/path/to/mydtd.dtd"/>
</catalog>

You can then reference this catalog from the <XmlCatalog>:

<xmlcatalog refid="commonDTDs"/>
  <catalogpath>
    <pathelement location="path/to/oasis.catalog"/>
  </catalogpath>
</xmlcatalog>

And that's that. It's a good idea to build up a reusable OASIS catalog file, and refer to it from various XML-related Ant tasks, all of which can use <XmlCatalog>.

skaffman
A: 

As an alternative, it looks like I can skip the whole validation by creating a blank file with the same name as the DVD file, and then deleting the file when I am done. Odds are I am going to go that route instead of using the catalog.

skiphoppy