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