1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_xmlscript.hxx" 26 27 #include "osl/diagnose.h" 28 #include "osl/mutex.hxx" 29 #include "rtl/ustrbuf.hxx" 30 #include "cppuhelper/factory.hxx" 31 #include "cppuhelper/implementationentry.hxx" 32 #include "cppuhelper/implbase1.hxx" 33 #include "cppuhelper/implbase3.hxx" 34 #include "xml_import.hxx" 35 36 #include "com/sun/star/xml/input/XAttributes.hpp" 37 #include "com/sun/star/lang/XInitialization.hpp" 38 #include "com/sun/star/uno/XComponentContext.hpp" 39 40 #include <vector> 41 #include <hash_map> 42 43 #include <memory> 44 45 46 using namespace ::rtl; 47 using namespace ::osl; 48 using namespace ::com::sun::star; 49 using namespace ::com::sun::star::uno; 50 51 namespace xmlscript 52 { 53 54 const sal_Int32 UID_UNKNOWN = -1; 55 56 Sequence< OUString > getSupportedServiceNames_DocumentHandlerImpl() 57 { 58 OUString name( RTL_CONSTASCII_USTRINGPARAM( 59 "com.sun.star.xml.input.SaxDocumentHandler") ); 60 return Sequence< OUString >( &name, 1 ); 61 } 62 63 OUString getImplementationName_DocumentHandlerImpl() 64 { 65 return OUString( RTL_CONSTASCII_USTRINGPARAM( 66 "com.sun.star.comp.xml.input.SaxDocumentHandler") ); 67 } 68 69 typedef ::std::hash_map< OUString, sal_Int32, OUStringHash > t_OUString2LongMap; 70 typedef ::std::hash_map< sal_Int32, OUString > t_Long2OUStringMap; 71 72 struct PrefixEntry 73 { 74 ::std::vector< sal_Int32 > m_Uids; 75 76 inline PrefixEntry() SAL_THROW( () ) 77 { m_Uids.reserve( 4 ); } 78 }; 79 80 typedef ::std::hash_map< 81 OUString, PrefixEntry *, OUStringHash > t_OUString2PrefixMap; 82 83 struct ElementEntry 84 { 85 Reference< xml::input::XElement > m_xElement; 86 ::std::vector< OUString > m_prefixes; 87 88 inline ElementEntry() 89 { m_prefixes.reserve( 2 ); } 90 }; 91 92 typedef ::std::vector< ElementEntry * > t_ElementVector; 93 94 class ExtendedAttributes; 95 96 //============================================================================== 97 struct MGuard 98 { 99 Mutex * m_pMutex; 100 explicit MGuard( Mutex * pMutex ) 101 : m_pMutex( pMutex ) 102 { if (m_pMutex) m_pMutex->acquire(); } 103 ~MGuard() throw () 104 { if (m_pMutex) m_pMutex->release(); } 105 }; 106 107 //============================================================================== 108 class DocumentHandlerImpl : 109 public ::cppu::WeakImplHelper3< xml::sax::XDocumentHandler, 110 xml::input::XNamespaceMapping, 111 lang::XInitialization > 112 { 113 friend class ExtendedAttributes; 114 115 Reference< xml::input::XRoot > m_xRoot; 116 117 t_OUString2LongMap m_URI2Uid; 118 sal_Int32 m_uid_count; 119 120 OUString m_sXMLNS_PREFIX_UNKNOWN; 121 OUString m_sXMLNS; 122 123 sal_Int32 m_nLastURI_lookup; 124 OUString m_aLastURI_lookup; 125 126 t_OUString2PrefixMap m_prefixes; 127 sal_Int32 m_nLastPrefix_lookup; 128 OUString m_aLastPrefix_lookup; 129 130 t_ElementVector m_elements; 131 sal_Int32 m_nSkipElements; 132 133 Mutex * m_pMutex; 134 135 inline Reference< xml::input::XElement > getCurrentElement() const; 136 137 inline sal_Int32 getUidByURI( OUString const & rURI ); 138 inline sal_Int32 getUidByPrefix( OUString const & rPrefix ); 139 140 inline void pushPrefix( 141 OUString const & rPrefix, OUString const & rURI ); 142 inline void popPrefix( OUString const & rPrefix ); 143 144 inline void getElementName( 145 OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName ); 146 147 public: 148 DocumentHandlerImpl( 149 Reference< xml::input::XRoot > const & xRoot, 150 bool bSingleThreadedUse ); 151 virtual ~DocumentHandlerImpl() throw (); 152 153 // XServiceInfo 154 virtual OUString SAL_CALL getImplementationName(); 155 virtual sal_Bool SAL_CALL supportsService( 156 OUString const & servicename ); 157 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(); 158 159 // XInitialization 160 virtual void SAL_CALL initialize( 161 Sequence< Any > const & arguments ); 162 163 // XDocumentHandler 164 virtual void SAL_CALL startDocument(); 165 virtual void SAL_CALL endDocument(); 166 virtual void SAL_CALL startElement( 167 OUString const & rQElementName, 168 Reference< xml::sax::XAttributeList > const & xAttribs ); 169 virtual void SAL_CALL endElement( 170 OUString const & rQElementName ); 171 virtual void SAL_CALL characters( 172 OUString const & rChars ); 173 virtual void SAL_CALL ignorableWhitespace( 174 OUString const & rWhitespaces ); 175 virtual void SAL_CALL processingInstruction( 176 OUString const & rTarget, OUString const & rData ); 177 virtual void SAL_CALL setDocumentLocator( 178 Reference< xml::sax::XLocator > const & xLocator ); 179 180 // XNamespaceMapping 181 virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri ); 182 virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid ); 183 }; 184 185 //______________________________________________________________________________ 186 DocumentHandlerImpl::DocumentHandlerImpl( 187 Reference< xml::input::XRoot > const & xRoot, 188 bool bSingleThreadedUse ) 189 : m_xRoot( xRoot ), 190 m_uid_count( 0 ), 191 m_sXMLNS_PREFIX_UNKNOWN( 192 RTL_CONSTASCII_USTRINGPARAM("<<< unknown prefix >>>") ), 193 m_sXMLNS( RTL_CONSTASCII_USTRINGPARAM("xmlns") ), 194 m_nLastURI_lookup( UID_UNKNOWN ), 195 m_aLastURI_lookup( RTL_CONSTASCII_USTRINGPARAM("<<< unknown URI >>>") ), 196 m_nLastPrefix_lookup( UID_UNKNOWN ), 197 m_aLastPrefix_lookup( 198 RTL_CONSTASCII_USTRINGPARAM("<<< unknown URI >>>") ), 199 m_nSkipElements( 0 ), 200 m_pMutex( 0 ) 201 { 202 m_elements.reserve( 10 ); 203 204 if (! bSingleThreadedUse) 205 m_pMutex = new Mutex(); 206 } 207 208 //______________________________________________________________________________ 209 DocumentHandlerImpl::~DocumentHandlerImpl() throw () 210 { 211 if (m_pMutex != 0) 212 { 213 delete m_pMutex; 214 #if OSL_DEBUG_LEVEL == 0 215 m_pMutex = 0; 216 #endif 217 } 218 } 219 220 //______________________________________________________________________________ 221 inline Reference< xml::input::XElement > 222 DocumentHandlerImpl::getCurrentElement() const 223 { 224 MGuard aGuard( m_pMutex ); 225 if (m_elements.empty()) 226 return Reference< xml::input::XElement >(); 227 else 228 return m_elements.back()->m_xElement; 229 } 230 231 //______________________________________________________________________________ 232 inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI ) 233 { 234 MGuard guard( m_pMutex ); 235 if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI) 236 { 237 t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) ); 238 if (iFind != m_URI2Uid.end()) // id found 239 { 240 m_nLastURI_lookup = iFind->second; 241 m_aLastURI_lookup = rURI; 242 } 243 else 244 { 245 m_nLastURI_lookup = m_uid_count; 246 ++m_uid_count; 247 m_URI2Uid[ rURI ] = m_nLastURI_lookup; 248 m_aLastURI_lookup = rURI; 249 } 250 } 251 return m_nLastURI_lookup; 252 } 253 254 //______________________________________________________________________________ 255 inline sal_Int32 DocumentHandlerImpl::getUidByPrefix( 256 OUString const & rPrefix ) 257 { 258 // commonly the last added prefix is used often for several tags... 259 // good guess 260 if (m_nLastPrefix_lookup == UID_UNKNOWN || m_aLastPrefix_lookup != rPrefix) 261 { 262 t_OUString2PrefixMap::const_iterator iFind( 263 m_prefixes.find( rPrefix ) ); 264 if (iFind != m_prefixes.end()) 265 { 266 const PrefixEntry & rPrefixEntry = *iFind->second; 267 OSL_ASSERT( ! rPrefixEntry.m_Uids.empty() ); 268 m_nLastPrefix_lookup = rPrefixEntry.m_Uids.back(); 269 m_aLastPrefix_lookup = rPrefix; 270 } 271 else 272 { 273 m_nLastPrefix_lookup = UID_UNKNOWN; 274 m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN; 275 } 276 } 277 return m_nLastPrefix_lookup; 278 } 279 280 //______________________________________________________________________________ 281 inline void DocumentHandlerImpl::pushPrefix( 282 OUString const & rPrefix, OUString const & rURI ) 283 { 284 // lookup id for URI 285 sal_Int32 nUid = getUidByURI( rURI ); 286 287 // mark prefix with id 288 t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) ); 289 if (iFind == m_prefixes.end()) // unused prefix 290 { 291 PrefixEntry * pEntry = new PrefixEntry(); 292 pEntry->m_Uids.push_back( nUid ); // latest id for prefix 293 m_prefixes[ rPrefix ] = pEntry; 294 } 295 else 296 { 297 PrefixEntry * pEntry = iFind->second; 298 OSL_ASSERT( ! pEntry->m_Uids.empty() ); 299 pEntry->m_Uids.push_back( nUid ); 300 } 301 302 m_aLastPrefix_lookup = rPrefix; 303 m_nLastPrefix_lookup = nUid; 304 } 305 306 //______________________________________________________________________________ 307 inline void DocumentHandlerImpl::popPrefix( 308 OUString const & rPrefix ) 309 { 310 t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) ); 311 if (iFind != m_prefixes.end()) // unused prefix 312 { 313 PrefixEntry * pEntry = iFind->second; 314 pEntry->m_Uids.pop_back(); // pop last id for prefix 315 if (pEntry->m_Uids.empty()) // erase prefix key 316 { 317 m_prefixes.erase( iFind ); 318 delete pEntry; 319 } 320 } 321 322 m_nLastPrefix_lookup = UID_UNKNOWN; 323 m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN; 324 } 325 326 //______________________________________________________________________________ 327 inline void DocumentHandlerImpl::getElementName( 328 OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName ) 329 { 330 sal_Int32 nColonPos = rQName.indexOf( (sal_Unicode)':' ); 331 *pLocalName = (nColonPos >= 0 ? rQName.copy( nColonPos +1 ) : rQName); 332 *pUid = getUidByPrefix( 333 nColonPos >= 0 ? rQName.copy( 0, nColonPos ) : OUString() ); 334 } 335 336 337 //============================================================================== 338 class ExtendedAttributes : 339 public ::cppu::WeakImplHelper1< xml::input::XAttributes > 340 { 341 sal_Int32 m_nAttributes; 342 sal_Int32 * m_pUids; 343 OUString * m_pPrefixes; 344 OUString * m_pLocalNames; 345 OUString * m_pQNames; 346 OUString * m_pValues; 347 348 DocumentHandlerImpl * m_pHandler; 349 350 public: 351 inline ExtendedAttributes( 352 sal_Int32 nAttributes, 353 sal_Int32 * pUids, OUString * pPrefixes, 354 OUString * pLocalNames, OUString * pQNames, 355 Reference< xml::sax::XAttributeList > const & xAttributeList, 356 DocumentHandlerImpl * pHandler ); 357 virtual ~ExtendedAttributes() throw (); 358 359 // XAttributes 360 virtual sal_Int32 SAL_CALL getLength(); 361 virtual sal_Int32 SAL_CALL getIndexByQName( 362 OUString const & rQName ); 363 virtual sal_Int32 SAL_CALL getIndexByUidName( 364 sal_Int32 nUid, OUString const & rLocalName ); 365 virtual OUString SAL_CALL getQNameByIndex( 366 sal_Int32 nIndex ); 367 virtual sal_Int32 SAL_CALL getUidByIndex( 368 sal_Int32 nIndex ); 369 virtual OUString SAL_CALL getLocalNameByIndex( 370 sal_Int32 nIndex ); 371 virtual OUString SAL_CALL getValueByIndex( 372 sal_Int32 nIndex ); 373 virtual OUString SAL_CALL getValueByUidName( 374 sal_Int32 nUid, OUString const & rLocalName ); 375 virtual OUString SAL_CALL getTypeByIndex( 376 sal_Int32 nIndex ); 377 }; 378 379 //______________________________________________________________________________ 380 inline ExtendedAttributes::ExtendedAttributes( 381 sal_Int32 nAttributes, 382 sal_Int32 * pUids, OUString * pPrefixes, 383 OUString * pLocalNames, OUString * pQNames, 384 Reference< xml::sax::XAttributeList > const & xAttributeList, 385 DocumentHandlerImpl * pHandler ) 386 : m_nAttributes( nAttributes ) 387 , m_pUids( pUids ) 388 , m_pPrefixes( pPrefixes ) 389 , m_pLocalNames( pLocalNames ) 390 , m_pQNames( pQNames ) 391 , m_pValues( new OUString[ nAttributes ] ) 392 , m_pHandler( pHandler ) 393 { 394 m_pHandler->acquire(); 395 396 for ( sal_Int16 nPos = 0; nPos < nAttributes; ++nPos ) 397 { 398 m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos ); 399 } 400 } 401 402 //______________________________________________________________________________ 403 ExtendedAttributes::~ExtendedAttributes() throw () 404 { 405 m_pHandler->release(); 406 407 delete [] m_pUids; 408 delete [] m_pPrefixes; 409 delete [] m_pLocalNames; 410 delete [] m_pQNames; 411 delete [] m_pValues; 412 } 413 414 415 //############################################################################## 416 417 // XServiceInfo 418 419 //______________________________________________________________________________ 420 OUString DocumentHandlerImpl::getImplementationName() 421 { 422 return getImplementationName_DocumentHandlerImpl(); 423 } 424 425 //______________________________________________________________________________ 426 sal_Bool DocumentHandlerImpl::supportsService( 427 OUString const & servicename ) 428 { 429 Sequence< OUString > names( getSupportedServiceNames_DocumentHandlerImpl() ); 430 for ( sal_Int32 nPos = names.getLength(); nPos--; ) 431 { 432 if (names[ nPos ].equals( servicename )) 433 return sal_True; 434 } 435 return sal_False; 436 } 437 438 //______________________________________________________________________________ 439 Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames() 440 { 441 return getSupportedServiceNames_DocumentHandlerImpl(); 442 } 443 444 // XInitialization 445 446 //______________________________________________________________________________ 447 void DocumentHandlerImpl::initialize( 448 Sequence< Any > const & arguments ) 449 { 450 MGuard guard( m_pMutex ); 451 Reference< xml::input::XRoot > xRoot; 452 if (arguments.getLength() == 1 && 453 (arguments[ 0 ] >>= xRoot) && 454 xRoot.is()) 455 { 456 m_xRoot = xRoot; 457 } 458 else 459 { 460 throw RuntimeException( 461 OUString( RTL_CONSTASCII_USTRINGPARAM( 462 "missing root instance!") ), 463 Reference< XInterface >() ); 464 } 465 } 466 467 468 // XNamespaceMapping 469 470 //______________________________________________________________________________ 471 sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri ) 472 { 473 sal_Int32 uid = getUidByURI( Uri ); 474 OSL_ASSERT( uid != UID_UNKNOWN ); 475 return uid; 476 } 477 478 //______________________________________________________________________________ 479 OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid ) 480 { 481 MGuard guard( m_pMutex ); 482 t_OUString2LongMap::const_iterator iPos( m_URI2Uid.begin() ); 483 t_OUString2LongMap::const_iterator const iEnd( m_URI2Uid.end() ); 484 for ( ; iPos != iEnd; ++iPos ) 485 { 486 if (iPos->second == Uid) 487 return iPos->first; 488 } 489 throw container::NoSuchElementException( 490 OUString( RTL_CONSTASCII_USTRINGPARAM("no such xmlns uid!") ), 491 static_cast< OWeakObject * >(this) ); 492 } 493 494 495 // XDocumentHandler 496 497 //______________________________________________________________________________ 498 void DocumentHandlerImpl::startDocument() 499 { 500 m_xRoot->startDocument( 501 static_cast< xml::input::XNamespaceMapping * >( this ) ); 502 } 503 504 //______________________________________________________________________________ 505 void DocumentHandlerImpl::endDocument() 506 { 507 m_xRoot->endDocument(); 508 } 509 510 //______________________________________________________________________________ 511 void DocumentHandlerImpl::startElement( 512 OUString const & rQElementName, 513 Reference< xml::sax::XAttributeList > const & xAttribs ) 514 { 515 Reference< xml::input::XElement > xCurrentElement; 516 Reference< xml::input::XAttributes > xAttributes; 517 sal_Int32 nUid; 518 OUString aLocalName; 519 ::std::auto_ptr< ElementEntry > elementEntry( new ElementEntry ); 520 521 { // guard start: 522 MGuard aGuard( m_pMutex ); 523 // currently skipping elements and waiting for end tags? 524 if (m_nSkipElements > 0) 525 { 526 ++m_nSkipElements; // wait for another end tag 527 #if OSL_DEBUG_LEVEL > 1 528 OString aQName( 529 OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) ); 530 OSL_TRACE( "### no context given on createChildElement() " 531 "=> ignoring element \"%s\" ...", aQName.getStr() ); 532 #endif 533 return; 534 } 535 536 sal_Int16 nAttribs = xAttribs->getLength(); 537 538 // save all namespace ids 539 sal_Int32 * pUids = new sal_Int32[ nAttribs ]; 540 OUString * pPrefixes = new OUString[ nAttribs ]; 541 OUString * pLocalNames = new OUString[ nAttribs ]; 542 OUString * pQNames = new OUString[ nAttribs ]; 543 544 // first recognize all xmlns attributes 545 sal_Int16 nPos; 546 for ( nPos = 0; nPos < nAttribs; ++nPos ) 547 { 548 // mark attribute to be collected further 549 // on with attribute's uid and current prefix 550 pUids[ nPos ] = 0; // modified 551 552 pQNames[ nPos ] = xAttribs->getNameByIndex( nPos ); 553 OUString const & rQAttributeName = pQNames[ nPos ]; 554 555 if (rQAttributeName.compareTo( m_sXMLNS, 5 ) == 0) 556 { 557 if (rQAttributeName.getLength() == 5) // set default namespace 558 { 559 OUString aDefNamespacePrefix; 560 pushPrefix( 561 aDefNamespacePrefix, 562 xAttribs->getValueByIndex( nPos ) ); 563 elementEntry->m_prefixes.push_back( aDefNamespacePrefix ); 564 pUids[ nPos ] = UID_UNKNOWN; 565 pPrefixes[ nPos ] = m_sXMLNS; 566 pLocalNames[ nPos ] = aDefNamespacePrefix; 567 } 568 else if ((sal_Unicode)':' == rQAttributeName[ 5 ]) // set prefix 569 { 570 OUString aPrefix( rQAttributeName.copy( 6 ) ); 571 pushPrefix( aPrefix, xAttribs->getValueByIndex( nPos ) ); 572 elementEntry->m_prefixes.push_back( aPrefix ); 573 pUids[ nPos ] = UID_UNKNOWN; 574 pPrefixes[ nPos ] = m_sXMLNS; 575 pLocalNames[ nPos ] = aPrefix; 576 } 577 // else just a name starting with xmlns, but no prefix 578 } 579 } 580 581 // now read out attribute prefixes (all namespace prefixes have been set) 582 for ( nPos = 0; nPos < nAttribs; ++nPos ) 583 { 584 if (pUids[ nPos ] >= 0) // no xmlns: attribute 585 { 586 OUString const & rQAttributeName = pQNames[ nPos ]; 587 OSL_ENSURE( 588 rQAttributeName.compareToAscii( 589 RTL_CONSTASCII_STRINGPARAM("xmlns:") ) != 0, 590 "### unexpected xmlns!" ); 591 592 // collect attribute's uid and current prefix 593 sal_Int32 nColonPos = rQAttributeName.indexOf( (sal_Unicode) ':' ); 594 if (nColonPos >= 0) 595 { 596 pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos ); 597 pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 ); 598 } 599 else 600 { 601 pPrefixes[ nPos ] = OUString(); 602 pLocalNames[ nPos ] = rQAttributeName; 603 // leave local names unmodified 604 } 605 pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] ); 606 } 607 } 608 // ownership of arrays belongs to attribute list 609 xAttributes = static_cast< xml::input::XAttributes * >( 610 new ExtendedAttributes( 611 nAttribs, pUids, pPrefixes, pLocalNames, pQNames, 612 xAttribs, this ) ); 613 614 getElementName( rQElementName, &nUid, &aLocalName ); 615 616 // create new child context and append to list 617 if (! m_elements.empty()) 618 xCurrentElement = m_elements.back()->m_xElement; 619 } // :guard end 620 621 if (xCurrentElement.is()) 622 { 623 elementEntry->m_xElement = 624 xCurrentElement->startChildElement( nUid, aLocalName, xAttributes ); 625 } 626 else 627 { 628 elementEntry->m_xElement = 629 m_xRoot->startRootElement( nUid, aLocalName, xAttributes ); 630 } 631 632 { 633 MGuard aGuard( m_pMutex ); 634 if (elementEntry->m_xElement.is()) 635 { 636 m_elements.push_back( elementEntry.release() ); 637 } 638 else 639 { 640 ++m_nSkipElements; 641 #if OSL_DEBUG_LEVEL > 1 642 OString aQName( 643 OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) ); 644 OSL_TRACE( 645 "### no context given on createChildElement() => " 646 "ignoring element \"%s\" ...", aQName.getStr() ); 647 #endif 648 } 649 } 650 } 651 652 //______________________________________________________________________________ 653 void DocumentHandlerImpl::endElement( 654 OUString const & rQElementName ) 655 { 656 Reference< xml::input::XElement > xCurrentElement; 657 { 658 MGuard aGuard( m_pMutex ); 659 if (m_nSkipElements) 660 { 661 --m_nSkipElements; 662 #if OSL_DEBUG_LEVEL > 1 663 OString aQName( 664 OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) ); 665 OSL_TRACE( "### received endElement() for \"%s\".", aQName.getStr() ); 666 #endif 667 static_cast<void>(rQElementName); 668 return; 669 } 670 671 // popping context 672 OSL_ASSERT( ! m_elements.empty() ); 673 ElementEntry * pEntry = m_elements.back(); 674 xCurrentElement = pEntry->m_xElement; 675 676 #if OSL_DEBUG_LEVEL > 0 677 sal_Int32 nUid; 678 OUString aLocalName; 679 getElementName( rQElementName, &nUid, &aLocalName ); 680 OSL_ASSERT( xCurrentElement->getLocalName() == aLocalName ); 681 OSL_ASSERT( xCurrentElement->getUid() == nUid ); 682 #endif 683 684 // pop prefixes 685 for ( sal_Int32 nPos = pEntry->m_prefixes.size(); nPos--; ) 686 { 687 popPrefix( pEntry->m_prefixes[ nPos ] ); 688 } 689 m_elements.pop_back(); 690 delete pEntry; 691 } 692 xCurrentElement->endElement(); 693 } 694 695 //______________________________________________________________________________ 696 void DocumentHandlerImpl::characters( OUString const & rChars ) 697 { 698 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() ); 699 if (xCurrentElement.is()) 700 xCurrentElement->characters( rChars ); 701 } 702 703 //______________________________________________________________________________ 704 void DocumentHandlerImpl::ignorableWhitespace( 705 OUString const & rWhitespaces ) 706 { 707 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() ); 708 if (xCurrentElement.is()) 709 xCurrentElement->ignorableWhitespace( rWhitespaces ); 710 } 711 712 //______________________________________________________________________________ 713 void DocumentHandlerImpl::processingInstruction( 714 OUString const & rTarget, OUString const & rData ) 715 { 716 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() ); 717 if (xCurrentElement.is()) 718 xCurrentElement->processingInstruction( rTarget, rData ); 719 else 720 m_xRoot->processingInstruction( rTarget, rData ); 721 } 722 723 //______________________________________________________________________________ 724 void DocumentHandlerImpl::setDocumentLocator( 725 Reference< xml::sax::XLocator > const & xLocator ) 726 { 727 m_xRoot->setDocumentLocator( xLocator ); 728 } 729 730 //############################################################################## 731 732 // XAttributes 733 734 //______________________________________________________________________________ 735 sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName ) 736 { 737 for ( sal_Int32 nPos = m_nAttributes; nPos--; ) 738 { 739 if (m_pQNames[ nPos ].equals( rQName )) 740 { 741 return nPos; 742 } 743 } 744 return -1; 745 } 746 747 //______________________________________________________________________________ 748 sal_Int32 ExtendedAttributes::getLength() 749 { 750 return m_nAttributes; 751 } 752 753 //______________________________________________________________________________ 754 OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex ) 755 { 756 if (nIndex < m_nAttributes) 757 return m_pLocalNames[ nIndex ]; 758 else 759 return OUString(); 760 } 761 762 //______________________________________________________________________________ 763 OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex ) 764 { 765 if (nIndex < m_nAttributes) 766 return m_pQNames[ nIndex ]; 767 else 768 return OUString(); 769 } 770 771 //______________________________________________________________________________ 772 OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex ) 773 { 774 static_cast<void>(nIndex); 775 OSL_ASSERT( nIndex < m_nAttributes ); 776 return OUString(); // unsupported 777 } 778 779 //______________________________________________________________________________ 780 OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex ) 781 { 782 if (nIndex < m_nAttributes) 783 return m_pValues[ nIndex ]; 784 else 785 return OUString(); 786 } 787 788 //______________________________________________________________________________ 789 sal_Int32 ExtendedAttributes::getIndexByUidName( 790 sal_Int32 nUid, OUString const & rLocalName ) 791 { 792 for ( sal_Int32 nPos = m_nAttributes; nPos--; ) 793 { 794 if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName) 795 { 796 return nPos; 797 } 798 } 799 return -1; 800 } 801 802 //______________________________________________________________________________ 803 sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex ) 804 { 805 if (nIndex < m_nAttributes) 806 return m_pUids[ nIndex ]; 807 else 808 return -1; 809 } 810 811 //______________________________________________________________________________ 812 OUString ExtendedAttributes::getValueByUidName( 813 sal_Int32 nUid, OUString const & rLocalName ) 814 { 815 for ( sal_Int32 nPos = m_nAttributes; nPos--; ) 816 { 817 if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName) 818 { 819 return m_pValues[ nPos ]; 820 } 821 } 822 return OUString(); 823 } 824 825 826 //############################################################################## 827 828 829 //============================================================================== 830 Reference< xml::sax::XDocumentHandler > SAL_CALL createDocumentHandler( 831 Reference< xml::input::XRoot > const & xRoot, 832 bool bSingleThreadedUse ) 833 SAL_THROW( () ) 834 { 835 OSL_ASSERT( xRoot.is() ); 836 if (xRoot.is()) 837 { 838 return static_cast< xml::sax::XDocumentHandler * >( 839 new DocumentHandlerImpl( xRoot, bSingleThreadedUse ) ); 840 } 841 return Reference< xml::sax::XDocumentHandler >(); 842 } 843 844 //------------------------------------------------------------------------------ 845 Reference< XInterface > SAL_CALL create_DocumentHandlerImpl( 846 Reference< XComponentContext > const & ) 847 { 848 return static_cast< ::cppu::OWeakObject * >( 849 new DocumentHandlerImpl( 850 Reference< xml::input::XRoot >(), false /* mt use */ ) ); 851 } 852 853 } 854