views:

384

answers:

1

I tried to use the xslt task in Ant to modify a Hibernate mapping file (*.hbm.xml) using XSLT. However I kept on getting an com.sun.org.apache.xml.internal.utils.WrappedRuntimeException.

If I take out the !DOCTYPE declaration in the source xml file, the following target runs without any error. Could someone please tell me what I'm doing wrong? Thanks!

Here's my Ant target:

<target name="generatePermHbmXml">
  <xslt in="${base.configuration.hibernate.dir}\Test.hbm.xml" 
        out="${base.configuration.hibernate.dir}\TestPerm.hbm.xml"
        style="${base.configuration.hibernate.dir}\perm.xsl">
    <xmlcatalog>
      <dtd publicId="-//Hibernate/Hibernate Mapping DTD//EN"
           location="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"/&gt;
    </xmlcatalog>
  </xslt>    
</target>

Here's my log output:

[xslt] : Error! hibernate.sourceforge.net
[xslt] : Error! com.sun.org.apache.xml.internal.utils.WrappedRuntimeException: hibernate.sourceforge.net

[Edit] Here's the DOCTYPE that I removed to get it working

<!DOCTYPE hibernate-mapping
PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;

[Edit2]: I found a fix, but I don't know whether if it is the "right" way or not. I downloaded the DTD file and placed that in my project dir. I referenced the file (as shown below) instead of the URL, and it seems to be working now.

<xmlcatalog>
  <dtd publicId="-//Hibernate/Hibernate Mapping DTD//EN"
       location="${base.configuration.hibernate.dir}/hibernate-mapping-3.0.dtd"/>
</xmlcatalog>
+2  A: 

Ah, I think I know the problem. In your xslt task, you specified an xmlcatalog:

<xmlcatalog>
  <dtd publicId="-//Hibernate/Hibernate Mapping DTD//EN"
       location="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"/&gt;
</xmlcatalog>

The xmlcatalog is used to help the xslt task find DTDs and other items needed for XML parsing and validation. If you go to the URL you specified as location you do get a DTD. (Which Firefox shows an an empty page, but viewing "page source" you see the DTD contents.) Since the DTD is in fact present at that URL, I don't know exactly why the build had a problem reading that DTD -- maybe there's a difference in encoding or maybe the site didn't respond properly. If you ran ANT with the -verbose option, you would see more of a stack dump around the failure if you really wanted to debug it. You would see the original Exception that got wrapped in the Exception you saw.

Anyway, if you download the DTD in question and then point your location in the dtd element at the local file, as you did:

<xmlcatalog>
  <dtd publicId="-//Hibernate/Hibernate Mapping DTD//EN"
       location="${base.configuration.hibernate.dir}/hibernate-mapping-3.0.dtd"/>
</xmlcatalog>

then the parser can find the DTD it needs, guaranteed, and it works fine.

So yes, your solution is the correct solution. This way, your builds don't depend on an external website being accessible and having a file available.

Eddie