|  | /************************************************************** | 
|  | * | 
|  | * Licensed to the Apache Software Foundation (ASF) under one | 
|  | * or more contributor license agreements.  See the NOTICE file | 
|  | * distributed with this work for additional information | 
|  | * regarding copyright ownership.  The ASF licenses this file | 
|  | * to you under the Apache License, Version 2.0 (the | 
|  | * "License"); you may not use this file except in compliance | 
|  | * with the License.  You may obtain a copy of the License at | 
|  | * | 
|  | *   http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, | 
|  | * software distributed under the License is distributed on an | 
|  | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
|  | * KIND, either express or implied.  See the License for the | 
|  | * specific language governing permissions and limitations | 
|  | * under the License. | 
|  | * | 
|  | *************************************************************/ | 
|  |  | 
|  |  | 
|  |  | 
|  | // MARKER(update_precomp.py): autogen include statement, do not remove | 
|  | #include "precompiled_xmloff.hxx" | 
|  |  | 
|  | #include <tools/debug.hxx> | 
|  | #include <tools/inetdef.hxx> | 
|  | #include <i18npool/mslangid.hxx> | 
|  | #include <tools/urlobj.hxx> | 
|  | #include <tools/time.hxx> | 
|  | #include <rtl/ustrbuf.hxx> | 
|  |  | 
|  | #include <xmloff/xmlmetae.hxx> | 
|  | #include <xmloff/xmlexp.hxx> | 
|  | #include <xmloff/xmluconv.hxx> | 
|  | #include <xmloff/nmspmap.hxx> | 
|  | #include "xmloff/xmlnmspe.hxx" | 
|  |  | 
|  | #include <com/sun/star/beans/XPropertyAccess.hpp> | 
|  | #include <com/sun/star/beans/StringPair.hpp> | 
|  | #include <com/sun/star/xml/dom/XDocument.hpp> | 
|  | #include <com/sun/star/xml/sax/XSAXSerializable.hpp> | 
|  |  | 
|  | #include <comphelper/sequenceasvector.hxx> | 
|  | #include <unotools/docinfohelper.hxx> | 
|  |  | 
|  | #include <string.h> | 
|  |  | 
|  |  | 
|  | using namespace com::sun::star; | 
|  | using namespace ::xmloff::token; | 
|  |  | 
|  |  | 
|  | //------------------------------------------------------------------------- | 
|  |  | 
|  | void lcl_AddTwoDigits( rtl::OUStringBuffer& rStr, sal_Int32 nVal ) | 
|  | { | 
|  | if ( nVal < 10 ) | 
|  | rStr.append( sal_Unicode('0') ); | 
|  | rStr.append( nVal ); | 
|  | } | 
|  |  | 
|  | rtl::OUString | 
|  | SvXMLMetaExport::GetISODateTimeString( const util::DateTime& rDateTime ) | 
|  | { | 
|  | //  return ISO date string "YYYY-MM-DDThh:mm:ss" | 
|  |  | 
|  | rtl::OUStringBuffer sTmp; | 
|  | sTmp.append( (sal_Int32) rDateTime.Year ); | 
|  | sTmp.append( sal_Unicode('-') ); | 
|  | lcl_AddTwoDigits( sTmp, rDateTime.Month ); | 
|  | sTmp.append( sal_Unicode('-') ); | 
|  | lcl_AddTwoDigits( sTmp, rDateTime.Day ); | 
|  | sTmp.append( sal_Unicode('T') ); | 
|  | lcl_AddTwoDigits( sTmp, rDateTime.Hours ); | 
|  | sTmp.append( sal_Unicode(':') ); | 
|  | lcl_AddTwoDigits( sTmp, rDateTime.Minutes ); | 
|  | sTmp.append( sal_Unicode(':') ); | 
|  | lcl_AddTwoDigits( sTmp, rDateTime.Seconds ); | 
|  |  | 
|  | return sTmp.makeStringAndClear(); | 
|  | } | 
|  |  | 
|  | //------------------------------------------------------------------------- | 
|  |  | 
|  | void SvXMLMetaExport::SimpleStringElement( const rtl::OUString& rText, | 
|  | sal_uInt16 nNamespace, enum XMLTokenEnum eElementName ) | 
|  | { | 
|  | if ( rText.getLength() ) { | 
|  | SvXMLElementExport aElem( mrExport, nNamespace, eElementName, | 
|  | sal_True, sal_False ); | 
|  | mrExport.Characters( rText ); | 
|  | } | 
|  | } | 
|  |  | 
|  | void SvXMLMetaExport::SimpleDateTimeElement( const util::DateTime & rDate, | 
|  | sal_uInt16 nNamespace, enum XMLTokenEnum eElementName ) | 
|  | { | 
|  | if (rDate.Month != 0) { // invalid dates are 0-0-0 | 
|  | rtl::OUString sValue = GetISODateTimeString( rDate ); | 
|  | if ( sValue.getLength() ) { | 
|  | SvXMLElementExport aElem( mrExport, nNamespace, eElementName, | 
|  | sal_True, sal_False ); | 
|  | mrExport.Characters( sValue ); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void SvXMLMetaExport::_MExport() | 
|  | { | 
|  | //  generator | 
|  | { | 
|  | SvXMLElementExport aElem( mrExport, XML_NAMESPACE_META, XML_GENERATOR, | 
|  | sal_True, sal_True ); | 
|  | mrExport.Characters( ::utl::DocInfoHelper::GetGeneratorString() ); | 
|  | } | 
|  |  | 
|  | //  document title | 
|  | SimpleStringElement  ( mxDocProps->getTitle(), | 
|  | XML_NAMESPACE_DC, XML_TITLE ); | 
|  |  | 
|  | //  description | 
|  | SimpleStringElement  ( mxDocProps->getDescription(), | 
|  | XML_NAMESPACE_DC, XML_DESCRIPTION ); | 
|  |  | 
|  | //  subject | 
|  | SimpleStringElement  ( mxDocProps->getSubject(), | 
|  | XML_NAMESPACE_DC, XML_SUBJECT ); | 
|  |  | 
|  | //  created... | 
|  | SimpleStringElement  ( mxDocProps->getAuthor(), | 
|  | XML_NAMESPACE_META, XML_INITIAL_CREATOR ); | 
|  | SimpleDateTimeElement( mxDocProps->getCreationDate(), | 
|  | XML_NAMESPACE_META, XML_CREATION_DATE ); | 
|  |  | 
|  | //  modified... | 
|  | SimpleStringElement  ( mxDocProps->getModifiedBy(), | 
|  | XML_NAMESPACE_DC, XML_CREATOR ); | 
|  | SimpleDateTimeElement( mxDocProps->getModificationDate(), | 
|  | XML_NAMESPACE_DC, XML_DATE ); | 
|  |  | 
|  | //  printed... | 
|  | SimpleStringElement  ( mxDocProps->getPrintedBy(), | 
|  | XML_NAMESPACE_META, XML_PRINTED_BY ); | 
|  | SimpleDateTimeElement( mxDocProps->getPrintDate(), | 
|  | XML_NAMESPACE_META, XML_PRINT_DATE ); | 
|  |  | 
|  | //  keywords | 
|  | const uno::Sequence< ::rtl::OUString > keywords = mxDocProps->getKeywords(); | 
|  | for (sal_Int32 i = 0; i < keywords.getLength(); ++i) { | 
|  | SvXMLElementExport aKwElem( mrExport, XML_NAMESPACE_META, XML_KEYWORD, | 
|  | sal_True, sal_False ); | 
|  | mrExport.Characters( keywords[i] ); | 
|  | } | 
|  |  | 
|  | //  document language | 
|  | { | 
|  | const lang::Locale aLocale = mxDocProps->getLanguage(); | 
|  | ::rtl::OUString sValue = aLocale.Language; | 
|  | if (sValue.getLength()) { | 
|  | if ( aLocale.Country.getLength() ) | 
|  | { | 
|  | sValue += rtl::OUString::valueOf((sal_Unicode)'-'); | 
|  | sValue += aLocale.Country; | 
|  | } | 
|  | SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DC, XML_LANGUAGE, | 
|  | sal_True, sal_False ); | 
|  | mrExport.Characters( sValue ); | 
|  | } | 
|  | } | 
|  |  | 
|  | //  editing cycles | 
|  | { | 
|  | SvXMLElementExport aElem( mrExport, | 
|  | XML_NAMESPACE_META, XML_EDITING_CYCLES, | 
|  | sal_True, sal_False ); | 
|  | mrExport.Characters( ::rtl::OUString::valueOf( | 
|  | static_cast<sal_Int32>(mxDocProps->getEditingCycles()) ) ); | 
|  | } | 
|  |  | 
|  | //  editing duration | 
|  | //  property is a int32 (seconds) | 
|  | { | 
|  | sal_Int32 secs = mxDocProps->getEditingDuration(); | 
|  | SvXMLElementExport aElem( mrExport, | 
|  | XML_NAMESPACE_META, XML_EDITING_DURATION, | 
|  | sal_True, sal_False ); | 
|  | mrExport.Characters( SvXMLUnitConverter::convertTimeDuration( | 
|  | Time(secs/3600, (secs%3600)/60, secs%60)) ); | 
|  | } | 
|  |  | 
|  | //  default target | 
|  | const ::rtl::OUString sDefTarget = mxDocProps->getDefaultTarget(); | 
|  | if ( sDefTarget.getLength() ) | 
|  | { | 
|  | mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, | 
|  | sDefTarget ); | 
|  |  | 
|  | //! define strings for xlink:show values | 
|  | const XMLTokenEnum eShow = | 
|  | sDefTarget.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_blank")) | 
|  | ? XML_NEW : XML_REPLACE; | 
|  | mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, eShow ); | 
|  |  | 
|  | SvXMLElementExport aElem( mrExport, | 
|  | XML_NAMESPACE_META,XML_HYPERLINK_BEHAVIOUR, | 
|  | sal_True, sal_False ); | 
|  | } | 
|  |  | 
|  | //  auto-reload | 
|  | const ::rtl::OUString sReloadURL = mxDocProps->getAutoloadURL(); | 
|  | const sal_Int32 sReloadDelay = mxDocProps->getAutoloadSecs(); | 
|  | if (sReloadDelay != 0 || sReloadURL.getLength() != 0) | 
|  | { | 
|  | mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, | 
|  | mrExport.GetRelativeReference( sReloadURL ) ); | 
|  |  | 
|  | mrExport.AddAttribute( XML_NAMESPACE_META, XML_DELAY, | 
|  | SvXMLUnitConverter::convertTimeDuration( | 
|  | Time(sReloadDelay/3600, (sReloadDelay%3600)/60, | 
|  | sReloadDelay%60 )) ); | 
|  |  | 
|  | SvXMLElementExport aElem( mrExport, XML_NAMESPACE_META, XML_AUTO_RELOAD, | 
|  | sal_True, sal_False ); | 
|  | } | 
|  |  | 
|  | //  template | 
|  | const rtl::OUString sTplPath = mxDocProps->getTemplateURL(); | 
|  | if ( sTplPath.getLength() ) | 
|  | { | 
|  | mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE ); | 
|  | mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONREQUEST ); | 
|  |  | 
|  | //  template URL | 
|  | mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, | 
|  | mrExport.GetRelativeReference(sTplPath) ); | 
|  |  | 
|  | //  template name | 
|  | mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TITLE, | 
|  | mxDocProps->getTemplateName() ); | 
|  |  | 
|  | //  template date | 
|  | mrExport.AddAttribute( XML_NAMESPACE_META, XML_DATE, | 
|  | GetISODateTimeString( mxDocProps->getTemplateDate() ) ); | 
|  |  | 
|  | SvXMLElementExport aElem( mrExport, XML_NAMESPACE_META, XML_TEMPLATE, | 
|  | sal_True, sal_False ); | 
|  | } | 
|  |  | 
|  | //  user defined fields | 
|  | uno::Reference< beans::XPropertyAccess > xUserDefined( | 
|  | mxDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW); | 
|  | const uno::Sequence< beans::PropertyValue > props = | 
|  | xUserDefined->getPropertyValues(); | 
|  | for (sal_Int32 i = 0; i < props.getLength(); ++i) { | 
|  | ::rtl::OUStringBuffer sValueBuffer; | 
|  | ::rtl::OUStringBuffer sType; | 
|  | if (!SvXMLUnitConverter::convertAny( | 
|  | sValueBuffer, sType, props[i].Value)) { | 
|  | continue; | 
|  | } | 
|  | mrExport.AddAttribute( XML_NAMESPACE_META, XML_NAME, props[i].Name ); | 
|  | mrExport.AddAttribute( XML_NAMESPACE_META, XML_VALUE_TYPE, | 
|  | sType.makeStringAndClear() ); | 
|  | SvXMLElementExport aElem( mrExport, XML_NAMESPACE_META, | 
|  | XML_USER_DEFINED, sal_True, sal_False ); | 
|  | mrExport.Characters( sValueBuffer.makeStringAndClear() ); | 
|  | } | 
|  |  | 
|  | const uno::Sequence< beans::NamedValue > aDocStatistic = | 
|  | mxDocProps->getDocumentStatistics(); | 
|  | // write document statistic if there is any provided | 
|  | if ( aDocStatistic.getLength() ) | 
|  | { | 
|  | for ( sal_Int32 nInd = 0; nInd < aDocStatistic.getLength(); nInd++ ) | 
|  | { | 
|  | sal_Int32 nValue = 0; | 
|  | if ( aDocStatistic[nInd].Value >>= nValue ) | 
|  | { | 
|  | ::rtl::OUString aValue = rtl::OUString::valueOf( nValue ); | 
|  | if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString( | 
|  | RTL_CONSTASCII_USTRINGPARAM( "TableCount" ) ) ) ) | 
|  | mrExport.AddAttribute( | 
|  | XML_NAMESPACE_META, XML_TABLE_COUNT, aValue ); | 
|  | else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString( | 
|  | RTL_CONSTASCII_USTRINGPARAM( "ObjectCount" ) ) ) ) | 
|  | mrExport.AddAttribute( | 
|  | XML_NAMESPACE_META, XML_OBJECT_COUNT, aValue ); | 
|  | else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString( | 
|  | RTL_CONSTASCII_USTRINGPARAM( "ImageCount" ) ) ) ) | 
|  | mrExport.AddAttribute( | 
|  | XML_NAMESPACE_META, XML_IMAGE_COUNT, aValue ); | 
|  | else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString( | 
|  | RTL_CONSTASCII_USTRINGPARAM( "PageCount" ) ) ) ) | 
|  | mrExport.AddAttribute( | 
|  | XML_NAMESPACE_META, XML_PAGE_COUNT, aValue ); | 
|  | else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString( | 
|  | RTL_CONSTASCII_USTRINGPARAM( "ParagraphCount" ) ) ) ) | 
|  | mrExport.AddAttribute( | 
|  | XML_NAMESPACE_META, XML_PARAGRAPH_COUNT, aValue ); | 
|  | else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString( | 
|  | RTL_CONSTASCII_USTRINGPARAM( "WordCount" ) ) ) ) | 
|  | mrExport.AddAttribute( | 
|  | XML_NAMESPACE_META, XML_WORD_COUNT, aValue ); | 
|  | else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString( | 
|  | RTL_CONSTASCII_USTRINGPARAM( "CharacterCount" ) ) ) ) | 
|  | mrExport.AddAttribute( | 
|  | XML_NAMESPACE_META, XML_CHARACTER_COUNT, aValue ); | 
|  | else if ( aDocStatistic[nInd].Name.equals( ::rtl::OUString( | 
|  | RTL_CONSTASCII_USTRINGPARAM( "CellCount" ) ) ) ) | 
|  | mrExport.AddAttribute( | 
|  | XML_NAMESPACE_META, XML_CELL_COUNT, aValue ); | 
|  | else | 
|  | { | 
|  | DBG_ASSERT( sal_False, "Unknown statistic value!\n" ); | 
|  | } | 
|  | } | 
|  | } | 
|  | SvXMLElementExport aElem( mrExport, | 
|  | XML_NAMESPACE_META, XML_DOCUMENT_STATISTIC, sal_True, sal_True ); | 
|  | } | 
|  | } | 
|  |  | 
|  | //------------------------------------------------------------------------- | 
|  |  | 
|  | static const char *s_xmlns  = "xmlns"; | 
|  | static const char *s_xmlns2 = "xmlns:"; | 
|  | static const char *s_meta   = "meta:"; | 
|  | static const char *s_href   = "xlink:href"; | 
|  |  | 
|  | SvXMLMetaExport::SvXMLMetaExport( | 
|  | SvXMLExport& i_rExp, | 
|  | const uno::Reference<document::XDocumentProperties>& i_rDocProps ) : | 
|  | mrExport( i_rExp ), | 
|  | mxDocProps( i_rDocProps ), | 
|  | m_level( 0 ), | 
|  | m_preservedNSs() | 
|  | { | 
|  | DBG_ASSERT( mxDocProps.is(), "no document properties" ); | 
|  | } | 
|  |  | 
|  | SvXMLMetaExport::~SvXMLMetaExport() | 
|  | { | 
|  | } | 
|  |  | 
|  | void SvXMLMetaExport::Export() | 
|  | { | 
|  | //    exportDom(xDOM, mrExport); // this would not work (root node, namespaces) | 
|  | uno::Reference< xml::sax::XSAXSerializable> xSAXable(mxDocProps, | 
|  | uno::UNO_QUERY); | 
|  | if (xSAXable.is()) { | 
|  | ::comphelper::SequenceAsVector< beans::StringPair > namespaces; | 
|  | const SvXMLNamespaceMap & rNsMap(mrExport.GetNamespaceMap()); | 
|  | for (sal_uInt16 key = rNsMap.GetFirstKey(); | 
|  | key != USHRT_MAX; key = rNsMap.GetNextKey(key)) { | 
|  | beans::StringPair ns; | 
|  | const ::rtl::OUString attrname = rNsMap.GetAttrNameByKey(key); | 
|  | if (attrname.matchAsciiL(s_xmlns2, strlen(s_xmlns2))) { | 
|  | ns.First  = attrname.copy(strlen(s_xmlns2)); | 
|  | } else if (attrname.equalsAsciiL(s_xmlns, strlen(s_xmlns))) { | 
|  | // default initialized empty string | 
|  | } else { | 
|  | DBG_ERROR("namespace attribute not starting with xmlns unexpected"); | 
|  | } | 
|  | ns.Second = rNsMap.GetNameByKey(key); | 
|  | namespaces.push_back(ns); | 
|  | } | 
|  | xSAXable->serialize(this, namespaces.getAsConstList()); | 
|  | } else { | 
|  | // office:meta | 
|  | SvXMLElementExport aElem( mrExport, XML_NAMESPACE_OFFICE, XML_META, | 
|  | sal_True, sal_True ); | 
|  | // fall back to using public interface of XDocumentProperties | 
|  | _MExport(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // ::com::sun::star::xml::sax::XDocumentHandler: | 
|  | void SAL_CALL | 
|  | SvXMLMetaExport::startDocument() | 
|  | throw (uno::RuntimeException, xml::sax::SAXException) | 
|  | { | 
|  | // ignore: has already been done by SvXMLExport::exportDoc | 
|  | DBG_ASSERT( m_level == 0, "SvXMLMetaExport: level error" ); | 
|  | } | 
|  |  | 
|  | void SAL_CALL | 
|  | SvXMLMetaExport::endDocument() | 
|  | throw (uno::RuntimeException, xml::sax::SAXException) | 
|  | { | 
|  | // ignore: will be done by SvXMLExport::exportDoc | 
|  | DBG_ASSERT( m_level == 0, "SvXMLMetaExport: level error" ); | 
|  | } | 
|  |  | 
|  | // unfortunately, this method contains far too much ugly namespace mangling. | 
|  | void SAL_CALL | 
|  | SvXMLMetaExport::startElement(const ::rtl::OUString & i_rName, | 
|  | const uno::Reference< xml::sax::XAttributeList > & i_xAttribs) | 
|  | throw (uno::RuntimeException, xml::sax::SAXException) | 
|  | { | 
|  |  | 
|  | if (m_level == 0) { | 
|  | // namepace decls: default ones have been written at the root element | 
|  | // non-default ones must be preserved here | 
|  | const sal_Int16 nCount = i_xAttribs->getLength(); | 
|  | for (sal_Int16 i = 0; i < nCount; ++i) { | 
|  | const ::rtl::OUString name(i_xAttribs->getNameByIndex(i)); | 
|  | if (name.matchAsciiL(s_xmlns, strlen(s_xmlns))) { | 
|  | bool found(false); | 
|  | const SvXMLNamespaceMap & rNsMap(mrExport.GetNamespaceMap()); | 
|  | for (sal_uInt16 key = rNsMap.GetFirstKey(); | 
|  | key != USHRT_MAX; key = rNsMap.GetNextKey(key)) { | 
|  | if (name.equals(rNsMap.GetAttrNameByKey(key))) { | 
|  | found = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!found) { | 
|  | m_preservedNSs.push_back(beans::StringPair(name, | 
|  | i_xAttribs->getValueByIndex(i))); | 
|  | } | 
|  | } | 
|  | } | 
|  | // ignore the root: it has been written already | 
|  | ++m_level; | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (m_level == 1) { | 
|  | // attach preserved namespace decls from root node here | 
|  | for (std::vector<beans::StringPair>::const_iterator iter = | 
|  | m_preservedNSs.begin(); iter != m_preservedNSs.end(); ++iter) { | 
|  | const ::rtl::OUString ns(iter->First); | 
|  | bool found(false); | 
|  | // but only if it is not already there | 
|  | const sal_Int16 nCount = i_xAttribs->getLength(); | 
|  | for (sal_Int16 i = 0; i < nCount; ++i) { | 
|  | const ::rtl::OUString name(i_xAttribs->getNameByIndex(i)); | 
|  | if (ns.equals(name)) { | 
|  | found = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!found) { | 
|  | mrExport.AddAttribute(ns, iter->Second); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // attach the attributes | 
|  | if (i_rName.matchAsciiL(s_meta, strlen(s_meta))) { | 
|  | // special handling for all elements that may have | 
|  | // xlink:href attributes; these must be made relative | 
|  | const sal_Int16 nLength = i_xAttribs->getLength(); | 
|  | for (sal_Int16 i = 0; i < nLength; ++i) { | 
|  | const ::rtl::OUString name (i_xAttribs->getNameByIndex (i)); | 
|  | ::rtl::OUString value(i_xAttribs->getValueByIndex(i)); | 
|  | if (name.matchAsciiL(s_href, strlen(s_href))) { | 
|  | value = mrExport.GetRelativeReference(value); | 
|  | } | 
|  | mrExport.AddAttribute(name, value); | 
|  | } | 
|  | } else { | 
|  | const sal_Int16 nLength = i_xAttribs->getLength(); | 
|  | for (sal_Int16 i = 0; i < nLength; ++i) { | 
|  | const ::rtl::OUString name  (i_xAttribs->getNameByIndex(i)); | 
|  | const ::rtl::OUString value (i_xAttribs->getValueByIndex(i)); | 
|  | mrExport.AddAttribute(name, value); | 
|  | } | 
|  | } | 
|  |  | 
|  | // finally, start the element | 
|  | // #i107240# no whitespace here, because the DOM may already contain | 
|  | // whitespace, which is not cleared when loading and thus accumulates. | 
|  | mrExport.StartElement(i_rName, (m_level > 1) ? sal_False : sal_True); | 
|  | ++m_level; | 
|  | } | 
|  |  | 
|  | void SAL_CALL | 
|  | SvXMLMetaExport::endElement(const ::rtl::OUString & i_rName) | 
|  | throw (uno::RuntimeException, xml::sax::SAXException) | 
|  | { | 
|  | --m_level; | 
|  | if (m_level == 0) { | 
|  | // ignore the root; see startElement | 
|  | return; | 
|  | } | 
|  | DBG_ASSERT( m_level >= 0, "SvXMLMetaExport: level error" ); | 
|  | mrExport.EndElement(i_rName, sal_False); | 
|  | } | 
|  |  | 
|  | void SAL_CALL | 
|  | SvXMLMetaExport::characters(const ::rtl::OUString & i_rChars) | 
|  | throw (uno::RuntimeException, xml::sax::SAXException) | 
|  | { | 
|  | mrExport.Characters(i_rChars); | 
|  | } | 
|  |  | 
|  | void SAL_CALL | 
|  | SvXMLMetaExport::ignorableWhitespace(const ::rtl::OUString & /*i_rWhitespaces*/) | 
|  | throw (uno::RuntimeException, xml::sax::SAXException) | 
|  | { | 
|  | mrExport.IgnorableWhitespace(/*i_rWhitespaces*/); | 
|  | } | 
|  |  | 
|  | void SAL_CALL | 
|  | SvXMLMetaExport::processingInstruction(const ::rtl::OUString & i_rTarget, | 
|  | const ::rtl::OUString & i_rData) | 
|  | throw (uno::RuntimeException, xml::sax::SAXException) | 
|  | { | 
|  | // ignore; the exporter cannot handle these | 
|  | (void) i_rTarget; | 
|  | (void) i_rData; | 
|  | } | 
|  |  | 
|  | void SAL_CALL | 
|  | SvXMLMetaExport::setDocumentLocator(const uno::Reference<xml::sax::XLocator>&) | 
|  | throw (uno::RuntimeException, xml::sax::SAXException) | 
|  | { | 
|  | // nothing to do here, move along... | 
|  | } | 
|  |  | 
|  |  |