1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*ca5ec200SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*ca5ec200SAndrew Rist * distributed with this work for additional information
6*ca5ec200SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*ca5ec200SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist * with the License. You may obtain a copy of the License at
10*ca5ec200SAndrew Rist *
11*ca5ec200SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*ca5ec200SAndrew Rist *
13*ca5ec200SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist * KIND, either express or implied. See the License for the
17*ca5ec200SAndrew Rist * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist * under the License.
19*ca5ec200SAndrew Rist *
20*ca5ec200SAndrew Rist *************************************************************/
21*ca5ec200SAndrew Rist
22*ca5ec200SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir #include "oox/core/contexthandler2.hxx"
25cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
26cdf0e10cSrcweir
27cdf0e10cSrcweir namespace oox {
28cdf0e10cSrcweir namespace core {
29cdf0e10cSrcweir
30cdf0e10cSrcweir // ============================================================================
31cdf0e10cSrcweir
32cdf0e10cSrcweir using namespace ::com::sun::star::uno;
33cdf0e10cSrcweir using namespace ::com::sun::star::xml::sax;
34cdf0e10cSrcweir
35cdf0e10cSrcweir using ::rtl::OUString;
36cdf0e10cSrcweir using ::rtl::OUStringBuffer;
37cdf0e10cSrcweir
38cdf0e10cSrcweir // ============================================================================
39cdf0e10cSrcweir
40cdf0e10cSrcweir /** Information about a processed element. */
41cdf0e10cSrcweir struct ElementInfo
42cdf0e10cSrcweir {
43cdf0e10cSrcweir OUStringBuffer maChars; /// Collected element characters.
44cdf0e10cSrcweir sal_Int32 mnElement; /// The element identifier.
45cdf0e10cSrcweir bool mbTrimSpaces; /// True = trims leading/trailing spaces from text data.
46cdf0e10cSrcweir
ElementInfooox::core::ElementInfo47cdf0e10cSrcweir inline explicit ElementInfo() : mnElement( XML_TOKEN_INVALID ), mbTrimSpaces( false ) {}
48cdf0e10cSrcweir };
49cdf0e10cSrcweir
50cdf0e10cSrcweir // ============================================================================
51cdf0e10cSrcweir
ContextHandler2Helper(bool bEnableTrimSpace)52cdf0e10cSrcweir ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace ) :
53cdf0e10cSrcweir mxContextStack( new ContextStack ),
54cdf0e10cSrcweir mnRootStackSize( 0 ),
55cdf0e10cSrcweir mbEnableTrimSpace( bEnableTrimSpace )
56cdf0e10cSrcweir {
57cdf0e10cSrcweir pushElementInfo( XML_ROOT_CONTEXT );
58cdf0e10cSrcweir }
59cdf0e10cSrcweir
ContextHandler2Helper(const ContextHandler2Helper & rParent)60cdf0e10cSrcweir ContextHandler2Helper::ContextHandler2Helper( const ContextHandler2Helper& rParent ) :
61cdf0e10cSrcweir mxContextStack( rParent.mxContextStack ),
62cdf0e10cSrcweir mnRootStackSize( rParent.mxContextStack->size() ),
63cdf0e10cSrcweir mbEnableTrimSpace( rParent.mbEnableTrimSpace )
64cdf0e10cSrcweir {
65cdf0e10cSrcweir }
66cdf0e10cSrcweir
~ContextHandler2Helper()67cdf0e10cSrcweir ContextHandler2Helper::~ContextHandler2Helper()
68cdf0e10cSrcweir {
69cdf0e10cSrcweir }
70cdf0e10cSrcweir
getCurrentElement() const71cdf0e10cSrcweir sal_Int32 ContextHandler2Helper::getCurrentElement() const
72cdf0e10cSrcweir {
73cdf0e10cSrcweir return mxContextStack->empty() ? XML_ROOT_CONTEXT : mxContextStack->back().mnElement;
74cdf0e10cSrcweir }
75cdf0e10cSrcweir
getParentElement(sal_Int32 nCountBack) const76cdf0e10cSrcweir sal_Int32 ContextHandler2Helper::getParentElement( sal_Int32 nCountBack ) const
77cdf0e10cSrcweir {
78cdf0e10cSrcweir if( (nCountBack < 0) || (mxContextStack->size() < static_cast< size_t >( nCountBack )) )
79cdf0e10cSrcweir return XML_TOKEN_INVALID;
80cdf0e10cSrcweir return (mxContextStack->size() == static_cast< size_t >( nCountBack )) ?
81cdf0e10cSrcweir XML_ROOT_CONTEXT : (*mxContextStack)[ mxContextStack->size() - nCountBack - 1 ].mnElement;
82cdf0e10cSrcweir }
83cdf0e10cSrcweir
isRootElement() const84cdf0e10cSrcweir bool ContextHandler2Helper::isRootElement() const
85cdf0e10cSrcweir {
86cdf0e10cSrcweir return mxContextStack->size() == mnRootStackSize + 1;
87cdf0e10cSrcweir }
88cdf0e10cSrcweir
implCreateChildContext(sal_Int32 nElement,const Reference<XFastAttributeList> & rxAttribs)89cdf0e10cSrcweir Reference< XFastContextHandler > ContextHandler2Helper::implCreateChildContext(
90cdf0e10cSrcweir sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs )
91cdf0e10cSrcweir {
92cdf0e10cSrcweir // #i76091# process collected characters (calls onCharacters() if needed)
93cdf0e10cSrcweir processCollectedChars();
94cdf0e10cSrcweir ContextHandlerRef xContext = onCreateContext( nElement, AttributeList( rxAttribs ) );
95cdf0e10cSrcweir return Reference< XFastContextHandler >( xContext.get() );
96cdf0e10cSrcweir }
97cdf0e10cSrcweir
implStartElement(sal_Int32 nElement,const Reference<XFastAttributeList> & rxAttribs)98cdf0e10cSrcweir void ContextHandler2Helper::implStartElement( sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs )
99cdf0e10cSrcweir {
100cdf0e10cSrcweir AttributeList aAttribs( rxAttribs );
101cdf0e10cSrcweir pushElementInfo( nElement ).mbTrimSpaces = aAttribs.getToken( XML_TOKEN( space ), XML_TOKEN_INVALID ) != XML_preserve;
102cdf0e10cSrcweir onStartElement( aAttribs );
103cdf0e10cSrcweir }
104cdf0e10cSrcweir
implCharacters(const OUString & rChars)105cdf0e10cSrcweir void ContextHandler2Helper::implCharacters( const OUString& rChars )
106cdf0e10cSrcweir {
107cdf0e10cSrcweir // #i76091# collect characters until new element starts or this element ends
108cdf0e10cSrcweir if( !mxContextStack->empty() )
109cdf0e10cSrcweir mxContextStack->back().maChars.append( rChars );
110cdf0e10cSrcweir }
111cdf0e10cSrcweir
implEndElement(sal_Int32 nElement)112cdf0e10cSrcweir void ContextHandler2Helper::implEndElement( sal_Int32 nElement )
113cdf0e10cSrcweir {
114cdf0e10cSrcweir (void)nElement; // prevent "unused parameter" warning in product build
115cdf0e10cSrcweir OSL_ENSURE( getCurrentElement() == nElement, "ContextHandler2Helper::implEndElement - context stack broken" );
116cdf0e10cSrcweir if( !mxContextStack->empty() )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir // #i76091# process collected characters (calls onCharacters() if needed)
119cdf0e10cSrcweir processCollectedChars();
120cdf0e10cSrcweir onEndElement();
121cdf0e10cSrcweir popElementInfo();
122cdf0e10cSrcweir }
123cdf0e10cSrcweir }
124cdf0e10cSrcweir
implCreateRecordContext(sal_Int32 nRecId,SequenceInputStream & rStrm)125cdf0e10cSrcweir ContextHandlerRef ContextHandler2Helper::implCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
126cdf0e10cSrcweir {
127cdf0e10cSrcweir return onCreateRecordContext( nRecId, rStrm );
128cdf0e10cSrcweir }
129cdf0e10cSrcweir
implStartRecord(sal_Int32 nRecId,SequenceInputStream & rStrm)130cdf0e10cSrcweir void ContextHandler2Helper::implStartRecord( sal_Int32 nRecId, SequenceInputStream& rStrm )
131cdf0e10cSrcweir {
132cdf0e10cSrcweir pushElementInfo( nRecId );
133cdf0e10cSrcweir onStartRecord( rStrm );
134cdf0e10cSrcweir }
135cdf0e10cSrcweir
implEndRecord(sal_Int32 nRecId)136cdf0e10cSrcweir void ContextHandler2Helper::implEndRecord( sal_Int32 nRecId )
137cdf0e10cSrcweir {
138cdf0e10cSrcweir (void)nRecId; // prevent "unused parameter" warning in product build
139cdf0e10cSrcweir OSL_ENSURE( getCurrentElement() == nRecId, "ContextHandler2Helper::implEndRecord - context stack broken" );
140cdf0e10cSrcweir if( !mxContextStack->empty() )
141cdf0e10cSrcweir {
142cdf0e10cSrcweir onEndRecord();
143cdf0e10cSrcweir popElementInfo();
144cdf0e10cSrcweir }
145cdf0e10cSrcweir }
146cdf0e10cSrcweir
pushElementInfo(sal_Int32 nElement)147cdf0e10cSrcweir ElementInfo& ContextHandler2Helper::pushElementInfo( sal_Int32 nElement )
148cdf0e10cSrcweir {
149cdf0e10cSrcweir mxContextStack->resize( mxContextStack->size() + 1 );
150cdf0e10cSrcweir ElementInfo& rInfo = mxContextStack->back();
151cdf0e10cSrcweir rInfo.mnElement = nElement;
152cdf0e10cSrcweir return rInfo;
153cdf0e10cSrcweir }
154cdf0e10cSrcweir
popElementInfo()155cdf0e10cSrcweir void ContextHandler2Helper::popElementInfo()
156cdf0e10cSrcweir {
157cdf0e10cSrcweir OSL_ENSURE( !mxContextStack->empty(), "ContextHandler2Helper::popElementInfo - context stack broken" );
158cdf0e10cSrcweir if( !mxContextStack->empty() )
159cdf0e10cSrcweir mxContextStack->pop_back();
160cdf0e10cSrcweir }
161cdf0e10cSrcweir
processCollectedChars()162cdf0e10cSrcweir void ContextHandler2Helper::processCollectedChars()
163cdf0e10cSrcweir {
164cdf0e10cSrcweir OSL_ENSURE( !mxContextStack->empty(), "ContextHandler2Helper::processCollectedChars - no context info" );
165cdf0e10cSrcweir ElementInfo& rInfo = mxContextStack->back();
166cdf0e10cSrcweir if( rInfo.maChars.getLength() > 0 )
167cdf0e10cSrcweir {
168cdf0e10cSrcweir OUString aChars = rInfo.maChars.makeStringAndClear();
169cdf0e10cSrcweir if( mbEnableTrimSpace && rInfo.mbTrimSpaces )
170cdf0e10cSrcweir aChars = aChars.trim();
171cdf0e10cSrcweir if( aChars.getLength() > 0 )
172cdf0e10cSrcweir onCharacters( aChars );
173cdf0e10cSrcweir }
174cdf0e10cSrcweir }
175cdf0e10cSrcweir
176cdf0e10cSrcweir // ============================================================================
177cdf0e10cSrcweir
ContextHandler2(ContextHandler2Helper & rParent)178cdf0e10cSrcweir ContextHandler2::ContextHandler2( ContextHandler2Helper& rParent ) :
179cdf0e10cSrcweir ContextHandler( dynamic_cast< ContextHandler& >( rParent ) ),
180cdf0e10cSrcweir ContextHandler2Helper( rParent )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir }
183cdf0e10cSrcweir
~ContextHandler2()184cdf0e10cSrcweir ContextHandler2::~ContextHandler2()
185cdf0e10cSrcweir {
186cdf0e10cSrcweir }
187cdf0e10cSrcweir
188cdf0e10cSrcweir // com.sun.star.xml.sax.XFastContextHandler interface -------------------------
189cdf0e10cSrcweir
createFastChildContext(sal_Int32 nElement,const Reference<XFastAttributeList> & rxAttribs)190cdf0e10cSrcweir Reference< XFastContextHandler > SAL_CALL ContextHandler2::createFastChildContext(
191cdf0e10cSrcweir sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw( SAXException, RuntimeException )
192cdf0e10cSrcweir {
193cdf0e10cSrcweir return implCreateChildContext( nElement, rxAttribs );
194cdf0e10cSrcweir }
195cdf0e10cSrcweir
startFastElement(sal_Int32 nElement,const Reference<XFastAttributeList> & rxAttribs)196cdf0e10cSrcweir void SAL_CALL ContextHandler2::startFastElement(
197cdf0e10cSrcweir sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw( SAXException, RuntimeException )
198cdf0e10cSrcweir {
199cdf0e10cSrcweir implStartElement( nElement, rxAttribs );
200cdf0e10cSrcweir }
201cdf0e10cSrcweir
characters(const OUString & rChars)202cdf0e10cSrcweir void SAL_CALL ContextHandler2::characters( const OUString& rChars ) throw( SAXException, RuntimeException )
203cdf0e10cSrcweir {
204cdf0e10cSrcweir implCharacters( rChars );
205cdf0e10cSrcweir }
206cdf0e10cSrcweir
endFastElement(sal_Int32 nElement)207cdf0e10cSrcweir void SAL_CALL ContextHandler2::endFastElement( sal_Int32 nElement ) throw( SAXException, RuntimeException )
208cdf0e10cSrcweir {
209cdf0e10cSrcweir implEndElement( nElement );
210cdf0e10cSrcweir }
211cdf0e10cSrcweir
212cdf0e10cSrcweir // oox.core.RecordContext interface -------------------------------------------
213cdf0e10cSrcweir
createRecordContext(sal_Int32 nRecId,SequenceInputStream & rStrm)214cdf0e10cSrcweir ContextHandlerRef ContextHandler2::createRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
215cdf0e10cSrcweir {
216cdf0e10cSrcweir return implCreateRecordContext( nRecId, rStrm );
217cdf0e10cSrcweir }
218cdf0e10cSrcweir
startRecord(sal_Int32 nRecId,SequenceInputStream & rStrm)219cdf0e10cSrcweir void ContextHandler2::startRecord( sal_Int32 nRecId, SequenceInputStream& rStrm )
220cdf0e10cSrcweir {
221cdf0e10cSrcweir implStartRecord( nRecId, rStrm );
222cdf0e10cSrcweir }
223cdf0e10cSrcweir
endRecord(sal_Int32 nRecId)224cdf0e10cSrcweir void ContextHandler2::endRecord( sal_Int32 nRecId )
225cdf0e10cSrcweir {
226cdf0e10cSrcweir implEndRecord( nRecId );
227cdf0e10cSrcweir }
228cdf0e10cSrcweir
229cdf0e10cSrcweir // oox.core.ContextHandler2Helper interface -----------------------------------
230cdf0e10cSrcweir
onCreateContext(sal_Int32,const AttributeList &)231cdf0e10cSrcweir ContextHandlerRef ContextHandler2::onCreateContext( sal_Int32, const AttributeList& )
232cdf0e10cSrcweir {
233cdf0e10cSrcweir return 0;
234cdf0e10cSrcweir }
235cdf0e10cSrcweir
onStartElement(const AttributeList &)236cdf0e10cSrcweir void ContextHandler2::onStartElement( const AttributeList& )
237cdf0e10cSrcweir {
238cdf0e10cSrcweir }
239cdf0e10cSrcweir
onCharacters(const OUString &)240cdf0e10cSrcweir void ContextHandler2::onCharacters( const OUString& )
241cdf0e10cSrcweir {
242cdf0e10cSrcweir }
243cdf0e10cSrcweir
onEndElement()244cdf0e10cSrcweir void ContextHandler2::onEndElement()
245cdf0e10cSrcweir {
246cdf0e10cSrcweir }
247cdf0e10cSrcweir
onCreateRecordContext(sal_Int32,SequenceInputStream &)248cdf0e10cSrcweir ContextHandlerRef ContextHandler2::onCreateRecordContext( sal_Int32, SequenceInputStream& )
249cdf0e10cSrcweir {
250cdf0e10cSrcweir return 0;
251cdf0e10cSrcweir }
252cdf0e10cSrcweir
onStartRecord(SequenceInputStream &)253cdf0e10cSrcweir void ContextHandler2::onStartRecord( SequenceInputStream& )
254cdf0e10cSrcweir {
255cdf0e10cSrcweir }
256cdf0e10cSrcweir
onEndRecord()257cdf0e10cSrcweir void ContextHandler2::onEndRecord()
258cdf0e10cSrcweir {
259cdf0e10cSrcweir }
260cdf0e10cSrcweir
261cdf0e10cSrcweir // ============================================================================
262cdf0e10cSrcweir
263cdf0e10cSrcweir } // namespace core
264cdf0e10cSrcweir } // namespace oox
265