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