Skip to Content.
Sympa Menu

xom-interest - [XOM-interest] nu.xom.URIUtil.relativize() fragility prevents round-tripping

xom-interest AT lists.ibiblio.org

Subject: XOM API for Processing XML with Java

List archive

Chronological Thread  
  • From: Wolfgang Hoschek <wolfgang.hoschek AT mac.com>
  • To: xom-interest AT lists.ibiblio.org
  • Subject: [XOM-interest] nu.xom.URIUtil.relativize() fragility prevents round-tripping
  • Date: Fri, 24 Mar 2006 19:35:58 -0800

nu.xom.URIUtil.relativize(documentURL, systemID) is a bit fragile which in turn means that some documents can't be round-tripped. To start out with

1) nu.xom.URIUtil.relativize(documentURL, systemID) is a bit fragile:

String documentURL="file:///Users/hoschek/unix/devel/xom/../xom-1.2/ data/pe.xml"
String systemID= "file:///Users/hoschek/unix/devel/xom-1.2/data/ pe.txt"
System.out.println(nu.xom.URIUtil.relativize(documentURL, systemID))

yields the following bogus output

1.2/data/pe.txt

This relative URL does not exist in the file system, of course.

2) This fragility in turn means that nu.xom.XOMHandler has an incompatibility bug with xerces-2.7.0 and 2.8.1 (but interestingly not with 2.6.2 because it reports systemIDs in a slightly different format) wrt. external entity declarations. To see that, add some print diagnostics to XOMHandler.externalEntityDecl()

public void externalEntityDecl(String name,
String publicID, String systemID) {

System.out.println("3name="+name+", publicID="+publicID+", systemID="+systemID);
if (inInternalSubset() && doctype != null) {
internalDTDSubset.append(" <!ENTITY ");
if (name.startsWith("%")) {
internalDTDSubset.append("% ");
internalDTDSubset.append(name.substring(1));
}
else {
internalDTDSubset.append(name);
}

if (locator != null && URIUtil.isAbsolute(systemID)) {
String documentURL = locator.getSystemId();
System.out.println("systemID1="+systemID);
System.out.println("docURL1="+documentURL);
// work around Crimson style file:/root URLs
if (documentURL != null) {
if (documentURL.startsWith("file:/") && ! documentURL.startsWith("file:///")) {
documentURL = "file://" + documentURL.substring(5);
System.out.println("docURL2="+documentURL);
}
if (systemID.startsWith("file:/") && ! systemID.startsWith("file:///")) {
systemID = "file://" + systemID.substring(5);
System.out.println("systemID2="+systemID);
}

System.out.println("normalizing (docURL,systemID) =\n"+documentURL+"\n"+systemID);
systemID = URIUtil.relativize(documentURL, systemID);
System.out.println("systemID3="+systemID);
}
}

if (publicID != null) {
internalDTDSubset.append(" PUBLIC \"");
internalDTDSubset.append(publicID);
internalDTDSubset.append("\" \"");
internalDTDSubset.append(systemID);
}
else {
// need to escape system ID????
internalDTDSubset.append(" SYSTEM \"");
internalDTDSubset.append(systemID);
}
internalDTDSubset.append("\">\n");

}

}


Now run something like this with xerces-2.8.0:

public class XOMExternalEntityTest {

public static void main(String[] args) throws Exception {
String file = args[0];
// String file = "/Users/hoschek/unix/devel/nux/../nuxtestdata/XOM/ data/pe.xml";
// String file = "/Users/hoschek/unix/devel/nux/nuxtestdata/XOM/data/ pe.xml";
Document doc = new Builder().build(new File(args[0]));
System.out.println(doc.toXML());
}

}


[hoschek /Users/hoschek/unix/devel/xom]
export JAVA_OPTS='-Djava.endorsed.dirs=/Users/hoschek/unix/java/share/ apache/xerces-2.8.0/'

[hoschek /Users/hoschek/unix/devel/xom] fire-java nux.xom.sandbox.XOMExternalEntityTest /Users/hoschek/unix/devel/ xom/../xom-1.2/data/pe.xml
3name=%ccl, publicID=null, systemID=file:///Users/hoschek/unix/devel/ xom-1.2/data/pe.txt
systemID1=file:///Users/hoschek/unix/devel/xom-1.2/data/pe.txt
docURL1=file:///Users/hoschek/unix/devel/xom/../xom-1.2/data/pe.xml
normalizing (docURL,systemID)=
file:///Users/hoschek/unix/devel/xom/../xom-1.2/data/pe.xml
file:///Users/hoschek/unix/devel/xom-1.2/data/pe.txt
systemID3=1.2/data/pe.txt
<?xml version="1.0"?>
<!DOCTYPE doc SYSTEM "pe.dtd" [
<!ENTITY % ccl SYSTEM "1.2/data/pe.txt">
]>
<doc />

[hoschek /Users/hoschek/unix/devel/xom]


3) Again, "1.2/data/pe.txt" is bogus. This in turn means that the document can't be round-tripped. Serializing the document and trying to reparse that will yield to an an exception like this:


Exception in thread "main" java.io.FileNotFoundException:
<some bogus path trailing in /1.2/data/pe.txt goes here> (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:106)
at java.io.FileInputStream.<init>(FileInputStream.java:66)
at sun.net.www.protocol.file.FileURLConnection.connect (FileURLConnection.java:69)
at sun.net.www.protocol.file.FileURLConnection.getInputStream (FileURLConnection.java:156)
at org.apache.xerces.impl.XMLEntityManager.setupCurrentEntity (Unknown Source)
at org.apache.xerces.impl.XMLEntityManager.startEntity (Unknown Source)
at org.apache.xerces.impl.XMLEntityManager.startEntity (Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.startPE(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.skipSeparator (Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanDecls (Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanDTDExternalSubset (Unknown Source)
at org.apache.xerces.impl.XMLDocumentScannerImpl $DTDDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument (Unknown Source)
at org.apache.xerces.parsers.DTDConfiguration.parse(Unknown Source)
at org.apache.xerces.parsers.DTDConfiguration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at nu.xom.Builder.build(Builder.java:1138)
at nu.xom.Builder.build(Builder.java:625)


voila,
Wolfgang.




Archive powered by MHonArc 2.6.24.

Top of Page