  | |  | Resolved: (XERCESJ-1250) Relative URI not being resolved correctly when c | Resolved: (XERCESJ-1250) Relative URI not being resolved correctly when c 2007-05-11 - By Michael Glavassevich (JIRA)
[ https://issues.apache.org/jira/browse/XERCESJ-1250?page=com.atlassian .jira.plugin.system.issuetabpanels:all-tabpanel ]
Michael Glavassevich resolved XERCESJ-1250. -------------------------------------------
Resolution: Invalid
This is a common usage error. When you only provide a InputStream or Reader the parser has no idea what the base URI of your document is. You need to set the system identifier [1] on the InputSource.
[1] http://xerces.apache.org/xerces2-j/javadocs/api/org/xml/sax/InputSource .html#setSystemId(java.lang.String)
> Relative URI not being resolved correctly when client code calls SAX parser through org.xml.sax.XMLReader(InputSource) interface > ----------------------------------------------------------------------------- --------------------------------------------------- > > Key: XERCESJ-1250 > URL: https://issues.apache.org/jira/browse/XERCESJ-1250 > Project: Xerces2-J > Issue Type: Bug > Components: DTD > Affects Versions: 2.9.0 > Environment: Windows XP Operating System, JDK 1.5.0_11 > Reporter: James Hurley > > The problem appears when client code calls the underlying implementation through the org.xml.sax.XMLReader.parse(InputSource) interface method in the JDK and the input source is set to an XML file that has a relative URI specified in its <!DOCTYPE...> delcaration. The result is that the URI resolution never attempts to resolve against the local directory containing the file and skips straight to resolving against the current system path. So, if I specify a document type declaration as (and let us pretend that this declaration is on some file that is in %BUILD_HOME%/config/MyCfgFile.xml): > <!DOCTYPE Config SYSTEM "MyDTD.dtd"> > > then I invoke the parser from a path %BUILD_HOME%\bin, the resolution of the URI will resolve against the current system path (i.e., %BUILD_HOME%\bin) instead of first trying to resolve against the directory containing the file (i .e., %BUILD_HOME%\config). > To clearly illustrate and reproduce the problem I constructed a test case that will reproduce it every time. The test case demonstrates the un-reliable resolving behavior by first demonstrating the resolving behavior of the implementation beneath the org.xml.sax.XMLReader.parse(String) method (which behaves as expected) then showing the results of calling the org.xml.sax .XMLReader.parse(InputSource) method. I pasted the source and instructions on recreating the test environment below (I didn't immediately see any way to simply zip the directory up from my local machine and attach it to this bug report). > The test requires the following directory structure to be setup at some location %TEST_HOME%: > %TEST_HOME%\bin > %TEST_HOME%\config > %TEST_HOME%\lib > %TEST_HOME%\lib\version_2.9.0 > %TEST_HOME%\src > ------------------------------------------ > In the %TEST_HOME%\bin directory create a batch script called "RelativePathsTest.bat" and add to this file the following script: > @(protected) off > rem > rem Run the test for the 2.6.2 Xerces version. Note that we begin by first > rem running the environment check to ensure that the proper parser version > rem got loaded. We'll then output the parser version number and execute > rem the test. > rem > set XERCES_HOME=%CD%\..\lib\version_2.9.0 > call java -classpath %XERCES_HOME%\..\xalan.jar;%XERCES_HOME%\resolver.jar; %XERCES_HOME%\xercesImpl.jar;%XERCES_HOME%\xml-apis.jar;%XERCES_HOME% \xmlParserAPIs.jar org.apache.xalan.xslt.EnvironmentCheck > ./tmp_env_output.txt > echo. > echo. *********************************************************************** *** > echo. First run the test with the default version of Xerces that ships with > echo. JDK 1.5. According to the release notes this should be version 2.6.2 > echo. *********************************************************************** *** > echo. > echo. Results from Xerces environment check: > findstr /L "version.xerces2" tmp_env_output.txt > echo. > echo. Test Results: > echo. > call java -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp .SAXParserFactoryImpl -classpath %XERCES_HOME%\..\xalan.jar;%XERCES_HOME% \resolver.jar;%XERCES_HOME%\xercesImpl.jar;%XERCES_HOME%\xml-apis.jar;%XERCES _HOME%\xmlParserAPIs.jar;%CD%\..\classes RelativePathTest ..\config\TestCfg.xml > rem > rem Now run the test for the 2.9.0 Xerces version > rem > echo. > echo. > echo. *********************************************************************** *** > echo. Now run the test with the latest version of Xerces. According to the > echo. apachewebsite (http://xerces.apache.org/xerces2-j/) this should be the > echo. 2.9.0 release. > echo. *********************************************************************** *** > call java -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp .SAXParserFactoryImpl -classpath %XERCES_HOME%\..\xalan.jar;%XERCES_HOME% \resolver.jar;%XERCES_HOME%\xercesImpl.jar;%XERCES_HOME%\xml-apis.jar;%XERCES _HOME%\serializer.jar org.apache.xalan.xslt.EnvironmentCheck > ./tmp_env_output .txt > echo. > echo. Results from Xerces environment check: > findstr /L "version.xerces2" tmp_env_output.txt > echo. > echo. Test Results: > echo. > call java -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp .SAXParserFactoryImpl -classpath %XERCES_HOME%\..\xalan.jar;%XERCES_HOME% \resolver.jar;%XERCES_HOME%\xercesImpl.jar;%XERCES_HOME%\xml-apis.jar;%XERCES _HOME%\serializer.jar;%CD%\..\classes RelativePathTest ..\config\TestCfg.xml > ------------------------------------- > In the %TEST_HOME%\bin directory create a DTD file named "RelativePathTest .dtd" and add to it the following content: > <!ELEMENT TestRoot (#PCDATA)> > <!ENTITY testText "This is the DTD from the /bin directory"> > ------------------------------------------ > In the %TEST_HOME%\src directory create a class called "RelativePathTest.java " and add to it the code pasted below. Note that before running the test you will need to compile this class and then move the RelativePathTest.class file to the %TEST_HOME%\classes directory (since this is where the .bat script used to run the test will set the classpath to). > //JDK imports > import java.io.BufferedReader; > import java.io.File; > import java.io.FileReader; > import org.xml.sax.Attributes; > import org.xml.sax.ContentHandler; > import org.xml.sax.InputSource; > import org.xml.sax.Locator; > import org.xml.sax.SAXException; > import org.xml.sax.XMLReader; > import org.xml.sax.helpers.XMLReaderFactory; > public class RelativePathTest > { > public static void main(String args[]) > { > try > { > // > // First run the parsing using the XMLReader.parse(String) method. This will > // result in the expected output. This way there is a benchmark against which > // to compare the output from the problematic method. > // > System.out.println("\nTest output using XMLReader.parse(String systemID) method:"); > XMLReader reader = XMLReaderFactory.createXMLReader(); > XMLEventHandler handler = new XMLEventHandler(); > reader.setContentHandler(handler); > reader.setFeature("http://xml.org/sax/features/validation", true); > reader.parse(args[0]); > > // > // Now run the parsing and use the XMLReader.parse(InputSource) method. This will > // product the unexpected output. > // > System.out.println("\n\nTest output using XMLReader.parse (InputSource input) method:"); > reader = XMLReaderFactory.createXMLReader(); > reader.setContentHandler(handler); > reader.setFeature("http://xml.org/sax/features/validation", true); > BufferedReader buffReader = new BufferedReader(new FileReader (args[0])); > reader.parse(new InputSource(buffReader)); > } > catch(Throwable th) > { > th.printStackTrace(); > } > } > > > /** > * A private test class that will handle the parsing events and output results > * to the screen. > */ > public static class XMLEventHandler implements ContentHandler > { > public void characters(char[] ch, int start, int length) > throws SAXException > { > StringBuilder charData = new StringBuilder(); > for(int charCntr = start; charCntr < length; charCntr++) > { > charData.append(ch[charCntr]); > } > System.out.println("XMLReader results: " + charData.toString()); > } > > public void endDocument() > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > public void endElement(String uri, String localName, String qName) > throws SAXException > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > public void endPrefixMapping(String prefix) > throws SAXException > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > public void ignorableWhitespace(char[] ch, int start, int length) > throws SAXException > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > public void processingInstruction(String target, String data) > throws SAXException > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > public void setDocumentLocator(Locator locator) > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > public void skippedEntity(String name) > throws SAXException > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > public void startDocument() > throws SAXException > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > public void startElement(String uri, String localName, String qName, Attributes atts) > throws SAXException > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > public void startPrefixMapping(String prefix, String uir) > throws SAXException > { > //Defined to be in agreement with the ContentHandler interface; Not used in this > //test though so this method has no implementation. > > } > > } //end inner class XMLEventHandler > > } //end class RelativePathTest > ------------------------------------------ > In the %TEST_HOME%\config directory, create an XML file called "TestCfg.xml" and add to it the following content: > <!DOCTYPE TestRoot SYSTEM "RelativePathTest.dtd"> > <TestRoot> > &testText; > </TestRoot > ----------------------------------------- > Finally create a DTD file called "RelativePathTest.dtd" in the %TEST_HOME% \config directory and add to it the content listed below: > <!ELEMENT TestRoot (#PCDATA)> > <!ENTITY testText "This is the DTD from the /config directory"> > ---------------------------------------- > Finally, the test was set up to output the Xerces version it was testing and was built to test both the standard version shipping with JDK 1.5 > (i.e, Xerces version 2.6.2) and the latest version I could find on your site (version 2.9.0). To do this a copy of the xalan.jar file had to be placed in the %TEST_HOME%\lib directory (this way the environment detection code could be executed to output the Xerces version number) and the jar files for the 2.9.0 release had to be placed into the %TEST_HOME%\lib\version_2.9.0 directory. In my test here I included all jars (i.e., resolver.jar, serializer.jar, xercesImpl.jar, and xml-apis.jar). > To run the test you only need to go to the %TEST_HOME%\bin directory and execute the RelativePathsTest.bat (make sure java home is in the path). There are no necessary arguments to the script. > The output from the test demonstrates that when using the underlying implementation for the org.xml.sax.XMLReader.parse(String) method, the logic correctly tries to resolve the relative URI for the DTD against the directory containing the TestCfg.xml file (resulting in the output "This is the DTD from the /config directory". This is the expected output. Then the test shows that the output from the org.xml.sax.XMLReader.parse(InputSource) method results in "This is the DTD from the /bin directory". This shows that the underlying implementation totally skips over resolving the relative URL against the path containing the XML file and goes straight to a resolution against the current system path. This is the unexpected result. The test also demonstrates that this behavior is inherent in the 2.6.2 version of Xerces (shipped with JDK 1.5) as well as in the latest release. The anticipated behavior would be for both parse methods to behave identically and attempt to resolve the relative URI against the file path containing the XML file first (since according to RFC 2396, Uniform Resource Identifiers, section 5.1 the behavior for resolving relative URI's should use the location of the resource defining the URI as a base as the 3rd resolution option) before moving on to trying the current system path.
-- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.
--------------------------------------------------------------------- To unsubscribe, e-mail: j-dev-unsubscribe@(protected) For additional commands, e-mail: j-dev-help@(protected)
|
|
 |