lok: Don't attempt to select the exact text after a failed search.
[LibreOffice.git] / comphelper / source / xml / ofopxmlhelper.cxx
blobd110a48c2145b740afae9b2727d334b2cf3b4725
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <com/sun/star/beans/StringPair.hpp>
22 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
23 #include <com/sun/star/io/XActiveDataSource.hpp>
24 #include <com/sun/star/xml/sax/Parser.hpp>
25 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
26 #include <com/sun/star/xml/sax/Writer.hpp>
27 #include <com/sun/star/lang/IllegalArgumentException.hpp>
29 #include <comphelper/ofopxmlhelper.hxx>
30 #include <comphelper/attributelist.hxx>
32 #define RELATIONINFO_FORMAT 0
33 #define CONTENTTYPE_FORMAT 1
34 #define FORMAT_MAX_ID CONTENTTYPE_FORMAT
36 using namespace ::com::sun::star;
38 namespace comphelper {
40 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadRelationsInfoSequence( const uno::Reference< io::XInputStream >& xInStream, const OUString & aStreamName, const uno::Reference< uno::XComponentContext >& rContext )
41 throw( uno::Exception )
43 OUString aStringID = "_rels/";
44 aStringID += aStreamName;
45 return ReadSequence_Impl( xInStream, aStringID, RELATIONINFO_FORMAT, rContext );
49 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadContentTypeSequence( const uno::Reference< io::XInputStream >& xInStream, const uno::Reference< uno::XComponentContext >& rContext )
50 throw( uno::Exception )
52 OUString aStringID = "[Content_Types].xml";
53 return ReadSequence_Impl( xInStream, aStringID, CONTENTTYPE_FORMAT, rContext );
57 void SAL_CALL OFOPXMLHelper::WriteRelationsInfoSequence( const uno::Reference< io::XOutputStream >& xOutStream, const uno::Sequence< uno::Sequence< beans::StringPair > >& aSequence, const uno::Reference< uno::XComponentContext >& rContext )
58 throw( uno::Exception )
60 if ( !xOutStream.is() )
61 throw uno::RuntimeException();
63 uno::Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create(rContext);
65 xWriter->setOutputStream( xOutStream );
67 OUString aRelListElement( "Relationships" );
68 OUString aRelElement( "Relationship" );
69 OUString aIDAttr( "Id" );
70 OUString aTypeAttr( "Type" );
71 OUString aTargetModeAttr( "TargetMode" );
72 OUString aTargetAttr( "Target" );
73 OUString aCDATAString( "CDATA" );
74 OUString aWhiteSpace( " " );
76 // write the namespace
77 AttributeList* pRootAttrList = new AttributeList;
78 uno::Reference< xml::sax::XAttributeList > xRootAttrList( pRootAttrList );
79 pRootAttrList->AddAttribute(
80 OUString( "xmlns" ),
81 aCDATAString,
82 OUString( "http://schemas.openxmlformats.org/package/2006/relationships" ) );
84 xWriter->startDocument();
85 xWriter->startElement( aRelListElement, xRootAttrList );
87 for ( sal_Int32 nInd = 0; nInd < aSequence.getLength(); nInd++ )
89 AttributeList *pAttrList = new AttributeList;
90 uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList );
91 for( sal_Int32 nSecInd = 0; nSecInd < aSequence[nInd].getLength(); nSecInd++ )
93 if ( aSequence[nInd][nSecInd].First.equals( aIDAttr )
94 || aSequence[nInd][nSecInd].First.equals( aTypeAttr )
95 || aSequence[nInd][nSecInd].First.equals( aTargetModeAttr )
96 || aSequence[nInd][nSecInd].First.equals( aTargetAttr ) )
98 pAttrList->AddAttribute( aSequence[nInd][nSecInd].First, aCDATAString, aSequence[nInd][nSecInd].Second );
100 else
102 // TODO/LATER: should the extensions be allowed?
103 throw lang::IllegalArgumentException();
107 xWriter->startElement( aRelElement, xAttrList );
108 xWriter->ignorableWhitespace( aWhiteSpace );
109 xWriter->endElement( aRelElement );
112 xWriter->ignorableWhitespace( aWhiteSpace );
113 xWriter->endElement( aRelListElement );
114 xWriter->endDocument();
118 void SAL_CALL OFOPXMLHelper::WriteContentSequence( const uno::Reference< io::XOutputStream >& xOutStream, const uno::Sequence< beans::StringPair >& aDefaultsSequence, const uno::Sequence< beans::StringPair >& aOverridesSequence, const uno::Reference< uno::XComponentContext >& rContext )
119 throw( uno::Exception )
121 if ( !xOutStream.is() )
122 throw uno::RuntimeException();
124 uno::Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create(rContext);
126 xWriter->setOutputStream( xOutStream );
128 OUString aTypesElement( "Types" );
129 OUString aDefaultElement( "Default" );
130 OUString aOverrideElement( "Override" );
131 OUString aExtensionAttr( "Extension" );
132 OUString aPartNameAttr( "PartName" );
133 OUString aContentTypeAttr( "ContentType" );
134 OUString aCDATAString( "CDATA" );
135 OUString aWhiteSpace( " " );
137 // write the namespace
138 AttributeList* pRootAttrList = new AttributeList;
139 uno::Reference< xml::sax::XAttributeList > xRootAttrList( pRootAttrList );
140 pRootAttrList->AddAttribute(
141 OUString( "xmlns" ),
142 aCDATAString,
143 OUString( "http://schemas.openxmlformats.org/package/2006/content-types" ) );
145 xWriter->startDocument();
146 xWriter->startElement( aTypesElement, xRootAttrList );
148 for ( sal_Int32 nInd = 0; nInd < aDefaultsSequence.getLength(); nInd++ )
150 AttributeList *pAttrList = new AttributeList;
151 uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList );
152 pAttrList->AddAttribute( aExtensionAttr, aCDATAString, aDefaultsSequence[nInd].First );
153 pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aDefaultsSequence[nInd].Second );
155 xWriter->startElement( aDefaultElement, xAttrList );
156 xWriter->ignorableWhitespace( aWhiteSpace );
157 xWriter->endElement( aDefaultElement );
160 for ( sal_Int32 nInd = 0; nInd < aOverridesSequence.getLength(); nInd++ )
162 AttributeList *pAttrList = new AttributeList;
163 uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList );
164 pAttrList->AddAttribute( aPartNameAttr, aCDATAString, aOverridesSequence[nInd].First );
165 pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aOverridesSequence[nInd].Second );
167 xWriter->startElement( aOverrideElement, xAttrList );
168 xWriter->ignorableWhitespace( aWhiteSpace );
169 xWriter->endElement( aOverrideElement );
172 xWriter->ignorableWhitespace( aWhiteSpace );
173 xWriter->endElement( aTypesElement );
174 xWriter->endDocument();
178 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadSequence_Impl( const uno::Reference< io::XInputStream >& xInStream, const OUString& aStringID, sal_uInt16 nFormat, const uno::Reference< uno::XComponentContext >& rContext )
179 throw( uno::Exception )
181 if ( !rContext.is() || !xInStream.is() || nFormat > FORMAT_MAX_ID )
182 throw uno::RuntimeException();
184 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create( rContext );
186 OFOPXMLHelper* pHelper = new OFOPXMLHelper( nFormat );
187 uno::Reference< xml::sax::XDocumentHandler > xHelper( static_cast< xml::sax::XDocumentHandler* >( pHelper ) );
188 xml::sax::InputSource aParserInput;
189 aParserInput.aInputStream = xInStream;
190 aParserInput.sSystemId = aStringID;
191 xParser->setDocumentHandler( xHelper );
192 xParser->parseStream( aParserInput );
193 xParser->setDocumentHandler( uno::Reference < xml::sax::XDocumentHandler > () );
195 return pHelper->GetParsingResult();
198 OFOPXMLHelper::OFOPXMLHelper( sal_uInt16 nFormat )
199 : m_nFormat( nFormat )
200 , m_aRelListElement( "Relationships" )
201 , m_aRelElement( "Relationship" )
202 , m_aIDAttr( "Id" )
203 , m_aTypeAttr( "Type" )
204 , m_aTargetModeAttr( "TargetMode" )
205 , m_aTargetAttr( "Target" )
206 , m_aTypesElement( "Types" )
207 , m_aDefaultElement( "Default" )
208 , m_aOverrideElement( "Override" )
209 , m_aExtensionAttr( "Extension" )
210 , m_aPartNameAttr( "PartName" )
211 , m_aContentTypeAttr( "ContentType" )
216 OFOPXMLHelper::~OFOPXMLHelper()
221 uno::Sequence< uno::Sequence< beans::StringPair > > OFOPXMLHelper::GetParsingResult()
223 if ( m_aElementsSeq.getLength() )
224 throw uno::RuntimeException(); // the parsing has still not finished!
226 return m_aResultSeq;
230 void SAL_CALL OFOPXMLHelper::startDocument()
231 throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
236 void SAL_CALL OFOPXMLHelper::endDocument()
237 throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
242 void SAL_CALL OFOPXMLHelper::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs )
243 throw( xml::sax::SAXException, uno::RuntimeException, std::exception )
245 if ( m_nFormat == RELATIONINFO_FORMAT )
247 if ( aName == m_aRelListElement )
249 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
251 if ( nNewLength != 1 )
252 throw xml::sax::SAXException(); // TODO: this element must be the first level element
254 m_aElementsSeq.realloc( nNewLength );
255 m_aElementsSeq[nNewLength-1] = aName;
257 return; // nothing to do
259 else if ( aName == m_aRelElement )
261 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
262 if ( nNewLength != 2 )
263 throw xml::sax::SAXException(); // TODO: this element must be the second level element
265 m_aElementsSeq.realloc( nNewLength );
266 m_aElementsSeq[nNewLength-1] = aName;
268 sal_Int32 nNewEntryNum = m_aResultSeq.getLength() + 1;
269 m_aResultSeq.realloc( nNewEntryNum );
270 sal_Int32 nAttrNum = 0;
271 m_aResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4
273 OUString aIDValue = xAttribs->getValueByName( m_aIDAttr );
274 if ( aIDValue.isEmpty() )
275 throw xml::sax::SAXException(); // TODO: the ID value must present
277 OUString aTypeValue = xAttribs->getValueByName( m_aTypeAttr );
278 OUString aTargetValue = xAttribs->getValueByName( m_aTargetAttr );
279 OUString aTargetModeValue = xAttribs->getValueByName( m_aTargetModeAttr );
281 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aIDAttr;
282 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aIDValue;
284 if ( !aTypeValue.isEmpty() )
286 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTypeAttr;
287 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTypeValue;
290 if ( !aTargetValue.isEmpty() )
292 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTargetAttr;
293 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetValue;
296 if ( !aTargetModeValue.isEmpty() )
298 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTargetModeAttr;
299 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetModeValue;
302 m_aResultSeq[nNewEntryNum-1].realloc( nAttrNum );
304 else
305 throw xml::sax::SAXException(); // TODO: no other elements expected!
307 else if ( m_nFormat == CONTENTTYPE_FORMAT )
309 if ( aName == m_aTypesElement )
311 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
313 if ( nNewLength != 1 )
314 throw xml::sax::SAXException(); // TODO: this element must be the first level element
316 m_aElementsSeq.realloc( nNewLength );
317 m_aElementsSeq[nNewLength-1] = aName;
319 if ( !m_aResultSeq.getLength() )
320 m_aResultSeq.realloc( 2 );
322 return; // nothing to do
324 else if ( aName == m_aDefaultElement )
326 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
327 if ( nNewLength != 2 )
328 throw xml::sax::SAXException(); // TODO: this element must be the second level element
330 m_aElementsSeq.realloc( nNewLength );
331 m_aElementsSeq[nNewLength-1] = aName;
333 if ( !m_aResultSeq.getLength() )
334 m_aResultSeq.realloc( 2 );
336 if ( m_aResultSeq.getLength() != 2 )
337 throw uno::RuntimeException();
339 OUString aExtensionValue = xAttribs->getValueByName( m_aExtensionAttr );
340 if ( aExtensionValue.isEmpty() )
341 throw xml::sax::SAXException(); // TODO: the Extension value must present
343 OUString aContentTypeValue = xAttribs->getValueByName( m_aContentTypeAttr );
344 if ( aContentTypeValue.isEmpty() )
345 throw xml::sax::SAXException(); // TODO: the ContentType value must present
347 sal_Int32 nNewResultLen = m_aResultSeq[0].getLength() + 1;
348 m_aResultSeq[0].realloc( nNewResultLen );
350 m_aResultSeq[0][nNewResultLen-1].First = aExtensionValue;
351 m_aResultSeq[0][nNewResultLen-1].Second = aContentTypeValue;
353 else if ( aName == m_aOverrideElement )
355 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
356 if ( nNewLength != 2 )
357 throw xml::sax::SAXException(); // TODO: this element must be the second level element
359 m_aElementsSeq.realloc( nNewLength );
360 m_aElementsSeq[nNewLength-1] = aName;
362 if ( !m_aResultSeq.getLength() )
363 m_aResultSeq.realloc( 2 );
365 if ( m_aResultSeq.getLength() != 2 )
366 throw uno::RuntimeException();
368 OUString aPartNameValue = xAttribs->getValueByName( m_aPartNameAttr );
369 if ( aPartNameValue.isEmpty() )
370 throw xml::sax::SAXException(); // TODO: the PartName value must present
372 OUString aContentTypeValue = xAttribs->getValueByName( m_aContentTypeAttr );
373 if ( aContentTypeValue.isEmpty() )
374 throw xml::sax::SAXException(); // TODO: the ContentType value must present
376 sal_Int32 nNewResultLen = m_aResultSeq[1].getLength() + 1;
377 m_aResultSeq[1].realloc( nNewResultLen );
379 m_aResultSeq[1][nNewResultLen-1].First = aPartNameValue;
380 m_aResultSeq[1][nNewResultLen-1].Second = aContentTypeValue;
382 else
383 throw xml::sax::SAXException(); // TODO: no other elements expected!
385 else
386 throw xml::sax::SAXException(); // TODO: no other elements expected!
390 void SAL_CALL OFOPXMLHelper::endElement( const OUString& aName )
391 throw( xml::sax::SAXException, uno::RuntimeException, std::exception )
393 if ( m_nFormat == RELATIONINFO_FORMAT || m_nFormat == CONTENTTYPE_FORMAT )
395 sal_Int32 nLength = m_aElementsSeq.getLength();
396 if ( nLength <= 0 )
397 throw xml::sax::SAXException(); // TODO: no other end elements expected!
399 if ( !m_aElementsSeq[nLength-1].equals( aName ) )
400 throw xml::sax::SAXException(); // TODO: unexpected element ended
402 m_aElementsSeq.realloc( nLength - 1 );
407 void SAL_CALL OFOPXMLHelper::characters( const OUString& /*aChars*/ )
408 throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
413 void SAL_CALL OFOPXMLHelper::ignorableWhitespace( const OUString& /*aWhitespaces*/ )
414 throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
419 void SAL_CALL OFOPXMLHelper::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ )
420 throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
425 void SAL_CALL OFOPXMLHelper::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ )
426 throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
430 } // namespace comphelper
432 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */