Bump for 3.6-28
[LibreOffice.git] / sax / source / fastparser / fastparser.cxx
blobb773d8a188389983047e6b926caeb0e864adbedf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <boost/scoped_ptr.hpp>
31 #include <osl/diagnose.h>
32 #include <rtl/ustrbuf.hxx>
34 #include <com/sun/star/lang/DisposedException.hpp>
35 #include <com/sun/star/xml/sax/XFastContextHandler.hpp>
36 #include <com/sun/star/xml/sax/SAXParseException.hpp>
37 #include <com/sun/star/xml/sax/FastToken.hpp>
39 #include "fastparser.hxx"
41 #include <string.h>
43 using ::rtl::OString;
44 using ::rtl::OUString;
45 using ::rtl::OUStringBuffer;
46 using namespace ::std;
47 using namespace ::osl;
48 using namespace ::cppu;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star::xml::sax;
52 using namespace ::com::sun::star::io;
54 namespace sax_fastparser {
56 // --------------------------------------------------------------------
58 struct SaxContextImpl
60 Reference< XFastContextHandler > mxContext;
61 sal_uInt32 mnNamespaceCount;
62 sal_Int32 mnElementToken;
63 OUString maNamespace;
64 OUString maElementName;
66 SaxContextImpl() { mnNamespaceCount = 0; mnElementToken = 0; }
67 SaxContextImpl( const SaxContextImplPtr& p ) { mnNamespaceCount = p->mnNamespaceCount; mnElementToken = p->mnElementToken; maNamespace = p->maNamespace; }
70 // --------------------------------------------------------------------
72 struct NamespaceDefine
74 OString maPrefix;
75 sal_Int32 mnToken;
76 OUString maNamespaceURL;
78 NamespaceDefine( const OString& rPrefix, sal_Int32 nToken, const OUString& rNamespaceURL ) : maPrefix( rPrefix ), mnToken( nToken ), maNamespaceURL( rNamespaceURL ) {}
81 // --------------------------------------------------------------------
82 // FastLocatorImpl
83 // --------------------------------------------------------------------
85 class FastSaxParser;
87 class FastLocatorImpl : public WeakImplHelper1< XLocator >
89 public:
90 FastLocatorImpl( FastSaxParser *p ) : mpParser(p) {}
92 void dispose() { mpParser = 0; }
93 void checkDispose() throw (RuntimeException) { if( !mpParser ) throw DisposedException(); }
95 //XLocator
96 virtual sal_Int32 SAL_CALL getColumnNumber(void) throw (RuntimeException);
97 virtual sal_Int32 SAL_CALL getLineNumber(void) throw (RuntimeException);
98 virtual OUString SAL_CALL getPublicId(void) throw (RuntimeException);
99 virtual OUString SAL_CALL getSystemId(void) throw (RuntimeException);
101 private:
102 FastSaxParser *mpParser;
105 // --------------------------------------------------------------------
106 // FastSaxParser
107 // --------------------------------------------------------------------
109 //---------------------------------------------
110 // the implementation part
111 //---------------------------------------------
113 extern "C" {
115 static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
117 FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
118 pFastParser->callbackStartElement( name, atts );
121 static void call_callbackEndElement(void *userData, const XML_Char *name)
123 FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
124 pFastParser->callbackEndElement( name );
127 static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
129 FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
130 pFastParser->callbackCharacters( s, nLen );
133 static void call_callbackEntityDecl(void *userData, const XML_Char *entityName,
134 int is_parameter_entity, const XML_Char *value, int value_length,
135 const XML_Char *base, const XML_Char *systemId,
136 const XML_Char *publicId, const XML_Char *notationName)
138 FastSaxParser* pFastParser = reinterpret_cast<FastSaxParser*>(userData);
139 pFastParser->callbackEntityDecl(entityName, is_parameter_entity, value,
140 value_length, base, systemId, publicId, notationName);
143 static int call_callbackExternalEntityRef( XML_Parser parser,
144 const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId )
146 FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( XML_GetUserData( parser ) );
147 return pFastParser->callbackExternalEntityRef( parser, openEntityNames, base, systemId, publicId );
150 } // extern "C"
152 // --------------------------------------------------------------------
153 // FastLocatorImpl implementation
154 // --------------------------------------------------------------------
156 sal_Int32 SAL_CALL FastLocatorImpl::getColumnNumber(void) throw (RuntimeException)
158 checkDispose();
159 return XML_GetCurrentColumnNumber( mpParser->getEntity().mpParser );
162 // --------------------------------------------------------------------
164 sal_Int32 SAL_CALL FastLocatorImpl::getLineNumber(void) throw (RuntimeException)
166 checkDispose();
167 return XML_GetCurrentLineNumber( mpParser->getEntity().mpParser );
170 // --------------------------------------------------------------------
172 OUString SAL_CALL FastLocatorImpl::getPublicId(void) throw (RuntimeException)
174 checkDispose();
175 return mpParser->getEntity().maStructSource.sPublicId;
177 // --------------------------------------------------------------------
179 OUString SAL_CALL FastLocatorImpl::getSystemId(void) throw (RuntimeException)
181 checkDispose();
182 return mpParser->getEntity().maStructSource.sSystemId;
185 // --------------------------------------------------------------------
187 ParserData::ParserData()
191 ParserData::~ParserData()
195 // --------------------------------------------------------------------
197 Entity::Entity( const ParserData& rData ) :
198 ParserData( rData )
200 // performance-Improvment. Reference is needed when calling the startTag callback.
201 // Handing out the same object with every call is allowed (see sax-specification)
202 mxAttributes.set( new FastAttributeList( mxTokenHandler ) );
205 Entity::~Entity()
209 // --------------------------------------------------------------------
210 // FastSaxParser implementation
211 // --------------------------------------------------------------------
213 FastSaxParser::FastSaxParser()
215 mxDocumentLocator.set( new FastLocatorImpl( this ) );
218 // --------------------------------------------------------------------
220 FastSaxParser::~FastSaxParser()
222 if( mxDocumentLocator.is() )
223 mxDocumentLocator->dispose();
226 // --------------------------------------------------------------------
228 void FastSaxParser::pushContext()
230 Entity& rEntity = getEntity();
231 if( rEntity.maContextStack.empty() )
233 rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl ) );
234 DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
236 else
238 rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl( rEntity.maContextStack.top() ) ) );
242 // --------------------------------------------------------------------
244 void FastSaxParser::popContext()
246 Entity& rEntity = getEntity();
247 OSL_ENSURE( !rEntity.maContextStack.empty(), "sax::FastSaxParser::popContext(), pop without push?" );
248 if( !rEntity.maContextStack.empty() )
249 rEntity.maContextStack.pop();
252 // --------------------------------------------------------------------
254 void FastSaxParser::DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL )
256 Entity& rEntity = getEntity();
257 OSL_ENSURE( !rEntity.maContextStack.empty(), "sax::FastSaxParser::DefineNamespace(), I need a context!" );
258 if( !rEntity.maContextStack.empty() )
260 sal_uInt32 nOffset = rEntity.maContextStack.top()->mnNamespaceCount++;
262 if( rEntity.maNamespaceDefines.size() <= nOffset )
263 rEntity.maNamespaceDefines.resize( rEntity.maNamespaceDefines.size() + 64 );
265 const OUString aNamespaceURL( pNamespaceURL, strlen( pNamespaceURL ), RTL_TEXTENCODING_UTF8 );
266 rEntity.maNamespaceDefines[nOffset].reset( new NamespaceDefine( rPrefix, GetNamespaceToken( aNamespaceURL ), aNamespaceURL ) );
270 // --------------------------------------------------------------------
272 sal_Int32 FastSaxParser::GetToken( const OString& rToken )
274 Sequence< sal_Int8 > aSeq( (sal_Int8*)rToken.getStr(), rToken.getLength() );
276 return getEntity().mxTokenHandler->getTokenFromUTF8( aSeq );
279 sal_Int32 FastSaxParser::GetToken( const sal_Char* pToken, sal_Int32 nLen /* = 0 */ )
281 if( !nLen )
282 nLen = strlen( pToken );
284 Sequence< sal_Int8 > aSeq( (sal_Int8*)pToken, nLen );
286 return getEntity().mxTokenHandler->getTokenFromUTF8( aSeq );
289 // --------------------------------------------------------------------
291 sal_Int32 FastSaxParser::GetTokenWithPrefix( const OString& rPrefix, const OString& rName ) throw (SAXException)
293 sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
295 Entity& rEntity = getEntity();
296 sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
297 while( nNamespace-- )
299 if( rEntity.maNamespaceDefines[nNamespace]->maPrefix == rPrefix )
301 nNamespaceToken = rEntity.maNamespaceDefines[nNamespace]->mnToken;
302 break;
305 if( !nNamespace )
306 throw SAXException(); // prefix that has no defined namespace url
309 if( nNamespaceToken != FastToken::DONTKNOW )
311 sal_Int32 nNameToken = GetToken( rName.getStr(), rName.getLength() );
312 if( nNameToken != FastToken::DONTKNOW )
313 return nNamespaceToken | nNameToken;
316 return FastToken::DONTKNOW;
319 sal_Int32 FastSaxParser::GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (SAXException)
321 sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
323 Entity& rEntity = getEntity();
324 sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
325 while( nNamespace-- )
327 const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix );
328 if( (rPrefix.getLength() == nPrefixLen) &&
329 (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
331 nNamespaceToken = rEntity.maNamespaceDefines[nNamespace]->mnToken;
332 break;
335 if( !nNamespace )
336 throw SAXException(); // prefix that has no defined namespace url
339 if( nNamespaceToken != FastToken::DONTKNOW )
341 sal_Int32 nNameToken = GetToken( pName, nNameLen );
342 if( nNameToken != FastToken::DONTKNOW )
343 return nNamespaceToken | nNameToken;
346 return FastToken::DONTKNOW;
349 // --------------------------------------------------------------------
351 sal_Int32 FastSaxParser::GetNamespaceToken( const OUString& rNamespaceURL )
353 NamespaceMap::iterator aIter( maNamespaceMap.find( rNamespaceURL ) );
354 if( aIter != maNamespaceMap.end() )
355 return (*aIter).second;
356 else
357 return FastToken::DONTKNOW;
360 // --------------------------------------------------------------------
362 OUString FastSaxParser::GetNamespaceURL( const OString& rPrefix ) throw (SAXException)
364 Entity& rEntity = getEntity();
365 if( !rEntity.maContextStack.empty() )
367 sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
368 while( nNamespace-- )
369 if( rEntity.maNamespaceDefines[nNamespace]->maPrefix == rPrefix )
370 return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL;
373 throw SAXException(); // prefix that has no defined namespace url
376 OUString FastSaxParser::GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw(SAXException)
378 Entity& rEntity = getEntity();
379 if( pPrefix && !rEntity.maContextStack.empty() )
381 sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
382 while( nNamespace-- )
384 const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix );
385 if( (rPrefix.getLength() == nPrefixLen) &&
386 (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
388 return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL;
393 throw SAXException(); // prefix that has no defined namespace url
396 // --------------------------------------------------------------------
398 sal_Int32 FastSaxParser::GetTokenWithNamespaceURL( const OUString& rNamespaceURL, const sal_Char* pName, int nNameLen )
400 sal_Int32 nNamespaceToken = GetNamespaceToken( rNamespaceURL );
402 if( nNamespaceToken != FastToken::DONTKNOW )
404 sal_Int32 nNameToken = GetToken( pName, nNameLen );
405 if( nNameToken != FastToken::DONTKNOW )
406 return nNamespaceToken | nNameToken;
409 return FastToken::DONTKNOW;
412 // --------------------------------------------------------------------
414 void FastSaxParser::splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen )
416 XML_Char *p;
417 for( p = const_cast< XML_Char* >( pwName ), rNameLen = 0, rPrefixLen = 0; *p; p++ )
419 if( *p == ':' )
421 rPrefixLen = p - pwName;
422 rNameLen = 0;
424 else
426 rNameLen++;
429 if( rPrefixLen )
431 rpPrefix = pwName;
432 rpName = &pwName[ rPrefixLen + 1 ];
434 else
436 rpPrefix = 0;
437 rpName = pwName;
441 /***************
443 * parseStream does Parser-startup initializations. The FastSaxParser::parse() method does
444 * the file-specific initialization work. (During a parser run, external files may be opened)
446 ****************/
447 void FastSaxParser::parseStream( const InputSource& maStructSource) throw (SAXException, IOException, RuntimeException)
449 // Only one text at one time
450 MutexGuard guard( maMutex );
452 Entity entity( maData );
453 entity.maStructSource = maStructSource;
455 if( !entity.maStructSource.aInputStream.is() )
456 throw SAXException( OUString( "No input source" ), Reference< XInterface >(), Any() );
458 entity.maConverter.setInputStream( entity.maStructSource.aInputStream );
459 if( !entity.maStructSource.sEncoding.isEmpty() )
460 entity.maConverter.setEncoding( OUStringToOString( entity.maStructSource.sEncoding, RTL_TEXTENCODING_ASCII_US ) );
462 // create parser with proper encoding
463 entity.mpParser = XML_ParserCreate( 0 );
464 if( !entity.mpParser )
465 throw SAXException( OUString( "Couldn't create parser" ), Reference< XInterface >(), Any() );
467 // set all necessary C-Callbacks
468 XML_SetUserData( entity.mpParser, this );
469 XML_SetElementHandler( entity.mpParser, call_callbackStartElement, call_callbackEndElement );
470 XML_SetCharacterDataHandler( entity.mpParser, call_callbackCharacters );
471 XML_SetEntityDeclHandler(entity.mpParser, call_callbackEntityDecl);
472 XML_SetExternalEntityRefHandler( entity.mpParser, call_callbackExternalEntityRef );
474 pushEntity( entity );
477 // start the document
478 if( entity.mxDocumentHandler.is() )
480 Reference< XLocator > xLoc( mxDocumentLocator.get() );
481 entity.mxDocumentHandler->setDocumentLocator( xLoc );
482 entity.mxDocumentHandler->startDocument();
485 parse();
487 // finish document
488 if( entity.mxDocumentHandler.is() )
490 entity.mxDocumentHandler->endDocument();
493 catch (const SAXException&)
495 popEntity();
496 XML_ParserFree( entity.mpParser );
497 throw;
499 catch (const IOException&)
501 popEntity();
502 XML_ParserFree( entity.mpParser );
503 throw;
505 catch (const RuntimeException&)
507 popEntity();
508 XML_ParserFree( entity.mpParser );
509 throw;
512 popEntity();
513 XML_ParserFree( entity.mpParser );
516 void FastSaxParser::setFastDocumentHandler( const Reference< XFastDocumentHandler >& Handler ) throw (RuntimeException)
518 maData.mxDocumentHandler = Handler;
521 void SAL_CALL FastSaxParser::setTokenHandler( const Reference< XFastTokenHandler >& Handler ) throw (RuntimeException)
523 maData.mxTokenHandler = Handler;
526 void SAL_CALL FastSaxParser::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
528 if( NamespaceToken >= FastToken::NAMESPACE )
530 if( GetNamespaceToken( NamespaceURL ) == FastToken::DONTKNOW )
532 maNamespaceMap[ NamespaceURL ] = NamespaceToken;
533 return;
536 throw IllegalArgumentException();
539 OUString SAL_CALL FastSaxParser::getNamespaceURL( const OUString& rPrefix ) throw(IllegalArgumentException, RuntimeException)
543 return GetNamespaceURL( OUStringToOString( rPrefix, RTL_TEXTENCODING_UTF8 ) );
545 catch (const Exception&)
548 throw IllegalArgumentException();
551 void FastSaxParser::setErrorHandler(const Reference< XErrorHandler > & Handler) throw (RuntimeException)
553 maData.mxErrorHandler = Handler;
556 void FastSaxParser::setEntityResolver(const Reference < XEntityResolver > & Resolver) throw (RuntimeException)
558 maData.mxEntityResolver = Resolver;
561 void FastSaxParser::setLocale( const Locale & Locale ) throw (RuntimeException)
563 maData.maLocale = Locale;
566 Sequence< OUString > FastSaxParser::getSupportedServiceNames_Static(void)
568 Sequence<OUString> aRet(1);
569 aRet.getArray()[0] = ::rtl::OUString( PARSER_SERVICE_NAME );
570 return aRet;
573 // XServiceInfo
574 OUString FastSaxParser::getImplementationName() throw (RuntimeException)
576 return OUString( PARSER_IMPLEMENTATION_NAME );
579 // XServiceInfo
580 sal_Bool FastSaxParser::supportsService(const OUString& ServiceName) throw (RuntimeException)
582 Sequence< OUString > aSNL = getSupportedServiceNames();
583 const OUString * pArray = aSNL.getConstArray();
585 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
586 if( pArray[i] == ServiceName )
587 return sal_True;
589 return sal_False;
592 // XServiceInfo
593 Sequence< OUString > FastSaxParser::getSupportedServiceNames(void) throw (RuntimeException)
596 Sequence<OUString> seq(1);
597 seq.getArray()[0] = OUString( PARSER_SERVICE_NAME );
598 return seq;
602 /*---------------------------------------
604 * Helper functions and classes
606 *-------------------------------------------*/
608 namespace {
610 OUString lclGetErrorMessage( XML_Error xmlE, const OUString& sSystemId, sal_Int32 nLine )
612 const sal_Char* pMessage = "";
613 switch( xmlE )
615 case XML_ERROR_NONE: pMessage = "No"; break;
616 case XML_ERROR_NO_MEMORY: pMessage = "no memory"; break;
617 case XML_ERROR_SYNTAX: pMessage = "syntax"; break;
618 case XML_ERROR_NO_ELEMENTS: pMessage = "no elements"; break;
619 case XML_ERROR_INVALID_TOKEN: pMessage = "invalid token"; break;
620 case XML_ERROR_UNCLOSED_TOKEN: pMessage = "unclosed token"; break;
621 case XML_ERROR_PARTIAL_CHAR: pMessage = "partial char"; break;
622 case XML_ERROR_TAG_MISMATCH: pMessage = "tag mismatch"; break;
623 case XML_ERROR_DUPLICATE_ATTRIBUTE: pMessage = "duplicate attribute"; break;
624 case XML_ERROR_JUNK_AFTER_DOC_ELEMENT: pMessage = "junk after doc element"; break;
625 case XML_ERROR_PARAM_ENTITY_REF: pMessage = "parameter entity reference"; break;
626 case XML_ERROR_UNDEFINED_ENTITY: pMessage = "undefined entity"; break;
627 case XML_ERROR_RECURSIVE_ENTITY_REF: pMessage = "recursive entity reference"; break;
628 case XML_ERROR_ASYNC_ENTITY: pMessage = "async entity"; break;
629 case XML_ERROR_BAD_CHAR_REF: pMessage = "bad char reference"; break;
630 case XML_ERROR_BINARY_ENTITY_REF: pMessage = "binary entity reference"; break;
631 case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF: pMessage = "attribute external entity reference"; break;
632 case XML_ERROR_MISPLACED_XML_PI: pMessage = "misplaced xml processing instruction"; break;
633 case XML_ERROR_UNKNOWN_ENCODING: pMessage = "unknown encoding"; break;
634 case XML_ERROR_INCORRECT_ENCODING: pMessage = "incorrect encoding"; break;
635 case XML_ERROR_UNCLOSED_CDATA_SECTION: pMessage = "unclosed cdata section"; break;
636 case XML_ERROR_EXTERNAL_ENTITY_HANDLING: pMessage = "external entity reference"; break;
637 case XML_ERROR_NOT_STANDALONE: pMessage = "not standalone"; break;
638 default:;
641 OUStringBuffer aBuffer( sal_Unicode( '[' ) );
642 aBuffer.append( sSystemId );
643 aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " line " ) );
644 aBuffer.append( nLine );
645 aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "]: " ) );
646 aBuffer.appendAscii( pMessage );
647 aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " error" ) );
648 return aBuffer.makeStringAndClear();
651 } // namespace
653 // starts parsing with actual parser !
654 void FastSaxParser::parse()
656 const int BUFFER_SIZE = 16 * 1024;
657 Sequence< sal_Int8 > seqOut( BUFFER_SIZE );
659 Entity& rEntity = getEntity();
660 int nRead = 0;
663 nRead = rEntity.maConverter.readAndConvert( seqOut, BUFFER_SIZE );
664 if( nRead <= 0 )
666 XML_Parse( rEntity.mpParser, (const char*) seqOut.getConstArray(), 0, 1 );
667 break;
670 bool bContinue = XML_Parse( rEntity.mpParser, (const char*) seqOut.getConstArray(), nRead, 0 ) != 0;
671 // callbacks used inside XML_Parse may have caught an exception
672 if( !bContinue || rEntity.maSavedException.hasValue() )
674 // Error during parsing !
675 XML_Error xmlE = XML_GetErrorCode( rEntity.mpParser );
676 OUString sSystemId = mxDocumentLocator->getSystemId();
677 sal_Int32 nLine = mxDocumentLocator->getLineNumber();
679 SAXParseException aExcept(
680 lclGetErrorMessage( xmlE, sSystemId, nLine ),
681 Reference< XInterface >(),
682 Any( &rEntity.maSavedException, getCppuType( &rEntity.maSavedException ) ),
683 mxDocumentLocator->getPublicId(),
684 mxDocumentLocator->getSystemId(),
685 mxDocumentLocator->getLineNumber(),
686 mxDocumentLocator->getColumnNumber()
689 // error handler is set, it may throw the exception
690 if( rEntity.mxErrorHandler.is() )
691 rEntity.mxErrorHandler->fatalError( Any( aExcept ) );
693 // error handler has not thrown, but parsing cannot go on, the
694 // exception MUST be thrown
695 throw aExcept;
698 while( nRead > 0 );
701 //------------------------------------------
703 // The C-Callbacks
705 //-----------------------------------------
707 namespace {
709 struct AttributeData
711 OString maPrefix;
712 OString maName;
713 OString maValue;
716 } // namespace
718 void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes )
720 Reference< XFastContextHandler > xParentContext;
721 Entity& rEntity = getEntity();
722 if( !rEntity.maContextStack.empty() )
724 xParentContext = rEntity.maContextStack.top()->mxContext;
725 if( !xParentContext.is() )
727 // we ignore current elements, so no processing needed
728 pushContext();
729 return;
733 pushContext();
735 rEntity.mxAttributes->clear();
737 // create attribute map and process namespace instructions
738 int i = 0;
739 sal_Int32 nNameLen, nPrefixLen;
740 const XML_Char *pName;
741 const XML_Char *pPrefix;
745 /* #158414# Each element may define new namespaces, also for attribues.
746 First, process all namespace attributes and cache other attributes in a
747 vector. Second, process the attributes after namespaces have been
748 initialized. */
749 ::std::vector< AttributeData > aAttribs;
751 // #158414# first: get namespaces
752 for( ; awAttributes[i]; i += 2 )
754 OSL_ASSERT( awAttributes[i+1] );
756 splitName( awAttributes[i], pPrefix, nPrefixLen, pName, nNameLen );
757 if( nPrefixLen )
759 if( (nPrefixLen == 5) && (strncmp( pPrefix, "xmlns", 5 ) == 0) )
761 DefineNamespace( OString( pName, nNameLen ), awAttributes[i+1] );
763 else
765 aAttribs.resize( aAttribs.size() + 1 );
766 aAttribs.back().maPrefix = OString( pPrefix, nPrefixLen );
767 aAttribs.back().maName = OString( pName, nNameLen );
768 aAttribs.back().maValue = OString( awAttributes[i+1] );
771 else
773 if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) )
775 // namespace of the element found
776 rEntity.maContextStack.top()->maNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 );
778 else
780 aAttribs.resize( aAttribs.size() + 1 );
781 aAttribs.back().maName = OString( pName, nNameLen );
782 aAttribs.back().maValue = OString( awAttributes[i+1] );
787 // #158414# second: fill attribute list with other attributes
788 for( ::std::vector< AttributeData >::const_iterator aIt = aAttribs.begin(), aEnd = aAttribs.end(); aIt != aEnd; ++aIt )
790 if( !aIt->maPrefix.isEmpty() )
792 sal_Int32 nAttributeToken = GetTokenWithPrefix( aIt->maPrefix, aIt->maName );
793 if( nAttributeToken != FastToken::DONTKNOW )
794 rEntity.mxAttributes->add( nAttributeToken, aIt->maValue );
795 else
796 rEntity.mxAttributes->addUnknown( GetNamespaceURL( aIt->maPrefix ), aIt->maName, aIt->maValue );
798 else
800 sal_Int32 nAttributeToken = GetToken( aIt->maName );
801 if( nAttributeToken != FastToken::DONTKNOW )
802 rEntity.mxAttributes->add( nAttributeToken, aIt->maValue );
803 else
804 rEntity.mxAttributes->addUnknown( aIt->maName, aIt->maValue );
808 sal_Int32 nElementToken;
809 splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen );
810 if( nPrefixLen > 0 )
811 nElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen );
812 else if( !rEntity.maContextStack.top()->maNamespace.isEmpty() )
813 nElementToken = GetTokenWithNamespaceURL( rEntity.maContextStack.top()->maNamespace, pName, nNameLen );
814 else
815 nElementToken = GetToken( pName );
816 rEntity.maContextStack.top()->mnElementToken = nElementToken;
818 Reference< XFastAttributeList > xAttr( rEntity.mxAttributes.get() );
819 Reference< XFastContextHandler > xContext;
820 if( nElementToken == FastToken::DONTKNOW )
822 if( nPrefixLen > 0 )
823 rEntity.maContextStack.top()->maNamespace = GetNamespaceURL( pPrefix, nPrefixLen );
825 const OUString aNamespace( rEntity.maContextStack.top()->maNamespace );
826 const OUString aElementName( pPrefix, nPrefixLen, RTL_TEXTENCODING_UTF8 );
827 rEntity.maContextStack.top()->maElementName = aElementName;
829 if( xParentContext.is() )
830 xContext = xParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
831 else
832 xContext = rEntity.mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
834 if( xContext.is() )
836 rEntity.maContextStack.top()->mxContext = xContext;
837 xContext->startUnknownElement( aNamespace, aElementName, xAttr );
840 else
842 if( xParentContext.is() )
843 xContext = xParentContext->createFastChildContext( nElementToken, xAttr );
844 else
845 xContext = rEntity.mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
848 if( xContext.is() )
850 rEntity.maContextStack.top()->mxContext = xContext;
851 xContext->startFastElement( nElementToken, xAttr );
855 catch (const Exception& e)
857 rEntity.maSavedException <<= e;
861 void FastSaxParser::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* )
863 Entity& rEntity = getEntity();
864 OSL_ENSURE( !rEntity.maContextStack.empty(), "FastSaxParser::callbackEndElement - no context" );
865 if( !rEntity.maContextStack.empty() )
867 SaxContextImplPtr pContext = rEntity.maContextStack.top();
868 const Reference< XFastContextHandler >& xContext( pContext->mxContext );
869 if( xContext.is() ) try
871 sal_Int32 nElementToken = pContext->mnElementToken;
872 if( nElementToken != FastToken::DONTKNOW )
873 xContext->endFastElement( nElementToken );
874 else
875 xContext->endUnknownElement( pContext->maNamespace, pContext->maElementName );
877 catch (const Exception& e)
879 rEntity.maSavedException <<= e;
882 popContext();
887 void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen )
889 Entity& rEntity = getEntity();
890 const Reference< XFastContextHandler >& xContext( rEntity.maContextStack.top()->mxContext );
891 if( xContext.is() ) try
893 xContext->characters( OUString( s, nLen, RTL_TEXTENCODING_UTF8 ) );
895 catch (const Exception& e)
897 rEntity.maSavedException <<= e;
901 void FastSaxParser::callbackEntityDecl(
902 SAL_UNUSED_PARAMETER const XML_Char * /*entityName*/,
903 SAL_UNUSED_PARAMETER int /*is_parameter_entity*/,
904 const XML_Char *value, SAL_UNUSED_PARAMETER int /*value_length*/,
905 SAL_UNUSED_PARAMETER const XML_Char * /*base*/,
906 SAL_UNUSED_PARAMETER const XML_Char * /*systemId*/,
907 SAL_UNUSED_PARAMETER const XML_Char * /*publicId*/,
908 SAL_UNUSED_PARAMETER const XML_Char * /*notationName*/)
910 if (value) { // value != 0 means internal entity
911 OSL_TRACE("FastSaxParser: internal entity declaration, stopping");
912 XML_StopParser(getEntity().mpParser, XML_FALSE);
913 getEntity().maSavedException <<= SAXParseException(
914 ::rtl::OUString(
915 "FastSaxParser: internal entity declaration, stopping"),
916 static_cast<OWeakObject*>(this), Any(),
917 mxDocumentLocator->getPublicId(),
918 mxDocumentLocator->getSystemId(),
919 mxDocumentLocator->getLineNumber(),
920 mxDocumentLocator->getColumnNumber() );
921 } else {
922 OSL_TRACE("FastSaxParser: ignoring external entity declaration");
926 int FastSaxParser::callbackExternalEntityRef(
927 XML_Parser parser, const XML_Char *context,
928 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
929 const XML_Char *publicId )
931 bool bOK = true;
932 InputSource source;
934 Entity& rCurrEntity = getEntity();
935 Entity aNewEntity( rCurrEntity );
937 if( rCurrEntity.mxEntityResolver.is() ) try
939 aNewEntity.maStructSource = rCurrEntity.mxEntityResolver->resolveEntity(
940 OUString( publicId, strlen( publicId ), RTL_TEXTENCODING_UTF8 ) ,
941 OUString( systemId, strlen( systemId ), RTL_TEXTENCODING_UTF8 ) );
943 catch (const SAXParseException & e)
945 rCurrEntity.maSavedException <<= e;
946 bOK = false;
948 catch (const SAXException& e)
950 rCurrEntity.maSavedException <<= SAXParseException(
951 e.Message, e.Context, e.WrappedException,
952 mxDocumentLocator->getPublicId(),
953 mxDocumentLocator->getSystemId(),
954 mxDocumentLocator->getLineNumber(),
955 mxDocumentLocator->getColumnNumber() );
956 bOK = false;
959 if( aNewEntity.maStructSource.aInputStream.is() )
961 aNewEntity.mpParser = XML_ExternalEntityParserCreate( parser, context, 0 );
962 if( !aNewEntity.mpParser )
964 return false;
967 aNewEntity.maConverter.setInputStream( aNewEntity.maStructSource.aInputStream );
968 pushEntity( aNewEntity );
971 parse();
973 catch (const SAXParseException& e)
975 rCurrEntity.maSavedException <<= e;
976 bOK = false;
978 catch (const IOException& e)
980 SAXException aEx;
981 aEx.WrappedException <<= e;
982 rCurrEntity.maSavedException <<= aEx;
983 bOK = false;
985 catch (const RuntimeException& e)
987 SAXException aEx;
988 aEx.WrappedException <<= e;
989 rCurrEntity.maSavedException <<= aEx;
990 bOK = false;
993 popEntity();
994 XML_ParserFree( aNewEntity.mpParser );
997 return bOK;
1000 } // namespace sax_fastparser
1002 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */