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"
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 // --------------------------------------------------------------------
60 Reference
< XFastContextHandler
> mxContext
;
61 sal_uInt32 mnNamespaceCount
;
62 sal_Int32 mnElementToken
;
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
76 OUString maNamespaceURL
;
78 NamespaceDefine( const OString
& rPrefix
, sal_Int32 nToken
, const OUString
& rNamespaceURL
) : maPrefix( rPrefix
), mnToken( nToken
), maNamespaceURL( rNamespaceURL
) {}
81 // --------------------------------------------------------------------
83 // --------------------------------------------------------------------
87 class FastLocatorImpl
: public WeakImplHelper1
< XLocator
>
90 FastLocatorImpl( FastSaxParser
*p
) : mpParser(p
) {}
92 void dispose() { mpParser
= 0; }
93 void checkDispose() throw (RuntimeException
) { if( !mpParser
) throw DisposedException(); }
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
);
102 FastSaxParser
*mpParser
;
105 // --------------------------------------------------------------------
107 // --------------------------------------------------------------------
109 //---------------------------------------------
110 // the implementation part
111 //---------------------------------------------
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
);
152 // --------------------------------------------------------------------
153 // FastLocatorImpl implementation
154 // --------------------------------------------------------------------
156 sal_Int32 SAL_CALL
FastLocatorImpl::getColumnNumber(void) throw (RuntimeException
)
159 return XML_GetCurrentColumnNumber( mpParser
->getEntity().mpParser
);
162 // --------------------------------------------------------------------
164 sal_Int32 SAL_CALL
FastLocatorImpl::getLineNumber(void) throw (RuntimeException
)
167 return XML_GetCurrentLineNumber( mpParser
->getEntity().mpParser
);
170 // --------------------------------------------------------------------
172 OUString SAL_CALL
FastLocatorImpl::getPublicId(void) throw (RuntimeException
)
175 return mpParser
->getEntity().maStructSource
.sPublicId
;
177 // --------------------------------------------------------------------
179 OUString SAL_CALL
FastLocatorImpl::getSystemId(void) throw (RuntimeException
)
182 return mpParser
->getEntity().maStructSource
.sSystemId
;
185 // --------------------------------------------------------------------
187 ParserData::ParserData()
191 ParserData::~ParserData()
195 // --------------------------------------------------------------------
197 Entity::Entity( const 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
) );
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");
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 */ )
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
;
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
;
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
;
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
)
417 for( p
= const_cast< XML_Char
* >( pwName
), rNameLen
= 0, rPrefixLen
= 0; *p
; p
++ )
421 rPrefixLen
= p
- pwName
;
432 rpName
= &pwName
[ rPrefixLen
+ 1 ];
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)
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();
488 if( entity
.mxDocumentHandler
.is() )
490 entity
.mxDocumentHandler
->endDocument();
493 catch (const SAXException
&)
496 XML_ParserFree( entity
.mpParser
);
499 catch (const IOException
&)
502 XML_ParserFree( entity
.mpParser
);
505 catch (const RuntimeException
&)
508 XML_ParserFree( entity
.mpParser
);
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
;
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
);
574 OUString
FastSaxParser::getImplementationName() throw (RuntimeException
)
576 return OUString( PARSER_IMPLEMENTATION_NAME
);
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
)
593 Sequence
< OUString
> FastSaxParser::getSupportedServiceNames(void) throw (RuntimeException
)
596 Sequence
<OUString
> seq(1);
597 seq
.getArray()[0] = OUString( PARSER_SERVICE_NAME
);
602 /*---------------------------------------
604 * Helper functions and classes
606 *-------------------------------------------*/
610 OUString
lclGetErrorMessage( XML_Error xmlE
, const OUString
& sSystemId
, sal_Int32 nLine
)
612 const sal_Char
* pMessage
= "";
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;
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();
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();
663 nRead
= rEntity
.maConverter
.readAndConvert( seqOut
, BUFFER_SIZE
);
666 XML_Parse( rEntity
.mpParser
, (const char*) seqOut
.getConstArray(), 0, 1 );
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
701 //------------------------------------------
705 //-----------------------------------------
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
735 rEntity
.mxAttributes
->clear();
737 // create attribute map and process namespace instructions
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
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
);
759 if( (nPrefixLen
== 5) && (strncmp( pPrefix
, "xmlns", 5 ) == 0) )
761 DefineNamespace( OString( pName
, nNameLen
), awAttributes
[i
+1] );
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] );
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
);
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
);
796 rEntity
.mxAttributes
->addUnknown( GetNamespaceURL( aIt
->maPrefix
), aIt
->maName
, aIt
->maValue
);
800 sal_Int32 nAttributeToken
= GetToken( aIt
->maName
);
801 if( nAttributeToken
!= FastToken::DONTKNOW
)
802 rEntity
.mxAttributes
->add( nAttributeToken
, aIt
->maValue
);
804 rEntity
.mxAttributes
->addUnknown( aIt
->maName
, aIt
->maValue
);
808 sal_Int32 nElementToken
;
809 splitName( pwName
, pPrefix
, nPrefixLen
, pName
, nNameLen
);
811 nElementToken
= GetTokenWithPrefix( pPrefix
, nPrefixLen
, pName
, nNameLen
);
812 else if( !rEntity
.maContextStack
.top()->maNamespace
.isEmpty() )
813 nElementToken
= GetTokenWithNamespaceURL( rEntity
.maContextStack
.top()->maNamespace
, pName
, nNameLen
);
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
)
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
);
832 xContext
= rEntity
.mxDocumentHandler
->createUnknownChildContext( aNamespace
, aElementName
, xAttr
);
836 rEntity
.maContextStack
.top()->mxContext
= xContext
;
837 xContext
->startUnknownElement( aNamespace
, aElementName
, xAttr
);
842 if( xParentContext
.is() )
843 xContext
= xParentContext
->createFastChildContext( nElementToken
, xAttr
);
845 xContext
= rEntity
.mxDocumentHandler
->createFastChildContext( nElementToken
, xAttr
);
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
);
875 xContext
->endUnknownElement( pContext
->maNamespace
, pContext
->maElementName
);
877 catch (const Exception
& e
)
879 rEntity
.maSavedException
<<= e
;
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(
915 "FastSaxParser: internal entity declaration, stopping"),
916 static_cast<OWeakObject
*>(this), Any(),
917 mxDocumentLocator
->getPublicId(),
918 mxDocumentLocator
->getSystemId(),
919 mxDocumentLocator
->getLineNumber(),
920 mxDocumentLocator
->getColumnNumber() );
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
)
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
;
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() );
959 if( aNewEntity
.maStructSource
.aInputStream
.is() )
961 aNewEntity
.mpParser
= XML_ExternalEntityParserCreate( parser
, context
, 0 );
962 if( !aNewEntity
.mpParser
)
967 aNewEntity
.maConverter
.setInputStream( aNewEntity
.maStructSource
.aInputStream
);
968 pushEntity( aNewEntity
);
973 catch (const SAXParseException
& e
)
975 rCurrEntity
.maSavedException
<<= e
;
978 catch (const IOException
& e
)
981 aEx
.WrappedException
<<= e
;
982 rCurrEntity
.maSavedException
<<= aEx
;
985 catch (const RuntimeException
& e
)
988 aEx
.WrappedException
<<= e
;
989 rCurrEntity
.maSavedException
<<= aEx
;
994 XML_ParserFree( aNewEntity
.mpParser
);
1000 } // namespace sax_fastparser
1002 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */