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