| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_xmlscript.hxx" |
| |
| #include "osl/diagnose.h" |
| #include "osl/mutex.hxx" |
| #include "rtl/ustrbuf.hxx" |
| #include "cppuhelper/factory.hxx" |
| #include "cppuhelper/implementationentry.hxx" |
| #include "cppuhelper/implbase1.hxx" |
| #include "cppuhelper/implbase3.hxx" |
| #include "xmlscript/xml_import.hxx" |
| |
| #include "com/sun/star/xml/input/XAttributes.hpp" |
| #include "com/sun/star/lang/XInitialization.hpp" |
| #include "com/sun/star/uno/XComponentContext.hpp" |
| |
| #include <vector> |
| #include <hash_map> |
| |
| #include <memory> |
| |
| |
| using namespace ::rtl; |
| using namespace ::osl; |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| |
| namespace xmlscript |
| { |
| |
| const sal_Int32 UID_UNKNOWN = -1; |
| |
| Sequence< OUString > getSupportedServiceNames_DocumentHandlerImpl() |
| { |
| OUString name( RTL_CONSTASCII_USTRINGPARAM( |
| "com.sun.star.xml.input.SaxDocumentHandler") ); |
| return Sequence< OUString >( &name, 1 ); |
| } |
| |
| OUString getImplementationName_DocumentHandlerImpl() |
| { |
| return OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "com.sun.star.comp.xml.input.SaxDocumentHandler") ); |
| } |
| |
| typedef ::std::hash_map< OUString, sal_Int32, OUStringHash > t_OUString2LongMap; |
| typedef ::std::hash_map< sal_Int32, OUString > t_Long2OUStringMap; |
| |
| struct PrefixEntry |
| { |
| ::std::vector< sal_Int32 > m_Uids; |
| |
| inline PrefixEntry() SAL_THROW( () ) |
| { m_Uids.reserve( 4 ); } |
| }; |
| |
| typedef ::std::hash_map< |
| OUString, PrefixEntry *, OUStringHash > t_OUString2PrefixMap; |
| |
| struct ElementEntry |
| { |
| Reference< xml::input::XElement > m_xElement; |
| ::std::vector< OUString > m_prefixes; |
| |
| inline ElementEntry() |
| { m_prefixes.reserve( 2 ); } |
| }; |
| |
| typedef ::std::vector< ElementEntry * > t_ElementVector; |
| |
| class ExtendedAttributes; |
| |
| //============================================================================== |
| struct MGuard |
| { |
| Mutex * m_pMutex; |
| explicit MGuard( Mutex * pMutex ) |
| : m_pMutex( pMutex ) |
| { if (m_pMutex) m_pMutex->acquire(); } |
| ~MGuard() throw () |
| { if (m_pMutex) m_pMutex->release(); } |
| }; |
| |
| //============================================================================== |
| class DocumentHandlerImpl : |
| public ::cppu::WeakImplHelper3< xml::sax::XDocumentHandler, |
| xml::input::XNamespaceMapping, |
| lang::XInitialization > |
| { |
| friend class ExtendedAttributes; |
| |
| Reference< xml::input::XRoot > m_xRoot; |
| |
| t_OUString2LongMap m_URI2Uid; |
| sal_Int32 m_uid_count; |
| |
| OUString m_sXMLNS_PREFIX_UNKNOWN; |
| OUString m_sXMLNS; |
| |
| sal_Int32 m_nLastURI_lookup; |
| OUString m_aLastURI_lookup; |
| |
| t_OUString2PrefixMap m_prefixes; |
| sal_Int32 m_nLastPrefix_lookup; |
| OUString m_aLastPrefix_lookup; |
| |
| t_ElementVector m_elements; |
| sal_Int32 m_nSkipElements; |
| |
| Mutex * m_pMutex; |
| |
| inline Reference< xml::input::XElement > getCurrentElement() const; |
| |
| inline sal_Int32 getUidByURI( OUString const & rURI ); |
| inline sal_Int32 getUidByPrefix( OUString const & rPrefix ); |
| |
| inline void pushPrefix( |
| OUString const & rPrefix, OUString const & rURI ); |
| inline void popPrefix( OUString const & rPrefix ); |
| |
| inline void getElementName( |
| OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName ); |
| |
| public: |
| DocumentHandlerImpl( |
| Reference< xml::input::XRoot > const & xRoot, |
| bool bSingleThreadedUse ); |
| virtual ~DocumentHandlerImpl() throw (); |
| |
| // XServiceInfo |
| virtual OUString SAL_CALL getImplementationName() |
| throw (RuntimeException); |
| virtual sal_Bool SAL_CALL supportsService( |
| OUString const & servicename ) |
| throw (RuntimeException); |
| virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() |
| throw (RuntimeException); |
| |
| // XInitialization |
| virtual void SAL_CALL initialize( |
| Sequence< Any > const & arguments ) |
| throw (Exception); |
| |
| // XDocumentHandler |
| virtual void SAL_CALL startDocument() |
| throw (xml::sax::SAXException, RuntimeException); |
| virtual void SAL_CALL endDocument() |
| throw (xml::sax::SAXException, RuntimeException); |
| virtual void SAL_CALL startElement( |
| OUString const & rQElementName, |
| Reference< xml::sax::XAttributeList > const & xAttribs ) |
| throw (xml::sax::SAXException, RuntimeException); |
| virtual void SAL_CALL endElement( |
| OUString const & rQElementName ) |
| throw (xml::sax::SAXException, RuntimeException); |
| virtual void SAL_CALL characters( |
| OUString const & rChars ) |
| throw (xml::sax::SAXException, RuntimeException); |
| virtual void SAL_CALL ignorableWhitespace( |
| OUString const & rWhitespaces ) |
| throw (xml::sax::SAXException, RuntimeException); |
| virtual void SAL_CALL processingInstruction( |
| OUString const & rTarget, OUString const & rData ) |
| throw (xml::sax::SAXException, RuntimeException); |
| virtual void SAL_CALL setDocumentLocator( |
| Reference< xml::sax::XLocator > const & xLocator ) |
| throw (xml::sax::SAXException, RuntimeException); |
| |
| // XNamespaceMapping |
| virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri ) |
| throw (RuntimeException); |
| virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid ) |
| throw (container::NoSuchElementException, RuntimeException); |
| }; |
| |
| //______________________________________________________________________________ |
| DocumentHandlerImpl::DocumentHandlerImpl( |
| Reference< xml::input::XRoot > const & xRoot, |
| bool bSingleThreadedUse ) |
| : m_xRoot( xRoot ), |
| m_uid_count( 0 ), |
| m_sXMLNS_PREFIX_UNKNOWN( |
| RTL_CONSTASCII_USTRINGPARAM("<<< unknown prefix >>>") ), |
| m_sXMLNS( RTL_CONSTASCII_USTRINGPARAM("xmlns") ), |
| m_nLastURI_lookup( UID_UNKNOWN ), |
| m_aLastURI_lookup( RTL_CONSTASCII_USTRINGPARAM("<<< unknown URI >>>") ), |
| m_nLastPrefix_lookup( UID_UNKNOWN ), |
| m_aLastPrefix_lookup( |
| RTL_CONSTASCII_USTRINGPARAM("<<< unknown URI >>>") ), |
| m_nSkipElements( 0 ), |
| m_pMutex( 0 ) |
| { |
| m_elements.reserve( 10 ); |
| |
| if (! bSingleThreadedUse) |
| m_pMutex = new Mutex(); |
| } |
| |
| //______________________________________________________________________________ |
| DocumentHandlerImpl::~DocumentHandlerImpl() throw () |
| { |
| if (m_pMutex != 0) |
| { |
| delete m_pMutex; |
| #if OSL_DEBUG_LEVEL == 0 |
| m_pMutex = 0; |
| #endif |
| } |
| } |
| |
| //______________________________________________________________________________ |
| inline Reference< xml::input::XElement > |
| DocumentHandlerImpl::getCurrentElement() const |
| { |
| MGuard aGuard( m_pMutex ); |
| if (m_elements.empty()) |
| return Reference< xml::input::XElement >(); |
| else |
| return m_elements.back()->m_xElement; |
| } |
| |
| //______________________________________________________________________________ |
| inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI ) |
| { |
| MGuard guard( m_pMutex ); |
| if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI) |
| { |
| t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) ); |
| if (iFind != m_URI2Uid.end()) // id found |
| { |
| m_nLastURI_lookup = iFind->second; |
| m_aLastURI_lookup = rURI; |
| } |
| else |
| { |
| m_nLastURI_lookup = m_uid_count; |
| ++m_uid_count; |
| m_URI2Uid[ rURI ] = m_nLastURI_lookup; |
| m_aLastURI_lookup = rURI; |
| } |
| } |
| return m_nLastURI_lookup; |
| } |
| |
| //______________________________________________________________________________ |
| inline sal_Int32 DocumentHandlerImpl::getUidByPrefix( |
| OUString const & rPrefix ) |
| { |
| // commonly the last added prefix is used often for several tags... |
| // good guess |
| if (m_nLastPrefix_lookup == UID_UNKNOWN || m_aLastPrefix_lookup != rPrefix) |
| { |
| t_OUString2PrefixMap::const_iterator iFind( |
| m_prefixes.find( rPrefix ) ); |
| if (iFind != m_prefixes.end()) |
| { |
| const PrefixEntry & rPrefixEntry = *iFind->second; |
| OSL_ASSERT( ! rPrefixEntry.m_Uids.empty() ); |
| m_nLastPrefix_lookup = rPrefixEntry.m_Uids.back(); |
| m_aLastPrefix_lookup = rPrefix; |
| } |
| else |
| { |
| m_nLastPrefix_lookup = UID_UNKNOWN; |
| m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN; |
| } |
| } |
| return m_nLastPrefix_lookup; |
| } |
| |
| //______________________________________________________________________________ |
| inline void DocumentHandlerImpl::pushPrefix( |
| OUString const & rPrefix, OUString const & rURI ) |
| { |
| // lookup id for URI |
| sal_Int32 nUid = getUidByURI( rURI ); |
| |
| // mark prefix with id |
| t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) ); |
| if (iFind == m_prefixes.end()) // unused prefix |
| { |
| PrefixEntry * pEntry = new PrefixEntry(); |
| pEntry->m_Uids.push_back( nUid ); // latest id for prefix |
| m_prefixes[ rPrefix ] = pEntry; |
| } |
| else |
| { |
| PrefixEntry * pEntry = iFind->second; |
| OSL_ASSERT( ! pEntry->m_Uids.empty() ); |
| pEntry->m_Uids.push_back( nUid ); |
| } |
| |
| m_aLastPrefix_lookup = rPrefix; |
| m_nLastPrefix_lookup = nUid; |
| } |
| |
| //______________________________________________________________________________ |
| inline void DocumentHandlerImpl::popPrefix( |
| OUString const & rPrefix ) |
| { |
| t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) ); |
| if (iFind != m_prefixes.end()) // unused prefix |
| { |
| PrefixEntry * pEntry = iFind->second; |
| pEntry->m_Uids.pop_back(); // pop last id for prefix |
| if (pEntry->m_Uids.empty()) // erase prefix key |
| { |
| m_prefixes.erase( iFind ); |
| delete pEntry; |
| } |
| } |
| |
| m_nLastPrefix_lookup = UID_UNKNOWN; |
| m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN; |
| } |
| |
| //______________________________________________________________________________ |
| inline void DocumentHandlerImpl::getElementName( |
| OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName ) |
| { |
| sal_Int32 nColonPos = rQName.indexOf( (sal_Unicode)':' ); |
| *pLocalName = (nColonPos >= 0 ? rQName.copy( nColonPos +1 ) : rQName); |
| *pUid = getUidByPrefix( |
| nColonPos >= 0 ? rQName.copy( 0, nColonPos ) : OUString() ); |
| } |
| |
| |
| //============================================================================== |
| class ExtendedAttributes : |
| public ::cppu::WeakImplHelper1< xml::input::XAttributes > |
| { |
| sal_Int32 m_nAttributes; |
| sal_Int32 * m_pUids; |
| OUString * m_pPrefixes; |
| OUString * m_pLocalNames; |
| OUString * m_pQNames; |
| OUString * m_pValues; |
| |
| DocumentHandlerImpl * m_pHandler; |
| |
| public: |
| inline ExtendedAttributes( |
| sal_Int32 nAttributes, |
| sal_Int32 * pUids, OUString * pPrefixes, |
| OUString * pLocalNames, OUString * pQNames, |
| Reference< xml::sax::XAttributeList > const & xAttributeList, |
| DocumentHandlerImpl * pHandler ); |
| virtual ~ExtendedAttributes() throw (); |
| |
| // XAttributes |
| virtual sal_Int32 SAL_CALL getLength() |
| throw (RuntimeException); |
| virtual sal_Int32 SAL_CALL getIndexByQName( |
| OUString const & rQName ) |
| throw (RuntimeException); |
| virtual sal_Int32 SAL_CALL getIndexByUidName( |
| sal_Int32 nUid, OUString const & rLocalName ) |
| throw (RuntimeException); |
| virtual OUString SAL_CALL getQNameByIndex( |
| sal_Int32 nIndex ) |
| throw (RuntimeException); |
| virtual sal_Int32 SAL_CALL getUidByIndex( |
| sal_Int32 nIndex ) |
| throw (RuntimeException); |
| virtual OUString SAL_CALL getLocalNameByIndex( |
| sal_Int32 nIndex ) |
| throw (RuntimeException); |
| virtual OUString SAL_CALL getValueByIndex( |
| sal_Int32 nIndex ) |
| throw (RuntimeException); |
| virtual OUString SAL_CALL getValueByUidName( |
| sal_Int32 nUid, OUString const & rLocalName ) |
| throw (RuntimeException); |
| virtual OUString SAL_CALL getTypeByIndex( |
| sal_Int32 nIndex ) |
| throw (RuntimeException); |
| }; |
| |
| //______________________________________________________________________________ |
| inline ExtendedAttributes::ExtendedAttributes( |
| sal_Int32 nAttributes, |
| sal_Int32 * pUids, OUString * pPrefixes, |
| OUString * pLocalNames, OUString * pQNames, |
| Reference< xml::sax::XAttributeList > const & xAttributeList, |
| DocumentHandlerImpl * pHandler ) |
| : m_nAttributes( nAttributes ) |
| , m_pUids( pUids ) |
| , m_pPrefixes( pPrefixes ) |
| , m_pLocalNames( pLocalNames ) |
| , m_pQNames( pQNames ) |
| , m_pValues( new OUString[ nAttributes ] ) |
| , m_pHandler( pHandler ) |
| { |
| m_pHandler->acquire(); |
| |
| for ( sal_Int16 nPos = 0; nPos < nAttributes; ++nPos ) |
| { |
| m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos ); |
| } |
| } |
| |
| //______________________________________________________________________________ |
| ExtendedAttributes::~ExtendedAttributes() throw () |
| { |
| m_pHandler->release(); |
| |
| delete [] m_pUids; |
| delete [] m_pPrefixes; |
| delete [] m_pLocalNames; |
| delete [] m_pQNames; |
| delete [] m_pValues; |
| } |
| |
| |
| //############################################################################## |
| |
| // XServiceInfo |
| |
| //______________________________________________________________________________ |
| OUString DocumentHandlerImpl::getImplementationName() |
| throw (RuntimeException) |
| { |
| return getImplementationName_DocumentHandlerImpl(); |
| } |
| |
| //______________________________________________________________________________ |
| sal_Bool DocumentHandlerImpl::supportsService( |
| OUString const & servicename ) |
| throw (RuntimeException) |
| { |
| Sequence< OUString > names( getSupportedServiceNames_DocumentHandlerImpl() ); |
| for ( sal_Int32 nPos = names.getLength(); nPos--; ) |
| { |
| if (names[ nPos ].equals( servicename )) |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| //______________________________________________________________________________ |
| Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames() |
| throw (RuntimeException) |
| { |
| return getSupportedServiceNames_DocumentHandlerImpl(); |
| } |
| |
| // XInitialization |
| |
| //______________________________________________________________________________ |
| void DocumentHandlerImpl::initialize( |
| Sequence< Any > const & arguments ) |
| throw (Exception) |
| { |
| MGuard guard( m_pMutex ); |
| Reference< xml::input::XRoot > xRoot; |
| if (arguments.getLength() == 1 && |
| (arguments[ 0 ] >>= xRoot) && |
| xRoot.is()) |
| { |
| m_xRoot = xRoot; |
| } |
| else |
| { |
| throw RuntimeException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "missing root instance!") ), |
| Reference< XInterface >() ); |
| } |
| } |
| |
| |
| // XNamespaceMapping |
| |
| //______________________________________________________________________________ |
| sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri ) |
| throw (RuntimeException) |
| { |
| sal_Int32 uid = getUidByURI( Uri ); |
| OSL_ASSERT( uid != UID_UNKNOWN ); |
| return uid; |
| } |
| |
| //______________________________________________________________________________ |
| OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid ) |
| throw (container::NoSuchElementException, RuntimeException) |
| { |
| MGuard guard( m_pMutex ); |
| t_OUString2LongMap::const_iterator iPos( m_URI2Uid.begin() ); |
| t_OUString2LongMap::const_iterator const iEnd( m_URI2Uid.end() ); |
| for ( ; iPos != iEnd; ++iPos ) |
| { |
| if (iPos->second == Uid) |
| return iPos->first; |
| } |
| throw container::NoSuchElementException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("no such xmlns uid!") ), |
| static_cast< OWeakObject * >(this) ); |
| } |
| |
| |
| // XDocumentHandler |
| |
| //______________________________________________________________________________ |
| void DocumentHandlerImpl::startDocument() |
| throw (xml::sax::SAXException, RuntimeException) |
| { |
| m_xRoot->startDocument( |
| static_cast< xml::input::XNamespaceMapping * >( this ) ); |
| } |
| |
| //______________________________________________________________________________ |
| void DocumentHandlerImpl::endDocument() |
| throw (xml::sax::SAXException, RuntimeException) |
| { |
| m_xRoot->endDocument(); |
| } |
| |
| //______________________________________________________________________________ |
| void DocumentHandlerImpl::startElement( |
| OUString const & rQElementName, |
| Reference< xml::sax::XAttributeList > const & xAttribs ) |
| throw (xml::sax::SAXException, RuntimeException) |
| { |
| Reference< xml::input::XElement > xCurrentElement; |
| Reference< xml::input::XAttributes > xAttributes; |
| sal_Int32 nUid; |
| OUString aLocalName; |
| ::std::auto_ptr< ElementEntry > elementEntry( new ElementEntry ); |
| |
| { // guard start: |
| MGuard aGuard( m_pMutex ); |
| // currently skipping elements and waiting for end tags? |
| if (m_nSkipElements > 0) |
| { |
| ++m_nSkipElements; // wait for another end tag |
| #if OSL_DEBUG_LEVEL > 1 |
| OString aQName( |
| OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) ); |
| OSL_TRACE( "### no context given on createChildElement() " |
| "=> ignoring element \"%s\" ...", aQName.getStr() ); |
| #endif |
| return; |
| } |
| |
| sal_Int16 nAttribs = xAttribs->getLength(); |
| |
| // save all namespace ids |
| sal_Int32 * pUids = new sal_Int32[ nAttribs ]; |
| OUString * pPrefixes = new OUString[ nAttribs ]; |
| OUString * pLocalNames = new OUString[ nAttribs ]; |
| OUString * pQNames = new OUString[ nAttribs ]; |
| |
| // first recognize all xmlns attributes |
| sal_Int16 nPos; |
| for ( nPos = 0; nPos < nAttribs; ++nPos ) |
| { |
| // mark attribute to be collected further |
| // on with attribute's uid and current prefix |
| pUids[ nPos ] = 0; // modified |
| |
| pQNames[ nPos ] = xAttribs->getNameByIndex( nPos ); |
| OUString const & rQAttributeName = pQNames[ nPos ]; |
| |
| if (rQAttributeName.compareTo( m_sXMLNS, 5 ) == 0) |
| { |
| if (rQAttributeName.getLength() == 5) // set default namespace |
| { |
| OUString aDefNamespacePrefix; |
| pushPrefix( |
| aDefNamespacePrefix, |
| xAttribs->getValueByIndex( nPos ) ); |
| elementEntry->m_prefixes.push_back( aDefNamespacePrefix ); |
| pUids[ nPos ] = UID_UNKNOWN; |
| pPrefixes[ nPos ] = m_sXMLNS; |
| pLocalNames[ nPos ] = aDefNamespacePrefix; |
| } |
| else if ((sal_Unicode)':' == rQAttributeName[ 5 ]) // set prefix |
| { |
| OUString aPrefix( rQAttributeName.copy( 6 ) ); |
| pushPrefix( aPrefix, xAttribs->getValueByIndex( nPos ) ); |
| elementEntry->m_prefixes.push_back( aPrefix ); |
| pUids[ nPos ] = UID_UNKNOWN; |
| pPrefixes[ nPos ] = m_sXMLNS; |
| pLocalNames[ nPos ] = aPrefix; |
| } |
| // else just a name starting with xmlns, but no prefix |
| } |
| } |
| |
| // now read out attribute prefixes (all namespace prefixes have been set) |
| for ( nPos = 0; nPos < nAttribs; ++nPos ) |
| { |
| if (pUids[ nPos ] >= 0) // no xmlns: attribute |
| { |
| OUString const & rQAttributeName = pQNames[ nPos ]; |
| OSL_ENSURE( |
| rQAttributeName.compareToAscii( |
| RTL_CONSTASCII_STRINGPARAM("xmlns:") ) != 0, |
| "### unexpected xmlns!" ); |
| |
| // collect attribute's uid and current prefix |
| sal_Int32 nColonPos = rQAttributeName.indexOf( (sal_Unicode) ':' ); |
| if (nColonPos >= 0) |
| { |
| pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos ); |
| pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 ); |
| } |
| else |
| { |
| pPrefixes[ nPos ] = OUString(); |
| pLocalNames[ nPos ] = rQAttributeName; |
| // leave local names unmodified |
| } |
| pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] ); |
| } |
| } |
| // ownership of arrays belongs to attribute list |
| xAttributes = static_cast< xml::input::XAttributes * >( |
| new ExtendedAttributes( |
| nAttribs, pUids, pPrefixes, pLocalNames, pQNames, |
| xAttribs, this ) ); |
| |
| getElementName( rQElementName, &nUid, &aLocalName ); |
| |
| // create new child context and append to list |
| if (! m_elements.empty()) |
| xCurrentElement = m_elements.back()->m_xElement; |
| } // :guard end |
| |
| if (xCurrentElement.is()) |
| { |
| elementEntry->m_xElement = |
| xCurrentElement->startChildElement( nUid, aLocalName, xAttributes ); |
| } |
| else |
| { |
| elementEntry->m_xElement = |
| m_xRoot->startRootElement( nUid, aLocalName, xAttributes ); |
| } |
| |
| { |
| MGuard aGuard( m_pMutex ); |
| if (elementEntry->m_xElement.is()) |
| { |
| m_elements.push_back( elementEntry.release() ); |
| } |
| else |
| { |
| ++m_nSkipElements; |
| #if OSL_DEBUG_LEVEL > 1 |
| OString aQName( |
| OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) ); |
| OSL_TRACE( |
| "### no context given on createChildElement() => " |
| "ignoring element \"%s\" ...", aQName.getStr() ); |
| #endif |
| } |
| } |
| } |
| |
| //______________________________________________________________________________ |
| void DocumentHandlerImpl::endElement( |
| OUString const & rQElementName ) |
| throw (xml::sax::SAXException, RuntimeException) |
| { |
| Reference< xml::input::XElement > xCurrentElement; |
| { |
| MGuard aGuard( m_pMutex ); |
| if (m_nSkipElements) |
| { |
| --m_nSkipElements; |
| #if OSL_DEBUG_LEVEL > 1 |
| OString aQName( |
| OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) ); |
| OSL_TRACE( "### received endElement() for \"%s\".", aQName.getStr() ); |
| #endif |
| static_cast<void>(rQElementName); |
| return; |
| } |
| |
| // popping context |
| OSL_ASSERT( ! m_elements.empty() ); |
| ElementEntry * pEntry = m_elements.back(); |
| xCurrentElement = pEntry->m_xElement; |
| |
| #if OSL_DEBUG_LEVEL > 0 |
| sal_Int32 nUid; |
| OUString aLocalName; |
| getElementName( rQElementName, &nUid, &aLocalName ); |
| OSL_ASSERT( xCurrentElement->getLocalName() == aLocalName ); |
| OSL_ASSERT( xCurrentElement->getUid() == nUid ); |
| #endif |
| |
| // pop prefixes |
| for ( sal_Int32 nPos = pEntry->m_prefixes.size(); nPos--; ) |
| { |
| popPrefix( pEntry->m_prefixes[ nPos ] ); |
| } |
| m_elements.pop_back(); |
| delete pEntry; |
| } |
| xCurrentElement->endElement(); |
| } |
| |
| //______________________________________________________________________________ |
| void DocumentHandlerImpl::characters( OUString const & rChars ) |
| throw (xml::sax::SAXException, RuntimeException) |
| { |
| Reference< xml::input::XElement > xCurrentElement( getCurrentElement() ); |
| if (xCurrentElement.is()) |
| xCurrentElement->characters( rChars ); |
| } |
| |
| //______________________________________________________________________________ |
| void DocumentHandlerImpl::ignorableWhitespace( |
| OUString const & rWhitespaces ) |
| throw (xml::sax::SAXException, RuntimeException) |
| { |
| Reference< xml::input::XElement > xCurrentElement( getCurrentElement() ); |
| if (xCurrentElement.is()) |
| xCurrentElement->ignorableWhitespace( rWhitespaces ); |
| } |
| |
| //______________________________________________________________________________ |
| void DocumentHandlerImpl::processingInstruction( |
| OUString const & rTarget, OUString const & rData ) |
| throw (xml::sax::SAXException, RuntimeException) |
| { |
| Reference< xml::input::XElement > xCurrentElement( getCurrentElement() ); |
| if (xCurrentElement.is()) |
| xCurrentElement->processingInstruction( rTarget, rData ); |
| else |
| m_xRoot->processingInstruction( rTarget, rData ); |
| } |
| |
| //______________________________________________________________________________ |
| void DocumentHandlerImpl::setDocumentLocator( |
| Reference< xml::sax::XLocator > const & xLocator ) |
| throw (xml::sax::SAXException, RuntimeException) |
| { |
| m_xRoot->setDocumentLocator( xLocator ); |
| } |
| |
| //############################################################################## |
| |
| // XAttributes |
| |
| //______________________________________________________________________________ |
| sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName ) |
| throw (RuntimeException) |
| { |
| for ( sal_Int32 nPos = m_nAttributes; nPos--; ) |
| { |
| if (m_pQNames[ nPos ].equals( rQName )) |
| { |
| return nPos; |
| } |
| } |
| return -1; |
| } |
| |
| //______________________________________________________________________________ |
| sal_Int32 ExtendedAttributes::getLength() |
| throw (RuntimeException) |
| { |
| return m_nAttributes; |
| } |
| |
| //______________________________________________________________________________ |
| OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex ) |
| throw (RuntimeException) |
| { |
| if (nIndex < m_nAttributes) |
| return m_pLocalNames[ nIndex ]; |
| else |
| return OUString(); |
| } |
| |
| //______________________________________________________________________________ |
| OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex ) |
| throw (RuntimeException) |
| { |
| if (nIndex < m_nAttributes) |
| return m_pQNames[ nIndex ]; |
| else |
| return OUString(); |
| } |
| |
| //______________________________________________________________________________ |
| OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex ) |
| throw (RuntimeException) |
| { |
| static_cast<void>(nIndex); |
| OSL_ASSERT( nIndex < m_nAttributes ); |
| return OUString(); // unsupported |
| } |
| |
| //______________________________________________________________________________ |
| OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex ) |
| throw (RuntimeException) |
| { |
| if (nIndex < m_nAttributes) |
| return m_pValues[ nIndex ]; |
| else |
| return OUString(); |
| } |
| |
| //______________________________________________________________________________ |
| sal_Int32 ExtendedAttributes::getIndexByUidName( |
| sal_Int32 nUid, OUString const & rLocalName ) |
| throw (RuntimeException) |
| { |
| for ( sal_Int32 nPos = m_nAttributes; nPos--; ) |
| { |
| if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName) |
| { |
| return nPos; |
| } |
| } |
| return -1; |
| } |
| |
| //______________________________________________________________________________ |
| sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex ) |
| throw (RuntimeException) |
| { |
| if (nIndex < m_nAttributes) |
| return m_pUids[ nIndex ]; |
| else |
| return -1; |
| } |
| |
| //______________________________________________________________________________ |
| OUString ExtendedAttributes::getValueByUidName( |
| sal_Int32 nUid, OUString const & rLocalName ) |
| throw (RuntimeException) |
| { |
| for ( sal_Int32 nPos = m_nAttributes; nPos--; ) |
| { |
| if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName) |
| { |
| return m_pValues[ nPos ]; |
| } |
| } |
| return OUString(); |
| } |
| |
| |
| //############################################################################## |
| |
| |
| //============================================================================== |
| Reference< xml::sax::XDocumentHandler > SAL_CALL createDocumentHandler( |
| Reference< xml::input::XRoot > const & xRoot, |
| bool bSingleThreadedUse ) |
| SAL_THROW( () ) |
| { |
| OSL_ASSERT( xRoot.is() ); |
| if (xRoot.is()) |
| { |
| return static_cast< xml::sax::XDocumentHandler * >( |
| new DocumentHandlerImpl( xRoot, bSingleThreadedUse ) ); |
| } |
| return Reference< xml::sax::XDocumentHandler >(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Reference< XInterface > SAL_CALL create_DocumentHandlerImpl( |
| Reference< XComponentContext > const & ) |
| SAL_THROW( (Exception) ) |
| { |
| return static_cast< ::cppu::OWeakObject * >( |
| new DocumentHandlerImpl( |
| Reference< xml::input::XRoot >(), false /* mt use */ ) ); |
| } |
| |
| } |