1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
52 #ifndef _XMLOFF_TRANSFORMERTOKENMAP_HXX
53 #include "TransformerTokenMap.hxx"
55 #include <xmloff/xmluconv.hxx>
57 #ifndef _XMLOFF_TRANSFORMERBASE_HXX
58 #include "TransformerBase.hxx"
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 // -----------------------------------------------------------------------------
76 bool lcl_ConvertAttr( OUString
& rOutAttribute
, sal_Int32 nParam
)
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
);
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
,
110 OSL_ENSURE( pContext
&& !pContext
->IsPersistent(),
111 "unknown or not persistent action" );
115 switch( nActionType
)
117 case XML_ETACTION_COPY_CONTENT
:
118 return new XMLIgnoreTransformerContext( *this, rQName
, 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() );
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
) );
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
) );
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
) );
193 OSL_ENSURE( !this, "unknown action" );
198 // default is copying
199 return new XMLTransformerContext( *this, rQName
);
202 XMLTransformerActions
*XMLTransformerBase::GetUserDefinedActions( sal_uInt16
)
207 XMLTransformerBase::XMLTransformerBase( XMLTransformerActionInit
*pInit
,
208 ::xmloff::token::XMLTokenEnum
*pTKMapInit
)
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 ()
229 delete m_pNamespaceMap
;
230 delete m_pReplaceNamespaceMap
;
232 delete m_pElemActions
;
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] ) )
268 pRewindMap
= m_pNamespaceMap
;
269 m_pNamespaceMap
= new SvXMLNamespaceMap( *m_pNamespaceMap
);
271 const OUString
& rAttrValue
= xAttrList
->getValueByIndex( i
);
273 OUString
aPrefix( ( rAttrName
.getLength() == 5 )
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
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.
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
,
321 xContext
= CreateContext( nPrefix
, aLocalName
, rName
);
324 OSL_ENSURE( xContext
.is(), "XMLTransformerBase::startElement: missing context" );
326 xContext
= new XMLTransformerContext( *this, rName
);
328 // Remeber old namespace map.
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
&
344 throw(SAXException
, RuntimeException
)
346 if( !m_pContexts
->empty() )
348 // Get topmost context
349 ::rtl::Reference
< XMLTransformerContext
> xContext
= m_pContexts
->back();
352 OSL_ENSURE( xContext
->GetQName() == rName
,
353 "XMLTransformerBase::endElement: popped context has wrong lname" );
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.
368 // Rewind a namespace map.
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
);
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.
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
);
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() )
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
);
479 sPropName
= OUString( RTL_CONSTASCII_USTRINGPARAM("StreamName" ) );
480 if( xPropSetInfo
->hasPropertyByName(sPropName
) )
482 aAny
= m_xPropSet
->getPropertyValue(sPropName
);
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?" );
501 OUString sTmp
= m_aExtPathPrefix
;
505 m_aExtPathPrefix
+= sTmp
;
506 nPos
= sRelPath
.indexOf( '/', nPos
+ 1 );
516 static MapUnit
lcl_getUnit( const OUString
& rValue
)
519 if( rValue
.endsWithIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "cm" ) ) )
521 else if ( rValue
.endsWithIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "mm" ) ) )
524 nDestUnit
= MAP_INCH
;
528 XMLMutableAttributeList
*XMLTransformerBase::ProcessAttrList(
529 Reference
< XAttributeList
>& rAttrList
, sal_uInt16 nActionMap
,
532 XMLMutableAttributeList
*pMutableAttrList
= 0;
533 XMLTransformerActions
*pActions
= GetUserDefinedActions( nActionMap
);
534 OSL_ENSURE( pActions
, "go no actions" );
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
);
543 sal_uInt16 nPrefix
= GetNamespaceMap().GetKeyByAttrName( rAttrName
,
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
,
555 rAttrList
= pMutableAttrList
;
558 sal_uInt32 nAction
= (*aIter
).second
.m_nActionType
;
559 sal_Bool bRename
= sal_False
;
562 case XML_ATACTION_RENAME
:
565 case XML_ATACTION_COPY
:
567 case XML_ATACTION_REMOVE
:
568 case XML_ATACTION_STYLE_DISPLAY_NAME
:
569 pMutableAttrList
->RemoveAttributeByIndex( i
);
573 case XML_ATACTION_RENAME_IN2INCH
:
575 case XML_ATACTION_IN2INCH
:
577 OUString
aAttrValue( rAttrValue
);
578 if( ReplaceSingleInWithInch( aAttrValue
) )
579 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
582 case XML_ATACTION_INS2INCHS
:
584 OUString
aAttrValue( rAttrValue
);
585 if( ReplaceInWithInch( aAttrValue
) )
586 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
589 case XML_ATACTION_RENAME_INCH2IN
:
591 case XML_ATACTION_INCH2IN
:
593 OUString
aAttrValue( rAttrValue
);
594 if( ReplaceSingleInchWithIn( aAttrValue
) )
595 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
598 case XML_ATACTION_INCHS2INS
:
600 OUString
aAttrValue( rAttrValue
);
601 if( ReplaceInchWithIn( aAttrValue
) )
602 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
605 case XML_ATACTION_TWIPS2IN
:
607 OUString
aAttrValue( rAttrValue
);
609 XMLTransformerBase::ReplaceSingleInchWithIn( aAttrValue
);
612 MapUnit nDestUnit
= lcl_getUnit( aAttrValue
);
614 // convert twips value to inch
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) );
626 rtl::OUStringBuffer aBuffer
;
627 SvXMLUnitConverter::convertMeasure( aBuffer
, nMeasure
, MAP_100TH_MM
, nDestUnit
);
628 aAttrValue
= aBuffer
.makeStringAndClear();
632 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
635 case XML_ATACTION_RENAME_DECODE_STYLE_NAME_REF
:
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
);
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(
654 ::xmloff::token::GetXMLToken(
655 XML_DISPLAY_NAME
) ) );
656 pMutableAttrList
->AddAttribute( aNewAttrQName
,
661 case XML_ATACTION_RENAME_ENCODE_STYLE_NAME_REF
:
663 case XML_ATACTION_ENCODE_STYLE_NAME_REF
:
665 OUString
aAttrValue( rAttrValue
);
666 if( EncodeStyleName(aAttrValue
) )
667 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
670 case XML_ATACTION_RENAME_NEG_PERCENT
:
672 case XML_ATACTION_NEG_PERCENT
:
674 OUString
aAttrValue( rAttrValue
);
675 if( NegPercent( aAttrValue
) )
676 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
679 case XML_ATACTION_RENAME_ADD_NAMESPACE_PREFIX
:
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
);
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
);
705 case XML_ATACTION_RENAME_REMOVE_NAMESPACE_PREFIX
:
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
);
718 case XML_ATACTION_REMOVE_ANY_NAMESPACE_PREFIX
:
720 OUString
aAttrValue( rAttrValue
);
721 if( RemoveNamespacePrefix( aAttrValue
) )
722 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
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
);
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
);
741 case XML_ATACTION_RENAME_ATTRIBUTE
:
743 OUString
aAttrValue( rAttrValue
);
744 RenameAttributeValue(
746 (*aIter
).second
.m_nParam1
,
747 (*aIter
).second
.m_nParam2
,
748 (*aIter
).second
.m_nParam3
);
749 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
752 case XML_ATACTION_RNG2ISO_DATETIME
:
754 OUString
aAttrValue( rAttrValue
);
755 if( ConvertRNGDateTimeToISO( aAttrValue
))
756 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
759 case XML_ATACTION_RENAME_RNG2ISO_DATETIME
:
761 OUString
aAttrValue( rAttrValue
);
762 if( ConvertRNGDateTimeToISO( aAttrValue
))
763 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
767 case XML_ATACTION_IN2TWIPS
:
769 OUString
aAttrValue( rAttrValue
);
770 XMLTransformerBase::ReplaceSingleInWithInch( aAttrValue
);
774 MapUnit nDestUnit
= lcl_getUnit( aAttrValue
);
776 // convert inch value to twips and export as faked inch
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) );
788 OUStringBuffer aBuffer
;
789 SvXMLUnitConverter::convertMeasure( aBuffer
, nMeasure
, MAP_100TH_MM
, nDestUnit
);
790 aAttrValue
= aBuffer
.makeStringAndClear();
794 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
797 case XML_ATACTION_SVG_WIDTH_HEIGHT_OOO
:
799 OUString
aAttrValue( rAttrValue
);
800 ReplaceSingleInchWithIn( aAttrValue
);
802 MapUnit nDestUnit
= lcl_getUnit( aAttrValue
);
805 if( SvXMLUnitConverter::convertMeasure(nMeasure
, aAttrValue
, MAP_100TH_MM
) )
810 else if( nMeasure
< 0 )
814 OUStringBuffer aBuffer
;
815 SvXMLUnitConverter::convertMeasure( aBuffer
, nMeasure
, MAP_100TH_MM
, nDestUnit
);
816 aAttrValue
= aBuffer
.makeStringAndClear();
819 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
822 case XML_ATACTION_SVG_WIDTH_HEIGHT_OASIS
:
824 OUString
aAttrValue( rAttrValue
);
825 ReplaceSingleInWithInch( aAttrValue
);
827 MapUnit nDestUnit
= lcl_getUnit( aAttrValue
);
830 if( SvXMLUnitConverter::convertMeasure(nMeasure
, aAttrValue
, MAP_100TH_MM
) )
835 else if( nMeasure
< 0 )
839 OUStringBuffer aBuffer
;
840 SvXMLUnitConverter::convertMeasure( aBuffer
, nMeasure
, MAP_100TH_MM
, nDestUnit
);
841 aAttrValue
= aBuffer
.makeStringAndClear();
844 pMutableAttrList
->SetValueByIndex( i
, aAttrValue
);
847 case XML_ATACTION_DECODE_ID
:
851 const sal_Int32 nLen
= rAttrValue
.getLength();
852 OUStringBuffer aBuffer
;
855 for( pos
= 0; pos
< nLen
; pos
++ )
857 sal_Unicode c
= rAttrValue
[pos
];
858 if( (c
>= '0') && (c
<= '9') )
861 aBuffer
.append( (sal_Int32
)c
);
864 pMutableAttrList
->SetValueByIndex( i
, aBuffer
.makeStringAndClear() );
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
);
895 OSL_ENSURE( !this, "unknown action" );
901 OUString
aNewAttrQName(
902 GetNamespaceMap().GetQNameByKey(
903 (*aIter
).second
.GetQNamePrefixFromParam1(),
904 ::xmloff::token::GetXMLToken(
905 (*aIter
).second
.GetQNameTokenFromParam1()) ) );
906 pMutableAttrList
->RenameAttributeByIndex( i
,
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] <= ' ' )
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 );
933 sal_Bool
XMLTransformerBase::ReplaceInchWithIn( OUString
& rValue
)
935 sal_Bool bRet
= sal_False
;
937 while( nPos
< rValue
.getLength()-3 )
939 sal_Unicode c
= rValue
[nPos
];
940 if( 'i'==c
|| 'I'==c
)
943 if( (c
>= '0' && c
<= '9') || '.' == c
)
946 if( 'n'==c
|| 'N'==c
)
949 if( 'c'==c
|| 'C'==c
)
952 if( 'h'==c
|| 'H'==c
)
954 rValue
= rValue
.replaceAt( nPos
,
955 4, GetXMLToken(XML_UNIT_INCH
) );
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] <= ' ' )
978 ('i'==rValue
[nPos
-2] ||
979 'I'==rValue
[nPos
-2]) &&
980 ('n'==rValue
[nPos
-1] ||
981 'N'==rValue
[nPos
-1]) )
984 rValue
= rValue
.replaceAt( nPos
, rValue
.getLength() - nPos
,
985 GetXMLToken(XML_INCH
) );
992 sal_Bool
XMLTransformerBase::ReplaceInWithInch( OUString
& rValue
)
994 sal_Bool bRet
= sal_False
;
996 while( nPos
< rValue
.getLength()-1 )
998 sal_Unicode c
= rValue
[nPos
];
999 if( 'i'==c
|| 'I'==c
)
1002 if( (c
>= '0' && c
<= '9') || '.' == c
)
1005 if( 'n'==c
|| 'N'==c
)
1007 rValue
= rValue
.replaceAt( nPos
,
1008 2, GetXMLToken(XML_INCH
) );
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
;
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
== '.') );
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 )
1063 if( !xCharClass
.is() )
1065 Reference
< XMultiServiceFactory
> xFactory
=
1066 comphelper::getProcessServiceFactory();
1071 const_cast < XMLTransformerBase
* >(this)
1073 Reference
< XCharacterClassification
>(
1074 xFactory
->createInstance(
1075 OUString::createFromAscii(
1076 "com.sun.star.i18n.CharacterClassification_Unicode") ),
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
);
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
;
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
1113 aBuffer
.append( c
);
1117 aBuffer
.append( static_cast< sal_Unicode
>( '_' ) );
1119 aBuffer
.append( static_cast< sal_Unicode
>(
1120 aHexTab
[ (c
>> 12) & 0x0f ] ) );
1122 aBuffer
.append( static_cast< sal_Unicode
>(
1123 aHexTab
[ (c
>> 8) & 0x0f ] ) );
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
;
1138 rName
= aBuffer
.makeStringAndClear();
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
];
1158 aBuffer
.append( cEnc
);
1163 bEncoded
= sal_True
;
1165 bWithinHex
= !bWithinHex
;
1167 else if( bWithinHex
)
1170 if( c
>= '0' && c
<= '9' )
1174 else if( c
>= 'a' && c
<= 'f' )
1176 cDigit
= c
- 'a' + 10;
1178 else if( c
>= 'A' && c
<= 'F' )
1180 cDigit
= c
- 'A' + 10;
1185 bEncoded
= sal_False
;
1188 cEnc
= (cEnc
<< 4) + cDigit
;
1192 aBuffer
.append( c
);
1197 rName
= aBuffer
.makeStringAndClear();
1201 sal_Bool
XMLTransformerBase::NegPercent( OUString
& rValue
)
1203 sal_Bool bRet
= sal_False
;
1204 sal_Bool bNeg
= sal_False
;
1207 sal_Int32 nPos
= 0L;
1208 sal_Int32 nLen
= rValue
.getLength();
1211 while( nPos
< nLen
&& sal_Unicode(' ') == rValue
[nPos
] )
1214 if( nPos
< nLen
&& sal_Unicode('-') == rValue
[nPos
] )
1221 while( nPos
< nLen
&&
1222 sal_Unicode('0') <= rValue
[nPos
] &&
1223 sal_Unicode('9') >= rValue
[nPos
] )
1225 // TODO: check overflow!
1227 nVal
+= (rValue
[nPos
] - sal_Unicode('0'));
1231 if( nPos
< nLen
&& sal_Unicode('.') == rValue
[nPos
] )
1235 while( nPos
< nLen
&&
1236 sal_Unicode('0') <= rValue
[nPos
] &&
1237 sal_Unicode('9') >= rValue
[nPos
] )
1239 // TODO: check overflow!
1241 nVal
+= ( static_cast<double>(rValue
[nPos
] - sal_Unicode('0')) / nDiv
);
1247 while( nPos
< nLen
&& sal_Unicode(' ') == rValue
[nPos
] )
1250 if( nPos
< nLen
&& sal_Unicode('%') == rValue
[nPos
] )
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();
1269 sal_Bool
XMLTransformerBase::AddNamespacePrefix( ::rtl::OUString
& rName
,
1270 sal_uInt16 nPrefix
) const
1272 rName
= GetNamespaceMap().GetQNameByKey( nPrefix
, rName
, sal_False
);
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
);
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
;
1301 // for package URIs, the '#' has to be removed
1302 if( bSupportPackage
)
1304 rURI
= rURI
.copy( 1 );
1309 // no rel path; nothing to do
1312 // a rel path; to keep URI simple, remove './', if there
1314 if( rURI
.getLength() > 1 && '/' == rURI
[1] )
1316 rURI
= rURI
.copy( 2 );
1321 // check for a RFC2396 schema
1325 sal_Int32 nLen
= rURI
.getLength();
1326 while( nPos
< nLen
)
1328 switch( rURI
[nPos
] )
1331 // a relative path segement
1332 nPos
= nLen
; // leave loop
1337 nPos
= nLen
; // leave loop
1340 // we don't care about any other characters
1350 OUString
sTmp( m_aExtPathPrefix
);
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
;
1370 // no rel path; nothing to to
1374 if( 0 == rURI
.compareTo( m_aExtPathPrefix
,
1375 m_aExtPathPrefix
.getLength() ) )
1377 // an external URI; remove '../'
1378 rURI
= rURI
.copy( m_aExtPathPrefix
.getLength() );
1383 bPackage
= sal_True
;
1387 // check for a RFC2396 schema
1389 bPackage
= sal_True
;
1391 sal_Int32 nLen
= rURI
.getLength();
1392 while( nPos
< nLen
)
1394 switch( rURI
[nPos
] )
1397 // a relative path segement within the package
1398 nPos
= nLen
; // leave loop
1402 bPackage
= sal_False
;
1403 nPos
= nLen
; // leave loop
1406 // we don't care about any other characters
1414 if( bPackage
&& bSupportPackage
)
1416 OUString
sTmp( OUString::valueOf( sal_Unicode( '#' ) ) );
1417 if( 0 == rURI
.compareToAscii( "./", 2 ) )
1418 rURI
= rURI
.copy( 2 );
1428 sal_Bool
XMLTransformerBase::RenameAttributeValue(
1429 OUString
& rOutAttributeValue
,
1434 return ( lcl_ConvertAttr( rOutAttributeValue
, nParam1
) ||
1435 lcl_ConvertAttr( rOutAttributeValue
, nParam2
) ||
1436 lcl_ConvertAttr( rOutAttributeValue
, nParam3
) );
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(','));
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
;
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
);
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" ) ) ) );