This one is definitely in the "use at your own risk" category. I needed the capability for an XML document to be validated from a Schema AND include short fragments. Currently you can have a DOCTYPE with an internal DTD and ENTITY definitions OR you can validate from a Schema, but not both. I got fed up with trying to sort through XLink, XPointer, XFragment, XPath, the XSchema 12/17 draft, and the rest of the XYouGottaBeKiddings so I took the brute force approach and patched XMLParser.java to get external entities from an internal DTD subset but still validate the rest of the document (and the included entities) against a Schema.
<!DOCTYPE document [ <!ENTITY abc SYSTEM "abc.xml"> ]> <document xmlns="doc.xsd"> ... &abc; ... </document> The patch to XMLParser.java works for me and is certainly not long-term but I would have otherwise had to scrap Schemas in my project and write a ton of custom validation code to supplement the DTD. I've been looking at XMLParser for only a few hours (and it's now 3AM) so if anyone sees problems in the appended diff or can point out alternatives I might have missed, I'd be glad to hear about them. George *************************************** *** XMLParserOrig.java Wed Jan 05 15:12:16 2000 --- XMLParser.java Fri Jan 07 01:04:08 2000 *************** *** 2005,2011 **** /** Scan doctype decl. */ public void scanDoctypeDecl(boolean standalone) throws Exception { fScanningDTD = true; ! fCheckedForSchema = true; fStandaloneDocument = standalone; fValidator = fDTDValidator; fDTDValidator.scanDoctypeDecl(standalone); --- 2005,2011 ---- /** Scan doctype decl. */ public void scanDoctypeDecl(boolean standalone) throws Exception { fScanningDTD = true; ! // fCheckedForSchema = true; fStandaloneDocument = standalone; fValidator = fDTDValidator; fDTDValidator.scanDoctypeDecl(standalone); *************** *** 2413,2419 **** public boolean startReadingFromEntity(int entityName, int readerDepth, int context) throws Exception { if (context > XMLEntityHandler.CONTEXT_IN_CONTENT) return startReadingFromParameterEntity(entityName, readerDepth, context); ! int entityHandle = fValidator.lookupEntity(entityName); if (entityHandle < 0) { int minorCode = XMLMessages.VC_ENTITY_DECLARED; int errorType = XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR; --- 2413,2419 ---- public boolean startReadingFromEntity(int entityName, int readerDepth, int context) throws Exception { if (context > XMLEntityHandler.CONTEXT_IN_CONTENT) return startReadingFromParameterEntity(entityName, readerDepth, context); ! int entityHandle = fDTDValidator.lookupEntity(entityName); if (entityHandle < 0) { int minorCode = XMLMessages.VC_ENTITY_DECLARED; int errorType = XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR; *************** *** 2432,2438 **** return false; } if (context == CONTEXT_IN_CONTENT) { ! if (fValidator.isUnparsedEntity(entityHandle)) { Object[] args = { fStringPool.toString(entityName) }; fErrorReporter.reportError(fErrorReporter.getLocator(), XMLMessages.XML_DOMAIN, --- 2432,2438 ---- return false; } if (context == CONTEXT_IN_CONTENT) { ! if (fDTDValidator.isUnparsedEntity(entityHandle)) { Object[] args = { fStringPool.toString(entityName) }; fErrorReporter.reportError(fErrorReporter.getLocator(), XMLMessages.XML_DOMAIN, *************** *** 2443,2449 **** return false; } } else { ! if (fValidator.isExternalEntity(entityHandle)) { Object[] args = { fStringPool.toString(entityName) }; fErrorReporter.reportError(fErrorReporter.getLocator(), XMLMessages.XML_DOMAIN, --- 2443,2449 ---- return false; } } else { ! if (fDTDValidator.isExternalEntity(entityHandle)) { Object[] args = { fStringPool.toString(entityName) }; fErrorReporter.reportError(fErrorReporter.getLocator(), XMLMessages.XML_DOMAIN, *************** *** 2470,2490 **** fEntityContext = context; fReaderDepth = readerDepth; fReaderId = fNextReaderId++; ! if (context != CONTEXT_IN_CONTENT || !fValidator.externalReferenceInContent(entityHandle)) { fEntityType = ENTITYTYPE_INTERNAL; fPublicId = null/*"Internal Entity: " + fStringPool.toString(entityName)*/; fSystemId = fSystemId; // keep expandSystemId happy int value = -1; if (context == CONTEXT_IN_CONTENT || context == CONTEXT_IN_DEFAULTATTVALUE) ! value = fValidator.getEntityValue(entityHandle); else ! value = fValidator.valueOfReferenceInAttValue(entityHandle); startReadingFromInternalEntity(value, false); return false; } fEntityType = ENTITYTYPE_EXTERNAL; ! fPublicId = fValidator.getPublicIdOfEntity(entityHandle); ! fSystemId = fValidator.getSystemIdOfEntity(entityHandle); return startReadingFromExternalEntity(true); } private boolean startReadingFromParameterEntity(int peName, int readerDepth, int context) throws Exception { --- 2470,2490 ---- fEntityContext = context; fReaderDepth = readerDepth; fReaderId = fNextReaderId++; ! if (context != CONTEXT_IN_CONTENT || !fDTDValidator.externalReferenceInContent(entityHandle)) { fEntityType = ENTITYTYPE_INTERNAL; fPublicId = null/*"Internal Entity: " + fStringPool.toString(entityName)*/; fSystemId = fSystemId; // keep expandSystemId happy int value = -1; if (context == CONTEXT_IN_CONTENT || context == CONTEXT_IN_DEFAULTATTVALUE) ! value = fDTDValidator.getEntityValue(entityHandle); else ! value = fDTDValidator.valueOfReferenceInAttValue(entityHandle); startReadingFromInternalEntity(value, false); return false; } fEntityType = ENTITYTYPE_EXTERNAL; ! fPublicId = fDTDValidator.getPublicIdOfEntity(entityHandle); ! fSystemId = fDTDValidator.getSystemIdOfEntity(entityHandle); return startReadingFromExternalEntity(true); } private boolean startReadingFromParameterEntity(int peName, int readerDepth, int context) throws Exception {