xref: /trunk/main/xmloff/source/meta/xmlmetae.cxx (revision 63bba73c)
1*63bba73cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*63bba73cSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*63bba73cSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*63bba73cSAndrew Rist  * distributed with this work for additional information
6*63bba73cSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*63bba73cSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*63bba73cSAndrew Rist  * "License"); you may not use this file except in compliance
9*63bba73cSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*63bba73cSAndrew Rist  *
11*63bba73cSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*63bba73cSAndrew Rist  *
13*63bba73cSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*63bba73cSAndrew Rist  * software distributed under the License is distributed on an
15*63bba73cSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*63bba73cSAndrew Rist  * KIND, either express or implied.  See the License for the
17*63bba73cSAndrew Rist  * specific language governing permissions and limitations
18*63bba73cSAndrew Rist  * under the License.
19*63bba73cSAndrew Rist  *
20*63bba73cSAndrew Rist  *************************************************************/
21*63bba73cSAndrew Rist 
22*63bba73cSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_xmloff.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <tools/debug.hxx>
28cdf0e10cSrcweir #include <tools/inetdef.hxx>
29cdf0e10cSrcweir #include <i18npool/mslangid.hxx>
30cdf0e10cSrcweir #include <tools/urlobj.hxx>
31cdf0e10cSrcweir #include <tools/time.hxx>
32cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <xmloff/xmlmetae.hxx>
35cdf0e10cSrcweir #include <xmloff/xmlexp.hxx>
36cdf0e10cSrcweir #include <xmloff/xmluconv.hxx>
37cdf0e10cSrcweir #include <xmloff/nmspmap.hxx>
38cdf0e10cSrcweir #include "xmloff/xmlnmspe.hxx"
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include <com/sun/star/beans/XPropertyAccess.hpp>
41cdf0e10cSrcweir #include <com/sun/star/beans/StringPair.hpp>
42cdf0e10cSrcweir #include <com/sun/star/xml/dom/XDocument.hpp>
43cdf0e10cSrcweir #include <com/sun/star/xml/sax/XSAXSerializable.hpp>
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #include <comphelper/sequenceasvector.hxx>
46cdf0e10cSrcweir #include <unotools/docinfohelper.hxx>
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include <string.h>
49cdf0e10cSrcweir 
50cdf0e10cSrcweir 
51cdf0e10cSrcweir using namespace com::sun::star;
52cdf0e10cSrcweir using namespace ::xmloff::token;
53cdf0e10cSrcweir 
54cdf0e10cSrcweir 
55cdf0e10cSrcweir //-------------------------------------------------------------------------
56cdf0e10cSrcweir 
lcl_AddTwoDigits(rtl::OUStringBuffer & rStr,sal_Int32 nVal)57cdf0e10cSrcweir void lcl_AddTwoDigits( rtl::OUStringBuffer& rStr, sal_Int32 nVal )
58cdf0e10cSrcweir {
59cdf0e10cSrcweir     if ( nVal < 10 )
60cdf0e10cSrcweir         rStr.append( sal_Unicode('0') );
61cdf0e10cSrcweir     rStr.append( nVal );
62cdf0e10cSrcweir }
63cdf0e10cSrcweir 
64cdf0e10cSrcweir rtl::OUString
GetISODateTimeString(const util::DateTime & rDateTime)65cdf0e10cSrcweir SvXMLMetaExport::GetISODateTimeString( const util::DateTime& rDateTime )
66cdf0e10cSrcweir {
67cdf0e10cSrcweir     //  return ISO date string "YYYY-MM-DDThh:mm:ss"
68cdf0e10cSrcweir 
69cdf0e10cSrcweir     rtl::OUStringBuffer sTmp;
70cdf0e10cSrcweir     sTmp.append( (sal_Int32) rDateTime.Year );
71cdf0e10cSrcweir     sTmp.append( sal_Unicode('-') );
72cdf0e10cSrcweir     lcl_AddTwoDigits( sTmp, rDateTime.Month );
73cdf0e10cSrcweir     sTmp.append( sal_Unicode('-') );
74cdf0e10cSrcweir     lcl_AddTwoDigits( sTmp, rDateTime.Day );
75cdf0e10cSrcweir     sTmp.append( sal_Unicode('T') );
76cdf0e10cSrcweir     lcl_AddTwoDigits( sTmp, rDateTime.Hours );
77cdf0e10cSrcweir     sTmp.append( sal_Unicode(':') );
78cdf0e10cSrcweir     lcl_AddTwoDigits( sTmp, rDateTime.Minutes );
79cdf0e10cSrcweir     sTmp.append( sal_Unicode(':') );
80cdf0e10cSrcweir     lcl_AddTwoDigits( sTmp, rDateTime.Seconds );
81cdf0e10cSrcweir 
82cdf0e10cSrcweir     return sTmp.makeStringAndClear();
83cdf0e10cSrcweir }
84cdf0e10cSrcweir 
85cdf0e10cSrcweir //-------------------------------------------------------------------------
86cdf0e10cSrcweir 
SimpleStringElement(const rtl::OUString & rText,sal_uInt16 nNamespace,enum XMLTokenEnum eElementName)87cdf0e10cSrcweir void SvXMLMetaExport::SimpleStringElement( const rtl::OUString& rText,
88cdf0e10cSrcweir         sal_uInt16 nNamespace, enum XMLTokenEnum eElementName )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir     if ( rText.getLength() ) {
91cdf0e10cSrcweir         SvXMLElementExport aElem( mrExport, nNamespace, eElementName,
92cdf0e10cSrcweir                                   sal_True, sal_False );
93cdf0e10cSrcweir         mrExport.Characters( rText );
94cdf0e10cSrcweir     }
95cdf0e10cSrcweir }
96cdf0e10cSrcweir 
SimpleDateTimeElement(const util::DateTime & rDate,sal_uInt16 nNamespace,enum XMLTokenEnum eElementName)97cdf0e10cSrcweir void SvXMLMetaExport::SimpleDateTimeElement( const util::DateTime & rDate,
98cdf0e10cSrcweir         sal_uInt16 nNamespace, enum XMLTokenEnum eElementName )
99cdf0e10cSrcweir {
100cdf0e10cSrcweir     if (rDate.Month != 0) { // invalid dates are 0-0-0
101cdf0e10cSrcweir         rtl::OUString sValue = GetISODateTimeString( rDate );
102cdf0e10cSrcweir         if ( sValue.getLength() ) {
103cdf0e10cSrcweir             SvXMLElementExport aElem( mrExport, nNamespace, eElementName,
104cdf0e10cSrcweir                                       sal_True, sal_False );
105cdf0e10cSrcweir             mrExport.Characters( sValue );
106cdf0e10cSrcweir         }
107cdf0e10cSrcweir     }
108cdf0e10cSrcweir }
109cdf0e10cSrcweir 
_MExport()110cdf0e10cSrcweir void SvXMLMetaExport::_MExport()
111cdf0e10cSrcweir {
112cdf0e10cSrcweir     //  generator
113cdf0e10cSrcweir     {
114cdf0e10cSrcweir         SvXMLElementExport aElem( mrExport, XML_NAMESPACE_META, XML_GENERATOR,
115cdf0e10cSrcweir                                   sal_True, sal_True );
116cdf0e10cSrcweir         mrExport.Characters( ::utl::DocInfoHelper::GetGeneratorString() );
117cdf0e10cSrcweir     }
118cdf0e10cSrcweir 
119cdf0e10cSrcweir     //  document title
120cdf0e10cSrcweir     SimpleStringElement  ( mxDocProps->getTitle(),
121cdf0e10cSrcweir                            XML_NAMESPACE_DC, XML_TITLE );
122cdf0e10cSrcweir 
123cdf0e10cSrcweir     //  description
124cdf0e10cSrcweir     SimpleStringElement  ( mxDocProps->getDescription(),
125cdf0e10cSrcweir                            XML_NAMESPACE_DC, XML_DESCRIPTION );
126cdf0e10cSrcweir 
127cdf0e10cSrcweir     //  subject
128cdf0e10cSrcweir     SimpleStringElement  ( mxDocProps->getSubject(),
129cdf0e10cSrcweir                            XML_NAMESPACE_DC, XML_SUBJECT );
130cdf0e10cSrcweir 
131cdf0e10cSrcweir     //  created...
132cdf0e10cSrcweir     SimpleStringElement  ( mxDocProps->getAuthor(),
133cdf0e10cSrcweir                            XML_NAMESPACE_META, XML_INITIAL_CREATOR );
134cdf0e10cSrcweir     SimpleDateTimeElement( mxDocProps->getCreationDate(),
135cdf0e10cSrcweir                            XML_NAMESPACE_META, XML_CREATION_DATE );
136cdf0e10cSrcweir 
137cdf0e10cSrcweir     //  modified...
138cdf0e10cSrcweir     SimpleStringElement  ( mxDocProps->getModifiedBy(),
139cdf0e10cSrcweir                            XML_NAMESPACE_DC, XML_CREATOR );
140cdf0e10cSrcweir     SimpleDateTimeElement( mxDocProps->getModificationDate(),
141cdf0e10cSrcweir                            XML_NAMESPACE_DC, XML_DATE );
142cdf0e10cSrcweir 
143cdf0e10cSrcweir     //  printed...
144cdf0e10cSrcweir     SimpleStringElement  ( mxDocProps->getPrintedBy(),
145cdf0e10cSrcweir                            XML_NAMESPACE_META, XML_PRINTED_BY );
146cdf0e10cSrcweir     SimpleDateTimeElement( mxDocProps->getPrintDate(),
147cdf0e10cSrcweir                            XML_NAMESPACE_META, XML_PRINT_DATE );
148cdf0e10cSrcweir 
149cdf0e10cSrcweir     //  keywords
150cdf0e10cSrcweir     const uno::Sequence< ::rtl::OUString > keywords = mxDocProps->getKeywords();
151cdf0e10cSrcweir     for (sal_Int32 i = 0; i < keywords.getLength(); ++i) {
152cdf0e10cSrcweir         SvXMLElementExport aKwElem( mrExport, XML_NAMESPACE_META, XML_KEYWORD,
153cdf0e10cSrcweir                                     sal_True, sal_False );
154cdf0e10cSrcweir         mrExport.Characters( keywords[i] );
155cdf0e10cSrcweir     }
156cdf0e10cSrcweir 
157cdf0e10cSrcweir     //  document language
158cdf0e10cSrcweir     {
159cdf0e10cSrcweir         const lang::Locale aLocale = mxDocProps->getLanguage();
160cdf0e10cSrcweir         ::rtl::OUString sValue = aLocale.Language;
161cdf0e10cSrcweir         if (sValue.getLength()) {
162cdf0e10cSrcweir             if ( aLocale.Country.getLength() )
163cdf0e10cSrcweir             {
164cdf0e10cSrcweir                 sValue += rtl::OUString::valueOf((sal_Unicode)'-');
165cdf0e10cSrcweir                 sValue += aLocale.Country;
166cdf0e10cSrcweir             }
167cdf0e10cSrcweir             SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DC, XML_LANGUAGE,
168cdf0e10cSrcweir                                       sal_True, sal_False );
169cdf0e10cSrcweir             mrExport.Characters( sValue );
170cdf0e10cSrcweir         }
171cdf0e10cSrcweir     }
172cdf0e10cSrcweir 
173cdf0e10cSrcweir     //  editing cycles
174cdf0e10cSrcweir     {
175cdf0e10cSrcweir         SvXMLElementExport aElem( mrExport,
176cdf0e10cSrcweir                                   XML_NAMESPACE_META, XML_EDITING_CYCLES,
177cdf0e10cSrcweir                                   sal_True, sal_False );
178cdf0e10cSrcweir         mrExport.Characters( ::rtl::OUString::valueOf(
179cdf0e10cSrcweir             static_cast<sal_Int32>(mxDocProps->getEditingCycles()) ) );
180cdf0e10cSrcweir     }
181cdf0e10cSrcweir 
182cdf0e10cSrcweir     //  editing duration
183cdf0e10cSrcweir     //  property is a int32 (seconds)
184cdf0e10cSrcweir     {
185cdf0e10cSrcweir         sal_Int32 secs = mxDocProps->getEditingDuration();
186cdf0e10cSrcweir         SvXMLElementExport aElem( mrExport,
187cdf0e10cSrcweir                                   XML_NAMESPACE_META, XML_EDITING_DURATION,
188cdf0e10cSrcweir                                   sal_True, sal_False );
189cdf0e10cSrcweir         mrExport.Characters( SvXMLUnitConverter::convertTimeDuration(
190cdf0e10cSrcweir             Time(secs/3600, (secs%3600)/60, secs%60)) );
191cdf0e10cSrcweir     }
192cdf0e10cSrcweir 
193cdf0e10cSrcweir     //  default target
194cdf0e10cSrcweir     const ::rtl::OUString sDefTarget = mxDocProps->getDefaultTarget();
195cdf0e10cSrcweir     if ( sDefTarget.getLength() )
196cdf0e10cSrcweir     {
197cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME,
198cdf0e10cSrcweir                                sDefTarget );
199cdf0e10cSrcweir 
200cdf0e10cSrcweir         //! define strings for xlink:show values
201cdf0e10cSrcweir         const XMLTokenEnum eShow =
202cdf0e10cSrcweir             sDefTarget.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_blank"))
203cdf0e10cSrcweir                 ? XML_NEW : XML_REPLACE;
204cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, eShow );
205cdf0e10cSrcweir 
206cdf0e10cSrcweir         SvXMLElementExport aElem( mrExport,
207cdf0e10cSrcweir                                   XML_NAMESPACE_META,XML_HYPERLINK_BEHAVIOUR,
208cdf0e10cSrcweir                                   sal_True, sal_False );
209cdf0e10cSrcweir     }
210cdf0e10cSrcweir 
211cdf0e10cSrcweir     //  auto-reload
212cdf0e10cSrcweir     const ::rtl::OUString sReloadURL = mxDocProps->getAutoloadURL();
213cdf0e10cSrcweir     const sal_Int32 sReloadDelay = mxDocProps->getAutoloadSecs();
214cdf0e10cSrcweir     if (sReloadDelay != 0 || sReloadURL.getLength() != 0)
215cdf0e10cSrcweir     {
216cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF,
217cdf0e10cSrcweir                               mrExport.GetRelativeReference( sReloadURL ) );
218cdf0e10cSrcweir 
219cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_META, XML_DELAY,
220cdf0e10cSrcweir             SvXMLUnitConverter::convertTimeDuration(
221cdf0e10cSrcweir                 Time(sReloadDelay/3600, (sReloadDelay%3600)/60,
222cdf0e10cSrcweir                     sReloadDelay%60 )) );
223cdf0e10cSrcweir 
224cdf0e10cSrcweir         SvXMLElementExport aElem( mrExport, XML_NAMESPACE_META, XML_AUTO_RELOAD,
225cdf0e10cSrcweir                                   sal_True, sal_False );
226cdf0e10cSrcweir     }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir     //  template
229cdf0e10cSrcweir     const rtl::OUString sTplPath = mxDocProps->getTemplateURL();
230cdf0e10cSrcweir     if ( sTplPath.getLength() )
231cdf0e10cSrcweir     {
232cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
233cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONREQUEST );
234cdf0e10cSrcweir 
235cdf0e10cSrcweir         //  template URL
236cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF,
237cdf0e10cSrcweir                               mrExport.GetRelativeReference(sTplPath) );
238cdf0e10cSrcweir 
239cdf0e10cSrcweir         //  template name
240cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TITLE,
241cdf0e10cSrcweir                               mxDocProps->getTemplateName() );
242cdf0e10cSrcweir 
243cdf0e10cSrcweir         //  template date
244cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_META, XML_DATE,
245cdf0e10cSrcweir                 GetISODateTimeString( mxDocProps->getTemplateDate() ) );
246cdf0e10cSrcweir 
247cdf0e10cSrcweir         SvXMLElementExport aElem( mrExport, XML_NAMESPACE_META, XML_TEMPLATE,
248cdf0e10cSrcweir                                   sal_True, sal_False );
249cdf0e10cSrcweir     }
250cdf0e10cSrcweir 
251cdf0e10cSrcweir     //  user defined fields
252cdf0e10cSrcweir     uno::Reference< beans::XPropertyAccess > xUserDefined(
253cdf0e10cSrcweir         mxDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
254cdf0e10cSrcweir     const uno::Sequence< beans::PropertyValue > props =
255cdf0e10cSrcweir         xUserDefined->getPropertyValues();
256cdf0e10cSrcweir     for (sal_Int32 i = 0; i < props.getLength(); ++i) {
257cdf0e10cSrcweir         ::rtl::OUStringBuffer sValueBuffer;
258cdf0e10cSrcweir         ::rtl::OUStringBuffer sType;
259cdf0e10cSrcweir         if (!SvXMLUnitConverter::convertAny(
260cdf0e10cSrcweir                 sValueBuffer, sType, props[i].Value)) {
261cdf0e10cSrcweir             continue;
262cdf0e10cSrcweir         }
263cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_META, XML_NAME, props[i].Name );
264cdf0e10cSrcweir         mrExport.AddAttribute( XML_NAMESPACE_META, XML_VALUE_TYPE,
265cdf0e10cSrcweir                               sType.makeStringAndClear() );
266cdf0e10cSrcweir         SvXMLElementExport aElem( mrExport, XML_NAMESPACE_META,
267cdf0e10cSrcweir                                   XML_USER_DEFINED, sal_True, sal_False );
268cdf0e10cSrcweir         mrExport.Characters( sValueBuffer.makeStringAndClear() );
269cdf0e10cSrcweir     }
270cdf0e10cSrcweir 
271cdf0e10cSrcweir     const uno::Sequence< beans::NamedValue > aDocStatistic =
272cdf0e10cSrcweir             mxDocProps->getDocumentStatistics();
273cdf0e10cSrcweir 	// write document statistic if there is any provided
274cdf0e10cSrcweir 	if ( aDocStatistic.getLength() )
275cdf0e10cSrcweir 	{
276cdf0e10cSrcweir 		for ( sal_Int32 nInd = 0; nInd < aDocStatistic.getLength(); nInd++ )
277cdf0e10cSrcweir 		{
278cdf0e10cSrcweir 			sal_Int32 nValue = 0;
279cdf0e10cSrcweir 			if ( aDocStatistic[nInd].Value >>= nValue )
280cdf0e10cSrcweir 			{
281cdf0e10cSrcweir 				::rtl::OUString aValue = rtl::OUString::valueOf( nValue );
282cdf0e10cSrcweir 				if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString(
283cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM( "TableCount" ) ) ) )
284cdf0e10cSrcweir 					mrExport.AddAttribute(
285cdf0e10cSrcweir                         XML_NAMESPACE_META, XML_TABLE_COUNT, aValue );
286cdf0e10cSrcweir 				else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString(
287cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM( "ObjectCount" ) ) ) )
288cdf0e10cSrcweir 					mrExport.AddAttribute(
289cdf0e10cSrcweir                         XML_NAMESPACE_META, XML_OBJECT_COUNT, aValue );
290cdf0e10cSrcweir 				else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString(
291cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM( "ImageCount" ) ) ) )
292cdf0e10cSrcweir 					mrExport.AddAttribute(
293cdf0e10cSrcweir                         XML_NAMESPACE_META, XML_IMAGE_COUNT, aValue );
294cdf0e10cSrcweir 				else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString(
295cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM( "PageCount" ) ) ) )
296cdf0e10cSrcweir 					mrExport.AddAttribute(
297cdf0e10cSrcweir                         XML_NAMESPACE_META, XML_PAGE_COUNT, aValue );
298cdf0e10cSrcweir 				else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString(
299cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM( "ParagraphCount" ) ) ) )
300cdf0e10cSrcweir 					mrExport.AddAttribute(
301cdf0e10cSrcweir                         XML_NAMESPACE_META, XML_PARAGRAPH_COUNT, aValue );
302cdf0e10cSrcweir 				else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString(
303cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM( "WordCount" ) ) ) )
304cdf0e10cSrcweir 					mrExport.AddAttribute(
305cdf0e10cSrcweir                         XML_NAMESPACE_META, XML_WORD_COUNT, aValue );
306cdf0e10cSrcweir 				else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString(
307cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM( "CharacterCount" ) ) ) )
308cdf0e10cSrcweir 					mrExport.AddAttribute(
309cdf0e10cSrcweir                         XML_NAMESPACE_META, XML_CHARACTER_COUNT, aValue );
310cdf0e10cSrcweir 				else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString(
311cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM( "CellCount" ) ) ) )
312cdf0e10cSrcweir 					mrExport.AddAttribute(
313cdf0e10cSrcweir                         XML_NAMESPACE_META, XML_CELL_COUNT, aValue );
314cdf0e10cSrcweir 				else
315cdf0e10cSrcweir 				{
316cdf0e10cSrcweir 					DBG_ASSERT( sal_False, "Unknown statistic value!\n" );
317cdf0e10cSrcweir 				}
318cdf0e10cSrcweir 			}
319cdf0e10cSrcweir 		}
320cdf0e10cSrcweir 		SvXMLElementExport aElem( mrExport,
321cdf0e10cSrcweir             XML_NAMESPACE_META, XML_DOCUMENT_STATISTIC, sal_True, sal_True );
322cdf0e10cSrcweir 	}
323cdf0e10cSrcweir }
324cdf0e10cSrcweir 
325cdf0e10cSrcweir //-------------------------------------------------------------------------
326cdf0e10cSrcweir 
327cdf0e10cSrcweir static const char *s_xmlns  = "xmlns";
328cdf0e10cSrcweir static const char *s_xmlns2 = "xmlns:";
329cdf0e10cSrcweir static const char *s_meta   = "meta:";
330cdf0e10cSrcweir static const char *s_href   = "xlink:href";
331cdf0e10cSrcweir 
SvXMLMetaExport(SvXMLExport & i_rExp,const uno::Reference<document::XDocumentProperties> & i_rDocProps)332cdf0e10cSrcweir SvXMLMetaExport::SvXMLMetaExport(
333cdf0e10cSrcweir         SvXMLExport& i_rExp,
334cdf0e10cSrcweir         const uno::Reference<document::XDocumentProperties>& i_rDocProps ) :
335cdf0e10cSrcweir     mrExport( i_rExp ),
336cdf0e10cSrcweir 	mxDocProps( i_rDocProps ),
337cdf0e10cSrcweir     m_level( 0 ),
338cdf0e10cSrcweir     m_preservedNSs()
339cdf0e10cSrcweir {
340cdf0e10cSrcweir     DBG_ASSERT( mxDocProps.is(), "no document properties" );
341cdf0e10cSrcweir }
342cdf0e10cSrcweir 
~SvXMLMetaExport()343cdf0e10cSrcweir SvXMLMetaExport::~SvXMLMetaExport()
344cdf0e10cSrcweir {
345cdf0e10cSrcweir }
346cdf0e10cSrcweir 
Export()347cdf0e10cSrcweir void SvXMLMetaExport::Export()
348cdf0e10cSrcweir {
349cdf0e10cSrcweir //    exportDom(xDOM, mrExport); // this would not work (root node, namespaces)
350cdf0e10cSrcweir     uno::Reference< xml::sax::XSAXSerializable> xSAXable(mxDocProps,
351cdf0e10cSrcweir         uno::UNO_QUERY);
352cdf0e10cSrcweir     if (xSAXable.is()) {
353cdf0e10cSrcweir         ::comphelper::SequenceAsVector< beans::StringPair > namespaces;
354cdf0e10cSrcweir         const SvXMLNamespaceMap & rNsMap(mrExport.GetNamespaceMap());
355cdf0e10cSrcweir         for (sal_uInt16 key = rNsMap.GetFirstKey();
356cdf0e10cSrcweir              key != USHRT_MAX; key = rNsMap.GetNextKey(key)) {
357cdf0e10cSrcweir             beans::StringPair ns;
358cdf0e10cSrcweir             const ::rtl::OUString attrname = rNsMap.GetAttrNameByKey(key);
359cdf0e10cSrcweir             if (attrname.matchAsciiL(s_xmlns2, strlen(s_xmlns2))) {
360cdf0e10cSrcweir                 ns.First  = attrname.copy(strlen(s_xmlns2));
361cdf0e10cSrcweir             } else if (attrname.equalsAsciiL(s_xmlns, strlen(s_xmlns))) {
362cdf0e10cSrcweir                 // default initialized empty string
363cdf0e10cSrcweir             } else {
364cdf0e10cSrcweir             DBG_ERROR("namespace attribute not starting with xmlns unexpected");
365cdf0e10cSrcweir             }
366cdf0e10cSrcweir             ns.Second = rNsMap.GetNameByKey(key);
367cdf0e10cSrcweir             namespaces.push_back(ns);
368cdf0e10cSrcweir         }
369cdf0e10cSrcweir         xSAXable->serialize(this, namespaces.getAsConstList());
370cdf0e10cSrcweir     } else {
371cdf0e10cSrcweir         // office:meta
372cdf0e10cSrcweir 		SvXMLElementExport aElem( mrExport, XML_NAMESPACE_OFFICE, XML_META,
373cdf0e10cSrcweir 								  sal_True, sal_True );
374cdf0e10cSrcweir         // fall back to using public interface of XDocumentProperties
375cdf0e10cSrcweir         _MExport();
376cdf0e10cSrcweir     }
377cdf0e10cSrcweir }
378cdf0e10cSrcweir 
379cdf0e10cSrcweir // ::com::sun::star::xml::sax::XDocumentHandler:
380cdf0e10cSrcweir void SAL_CALL
startDocument()381cdf0e10cSrcweir SvXMLMetaExport::startDocument()
382cdf0e10cSrcweir     throw (uno::RuntimeException, xml::sax::SAXException)
383cdf0e10cSrcweir {
384cdf0e10cSrcweir     // ignore: has already been done by SvXMLExport::exportDoc
385cdf0e10cSrcweir     DBG_ASSERT( m_level == 0, "SvXMLMetaExport: level error" );
386cdf0e10cSrcweir }
387cdf0e10cSrcweir 
388cdf0e10cSrcweir void SAL_CALL
endDocument()389cdf0e10cSrcweir SvXMLMetaExport::endDocument()
390cdf0e10cSrcweir     throw (uno::RuntimeException, xml::sax::SAXException)
391cdf0e10cSrcweir {
392cdf0e10cSrcweir     // ignore: will be done by SvXMLExport::exportDoc
393cdf0e10cSrcweir     DBG_ASSERT( m_level == 0, "SvXMLMetaExport: level error" );
394cdf0e10cSrcweir }
395cdf0e10cSrcweir 
396cdf0e10cSrcweir // unfortunately, this method contains far too much ugly namespace mangling.
397cdf0e10cSrcweir void SAL_CALL
startElement(const::rtl::OUString & i_rName,const uno::Reference<xml::sax::XAttributeList> & i_xAttribs)398cdf0e10cSrcweir SvXMLMetaExport::startElement(const ::rtl::OUString & i_rName,
399cdf0e10cSrcweir     const uno::Reference< xml::sax::XAttributeList > & i_xAttribs)
400cdf0e10cSrcweir     throw (uno::RuntimeException, xml::sax::SAXException)
401cdf0e10cSrcweir {
402cdf0e10cSrcweir 
403cdf0e10cSrcweir     if (m_level == 0) {
404cdf0e10cSrcweir         // namepace decls: default ones have been written at the root element
405cdf0e10cSrcweir         // non-default ones must be preserved here
406cdf0e10cSrcweir         const sal_Int16 nCount = i_xAttribs->getLength();
407cdf0e10cSrcweir         for (sal_Int16 i = 0; i < nCount; ++i) {
408cdf0e10cSrcweir             const ::rtl::OUString name(i_xAttribs->getNameByIndex(i));
409cdf0e10cSrcweir             if (name.matchAsciiL(s_xmlns, strlen(s_xmlns))) {
410cdf0e10cSrcweir                 bool found(false);
411cdf0e10cSrcweir                 const SvXMLNamespaceMap & rNsMap(mrExport.GetNamespaceMap());
412cdf0e10cSrcweir                 for (sal_uInt16 key = rNsMap.GetFirstKey();
413cdf0e10cSrcweir                      key != USHRT_MAX; key = rNsMap.GetNextKey(key)) {
414cdf0e10cSrcweir                     if (name.equals(rNsMap.GetAttrNameByKey(key))) {
415cdf0e10cSrcweir                         found = true;
416cdf0e10cSrcweir                         break;
417cdf0e10cSrcweir                     }
418cdf0e10cSrcweir                 }
419cdf0e10cSrcweir                 if (!found) {
420cdf0e10cSrcweir                     m_preservedNSs.push_back(beans::StringPair(name,
421cdf0e10cSrcweir                         i_xAttribs->getValueByIndex(i)));
422cdf0e10cSrcweir                 }
423cdf0e10cSrcweir             }
424cdf0e10cSrcweir         }
425cdf0e10cSrcweir         // ignore the root: it has been written already
426cdf0e10cSrcweir         ++m_level;
427cdf0e10cSrcweir         return;
428cdf0e10cSrcweir     }
429cdf0e10cSrcweir 
430cdf0e10cSrcweir     if (m_level == 1) {
431cdf0e10cSrcweir         // attach preserved namespace decls from root node here
432cdf0e10cSrcweir         for (std::vector<beans::StringPair>::const_iterator iter =
433cdf0e10cSrcweir                 m_preservedNSs.begin(); iter != m_preservedNSs.end(); ++iter) {
434cdf0e10cSrcweir             const ::rtl::OUString ns(iter->First);
435cdf0e10cSrcweir             bool found(false);
436cdf0e10cSrcweir             // but only if it is not already there
437cdf0e10cSrcweir             const sal_Int16 nCount = i_xAttribs->getLength();
438cdf0e10cSrcweir             for (sal_Int16 i = 0; i < nCount; ++i) {
439cdf0e10cSrcweir                 const ::rtl::OUString name(i_xAttribs->getNameByIndex(i));
440cdf0e10cSrcweir                 if (ns.equals(name)) {
441cdf0e10cSrcweir                     found = true;
442cdf0e10cSrcweir                     break;
443cdf0e10cSrcweir                 }
444cdf0e10cSrcweir             }
445cdf0e10cSrcweir             if (!found) {
446cdf0e10cSrcweir                 mrExport.AddAttribute(ns, iter->Second);
447cdf0e10cSrcweir             }
448cdf0e10cSrcweir         }
449cdf0e10cSrcweir     }
450cdf0e10cSrcweir 
451cdf0e10cSrcweir     // attach the attributes
452cdf0e10cSrcweir     if (i_rName.matchAsciiL(s_meta, strlen(s_meta))) {
453cdf0e10cSrcweir         // special handling for all elements that may have
454cdf0e10cSrcweir         // xlink:href attributes; these must be made relative
455cdf0e10cSrcweir         const sal_Int16 nLength = i_xAttribs->getLength();
456cdf0e10cSrcweir         for (sal_Int16 i = 0; i < nLength; ++i) {
457cdf0e10cSrcweir             const ::rtl::OUString name (i_xAttribs->getNameByIndex (i));
458cdf0e10cSrcweir             ::rtl::OUString value(i_xAttribs->getValueByIndex(i));
459cdf0e10cSrcweir             if (name.matchAsciiL(s_href, strlen(s_href))) {
460cdf0e10cSrcweir                 value = mrExport.GetRelativeReference(value);
461cdf0e10cSrcweir             }
462cdf0e10cSrcweir             mrExport.AddAttribute(name, value);
463cdf0e10cSrcweir         }
464cdf0e10cSrcweir     } else {
465cdf0e10cSrcweir         const sal_Int16 nLength = i_xAttribs->getLength();
466cdf0e10cSrcweir         for (sal_Int16 i = 0; i < nLength; ++i) {
467cdf0e10cSrcweir             const ::rtl::OUString name  (i_xAttribs->getNameByIndex(i));
468cdf0e10cSrcweir             const ::rtl::OUString value (i_xAttribs->getValueByIndex(i));
469cdf0e10cSrcweir             mrExport.AddAttribute(name, value);
470cdf0e10cSrcweir         }
471cdf0e10cSrcweir     }
472cdf0e10cSrcweir 
473cdf0e10cSrcweir     // finally, start the element
474cdf0e10cSrcweir     // #i107240# no whitespace here, because the DOM may already contain
475cdf0e10cSrcweir     // whitespace, which is not cleared when loading and thus accumulates.
476cdf0e10cSrcweir     mrExport.StartElement(i_rName, (m_level > 1) ? sal_False : sal_True);
477cdf0e10cSrcweir     ++m_level;
478cdf0e10cSrcweir }
479cdf0e10cSrcweir 
480cdf0e10cSrcweir void SAL_CALL
endElement(const::rtl::OUString & i_rName)481cdf0e10cSrcweir SvXMLMetaExport::endElement(const ::rtl::OUString & i_rName)
482cdf0e10cSrcweir     throw (uno::RuntimeException, xml::sax::SAXException)
483cdf0e10cSrcweir {
484cdf0e10cSrcweir     --m_level;
485cdf0e10cSrcweir     if (m_level == 0) {
486cdf0e10cSrcweir         // ignore the root; see startElement
487cdf0e10cSrcweir         return;
488cdf0e10cSrcweir     }
489cdf0e10cSrcweir     DBG_ASSERT( m_level >= 0, "SvXMLMetaExport: level error" );
490cdf0e10cSrcweir     mrExport.EndElement(i_rName, sal_False);
491cdf0e10cSrcweir }
492cdf0e10cSrcweir 
493cdf0e10cSrcweir void SAL_CALL
characters(const::rtl::OUString & i_rChars)494cdf0e10cSrcweir SvXMLMetaExport::characters(const ::rtl::OUString & i_rChars)
495cdf0e10cSrcweir     throw (uno::RuntimeException, xml::sax::SAXException)
496cdf0e10cSrcweir {
497cdf0e10cSrcweir     mrExport.Characters(i_rChars);
498cdf0e10cSrcweir }
499cdf0e10cSrcweir 
500cdf0e10cSrcweir void SAL_CALL
ignorableWhitespace(const::rtl::OUString &)501cdf0e10cSrcweir SvXMLMetaExport::ignorableWhitespace(const ::rtl::OUString & /*i_rWhitespaces*/)
502cdf0e10cSrcweir     throw (uno::RuntimeException, xml::sax::SAXException)
503cdf0e10cSrcweir {
504cdf0e10cSrcweir     mrExport.IgnorableWhitespace(/*i_rWhitespaces*/);
505cdf0e10cSrcweir }
506cdf0e10cSrcweir 
507cdf0e10cSrcweir void SAL_CALL
processingInstruction(const::rtl::OUString & i_rTarget,const::rtl::OUString & i_rData)508cdf0e10cSrcweir SvXMLMetaExport::processingInstruction(const ::rtl::OUString & i_rTarget,
509cdf0e10cSrcweir     const ::rtl::OUString & i_rData)
510cdf0e10cSrcweir     throw (uno::RuntimeException, xml::sax::SAXException)
511cdf0e10cSrcweir {
512cdf0e10cSrcweir     // ignore; the exporter cannot handle these
513cdf0e10cSrcweir     (void) i_rTarget;
514cdf0e10cSrcweir     (void) i_rData;
515cdf0e10cSrcweir }
516cdf0e10cSrcweir 
517cdf0e10cSrcweir void SAL_CALL
setDocumentLocator(const uno::Reference<xml::sax::XLocator> &)518cdf0e10cSrcweir SvXMLMetaExport::setDocumentLocator(const uno::Reference<xml::sax::XLocator>&)
519cdf0e10cSrcweir     throw (uno::RuntimeException, xml::sax::SAXException)
520cdf0e10cSrcweir {
521cdf0e10cSrcweir     // nothing to do here, move along...
522cdf0e10cSrcweir }
523cdf0e10cSrcweir 
524cdf0e10cSrcweir 
525