xref: /trunk/main/xmloff/source/transform/TransformerBase.cxx (revision 45c5a00162811bd03b87fcb4fe9996782f2b59ec)
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