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