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