| /************************************************************** |
| * |
| * 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 "XMLRedlineExport.hxx" |
| #include <tools/debug.hxx> |
| #include <rtl/ustring.hxx> |
| #include <rtl/ustrbuf.hxx> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/beans/UnknownPropertyException.hpp> |
| #include <com/sun/star/container/XEnumerationAccess.hpp> |
| |
| #include <com/sun/star/container/XEnumeration.hpp> |
| #include <com/sun/star/document/XRedlinesSupplier.hpp> |
| #include <com/sun/star/text/XText.hpp> |
| #include <com/sun/star/text/XTextContent.hpp> |
| #include <com/sun/star/text/XTextSection.hpp> |
| #include <com/sun/star/util/DateTime.hpp> |
| #include <xmloff/xmltoken.hxx> |
| #include "xmloff/xmlnmspe.hxx" |
| #include <xmloff/xmlexp.hxx> |
| #include <xmloff/xmluconv.hxx> |
| |
| |
| using namespace ::com::sun::star; |
| using namespace ::xmloff::token; |
| |
| using ::com::sun::star::beans::PropertyValue; |
| using ::com::sun::star::beans::XPropertySet; |
| using ::com::sun::star::beans::UnknownPropertyException; |
| using ::com::sun::star::document::XRedlinesSupplier; |
| using ::com::sun::star::container::XEnumerationAccess; |
| using ::com::sun::star::container::XEnumeration; |
| using ::com::sun::star::text::XText; |
| using ::com::sun::star::text::XTextContent; |
| using ::com::sun::star::text::XTextSection; |
| using ::com::sun::star::uno::Any; |
| using ::com::sun::star::uno::Reference; |
| using ::com::sun::star::uno::Sequence; |
| using ::com::sun::star::util::DateTime; |
| using ::rtl::OUString; |
| using ::rtl::OUStringBuffer; |
| using ::std::list; |
| |
| |
| XMLRedlineExport::XMLRedlineExport(SvXMLExport& rExp) |
| : sDelete(RTL_CONSTASCII_USTRINGPARAM("Delete")) |
| , sDeletion(GetXMLToken(XML_DELETION)) |
| , sFormat(RTL_CONSTASCII_USTRINGPARAM("Format")) |
| , sFormatChange(GetXMLToken(XML_FORMAT_CHANGE)) |
| , sInsert(RTL_CONSTASCII_USTRINGPARAM("Insert")) |
| , sInsertion(GetXMLToken(XML_INSERTION)) |
| , sIsCollapsed(RTL_CONSTASCII_USTRINGPARAM("IsCollapsed")) |
| , sIsStart(RTL_CONSTASCII_USTRINGPARAM("IsStart")) |
| , sRedlineAuthor(RTL_CONSTASCII_USTRINGPARAM("RedlineAuthor")) |
| , sRedlineComment(RTL_CONSTASCII_USTRINGPARAM("RedlineComment")) |
| , sRedlineDateTime(RTL_CONSTASCII_USTRINGPARAM("RedlineDateTime")) |
| , sRedlineSuccessorData(RTL_CONSTASCII_USTRINGPARAM("RedlineSuccessorData")) |
| , sRedlineText(RTL_CONSTASCII_USTRINGPARAM("RedlineText")) |
| , sRedlineType(RTL_CONSTASCII_USTRINGPARAM("RedlineType")) |
| , sStyle(RTL_CONSTASCII_USTRINGPARAM("Style")) |
| , sTextTable(RTL_CONSTASCII_USTRINGPARAM("TextTable")) |
| , sUnknownChange(RTL_CONSTASCII_USTRINGPARAM("UnknownChange")) |
| , sStartRedline(RTL_CONSTASCII_USTRINGPARAM("StartRedline")) |
| , sEndRedline(RTL_CONSTASCII_USTRINGPARAM("EndRedline")) |
| , sRedlineIdentifier(RTL_CONSTASCII_USTRINGPARAM("RedlineIdentifier")) |
| , sIsInHeaderFooter(RTL_CONSTASCII_USTRINGPARAM("IsInHeaderFooter")) |
| , sRedlineProtectionKey(RTL_CONSTASCII_USTRINGPARAM("RedlineProtectionKey")) |
| , sRecordChanges(RTL_CONSTASCII_USTRINGPARAM("RecordChanges")) |
| , sMergeLastPara(RTL_CONSTASCII_USTRINGPARAM("MergeLastPara")) |
| , sChangePrefix(RTL_CONSTASCII_USTRINGPARAM("ct")) |
| , rExport(rExp) |
| , pCurrentChangesList(NULL) |
| { |
| } |
| |
| |
| XMLRedlineExport::~XMLRedlineExport() |
| { |
| // delete changes lists |
| for( ChangesMapType::iterator aIter = aChangeMap.begin(); |
| aIter != aChangeMap.end(); |
| aIter++ ) |
| { |
| delete aIter->second; |
| } |
| aChangeMap.clear(); |
| } |
| |
| |
| void XMLRedlineExport::ExportChange( |
| const Reference<XPropertySet> & rPropSet, |
| sal_Bool bAutoStyle) |
| { |
| if (bAutoStyle) |
| { |
| // For the headers/footers, we have to collect the autostyles |
| // here. For the general case, however, it's better to collet |
| // the autostyles by iterating over the global redline |
| // list. So that's what we do: Here, we collect autostyles |
| // only if we have no current list of changes. For the |
| // main-document case, the autostyles are collected in |
| // ExportChangesListAutoStyles(). |
| if (pCurrentChangesList != NULL) |
| ExportChangeAutoStyle(rPropSet); |
| } |
| else |
| { |
| ExportChangeInline(rPropSet); |
| } |
| } |
| |
| |
| void XMLRedlineExport::ExportChangesList(sal_Bool bAutoStyles) |
| { |
| if (bAutoStyles) |
| { |
| ExportChangesListAutoStyles(); |
| } |
| else |
| { |
| ExportChangesListElements(); |
| } |
| } |
| |
| |
| void XMLRedlineExport::ExportChangesList( |
| const Reference<XText> & rText, |
| sal_Bool bAutoStyles) |
| { |
| // in the header/footer case, auto styles are collected from the |
| // inline change elements. |
| if (bAutoStyles) |
| return; |
| |
| // look for changes list for this XText |
| ChangesMapType::iterator aFind = aChangeMap.find(rText); |
| if (aFind != aChangeMap.end()) |
| { |
| ChangesListType* pChangesList = aFind->second; |
| |
| // export only if changes are found |
| if (pChangesList->size() > 0) |
| { |
| // changes container element |
| SvXMLElementExport aChanges(rExport, XML_NAMESPACE_TEXT, |
| XML_TRACKED_CHANGES, |
| sal_True, sal_True); |
| |
| // iterate over changes list |
| for( ChangesListType::iterator aIter = pChangesList->begin(); |
| aIter != pChangesList->end(); |
| aIter++ ) |
| { |
| ExportChangedRegion( *aIter ); |
| } |
| } |
| // else: changes list empty -> ignore |
| } |
| // else: no changes list found -> empty |
| } |
| |
| void XMLRedlineExport::SetCurrentXText( |
| const Reference<XText> & rText) |
| { |
| if (rText.is()) |
| { |
| // look for appropriate list in map; use the found one, or create new |
| ChangesMapType::iterator aIter = aChangeMap.find(rText); |
| if (aIter == aChangeMap.end()) |
| { |
| ChangesListType* pList = new ChangesListType; |
| aChangeMap[rText] = pList; |
| pCurrentChangesList = pList; |
| } |
| else |
| pCurrentChangesList = aIter->second; |
| } |
| else |
| { |
| // don't record changes |
| SetCurrentXText(); |
| } |
| } |
| |
| void XMLRedlineExport::SetCurrentXText() |
| { |
| pCurrentChangesList = NULL; |
| } |
| |
| |
| void XMLRedlineExport::ExportChangesListElements() |
| { |
| // get redlines (aka tracked changes) from the model |
| Reference<XRedlinesSupplier> xSupplier(rExport.GetModel(), uno::UNO_QUERY); |
| if (xSupplier.is()) |
| { |
| Reference<XEnumerationAccess> aEnumAccess = xSupplier->getRedlines(); |
| |
| // redline protection key |
| Reference<XPropertySet> aDocPropertySet( rExport.GetModel(), |
| uno::UNO_QUERY ); |
| // redlining enabled? |
| sal_Bool bEnabled = *(sal_Bool*)aDocPropertySet->getPropertyValue( |
| sRecordChanges ).getValue(); |
| |
| // only export if we have redlines or attributes |
| if ( aEnumAccess->hasElements() || bEnabled ) |
| { |
| |
| // export only if we have changes, but tracking is not enabled |
| if ( !bEnabled != !aEnumAccess->hasElements() ) |
| { |
| rExport.AddAttribute( |
| XML_NAMESPACE_TEXT, XML_TRACK_CHANGES, |
| bEnabled ? XML_TRUE : XML_FALSE ); |
| } |
| |
| // changes container element |
| SvXMLElementExport aChanges(rExport, XML_NAMESPACE_TEXT, |
| XML_TRACKED_CHANGES, |
| sal_True, sal_True); |
| |
| // get enumeration and iterate over elements |
| Reference<XEnumeration> aEnum = aEnumAccess->createEnumeration(); |
| while (aEnum->hasMoreElements()) |
| { |
| Any aAny = aEnum->nextElement(); |
| Reference<XPropertySet> xPropSet; |
| aAny >>= xPropSet; |
| |
| DBG_ASSERT(xPropSet.is(), |
| "can't get XPropertySet; skipping Redline"); |
| if (xPropSet.is()) |
| { |
| // export only if not in header or footer |
| // (those must be exported with their XText) |
| aAny = xPropSet->getPropertyValue(sIsInHeaderFooter); |
| if (! *(sal_Bool*)aAny.getValue()) |
| { |
| // and finally, export change |
| ExportChangedRegion(xPropSet); |
| } |
| } |
| // else: no XPropertySet -> no export |
| } |
| } |
| // else: no redlines -> no export |
| } |
| // else: no XRedlineSupplier -> no export |
| } |
| |
| void XMLRedlineExport::ExportChangeAutoStyle( |
| const Reference<XPropertySet> & rPropSet) |
| { |
| // record change (if changes should be recorded) |
| if (NULL != pCurrentChangesList) |
| { |
| // put redline in list if it's collapsed or the redline start |
| Any aIsStart = rPropSet->getPropertyValue(sIsStart); |
| Any aIsCollapsed = rPropSet->getPropertyValue(sIsCollapsed); |
| |
| if ( *(sal_Bool*)aIsStart.getValue() || |
| *(sal_Bool*)aIsCollapsed.getValue() ) |
| pCurrentChangesList->push_back(rPropSet); |
| } |
| |
| // get XText for export of redline auto styles |
| Any aAny = rPropSet->getPropertyValue(sRedlineText); |
| Reference<XText> xText; |
| aAny >>= xText; |
| if (xText.is()) |
| { |
| // export the auto styles |
| rExport.GetTextParagraphExport()->collectTextAutoStyles(xText); |
| } |
| } |
| |
| void XMLRedlineExport::ExportChangesListAutoStyles() |
| { |
| // get redlines (aka tracked changes) from the model |
| Reference<XRedlinesSupplier> xSupplier(rExport.GetModel(), uno::UNO_QUERY); |
| if (xSupplier.is()) |
| { |
| Reference<XEnumerationAccess> aEnumAccess = xSupplier->getRedlines(); |
| |
| // only export if we actually have redlines |
| if (aEnumAccess->hasElements()) |
| { |
| // get enumeration and iterate over elements |
| Reference<XEnumeration> aEnum = aEnumAccess->createEnumeration(); |
| while (aEnum->hasMoreElements()) |
| { |
| Any aAny = aEnum->nextElement(); |
| Reference<XPropertySet> xPropSet; |
| aAny >>= xPropSet; |
| |
| DBG_ASSERT(xPropSet.is(), |
| "can't get XPropertySet; skipping Redline"); |
| if (xPropSet.is()) |
| { |
| |
| // export only if not in header or footer |
| // (those must be exported with their XText) |
| aAny = xPropSet->getPropertyValue(sIsInHeaderFooter); |
| if (! *(sal_Bool*)aAny.getValue()) |
| { |
| ExportChangeAutoStyle(xPropSet); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| void XMLRedlineExport::ExportChangeInline( |
| const Reference<XPropertySet> & rPropSet) |
| { |
| // determine element name (depending on collapsed, start/end) |
| enum XMLTokenEnum eElement = XML_TOKEN_INVALID; |
| Any aAny = rPropSet->getPropertyValue(sIsCollapsed); |
| sal_Bool bCollapsed = *(sal_Bool *)aAny.getValue(); |
| sal_Bool bStart = sal_True; // ignored if bCollapsed = sal_True |
| if (bCollapsed) |
| { |
| eElement = XML_CHANGE; |
| } |
| else |
| { |
| aAny = rPropSet->getPropertyValue(sIsStart); |
| bStart = *(sal_Bool *)aAny.getValue(); |
| eElement = bStart ? XML_CHANGE_START : XML_CHANGE_END; |
| } |
| |
| if (XML_TOKEN_INVALID != eElement) |
| { |
| // we always need the ID |
| rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_CHANGE_ID, |
| GetRedlineID(rPropSet)); |
| |
| // export the element (no whitespace because we're in the text body) |
| SvXMLElementExport aChangeElem(rExport, XML_NAMESPACE_TEXT, |
| eElement, sal_False, sal_False); |
| } |
| } |
| |
| |
| void XMLRedlineExport::ExportChangedRegion( |
| const Reference<XPropertySet> & rPropSet) |
| { |
| // Redline-ID |
| rExport.AddAttributeIdLegacy(XML_NAMESPACE_TEXT, GetRedlineID(rPropSet)); |
| |
| // merge-last-paragraph |
| Any aAny = rPropSet->getPropertyValue(sMergeLastPara); |
| if( ! *(sal_Bool*)aAny.getValue() ) |
| rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_MERGE_LAST_PARAGRAPH, |
| XML_FALSE); |
| |
| // export change region element |
| SvXMLElementExport aChangedRegion(rExport, XML_NAMESPACE_TEXT, |
| XML_CHANGED_REGION, sal_True, sal_True); |
| |
| |
| // scope for (first) change element |
| { |
| aAny = rPropSet->getPropertyValue(sRedlineType); |
| OUString sType; |
| aAny >>= sType; |
| SvXMLElementExport aChange(rExport, XML_NAMESPACE_TEXT, |
| ConvertTypeName(sType), sal_True, sal_True); |
| |
| ExportChangeInfo(rPropSet); |
| |
| // get XText from the redline and export (if the XText exists) |
| aAny = rPropSet->getPropertyValue(sRedlineText); |
| Reference<XText> xText; |
| aAny >>= xText; |
| if (xText.is()) |
| { |
| rExport.GetTextParagraphExport()->exportText(xText); |
| // default parameters: bProgress, bExportParagraph ??? |
| } |
| // else: no text interface -> content is inline and will |
| // be exported there |
| } |
| |
| // changed change? Hierarchical changes can onl be two levels |
| // deep. Here we check for the second level. |
| aAny = rPropSet->getPropertyValue(sRedlineSuccessorData); |
| Sequence<PropertyValue> aSuccessorData; |
| aAny >>= aSuccessorData; |
| |
| // if we actually got a hierarchical change, make element and |
| // process change info |
| if (aSuccessorData.getLength() > 0) |
| { |
| // The only change that can be "undone" is an insertion - |
| // after all, you can't re-insert an deletion, but you can |
| // delete an insertion. This assumption is asserted in |
| // ExportChangeInfo(Sequence<PropertyValue>&). |
| SvXMLElementExport aSecondChangeElem( |
| rExport, XML_NAMESPACE_TEXT, XML_INSERTION, |
| sal_True, sal_True); |
| |
| ExportChangeInfo(aSuccessorData); |
| } |
| // else: no hierarchical change |
| } |
| |
| |
| const OUString XMLRedlineExport::ConvertTypeName( |
| const OUString& sApiName) |
| { |
| if (sApiName == sDelete) |
| { |
| return sDeletion; |
| } |
| else if (sApiName == sInsert) |
| { |
| return sInsertion; |
| } |
| else if (sApiName == sFormat) |
| { |
| return sFormatChange; |
| } |
| else |
| { |
| DBG_ERROR("unknown redline type"); |
| return sUnknownChange; |
| } |
| } |
| |
| |
| /** Create a Redline-ID */ |
| const OUString XMLRedlineExport::GetRedlineID( |
| const Reference<XPropertySet> & rPropSet) |
| { |
| Any aAny = rPropSet->getPropertyValue(sRedlineIdentifier); |
| OUString sTmp; |
| aAny >>= sTmp; |
| |
| OUStringBuffer sBuf(sChangePrefix); |
| sBuf.append(sTmp); |
| return sBuf.makeStringAndClear(); |
| } |
| |
| |
| void XMLRedlineExport::ExportChangeInfo( |
| const Reference<XPropertySet> & rPropSet) |
| { |
| |
| SvXMLElementExport aChangeInfo(rExport, XML_NAMESPACE_OFFICE, |
| XML_CHANGE_INFO, sal_True, sal_True); |
| |
| Any aAny = rPropSet->getPropertyValue(sRedlineAuthor); |
| OUString sTmp; |
| aAny >>= sTmp; |
| if (sTmp.getLength() > 0) |
| { |
| SvXMLElementExport aCreatorElem( rExport, XML_NAMESPACE_DC, |
| XML_CREATOR, sal_True, |
| sal_False ); |
| rExport.Characters(sTmp); |
| } |
| |
| aAny = rPropSet->getPropertyValue(sRedlineDateTime); |
| util::DateTime aDateTime; |
| aAny >>= aDateTime; |
| { |
| OUStringBuffer sBuf; |
| rExport.GetMM100UnitConverter().convertDateTime(sBuf, aDateTime); |
| SvXMLElementExport aDateElem( rExport, XML_NAMESPACE_DC, |
| XML_DATE, sal_True, |
| sal_False ); |
| rExport.Characters(sBuf.makeStringAndClear()); |
| } |
| |
| // comment as <text:p> sequence |
| aAny = rPropSet->getPropertyValue(sRedlineComment); |
| aAny >>= sTmp; |
| WriteComment( sTmp ); |
| } |
| |
| void XMLRedlineExport::ExportChangeInfo( |
| const Sequence<PropertyValue> & rPropertyValues) |
| { |
| OUString sComment; |
| |
| sal_Int32 nCount = rPropertyValues.getLength(); |
| for(sal_Int32 i = 0; i < nCount; i++) |
| { |
| const PropertyValue& rVal = rPropertyValues[i]; |
| |
| if( rVal.Name.equals(sRedlineAuthor) ) |
| { |
| OUString sTmp; |
| rVal.Value >>= sTmp; |
| if (sTmp.getLength() > 0) |
| { |
| rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_CHG_AUTHOR, sTmp); |
| } |
| } |
| else if( rVal.Name.equals(sRedlineComment) ) |
| { |
| rVal.Value >>= sComment; |
| } |
| else if( rVal.Name.equals(sRedlineDateTime) ) |
| { |
| util::DateTime aDateTime; |
| rVal.Value >>= aDateTime; |
| OUStringBuffer sBuf; |
| rExport.GetMM100UnitConverter().convertDateTime(sBuf, aDateTime); |
| rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_CHG_DATE_TIME, |
| sBuf.makeStringAndClear()); |
| } |
| else if( rVal.Name.equals(sRedlineType) ) |
| { |
| // check if this is an insertion; cf. comment at calling location |
| OUString sTmp; |
| rVal.Value >>= sTmp; |
| DBG_ASSERT(sTmp.equals(sInsert), |
| "hierarchical change must be insertion"); |
| } |
| // else: unknown value -> ignore |
| } |
| |
| // finally write element |
| SvXMLElementExport aChangeInfo(rExport, XML_NAMESPACE_OFFICE, |
| XML_CHANGE_INFO, sal_True, sal_True); |
| |
| WriteComment( sComment ); |
| } |
| |
| void XMLRedlineExport::ExportStartOrEndRedline( |
| const Reference<XPropertySet> & rPropSet, |
| sal_Bool bStart) |
| { |
| if( ! rPropSet.is() ) |
| return; |
| |
| // get appropriate (start or end) property |
| Any aAny; |
| try |
| { |
| aAny = rPropSet->getPropertyValue(bStart ? sStartRedline : sEndRedline); |
| } |
| catch( UnknownPropertyException e ) |
| { |
| // If we don't have the property, there's nothing to do. |
| return; |
| } |
| |
| Sequence<PropertyValue> aValues; |
| aAny >>= aValues; |
| const PropertyValue* pValues = aValues.getConstArray(); |
| |
| // seek for redline properties |
| sal_Bool bIsCollapsed = sal_False; |
| sal_Bool bIsStart = sal_True; |
| OUString sId; |
| sal_Bool bIdOK = sal_False; // have we seen an ID? |
| sal_Int32 nLength = aValues.getLength(); |
| for(sal_Int32 i = 0; i < nLength; i++) |
| { |
| if (sRedlineIdentifier.equals(pValues[i].Name)) |
| { |
| pValues[i].Value >>= sId; |
| bIdOK = sal_True; |
| } |
| else if (sIsCollapsed.equals(pValues[i].Name)) |
| { |
| bIsCollapsed = *(sal_Bool*)pValues[i].Value.getValue(); |
| } |
| else if (sIsStart.equals(pValues[i].Name)) |
| { |
| bIsStart = *(sal_Bool*)pValues[i].Value.getValue(); |
| } |
| } |
| |
| if( bIdOK ) |
| { |
| DBG_ASSERT( sId.getLength() > 0, "Redlines must have IDs" ); |
| |
| // TODO: use GetRedlineID or elimiate that function |
| OUStringBuffer sBuffer(sChangePrefix); |
| sBuffer.append(sId); |
| |
| rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_CHANGE_ID, |
| sBuffer.makeStringAndClear()); |
| |
| // export the element |
| // (whitespace because we're not inside paragraphs) |
| SvXMLElementExport aChangeElem( |
| rExport, XML_NAMESPACE_TEXT, |
| bIsCollapsed ? XML_CHANGE : |
| ( bIsStart ? XML_CHANGE_START : XML_CHANGE_END ), |
| sal_True, sal_True); |
| } |
| } |
| |
| void XMLRedlineExport::ExportStartOrEndRedline( |
| const Reference<XTextContent> & rContent, |
| sal_Bool bStart) |
| { |
| Reference<XPropertySet> xPropSet(rContent, uno::UNO_QUERY); |
| if (xPropSet.is()) |
| { |
| ExportStartOrEndRedline(xPropSet, bStart); |
| } |
| else |
| { |
| DBG_ERROR("XPropertySet expected"); |
| } |
| } |
| |
| void XMLRedlineExport::ExportStartOrEndRedline( |
| const Reference<XTextSection> & rSection, |
| sal_Bool bStart) |
| { |
| Reference<XPropertySet> xPropSet(rSection, uno::UNO_QUERY); |
| if (xPropSet.is()) |
| { |
| ExportStartOrEndRedline(xPropSet, bStart); |
| } |
| else |
| { |
| DBG_ERROR("XPropertySet expected"); |
| } |
| } |
| |
| void XMLRedlineExport::WriteComment(const OUString& rComment) |
| { |
| if (rComment.getLength() > 0) |
| { |
| // iterate over all string-pieces separated by return (0x0a) and |
| // put each inside a paragraph element. |
| SvXMLTokenEnumerator aEnumerator(rComment, sal_Char(0x0a)); |
| OUString aSubString; |
| while (aEnumerator.getNextToken(aSubString)) |
| { |
| SvXMLElementExport aParagraph( |
| rExport, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_False); |
| rExport.Characters(aSubString); |
| } |
| } |
| } |