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