diff --git a/src/parsers/SAX2XMLReaderImpl.cpp b/src/parsers/SAX2XMLReaderImpl.cpp index c175dd7831be0545b48fca0494ddc7e27d886ac2..76f488ae503129a30104cbc3579b6f2d2a334937 100644 --- a/src/parsers/SAX2XMLReaderImpl.cpp +++ b/src/parsers/SAX2XMLReaderImpl.cpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.24 2002/01/28 17:08:47 knoaman + * SAX2-ext's DeclHandler support. + * * Revision 1.23 2002/01/28 16:29:21 knoaman * The namespace-prefixes feature in SAX2 should be off by default. * @@ -177,6 +180,7 @@ #include <util/XMLUniDefs.hpp> #include <sax2/ContentHandler.hpp> #include <sax2/LexicalHandler.hpp> +#include <sax2/DeclHandler.hpp> #include <sax/DTDHandler.hpp> #include <sax/ErrorHandler.hpp> #include <sax/EntityResolver.hpp> @@ -367,6 +371,7 @@ SAX2XMLReaderImpl::SAX2XMLReaderImpl() : , fEntityResolver(0) , fErrorHandler(0) , fLexicalHandler(0) + , fDeclHandler(0) , fAdvDHCount(0) , fAdvDHList(0) , fAdvDHListSize(32) @@ -584,6 +589,15 @@ void SAX2XMLReaderImpl::setLexicalHandler(LexicalHandler* const handler) fScanner->setDocTypeHandler(0); } +void SAX2XMLReaderImpl::setDeclarationHandler(DeclHandler* const handler) +{ + fDeclHandler = handler; + if (fDeclHandler) + fScanner->setDocTypeHandler(this); + else + fScanner->setDocTypeHandler(0); +} + void SAX2XMLReaderImpl::setEntityResolver(EntityResolver* const resolver) { @@ -1112,7 +1126,50 @@ void SAX2XMLReaderImpl::attDef( const DTDElementDecl& elemDecl , const DTDAttDef& attDef , const bool ignoring) { - // Unused by SAX DTDHandler interface at this time + if (fDeclHandler && !ignoring) { + + XMLAttDef::AttTypes attType = attDef.getType(); + XMLAttDef::DefAttTypes defAttType = attDef.getDefaultType(); + const XMLCh* defAttTypeStr = XMLUni::fgNullString; + bool isEnumeration = (attType == XMLAttDef::Notation || attType == XMLAttDef::Enumeration); + XMLBuffer enumBuf(128); + + if (defAttType == XMLAttDef::Fixed || + defAttType == XMLAttDef::Implied || + defAttType == XMLAttDef::Required) { + defAttTypeStr = attDef.getDefAttTypeString(defAttType); + } + + if (isEnumeration) { + + const XMLCh* enumString = attDef.getEnumeration(); + unsigned int enumLen = XMLString::stringLen(enumString); + + if (attType == XMLAttDef::Notation) { + + enumBuf.set(XMLUni::fgNotationString); + enumBuf.append(chSpace); + } + + enumBuf.append(chOpenParen); + + for (unsigned int i=0; i<enumLen; i++) { + if (enumString[i] == chSpace) + enumBuf.append(chPipe); + else + enumBuf.append(enumString[i]); + } + + enumBuf.append(chCloseParen); + } + + fDeclHandler->attributeDecl(elemDecl.getFullName(), + attDef.getFullName(), + (isEnumeration) ? enumBuf.getRawBuffer() + : attDef.getAttTypeString(attDef.getType()), + defAttTypeStr, + attDef.getValue()); + } } @@ -1149,9 +1206,12 @@ void SAX2XMLReaderImpl::doctypeWhitespace( const XMLCh* const chars } -void SAX2XMLReaderImpl::elementDecl(const DTDElementDecl&, const bool) +void SAX2XMLReaderImpl::elementDecl(const DTDElementDecl& elemDecl, + const bool isIgnored) { - // Unused by SAX DTDHandler interface at this time + if (fDeclHandler && !isIgnored) + fDeclHandler->elementDecl(elemDecl.getFullName(), + elemDecl.getFormattedContentModel()); } @@ -1187,19 +1247,54 @@ void SAX2XMLReaderImpl::entityDecl( const DTDEntityDecl& entityDecl { // // If we have a DTD handler, and this entity is not ignored, and - // its an unparsed entity, then send this one. + // its an unparsed entity, then send this one, else if we have a Decl + // handler then send this one. // - if (fDTDHandler && !isIgnored) - { - if (entityDecl.isUnparsed()) - { - fDTDHandler->unparsedEntityDecl - ( - entityDecl.getName() - , entityDecl.getPublicId() - , entityDecl.getSystemId() - , entityDecl.getNotationName() - ); + if (!isIgnored) { + + if (entityDecl.isUnparsed()) { + + if (fDTDHandler) { + fDTDHandler->unparsedEntityDecl + ( + entityDecl.getName() + , entityDecl.getPublicId() + , entityDecl.getSystemId() + , entityDecl.getNotationName() + ); + } + } + else if (fDeclHandler) { + + const XMLCh* entityName = entityDecl.getName(); + ArrayJanitor<XMLCh> tmpNameJan(0); + + if (isPEDecl) { + + unsigned int nameLen = XMLString::stringLen(entityName); + XMLCh* tmpName = new XMLCh[nameLen + 2]; + + tmpNameJan.reset(tmpName); + tmpName[0] = chPercent; + XMLString::copyString(tmpName + 1, entityName); + entityName = tmpName; + } + + if (entityDecl.isExternal()) { + fDeclHandler->externalEntityDecl + ( + entityName + , entityDecl.getPublicId() + , entityDecl.getSystemId() + ); + } + else { + fDeclHandler->internalEntityDecl + ( + entityName + , entityDecl.getValue() + ); + } } } } diff --git a/src/parsers/SAX2XMLReaderImpl.hpp b/src/parsers/SAX2XMLReaderImpl.hpp index 2e6ddc17b54f228dc79aa9d628a3219e061b951e..82477f2e104981079c49b33857a905ed9b9c42fa 100644 --- a/src/parsers/SAX2XMLReaderImpl.hpp +++ b/src/parsers/SAX2XMLReaderImpl.hpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.20 2002/01/28 17:08:47 knoaman + * SAX2-ext's DeclHandler support. + * * Revision 1.19 2002/01/24 16:30:34 tng * [Bug 3111] Problem with LexicalHandler::startDTD() and LexicalHandler::endDTD() . * @@ -144,6 +147,7 @@ class ContentHandler; class LexicalHandler; +class DeclHandler; /** * This class implements the SAX2 'XMLReader' interface and should be @@ -477,6 +481,13 @@ public : */ virtual LexicalHandler* getLexicalHandler() const ; + /** + * This method returns the installed declaration handler. + * + * @return A pointer to the installed declaration handler object. + */ + virtual DeclHandler* getDeclarationHandler() const ; + /** * This method returns the state of the parser's * exit-on-First-Fatal-Error flag. @@ -611,6 +622,24 @@ public : */ virtual void setLexicalHandler(LexicalHandler* const handler) ; + /** + * Allow an application to register a declaration event handler. + * + * If the application does not register a declaration handler, + * all events reported by the SAX parser will be silently + * ignored. (this is the default behaviour implemented by DefaultHandler). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The DTD declaration handler. + * @see DeclHandler#DeclHandler + * @see SAXException#SAXException + * @see DefaultHandler#DefaultHandler + */ + virtual void setDeclarationHandler(DeclHandler* const handler); + /** * This method allows users to set the parser's behaviour when it * encounters the first fatal error. If set to true, the parser @@ -1393,6 +1422,9 @@ private : // fLexicalHandler // The installed SAX lexical handler, if any. Null if none. // + // fDecllHandler + // The installed SAX declaration handler, if any. Null if none. + // // fAdvDHCount // fAdvDHList // fAdvDHListSize @@ -1436,6 +1468,7 @@ private : EntityResolver* fEntityResolver; ErrorHandler* fErrorHandler; LexicalHandler* fLexicalHandler; + DeclHandler* fDeclHandler; unsigned int fAdvDHCount; XMLDocumentHandler** fAdvDHList; unsigned int fAdvDHListSize; @@ -1483,6 +1516,11 @@ inline LexicalHandler* SAX2XMLReaderImpl::getLexicalHandler() const return fLexicalHandler; } +inline DeclHandler* SAX2XMLReaderImpl::getDeclarationHandler() const +{ + return fDeclHandler; +} + inline bool SAX2XMLReaderImpl::getExitOnFirstFatalError() const { return fScanner->getExitOnFirstFatal(); diff --git a/src/sax2/DeclHandler.hpp b/src/sax2/DeclHandler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..87bc1c7340e191f52ac4097ccb369d3ed660ee32 --- /dev/null +++ b/src/sax2/DeclHandler.hpp @@ -0,0 +1,203 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2000 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Xerces" and "Apache Software Foundation" must + * not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact apache\@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * nor may "Apache" appear in their name, without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation, and was + * originally based on software copyright (c) 1999, International + * Business Machines, Inc., http://www.ibm.com . For more information + * on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/* + * $Log$ + * Revision 1.1 2002/01/28 17:08:33 knoaman + * SAX2-ext's DeclHandler support. + * + */ + + +#ifndef DECLHANDLER_HPP +#define DECLHANDLER_HPP + +#include <util/XercesDefs.hpp> + + +/** + * Receive notification of DTD declaration events. + * + * <p>This is an optional extension handler for SAX2 to provide more + * complete information about DTD declarations in an XML document. + * XML readers are not required to recognize this handler, and it is not + * part of core-only SAX2 distributions.</p> + * + * <p>Note that data-related DTD declarations (unparsed entities and + * notations) are already reported through the DTDHandler interface.</p> + * + * <p>If you are using the declaration handler together with a lexical + * handler, all of the events will occur between the startDTD and the endDTD + * events.</p> + * + * @see SAX2XMLReader#setLexicalHandler + * @see SAX2XMLReader#setDeclarationHandler + */ + +class SAX2_EXPORT DeclHandler +{ +public: + /** @name Constructors and Destructor */ + //@{ + /** Default constructor */ + DeclHandler() + { + } + + /** Destructor */ + virtual ~DeclHandler() + { + } + //@} + + /** @name The virtual declaration handler interface */ + + //@{ + /** + * Report an element type declaration. + * + * <p>The content model will consist of the string "EMPTY", the string + * "ANY", or a parenthesised group, optionally followed by an occurrence + * indicator. The model will be normalized so that all parameter entities + * are fully resolved and all whitespace is removed,and will include the + * enclosing parentheses. Other normalization (such as removing redundant + * parentheses or simplifying occurrence indicators) is at the discretion + * of the parser.</p> + * + * @param name The element type name. + * @param model The content model as a normalized string. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void elementDecl + ( + const XMLCh* const name + , const XMLCh* const model + ) = 0; + + /** + * Report an attribute type declaration. + * + * <p>The Parser will call this method to report each occurence of + * a comment in the XML document.</p> + * + * <p>The application must not attempt to read from the array + * outside of the specified range.</p> + * + * @param eName The name of the associated element. + * @param aName The name of the attribute. + * @param type A string representing the attribute type. + * @param mode A string representing the attribute defaulting mode ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if none of these applies. + * @param value A string representing the attribute's default value, or null if there is none. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void attributeDecl + ( + const XMLCh* const eName + , const XMLCh* const aName + , const XMLCh* const type + , const XMLCh* const mode + , const XMLCh* const value + ) = 0; + + /** + * Report an internal entity declaration. + * + * <p>Only the effective (first) declaration for each entity will be + * reported. All parameter entities in the value will be expanded, but + * general entities will not.</p> + * + * @param name The name of the entity. If it is a parameter entity, the name will begin with '%'. + * @param value The replacement text of the entity. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void internalEntityDecl + ( + const XMLCh* const name + , const XMLCh* const value + ) = 0; + + /** + * Report a parsed external entity declaration. + * + * <p>Only the effective (first) declaration for each entity will + * be reported.</p> + * + * @param name The name of the entity. If it is a parameter entity, the name will begin with '%'. + * @param publicId The The declared public identifier of the entity, or null if none was declared. + * @param systemId The declared system identifier of the entity. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void externalEntityDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ) = 0; + + //@} +private : + /* Unimplemented Constructors and operators */ + /* Copy constructor */ + DeclHandler(const DeclHandler&); + /** Assignment operator */ + void operator=(const DeclHandler&); +}; + +#endif diff --git a/src/sax2/DefaultHandler.hpp b/src/sax2/DefaultHandler.hpp index 92dfc149588db802d0852eaa2eb3ced84de88be1..2985bc58a9298fc1b88221dd4c4344c2e6061729 100644 --- a/src/sax2/DefaultHandler.hpp +++ b/src/sax2/DefaultHandler.hpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.6 2002/01/28 17:08:33 knoaman + * SAX2-ext's DeclHandler support. + * * Revision 1.5 2001/11/13 13:24:05 tng * Fix documentation for DefaultHandler. * @@ -82,6 +85,7 @@ #include <sax2/ContentHandler.hpp> #include <sax2/LexicalHandler.hpp> +#include <sax2/DeclHandler.hpp> #include <sax/DTDHandler.hpp> #include <sax/EntityResolver.hpp> #include <sax/ErrorHandler.hpp> @@ -95,7 +99,7 @@ class Attributes; * * <p>This class implements the default behaviour for SAX2 * interfaces: EntityResolver, DTDHandler, ContentHandler, - * ErrorHandler, and LexicalHandler.</p> + * ErrorHandler, LexicalHandler, and DeclHandler.</p> * * <p>Application writers can extend this class when they need to * implement only part of an interface; parser writers can @@ -109,6 +113,7 @@ class Attributes; * @see ContentHandler#ContentHandler * @see ErrorHandler#ErrorHandler * @see LexicalHandler#LexicalHandler + * @see DeclHandler#DeclHandler */ class SAX2_EXPORT DefaultHandler : @@ -116,8 +121,9 @@ class SAX2_EXPORT DefaultHandler : public EntityResolver, public DTDHandler, public ContentHandler, - public ErrorHandler, - public LexicalHandler + public ErrorHandler, + public LexicalHandler, + public DeclHandler { public: /** @name Default handlers for the DocumentHandler interface */ @@ -594,6 +600,94 @@ public: virtual void startEntity (const XMLCh* const name); //@} + + /** @name Default implementation of DeclHandler interface. */ + + //@{ + + /** + * Report an element type declaration. + * + * <p>The content model will consist of the string "EMPTY", the string + * "ANY", or a parenthesised group, optionally followed by an occurrence + * indicator. The model will be normalized so that all parameter entities + * are fully resolved and all whitespace is removed,and will include the + * enclosing parentheses. Other normalization (such as removing redundant + * parentheses or simplifying occurrence indicators) is at the discretion + * of the parser.</p> + * + * @param name The element type name. + * @param model The content model as a normalized string. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void elementDecl + ( + const XMLCh* const name + , const XMLCh* const model + ); + + /** + * Report an attribute type declaration. + * + * <p>Only the effective (first) declaration for an attribute will + * be reported.</p> + * + * @param eName The name of the associated element. + * @param aName The name of the attribute. + * @param type A string representing the attribute type. + * @param mode A string representing the attribute defaulting mode ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if none of these applies. + * @param value A string representing the attribute's default value, or null if there is none. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void attributeDecl + ( + const XMLCh* const eName + , const XMLCh* const aName + , const XMLCh* const type + , const XMLCh* const mode + , const XMLCh* const value + ); + + /** + * Report an internal entity declaration. + * + * <p>Only the effective (first) declaration for each entity will be + * reported. All parameter entities in the value will be expanded, but + * general entities will not.</p> + * + * @param name The name of the entity. If it is a parameter entity, the name will begin with '%'. + * @param value The replacement text of the entity. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void internalEntityDecl + ( + const XMLCh* const name + , const XMLCh* const value + ); + + /** + * Report a parsed external entity declaration. + * + * <p>Only the effective (first) declaration for each entity will + * be reported.</p> + * + * @param name The name of the entity. If it is a parameter entity, the name will begin with '%'. + * @param publicId The The declared public identifier of the entity, or null if none was declared. + * @param systemId The declared system identifier of the entity. + * @exception SAXException Any SAX exception, possibly + * wrapping another exception. + */ + virtual void externalEntityDecl + ( + const XMLCh* const name + , const XMLCh* const publicId + , const XMLCh* const systemId + ); + + //@} }; @@ -734,4 +828,28 @@ inline void DefaultHandler::startEntity (const XMLCh* const name) { } +inline void DefaultHandler::attributeDecl(const XMLCh* const, + const XMLCh* const, + const XMLCh* const, + const XMLCh* const, + const XMLCh* const) +{ +} + +inline void DefaultHandler::elementDecl(const XMLCh* const, + const XMLCh* const) +{ +} + +inline void DefaultHandler::externalEntityDecl(const XMLCh* const, + const XMLCh* const, + const XMLCh* const) +{ +} + +inline void DefaultHandler::internalEntityDecl(const XMLCh* const, + const XMLCh* const) +{ +} + #endif // ! DEFAULTHANDLER_HPP diff --git a/src/sax2/Makefile.in b/src/sax2/Makefile.in index 02040027decb4b6a359a45253d9aa3ba9e63b567..bf65c63bb6b1ac1b9bab04f18a77991a54af9385 100644 --- a/src/sax2/Makefile.in +++ b/src/sax2/Makefile.in @@ -81,6 +81,7 @@ SAX2_CPP_PUBHEADERS = \ ContentHandler.hpp \ DefaultHandler.hpp \ LexicalHandler.hpp \ + DeclHandler.hpp \ SAX2XMLReader.hpp \ XMLReaderFactory.hpp diff --git a/src/sax2/SAX2XMLReader.hpp b/src/sax2/SAX2XMLReader.hpp index 95a503484829d6b8f3267d24596fd3751ea6934d..d70cc6a46f0cf3a475c86d50ebe764911868baeb 100644 --- a/src/sax2/SAX2XMLReader.hpp +++ b/src/sax2/SAX2XMLReader.hpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.17 2002/01/28 17:08:33 knoaman + * SAX2-ext's DeclHandler support. + * * Revision 1.16 2002/01/18 16:31:26 tng * Break program.xml which takes too long to load, into program-sax.xml, program-sax2.xml, program-dom.xml, program-idom.xml. * @@ -135,6 +138,7 @@ class EntityResolver; class ErrorHandler; class InputSource; class LexicalHandler; +class DeclHandler; class XMLDocumentHandler; class SAX2_EXPORT SAX2XMLReader @@ -216,6 +220,13 @@ public: */ virtual LexicalHandler* getLexicalHandler() const = 0 ; + /** + * This method returns the installed declaration handler. + * + * @return A pointer to the installed declaration handler object. + */ + virtual DeclHandler* getDeclarationHandler() const = 0 ; + /** * Query the current state of any feature in a SAX2 XMLReader. * @@ -438,6 +449,24 @@ public: */ virtual void setLexicalHandler(LexicalHandler* const handler) = 0; + /** + * Allow an application to register a declaration event handler. + * + * If the application does not register a declaration handler, + * all events reported by the SAX parser will be silently + * ignored. (this is the default behaviour implemented by DefaultHandler). + * + * Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately. + * + * @param handler The DTD declaration handler. + * @see DeclHandler#DeclHandler + * @see SAXException#SAXException + * @see DefaultHandler#DefaultHandler + */ + virtual void setDeclarationHandler(DeclHandler* const handler) = 0; + /** * This method allows users to set the parser's behaviour when it * encounters the first fatal error. If set to true, the parser