1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_xmloff.hxx" 30 #include <rtl/ref.hxx> 31 #include <rtl/ustrbuf.hxx> 32 #include <com/sun/star/i18n/XCharacterClassification.hpp> 33 #include <com/sun/star/i18n/UnicodeType.hpp> 34 #include <comphelper/processfactory.hxx> 35 #include <xmloff/nmspmap.hxx> 36 #include "xmloff/xmlnmspe.hxx" 37 #include "IgnoreTContext.hxx" 38 #include "RenameElemTContext.hxx" 39 #include "ProcAttrTContext.hxx" 40 #include "ProcAddAttrTContext.hxx" 41 #include "MergeElemTContext.hxx" 42 #include "CreateElemTContext.hxx" 43 #include "MutableAttrList.hxx" 44 #include "TransformerActions.hxx" 45 #include "ElemTransformerAction.hxx" 46 // --> OD 2005-06-29 #i50322# 47 #include "PropertyActionsOOo.hxx" 48 // <-- 49 #ifndef _XMLOFF_TRANSFORMERTOKENMAP_HXX 50 #include "TransformerTokenMap.hxx" 51 #endif 52 #include <xmloff/xmluconv.hxx> 53 54 #ifndef _XMLOFF_TRANSFORMERBASE_HXX 55 #include "TransformerBase.hxx" 56 #endif 57 #include "TContextVector.hxx" 58 59 using ::rtl::OUString; 60 using ::rtl::OUStringBuffer; 61 using namespace ::osl; 62 using namespace ::xmloff::token; 63 using namespace ::com::sun::star::uno; 64 using namespace ::com::sun::star::beans; 65 using namespace ::com::sun::star::lang; 66 using namespace ::com::sun::star::i18n; 67 using namespace ::com::sun::star::xml::sax; 68 69 // ----------------------------------------------------------------------------- 70 71 namespace 72 { 73 bool lcl_ConvertAttr( OUString & rOutAttribute, sal_Int32 nParam ) 74 { 75 bool bResult = false; 76 enum XMLTokenEnum eTokenToRename = 77 static_cast< enum XMLTokenEnum >( nParam & 0xffff ); 78 if( eTokenToRename != XML_TOKEN_INVALID && 79 IsXMLToken( rOutAttribute, eTokenToRename )) 80 { 81 enum XMLTokenEnum eReplacementToken = 82 static_cast< enum XMLTokenEnum >( nParam >> 16 ); 83 rOutAttribute = GetXMLToken( eReplacementToken ); 84 bResult = true; 85 } 86 return bResult; 87 } 88 } // anonymous namespace 89 90 // ----------------------------------------------------------------------------- 91 92 XMLTransformerContext *XMLTransformerBase::CreateContext( sal_uInt16 nPrefix, 93 const OUString& rLocalName, const OUString& rQName ) 94 { 95 XMLTransformerActions::key_type aKey( nPrefix, rLocalName ); 96 XMLTransformerActions::const_iterator aIter = 97 GetElemActions().find( aKey ); 98 99 if( !(aIter == GetElemActions().end()) ) 100 { 101 sal_uInt32 nActionType = (*aIter).second.m_nActionType; 102 if( (nActionType & XML_ETACTION_USER_DEFINED) != 0 ) 103 { 104 XMLTransformerContext *pContext = 105 CreateUserDefinedContext( (*aIter).second, 106 rQName ); 107 OSL_ENSURE( pContext && !pContext->IsPersistent(), 108 "unknown or not persistent action" ); 109 return pContext; 110 } 111 112 switch( nActionType ) 113 { 114 case XML_ETACTION_COPY_CONTENT: 115 return new XMLIgnoreTransformerContext( *this, rQName, sal_False, 116 sal_False ); 117 case XML_ETACTION_COPY: 118 return new XMLTransformerContext( *this, rQName ); 119 case XML_ETACTION_RENAME_ELEM: 120 return new XMLRenameElemTransformerContext( *this, rQName, 121 (*aIter).second.GetQNamePrefixFromParam1(), 122 (*aIter).second.GetQNameTokenFromParam1() ); 123 case XML_ETACTION_RENAME_ELEM_ADD_ATTR: 124 return new XMLRenameElemTransformerContext( *this, rQName, 125 (*aIter).second.GetQNamePrefixFromParam1(), 126 (*aIter).second.GetQNameTokenFromParam1(), 127 (*aIter).second.GetQNamePrefixFromParam2(), 128 (*aIter).second.GetQNameTokenFromParam2(), 129 static_cast< XMLTokenEnum >( (*aIter).second.m_nParam3 ) ); 130 case XML_ETACTION_RENAME_ELEM_PROC_ATTRS: 131 return new XMLProcAttrTransformerContext( *this, rQName, 132 (*aIter).second.GetQNamePrefixFromParam1(), 133 (*aIter).second.GetQNameTokenFromParam1(), 134 static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) ); 135 case XML_ETACTION_RENAME_ELEM_ADD_PROC_ATTR: 136 return new XMLProcAddAttrTransformerContext( *this, rQName, 137 (*aIter).second.GetQNamePrefixFromParam1(), 138 (*aIter).second.GetQNameTokenFromParam1(), 139 static_cast< sal_uInt16 >( 140 (*aIter).second.m_nParam3 >> 16 ), 141 (*aIter).second.GetQNamePrefixFromParam2(), 142 (*aIter).second.GetQNameTokenFromParam2(), 143 static_cast< XMLTokenEnum >( 144 (*aIter).second.m_nParam3 & 0xffff ) ); 145 case XML_ETACTION_RENAME_ELEM_COND: 146 { 147 const XMLTransformerContext *pCurrent = GetCurrentContext(); 148 if( pCurrent->HasQName( 149 (*aIter).second.GetQNamePrefixFromParam2(), 150 (*aIter).second.GetQNameTokenFromParam2() ) ) 151 return new XMLRenameElemTransformerContext( *this, rQName, 152 (*aIter).second.GetQNamePrefixFromParam1(), 153 (*aIter).second.GetQNameTokenFromParam1() ); 154 } 155 break; 156 case XML_ETACTION_RENAME_ELEM_PROC_ATTRS_COND: 157 { 158 const XMLTransformerContext *pCurrent = GetCurrentContext(); 159 if( pCurrent->HasQName( 160 (*aIter).second.GetQNamePrefixFromParam3(), 161 (*aIter).second.GetQNameTokenFromParam3() ) ) 162 return new XMLProcAttrTransformerContext( *this, rQName, 163 (*aIter).second.GetQNamePrefixFromParam1(), 164 (*aIter).second.GetQNameTokenFromParam1(), 165 static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) ); 166 else 167 return new XMLProcAttrTransformerContext( *this, rQName, 168 static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) ); 169 } 170 case XML_ETACTION_PROC_ATTRS: 171 return new XMLProcAttrTransformerContext( *this, rQName, 172 static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) ); 173 case XML_ETACTION_PROC_ATTRS_COND: 174 { 175 const XMLTransformerContext *pCurrent = GetCurrentContext(); 176 if( pCurrent->HasQName( 177 (*aIter).second.GetQNamePrefixFromParam1(), 178 (*aIter).second.GetQNameTokenFromParam1() ) ) 179 return new XMLProcAttrTransformerContext( *this, rQName, 180 static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) ); 181 } 182 break; 183 case XML_ETACTION_MOVE_ATTRS_TO_ELEMS: 184 return new XMLCreateElemTransformerContext( *this, rQName, 185 static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) ); 186 case XML_ETACTION_MOVE_ELEMS_TO_ATTRS: 187 return new XMLMergeElemTransformerContext( *this, rQName, 188 static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) ); 189 default: 190 OSL_ENSURE( !this, "unknown action" ); 191 break; 192 } 193 } 194 195 // default is copying 196 return new XMLTransformerContext( *this, rQName ); 197 } 198 199 XMLTransformerActions *XMLTransformerBase::GetUserDefinedActions( sal_uInt16 ) 200 { 201 return 0; 202 } 203 204 XMLTransformerBase::XMLTransformerBase( XMLTransformerActionInit *pInit, 205 ::xmloff::token::XMLTokenEnum *pTKMapInit ) 206 throw () : 207 m_pNamespaceMap( new SvXMLNamespaceMap ), 208 m_pReplaceNamespaceMap( new SvXMLNamespaceMap ), 209 m_pContexts( new XMLTransformerContextVector ), 210 m_pElemActions( new XMLTransformerActions( pInit ) ), 211 m_pTokenMap( new XMLTransformerTokenMap( pTKMapInit ) ) 212 { 213 GetNamespaceMap().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK ); 214 GetNamespaceMap().Add( GetXMLToken(XML_NP_DC), GetXMLToken(XML_N_DC), XML_NAMESPACE_DC ); 215 GetNamespaceMap().Add( GetXMLToken(XML_NP_MATH), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH ); 216 GetNamespaceMap().Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO ); 217 GetNamespaceMap().Add( GetXMLToken(XML_NP_DOM), GetXMLToken(XML_N_DOM), XML_NAMESPACE_DOM ); 218 GetNamespaceMap().Add( GetXMLToken(XML_NP_OOOW), GetXMLToken(XML_N_OOOW), XML_NAMESPACE_OOOW ); 219 GetNamespaceMap().Add( GetXMLToken(XML_NP_OOOC), GetXMLToken(XML_N_OOOC), XML_NAMESPACE_OOOC ); 220 } 221 222 XMLTransformerBase::~XMLTransformerBase() throw () 223 { 224 ResetTokens(); 225 226 delete m_pNamespaceMap; 227 delete m_pReplaceNamespaceMap; 228 delete m_pContexts; 229 delete m_pElemActions; 230 delete m_pTokenMap; 231 } 232 233 void SAL_CALL XMLTransformerBase::startDocument( void ) 234 throw( SAXException, RuntimeException ) 235 { 236 m_xHandler->startDocument(); 237 } 238 239 void SAL_CALL XMLTransformerBase::endDocument( void ) 240 throw( SAXException, RuntimeException) 241 { 242 m_xHandler->endDocument(); 243 } 244 245 void SAL_CALL XMLTransformerBase::startElement( const OUString& rName, 246 const Reference< XAttributeList >& rAttrList ) 247 throw(SAXException, RuntimeException) 248 { 249 SvXMLNamespaceMap *pRewindMap = 0; 250 251 bool bRect = rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "presentation:show-shape" ) ); 252 (void)bRect; 253 254 // Process namespace attributes. This must happen before creating the 255 // context, because namespace decaration apply to the element name itself. 256 XMLMutableAttributeList *pMutableAttrList = 0; 257 Reference< XAttributeList > xAttrList( rAttrList ); 258 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; 259 for( sal_Int16 i=0; i < nAttrCount; i++ ) 260 { 261 const OUString& rAttrName = xAttrList->getNameByIndex( i ); 262 if( ( rAttrName.getLength() >= 5 ) && 263 ( rAttrName.compareTo( GetXMLToken(XML_XMLNS), 5 ) == 0 ) && 264 ( rAttrName.getLength() == 5 || ':' == rAttrName[5] ) ) 265 { 266 if( !pRewindMap ) 267 { 268 pRewindMap = m_pNamespaceMap; 269 m_pNamespaceMap = new SvXMLNamespaceMap( *m_pNamespaceMap ); 270 } 271 const OUString& rAttrValue = xAttrList->getValueByIndex( i ); 272 273 OUString aPrefix( ( rAttrName.getLength() == 5 ) 274 ? OUString() 275 : rAttrName.copy( 6 ) ); 276 // Add namespace, but only if it is known. 277 sal_uInt16 nKey = m_pNamespaceMap->AddIfKnown( aPrefix, rAttrValue ); 278 // If namespace is unknwon, try to match a name with similar 279 // TC Id an version 280 if( XML_NAMESPACE_UNKNOWN == nKey ) 281 { 282 OUString aTestName( rAttrValue ); 283 if( SvXMLNamespaceMap::NormalizeOasisURN( aTestName ) ) 284 nKey = m_pNamespaceMap->AddIfKnown( aPrefix, aTestName ); 285 } 286 // If that namespace is not known, too, add it as unknown 287 if( XML_NAMESPACE_UNKNOWN == nKey ) 288 nKey = m_pNamespaceMap->Add( aPrefix, rAttrValue ); 289 290 const OUString& rRepName = m_pReplaceNamespaceMap->GetNameByKey( nKey ); 291 if( rRepName.getLength() ) 292 { 293 if( !pMutableAttrList ) 294 { 295 pMutableAttrList = new XMLMutableAttributeList( xAttrList ); 296 xAttrList = pMutableAttrList; 297 } 298 299 pMutableAttrList->SetValueByIndex( i, rRepName ); 300 } 301 } 302 } 303 304 // Get element's namespace and local name. 305 OUString aLocalName; 306 sal_uInt16 nPrefix = 307 m_pNamespaceMap->GetKeyByAttrName( rName, &aLocalName ); 308 309 // If there are contexts already, call a CreateChildContext at the topmost 310 // context. Otherwise, create a default context. 311 ::rtl::Reference < XMLTransformerContext > xContext; 312 if( !m_pContexts->empty() ) 313 { 314 xContext = m_pContexts->back()->CreateChildContext( nPrefix, 315 aLocalName, 316 rName, 317 xAttrList ); 318 } 319 else 320 { 321 xContext = CreateContext( nPrefix, aLocalName, rName ); 322 } 323 324 OSL_ENSURE( xContext.is(), "XMLTransformerBase::startElement: missing context" ); 325 if( !xContext.is() ) 326 xContext = new XMLTransformerContext( *this, rName ); 327 328 // Remeber old namespace map. 329 if( pRewindMap ) 330 xContext->SetRewindMap( pRewindMap ); 331 332 // Push context on stack. 333 m_pContexts->push_back( xContext ); 334 335 // Call a startElement at the new context. 336 xContext->StartElement( xAttrList ); 337 } 338 339 void SAL_CALL XMLTransformerBase::endElement( const OUString& 340 #ifdef DBG_UTIL 341 rName 342 #endif 343 ) 344 throw(SAXException, RuntimeException) 345 { 346 if( !m_pContexts->empty() ) 347 { 348 // Get topmost context 349 ::rtl::Reference< XMLTransformerContext > xContext = m_pContexts->back(); 350 351 #ifdef DBG_UTIL 352 OSL_ENSURE( xContext->GetQName() == rName, 353 "XMLTransformerBase::endElement: popped context has wrong lname" ); 354 #endif 355 356 // Call a EndElement at the current context. 357 xContext->EndElement(); 358 359 // and remove it from the stack. 360 m_pContexts->pop_back(); 361 362 // Get a namespace map to rewind. 363 SvXMLNamespaceMap *pRewindMap = xContext->GetRewindMap(); 364 365 // Delete the current context. 366 xContext = 0; 367 368 // Rewind a namespace map. 369 if( pRewindMap ) 370 { 371 delete m_pNamespaceMap; 372 m_pNamespaceMap = pRewindMap; 373 } 374 } 375 } 376 377 void SAL_CALL XMLTransformerBase::characters( const OUString& rChars ) 378 throw(SAXException, RuntimeException) 379 { 380 if( !m_pContexts->empty() ) 381 { 382 m_pContexts->back()->Characters( rChars ); 383 } 384 } 385 386 void SAL_CALL XMLTransformerBase::ignorableWhitespace( const OUString& rWhitespaces ) 387 throw(SAXException, RuntimeException) 388 { 389 m_xHandler->ignorableWhitespace( rWhitespaces ); 390 } 391 392 void SAL_CALL XMLTransformerBase::processingInstruction( const OUString& rTarget, 393 const OUString& rData ) 394 throw(SAXException, RuntimeException) 395 { 396 m_xHandler->processingInstruction( rTarget, rData ); 397 } 398 399 void SAL_CALL XMLTransformerBase::setDocumentLocator( const Reference< XLocator >& rLocator ) 400 throw(SAXException, RuntimeException) 401 { 402 m_xLocator = rLocator; 403 } 404 405 // XExtendedDocumentHandler 406 void SAL_CALL XMLTransformerBase::startCDATA( void ) throw(SAXException, RuntimeException) 407 { 408 if( m_xExtHandler.is() ) 409 m_xExtHandler->startCDATA(); 410 } 411 412 void SAL_CALL XMLTransformerBase::endCDATA( void ) throw(RuntimeException) 413 { 414 if( m_xExtHandler.is() ) 415 m_xExtHandler->endCDATA(); 416 } 417 418 void SAL_CALL XMLTransformerBase::comment( const OUString& rComment ) 419 throw(SAXException, RuntimeException) 420 { 421 if( m_xExtHandler.is() ) 422 m_xExtHandler->comment( rComment ); 423 } 424 425 void SAL_CALL XMLTransformerBase::allowLineBreak( void ) 426 throw(SAXException, RuntimeException) 427 { 428 if( m_xExtHandler.is() ) 429 m_xExtHandler->allowLineBreak(); 430 } 431 432 void SAL_CALL XMLTransformerBase::unknown( const OUString& rString ) 433 throw(SAXException, RuntimeException) 434 { 435 if( m_xExtHandler.is() ) 436 m_xExtHandler->unknown( rString ); 437 } 438 439 // XInitialize 440 void SAL_CALL XMLTransformerBase::initialize( const Sequence< Any >& aArguments ) 441 throw(Exception, RuntimeException) 442 { 443 const sal_Int32 nAnyCount = aArguments.getLength(); 444 const Any* pAny = aArguments.getConstArray(); 445 446 for( sal_Int32 nIndex = 0; nIndex < nAnyCount; nIndex++, pAny++ ) 447 { 448 // #b6236750# use isAssignableFrom instead of comparing the types to 449 // allow XExtendedDocumentHandler instead of XDocumentHandler (used in 450 // writeOasis2OOoLibraryElement in sfx2). 451 // The Any shift operator can't be used to query the type because it 452 // uses queryInterface, and the model also has a XPropertySet interface. 453 454 // document handler 455 if( ::getCppuType( (const Reference< XDocumentHandler >*) 0 ).isAssignableFrom( pAny->getValueType() ) ) 456 m_xHandler.set( *pAny, UNO_QUERY ); 457 458 // property set to transport data across 459 if( ::getCppuType( (const Reference< XPropertySet >*) 0 ).isAssignableFrom( pAny->getValueType() ) ) 460 m_xPropSet.set( *pAny, UNO_QUERY ); 461 462 // xmodel 463 if( ::getCppuType( (const Reference< ::com::sun::star::frame::XModel >*) 0 ).isAssignableFrom( pAny->getValueType() ) ) 464 mxModel.set( *pAny, UNO_QUERY ); 465 } 466 467 if( m_xPropSet.is() ) 468 { 469 Any aAny; 470 OUString sRelPath, sName; 471 Reference< XPropertySetInfo > xPropSetInfo = 472 m_xPropSet->getPropertySetInfo(); 473 OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("StreamRelPath" ) ); 474 if( xPropSetInfo->hasPropertyByName(sPropName) ) 475 { 476 aAny = m_xPropSet->getPropertyValue(sPropName); 477 aAny >>= sRelPath; 478 } 479 sPropName = OUString( RTL_CONSTASCII_USTRINGPARAM("StreamName" ) ); 480 if( xPropSetInfo->hasPropertyByName(sPropName) ) 481 { 482 aAny = m_xPropSet->getPropertyValue(sPropName); 483 aAny >>= sName; 484 } 485 if( sName.getLength() ) 486 { 487 m_aExtPathPrefix = OUString( RTL_CONSTASCII_USTRINGPARAM("../" ) ); 488 489 // If there is a rel path within a package, then append 490 // additional '../'. If the rel path contains an ':', then it is 491 // an absolute URI (or invalid URI, because zip files don't 492 // permit ':'), and it will be ignored. 493 if( sRelPath.getLength() ) 494 { 495 sal_Int32 nColPos = sRelPath.indexOf( ':' ); 496 OSL_ENSURE( -1 == nColPos, 497 "StreamRelPath contains ':', absolute URI?" ); 498 499 if( -1 == nColPos ) 500 { 501 OUString sTmp = m_aExtPathPrefix; 502 sal_Int32 nPos = 0; 503 do 504 { 505 m_aExtPathPrefix += sTmp; 506 nPos = sRelPath.indexOf( '/', nPos + 1 ); 507 } 508 while( -1 != nPos ); 509 } 510 } 511 512 } 513 } 514 } 515 516 static MapUnit lcl_getUnit( const OUString& rValue ) 517 { 518 MapUnit nDestUnit; 519 if( rValue.endsWithIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "cm" ) ) ) 520 nDestUnit = MAP_CM; 521 else if ( rValue.endsWithIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "mm" ) ) ) 522 nDestUnit = MAP_MM; 523 else 524 nDestUnit = MAP_INCH; 525 return nDestUnit; 526 } 527 528 XMLMutableAttributeList *XMLTransformerBase::ProcessAttrList( 529 Reference< XAttributeList >& rAttrList, sal_uInt16 nActionMap, 530 sal_Bool bClone ) 531 { 532 XMLMutableAttributeList *pMutableAttrList = 0; 533 XMLTransformerActions *pActions = GetUserDefinedActions( nActionMap ); 534 OSL_ENSURE( pActions, "go no actions" ); 535 if( pActions ) 536 { 537 sal_Int16 nAttrCount = rAttrList.is() ? rAttrList->getLength() : 0; 538 for( sal_Int16 i=0; i < nAttrCount; ++i ) 539 { 540 const OUString& rAttrName = rAttrList->getNameByIndex( i ); 541 const OUString& rAttrValue = rAttrList->getValueByIndex( i ); 542 OUString aLocalName; 543 sal_uInt16 nPrefix = GetNamespaceMap().GetKeyByAttrName( rAttrName, 544 &aLocalName ); 545 546 XMLTransformerActions::key_type aKey( nPrefix, aLocalName ); 547 XMLTransformerActions::const_iterator aIter = 548 pActions->find( aKey ); 549 if( !(aIter == pActions->end() ) ) 550 { 551 if( !pMutableAttrList ) 552 { 553 pMutableAttrList = new XMLMutableAttributeList( rAttrList, 554 bClone ); 555 rAttrList = pMutableAttrList; 556 } 557 558 sal_uInt32 nAction = (*aIter).second.m_nActionType; 559 sal_Bool bRename = sal_False; 560 switch( nAction ) 561 { 562 case XML_ATACTION_RENAME: 563 bRename = sal_True; 564 break; 565 case XML_ATACTION_COPY: 566 break; 567 case XML_ATACTION_REMOVE: 568 case XML_ATACTION_STYLE_DISPLAY_NAME: 569 pMutableAttrList->RemoveAttributeByIndex( i ); 570 --i; 571 --nAttrCount; 572 break; 573 case XML_ATACTION_RENAME_IN2INCH: 574 bRename = sal_True; 575 case XML_ATACTION_IN2INCH: 576 { 577 OUString aAttrValue( rAttrValue ); 578 if( ReplaceSingleInWithInch( aAttrValue ) ) 579 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 580 } 581 break; 582 case XML_ATACTION_INS2INCHS: 583 { 584 OUString aAttrValue( rAttrValue ); 585 if( ReplaceInWithInch( aAttrValue ) ) 586 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 587 } 588 break; 589 case XML_ATACTION_RENAME_INCH2IN: 590 bRename = sal_True; 591 case XML_ATACTION_INCH2IN: 592 { 593 OUString aAttrValue( rAttrValue ); 594 if( ReplaceSingleInchWithIn( aAttrValue ) ) 595 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 596 } 597 break; 598 case XML_ATACTION_INCHS2INS: 599 { 600 OUString aAttrValue( rAttrValue ); 601 if( ReplaceInchWithIn( aAttrValue ) ) 602 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 603 } 604 break; 605 case XML_ATACTION_TWIPS2IN: 606 { 607 OUString aAttrValue( rAttrValue ); 608 609 XMLTransformerBase::ReplaceSingleInchWithIn( aAttrValue ); 610 if( isWriter() ) 611 { 612 MapUnit nDestUnit = lcl_getUnit( aAttrValue ); 613 614 // convert twips value to inch 615 sal_Int32 nMeasure; 616 if( SvXMLUnitConverter::convertMeasure(nMeasure, aAttrValue, MAP_100TH_MM ) ) 617 { 618 619 // --> OD 2004-10-29 #i13778#,#i36248# 620 // apply correct twip-to-1/100mm 621 nMeasure = (sal_Int32)( nMeasure >= 0 622 ? ((nMeasure*127+36)/72) 623 : ((nMeasure*127-36)/72) ); 624 // <-- 625 626 rtl::OUStringBuffer aBuffer; 627 SvXMLUnitConverter::convertMeasure( aBuffer, nMeasure, MAP_100TH_MM, nDestUnit ); 628 aAttrValue = aBuffer.makeStringAndClear(); 629 } 630 } 631 632 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 633 } 634 break; 635 case XML_ATACTION_RENAME_DECODE_STYLE_NAME_REF: 636 bRename = sal_True; 637 case XML_ATACTION_DECODE_STYLE_NAME: 638 case XML_ATACTION_DECODE_STYLE_NAME_REF: 639 { 640 OUString aAttrValue( rAttrValue ); 641 if( DecodeStyleName(aAttrValue) ) 642 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 643 } 644 break; 645 case XML_ATACTION_ENCODE_STYLE_NAME: 646 { 647 OUString aAttrValue( rAttrValue ); 648 if( EncodeStyleName(aAttrValue) ) 649 { 650 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 651 OUString aNewAttrQName( 652 GetNamespaceMap().GetQNameByKey( 653 nPrefix, 654 ::xmloff::token::GetXMLToken( 655 XML_DISPLAY_NAME ) ) ); 656 pMutableAttrList->AddAttribute( aNewAttrQName, 657 rAttrValue ); 658 } 659 } 660 break; 661 case XML_ATACTION_RENAME_ENCODE_STYLE_NAME_REF: 662 bRename = sal_True; 663 case XML_ATACTION_ENCODE_STYLE_NAME_REF: 664 { 665 OUString aAttrValue( rAttrValue ); 666 if( EncodeStyleName(aAttrValue) ) 667 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 668 } 669 break; 670 case XML_ATACTION_RENAME_NEG_PERCENT: 671 bRename = sal_True; 672 case XML_ATACTION_NEG_PERCENT: 673 { 674 OUString aAttrValue( rAttrValue ); 675 if( NegPercent( aAttrValue ) ) 676 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 677 } 678 break; 679 case XML_ATACTION_RENAME_ADD_NAMESPACE_PREFIX: 680 bRename = sal_True; 681 case XML_ATACTION_ADD_NAMESPACE_PREFIX: 682 { 683 OUString aAttrValue( rAttrValue ); 684 sal_uInt16 nValPrefix = 685 static_cast<sal_uInt16>( 686 bRename ? (*aIter).second.m_nParam2 687 : (*aIter).second.m_nParam1); 688 if( AddNamespacePrefix( aAttrValue, nValPrefix ) ) 689 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 690 } 691 break; 692 case XML_ATACTION_ADD_APP_NAMESPACE_PREFIX: 693 { 694 OUString aAttrValue( rAttrValue ); 695 sal_uInt16 nValPrefix = 696 static_cast<sal_uInt16>((*aIter).second.m_nParam1); 697 if( IsXMLToken( GetClass(), XML_SPREADSHEET ) ) 698 nValPrefix = XML_NAMESPACE_OOOC; 699 else if( IsXMLToken( GetClass(), XML_TEXT ) ) 700 nValPrefix = XML_NAMESPACE_OOOW; 701 if( AddNamespacePrefix( aAttrValue, nValPrefix ) ) 702 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 703 } 704 break; 705 case XML_ATACTION_RENAME_REMOVE_NAMESPACE_PREFIX: 706 bRename = sal_True; 707 case XML_ATACTION_REMOVE_NAMESPACE_PREFIX: 708 { 709 OUString aAttrValue( rAttrValue ); 710 sal_uInt16 nValPrefix = 711 static_cast<sal_uInt16>( 712 bRename ? (*aIter).second.m_nParam2 713 : (*aIter).second.m_nParam1); 714 if( RemoveNamespacePrefix( aAttrValue, nValPrefix ) ) 715 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 716 } 717 break; 718 case XML_ATACTION_REMOVE_ANY_NAMESPACE_PREFIX: 719 { 720 OUString aAttrValue( rAttrValue ); 721 if( RemoveNamespacePrefix( aAttrValue ) ) 722 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 723 } 724 break; 725 case XML_ATACTION_URI_OOO: 726 { 727 OUString aAttrValue( rAttrValue ); 728 if( ConvertURIToOASIS( aAttrValue, 729 static_cast< sal_Bool >((*aIter).second.m_nParam1))) 730 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 731 } 732 break; 733 case XML_ATACTION_URI_OASIS: 734 { 735 OUString aAttrValue( rAttrValue ); 736 if( ConvertURIToOOo( aAttrValue, 737 static_cast< sal_Bool >((*aIter).second.m_nParam1))) 738 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 739 } 740 break; 741 case XML_ATACTION_RENAME_ATTRIBUTE: 742 { 743 OUString aAttrValue( rAttrValue ); 744 RenameAttributeValue( 745 aAttrValue, 746 (*aIter).second.m_nParam1, 747 (*aIter).second.m_nParam2, 748 (*aIter).second.m_nParam3 ); 749 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 750 } 751 break; 752 case XML_ATACTION_RNG2ISO_DATETIME: 753 { 754 OUString aAttrValue( rAttrValue ); 755 if( ConvertRNGDateTimeToISO( aAttrValue )) 756 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 757 } 758 break; 759 case XML_ATACTION_RENAME_RNG2ISO_DATETIME: 760 { 761 OUString aAttrValue( rAttrValue ); 762 if( ConvertRNGDateTimeToISO( aAttrValue )) 763 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 764 bRename = sal_True; 765 } 766 break; 767 case XML_ATACTION_IN2TWIPS: 768 { 769 OUString aAttrValue( rAttrValue ); 770 XMLTransformerBase::ReplaceSingleInWithInch( aAttrValue ); 771 772 if( isWriter() ) 773 { 774 MapUnit nDestUnit = lcl_getUnit( aAttrValue ); 775 776 // convert inch value to twips and export as faked inch 777 sal_Int32 nMeasure; 778 if( SvXMLUnitConverter::convertMeasure(nMeasure, aAttrValue, MAP_100TH_MM ) ) 779 { 780 781 // --> OD 2004-10-29 #i13778#,#i36248# 782 // apply correct 1/100mm-to-twip conversion 783 nMeasure = (sal_Int32)( nMeasure >= 0 784 ? ((nMeasure*72+63)/127) 785 : ((nMeasure*72-63)/127) ); 786 // <-- 787 788 OUStringBuffer aBuffer; 789 SvXMLUnitConverter::convertMeasure( aBuffer, nMeasure, MAP_100TH_MM, nDestUnit ); 790 aAttrValue = aBuffer.makeStringAndClear(); 791 } 792 } 793 794 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 795 } 796 break; 797 case XML_ATACTION_SVG_WIDTH_HEIGHT_OOO: 798 { 799 OUString aAttrValue( rAttrValue ); 800 ReplaceSingleInchWithIn( aAttrValue ); 801 802 MapUnit nDestUnit = lcl_getUnit( aAttrValue ); 803 804 sal_Int32 nMeasure; 805 if( SvXMLUnitConverter::convertMeasure(nMeasure, aAttrValue, MAP_100TH_MM ) ) 806 { 807 808 if( nMeasure > 0 ) 809 nMeasure -= 1; 810 else if( nMeasure < 0 ) 811 nMeasure += 1; 812 813 814 OUStringBuffer aBuffer; 815 SvXMLUnitConverter::convertMeasure( aBuffer, nMeasure, MAP_100TH_MM, nDestUnit ); 816 aAttrValue = aBuffer.makeStringAndClear(); 817 } 818 819 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 820 } 821 break; 822 case XML_ATACTION_SVG_WIDTH_HEIGHT_OASIS: 823 { 824 OUString aAttrValue( rAttrValue ); 825 ReplaceSingleInWithInch( aAttrValue ); 826 827 MapUnit nDestUnit = lcl_getUnit( aAttrValue ); 828 829 sal_Int32 nMeasure; 830 if( SvXMLUnitConverter::convertMeasure(nMeasure, aAttrValue, MAP_100TH_MM ) ) 831 { 832 833 if( nMeasure > 0 ) 834 nMeasure += 1; 835 else if( nMeasure < 0 ) 836 nMeasure -= 1; 837 838 839 OUStringBuffer aBuffer; 840 SvXMLUnitConverter::convertMeasure( aBuffer, nMeasure, MAP_100TH_MM, nDestUnit ); 841 aAttrValue = aBuffer.makeStringAndClear(); 842 } 843 844 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 845 } 846 break; 847 case XML_ATACTION_DECODE_ID: 848 { 849 OUString aAttrValue; 850 851 const sal_Int32 nLen = rAttrValue.getLength(); 852 OUStringBuffer aBuffer; 853 854 sal_Int32 pos; 855 for( pos = 0; pos < nLen; pos++ ) 856 { 857 sal_Unicode c = rAttrValue[pos]; 858 if( (c >= '0') && (c <= '9') ) 859 aBuffer.append( c ); 860 else 861 aBuffer.append( (sal_Int32)c ); 862 } 863 864 pMutableAttrList->SetValueByIndex( i, aBuffer.makeStringAndClear() ); 865 } 866 break; 867 // --> OD 2005-06-10 #i50322# - special handling for the 868 // transparency of writer background graphics. 869 case XML_ATACTION_WRITER_BACK_GRAPHIC_TRANSPARENCY: 870 { 871 // determine, if it's the transparency of a document style 872 XMLTransformerContext* pFirstContext = (*m_pContexts)[0].get(); 873 OUString aFirstContextLocalName; 874 /* sal_uInt16 nFirstContextPrefix = */ 875 GetNamespaceMap().GetKeyByAttrName( pFirstContext->GetQName(), 876 &aFirstContextLocalName ); 877 bool bIsDocumentStyle( 878 ::xmloff::token::IsXMLToken( aFirstContextLocalName, 879 XML_DOCUMENT_STYLES ) ); 880 // no conversion of transparency value for document 881 // styles, because former OpenOffice.org version writes 882 // writes always a transparency value of 100% and doesn't 883 // read the value. Thus, it's intepreted as 0% 884 if ( !bIsDocumentStyle ) 885 { 886 OUString aAttrValue( rAttrValue ); 887 NegPercent(aAttrValue); 888 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 889 } 890 bRename = sal_True; 891 } 892 break; 893 // <-- 894 case XML_ATACTION_SHAPEID: 895 { 896 OUString sNewValue( RTL_CONSTASCII_USTRINGPARAM( "shape" ) ); 897 sNewValue += rAttrValue; 898 pMutableAttrList->SetValueByIndex( i, sNewValue ); 899 break; 900 } 901 902 default: 903 OSL_ENSURE( !this, "unknown action" ); 904 break; 905 } 906 907 if( bRename ) 908 { 909 OUString aNewAttrQName( 910 GetNamespaceMap().GetQNameByKey( 911 (*aIter).second.GetQNamePrefixFromParam1(), 912 ::xmloff::token::GetXMLToken( 913 (*aIter).second.GetQNameTokenFromParam1()) ) ); 914 pMutableAttrList->RenameAttributeByIndex( i, 915 aNewAttrQName ); 916 } 917 } 918 } 919 } 920 921 return pMutableAttrList; 922 } 923 924 sal_Bool XMLTransformerBase::ReplaceSingleInchWithIn( OUString& rValue ) 925 { 926 sal_Bool bRet = sal_False; 927 sal_Int32 nPos = rValue.getLength(); 928 while( nPos && rValue[nPos-1] <= ' ' ) 929 --nPos; 930 if( nPos > 2 && 931 ('c'==rValue[nPos-2] || 'C'==rValue[nPos-2]) && 932 ('h'==rValue[nPos-1] || 'H'==rValue[nPos-1]) ) 933 { 934 rValue =rValue.copy( 0, nPos-2 ); 935 bRet = sal_True; 936 } 937 938 return bRet; 939 } 940 941 sal_Bool XMLTransformerBase::ReplaceInchWithIn( OUString& rValue ) 942 { 943 sal_Bool bRet = sal_False; 944 sal_Int32 nPos = 1; 945 while( nPos < rValue.getLength()-3 ) 946 { 947 sal_Unicode c = rValue[nPos]; 948 if( 'i'==c || 'I'==c ) 949 { 950 c = rValue[nPos-1]; 951 if( (c >= '0' && c <= '9') || '.' == c ) 952 { 953 c = rValue[nPos+1]; 954 if( 'n'==c || 'N'==c ) 955 { 956 c = rValue[nPos+2]; 957 if( 'c'==c || 'C'==c ) 958 { 959 c = rValue[nPos+3]; 960 if( 'h'==c || 'H'==c ) 961 { 962 rValue = rValue.replaceAt( nPos, 963 4, GetXMLToken(XML_UNIT_INCH) ); 964 nPos += 2; 965 bRet = sal_True; 966 continue; 967 } 968 } 969 } 970 } 971 } 972 ++nPos; 973 } 974 975 return bRet; 976 } 977 978 sal_Bool XMLTransformerBase::ReplaceSingleInWithInch( OUString& rValue ) 979 { 980 sal_Bool bRet = sal_False; 981 982 sal_Int32 nPos = rValue.getLength(); 983 while( nPos && rValue[nPos-1] <= ' ' ) 984 --nPos; 985 if( nPos > 2 && 986 ('i'==rValue[nPos-2] || 987 'I'==rValue[nPos-2]) && 988 ('n'==rValue[nPos-1] || 989 'N'==rValue[nPos-1]) ) 990 { 991 nPos -= 2; 992 rValue = rValue.replaceAt( nPos, rValue.getLength() - nPos, 993 GetXMLToken(XML_INCH) ); 994 bRet = sal_True; 995 } 996 997 return bRet; 998 } 999 1000 sal_Bool XMLTransformerBase::ReplaceInWithInch( OUString& rValue ) 1001 { 1002 sal_Bool bRet = sal_False; 1003 sal_Int32 nPos = 1; 1004 while( nPos < rValue.getLength()-1 ) 1005 { 1006 sal_Unicode c = rValue[nPos]; 1007 if( 'i'==c || 'I'==c ) 1008 { 1009 c = rValue[nPos-1]; 1010 if( (c >= '0' && c <= '9') || '.' == c ) 1011 { 1012 c = rValue[nPos+1]; 1013 if( 'n'==c || 'N'==c ) 1014 { 1015 rValue = rValue.replaceAt( nPos, 1016 2, GetXMLToken(XML_INCH) ); 1017 nPos += 4; 1018 bRet = sal_True; 1019 continue; 1020 } 1021 } 1022 } 1023 ++nPos; 1024 } 1025 1026 return bRet; 1027 } 1028 1029 sal_Bool XMLTransformerBase::EncodeStyleName( OUString& rName ) const 1030 { 1031 static sal_Char aHexTab[] = "0123456789abcdef"; 1032 1033 sal_Bool bEncoded = sal_False; 1034 1035 sal_Int32 nLen = rName.getLength(); 1036 OUStringBuffer aBuffer( nLen ); 1037 1038 for( sal_Int32 i = 0; i < nLen; i++ ) 1039 { 1040 sal_Unicode c = rName[i]; 1041 sal_Bool bValidChar = sal_False; 1042 if( c < 0x00ffU ) 1043 { 1044 bValidChar = 1045 (c >= 0x0041 && c <= 0x005a) || 1046 (c >= 0x0061 && c <= 0x007a) || 1047 (c >= 0x00c0 && c <= 0x00d6) || 1048 (c >= 0x00d8 && c <= 0x00f6) || 1049 (c >= 0x00f8 && c <= 0x00ff) || 1050 ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) || 1051 c == 0x00b7 || c == '-' || c == '.') ); 1052 } 1053 else 1054 { 1055 if( (c >= 0xf900U && c <= 0xfffeU) || 1056 (c >= 0x20ddU && c <= 0x20e0U)) 1057 { 1058 bValidChar = sal_False; 1059 } 1060 else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 || 1061 c == 0x06e5 || c == 0x06e6 ) 1062 { 1063 bValidChar = sal_True; 1064 } 1065 else if( c == 0x0387 ) 1066 { 1067 bValidChar = i > 0; 1068 } 1069 else 1070 { 1071 if( !xCharClass.is() ) 1072 { 1073 Reference< XMultiServiceFactory > xFactory = 1074 comphelper::getProcessServiceFactory(); 1075 if( xFactory.is() ) 1076 { 1077 try 1078 { 1079 const_cast < XMLTransformerBase * >(this) 1080 ->xCharClass = 1081 Reference < XCharacterClassification >( 1082 xFactory->createInstance( 1083 OUString::createFromAscii( 1084 "com.sun.star.i18n.CharacterClassification_Unicode") ), 1085 UNO_QUERY ); 1086 1087 OSL_ENSURE( xCharClass.is(), 1088 "can't instantiate character clossification component" ); 1089 } 1090 catch( com::sun::star::uno::Exception& ) 1091 { 1092 } 1093 } 1094 } 1095 if( xCharClass.is() ) 1096 { 1097 sal_Int16 nType = xCharClass->getType( rName, i ); 1098 1099 switch( nType ) 1100 { 1101 case UnicodeType::UPPERCASE_LETTER: // Lu 1102 case UnicodeType::LOWERCASE_LETTER: // Ll 1103 case UnicodeType::TITLECASE_LETTER: // Lt 1104 case UnicodeType::OTHER_LETTER: // Lo 1105 case UnicodeType::LETTER_NUMBER: // Nl 1106 bValidChar = sal_True; 1107 break; 1108 case UnicodeType::NON_SPACING_MARK: // Ms 1109 case UnicodeType::ENCLOSING_MARK: // Me 1110 case UnicodeType::COMBINING_SPACING_MARK: //Mc 1111 case UnicodeType::MODIFIER_LETTER: // Lm 1112 case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd 1113 bValidChar = i > 0; 1114 break; 1115 } 1116 } 1117 } 1118 } 1119 if( bValidChar ) 1120 { 1121 aBuffer.append( c ); 1122 } 1123 else 1124 { 1125 aBuffer.append( static_cast< sal_Unicode >( '_' ) ); 1126 if( c > 0x0fff ) 1127 aBuffer.append( static_cast< sal_Unicode >( 1128 aHexTab[ (c >> 12) & 0x0f ] ) ); 1129 if( c > 0x00ff ) 1130 aBuffer.append( static_cast< sal_Unicode >( 1131 aHexTab[ (c >> 8) & 0x0f ] ) ); 1132 if( c > 0x000f ) 1133 aBuffer.append( static_cast< sal_Unicode >( 1134 aHexTab[ (c >> 4) & 0x0f ] ) ); 1135 aBuffer.append( static_cast< sal_Unicode >( 1136 aHexTab[ c & 0x0f ] ) ); 1137 aBuffer.append( static_cast< sal_Unicode >( '_' ) ); 1138 bEncoded = sal_True; 1139 } 1140 } 1141 1142 if( aBuffer.getLength() > (1<<15)-1 ) 1143 bEncoded = sal_False; 1144 1145 if( bEncoded ) 1146 rName = aBuffer.makeStringAndClear(); 1147 return bEncoded; 1148 } 1149 1150 sal_Bool XMLTransformerBase::DecodeStyleName( OUString& rName ) 1151 { 1152 sal_Bool bEncoded = sal_False; 1153 1154 sal_Int32 nLen = rName.getLength(); 1155 OUStringBuffer aBuffer( nLen ); 1156 1157 sal_Bool bWithinHex = sal_False; 1158 sal_Unicode cEnc = 0; 1159 for( sal_Int32 i = 0; i < nLen; i++ ) 1160 { 1161 sal_Unicode c = rName[i]; 1162 if( '_' == c ) 1163 { 1164 if( bWithinHex ) 1165 { 1166 aBuffer.append( cEnc ); 1167 cEnc = 0; 1168 } 1169 else 1170 { 1171 bEncoded = sal_True; 1172 } 1173 bWithinHex = !bWithinHex; 1174 } 1175 else if( bWithinHex ) 1176 { 1177 sal_Unicode cDigit; 1178 if( c >= '0' && c <= '9' ) 1179 { 1180 cDigit = c - '0'; 1181 } 1182 else if( c >= 'a' && c <= 'f' ) 1183 { 1184 cDigit = c - 'a' + 10; 1185 } 1186 else if( c >= 'A' && c <= 'F' ) 1187 { 1188 cDigit = c - 'A' + 10; 1189 } 1190 else 1191 { 1192 // error 1193 bEncoded = sal_False; 1194 break; 1195 } 1196 cEnc = (cEnc << 4) + cDigit; 1197 } 1198 else 1199 { 1200 aBuffer.append( c ); 1201 } 1202 } 1203 1204 if( bEncoded ) 1205 rName = aBuffer.makeStringAndClear(); 1206 return bEncoded; 1207 } 1208 1209 sal_Bool XMLTransformerBase::NegPercent( OUString& rValue ) 1210 { 1211 sal_Bool bRet = sal_False; 1212 sal_Bool bNeg = sal_False; 1213 double nVal = 0; 1214 1215 sal_Int32 nPos = 0; 1216 sal_Int32 nLen = rValue.getLength(); 1217 1218 // skip white space 1219 while( nPos < nLen && sal_Unicode(' ') == rValue[nPos] ) 1220 nPos++; 1221 1222 if( nPos < nLen && sal_Unicode('-') == rValue[nPos] ) 1223 { 1224 bNeg = sal_True; 1225 nPos++; 1226 } 1227 1228 // get number 1229 while( nPos < nLen && 1230 sal_Unicode('0') <= rValue[nPos] && 1231 sal_Unicode('9') >= rValue[nPos] ) 1232 { 1233 // TODO: check overflow! 1234 nVal *= 10; 1235 nVal += (rValue[nPos] - sal_Unicode('0')); 1236 nPos++; 1237 } 1238 double nDiv = 1.; 1239 if( nPos < nLen && sal_Unicode('.') == rValue[nPos] ) 1240 { 1241 nPos++; 1242 1243 while( nPos < nLen && 1244 sal_Unicode('0') <= rValue[nPos] && 1245 sal_Unicode('9') >= rValue[nPos] ) 1246 { 1247 // TODO: check overflow! 1248 nDiv *= 10; 1249 nVal += ( static_cast<double>(rValue[nPos] - sal_Unicode('0')) / nDiv ); 1250 nPos++; 1251 } 1252 } 1253 1254 // skip white space 1255 while( nPos < nLen && sal_Unicode(' ') == rValue[nPos] ) 1256 nPos++; 1257 1258 if( nPos < nLen && sal_Unicode('%') == rValue[nPos] ) 1259 { 1260 if( bNeg ) 1261 nVal = -nVal; 1262 nVal += .5; 1263 1264 sal_Int32 nIntVal = 100 - static_cast<sal_Int32>( nVal ); 1265 1266 OUStringBuffer aNewValBuffer; 1267 aNewValBuffer.append( nIntVal ); 1268 aNewValBuffer.append( sal_Unicode('%' ) ); 1269 1270 rValue = aNewValBuffer.makeStringAndClear(); 1271 bRet = sal_True; 1272 } 1273 1274 return bRet; 1275 } 1276 1277 sal_Bool XMLTransformerBase::AddNamespacePrefix( ::rtl::OUString& rName, 1278 sal_uInt16 nPrefix ) const 1279 { 1280 rName = GetNamespaceMap().GetQNameByKey( nPrefix, rName, sal_False ); 1281 return sal_True; 1282 } 1283 1284 sal_Bool XMLTransformerBase::RemoveNamespacePrefix( ::rtl::OUString& rName, 1285 sal_uInt16 nPrefixOnly ) const 1286 { 1287 OUString aLocalName; 1288 sal_uInt16 nPrefix = 1289 GetNamespaceMap()._GetKeyByAttrName( rName, &aLocalName, sal_False ); 1290 sal_Bool bRet = XML_NAMESPACE_UNKNOWN != nPrefix && 1291 (USHRT_MAX == nPrefixOnly || nPrefix == nPrefixOnly); 1292 if( bRet ) 1293 rName = aLocalName; 1294 1295 return bRet; 1296 } 1297 1298 sal_Bool XMLTransformerBase::ConvertURIToOASIS( ::rtl::OUString& rURI, 1299 sal_Bool bSupportPackage ) const 1300 { 1301 sal_Bool bRet = sal_False; 1302 if( m_aExtPathPrefix.getLength() && rURI.getLength() ) 1303 { 1304 sal_Bool bRel = sal_False; 1305 switch( rURI[0] ) 1306 { 1307 case '#': 1308 // no rel path, but 1309 // for package URIs, the '#' has to be removed 1310 if( bSupportPackage ) 1311 { 1312 rURI = rURI.copy( 1 ); 1313 bRet = sal_True; 1314 } 1315 break; 1316 case '/': 1317 // no rel path; nothing to do 1318 break; 1319 case '.': 1320 // a rel path; to keep URI simple, remove './', if there 1321 bRel = sal_True; 1322 if( rURI.getLength() > 1 && '/' == rURI[1] ) 1323 { 1324 rURI = rURI.copy( 2 ); 1325 bRet = sal_True; 1326 } 1327 break; 1328 default: 1329 // check for a RFC2396 schema 1330 { 1331 bRel = sal_True; 1332 sal_Int32 nPos = 1; 1333 sal_Int32 nLen = rURI.getLength(); 1334 while( nPos < nLen ) 1335 { 1336 switch( rURI[nPos] ) 1337 { 1338 case '/': 1339 // a relative path segement 1340 nPos = nLen; // leave loop 1341 break; 1342 case ':': 1343 // a schema 1344 bRel = sal_False; 1345 nPos = nLen; // leave loop 1346 break; 1347 default: 1348 // we don't care about any other characters 1349 break; 1350 } 1351 ++nPos; 1352 } 1353 } 1354 } 1355 1356 if( bRel ) 1357 { 1358 OUString sTmp( m_aExtPathPrefix ); 1359 sTmp += rURI; 1360 rURI = sTmp; 1361 bRet = sal_True; 1362 } 1363 } 1364 1365 return bRet; 1366 } 1367 1368 sal_Bool XMLTransformerBase::ConvertURIToOOo( ::rtl::OUString& rURI, 1369 sal_Bool bSupportPackage ) const 1370 { 1371 sal_Bool bRet = sal_False; 1372 if( rURI.getLength() ) 1373 { 1374 sal_Bool bPackage = sal_False; 1375 switch( rURI[0] ) 1376 { 1377 case '/': 1378 // no rel path; nothing to to 1379 break; 1380 case '.': 1381 // a rel path 1382 if( 0 == rURI.compareTo( m_aExtPathPrefix, 1383 m_aExtPathPrefix.getLength() ) ) 1384 { 1385 // an external URI; remove '../' 1386 rURI = rURI.copy( m_aExtPathPrefix.getLength() ); 1387 bRet = sal_True; 1388 } 1389 else 1390 { 1391 bPackage = sal_True; 1392 } 1393 break; 1394 default: 1395 // check for a RFC2396 schema 1396 { 1397 bPackage = sal_True; 1398 sal_Int32 nPos = 1; 1399 sal_Int32 nLen = rURI.getLength(); 1400 while( nPos < nLen ) 1401 { 1402 switch( rURI[nPos] ) 1403 { 1404 case '/': 1405 // a relative path segement within the package 1406 nPos = nLen; // leave loop 1407 break; 1408 case ':': 1409 // a schema 1410 bPackage = sal_False; 1411 nPos = nLen; // leave loop 1412 break; 1413 default: 1414 // we don't care about any other characters 1415 break; 1416 } 1417 ++nPos; 1418 } 1419 } 1420 } 1421 1422 if( bPackage && bSupportPackage ) 1423 { 1424 OUString sTmp( OUString::valueOf( sal_Unicode( '#' ) ) ); 1425 if( 0 == rURI.compareToAscii( "./", 2 ) ) 1426 rURI = rURI.copy( 2 ); 1427 sTmp += rURI; 1428 rURI = sTmp; 1429 bRet = sal_True; 1430 } 1431 } 1432 1433 return bRet; 1434 } 1435 1436 sal_Bool XMLTransformerBase::RenameAttributeValue( 1437 OUString& rOutAttributeValue, 1438 sal_Int32 nParam1, 1439 sal_Int32 nParam2, 1440 sal_Int32 nParam3 ) 1441 { 1442 return ( lcl_ConvertAttr( rOutAttributeValue, nParam1) || 1443 lcl_ConvertAttr( rOutAttributeValue, nParam2) || 1444 lcl_ConvertAttr( rOutAttributeValue, nParam3) ); 1445 } 1446 1447 // static 1448 bool XMLTransformerBase::ConvertRNGDateTimeToISO( ::rtl::OUString& rDateTime ) 1449 { 1450 if( rDateTime.getLength() > 0 && 1451 rDateTime.indexOf( sal_Unicode('.')) != -1 ) 1452 { 1453 rDateTime = rDateTime.replace( sal_Unicode('.'), sal_Unicode(',')); 1454 return true; 1455 } 1456 1457 return false; 1458 } 1459 1460 XMLTokenEnum XMLTransformerBase::GetToken( const OUString& rStr ) const 1461 { 1462 XMLTransformerTokenMap::const_iterator aIter = 1463 m_pTokenMap->find( rStr ); 1464 if( aIter == m_pTokenMap->end() ) 1465 return XML_TOKEN_END; 1466 else 1467 return (*aIter).second; 1468 } 1469 1470 1471 1472 const XMLTransformerContext *XMLTransformerBase::GetCurrentContext() const 1473 { 1474 OSL_ENSURE( !m_pContexts->empty(), "empty stack" ); 1475 1476 1477 return m_pContexts->empty() ? 0 : m_pContexts->back().get(); 1478 } 1479 1480 const XMLTransformerContext *XMLTransformerBase::GetAncestorContext( 1481 sal_uInt32 n ) const 1482 { 1483 XMLTransformerContextVector::size_type nSize = 1484 m_pContexts->size(); 1485 XMLTransformerContextVector::size_type nPos = 1486 static_cast<XMLTransformerContextVector::size_type>( n ); 1487 1488 OSL_ENSURE( nSize >nPos+2 , "invalid context" ); 1489 1490 return nSize > nPos+2 ? (*m_pContexts)[nSize-(nPos+2)].get() : 0; 1491 } 1492 1493 bool XMLTransformerBase::isWriter() const 1494 { 1495 Reference< XServiceInfo > xSI( mxModel, UNO_QUERY ); 1496 return xSI.is() && 1497 ( xSI->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ) ) ) || 1498 xSI->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.WebDocument" ) ) ) || 1499 xSI->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.GlobalDocument" ) ) ) ); 1500 } 1501