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 {
lcl_ConvertAttr(OUString & rOutAttribute,sal_Int32 nParam)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
CreateContext(sal_uInt16 nPrefix,const OUString & rLocalName,const OUString & rQName)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
GetUserDefinedActions(sal_uInt16)195 XMLTransformerActions *XMLTransformerBase::GetUserDefinedActions( sal_uInt16 )
196 {
197 return 0;
198 }
199
XMLTransformerBase(XMLTransformerActionInit * pInit,::xmloff::token::XMLTokenEnum * pTKMapInit)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
~XMLTransformerBase()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
startDocument(void)229 void SAL_CALL XMLTransformerBase::startDocument( void )
230 {
231 m_xHandler->startDocument();
232 }
233
endDocument(void)234 void SAL_CALL XMLTransformerBase::endDocument( void )
235 {
236 m_xHandler->endDocument();
237 }
238
startElement(const OUString & rName,const Reference<XAttributeList> & rAttrList)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
endElement(const OUString & rName)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
characters(const OUString & rChars)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
ignorableWhitespace(const OUString & rWhitespaces)377 void SAL_CALL XMLTransformerBase::ignorableWhitespace( const OUString& rWhitespaces )
378 {
379 m_xHandler->ignorableWhitespace( rWhitespaces );
380 }
381
processingInstruction(const OUString & rTarget,const OUString & rData)382 void SAL_CALL XMLTransformerBase::processingInstruction( const OUString& rTarget,
383 const OUString& rData )
384 {
385 m_xHandler->processingInstruction( rTarget, rData );
386 }
387
setDocumentLocator(const Reference<XLocator> & rLocator)388 void SAL_CALL XMLTransformerBase::setDocumentLocator( const Reference< XLocator >& rLocator )
389 {
390 m_xLocator = rLocator;
391 }
392
393 // XExtendedDocumentHandler
startCDATA(void)394 void SAL_CALL XMLTransformerBase::startCDATA( void )
395 {
396 if( m_xExtHandler.is() )
397 m_xExtHandler->startCDATA();
398 }
399
endCDATA(void)400 void SAL_CALL XMLTransformerBase::endCDATA( void )
401 {
402 if( m_xExtHandler.is() )
403 m_xExtHandler->endCDATA();
404 }
405
comment(const OUString & rComment)406 void SAL_CALL XMLTransformerBase::comment( const OUString& rComment )
407 {
408 if( m_xExtHandler.is() )
409 m_xExtHandler->comment( rComment );
410 }
411
allowLineBreak(void)412 void SAL_CALL XMLTransformerBase::allowLineBreak( void )
413 {
414 if( m_xExtHandler.is() )
415 m_xExtHandler->allowLineBreak();
416 }
417
unknown(const OUString & rString)418 void SAL_CALL XMLTransformerBase::unknown( const OUString& rString )
419 {
420 if( m_xExtHandler.is() )
421 m_xExtHandler->unknown( rString );
422 }
423
424 // XInitialize
initialize(const Sequence<Any> & aArguments)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
lcl_getUnit(const OUString & rValue)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
ProcessAttrList(Reference<XAttributeList> & rAttrList,sal_uInt16 nActionMap,sal_Bool bClone)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
ReplaceSingleInchWithIn(OUString & rValue)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
ReplaceInchWithIn(OUString & rValue)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
ReplaceSingleInWithInch(OUString & rValue)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
ReplaceInWithInch(OUString & rValue)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
EncodeStyleName(OUString & rName) const1013 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
DecodeStyleName(OUString & rName)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
NegPercent(OUString & rValue)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
AddNamespacePrefix(::rtl::OUString & rName,sal_uInt16 nPrefix) const1261 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
RemoveNamespacePrefix(::rtl::OUString & rName,sal_uInt16 nPrefixOnly) const1268 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
ConvertURIToOASIS(::rtl::OUString & rURI,sal_Bool bSupportPackage) const1282 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
ConvertURIToOOo(::rtl::OUString & rURI,sal_Bool bSupportPackage) const1352 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
RenameAttributeValue(OUString & rOutAttributeValue,sal_Int32 nParam1,sal_Int32 nParam2,sal_Int32 nParam3)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
ConvertRNGDateTimeToISO(::rtl::OUString & rDateTime)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
GetToken(const OUString & rStr) const1444 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
GetCurrentContext() const1456 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
GetAncestorContext(sal_uInt32 n) const1464 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
isWriter() const1477 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