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 10cdf0e10cSrcweir * 11*63bba73cSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 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. 19cdf0e10cSrcweir * 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 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 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 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 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 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 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 343cdf0e10cSrcweir SvXMLMetaExport::~SvXMLMetaExport() 344cdf0e10cSrcweir { 345cdf0e10cSrcweir } 346cdf0e10cSrcweir 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 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 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 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 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 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 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 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 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