xref: /trunk/main/xmloff/source/style/xmlexppr.cxx (revision 870262e3)
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 <com/sun/star/container/XNameContainer.hpp>
27 #include <com/sun/star/xml/AttributeData.hpp>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/beans/XPropertyState.hpp>
30 #include <com/sun/star/lang/XTypeProvider.hpp>
31 #include <com/sun/star/beans/XMultiPropertySet.hpp>
32 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
33 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
34 #include <rtl/ustrbuf.hxx>
35 #include <list>
36 #include <hash_map>
37 
38 #include <xmloff/xmlexppr.hxx>
39 #include <xmloff/xmltoken.hxx>
40 #include <xmloff/attrlist.hxx>
41 #include <xmloff/nmspmap.hxx>
42 #include "xmloff/xmlnmspe.hxx"
43 #include <xmloff/xmlexp.hxx>
44 #include <xmloff/xmlprmap.hxx>
45 #include <xmloff/PropertySetInfoHash.hxx>
46 #include <comphelper/stl_types.hxx>
47 
48 #ifndef _SVSTDARR_USHORTS
49 #define _SVSTDARR_USHORTS
50 #include <svl/svstdarr.hxx>
51 #endif
52 
53 using ::rtl::OUString;
54 using ::rtl::OUStringBuffer;
55 
56 using namespace ::std;
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::beans;
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::lang;
61 using namespace ::xmloff::token;
62 
63 #define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
64 
65 struct XMLPropTokens_Impl
66 {
67 	sal_uInt16 nType;
68 	XMLTokenEnum eToken;
69 };
70 
71 #define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
72 const sal_uInt16 MAX_PROP_TYPES =
73 	(XML_TYPE_PROP_END >> XML_TYPE_PROP_SHIFT) -
74 	(XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT);
75 
76 static  XMLPropTokens_Impl aPropTokens[MAX_PROP_TYPES] =
77 {
78 	ENTRY(CHART),
79 	ENTRY(GRAPHIC),
80 	ENTRY(TABLE),
81 	ENTRY(TABLE_COLUMN),
82 	ENTRY(TABLE_ROW),
83 	ENTRY(TABLE_CELL),
84 	ENTRY(LIST_LEVEL),
85 	ENTRY(PARAGRAPH),
86 	ENTRY(TEXT),
87 	ENTRY(DRAWING_PAGE),
88 	ENTRY(PAGE_LAYOUT),
89 	ENTRY(HEADER_FOOTER),
90 	ENTRY(RUBY),
91 	ENTRY(SECTION)
92 };
93 
94 ///////////////////////////////////////////////////////////////////////////////
95 //
96 // public methods
97 //
98 
99 ///////////////////////////////////////////////////////////////////////////
100 //
101 // Take all properties of the XPropertySet which are also found in the
102 // XMLPropertyMapEntry-array and which are not set to their default-value,
103 // if a state is available.
104 //
105 // After that I call the method 'ContextFilter'.
106 //
107 
108 typedef std::list<XMLPropertyState> XMLPropertyStateList_Impl;
109 
110 class XMLPropertyStates_Impl
111 {
112 	XMLPropertyStateList_Impl			aPropStates;
113 	XMLPropertyStateList_Impl::iterator	aLastItr;
114 	sal_uInt32							nCount;
115 public:
116 	XMLPropertyStates_Impl();
117 	void AddPropertyState(const XMLPropertyState& rPropState);
118 	void FillPropertyStateVector(std::vector<XMLPropertyState>& rVector);
119 };
120 
XMLPropertyStates_Impl()121 XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
122 	aPropStates(),
123 	nCount(0)
124 {
125 	aLastItr = aPropStates.begin();
126 }
127 
AddPropertyState(const XMLPropertyState & rPropState)128 void XMLPropertyStates_Impl::AddPropertyState(
129 		const XMLPropertyState& rPropState)
130 {
131 	XMLPropertyStateList_Impl::iterator aItr = aPropStates.begin();
132 	sal_Bool bInserted(sal_False);
133 	if (nCount)
134 	{
135 		if (aLastItr->mnIndex < rPropState.mnIndex)
136 			aItr = ++aLastItr;
137 	}
138 	do
139 	{
140 		// TODO: one path required only
141 		if (aItr == aPropStates.end())
142 		{
143 			aLastItr = aPropStates.insert(aPropStates.end(), rPropState);
144 			bInserted = sal_True;
145 			nCount++;
146 		}
147 		else if (aItr->mnIndex > rPropState.mnIndex)
148 		{
149 			aLastItr = aPropStates.insert(aItr, rPropState);
150 			bInserted = sal_True;
151 			nCount++;
152 		}
153 	}
154 	while(!bInserted && (aItr++ != aPropStates.end()));
155 }
156 
FillPropertyStateVector(std::vector<XMLPropertyState> & rVector)157 void XMLPropertyStates_Impl::FillPropertyStateVector(
158 		std::vector<XMLPropertyState>& rVector)
159 {
160 	if (nCount)
161 	{
162 		rVector.resize(nCount, XMLPropertyState(-1));
163         ::std::copy( aPropStates.begin(), aPropStates.end(), rVector.begin() );
164 	}
165 }
166 
167 class FilterPropertyInfo_Impl
168 {
169 	const rtl::OUString		sApiName;
170 	std::list<sal_uInt32>	aIndexes;
171 	sal_uInt32				nCount;
172 
173 public:
174 
175 	FilterPropertyInfo_Impl( const rtl::OUString& rApiName,
176 							 const sal_uInt32 nIndex);
177 
GetApiName() const178 	const OUString& GetApiName() const { return sApiName; }
GetIndexes()179 	std::list<sal_uInt32>& GetIndexes() { return aIndexes; }
180 
AddIndex(sal_uInt32 nIndex)181 	void AddIndex( sal_uInt32 nIndex )
182 	{
183 		aIndexes.push_back(nIndex);
184 		nCount++;
185 	}
186 
187     // for sort
operator <(const FilterPropertyInfo_Impl & rArg) const188     sal_Bool operator< ( const FilterPropertyInfo_Impl& rArg ) const
189     {
190         return (GetApiName() < rArg.GetApiName());
191     }
192 };
193 
FilterPropertyInfo_Impl(const rtl::OUString & rApiName,const sal_uInt32 nIndex)194 FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
195 		const rtl::OUString& rApiName,
196 		const sal_uInt32 nIndex ) :
197 	sApiName( rApiName ),
198 	aIndexes(),
199 	nCount(1)
200 {
201 	aIndexes.push_back(nIndex);
202 }
203 
204 typedef std::list<FilterPropertyInfo_Impl> FilterPropertyInfoList_Impl;
205 
206 // ----------------------------------------------------------------------------
207 
208 class FilterPropertiesInfo_Impl
209 {
210 	sal_uInt32								nCount;
211 	FilterPropertyInfoList_Impl				aPropInfos;
212 	FilterPropertyInfoList_Impl::iterator	aLastItr;
213 
214 	Sequence <OUString> 					*pApiNames;
215 
216 public:
217 	FilterPropertiesInfo_Impl();
218 	~FilterPropertiesInfo_Impl();
219 
220 	void AddProperty(const rtl::OUString& rApiName, const sal_uInt32 nIndex);
221 	const uno::Sequence<OUString>& GetApiNames();
222 	void FillPropertyStateArray(
223 			vector< XMLPropertyState >& rPropStates,
224 			const Reference< XPropertySet >& xPropSet,
225 			const UniReference< XMLPropertySetMapper >& maPropMapper,
226 			const sal_Bool bDefault = sal_False);
GetPropertyCount() const227 	sal_uInt32 GetPropertyCount() const { return nCount; }
228 };
229 
230 // ----------------------------------------------------------------------------
231 
232 typedef std::hash_map
233 <
234 	PropertySetInfoKey,
235 	FilterPropertiesInfo_Impl *,
236 	PropertySetInfoHash,
237 	PropertySetInfoHash
238 >
239 FilterOropertiesHashMap_Impl;
240 
241 class FilterPropertiesInfos_Impl : public FilterOropertiesHashMap_Impl
242 {
243 public:
244 	~FilterPropertiesInfos_Impl ();
245 };
246 
~FilterPropertiesInfos_Impl()247 FilterPropertiesInfos_Impl::~FilterPropertiesInfos_Impl ()
248 {
249 	FilterOropertiesHashMap_Impl::iterator aIter = begin();
250 	FilterOropertiesHashMap_Impl::iterator aEnd = end();
251 	while( aIter != aEnd )
252 	{
253 		delete (*aIter).second;
254 		(*aIter).second = 0;
255 		++aIter;
256 	}
257 }
258 
259 // ----------------------------------------------------------------------------
260 
FilterPropertiesInfo_Impl()261 FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
262 	nCount(0),
263 	aPropInfos(),
264 	pApiNames( 0 )
265 {
266 	aLastItr = aPropInfos.begin();
267 }
268 
~FilterPropertiesInfo_Impl()269 FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
270 {
271 	delete pApiNames;
272 }
273 
AddProperty(const rtl::OUString & rApiName,const sal_uInt32 nIndex)274 void FilterPropertiesInfo_Impl::AddProperty(
275 		const rtl::OUString& rApiName, const sal_uInt32 nIndex)
276 {
277     aPropInfos.push_back(FilterPropertyInfo_Impl(rApiName, nIndex));
278     nCount++;
279 
280 	OSL_ENSURE( !pApiNames, "performance warning: API names already retrieved" );
281 	if( pApiNames )
282 	{
283 		delete pApiNames;
284 		pApiNames = NULL;
285 	}
286 }
GetApiNames()287 const uno::Sequence<OUString>& FilterPropertiesInfo_Impl::GetApiNames()
288 {
289 	OSL_ENSURE(nCount == aPropInfos.size(), "wrong property count");
290 	if( !pApiNames )
291 	{
292         // we have to do three things:
293         // 1) sort API names,
294         // 2) merge duplicates,
295         // 3) construct sequence
296 
297         // sort names
298         aPropInfos.sort();
299 
300         // merge duplicates
301         if ( nCount > 1 )
302         {
303             FilterPropertyInfoList_Impl::iterator aOld = aPropInfos.begin();
304             FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
305             FilterPropertyInfoList_Impl::iterator aCurrent = aOld;
306             aCurrent++;
307 
308             while ( aCurrent != aEnd )
309             {
310                 // equal to next element?
311                 if ( aOld->GetApiName().equals( aCurrent->GetApiName() ) )
312                 {
313                     // if equal: merge index lists
314                     aOld->GetIndexes().merge( aCurrent->GetIndexes() );
315                     // erase element, and continue with next
316                     aCurrent = aPropInfos.erase( aCurrent );
317 					nCount--;
318                 }
319                 else
320                 {
321                     // remember old element and continue with next
322                     aOld = aCurrent;
323                     aCurrent++;
324                 }
325             }
326         }
327 
328         // construct sequence
329 		pApiNames = new Sequence < OUString >( nCount );
330 		OUString *pNames = pApiNames->getArray();
331 		FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
332 		FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
333 		for ( ; aItr != aEnd; aItr++, pNames++)
334 			*pNames = aItr->GetApiName();
335 	}
336 
337 	return *pApiNames;
338 }
339 
FillPropertyStateArray(vector<XMLPropertyState> & rPropStates,const Reference<XPropertySet> & rPropSet,const UniReference<XMLPropertySetMapper> & rPropMapper,const sal_Bool bDefault)340 void FilterPropertiesInfo_Impl::FillPropertyStateArray(
341 		vector< XMLPropertyState >& rPropStates,
342 		const Reference< XPropertySet >& rPropSet,
343 		const UniReference< XMLPropertySetMapper >& rPropMapper,
344 		const sal_Bool bDefault )
345 {
346 	XMLPropertyStates_Impl aPropStates;
347 
348 	const uno::Sequence<OUString>& rApiNames = GetApiNames();
349 
350     Reference < XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
351     if (xTolPropSet.is())
352     {
353         if (!bDefault)
354         {
355             Sequence < beans::GetDirectPropertyTolerantResult > aResults(xTolPropSet->getDirectPropertyValuesTolerant(rApiNames));
356             sal_Int32 nResultCount(aResults.getLength());
357             if (nResultCount > 0)
358             {
359 		        const beans::GetDirectPropertyTolerantResult *pResults = aResults.getConstArray();
360 		        FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
361 		        XMLPropertyState aNewProperty( -1 );
362                 sal_uInt32 i = 0;
363                 while (nResultCount > 0 && i < nCount)
364 		        {
365                     if (pResults->Name == aPropIter->GetApiName())
366                     {
367 			            aNewProperty.mnIndex = -1;
368 			            aNewProperty.maValue = pResults->Value;
369 
370 			            for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
371 				            aIndexItr != aPropIter->GetIndexes().end();
372 				            ++aIndexItr )
373 			            {
374 				            aNewProperty.mnIndex = *aIndexItr;
375 				            aPropStates.AddPropertyState( aNewProperty );
376 			            }
377     			        ++pResults;
378                         --nResultCount;
379                     }
380 		            ++aPropIter;
381                     ++i;
382                 }
383 		    }
384         }
385         else
386         {
387             Sequence < beans::GetPropertyTolerantResult > aResults(xTolPropSet->getPropertyValuesTolerant(rApiNames));
388             OSL_ENSURE( rApiNames.getLength() == aResults.getLength(), "wrong implemented XTolerantMultiPropertySet" );
389 		    const beans::GetPropertyTolerantResult *pResults = aResults.getConstArray();
390 		    FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
391 		    XMLPropertyState aNewProperty( -1 );
392             sal_uInt32 nResultCount(aResults.getLength());
393             OSL_ENSURE( nCount == nResultCount, "wrong implemented XTolerantMultiPropertySet??" );
394 		    for( sal_uInt32 i = 0; i < nResultCount; ++i )
395 		    {
396                 if ((pResults->Result == beans::TolerantPropertySetResultType::SUCCESS) &&
397                     ((pResults->State == PropertyState_DIRECT_VALUE) || (pResults->State == PropertyState_DEFAULT_VALUE)))
398                 {
399 			        aNewProperty.mnIndex = -1;
400 			        aNewProperty.maValue = pResults->Value;
401 
402 			        for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
403 				        aIndexItr != aPropIter->GetIndexes().end();
404 				        ++aIndexItr )
405 			        {
406 				        aNewProperty.mnIndex = *aIndexItr;
407 				        aPropStates.AddPropertyState( aNewProperty );
408 			        }
409                 }
410     			++pResults;
411     		    ++aPropIter;
412 		    }
413         }
414     }
415     else
416     {
417 	    Sequence < PropertyState > aStates;
418 	    const PropertyState *pStates = 0;
419 	    Reference< XPropertyState > xPropState( rPropSet, UNO_QUERY );
420    	    if( xPropState.is() )
421 	    {
422 		    aStates = xPropState->getPropertyStates( rApiNames );
423 		    pStates = aStates.getConstArray();
424 	    }
425 
426 	    Reference < XMultiPropertySet > xMultiPropSet( rPropSet, UNO_QUERY );
427 	    if( xMultiPropSet.is() && !bDefault )
428 	    {
429 		    Sequence < Any > aValues;
430 		    if( pStates )
431 		    {
432 			    // step 1: get value count
433 			    sal_uInt32 nValueCount = 0;
434 			    sal_uInt32 i;
435 
436 			    for( i = 0; i < nCount; ++i, ++pStates )
437 			    {
438 				    if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
439 					    nValueCount++;
440 			    }
441 
442 			    if( nValueCount )
443 			    {
444 				    // step 2: collect property names
445 				    Sequence < OUString > aAPINames( nValueCount );
446 				    OUString *pAPINames = aAPINames.getArray();
447 
448                     ::std::vector< FilterPropertyInfoList_Impl::iterator > aPropIters;
449                     aPropIters.reserve( nValueCount );
450 
451 				    FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
452     				OSL_ENSURE(aItr != aPropInfos.end(),"Invalid iterator!");
453 
454 				    pStates = aStates.getConstArray();
455 				    i = 0;
456 				    while( i < nValueCount )
457 				    {
458 					    if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
459 					    {
460 						    *pAPINames++ = aItr->GetApiName();
461                             aPropIters.push_back( aItr );
462 						    ++i;
463 					    }
464                         ++aItr;
465 					    ++pStates;
466 				    }
467 
468 				    aValues = xMultiPropSet->getPropertyValues( aAPINames );
469 				    const Any *pValues = aValues.getConstArray();
470 
471                     ::std::vector< FilterPropertyInfoList_Impl::iterator >::const_iterator
472                         pPropIter = aPropIters.begin();
473 
474 				    XMLPropertyState aNewProperty( -1 );
475 				    for( i = 0; i < nValueCount; i++ )
476 				    {
477 					    aNewProperty.mnIndex = -1;
478 					    aNewProperty.maValue = *pValues;
479 
480                         const ::std::list< sal_uInt32 >& rIndexes( (*pPropIter)->GetIndexes() );
481 					    for (   std::list<sal_uInt32>::const_iterator aIndexItr = rIndexes.begin();
482 						        aIndexItr != rIndexes.end();
483 						        ++aIndexItr
484                             )
485 					    {
486 						    aNewProperty.mnIndex = *aIndexItr;
487 						    aPropStates.AddPropertyState( aNewProperty );
488 					    }
489 
490 					    ++pPropIter;
491 					    ++pValues;
492 				    }
493 			    }
494 		    }
495 		    else
496 		    {
497 			    aValues = xMultiPropSet->getPropertyValues( rApiNames );
498 			    const Any *pValues = aValues.getConstArray();
499 
500 			    FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
501 			    for(sal_uInt32 i = 0; i < nCount; i++ )
502 			    {
503 				    // The value is stored in the PropertySet itself, add to list.
504 				    XMLPropertyState aNewProperty( -1 );
505 				    aNewProperty.maValue = *pValues;
506 				    ++pValues;
507 				    for( std::list<sal_uInt32>::iterator aIndexItr =
508 						    aItr->GetIndexes().begin();
509 					    aIndexItr != aItr->GetIndexes().end();
510 					    aIndexItr++ )
511 				    {
512 					    aNewProperty.mnIndex = *aIndexItr;
513 					    aPropStates.AddPropertyState( aNewProperty );
514 				    }
515 				    aItr++;
516 			    }
517 		    }
518 	    }
519 	    else
520 	    {
521 		    FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
522 		    for(sal_uInt32 i = 0; i < nCount; i++ )
523 		    {
524 			    sal_Bool bDirectValue =
525 				    !pStates || *pStates == PropertyState_DIRECT_VALUE;
526 			    if( bDirectValue || bDefault )
527 			    {
528 				    // The value is stored in the PropertySet itself, add to list.
529 				    sal_Bool bGotValue = sal_False;
530 				    XMLPropertyState aNewProperty( -1 );
531 				    for( std::list<sal_uInt32>::const_iterator aIndexItr =
532 						    aItr->GetIndexes().begin();
533 					    aIndexItr != aItr->GetIndexes().end();
534 					    aIndexItr++ )
535 				    {
536 					    if( bDirectValue ||
537 						    (rPropMapper->GetEntryFlags( *aIndexItr ) &
538 										    MID_FLAG_DEFAULT_ITEM_EXPORT) != 0 )
539 					    {
540 						    try
541 						    {
542 							    if( !bGotValue )
543 							    {
544 								    aNewProperty.maValue =
545 									    rPropSet->getPropertyValue( aItr->GetApiName() );
546 								    bGotValue = sal_True;
547 							    }
548 							    aNewProperty.mnIndex = *aIndexItr;
549 							    aPropStates.AddPropertyState( aNewProperty );
550 						    }
551 						    catch( UnknownPropertyException& )
552 						    {
553 							    // might be a problem of getImplemenetationId
554 							    OSL_ENSURE( sal_False, "unknown property in getPropertyValue" );
555 						    }
556 
557 					    }
558 				    }
559 			    }
560 
561 			    aItr++;
562 			    if( pStates )
563 				    pStates++;
564 		    }
565 	    }
566     }
567 	aPropStates.FillPropertyStateVector(rPropStates);
568 }
569 
570 ///////////////////////////////////////////////////////////////////////////////
571 //
572 // ctor/dtor , class SvXMLExportPropertyMapper
573 //
574 
SvXMLExportPropertyMapper(const UniReference<XMLPropertySetMapper> & rMapper)575 SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
576 		const UniReference< XMLPropertySetMapper >& rMapper ) :
577 	pCache( 0 ),
578 	maPropMapper( rMapper )
579 {
580 }
581 
~SvXMLExportPropertyMapper()582 SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
583 {
584 	delete pCache;
585 	mxNextMapper = 0;
586 }
587 
ChainExportMapper(const UniReference<SvXMLExportPropertyMapper> & rMapper)588 void SvXMLExportPropertyMapper::ChainExportMapper(
589 		const UniReference< SvXMLExportPropertyMapper>& rMapper )
590 {
591 	// add map entries from rMapper to current map
592 	maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
593 	// rMapper uses the same map as 'this'
594 	rMapper->maPropMapper = maPropMapper;
595 
596 	// set rMapper as last mapper in current chain
597 	UniReference< SvXMLExportPropertyMapper > xNext = mxNextMapper;
598 	if( xNext.is())
599 	{
600 		while( xNext->mxNextMapper.is())
601 			xNext = xNext->mxNextMapper;
602 		xNext->mxNextMapper = rMapper;
603 	}
604 	else
605 		mxNextMapper = rMapper;
606 
607 	// if rMapper was already chained, correct
608 	// map pointer of successors
609 	xNext = rMapper;
610 
611 	while( xNext->mxNextMapper.is())
612 	{
613 		xNext = xNext->mxNextMapper;
614 		xNext->maPropMapper = maPropMapper;
615 	}
616 }
617 
618 
_Filter(const Reference<XPropertySet> xPropSet,const sal_Bool bDefault) const619 vector< XMLPropertyState > SvXMLExportPropertyMapper::_Filter(
620 		const Reference< XPropertySet > xPropSet,
621 		const sal_Bool bDefault ) const
622 {
623 	vector< XMLPropertyState > aPropStateArray;
624 
625 	// Retrieve XPropertySetInfo and XPropertyState
626 	Reference< XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
627 	if( !xInfo.is() )
628 		return aPropStateArray;
629 
630 	sal_Int32 nProps = maPropMapper->GetEntryCount();
631 
632 	FilterPropertiesInfo_Impl *pFilterInfo = 0;
633 
634 	Reference < XTypeProvider > xTypeProv( xPropSet, UNO_QUERY );
635 	Sequence< sal_Int8 > aImplId;
636 	if( xTypeProv.is() )
637 	{
638 		aImplId = xTypeProv->getImplementationId();
639 		if( aImplId.getLength() == 16 )
640 		{
641 			if( pCache )
642 			{
643 				// The key must not be created outside this block, because it
644 				// keeps a reference to the property set info.
645 				PropertySetInfoKey aKey( xInfo, aImplId );
646 				FilterPropertiesInfos_Impl::iterator aIter =
647 					pCache->find( aKey );
648 				if( aIter != pCache->end() )
649 					pFilterInfo = (*aIter).second;
650 			}
651 		}
652 	}
653 
654 	sal_Bool bDelInfo = sal_False;
655 	if( !pFilterInfo )
656 	{
657 		pFilterInfo = new FilterPropertiesInfo_Impl;
658 		for( sal_Int32 i=0; i < nProps; i++ )
659 		{
660 			// Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
661 			// Does the PropertySet contain name of mpEntries-array ?
662 			const OUString& rAPIName = maPropMapper->GetEntryAPIName( i );
663 			const sal_Int32 nFlags = maPropMapper->GetEntryFlags( i );
664 			if( (0 == (nFlags & MID_FLAG_NO_PROPERTY_EXPORT)) &&
665 				( (0 != (nFlags & MID_FLAG_MUST_EXIST)) ||
666 				  xInfo->hasPropertyByName( rAPIName ) ) )
667             {
668                 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
669                 const SvtSaveOptions::ODFDefaultVersion nEarliestODFVersionForExport(
670                         maPropMapper->GetEarliestODFVersionForExport( i ) );
671                 if( nCurrentVersion >= nEarliestODFVersionForExport
672                         || nCurrentVersion == SvtSaveOptions::ODFVER_UNKNOWN
673                         || nEarliestODFVersionForExport == SvtSaveOptions::ODFVER_UNKNOWN )
674                     pFilterInfo->AddProperty(rAPIName, i);
675             }
676 		}
677 
678 		if( xTypeProv.is() && aImplId.getLength() == 16 )
679 		{
680 			// Check whether the property set info is destroyed if it is
681 			// assigned to a weak reference only. If it is destroyed, then
682 			// every instance of getPropertySetInfo returns a new object.
683 			// Such property set infos must not be cached.
684 			WeakReference < XPropertySetInfo > xWeakInfo( xInfo );
685 			xInfo = 0;
686 			xInfo = xWeakInfo;
687 			if( xInfo.is() )
688 			{
689 				if( !pCache )
690 					((SvXMLExportPropertyMapper *)this)->pCache =
691 						new FilterPropertiesInfos_Impl;
692 				PropertySetInfoKey aKey( xInfo, aImplId );
693 				(*pCache)[aKey] = pFilterInfo;
694 			}
695 			else
696 				bDelInfo = sal_True;
697 		}
698 		else
699 		{
700 			OSL_ENSURE(sal_False, "here is no TypeProvider or the ImplId is wrong");
701 			bDelInfo = sal_True;
702 		}
703 	}
704 
705 	if( pFilterInfo->GetPropertyCount() )
706 	{
707 		try
708 		{
709 			pFilterInfo->FillPropertyStateArray(aPropStateArray,
710 												xPropSet, maPropMapper,
711 												bDefault);
712 		}
713 		catch( UnknownPropertyException& )
714 		{
715 			// might be a problem of getImplemenetationId
716 			OSL_ENSURE( sal_False, "unknown property in getPropertyStates" );
717 		}
718 	}
719 
720 	// Call centext-filter
721 	if( !aPropStateArray.empty() )
722 		ContextFilter( aPropStateArray, xPropSet );
723 
724 	// Have to do if we change from a vector to a list or something like that
725 	/*vector< XMLPropertyState >::iterator aItr = aPropStateArray.begin();
726 	while (aItr != aPropStateArray.end())
727 	{
728 		if (aItr->mnIndex == -1)
729 			aItr = aPropStateArray.erase(aItr);
730 		else
731 			aItr++;
732 	}*/
733 
734 	if( bDelInfo )
735 		delete pFilterInfo;
736 
737 	return aPropStateArray;
738 }
739 
ContextFilter(vector<XMLPropertyState> & rProperties,Reference<XPropertySet> rPropSet) const740 void SvXMLExportPropertyMapper::ContextFilter(
741 		vector< XMLPropertyState >& rProperties,
742 		Reference< XPropertySet > rPropSet ) const
743 {
744 	// Derived class could implement this.
745 	if( mxNextMapper.is() )
746 		mxNextMapper->ContextFilter( rProperties, rPropSet );
747 }
748 
749 ///////////////////////////////////////////////////////////////////////////
750 //
751 // Compares two Sequences of XMLPropertyState:
752 //	1.Number of elements equal ?
753 //	2.Index of each element equal ? (So I know whether the propertynames are the same)
754 //	3.Value of each element equal ?
755 //
Equals(const vector<XMLPropertyState> & aProperties1,const vector<XMLPropertyState> & aProperties2) const756 sal_Bool SvXMLExportPropertyMapper::Equals(
757 		const vector< XMLPropertyState >& aProperties1,
758 	    const vector< XMLPropertyState >& aProperties2 ) const
759 {
760 	sal_Bool bRet = sal_True;
761 	sal_uInt32 nCount = aProperties1.size();
762 
763 	if( nCount == aProperties2.size() )
764 	{
765 		sal_uInt32 nIndex = 0;
766 		while( bRet && nIndex < nCount )
767 		{
768 			const XMLPropertyState& rProp1 = aProperties1[ nIndex ];
769 			const XMLPropertyState& rProp2 = aProperties2[ nIndex ];
770 
771 			// Compare index. If equal, compare value
772 			if( rProp1.mnIndex == rProp2.mnIndex )
773 			{
774 				if( rProp1.mnIndex != -1 )
775 				{
776 					// Now compare values
777 					if( ( maPropMapper->GetEntryType( rProp1.mnIndex ) &
778 						  XML_TYPE_BUILDIN_CMP ) != 0 )
779 						// simple type ( binary compare )
780 						bRet = ( rProp1.maValue == rProp2.maValue );
781 					else
782 						// complex type ( ask for compare-function )
783 						bRet = maPropMapper->GetPropertyHandler(
784 									rProp1.mnIndex )->equals( rProp1.maValue,
785 															  rProp2.maValue );
786 				}
787 			}
788 			else
789 				bRet = sal_False;
790 
791 			nIndex++;
792 		}
793 	}
794 	else
795 		bRet = sal_False;
796 
797 	return bRet;
798 }
799 
800 
801 /** fills the given attribute list with the items in the given set
802 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
803 		const ::std::vector< XMLPropertyState >& rProperties,
804 		const SvXMLUnitConverter& rUnitConverter,
805 		const SvXMLNamespaceMap& rNamespaceMap,
806 		sal_uInt16 nFlags ) const
807 {
808 	_exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
809 				nFlags, 0, -1, -1 );
810 }
811 
812 
813 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
814 		const ::std::vector< XMLPropertyState >& rProperties,
815 		const SvXMLUnitConverter& rUnitConverter,
816 		const SvXMLNamespaceMap& rNamespaceMap,
817 		sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
818 		sal_uInt16 nFlags ) const
819 {
820 	_exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
821 				nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
822 }
823 */
824 
825 
exportXML(SvXMLAttributeList & rAttrList,const XMLPropertyState & rProperty,const SvXMLUnitConverter & rUnitConverter,const SvXMLNamespaceMap & rNamespaceMap,sal_uInt16 nFlags) const826 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
827 		const XMLPropertyState& rProperty,
828 		const SvXMLUnitConverter& rUnitConverter,
829 		const SvXMLNamespaceMap& rNamespaceMap,
830 		sal_uInt16 nFlags ) const
831 {
832 	if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
833 				MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
834 		_exportXML( rAttrList, rProperty, rUnitConverter, rNamespaceMap,
835 					nFlags );
836 }
837 
exportXML(SvXMLExport & rExport,const::std::vector<XMLPropertyState> & rProperties,sal_uInt16 nFlags) const838 void SvXMLExportPropertyMapper::exportXML(
839         SvXMLExport& rExport,
840 		const ::std::vector< XMLPropertyState >& rProperties,
841 		sal_uInt16 nFlags ) const
842 {
843 	exportXML( rExport, rProperties, -1, -1,  nFlags );
844 }
845 
exportXML(SvXMLExport & rExport,const::std::vector<XMLPropertyState> & rProperties,sal_Int32 nPropMapStartIdx,sal_Int32 nPropMapEndIdx,sal_uInt16 nFlags) const846 void SvXMLExportPropertyMapper::exportXML(
847         SvXMLExport& rExport,
848 		const ::std::vector< XMLPropertyState >& rProperties,
849 		sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
850 		sal_uInt16 nFlags ) const
851 {
852 	sal_uInt16 nPropTypeFlags = 0;
853 	for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i )
854 	{
855 		sal_uInt16 nPropType = aPropTokens[i].nType;
856 		if( 0==i || (nPropTypeFlags & (1 << nPropType)) != 0 )
857 		{
858 			SvUShorts aIndexArray;
859 
860 			_exportXML( nPropType, nPropTypeFlags,
861 						rExport.GetAttrList(), rProperties,
862 						rExport.GetMM100UnitConverter(),
863 						rExport.GetNamespaceMap(),
864 						nFlags, &aIndexArray,
865 						nPropMapStartIdx, nPropMapEndIdx );
866 
867 			if( rExport.GetAttrList().getLength() > 0L ||
868 				(nFlags & XML_EXPORT_FLAG_EMPTY) != 0 ||
869 				aIndexArray.Count() != 0 )
870 			{
871 				SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE,
872 								  aPropTokens[i].eToken,
873 								  (nFlags & XML_EXPORT_FLAG_IGN_WS) != 0,
874 								  sal_False );
875 
876 				exportElementItems( rExport, rProperties, nFlags, aIndexArray );
877 			}
878 		}
879 	}
880 }
881 
882 /** this method is called for every item that has the
883     MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
handleSpecialItem(SvXMLAttributeList & rAttrList,const XMLPropertyState & rProperty,const SvXMLUnitConverter & rUnitConverter,const SvXMLNamespaceMap & rNamespaceMap,const::std::vector<XMLPropertyState> * pProperties,sal_uInt32 nIdx) const884 void SvXMLExportPropertyMapper::handleSpecialItem(
885 		SvXMLAttributeList& rAttrList,
886 		const XMLPropertyState& rProperty,
887 		const SvXMLUnitConverter& rUnitConverter,
888 		const SvXMLNamespaceMap& rNamespaceMap,
889 		const ::std::vector< XMLPropertyState > *pProperties,
890 		sal_uInt32 nIdx ) const
891 {
892 	OSL_ENSURE( mxNextMapper.is(), "special item not handled in xml export" );
893 	if( mxNextMapper.is() )
894 		mxNextMapper->handleSpecialItem( rAttrList, rProperty, rUnitConverter,
895 										rNamespaceMap, pProperties, nIdx );
896 }
897 
898 /** this method is called for every item that has the
899     MID_FLAG_ELEMENT_EXPORT flag set */
handleElementItem(SvXMLExport & rExport,const XMLPropertyState & rProperty,sal_uInt16 nFlags,const::std::vector<XMLPropertyState> * pProperties,sal_uInt32 nIdx) const900 void SvXMLExportPropertyMapper::handleElementItem(
901         SvXMLExport& rExport,
902 		const XMLPropertyState& rProperty,
903 		sal_uInt16 nFlags,
904 		const ::std::vector< XMLPropertyState > *pProperties,
905 		sal_uInt32 nIdx ) const
906 {
907 	OSL_ENSURE( mxNextMapper.is(), "element item not handled in xml export" );
908 	if( mxNextMapper.is() )
909 		mxNextMapper->handleElementItem( rExport, rProperty, nFlags,
910                                          pProperties, nIdx );
911 }
912 
913 ///////////////////////////////////////////////////////////////////////////////
914 //
915 // protected methods
916 //
917 
918 /** fills the given attribute list with the items in the given set */
_exportXML(sal_uInt16 nPropType,sal_uInt16 & rPropTypeFlags,SvXMLAttributeList & rAttrList,const::std::vector<XMLPropertyState> & rProperties,const SvXMLUnitConverter & rUnitConverter,const SvXMLNamespaceMap & rNamespaceMap,sal_uInt16 nFlags,SvUShorts * pIndexArray,sal_Int32 nPropMapStartIdx,sal_Int32 nPropMapEndIdx) const919 void SvXMLExportPropertyMapper::_exportXML(
920 		sal_uInt16 nPropType, sal_uInt16& rPropTypeFlags,
921 		SvXMLAttributeList& rAttrList,
922 		const ::std::vector< XMLPropertyState >& rProperties,
923 		const SvXMLUnitConverter& rUnitConverter,
924 		const SvXMLNamespaceMap& rNamespaceMap,
925 		sal_uInt16 nFlags,
926 		SvUShorts* pIndexArray,
927 		sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx ) const
928 {
929 	const sal_uInt32 nCount = rProperties.size();
930 	sal_uInt32 nIndex = 0;
931 
932 	if( -1 == nPropMapStartIdx )
933 		nPropMapStartIdx = 0;
934 	if( -1 == nPropMapEndIdx )
935 		nPropMapEndIdx = maPropMapper->GetEntryCount();
936 
937 	while( nIndex < nCount )
938 	{
939 		sal_Int32 nPropMapIdx = rProperties[nIndex].mnIndex;
940 		if( nPropMapIdx >= nPropMapStartIdx &&
941 			nPropMapIdx < nPropMapEndIdx  )// valid entry?
942 		{
943 			sal_uInt32 nEFlags = maPropMapper->GetEntryFlags( nPropMapIdx );
944 			sal_uInt16 nEPType = GET_PROP_TYPE(nEFlags);
945 			OSL_ENSURE( nEPType >= (XML_TYPE_PROP_START>>XML_TYPE_PROP_SHIFT),
946 						"no prop type sepcified" );
947 			rPropTypeFlags |= (1 << nEPType);
948 			if( nEPType == nPropType )
949 			{
950 				// we have a valid map entry here, so lets use it...
951 				if( ( nEFlags & MID_FLAG_ELEMENT_ITEM_EXPORT ) != 0 )
952 				{
953 					// element items do not add any properties,
954 					// we export it later
955 					if( pIndexArray )
956 						pIndexArray->Insert( (sal_uInt16)nIndex, pIndexArray->Count() );
957 				}
958 				else
959 				{
960 					_exportXML( rAttrList, rProperties[nIndex], rUnitConverter,
961 								rNamespaceMap, nFlags, &rProperties, nIndex );
962 				}
963 			}
964 		}
965 
966 		nIndex++;
967 	}
968 }
969 
_exportXML(SvXMLAttributeList & rAttrList,const XMLPropertyState & rProperty,const SvXMLUnitConverter & rUnitConverter,const SvXMLNamespaceMap & rNamespaceMap,sal_uInt16,const::std::vector<XMLPropertyState> * pProperties,sal_uInt32 nIdx) const970 void SvXMLExportPropertyMapper::_exportXML(
971 		SvXMLAttributeList& rAttrList,
972 		const XMLPropertyState& rProperty,
973 		const SvXMLUnitConverter& rUnitConverter,
974 		const SvXMLNamespaceMap& rNamespaceMap,
975 		sal_uInt16 /*nFlags*/,
976 		const ::std::vector< XMLPropertyState > *pProperties,
977 		sal_uInt32 nIdx ) const
978 {
979 	OUString sCDATA( GetXMLToken(XML_CDATA) );
980 
981 	if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
982 				MID_FLAG_SPECIAL_ITEM_EXPORT ) != 0 )
983 	{
984 		uno::Reference< container::XNameContainer > xAttrContainer;
985 		if( (rProperty.maValue >>= xAttrContainer) && xAttrContainer.is() )
986 		{
987 			SvXMLNamespaceMap *pNewNamespaceMap = 0;
988 			const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;
989 
990 			uno::Sequence< OUString > aAttribNames( xAttrContainer->getElementNames() );
991 			const OUString* pAttribName = aAttribNames.getConstArray();
992 
993 			const sal_Int32 nCount = aAttribNames.getLength();
994 
995 			OUStringBuffer sNameBuffer;
996 			xml::AttributeData aData;
997 			for( sal_Int32 i=0; i < nCount; i++, pAttribName++ )
998 			{
999 				xAttrContainer->getByName( *pAttribName ) >>= aData;
1000 				OUString sAttribName( *pAttribName );
1001 
1002 				// extract namespace prefix from attribute name if it exists
1003 				OUString sPrefix;
1004 				const sal_Int32 nColonPos =
1005 					pAttribName->indexOf( sal_Unicode(':') );
1006 				if( nColonPos != -1 )
1007 					sPrefix = pAttribName->copy( 0, nColonPos );
1008 
1009 				if( sPrefix.getLength() )
1010 				{
1011 					OUString sNamespace( aData.Namespace );
1012 
1013 					// if the prefix isn't defined yet or has another meaning,
1014 					// we have to redefine it now.
1015 					sal_uInt16 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
1016 					if( USHRT_MAX == nKey || pNamespaceMap->GetNameByKey( nKey ) != sNamespace )
1017 					{
1018 						sal_Bool bAddNamespace = sal_False;
1019 						if( USHRT_MAX == nKey )
1020 						{
1021 							// The prefix is unused, so it is sufficient
1022 							// to add it to the namespace map.
1023 							bAddNamespace = sal_True;
1024 						}
1025 						else
1026 						{
1027 							// check if there is a prefix registered for the
1028 							// namepsace URI
1029 							nKey = pNamespaceMap->GetKeyByName( sNamespace );
1030 							if( XML_NAMESPACE_UNKNOWN == nKey )
1031 							{
1032 								// There is no prefix for the namespace, so
1033 								// we have to generate one and have to add it.
1034 								sal_Int32 n=0;
1035 								OUString sOrigPrefix( sPrefix );
1036 								do
1037 								{
1038 									sNameBuffer.append( sOrigPrefix );
1039 									sNameBuffer.append( ++n );
1040 									sPrefix = sNameBuffer.makeStringAndClear();
1041 									nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
1042 								}
1043 								while( nKey != USHRT_MAX );
1044 
1045 								bAddNamespace = sal_True;
1046 							}
1047 							else
1048 							{
1049 								// If there is a prefix for the namespace,
1050 								// we reuse that.
1051 								sPrefix = pNamespaceMap->GetPrefixByKey( nKey );
1052 							}
1053 							// In any case, the attribute name has to be adapted.
1054 							sNameBuffer.append( sPrefix );
1055 							sNameBuffer.append( sal_Unicode(':') );
1056 							sNameBuffer.append( pAttribName->copy( nColonPos+1 ) );
1057 							sAttribName = sNameBuffer.makeStringAndClear();
1058 						}
1059 
1060 						if( bAddNamespace )
1061 						{
1062 							if( !pNewNamespaceMap )
1063 							{
1064 								pNewNamespaceMap = new SvXMLNamespaceMap( rNamespaceMap );
1065 								pNamespaceMap = pNewNamespaceMap;
1066 							}
1067 							pNewNamespaceMap->Add( sPrefix, sNamespace );
1068 							sNameBuffer.append( GetXMLToken(XML_XMLNS) );
1069 							sNameBuffer.append( sal_Unicode(':') );
1070 							sNameBuffer.append( sPrefix );
1071 							rAttrList.AddAttribute( sNameBuffer.makeStringAndClear(),
1072 													sNamespace );
1073 						}
1074 					}
1075 				}
1076 				OUString sOldValue( rAttrList.getValueByName( sAttribName ) );
1077 				OSL_ENSURE( sOldValue.getLength() == 0, "alien attribute exists already" );
1078                 OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out");
1079 				if( !sOldValue.getLength() )
1080 					rAttrList.AddAttribute( sAttribName, aData.Value );
1081 			}
1082 
1083 			delete pNewNamespaceMap;
1084 		}
1085 		else
1086 		{
1087 			handleSpecialItem( rAttrList, rProperty, rUnitConverter,
1088 							   rNamespaceMap, pProperties, nIdx );
1089 		}
1090 	}
1091 	else if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
1092 					MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
1093 	{
1094 		OUString aValue;
1095 		const OUString sName( rNamespaceMap.GetQNameByKey(
1096 					maPropMapper->GetEntryNameSpace( rProperty.mnIndex ),
1097 				    maPropMapper->GetEntryXMLName( rProperty.mnIndex ) ) );
1098 
1099 		sal_Bool bRemove = sal_False;
1100 		if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
1101 					MID_FLAG_MERGE_ATTRIBUTE ) != 0 )
1102 		{
1103 			aValue = rAttrList.getValueByName( sName );
1104 			bRemove = sal_True; //aValue.getLength() != 0;
1105 		}
1106 
1107 		if( maPropMapper->exportXML( aValue, rProperty, rUnitConverter ) )
1108 		{
1109 			if( bRemove )
1110 				rAttrList.RemoveAttribute( sName );
1111 			rAttrList.AddAttribute( sName, aValue );
1112 		}
1113 	}
1114 }
1115 
exportElementItems(SvXMLExport & rExport,const::std::vector<XMLPropertyState> & rProperties,sal_uInt16 nFlags,const SvUShorts & rIndexArray) const1116 void SvXMLExportPropertyMapper::exportElementItems(
1117         SvXMLExport& rExport,
1118 		const ::std::vector< XMLPropertyState >& rProperties,
1119 		sal_uInt16 nFlags,
1120 		const SvUShorts& rIndexArray ) const
1121 {
1122 	const sal_uInt16 nCount = rIndexArray.Count();
1123 
1124 	sal_Bool bItemsExported = sal_False;
1125 	OUString sWS( GetXMLToken(XML_WS) );
1126 	for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ )
1127 	{
1128 		const sal_uInt16 nElement = rIndexArray.GetObject( nIndex );
1129 
1130 		OSL_ENSURE( 0 != ( maPropMapper->GetEntryFlags(
1131 				rProperties[nElement].mnIndex ) & MID_FLAG_ELEMENT_ITEM_EXPORT),
1132 				"wrong mid flag!" );
1133 
1134 		rExport.IgnorableWhitespace();
1135 		handleElementItem( rExport, rProperties[nElement],
1136                            nFlags, &rProperties, nElement );
1137 		bItemsExported = sal_True;
1138 	}
1139 
1140 	if( bItemsExported )
1141 		rExport.IgnorableWhitespace();
1142 }
1143