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 ************************************************************************/
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"
47 using ::rtl::OUString
;
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 // --------------------------------------------------------------------
64 Reference
< XFastContextHandler
> mxContext
;
65 sal_uInt32 mnNamespaceCount
;
66 sal_Int32 mnElementToken
;
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
80 OUString maNamespaceURL
;
82 NamespaceDefine( const OString
& rPrefix
, sal_Int32 nToken
, const OUString
& rNamespaceURL
) : maPrefix( rPrefix
), mnToken( nToken
), maNamespaceURL( rNamespaceURL
) {}
85 // --------------------------------------------------------------------
87 // --------------------------------------------------------------------
91 class FastLocatorImpl
: public WeakImplHelper1
< XLocator
>
94 FastLocatorImpl( FastSaxParser
*p
) : mpParser(p
) {}
96 void dispose() { mpParser
= 0; }
97 void checkDispose() throw (RuntimeException
) { if( !mpParser
) throw DisposedException(); }
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
);
106 FastSaxParser
*mpParser
;
109 // --------------------------------------------------------------------
111 // --------------------------------------------------------------------
113 //---------------------------------------------
114 // the implementation part
115 //---------------------------------------------
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
)
148 return XML_GetCurrentColumnNumber( mpParser
->getEntity().mpParser
);
151 // --------------------------------------------------------------------
153 sal_Int32 SAL_CALL
FastLocatorImpl::getLineNumber(void) throw (RuntimeException
)
156 return XML_GetCurrentLineNumber( mpParser
->getEntity().mpParser
);
159 // --------------------------------------------------------------------
161 OUString SAL_CALL
FastLocatorImpl::getPublicId(void) throw (RuntimeException
)
164 return mpParser
->getEntity().maStructSource
.sPublicId
;
166 // --------------------------------------------------------------------
168 OUString SAL_CALL
FastLocatorImpl::getSystemId(void) throw (RuntimeException
)
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;
203 if( maContextStack
.empty() )
205 p
.reset( new SaxContextImpl() );
210 p
.reset( new SaxContextImpl( maContextStack
.top() ) );
212 maContextStack
.push( p
);
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 */ )
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
;
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
;
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
;
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
)
387 for( p
= const_cast< XML_Char
* >( pwName
), rNameLen
= 0, rPrefixLen
= 0; *p
; p
++ )
391 rPrefixLen
= p
- pwName
;
402 rpName
= &pwName
[ rPrefixLen
+ 1 ];
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)
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();
467 if( mxDocumentHandler
.is() )
469 mxDocumentHandler
->endDocument();
472 catch( SAXException
& )
475 XML_ParserFree( entity
.mpParser
);
478 catch( IOException
& )
481 XML_ParserFree( entity
.mpParser
);
484 catch( RuntimeException
& )
487 XML_ParserFree( entity
.mpParser
);
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
;
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
)
534 Sequence
< OUString
> FastSaxParser::getSupportedServiceNames_Static(void)
536 Sequence
<OUString
> aRet(1);
537 aRet
.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(PARSER_SERVICE_NAME
) );
542 OUString
FastSaxParser::getImplementationName() throw (RuntimeException
)
544 return OUString::createFromAscii( PARSER_IMPLEMENTATION_NAME
);
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
)
561 Sequence
< OUString
> FastSaxParser::getSupportedServiceNames(void) throw (RuntimeException
)
564 Sequence
<OUString
> seq(1);
565 seq
.getArray()[0] = OUString::createFromAscii( PARSER_SERVICE_NAME
);
570 /*---------------------------------------
572 * Helper functions and classes
574 *-------------------------------------------*/
575 OUString
getErrorMessage( XML_Error xmlE
, OUString sSystemId
, sal_Int32 nLine
)
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( "[" );
650 str
+= OUString::createFromAscii( " line " );
651 str
+= OUString::valueOf( nLine
);
652 str
+= OUString::createFromAscii( "]: " );
654 str
+= OUString::createFromAscii( "error" );
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
);
670 nRead
= getEntity().maConverter
.readAndConvert( seqOut
, nBufSize
);
674 XML_Parse( getEntity().mpParser
, ( const char * ) seqOut
.getArray(), 0 , 1 );
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.
710 //------------------------------------------
714 //-----------------------------------------
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();
743 pThis
->pushContext();
745 pThis
->mxAttributes
->clear();
747 // create attribute map and process namespace instructions
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
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
);
767 if( (nPrefixLen
== 5) && (strncmp( pPrefix
, "xmlns", 5 ) == 0) )
769 pThis
->DefineNamespace( OString( pName
, nNameLen
), awAttributes
[i
+1] );
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] );
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
);
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
);
804 pThis
->mxAttributes
->addUnknown( pThis
->GetNamespaceURL( aIt
->maPrefix
), aIt
->maName
, aIt
->maValue
);
808 const sal_Int32 nAttributeToken
= pThis
->GetToken( aIt
->maName
);
809 if( nAttributeToken
!= FastToken::DONTKNOW
)
810 pThis
->mxAttributes
->add( nAttributeToken
, aIt
->maValue
);
812 pThis
->mxAttributes
->addUnknown( aIt
->maName
, aIt
->maValue
);
816 sal_Int32 nElementToken
;
817 pThis
->splitName( pwName
, pPrefix
, nPrefixLen
, pName
, nNameLen
);
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
);
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
)
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
);
850 xContext
= pThis
->mxDocumentHandler
->createUnknownChildContext( aNamespace
, aElementName
, xAttr
);
854 pThis
->maContextStack
.top()->mxContext
= xContext
;
855 xContext
->startUnknownElement( aNamespace
, aElementName
, xAttr
);
860 if( xParentContext
.is() )
861 xContext
= xParentContext
->createFastChildContext( nElementToken
, xAttr
);
863 xContext
= pThis
->mxDocumentHandler
->createFastChildContext( nElementToken
, xAttr
);
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
);
896 xContext
->endUnknownElement( pContext
->maNamespace
, pContext
->maElementName
);
899 catch( Exception
& e
)
901 pThis
->maSavedException
<<= e
;
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
)
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
;
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() );
964 if( entity
.maStructSource
.aInputStream
.is() )
966 entity
.mpParser
= XML_ExternalEntityParserCreate( parser
, context
, 0 );
967 if( ! entity
.mpParser
)
972 entity
.maConverter
.setInputStream( entity
.maStructSource
.aInputStream
);
973 pImpl
->pushEntity( entity
);
978 catch( SAXParseException
& e
)
980 pImpl
->maSavedException
<<= e
;
983 catch( IOException
&e
)
986 aEx
.WrappedException
<<= e
;
987 pImpl
->maSavedException
<<= aEx
;
990 catch( RuntimeException
&e
)
993 aEx
.WrappedException
<<= e
;
994 pImpl
->maSavedException
<<= aEx
;
1000 XML_ParserFree( entity
.mpParser
);