Update ooo320-m1
[ooovba.git] / xmloff / source / transform / TransformerBase.cxx
blobb1ce8c4995657ededacee996d0205f650b07b0be
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: TransformerBase.cxx,v $
10 * $Revision: 1.23.56.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
33 #include <rtl/ref.hxx>
34 #include <rtl/ustrbuf.hxx>
35 #include <com/sun/star/i18n/XCharacterClassification.hpp>
36 #include <com/sun/star/i18n/UnicodeType.hpp>
37 #include <comphelper/processfactory.hxx>
38 #include <xmloff/nmspmap.hxx>
39 #include "xmlnmspe.hxx"
40 #include "IgnoreTContext.hxx"
41 #include "RenameElemTContext.hxx"
42 #include "ProcAttrTContext.hxx"
43 #include "ProcAddAttrTContext.hxx"
44 #include "MergeElemTContext.hxx"
45 #include "CreateElemTContext.hxx"
46 #include "MutableAttrList.hxx"
47 #include "TransformerActions.hxx"
48 #include "ElemTransformerAction.hxx"
49 // --> OD 2005-06-29 #i50322#
50 #include "PropertyActionsOOo.hxx"
51 // <--
52 #ifndef _XMLOFF_TRANSFORMERTOKENMAP_HXX
53 #include "TransformerTokenMap.hxx"
54 #endif
55 #include <xmloff/xmluconv.hxx>
57 #ifndef _XMLOFF_TRANSFORMERBASE_HXX
58 #include "TransformerBase.hxx"
59 #endif
60 #include "TContextVector.hxx"
62 using ::rtl::OUString;
63 using ::rtl::OUStringBuffer;
64 using namespace ::osl;
65 using namespace ::xmloff::token;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::beans;
68 using namespace ::com::sun::star::lang;
69 using namespace ::com::sun::star::i18n;
70 using namespace ::com::sun::star::xml::sax;
72 // -----------------------------------------------------------------------------
74 namespace
76 bool lcl_ConvertAttr( OUString & rOutAttribute, sal_Int32 nParam )
78 bool bResult = false;
79 enum XMLTokenEnum eTokenToRename =
80 static_cast< enum XMLTokenEnum >( nParam & 0xffff );
81 if( eTokenToRename != XML_TOKEN_INVALID &&
82 IsXMLToken( rOutAttribute, eTokenToRename ))
84 enum XMLTokenEnum eReplacementToken =
85 static_cast< enum XMLTokenEnum >( nParam >> 16 );
86 rOutAttribute = GetXMLToken( eReplacementToken );
87 bResult = true;
89 return bResult;
91 } // anonymous namespace
93 // -----------------------------------------------------------------------------
95 XMLTransformerContext *XMLTransformerBase::CreateContext( USHORT nPrefix,
96 const OUString& rLocalName, const OUString& rQName )
98 XMLTransformerActions::key_type aKey( nPrefix, rLocalName );
99 XMLTransformerActions::const_iterator aIter =
100 GetElemActions().find( aKey );
102 if( !(aIter == GetElemActions().end()) )
104 sal_uInt32 nActionType = (*aIter).second.m_nActionType;
105 if( (nActionType & XML_ETACTION_USER_DEFINED) != 0 )
107 XMLTransformerContext *pContext =
108 CreateUserDefinedContext( (*aIter).second,
109 rQName );
110 OSL_ENSURE( pContext && !pContext->IsPersistent(),
111 "unknown or not persistent action" );
112 return pContext;
115 switch( nActionType )
117 case XML_ETACTION_COPY_CONTENT:
118 return new XMLIgnoreTransformerContext( *this, rQName, sal_False,
119 sal_False );
120 case XML_ETACTION_COPY:
121 return new XMLTransformerContext( *this, rQName );
122 case XML_ETACTION_RENAME_ELEM:
123 return new XMLRenameElemTransformerContext( *this, rQName,
124 (*aIter).second.GetQNamePrefixFromParam1(),
125 (*aIter).second.GetQNameTokenFromParam1() );
126 case XML_ETACTION_RENAME_ELEM_ADD_ATTR:
127 return new XMLRenameElemTransformerContext( *this, rQName,
128 (*aIter).second.GetQNamePrefixFromParam1(),
129 (*aIter).second.GetQNameTokenFromParam1(),
130 (*aIter).second.GetQNamePrefixFromParam2(),
131 (*aIter).second.GetQNameTokenFromParam2(),
132 static_cast< XMLTokenEnum >( (*aIter).second.m_nParam3 ) );
133 case XML_ETACTION_RENAME_ELEM_PROC_ATTRS:
134 return new XMLProcAttrTransformerContext( *this, rQName,
135 (*aIter).second.GetQNamePrefixFromParam1(),
136 (*aIter).second.GetQNameTokenFromParam1(),
137 static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) );
138 case XML_ETACTION_RENAME_ELEM_ADD_PROC_ATTR:
139 return new XMLProcAddAttrTransformerContext( *this, rQName,
140 (*aIter).second.GetQNamePrefixFromParam1(),
141 (*aIter).second.GetQNameTokenFromParam1(),
142 static_cast< sal_uInt16 >(
143 (*aIter).second.m_nParam3 >> 16 ),
144 (*aIter).second.GetQNamePrefixFromParam2(),
145 (*aIter).second.GetQNameTokenFromParam2(),
146 static_cast< XMLTokenEnum >(
147 (*aIter).second.m_nParam3 & 0xffff ) );
148 case XML_ETACTION_RENAME_ELEM_COND:
150 const XMLTransformerContext *pCurrent = GetCurrentContext();
151 if( pCurrent->HasQName(
152 (*aIter).second.GetQNamePrefixFromParam2(),
153 (*aIter).second.GetQNameTokenFromParam2() ) )
154 return new XMLRenameElemTransformerContext( *this, rQName,
155 (*aIter).second.GetQNamePrefixFromParam1(),
156 (*aIter).second.GetQNameTokenFromParam1() );
158 break;
159 case XML_ETACTION_RENAME_ELEM_PROC_ATTRS_COND:
161 const XMLTransformerContext *pCurrent = GetCurrentContext();
162 if( pCurrent->HasQName(
163 (*aIter).second.GetQNamePrefixFromParam3(),
164 (*aIter).second.GetQNameTokenFromParam3() ) )
165 return new XMLProcAttrTransformerContext( *this, rQName,
166 (*aIter).second.GetQNamePrefixFromParam1(),
167 (*aIter).second.GetQNameTokenFromParam1(),
168 static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) );
169 else
170 return new XMLProcAttrTransformerContext( *this, rQName,
171 static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) );
173 case XML_ETACTION_PROC_ATTRS:
174 return new XMLProcAttrTransformerContext( *this, rQName,
175 static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) );
176 case XML_ETACTION_PROC_ATTRS_COND:
178 const XMLTransformerContext *pCurrent = GetCurrentContext();
179 if( pCurrent->HasQName(
180 (*aIter).second.GetQNamePrefixFromParam1(),
181 (*aIter).second.GetQNameTokenFromParam1() ) )
182 return new XMLProcAttrTransformerContext( *this, rQName,
183 static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) );
185 break;
186 case XML_ETACTION_MOVE_ATTRS_TO_ELEMS:
187 return new XMLCreateElemTransformerContext( *this, rQName,
188 static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) );
189 case XML_ETACTION_MOVE_ELEMS_TO_ATTRS:
190 return new XMLMergeElemTransformerContext( *this, rQName,
191 static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) );
192 default:
193 OSL_ENSURE( !this, "unknown action" );
194 break;
198 // default is copying
199 return new XMLTransformerContext( *this, rQName );
202 XMLTransformerActions *XMLTransformerBase::GetUserDefinedActions( sal_uInt16 )
204 return 0;
207 XMLTransformerBase::XMLTransformerBase( XMLTransformerActionInit *pInit,
208 ::xmloff::token::XMLTokenEnum *pTKMapInit )
209 throw () :
210 m_pNamespaceMap( new SvXMLNamespaceMap ),
211 m_pReplaceNamespaceMap( new SvXMLNamespaceMap ),
212 m_pContexts( new XMLTransformerContextVector ),
213 m_pElemActions( new XMLTransformerActions( pInit ) ),
214 m_pTokenMap( new XMLTransformerTokenMap( pTKMapInit ) )
216 GetNamespaceMap().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
217 GetNamespaceMap().Add( GetXMLToken(XML_NP_DC), GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
218 GetNamespaceMap().Add( GetXMLToken(XML_NP_MATH), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH );
219 GetNamespaceMap().Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
220 GetNamespaceMap().Add( GetXMLToken(XML_NP_DOM), GetXMLToken(XML_N_DOM), XML_NAMESPACE_DOM );
221 GetNamespaceMap().Add( GetXMLToken(XML_NP_OOOW), GetXMLToken(XML_N_OOOW), XML_NAMESPACE_OOOW );
222 GetNamespaceMap().Add( GetXMLToken(XML_NP_OOOC), GetXMLToken(XML_N_OOOC), XML_NAMESPACE_OOOC );
225 XMLTransformerBase::~XMLTransformerBase() throw ()
227 ResetTokens();
229 delete m_pNamespaceMap;
230 delete m_pReplaceNamespaceMap;
231 delete m_pContexts;
232 delete m_pElemActions;
233 delete m_pTokenMap;
236 void SAL_CALL XMLTransformerBase::startDocument( void )
237 throw( SAXException, RuntimeException )
239 m_xHandler->startDocument();
242 void SAL_CALL XMLTransformerBase::endDocument( void )
243 throw( SAXException, RuntimeException)
245 m_xHandler->endDocument();
248 void SAL_CALL XMLTransformerBase::startElement( const OUString& rName,
249 const Reference< XAttributeList >& rAttrList )
250 throw(SAXException, RuntimeException)
252 SvXMLNamespaceMap *pRewindMap = 0;
254 // Process namespace attributes. This must happen before creating the
255 // context, because namespace decaration apply to the element name itself.
256 XMLMutableAttributeList *pMutableAttrList = 0;
257 Reference< XAttributeList > xAttrList( rAttrList );
258 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
259 for( sal_Int16 i=0; i < nAttrCount; i++ )
261 const OUString& rAttrName = xAttrList->getNameByIndex( i );
262 if( ( rAttrName.getLength() >= 5 ) &&
263 ( rAttrName.compareTo( GetXMLToken(XML_XMLNS), 5 ) == 0 ) &&
264 ( rAttrName.getLength() == 5 || ':' == rAttrName[5] ) )
266 if( !pRewindMap )
268 pRewindMap = m_pNamespaceMap;
269 m_pNamespaceMap = new SvXMLNamespaceMap( *m_pNamespaceMap );
271 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
273 OUString aPrefix( ( rAttrName.getLength() == 5 )
274 ? OUString()
275 : rAttrName.copy( 6 ) );
276 // Add namespace, but only if it is known.
277 sal_uInt16 nKey = m_pNamespaceMap->AddIfKnown( aPrefix, rAttrValue );
278 // If namespace is unknwon, try to match a name with similar
279 // TC Id an version
280 if( XML_NAMESPACE_UNKNOWN == nKey )
282 OUString aTestName( rAttrValue );
283 if( SvXMLNamespaceMap::NormalizeOasisURN( aTestName ) )
284 nKey = m_pNamespaceMap->AddIfKnown( aPrefix, aTestName );
286 // If that namespace is not known, too, add it as unknown
287 if( XML_NAMESPACE_UNKNOWN == nKey )
288 nKey = m_pNamespaceMap->Add( aPrefix, rAttrValue );
290 const OUString& rRepName = m_pReplaceNamespaceMap->GetNameByKey( nKey );
291 if( rRepName.getLength() )
293 if( !pMutableAttrList )
295 pMutableAttrList = new XMLMutableAttributeList( xAttrList );
296 xAttrList = pMutableAttrList;
299 pMutableAttrList->SetValueByIndex( i, rRepName );
304 // Get element's namespace and local name.
305 OUString aLocalName;
306 sal_uInt16 nPrefix =
307 m_pNamespaceMap->GetKeyByAttrName( rName, &aLocalName );
309 // If there are contexts already, call a CreateChildContext at the topmost
310 // context. Otherwise, create a default context.
311 ::rtl::Reference < XMLTransformerContext > xContext;
312 if( !m_pContexts->empty() )
314 xContext = m_pContexts->back()->CreateChildContext( nPrefix,
315 aLocalName,
316 rName,
317 xAttrList );
319 else
321 xContext = CreateContext( nPrefix, aLocalName, rName );
324 OSL_ENSURE( xContext.is(), "XMLTransformerBase::startElement: missing context" );
325 if( !xContext.is() )
326 xContext = new XMLTransformerContext( *this, rName );
328 // Remeber old namespace map.
329 if( pRewindMap )
330 xContext->SetRewindMap( pRewindMap );
332 // Push context on stack.
333 m_pContexts->push_back( xContext );
335 // Call a startElement at the new context.
336 xContext->StartElement( xAttrList );
339 void SAL_CALL XMLTransformerBase::endElement( const OUString&
340 #ifndef PRODUCT
341 rName
342 #endif
344 throw(SAXException, RuntimeException)
346 if( !m_pContexts->empty() )
348 // Get topmost context
349 ::rtl::Reference< XMLTransformerContext > xContext = m_pContexts->back();
351 #ifndef PRODUCT
352 OSL_ENSURE( xContext->GetQName() == rName,
353 "XMLTransformerBase::endElement: popped context has wrong lname" );
354 #endif
356 // Call a EndElement at the current context.
357 xContext->EndElement();
359 // and remove it from the stack.
360 m_pContexts->pop_back();
362 // Get a namespace map to rewind.
363 SvXMLNamespaceMap *pRewindMap = xContext->GetRewindMap();
365 // Delete the current context.
366 xContext = 0;
368 // Rewind a namespace map.
369 if( pRewindMap )
371 delete m_pNamespaceMap;
372 m_pNamespaceMap = pRewindMap;
377 void SAL_CALL XMLTransformerBase::characters( const OUString& rChars )
378 throw(SAXException, RuntimeException)
380 if( !m_pContexts->empty() )
382 m_pContexts->back()->Characters( rChars );
386 void SAL_CALL XMLTransformerBase::ignorableWhitespace( const OUString& rWhitespaces )
387 throw(SAXException, RuntimeException)
389 m_xHandler->ignorableWhitespace( rWhitespaces );
392 void SAL_CALL XMLTransformerBase::processingInstruction( const OUString& rTarget,
393 const OUString& rData )
394 throw(SAXException, RuntimeException)
396 m_xHandler->processingInstruction( rTarget, rData );
399 void SAL_CALL XMLTransformerBase::setDocumentLocator( const Reference< XLocator >& rLocator )
400 throw(SAXException, RuntimeException)
402 m_xLocator = rLocator;
405 // XExtendedDocumentHandler
406 void SAL_CALL XMLTransformerBase::startCDATA( void ) throw(SAXException, RuntimeException)
408 if( m_xExtHandler.is() )
409 m_xExtHandler->startCDATA();
412 void SAL_CALL XMLTransformerBase::endCDATA( void ) throw(RuntimeException)
414 if( m_xExtHandler.is() )
415 m_xExtHandler->endCDATA();
418 void SAL_CALL XMLTransformerBase::comment( const OUString& rComment )
419 throw(SAXException, RuntimeException)
421 if( m_xExtHandler.is() )
422 m_xExtHandler->comment( rComment );
425 void SAL_CALL XMLTransformerBase::allowLineBreak( void )
426 throw(SAXException, RuntimeException)
428 if( m_xExtHandler.is() )
429 m_xExtHandler->allowLineBreak();
432 void SAL_CALL XMLTransformerBase::unknown( const OUString& rString )
433 throw(SAXException, RuntimeException)
435 if( m_xExtHandler.is() )
436 m_xExtHandler->unknown( rString );
439 // XInitialize
440 void SAL_CALL XMLTransformerBase::initialize( const Sequence< Any >& aArguments )
441 throw(Exception, RuntimeException)
443 const sal_Int32 nAnyCount = aArguments.getLength();
444 const Any* pAny = aArguments.getConstArray();
446 for( sal_Int32 nIndex = 0; nIndex < nAnyCount; nIndex++, pAny++ )
448 // #b6236750# use isAssignableFrom instead of comparing the types to
449 // allow XExtendedDocumentHandler instead of XDocumentHandler (used in
450 // writeOasis2OOoLibraryElement in sfx2).
451 // The Any shift operator can't be used to query the type because it
452 // uses queryInterface, and the model also has a XPropertySet interface.
454 // document handler
455 if( ::getCppuType( (const Reference< XDocumentHandler >*) 0 ).isAssignableFrom( pAny->getValueType() ) )
456 m_xHandler.set( *pAny, UNO_QUERY );
458 // property set to transport data across
459 if( ::getCppuType( (const Reference< XPropertySet >*) 0 ).isAssignableFrom( pAny->getValueType() ) )
460 m_xPropSet.set( *pAny, UNO_QUERY );
462 // xmodel
463 if( ::getCppuType( (const Reference< ::com::sun::star::frame::XModel >*) 0 ).isAssignableFrom( pAny->getValueType() ) )
464 mxModel.set( *pAny, UNO_QUERY );
467 if( m_xPropSet.is() )
469 Any aAny;
470 OUString sRelPath, sName;
471 Reference< XPropertySetInfo > xPropSetInfo =
472 m_xPropSet->getPropertySetInfo();
473 OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("StreamRelPath" ) );
474 if( xPropSetInfo->hasPropertyByName(sPropName) )
476 aAny = m_xPropSet->getPropertyValue(sPropName);
477 aAny >>= sRelPath;
479 sPropName = OUString( RTL_CONSTASCII_USTRINGPARAM("StreamName" ) );
480 if( xPropSetInfo->hasPropertyByName(sPropName) )
482 aAny = m_xPropSet->getPropertyValue(sPropName);
483 aAny >>= sName;
485 if( sName.getLength() )
487 m_aExtPathPrefix = OUString( RTL_CONSTASCII_USTRINGPARAM("../" ) );
489 // If there is a rel path within a package, then append
490 // additional '../'. If the rel path contains an ':', then it is
491 // an absolute URI (or invalid URI, because zip files don't
492 // permit ':'), and it will be ignored.
493 if( sRelPath.getLength() )
495 sal_Int32 nColPos = sRelPath.indexOf( ':' );
496 OSL_ENSURE( -1 == nColPos,
497 "StreamRelPath contains ':', absolute URI?" );
499 if( -1 == nColPos )
501 OUString sTmp = m_aExtPathPrefix;
502 sal_Int32 nPos = 0;
505 m_aExtPathPrefix += sTmp;
506 nPos = sRelPath.indexOf( '/', nPos + 1 );
508 while( -1 != nPos );
516 static MapUnit lcl_getUnit( const OUString& rValue )
518 MapUnit nDestUnit;
519 if( rValue.endsWithIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "cm" ) ) )
520 nDestUnit = MAP_CM;
521 else if ( rValue.endsWithIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "mm" ) ) )
522 nDestUnit = MAP_MM;
523 else
524 nDestUnit = MAP_INCH;
525 return nDestUnit;
528 XMLMutableAttributeList *XMLTransformerBase::ProcessAttrList(
529 Reference< XAttributeList >& rAttrList, sal_uInt16 nActionMap,
530 sal_Bool bClone )
532 XMLMutableAttributeList *pMutableAttrList = 0;
533 XMLTransformerActions *pActions = GetUserDefinedActions( nActionMap );
534 OSL_ENSURE( pActions, "go no actions" );
535 if( pActions )
537 sal_Int16 nAttrCount = rAttrList.is() ? rAttrList->getLength() : 0;
538 for( sal_Int16 i=0; i < nAttrCount; ++i )
540 const OUString& rAttrName = rAttrList->getNameByIndex( i );
541 const OUString& rAttrValue = rAttrList->getValueByIndex( i );
542 OUString aLocalName;
543 sal_uInt16 nPrefix = GetNamespaceMap().GetKeyByAttrName( rAttrName,
544 &aLocalName );
546 XMLTransformerActions::key_type aKey( nPrefix, aLocalName );
547 XMLTransformerActions::const_iterator aIter =
548 pActions->find( aKey );
549 if( !(aIter == pActions->end() ) )
551 if( !pMutableAttrList )
553 pMutableAttrList = new XMLMutableAttributeList( rAttrList,
554 bClone );
555 rAttrList = pMutableAttrList;
558 sal_uInt32 nAction = (*aIter).second.m_nActionType;
559 sal_Bool bRename = sal_False;
560 switch( nAction )
562 case XML_ATACTION_RENAME:
563 bRename = sal_True;
564 break;
565 case XML_ATACTION_COPY:
566 break;
567 case XML_ATACTION_REMOVE:
568 case XML_ATACTION_STYLE_DISPLAY_NAME:
569 pMutableAttrList->RemoveAttributeByIndex( i );
570 --i;
571 --nAttrCount;
572 break;
573 case XML_ATACTION_RENAME_IN2INCH:
574 bRename = sal_True;
575 case XML_ATACTION_IN2INCH:
577 OUString aAttrValue( rAttrValue );
578 if( ReplaceSingleInWithInch( aAttrValue ) )
579 pMutableAttrList->SetValueByIndex( i, aAttrValue );
581 break;
582 case XML_ATACTION_INS2INCHS:
584 OUString aAttrValue( rAttrValue );
585 if( ReplaceInWithInch( aAttrValue ) )
586 pMutableAttrList->SetValueByIndex( i, aAttrValue );
588 break;
589 case XML_ATACTION_RENAME_INCH2IN:
590 bRename = sal_True;
591 case XML_ATACTION_INCH2IN:
593 OUString aAttrValue( rAttrValue );
594 if( ReplaceSingleInchWithIn( aAttrValue ) )
595 pMutableAttrList->SetValueByIndex( i, aAttrValue );
597 break;
598 case XML_ATACTION_INCHS2INS:
600 OUString aAttrValue( rAttrValue );
601 if( ReplaceInchWithIn( aAttrValue ) )
602 pMutableAttrList->SetValueByIndex( i, aAttrValue );
604 break;
605 case XML_ATACTION_TWIPS2IN:
607 OUString aAttrValue( rAttrValue );
609 XMLTransformerBase::ReplaceSingleInchWithIn( aAttrValue );
610 if( isWriter() )
612 MapUnit nDestUnit = lcl_getUnit( aAttrValue );
614 // convert twips value to inch
615 sal_Int32 nMeasure;
616 if( SvXMLUnitConverter::convertMeasure(nMeasure, aAttrValue, MAP_100TH_MM ) )
619 // --> OD 2004-10-29 #i13778#,#i36248#
620 // apply correct twip-to-1/100mm
621 nMeasure = (sal_Int32)( nMeasure >= 0
622 ? ((nMeasure*127L+36L)/72L)
623 : ((nMeasure*127L-36L)/72L) );
624 // <--
626 rtl::OUStringBuffer aBuffer;
627 SvXMLUnitConverter::convertMeasure( aBuffer, nMeasure, MAP_100TH_MM, nDestUnit );
628 aAttrValue = aBuffer.makeStringAndClear();
632 pMutableAttrList->SetValueByIndex( i, aAttrValue );
634 break;
635 case XML_ATACTION_RENAME_DECODE_STYLE_NAME_REF:
636 bRename = sal_True;
637 case XML_ATACTION_DECODE_STYLE_NAME:
638 case XML_ATACTION_DECODE_STYLE_NAME_REF:
640 OUString aAttrValue( rAttrValue );
641 if( DecodeStyleName(aAttrValue) )
642 pMutableAttrList->SetValueByIndex( i, aAttrValue );
644 break;
645 case XML_ATACTION_ENCODE_STYLE_NAME:
647 OUString aAttrValue( rAttrValue );
648 if( EncodeStyleName(aAttrValue) )
650 pMutableAttrList->SetValueByIndex( i, aAttrValue );
651 OUString aNewAttrQName(
652 GetNamespaceMap().GetQNameByKey(
653 nPrefix,
654 ::xmloff::token::GetXMLToken(
655 XML_DISPLAY_NAME ) ) );
656 pMutableAttrList->AddAttribute( aNewAttrQName,
657 rAttrValue );
660 break;
661 case XML_ATACTION_RENAME_ENCODE_STYLE_NAME_REF:
662 bRename = sal_True;
663 case XML_ATACTION_ENCODE_STYLE_NAME_REF:
665 OUString aAttrValue( rAttrValue );
666 if( EncodeStyleName(aAttrValue) )
667 pMutableAttrList->SetValueByIndex( i, aAttrValue );
669 break;
670 case XML_ATACTION_RENAME_NEG_PERCENT:
671 bRename = sal_True;
672 case XML_ATACTION_NEG_PERCENT:
674 OUString aAttrValue( rAttrValue );
675 if( NegPercent( aAttrValue ) )
676 pMutableAttrList->SetValueByIndex( i, aAttrValue );
678 break;
679 case XML_ATACTION_RENAME_ADD_NAMESPACE_PREFIX:
680 bRename = sal_True;
681 case XML_ATACTION_ADD_NAMESPACE_PREFIX:
683 OUString aAttrValue( rAttrValue );
684 sal_uInt16 nValPrefix =
685 static_cast<sal_uInt16>(
686 bRename ? (*aIter).second.m_nParam2
687 : (*aIter).second.m_nParam1);
688 if( AddNamespacePrefix( aAttrValue, nValPrefix ) )
689 pMutableAttrList->SetValueByIndex( i, aAttrValue );
691 break;
692 case XML_ATACTION_ADD_APP_NAMESPACE_PREFIX:
694 OUString aAttrValue( rAttrValue );
695 sal_uInt16 nValPrefix =
696 static_cast<sal_uInt16>((*aIter).second.m_nParam1);
697 if( IsXMLToken( GetClass(), XML_SPREADSHEET ) )
698 nValPrefix = XML_NAMESPACE_OOOC;
699 else if( IsXMLToken( GetClass(), XML_TEXT ) )
700 nValPrefix = XML_NAMESPACE_OOOW;
701 if( AddNamespacePrefix( aAttrValue, nValPrefix ) )
702 pMutableAttrList->SetValueByIndex( i, aAttrValue );
704 break;
705 case XML_ATACTION_RENAME_REMOVE_NAMESPACE_PREFIX:
706 bRename = sal_True;
707 case XML_ATACTION_REMOVE_NAMESPACE_PREFIX:
709 OUString aAttrValue( rAttrValue );
710 sal_uInt16 nValPrefix =
711 static_cast<sal_uInt16>(
712 bRename ? (*aIter).second.m_nParam2
713 : (*aIter).second.m_nParam1);
714 if( RemoveNamespacePrefix( aAttrValue, nValPrefix ) )
715 pMutableAttrList->SetValueByIndex( i, aAttrValue );
717 break;
718 case XML_ATACTION_REMOVE_ANY_NAMESPACE_PREFIX:
720 OUString aAttrValue( rAttrValue );
721 if( RemoveNamespacePrefix( aAttrValue ) )
722 pMutableAttrList->SetValueByIndex( i, aAttrValue );
724 break;
725 case XML_ATACTION_URI_OOO:
727 OUString aAttrValue( rAttrValue );
728 if( ConvertURIToOASIS( aAttrValue,
729 static_cast< sal_Bool >((*aIter).second.m_nParam1)))
730 pMutableAttrList->SetValueByIndex( i, aAttrValue );
732 break;
733 case XML_ATACTION_URI_OASIS:
735 OUString aAttrValue( rAttrValue );
736 if( ConvertURIToOOo( aAttrValue,
737 static_cast< sal_Bool >((*aIter).second.m_nParam1)))
738 pMutableAttrList->SetValueByIndex( i, aAttrValue );
740 break;
741 case XML_ATACTION_RENAME_ATTRIBUTE:
743 OUString aAttrValue( rAttrValue );
744 RenameAttributeValue(
745 aAttrValue,
746 (*aIter).second.m_nParam1,
747 (*aIter).second.m_nParam2,
748 (*aIter).second.m_nParam3 );
749 pMutableAttrList->SetValueByIndex( i, aAttrValue );
751 break;
752 case XML_ATACTION_RNG2ISO_DATETIME:
754 OUString aAttrValue( rAttrValue );
755 if( ConvertRNGDateTimeToISO( aAttrValue ))
756 pMutableAttrList->SetValueByIndex( i, aAttrValue );
758 break;
759 case XML_ATACTION_RENAME_RNG2ISO_DATETIME:
761 OUString aAttrValue( rAttrValue );
762 if( ConvertRNGDateTimeToISO( aAttrValue ))
763 pMutableAttrList->SetValueByIndex( i, aAttrValue );
764 bRename = sal_True;
766 break;
767 case XML_ATACTION_IN2TWIPS:
769 OUString aAttrValue( rAttrValue );
770 XMLTransformerBase::ReplaceSingleInWithInch( aAttrValue );
772 if( isWriter() )
774 MapUnit nDestUnit = lcl_getUnit( aAttrValue );
776 // convert inch value to twips and export as faked inch
777 sal_Int32 nMeasure;
778 if( SvXMLUnitConverter::convertMeasure(nMeasure, aAttrValue, MAP_100TH_MM ) )
781 // --> OD 2004-10-29 #i13778#,#i36248#
782 // apply correct 1/100mm-to-twip conversion
783 nMeasure = (sal_Int32)( nMeasure >= 0
784 ? ((nMeasure*72L+63L)/127L)
785 : ((nMeasure*72L-63L)/127L) );
786 // <--
788 OUStringBuffer aBuffer;
789 SvXMLUnitConverter::convertMeasure( aBuffer, nMeasure, MAP_100TH_MM, nDestUnit );
790 aAttrValue = aBuffer.makeStringAndClear();
794 pMutableAttrList->SetValueByIndex( i, aAttrValue );
796 break;
797 case XML_ATACTION_SVG_WIDTH_HEIGHT_OOO:
799 OUString aAttrValue( rAttrValue );
800 ReplaceSingleInchWithIn( aAttrValue );
802 MapUnit nDestUnit = lcl_getUnit( aAttrValue );
804 sal_Int32 nMeasure;
805 if( SvXMLUnitConverter::convertMeasure(nMeasure, aAttrValue, MAP_100TH_MM ) )
808 if( nMeasure > 0 )
809 nMeasure -= 1;
810 else if( nMeasure < 0 )
811 nMeasure += 1;
814 OUStringBuffer aBuffer;
815 SvXMLUnitConverter::convertMeasure( aBuffer, nMeasure, MAP_100TH_MM, nDestUnit );
816 aAttrValue = aBuffer.makeStringAndClear();
819 pMutableAttrList->SetValueByIndex( i, aAttrValue );
821 break;
822 case XML_ATACTION_SVG_WIDTH_HEIGHT_OASIS:
824 OUString aAttrValue( rAttrValue );
825 ReplaceSingleInWithInch( aAttrValue );
827 MapUnit nDestUnit = lcl_getUnit( aAttrValue );
829 sal_Int32 nMeasure;
830 if( SvXMLUnitConverter::convertMeasure(nMeasure, aAttrValue, MAP_100TH_MM ) )
833 if( nMeasure > 0 )
834 nMeasure += 1;
835 else if( nMeasure < 0 )
836 nMeasure -= 1;
839 OUStringBuffer aBuffer;
840 SvXMLUnitConverter::convertMeasure( aBuffer, nMeasure, MAP_100TH_MM, nDestUnit );
841 aAttrValue = aBuffer.makeStringAndClear();
844 pMutableAttrList->SetValueByIndex( i, aAttrValue );
846 break;
847 case XML_ATACTION_DECODE_ID:
849 OUString aAttrValue;
851 const sal_Int32 nLen = rAttrValue.getLength();
852 OUStringBuffer aBuffer;
854 sal_Int32 pos;
855 for( pos = 0; pos < nLen; pos++ )
857 sal_Unicode c = rAttrValue[pos];
858 if( (c >= '0') && (c <= '9') )
859 aBuffer.append( c );
860 else
861 aBuffer.append( (sal_Int32)c );
864 pMutableAttrList->SetValueByIndex( i, aBuffer.makeStringAndClear() );
866 break;
867 // --> OD 2005-06-10 #i50322# - special handling for the
868 // transparency of writer background graphics.
869 case XML_ATACTION_WRITER_BACK_GRAPHIC_TRANSPARENCY:
871 // determine, if it's the transparency of a document style
872 XMLTransformerContext* pFirstContext = (*m_pContexts)[0].get();
873 OUString aFirstContextLocalName;
874 /* sal_uInt16 nFirstContextPrefix = */
875 GetNamespaceMap().GetKeyByAttrName( pFirstContext->GetQName(),
876 &aFirstContextLocalName );
877 bool bIsDocumentStyle(
878 ::xmloff::token::IsXMLToken( aFirstContextLocalName,
879 XML_DOCUMENT_STYLES ) );
880 // no conversion of transparency value for document
881 // styles, because former OpenOffice.org version writes
882 // writes always a transparency value of 100% and doesn't
883 // read the value. Thus, it's intepreted as 0%
884 if ( !bIsDocumentStyle )
886 OUString aAttrValue( rAttrValue );
887 NegPercent(aAttrValue);
888 pMutableAttrList->SetValueByIndex( i, aAttrValue );
890 bRename = sal_True;
892 break;
893 // <--
894 default:
895 OSL_ENSURE( !this, "unknown action" );
896 break;
899 if( bRename )
901 OUString aNewAttrQName(
902 GetNamespaceMap().GetQNameByKey(
903 (*aIter).second.GetQNamePrefixFromParam1(),
904 ::xmloff::token::GetXMLToken(
905 (*aIter).second.GetQNameTokenFromParam1()) ) );
906 pMutableAttrList->RenameAttributeByIndex( i,
907 aNewAttrQName );
913 return pMutableAttrList;
916 sal_Bool XMLTransformerBase::ReplaceSingleInchWithIn( OUString& rValue )
918 sal_Bool bRet = sal_False;
919 sal_Int32 nPos = rValue.getLength();
920 while( nPos && rValue[nPos-1] <= ' ' )
921 --nPos;
922 if( nPos > 2 &&
923 ('c'==rValue[nPos-2] || 'C'==rValue[nPos-2]) &&
924 ('h'==rValue[nPos-1] || 'H'==rValue[nPos-1]) )
926 rValue =rValue.copy( 0, nPos-2 );
927 bRet = sal_True;
930 return bRet;
933 sal_Bool XMLTransformerBase::ReplaceInchWithIn( OUString& rValue )
935 sal_Bool bRet = sal_False;
936 sal_Int32 nPos = 1;
937 while( nPos < rValue.getLength()-3 )
939 sal_Unicode c = rValue[nPos];
940 if( 'i'==c || 'I'==c )
942 c = rValue[nPos-1];
943 if( (c >= '0' && c <= '9') || '.' == c )
945 c = rValue[nPos+1];
946 if( 'n'==c || 'N'==c )
948 c = rValue[nPos+2];
949 if( 'c'==c || 'C'==c )
951 c = rValue[nPos+3];
952 if( 'h'==c || 'H'==c )
954 rValue = rValue.replaceAt( nPos,
955 4, GetXMLToken(XML_UNIT_INCH) );
956 nPos += 2;
957 bRet = sal_True;
958 continue;
964 ++nPos;
967 return bRet;
970 sal_Bool XMLTransformerBase::ReplaceSingleInWithInch( OUString& rValue )
972 sal_Bool bRet = sal_False;
974 sal_Int32 nPos = rValue.getLength();
975 while( nPos && rValue[nPos-1] <= ' ' )
976 --nPos;
977 if( nPos > 2 &&
978 ('i'==rValue[nPos-2] ||
979 'I'==rValue[nPos-2]) &&
980 ('n'==rValue[nPos-1] ||
981 'N'==rValue[nPos-1]) )
983 nPos -= 2;
984 rValue = rValue.replaceAt( nPos, rValue.getLength() - nPos,
985 GetXMLToken(XML_INCH) );
986 bRet = sal_True;
989 return bRet;
992 sal_Bool XMLTransformerBase::ReplaceInWithInch( OUString& rValue )
994 sal_Bool bRet = sal_False;
995 sal_Int32 nPos = 1;
996 while( nPos < rValue.getLength()-1 )
998 sal_Unicode c = rValue[nPos];
999 if( 'i'==c || 'I'==c )
1001 c = rValue[nPos-1];
1002 if( (c >= '0' && c <= '9') || '.' == c )
1004 c = rValue[nPos+1];
1005 if( 'n'==c || 'N'==c )
1007 rValue = rValue.replaceAt( nPos,
1008 2, GetXMLToken(XML_INCH) );
1009 nPos += 4;
1010 bRet = sal_True;
1011 continue;
1015 ++nPos;
1018 return bRet;
1021 sal_Bool XMLTransformerBase::EncodeStyleName( OUString& rName ) const
1023 static sal_Char aHexTab[] = "0123456789abcdef";
1025 sal_Bool bEncoded = sal_False;
1027 sal_Int32 nLen = rName.getLength();
1028 OUStringBuffer aBuffer( nLen );
1030 for( sal_Int32 i = 0; i < nLen; i++ )
1032 sal_Unicode c = rName[i];
1033 sal_Bool bValidChar = sal_False;
1034 if( c < 0x00ffU )
1036 bValidChar =
1037 (c >= 0x0041 && c <= 0x005a) ||
1038 (c >= 0x0061 && c <= 0x007a) ||
1039 (c >= 0x00c0 && c <= 0x00d6) ||
1040 (c >= 0x00d8 && c <= 0x00f6) ||
1041 (c >= 0x00f8 && c <= 0x00ff) ||
1042 ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) ||
1043 c == 0x00b7 || c == '-' || c == '.') );
1045 else
1047 if( (c >= 0xf900U && c <= 0xfffeU) ||
1048 (c >= 0x20ddU && c <= 0x20e0U))
1050 bValidChar = sal_False;
1052 else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
1053 c == 0x06e5 || c == 0x06e6 )
1055 bValidChar = sal_True;
1057 else if( c == 0x0387 )
1059 bValidChar = i > 0;
1061 else
1063 if( !xCharClass.is() )
1065 Reference< XMultiServiceFactory > xFactory =
1066 comphelper::getProcessServiceFactory();
1067 if( xFactory.is() )
1071 const_cast < XMLTransformerBase * >(this)
1072 ->xCharClass =
1073 Reference < XCharacterClassification >(
1074 xFactory->createInstance(
1075 OUString::createFromAscii(
1076 "com.sun.star.i18n.CharacterClassification_Unicode") ),
1077 UNO_QUERY );
1079 OSL_ENSURE( xCharClass.is(),
1080 "can't instantiate character clossification component" );
1082 catch( com::sun::star::uno::Exception& )
1087 if( xCharClass.is() )
1089 sal_Int16 nType = xCharClass->getType( rName, i );
1091 switch( nType )
1093 case UnicodeType::UPPERCASE_LETTER: // Lu
1094 case UnicodeType::LOWERCASE_LETTER: // Ll
1095 case UnicodeType::TITLECASE_LETTER: // Lt
1096 case UnicodeType::OTHER_LETTER: // Lo
1097 case UnicodeType::LETTER_NUMBER: // Nl
1098 bValidChar = sal_True;
1099 break;
1100 case UnicodeType::NON_SPACING_MARK: // Ms
1101 case UnicodeType::ENCLOSING_MARK: // Me
1102 case UnicodeType::COMBINING_SPACING_MARK: //Mc
1103 case UnicodeType::MODIFIER_LETTER: // Lm
1104 case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd
1105 bValidChar = i > 0;
1106 break;
1111 if( bValidChar )
1113 aBuffer.append( c );
1115 else
1117 aBuffer.append( static_cast< sal_Unicode >( '_' ) );
1118 if( c > 0x0fff )
1119 aBuffer.append( static_cast< sal_Unicode >(
1120 aHexTab[ (c >> 12) & 0x0f ] ) );
1121 if( c > 0x00ff )
1122 aBuffer.append( static_cast< sal_Unicode >(
1123 aHexTab[ (c >> 8) & 0x0f ] ) );
1124 if( c > 0x000f )
1125 aBuffer.append( static_cast< sal_Unicode >(
1126 aHexTab[ (c >> 4) & 0x0f ] ) );
1127 aBuffer.append( static_cast< sal_Unicode >(
1128 aHexTab[ c & 0x0f ] ) );
1129 aBuffer.append( static_cast< sal_Unicode >( '_' ) );
1130 bEncoded = sal_True;
1134 if( aBuffer.getLength() > (1<<15)-1 )
1135 bEncoded = sal_False;
1137 if( bEncoded )
1138 rName = aBuffer.makeStringAndClear();
1139 return bEncoded;
1142 sal_Bool XMLTransformerBase::DecodeStyleName( OUString& rName )
1144 sal_Bool bEncoded = sal_False;
1146 sal_Int32 nLen = rName.getLength();
1147 OUStringBuffer aBuffer( nLen );
1149 sal_Bool bWithinHex = sal_False;
1150 sal_Unicode cEnc = 0;
1151 for( sal_Int32 i = 0; i < nLen; i++ )
1153 sal_Unicode c = rName[i];
1154 if( '_' == c )
1156 if( bWithinHex )
1158 aBuffer.append( cEnc );
1159 cEnc = 0;
1161 else
1163 bEncoded = sal_True;
1165 bWithinHex = !bWithinHex;
1167 else if( bWithinHex )
1169 sal_Unicode cDigit;
1170 if( c >= '0' && c <= '9' )
1172 cDigit = c - '0';
1174 else if( c >= 'a' && c <= 'f' )
1176 cDigit = c - 'a' + 10;
1178 else if( c >= 'A' && c <= 'F' )
1180 cDigit = c - 'A' + 10;
1182 else
1184 // error
1185 bEncoded = sal_False;
1186 break;
1188 cEnc = (cEnc << 4) + cDigit;
1190 else
1192 aBuffer.append( c );
1196 if( bEncoded )
1197 rName = aBuffer.makeStringAndClear();
1198 return bEncoded;
1201 sal_Bool XMLTransformerBase::NegPercent( OUString& rValue )
1203 sal_Bool bRet = sal_False;
1204 sal_Bool bNeg = sal_False;
1205 double nVal = 0;
1207 sal_Int32 nPos = 0L;
1208 sal_Int32 nLen = rValue.getLength();
1210 // skip white space
1211 while( nPos < nLen && sal_Unicode(' ') == rValue[nPos] )
1212 nPos++;
1214 if( nPos < nLen && sal_Unicode('-') == rValue[nPos] )
1216 bNeg = sal_True;
1217 nPos++;
1220 // get number
1221 while( nPos < nLen &&
1222 sal_Unicode('0') <= rValue[nPos] &&
1223 sal_Unicode('9') >= rValue[nPos] )
1225 // TODO: check overflow!
1226 nVal *= 10;
1227 nVal += (rValue[nPos] - sal_Unicode('0'));
1228 nPos++;
1230 double nDiv = 1.;
1231 if( nPos < nLen && sal_Unicode('.') == rValue[nPos] )
1233 nPos++;
1235 while( nPos < nLen &&
1236 sal_Unicode('0') <= rValue[nPos] &&
1237 sal_Unicode('9') >= rValue[nPos] )
1239 // TODO: check overflow!
1240 nDiv *= 10;
1241 nVal += ( static_cast<double>(rValue[nPos] - sal_Unicode('0')) / nDiv );
1242 nPos++;
1246 // skip white space
1247 while( nPos < nLen && sal_Unicode(' ') == rValue[nPos] )
1248 nPos++;
1250 if( nPos < nLen && sal_Unicode('%') == rValue[nPos] )
1252 if( bNeg )
1253 nVal = -nVal;
1254 nVal += .5;
1256 sal_Int32 nIntVal = 100 - static_cast<sal_Int32>( nVal );
1258 OUStringBuffer aNewValBuffer;
1259 aNewValBuffer.append( nIntVal );
1260 aNewValBuffer.append( sal_Unicode('%' ) );
1262 rValue = aNewValBuffer.makeStringAndClear();
1263 bRet = sal_True;
1266 return bRet;
1269 sal_Bool XMLTransformerBase::AddNamespacePrefix( ::rtl::OUString& rName,
1270 sal_uInt16 nPrefix ) const
1272 rName = GetNamespaceMap().GetQNameByKey( nPrefix, rName, sal_False );
1273 return sal_True;
1276 sal_Bool XMLTransformerBase::RemoveNamespacePrefix( ::rtl::OUString& rName,
1277 sal_uInt16 nPrefixOnly ) const
1279 OUString aLocalName;
1280 sal_uInt16 nPrefix =
1281 GetNamespaceMap()._GetKeyByAttrName( rName, &aLocalName, sal_False );
1282 sal_Bool bRet = XML_NAMESPACE_UNKNOWN != nPrefix &&
1283 (USHRT_MAX == nPrefixOnly || nPrefix == nPrefixOnly);
1284 if( bRet )
1285 rName = aLocalName;
1287 return bRet;
1290 sal_Bool XMLTransformerBase::ConvertURIToOASIS( ::rtl::OUString& rURI,
1291 sal_Bool bSupportPackage ) const
1293 sal_Bool bRet = sal_False;
1294 if( m_aExtPathPrefix.getLength() && rURI.getLength() )
1296 sal_Bool bRel = sal_False;
1297 switch( rURI[0] )
1299 case '#':
1300 // no rel path, but
1301 // for package URIs, the '#' has to be removed
1302 if( bSupportPackage )
1304 rURI = rURI.copy( 1 );
1305 bRet = sal_True;
1307 break;
1308 case '/':
1309 // no rel path; nothing to do
1310 break;
1311 case '.':
1312 // a rel path; to keep URI simple, remove './', if there
1313 bRel = sal_True;
1314 if( rURI.getLength() > 1 && '/' == rURI[1] )
1316 rURI = rURI.copy( 2 );
1317 bRet = sal_True;
1319 break;
1320 default:
1321 // check for a RFC2396 schema
1323 bRel = sal_True;
1324 sal_Int32 nPos = 1;
1325 sal_Int32 nLen = rURI.getLength();
1326 while( nPos < nLen )
1328 switch( rURI[nPos] )
1330 case '/':
1331 // a relative path segement
1332 nPos = nLen; // leave loop
1333 break;
1334 case ':':
1335 // a schema
1336 bRel = sal_False;
1337 nPos = nLen; // leave loop
1338 break;
1339 default:
1340 // we don't care about any other characters
1341 break;
1343 ++nPos;
1348 if( bRel )
1350 OUString sTmp( m_aExtPathPrefix );
1351 sTmp += rURI;
1352 rURI = sTmp;
1353 bRet = sal_True;
1357 return bRet;
1360 sal_Bool XMLTransformerBase::ConvertURIToOOo( ::rtl::OUString& rURI,
1361 sal_Bool bSupportPackage ) const
1363 sal_Bool bRet = sal_False;
1364 if( rURI.getLength() )
1366 sal_Bool bPackage = sal_False;
1367 switch( rURI[0] )
1369 case '/':
1370 // no rel path; nothing to to
1371 break;
1372 case '.':
1373 // a rel path
1374 if( 0 == rURI.compareTo( m_aExtPathPrefix,
1375 m_aExtPathPrefix.getLength() ) )
1377 // an external URI; remove '../'
1378 rURI = rURI.copy( m_aExtPathPrefix.getLength() );
1379 bRet = sal_True;
1381 else
1383 bPackage = sal_True;
1385 break;
1386 default:
1387 // check for a RFC2396 schema
1389 bPackage = sal_True;
1390 sal_Int32 nPos = 1;
1391 sal_Int32 nLen = rURI.getLength();
1392 while( nPos < nLen )
1394 switch( rURI[nPos] )
1396 case '/':
1397 // a relative path segement within the package
1398 nPos = nLen; // leave loop
1399 break;
1400 case ':':
1401 // a schema
1402 bPackage = sal_False;
1403 nPos = nLen; // leave loop
1404 break;
1405 default:
1406 // we don't care about any other characters
1407 break;
1409 ++nPos;
1414 if( bPackage && bSupportPackage )
1416 OUString sTmp( OUString::valueOf( sal_Unicode( '#' ) ) );
1417 if( 0 == rURI.compareToAscii( "./", 2 ) )
1418 rURI = rURI.copy( 2 );
1419 sTmp += rURI;
1420 rURI = sTmp;
1421 bRet = sal_True;
1425 return bRet;
1428 sal_Bool XMLTransformerBase::RenameAttributeValue(
1429 OUString& rOutAttributeValue,
1430 sal_Int32 nParam1,
1431 sal_Int32 nParam2,
1432 sal_Int32 nParam3 )
1434 return ( lcl_ConvertAttr( rOutAttributeValue, nParam1) ||
1435 lcl_ConvertAttr( rOutAttributeValue, nParam2) ||
1436 lcl_ConvertAttr( rOutAttributeValue, nParam3) );
1439 // static
1440 bool XMLTransformerBase::ConvertRNGDateTimeToISO( ::rtl::OUString& rDateTime )
1442 if( rDateTime.getLength() > 0 &&
1443 rDateTime.indexOf( sal_Unicode('.')) != -1 )
1445 rDateTime = rDateTime.replace( sal_Unicode('.'), sal_Unicode(','));
1446 return true;
1449 return false;
1452 XMLTokenEnum XMLTransformerBase::GetToken( const OUString& rStr ) const
1454 XMLTransformerTokenMap::const_iterator aIter =
1455 m_pTokenMap->find( rStr );
1456 if( aIter == m_pTokenMap->end() )
1457 return XML_TOKEN_END;
1458 else
1459 return (*aIter).second;
1464 const XMLTransformerContext *XMLTransformerBase::GetCurrentContext() const
1466 OSL_ENSURE( !m_pContexts->empty(), "empty stack" );
1469 return m_pContexts->empty() ? 0 : m_pContexts->back().get();
1472 const XMLTransformerContext *XMLTransformerBase::GetAncestorContext(
1473 sal_uInt32 n ) const
1475 XMLTransformerContextVector::size_type nSize =
1476 m_pContexts->size();
1477 XMLTransformerContextVector::size_type nPos =
1478 static_cast<XMLTransformerContextVector::size_type>( n );
1480 OSL_ENSURE( nSize >nPos+2 , "invalid context" );
1482 return nSize > nPos+2 ? (*m_pContexts)[nSize-(nPos+2)].get() : 0;
1485 bool XMLTransformerBase::isWriter() const
1487 Reference< XServiceInfo > xSI( mxModel, UNO_QUERY );
1488 return xSI.is() &&
1489 ( xSI->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ) ) ) ||
1490 xSI->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.WebDocument" ) ) ) ||
1491 xSI->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.GlobalDocument" ) ) ) );