merge the formfield patch from ooo-build
[ooovba.git] / sax / source / fastparser / fastparser.cxx
blob26214bbc2ecf6b800487f5606cdf978c7d01439e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fastparser.cxx,v $
10 * $Revision: 1.4.10.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 //#include <stdlib.h>
32 //#include <sal/alloca.h>
34 #include <boost/scoped_ptr.hpp>
36 #include <osl/diagnose.h>
38 #include <com/sun/star/lang/DisposedException.hpp>
39 #include <com/sun/star/xml/sax/XFastContextHandler.hpp>
40 #include <com/sun/star/xml/sax/SAXParseException.hpp>
41 #include <com/sun/star/xml/sax/FastToken.hpp>
43 #include "fastparser.hxx"
45 #include <string.h>
47 using ::rtl::OUString;
48 using ::rtl::OString;
49 using namespace ::std;
50 using namespace ::osl;
51 using namespace ::cppu;
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::lang;
54 using namespace ::com::sun::star::xml::sax;
55 //using namespace ::com::sun::star::util;
56 using namespace ::com::sun::star::io;
57 namespace sax_fastparser
60 // --------------------------------------------------------------------
62 struct SaxContextImpl
64 Reference< XFastContextHandler > mxContext;
65 sal_uInt32 mnNamespaceCount;
66 sal_Int32 mnElementToken;
67 OUString maNamespace;
68 OUString maElementName;
70 SaxContextImpl() { mnNamespaceCount = 0; mnElementToken = 0; }
71 SaxContextImpl( const SaxContextImplPtr& p ) { mnNamespaceCount = p->mnNamespaceCount; mnElementToken = p->mnElementToken; maNamespace = p->maNamespace; }
74 // --------------------------------------------------------------------
76 struct NamespaceDefine
78 OString maPrefix;
79 sal_Int32 mnToken;
80 OUString maNamespaceURL;
82 NamespaceDefine( const OString& rPrefix, sal_Int32 nToken, const OUString& rNamespaceURL ) : maPrefix( rPrefix ), mnToken( nToken ), maNamespaceURL( rNamespaceURL ) {}
85 // --------------------------------------------------------------------
86 // FastLocatorImpl
87 // --------------------------------------------------------------------
89 class FastSaxParser;
91 class FastLocatorImpl : public WeakImplHelper1< XLocator >
93 public:
94 FastLocatorImpl( FastSaxParser *p ) : mpParser(p) {}
96 void dispose() { mpParser = 0; }
97 void checkDispose() throw (RuntimeException) { if( !mpParser ) throw DisposedException(); }
99 //XLocator
100 virtual sal_Int32 SAL_CALL getColumnNumber(void) throw (RuntimeException);
101 virtual sal_Int32 SAL_CALL getLineNumber(void) throw (RuntimeException);
102 virtual OUString SAL_CALL getPublicId(void) throw (RuntimeException);
103 virtual OUString SAL_CALL getSystemId(void) throw (RuntimeException);
105 private:
106 FastSaxParser *mpParser;
109 // --------------------------------------------------------------------
110 // FastSaxParser
111 // --------------------------------------------------------------------
113 //---------------------------------------------
114 // the implementation part
115 //---------------------------------------------
117 extern "C"
119 static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
121 FastSaxParser::callbackStartElement(userData,name,atts);
123 static void call_callbackEndElement(void *userData, const XML_Char *name)
125 FastSaxParser::callbackEndElement(userData,name);
127 static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
129 FastSaxParser::callbackCharacters(userData,s,nLen);
131 static int call_callbackExternalEntityRef(XML_Parser parser,
132 const XML_Char *openEntityNames,
133 const XML_Char *base,
134 const XML_Char *systemId,
135 const XML_Char *publicId)
137 return FastSaxParser::callbackExternalEntityRef(parser,openEntityNames,base,systemId,publicId);
141 // --------------------------------------------------------------------
142 // FastLocatorImpl implementation
143 // --------------------------------------------------------------------
145 sal_Int32 SAL_CALL FastLocatorImpl::getColumnNumber(void) throw (RuntimeException)
147 checkDispose();
148 return XML_GetCurrentColumnNumber( mpParser->getEntity().mpParser );
151 // --------------------------------------------------------------------
153 sal_Int32 SAL_CALL FastLocatorImpl::getLineNumber(void) throw (RuntimeException)
155 checkDispose();
156 return XML_GetCurrentLineNumber( mpParser->getEntity().mpParser );
159 // --------------------------------------------------------------------
161 OUString SAL_CALL FastLocatorImpl::getPublicId(void) throw (RuntimeException)
163 checkDispose();
164 return mpParser->getEntity().maStructSource.sPublicId;
166 // --------------------------------------------------------------------
168 OUString SAL_CALL FastLocatorImpl::getSystemId(void) throw (RuntimeException)
170 checkDispose();
171 return mpParser->getEntity().maStructSource.sSystemId;
174 // --------------------------------------------------------------------
175 // FastSaxParser implementation
176 // --------------------------------------------------------------------
178 FastSaxParser::FastSaxParser( )
180 mxDocumentLocator.set( new FastLocatorImpl( this ) );
182 // performance-Improvment. Reference is needed when calling the startTag callback.
183 // Handing out the same object with every call is allowed (see sax-specification)
184 mxAttributes.set( new FastAttributeList( mxTokenHandler ) );
186 mbExceptionWasThrown = sal_False;
189 // --------------------------------------------------------------------
191 FastSaxParser::~FastSaxParser()
193 if( mxDocumentLocator.is() )
194 mxDocumentLocator->dispose();
197 // --------------------------------------------------------------------
199 void FastSaxParser::pushContext()
201 bool bRootContext = false;
202 SaxContextImplPtr p;
203 if( maContextStack.empty() )
205 p.reset( new SaxContextImpl() );
206 bRootContext = true;
208 else
210 p.reset( new SaxContextImpl( maContextStack.top() ) );
212 maContextStack.push( p );
214 if( bRootContext )
215 DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
218 // --------------------------------------------------------------------
220 void FastSaxParser::popContext()
222 OSL_ENSURE( !maContextStack.empty(), "sax::FastSaxParser::popContext(), pop without push?" );
223 if( !maContextStack.empty() )
224 maContextStack.pop();
227 // --------------------------------------------------------------------
229 void FastSaxParser::DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL )
231 OSL_ENSURE( !maContextStack.empty(), "sax::FastSaxParser::DefineNamespace(), I need a context!" );
232 if( !maContextStack.empty() )
234 sal_uInt32 nOffset = maContextStack.top()->mnNamespaceCount++;
236 if( maNamespaceDefines.size() <= nOffset )
237 maNamespaceDefines.resize( maNamespaceDefines.size() + 64 );
239 const OUString aNamespaceURL( pNamespaceURL, strlen( pNamespaceURL ), RTL_TEXTENCODING_UTF8 );
240 maNamespaceDefines[nOffset].reset( new NamespaceDefine( rPrefix, GetNamespaceToken( aNamespaceURL ), aNamespaceURL ) );
244 // --------------------------------------------------------------------
246 sal_Int32 FastSaxParser::GetToken( const OString& rToken )
248 Sequence< sal_Int8 > aSeq( (sal_Int8*)rToken.getStr(), rToken.getLength() );
250 return mxTokenHandler->getTokenFromUTF8( aSeq );
253 sal_Int32 FastSaxParser::GetToken( const sal_Char* pToken, sal_Int32 nLen /* = 0 */ )
255 if( !nLen )
256 nLen = strlen( pToken );
258 Sequence< sal_Int8 > aSeq( (sal_Int8*)pToken, nLen );
260 return mxTokenHandler->getTokenFromUTF8( aSeq );
263 // --------------------------------------------------------------------
265 sal_Int32 FastSaxParser::GetTokenWithPrefix( const OString& rPrefix, const OString& rName ) throw (SAXException)
267 sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
269 sal_uInt32 nNamespace = maContextStack.top()->mnNamespaceCount;
270 while( nNamespace-- )
272 if( maNamespaceDefines[nNamespace]->maPrefix == rPrefix )
274 nNamespaceToken = maNamespaceDefines[nNamespace]->mnToken;
275 break;
278 if( !nNamespace )
279 throw SAXException(); // prefix that has no defined namespace url
282 if( nNamespaceToken != FastToken::DONTKNOW )
284 sal_Int32 nNameToken = GetToken( rName.getStr(), rName.getLength() );
285 if( nNameToken != FastToken::DONTKNOW )
286 return nNamespaceToken | nNameToken;
289 return FastToken::DONTKNOW;
292 sal_Int32 FastSaxParser::GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (SAXException)
294 sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
296 sal_uInt32 nNamespace = maContextStack.top()->mnNamespaceCount;
297 while( nNamespace-- )
299 const OString& rPrefix( maNamespaceDefines[nNamespace]->maPrefix );
300 if( (rPrefix.getLength() == nPrefixLen) &&
301 (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
303 nNamespaceToken = maNamespaceDefines[nNamespace]->mnToken;
304 break;
307 if( !nNamespace )
308 throw SAXException(); // prefix that has no defined namespace url
311 if( nNamespaceToken != FastToken::DONTKNOW )
313 sal_Int32 nNameToken = GetToken( pName, nNameLen );
314 if( nNameToken != FastToken::DONTKNOW )
315 return nNamespaceToken | nNameToken;
318 return FastToken::DONTKNOW;
321 // --------------------------------------------------------------------
323 sal_Int32 FastSaxParser::GetNamespaceToken( const OUString& rNamespaceURL )
325 NamespaceMap::iterator aIter( maNamespaceMap.find( rNamespaceURL ) );
326 if( aIter != maNamespaceMap.end() )
327 return (*aIter).second;
328 else
329 return FastToken::DONTKNOW;
332 // --------------------------------------------------------------------
334 OUString FastSaxParser::GetNamespaceURL( const OString& rPrefix ) throw (SAXException)
336 if( !maContextStack.empty() )
338 sal_uInt32 nNamespace = maContextStack.top()->mnNamespaceCount;
339 while( nNamespace-- )
340 if( maNamespaceDefines[nNamespace]->maPrefix == rPrefix )
341 return maNamespaceDefines[nNamespace]->maNamespaceURL;
344 throw SAXException(); // prefix that has no defined namespace url
347 OUString FastSaxParser::GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw(SAXException)
349 if( pPrefix && !maContextStack.empty() )
351 sal_uInt32 nNamespace = maContextStack.top()->mnNamespaceCount;
352 while( nNamespace-- )
354 const OString& rPrefix( maNamespaceDefines[nNamespace]->maPrefix );
355 if( (rPrefix.getLength() == nPrefixLen) &&
356 (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
358 return maNamespaceDefines[nNamespace]->maNamespaceURL;
363 throw SAXException(); // prefix that has no defined namespace url
366 // --------------------------------------------------------------------
368 sal_Int32 FastSaxParser::GetTokenWithNamespaceURL( const OUString& rNamespaceURL, const sal_Char* pName, int nNameLen )
370 sal_Int32 nNamespaceToken = GetNamespaceToken( rNamespaceURL );
372 if( nNamespaceToken != FastToken::DONTKNOW )
374 sal_Int32 nNameToken = GetToken( pName, nNameLen );
375 if( nNameToken != FastToken::DONTKNOW )
376 return nNamespaceToken | nNameToken;
379 return FastToken::DONTKNOW;
382 // --------------------------------------------------------------------
384 void FastSaxParser::splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen )
386 XML_Char *p;
387 for( p = const_cast< XML_Char* >( pwName ), rNameLen = 0, rPrefixLen = 0; *p; p++ )
389 if( *p == ':' )
391 rPrefixLen = p - pwName;
392 rNameLen = 0;
394 else
396 rNameLen++;
399 if( rPrefixLen )
401 rpPrefix = pwName;
402 rpName = &pwName[ rPrefixLen + 1 ];
404 else
406 rpPrefix = 0;
407 rpName = pwName;
411 /***************
413 * parseStream does Parser-startup initializations. The FastSaxParser::parse() method does
414 * the file-specific initialization work. (During a parser run, external files may be opened)
416 ****************/
417 void FastSaxParser::parseStream( const InputSource& maStructSource) throw (SAXException, IOException, RuntimeException)
419 // Only one text at one time
420 MutexGuard guard( maMutex );
422 struct Entity entity;
423 entity.maStructSource = maStructSource;
425 if( ! entity.maStructSource.aInputStream.is() )
427 throw SAXException( OUString::createFromAscii( "No input source" ), Reference< XInterface > () , Any() );
430 entity.maConverter.setInputStream( entity.maStructSource.aInputStream );
431 if( entity.maStructSource.sEncoding.getLength() )
433 entity.maConverter.setEncoding( OUStringToOString( entity.maStructSource.sEncoding , RTL_TEXTENCODING_ASCII_US ) );
436 // create parser with proper encoding
437 entity.mpParser = XML_ParserCreate( 0 );
438 if( ! entity.mpParser )
440 throw SAXException( OUString::createFromAscii( "Couldn't create parser" ), Reference< XInterface > (), Any() );
443 // set all necessary C-Callbacks
444 XML_SetUserData( entity.mpParser , this );
445 XML_SetElementHandler( entity.mpParser ,
446 call_callbackStartElement ,
447 call_callbackEndElement );
448 XML_SetCharacterDataHandler( entity.mpParser , call_callbackCharacters );
449 XML_SetExternalEntityRefHandler( entity.mpParser,
450 call_callbackExternalEntityRef);
452 maSavedException.clear();
453 pushEntity( entity );
456 // start the document
457 if( mxDocumentHandler.is() )
459 Reference< XLocator > xLoc( mxDocumentLocator.get() );
460 mxDocumentHandler->setDocumentLocator( xLoc );
461 mxDocumentHandler->startDocument();
464 parse();
466 // finish document
467 if( mxDocumentHandler.is() )
469 mxDocumentHandler->endDocument();
472 catch( SAXException & )
474 popEntity();
475 XML_ParserFree( entity.mpParser );
476 throw;
478 catch( IOException & )
480 popEntity();
481 XML_ParserFree( entity.mpParser );
482 throw;
484 catch( RuntimeException & )
486 popEntity();
487 XML_ParserFree( entity.mpParser );
488 throw;
491 popEntity();
492 XML_ParserFree( entity.mpParser );
495 void FastSaxParser::setFastDocumentHandler( const Reference< XFastDocumentHandler >& Handler ) throw (RuntimeException)
497 mxDocumentHandler = Handler;
500 void SAL_CALL FastSaxParser::setTokenHandler( const Reference< XFastTokenHandler >& Handler ) throw (RuntimeException)
502 mxTokenHandler = Handler;
503 mxAttributes.set( new FastAttributeList( mxTokenHandler ) );
506 void SAL_CALL FastSaxParser::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
508 if( NamespaceToken >= FastToken::NAMESPACE )
510 if( GetNamespaceToken( NamespaceURL ) == FastToken::DONTKNOW )
512 maNamespaceMap[ NamespaceURL ] = NamespaceToken;
513 return;
516 throw IllegalArgumentException();
519 void FastSaxParser::setErrorHandler(const Reference< XErrorHandler > & Handler) throw (RuntimeException)
521 mxErrorHandler = Handler;
524 void FastSaxParser::setEntityResolver(const Reference < XEntityResolver > & Resolver) throw (RuntimeException)
526 mxEntityResolver = Resolver;
529 void FastSaxParser::setLocale( const Locale & Locale ) throw (RuntimeException)
531 maLocale = Locale;
534 Sequence< OUString > FastSaxParser::getSupportedServiceNames_Static(void)
536 Sequence<OUString> aRet(1);
537 aRet.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(PARSER_SERVICE_NAME) );
538 return aRet;
541 // XServiceInfo
542 OUString FastSaxParser::getImplementationName() throw (RuntimeException)
544 return OUString::createFromAscii( PARSER_IMPLEMENTATION_NAME );
547 // XServiceInfo
548 sal_Bool FastSaxParser::supportsService(const OUString& ServiceName) throw (RuntimeException)
550 Sequence< OUString > aSNL = getSupportedServiceNames();
551 const OUString * pArray = aSNL.getConstArray();
553 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
554 if( pArray[i] == ServiceName )
555 return sal_True;
557 return sal_False;
560 // XServiceInfo
561 Sequence< OUString > FastSaxParser::getSupportedServiceNames(void) throw (RuntimeException)
564 Sequence<OUString> seq(1);
565 seq.getArray()[0] = OUString::createFromAscii( PARSER_SERVICE_NAME );
566 return seq;
570 /*---------------------------------------
572 * Helper functions and classes
574 *-------------------------------------------*/
575 OUString getErrorMessage( XML_Error xmlE, OUString sSystemId , sal_Int32 nLine )
577 OUString Message;
578 if( XML_ERROR_NONE == xmlE ) {
579 Message = OUString::createFromAscii( "No" );
581 else if( XML_ERROR_NO_MEMORY == xmlE ) {
582 Message = OUString::createFromAscii( "no memory" );
584 else if( XML_ERROR_SYNTAX == xmlE ) {
585 Message = OUString::createFromAscii( "syntax" );
587 else if( XML_ERROR_NO_ELEMENTS == xmlE ) {
588 Message = OUString::createFromAscii( "no elements" );
590 else if( XML_ERROR_INVALID_TOKEN == xmlE ) {
591 Message = OUString::createFromAscii( "invalid token" );
593 else if( XML_ERROR_UNCLOSED_TOKEN == xmlE ) {
594 Message = OUString::createFromAscii( "unclosed token" );
596 else if( XML_ERROR_PARTIAL_CHAR == xmlE ) {
597 Message = OUString::createFromAscii( "partial char" );
599 else if( XML_ERROR_TAG_MISMATCH == xmlE ) {
600 Message = OUString::createFromAscii( "tag mismatch" );
602 else if( XML_ERROR_DUPLICATE_ATTRIBUTE == xmlE ) {
603 Message = OUString::createFromAscii( "duplicate attribute" );
605 else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT == xmlE ) {
606 Message = OUString::createFromAscii( "junk after doc element" );
608 else if( XML_ERROR_PARAM_ENTITY_REF == xmlE ) {
609 Message = OUString::createFromAscii( "parameter entity reference" );
611 else if( XML_ERROR_UNDEFINED_ENTITY == xmlE ) {
612 Message = OUString::createFromAscii( "undefined entity" );
614 else if( XML_ERROR_RECURSIVE_ENTITY_REF == xmlE ) {
615 Message = OUString::createFromAscii( "recursive entity reference" );
617 else if( XML_ERROR_ASYNC_ENTITY == xmlE ) {
618 Message = OUString::createFromAscii( "async entity" );
620 else if( XML_ERROR_BAD_CHAR_REF == xmlE ) {
621 Message = OUString::createFromAscii( "bad char reference" );
623 else if( XML_ERROR_BINARY_ENTITY_REF == xmlE ) {
624 Message = OUString::createFromAscii( "binary entity reference" );
626 else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF == xmlE ) {
627 Message = OUString::createFromAscii( "attribute external entity reference" );
629 else if( XML_ERROR_MISPLACED_XML_PI == xmlE ) {
630 Message = OUString::createFromAscii( "misplaced xml processing instruction" );
632 else if( XML_ERROR_UNKNOWN_ENCODING == xmlE ) {
633 Message = OUString::createFromAscii( "unknown encoding" );
635 else if( XML_ERROR_INCORRECT_ENCODING == xmlE ) {
636 Message = OUString::createFromAscii( "incorrect encoding" );
638 else if( XML_ERROR_UNCLOSED_CDATA_SECTION == xmlE ) {
639 Message = OUString::createFromAscii( "unclosed cdata section" );
641 else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING == xmlE ) {
642 Message = OUString::createFromAscii( "external entity reference" );
644 else if( XML_ERROR_NOT_STANDALONE == xmlE ) {
645 Message = OUString::createFromAscii( "not standalone" );
648 OUString str = OUString::createFromAscii( "[" );
649 str += sSystemId;
650 str += OUString::createFromAscii( " line " );
651 str += OUString::valueOf( nLine );
652 str += OUString::createFromAscii( "]: " );
653 str += Message;
654 str += OUString::createFromAscii( "error" );
656 return str;
660 // starts parsing with actual parser !
661 void FastSaxParser::parse( )
663 const int nBufSize = 16*1024;
665 int nRead = nBufSize;
666 Sequence< sal_Int8 > seqOut(nBufSize);
668 while( nRead )
670 nRead = getEntity().maConverter.readAndConvert( seqOut, nBufSize );
672 if( ! nRead )
674 XML_Parse( getEntity().mpParser, ( const char * ) seqOut.getArray(), 0 , 1 );
675 break;
678 sal_Bool bContinue = ( XML_Parse( getEntity().mpParser, (const char *) seqOut.getArray(), nRead, 0 ) != 0 );
680 if( !bContinue || mbExceptionWasThrown )
682 // Error during parsing !
683 XML_Error xmlE = XML_GetErrorCode( getEntity().mpParser );
684 OUString sSystemId = mxDocumentLocator->getSystemId();
685 sal_Int32 nLine = mxDocumentLocator->getLineNumber();
687 SAXParseException aExcept(
688 getErrorMessage(xmlE , sSystemId, nLine) ,
689 Reference< XInterface >(),
690 Any( &maSavedException , getCppuType( &maSavedException) ),
691 mxDocumentLocator->getPublicId(),
692 mxDocumentLocator->getSystemId(),
693 mxDocumentLocator->getLineNumber(),
694 mxDocumentLocator->getColumnNumber()
697 if( mxErrorHandler.is() )
699 // error handler is set, so the handler may throw the maSavedException
700 mxErrorHandler->fatalError( Any( aExcept ) );
703 // Error handler has not thrown an maSavedException, but parsing cannot go on,
704 // so an maSavedException MUST be thrown.
705 throw aExcept;
710 //------------------------------------------
712 // The C-Callbacks
714 //-----------------------------------------
716 namespace {
718 struct AttributeData
720 OString maPrefix;
721 OString maName;
722 OString maValue;
725 } // namespace
727 void FastSaxParser::callbackStartElement( void *pvThis, const XML_Char *pwName, const XML_Char **awAttributes )
729 FastSaxParser *pThis = (FastSaxParser*)pvThis;
731 Reference< XFastContextHandler > xParentContext;
732 if( !pThis->maContextStack.empty() )
734 xParentContext = pThis->maContextStack.top()->mxContext;
735 if( !xParentContext.is() )
737 // we ignore current elements, so no processing needed
738 pThis->pushContext();
739 return;
743 pThis->pushContext();
745 pThis->mxAttributes->clear();
747 // create attribute map and process namespace instructions
748 int i = 0;
749 sal_Int32 nNameLen, nPrefixLen;
750 const XML_Char *pName;
751 const XML_Char *pPrefix;
753 /* #158414# Each element may define new namespaces, also for attribues.
754 First, process all namespace attributes and cache other attributes in a
755 vector. Second, process the attributes after namespaces have been
756 initialized. */
757 ::std::vector< AttributeData > aAttribs;
759 // #158414# first: get namespaces
760 for( ; awAttributes[i]; i += 2 )
762 OSL_ASSERT( awAttributes[i+1] );
764 pThis->splitName( awAttributes[i], pPrefix, nPrefixLen, pName, nNameLen );
765 if( nPrefixLen )
767 if( (nPrefixLen == 5) && (strncmp( pPrefix, "xmlns", 5 ) == 0) )
769 pThis->DefineNamespace( OString( pName, nNameLen ), awAttributes[i+1] );
771 else
773 aAttribs.resize( aAttribs.size() + 1 );
774 aAttribs.back().maPrefix = OString( pPrefix, nPrefixLen );
775 aAttribs.back().maName = OString( pName, nNameLen );
776 aAttribs.back().maValue = OString( awAttributes[i+1] );
779 else
781 if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) )
783 // namespace of the element found
784 pThis->maContextStack.top()->maNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 );
786 else
788 aAttribs.resize( aAttribs.size() + 1 );
789 aAttribs.back().maName = OString( pName, nNameLen );
790 aAttribs.back().maValue = OString( awAttributes[i+1] );
795 // #158414# second: fill attribute list with other attributes
796 for( ::std::vector< AttributeData >::const_iterator aIt = aAttribs.begin(), aEnd = aAttribs.end(); aIt != aEnd; ++aIt )
798 if( aIt->maPrefix.getLength() )
800 const sal_Int32 nAttributeToken = pThis->GetTokenWithPrefix( aIt->maPrefix, aIt->maName );
801 if( nAttributeToken != FastToken::DONTKNOW )
802 pThis->mxAttributes->add( nAttributeToken, aIt->maValue );
803 else
804 pThis->mxAttributes->addUnknown( pThis->GetNamespaceURL( aIt->maPrefix ), aIt->maName, aIt->maValue );
806 else
808 const sal_Int32 nAttributeToken = pThis->GetToken( aIt->maName );
809 if( nAttributeToken != FastToken::DONTKNOW )
810 pThis->mxAttributes->add( nAttributeToken, aIt->maValue );
811 else
812 pThis->mxAttributes->addUnknown( aIt->maName, aIt->maValue );
816 sal_Int32 nElementToken;
817 pThis->splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen );
818 if( nPrefixLen )
820 nElementToken = pThis->GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen );
822 else if( pThis->maContextStack.top()->maNamespace.getLength() )
824 nElementToken = pThis->GetTokenWithNamespaceURL( pThis->maContextStack.top()->maNamespace, pName, nNameLen );
826 else
828 nElementToken = pThis->GetToken( pName );
830 pThis->maContextStack.top()->mnElementToken = nElementToken;
834 Reference< XFastAttributeList > xAttr( pThis->mxAttributes.get() );
835 Reference< XFastContextHandler > xContext;
836 if( nElementToken == FastToken::DONTKNOW )
838 if( nPrefixLen )
840 pThis->maContextStack.top()->maNamespace = pThis->GetNamespaceURL( pPrefix, nPrefixLen );
843 const OUString aNamespace( pThis->maContextStack.top()->maNamespace );
844 const OUString aElementName( pPrefix, nPrefixLen, RTL_TEXTENCODING_UTF8 );
845 pThis->maContextStack.top()->maElementName = aElementName;
847 if( xParentContext.is() )
848 xContext = xParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
849 else
850 xContext = pThis->mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
852 if( xContext.is() )
854 pThis->maContextStack.top()->mxContext = xContext;
855 xContext->startUnknownElement( aNamespace, aElementName, xAttr );
858 else
860 if( xParentContext.is() )
861 xContext = xParentContext->createFastChildContext( nElementToken, xAttr );
862 else
863 xContext = pThis->mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
866 if( xContext.is() )
868 pThis->maContextStack.top()->mxContext = xContext;
869 xContext->startFastElement( nElementToken, xAttr );
873 catch( Exception& e )
875 pThis->maSavedException <<= e;
879 void FastSaxParser::callbackEndElement( void *pvThis , const XML_Char * )
881 FastSaxParser *pThis = (FastSaxParser*)pvThis;
883 if( !pThis->maContextStack.empty() )
885 SaxContextImplPtr pContext( pThis->maContextStack.top() );
886 const Reference< XFastContextHandler >& xContext( pContext->mxContext );
887 if( xContext.is() ) try
889 sal_Int32 nElementToken = pContext->mnElementToken;
890 if( nElementToken != FastToken::DONTKNOW )
892 xContext->endFastElement( nElementToken );
894 else
896 xContext->endUnknownElement( pContext->maNamespace, pContext->maElementName );
899 catch( Exception& e )
901 pThis->maSavedException <<= e;
904 pThis->popContext();
906 else
908 OSL_ENSURE( false, "no context on sax::FastSaxParser::callbackEndElement() ??? ");
913 void FastSaxParser::callbackCharacters( void *pvThis , const XML_Char *s , int nLen )
915 FastSaxParser *pThis = (FastSaxParser*)pvThis;
917 const Reference< XFastContextHandler >& xContext( pThis->maContextStack.top()->mxContext );
918 if( xContext.is() ) try
920 xContext->characters( OUString( s, nLen, RTL_TEXTENCODING_UTF8 ) );
922 catch( Exception& e )
924 pThis->maSavedException <<= e;
928 int FastSaxParser::callbackExternalEntityRef( XML_Parser parser,
929 const XML_Char *context,
930 const XML_Char * /*base*/,
931 const XML_Char *systemId,
932 const XML_Char *publicId)
934 bool bOK = true;
935 InputSource source;
936 FastSaxParser *pImpl = ((FastSaxParser*)XML_GetUserData( parser ));
938 struct Entity entity;
940 if( pImpl->mxEntityResolver.is() ) {
943 entity.maStructSource = pImpl->mxEntityResolver->resolveEntity(
944 OUString( publicId, strlen( publicId ), RTL_TEXTENCODING_UTF8 ) ,
945 OUString( systemId, strlen( systemId ), RTL_TEXTENCODING_UTF8 ) );
947 catch( SAXParseException & e )
949 pImpl->maSavedException <<= e;
950 bOK = false;
952 catch( SAXException & e )
954 pImpl->maSavedException <<= SAXParseException(
955 e.Message , e.Context , e.WrappedException ,
956 pImpl->mxDocumentLocator->getPublicId(),
957 pImpl->mxDocumentLocator->getSystemId(),
958 pImpl->mxDocumentLocator->getLineNumber(),
959 pImpl->mxDocumentLocator->getColumnNumber() );
960 bOK = false;
964 if( entity.maStructSource.aInputStream.is() )
966 entity.mpParser = XML_ExternalEntityParserCreate( parser , context, 0 );
967 if( ! entity.mpParser )
969 return false;
972 entity.maConverter.setInputStream( entity.maStructSource.aInputStream );
973 pImpl->pushEntity( entity );
976 pImpl->parse();
978 catch( SAXParseException & e )
980 pImpl->maSavedException <<= e;
981 bOK = false;
983 catch( IOException &e )
985 SAXException aEx;
986 aEx.WrappedException <<= e;
987 pImpl->maSavedException <<= aEx;
988 bOK = false;
990 catch( RuntimeException &e )
992 SAXException aEx;
993 aEx.WrappedException <<= e;
994 pImpl->maSavedException <<= aEx;
995 bOK = false;
998 pImpl->popEntity();
1000 XML_ParserFree( entity.mpParser );
1003 return bOK;