Hi (and Happy Holidays) I have a case where a dtd is located in a peer directory of the document, so that the document does something like
<!DOCTYPE messages SYSTEM "../dtd/messages.dtd">
We then have messages.dtd doing an external entity reference to another dtd,
in this case, language.dtd. The file language.dtd is located in the same
directory as messages.dtd.
<!ENTITY % language SYSTEM "language.dtd">
%language;
Running the document through the parser gets the following error:
DOMCount -v C:/TEMP/p2/docs/small.xml
Fatal Error at (file C:\TEMP\p2\docs\../dtd/messages.dtd, line 6, char 11):
An exception occured!
Type:RuntimeException, Message:Could not open external entity
'C:\TEMP\p2\docs\language.dtd'
I pretty sure (let me know if I'm wrong about this) that language.dtd is in
the correct place, but the file name is being assembled incorrectly.
Here's a patch that shows where I think the problem is, with the
test files attached.
Thanks!
John
diff -c -r xerces-cvs-build/c/src/internal/ReaderMgr.cpp
xerces-ReaderMgr/c/src/internal/ReaderMgr.cpp
*** xerces-cvs-build/c/src/internal/ReaderMgr.cpp Sat Dec 18 00:48:28 1999
--- xerces-ReaderMgr/c/src/internal/ReaderMgr.cpp Thu Dec 23 00:28:29 1999
***************
*** 548,556 ****
// Its just a file path
if (XMLPlatformUtils::isRelative(sysId))
{
! // Its relative so first store the base directory, if any
! if (fBasePath)
! expSysId.set(fBasePath);
// And then append the relative path
expSysId.append(sysId);
--- 548,557 ----
// Its just a file path
if (XMLPlatformUtils::isRelative(sysId))
{
! // Its relative so first store the base directory
! XMLCh *pathPtr = getCurrentBasePath();
! ArrayJanitor<XMLCh> janName(pathPtr);
! expSysId.set(pathPtr);
// And then append the relative path
expSysId.append(sysId);
***************
*** 642,647 ****
--- 643,704 ----
// Set the reader number to the next available number
retVal->setReaderNum(fNextReaderNum++);
return retVal;
+ }
+
+
+ XMLCh* ReaderMgr::getCurrentBasePath()
+ {
+ // Create a buffer for computing the current base path
+ XMLBuffer computedBasePath;
+
+ // Start with the parser base if any external entities return relative
+ if (fBasePath)
+ computedBasePath.set(fBasePath);
+
+ // Get the last external entity.
+ LastExtEntityInfo extInfo;
+ getLastExtEntityInfo(extInfo);
+
+ // If the last external entity is valid, form the base path from it.
+ if (XMLString::stringLen(extInfo.systemId))
+ {
+ // Handle URL systemId values.
+ URL tmpURL;
+ try
+ {
+ tmpURL.setURL(extInfo.systemId);
+ const XMLCh * const urlString = tmpURL.getURL();
+
+ // find the character position after the last slash
+ unsigned int afterSlash = 0;
+ unsigned int index = 0;
+ const XMLCh *urlStringPtr = urlString;
+ while (*urlStringPtr)
+ {
+ if (*urlStringPtr == chForwardSlash || *urlStringPtr ==
chBackSlash)
+ afterSlash = index + 1;
+ urlStringPtr++;
+ index++;
+ }
+
+ computedBasePath.set(urlString, afterSlash);
+ }
+
+ catch(const MalformedURLException&)
+ {
+ // A file path.
+ if (XMLPlatformUtils::isRelative(extInfo.systemId))
+ computedBasePath.append(extInfo.systemId);
+ else
+ computedBasePath.set(extInfo.systemId);
+
+ XMLCh *basePathPtr =
XMLPlatformUtils::getBasePath(computedBasePath.getRawBuffer());
+ ArrayJanitor<XMLCh> janName(basePathPtr);
+ computedBasePath.set(basePathPtr);
+ }
+ }
+
+ return XMLString::replicate(computedBasePath.getRawBuffer());
}
diff -c -r xerces-cvs-build/c/src/internal/ReaderMgr.hpp
xerces-ReaderMgr/c/src/internal/ReaderMgr.hpp
*** xerces-cvs-build/c/src/internal/ReaderMgr.hpp Wed Dec 15 23:54:22 1999
--- xerces-ReaderMgr/c/src/internal/ReaderMgr.hpp Wed Dec 22 23:09:18 1999
***************
*** 199,204 ****
--- 199,205 ----
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
+ XMLCh* getCurrentBasePath();
const XMLCh* getCurrentEncodingStr() const;
const XMLEntityDecl* getCurrentEntity() const;
XMLEntityDecl* getCurrentEntity();
<?xml version='1.0' standalone='no'?>
<!DOCTYPE messages SYSTEM "../dtd/messages.dtd">
<messages version="1">
<language id="42" area="51">
<group name="xxy">
<text id="1">stuff</text>
</group>
</language>
</messages>
messages.dtd
Description: Binary data
language.dtd
Description: Binary data
ReaderMgr.patch
Description: Binary data
