xref: /aoo4110/main/sax/test/saxdemo.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 //------------------------------------------------------
25 // testcomponent - Loads a service and its testcomponent from dlls performs a test.
26 // Expands the dll-names depending on the actual environment.
27 // Example : testcomponent stardiv.uno.io.Pipe stm
28 //
29 // Therefor the testcode must exist in teststm and the testservice must be named test.stardiv.uno.io.Pipe
30 //
31 
32 #include <stdio.h>
33 #include <vector>
34 
35 #include <com/sun/star/registry/XImplementationRegistration.hpp>
36 #include <com/sun/star/lang/XComponent.hpp>
37 
38 #include <com/sun/star/xml/sax/SAXParseException.hpp>
39 #include <com/sun/star/xml/sax/XParser.hpp>
40 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
41 
42 #include <com/sun/star/io/XOutputStream.hpp>
43 #include <com/sun/star/io/XActiveDataSource.hpp>
44 
45 #include <cppuhelper/servicefactory.hxx>
46 #include <cppuhelper/implbase1.hxx>
47 #include <cppuhelper/implbase3.hxx>
48 
49 #include <vos/dynload.hxx>
50 #include <vos/diagnose.hxx>
51 
52 using namespace ::rtl;
53 using namespace ::std;
54 using namespace ::cppu;
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::lang;
57 using namespace ::com::sun::star::registry;
58 using namespace ::com::sun::star::xml::sax;
59 using namespace ::com::sun::star::io;
60 
61 
62 /************
63  * Sequence of bytes -> InputStream
64  ************/
65 class OInputStream : public WeakImplHelper1 < XInputStream >
66 {
67 public:
OInputStream(const Sequence<sal_Int8> & seq)68 	OInputStream( const Sequence< sal_Int8 >&seq ) :
69 		m_seq( seq ),
70 		nPos( 0 )
71 		{}
72 
73 public:
readBytes(Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)74     virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
75 		throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
76 		{
77 			nBytesToRead = (nBytesToRead > m_seq.getLength() - nPos ) ?
78 				m_seq.getLength() - nPos :
79 				nBytesToRead;
80 			aData = Sequence< sal_Int8 > ( &(m_seq.getConstArray()[nPos]) , nBytesToRead );
81 			nPos += nBytesToRead;
82 			return nBytesToRead;
83 		}
readSomeBytes(::com::sun::star::uno::Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)84     virtual sal_Int32 SAL_CALL readSomeBytes(
85 		::com::sun::star::uno::Sequence< sal_Int8 >& aData,
86 		sal_Int32 nMaxBytesToRead )
87 		throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
88 		{
89 			return readBytes( aData, nMaxBytesToRead );
90 		}
skipBytes(sal_Int32 nBytesToSkip)91     virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
92 		throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
93 		{
94 			// not implemented
95 		}
available()96     virtual sal_Int32 SAL_CALL available(  )
97 		throw(NotConnectedException, IOException, RuntimeException)
98 		{
99 			return m_seq.getLength() - nPos;
100 		}
closeInput()101     virtual void SAL_CALL closeInput(  )
102 		throw(NotConnectedException, IOException, RuntimeException)
103 		{
104 			// not needed
105 		}
106 	sal_Int32 nPos;
107 	Sequence< sal_Int8> m_seq;
108 };
109 
110 //-------------------------------
111 // Helper : create an input stream from a file
112 //------------------------------
createStreamFromFile(const char * pcFile)113 Reference< XInputStream > createStreamFromFile(
114 	const char *pcFile )
115 {
116 	FILE *f = fopen( pcFile , "rb" );
117 	Reference<  XInputStream >  r;
118 
119 	if( f ) {
120 		fseek( f , 0 , SEEK_END );
121 		int nLength = ftell( f );
122 		fseek( f , 0 , SEEK_SET );
123 
124 		Sequence<sal_Int8> seqIn(nLength);
125 		fread( seqIn.getArray() , nLength , 1 , f );
126 
127 		r = Reference< XInputStream > ( new OInputStream( seqIn ) );
128 		fclose( f );
129 	}
130 	return r;
131 }
132 
133 //-----------------------------------------
134 // The document handler, which is needed for the saxparser
135 // The Documenthandler for reading sax
136 //-----------------------------------------
137 class TestDocumentHandler :
138 	public WeakImplHelper3< XExtendedDocumentHandler , XEntityResolver , XErrorHandler >
139 {
140 public:
TestDocumentHandler()141 	TestDocumentHandler(  )
142 	{
143 	}
144 
145 public: // Error handler
error(const Any & aSAXParseException)146     virtual void SAL_CALL error(const Any& aSAXParseException) throw (SAXException, RuntimeException)
147     {
148     	printf( "Error !\n" );
149     	throw  SAXException(
150 			OUString( RTL_CONSTASCII_USTRINGPARAM("error from error handler")) ,
151 			Reference < XInterface >() ,
152 			aSAXParseException );
153     }
fatalError(const Any & aSAXParseException)154     virtual void SAL_CALL fatalError(const Any& aSAXParseException) throw (SAXException, RuntimeException)
155     {
156     	printf( "Fatal Error !\n" );
157     }
warning(const Any & aSAXParseException)158     virtual void SAL_CALL warning(const Any& aSAXParseException) throw (SAXException, RuntimeException)
159     {
160     	printf( "Warning !\n" );
161     }
162 
163 
164 public: // ExtendedDocumentHandler
165 
startDocument(void)166     virtual void SAL_CALL startDocument(void) throw (SAXException, RuntimeException)
167     {
168 		m_iElementCount = 0;
169 		m_iAttributeCount = 0;
170 		m_iWhitespaceCount =0;
171 		m_iCharCount=0;
172    		printf( "document started\n" );
173     }
endDocument(void)174     virtual void SAL_CALL endDocument(void) throw (SAXException, RuntimeException)
175     {
176 		printf( "document finished\n" );
177 		printf( "(ElementCount %d),(AttributeCount %d),(WhitespaceCount %d),(CharCount %d)\n",
178 				m_iElementCount, m_iAttributeCount, m_iWhitespaceCount , m_iCharCount );
179 
180     }
startElement(const OUString & aName,const Reference<XAttributeList> & xAttribs)181     virtual void SAL_CALL startElement(const OUString& aName,
182 							  const Reference< XAttributeList > & xAttribs)
183 		throw (SAXException,RuntimeException)
184 	{
185     	m_iElementCount ++;
186     	m_iAttributeCount += xAttribs->getLength();
187     }
188 
endElement(const OUString & aName)189     virtual void SAL_CALL endElement(const OUString& aName) throw (SAXException,RuntimeException)
190     {
191 		// ignored
192     }
193 
characters(const OUString & aChars)194     virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException)
195     {
196     	m_iCharCount += aChars.getLength();
197     }
ignorableWhitespace(const OUString & aWhitespaces)198     virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw (SAXException,RuntimeException)
199     {
200 		m_iWhitespaceCount += aWhitespaces.getLength();
201     }
202 
processingInstruction(const OUString & aTarget,const OUString & aData)203     virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw (SAXException,RuntimeException)
204     {
205 		// ignored
206     }
207 
setDocumentLocator(const Reference<XLocator> & xLocator)208     virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & xLocator)
209 		throw (SAXException,RuntimeException)
210     {
211 		// ignored
212     }
213 
resolveEntity(const OUString & sPublicId,const OUString & sSystemId)214     virtual InputSource SAL_CALL resolveEntity(
215 		const OUString& sPublicId,
216 		const OUString& sSystemId)
217 		throw (SAXException,RuntimeException)
218 	{
219 		InputSource source;
220 		source.sSystemId = sSystemId;
221 		source.sPublicId = sPublicId;
222 
223 		source.aInputStream = createStreamFromFile(
224 			OUStringToOString( sSystemId , RTL_TEXTENCODING_ASCII_US) );
225 
226 		return source;
227 	}
228 
startCDATA(void)229     virtual void SAL_CALL startCDATA(void) throw (SAXException,RuntimeException)
230     {
231     }
endCDATA(void)232     virtual void SAL_CALL endCDATA(void) throw (SAXException,RuntimeException)
233     {
234     }
comment(const OUString & sComment)235     virtual void SAL_CALL comment(const OUString& sComment) throw (SAXException,RuntimeException)
236     {
237     }
unknown(const OUString & sString)238     virtual void SAL_CALL unknown(const OUString& sString) throw (SAXException,RuntimeException)
239     {
240     }
241 
allowLineBreak(void)242 	virtual void SAL_CALL allowLineBreak( void) throw (SAXException, RuntimeException )
243 	{
244 
245 	}
246 
247 public:
248 	int m_iElementCount;
249 	int m_iAttributeCount;
250 	int m_iWhitespaceCount;
251 	int m_iCharCount;
252 };
253 
254 //--------------------------------------
255 // helper implementation for writing
256 // implements an XAttributeList
257 //-------------------------------------
258 struct AttributeListImpl_impl;
259 class AttributeListImpl : public WeakImplHelper1< XAttributeList >
260 {
261 public:
262 	AttributeListImpl();
263 	AttributeListImpl( const AttributeListImpl & );
264 	~AttributeListImpl();
265 
266 public:
267     virtual sal_Int16 SAL_CALL getLength(void) throw  (RuntimeException);
268     virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) throw  (RuntimeException);
269     virtual OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw  (RuntimeException);
270     virtual OUString SAL_CALL getTypeByName(const OUString& aName) throw  (RuntimeException);
271     virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) throw  (RuntimeException);
272     virtual OUString SAL_CALL getValueByName(const OUString& aName) throw  (RuntimeException);
273 
274 public:
275 	void addAttribute( const OUString &sName ,
276 					   const OUString &sType ,
277 					   const OUString &sValue );
278 	void clear();
279 
280 private:
281 	struct AttributeListImpl_impl *m_pImpl;
282 };
283 
284 
285 struct TagAttribute
286 {
TagAttributeTagAttribute287 	TagAttribute(){}
TagAttributeTagAttribute288 	TagAttribute( const OUString &sName,
289 				  const OUString &sType ,
290 				  const OUString &sValue )
291 	{
292 		this->sName 	= sName;
293 		this->sType 	= sType;
294 		this->sValue 	= sValue;
295 	}
296 
297 	OUString sName;
298 	OUString sType;
299 	OUString sValue;
300 };
301 
302 struct AttributeListImpl_impl
303 {
AttributeListImpl_implAttributeListImpl_impl304 	AttributeListImpl_impl()
305 	{
306 		// performance improvement during adding
307 		vecAttribute.reserve(20);
308 	}
309 	vector<struct TagAttribute> vecAttribute;
310 };
311 
312 
313 
getLength(void)314 sal_Int16 AttributeListImpl::getLength(void) throw  (RuntimeException)
315 {
316 	return m_pImpl->vecAttribute.size();
317 }
318 
319 
AttributeListImpl(const AttributeListImpl & r)320 AttributeListImpl::AttributeListImpl( const AttributeListImpl &r )
321 {
322 	m_pImpl = new AttributeListImpl_impl;
323 	*m_pImpl = *(r.m_pImpl);
324 }
325 
getNameByIndex(sal_Int16 i)326 OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw  (RuntimeException)
327 {
328 	if( i < m_pImpl->vecAttribute.size() ) {
329 		return m_pImpl->vecAttribute[i].sName;
330 	}
331 	return OUString();
332 }
333 
334 
getTypeByIndex(sal_Int16 i)335 OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw  (RuntimeException)
336 {
337 	if( i < m_pImpl->vecAttribute.size() ) {
338 		return m_pImpl->vecAttribute[i].sType;
339 	}
340 	return OUString();
341 }
342 
getValueByIndex(sal_Int16 i)343 OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw  (RuntimeException)
344 {
345 	if( i < m_pImpl->vecAttribute.size() ) {
346 		return m_pImpl->vecAttribute[i].sValue;
347 	}
348 	return OUString();
349 
350 }
351 
getTypeByName(const OUString & sName)352 OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw  (RuntimeException)
353 {
354 	vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
355 
356 	for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
357 		if( (*ii).sName == sName ) {
358 			return (*ii).sType;
359 		}
360 	}
361 	return OUString();
362 }
363 
getValueByName(const OUString & sName)364 OUString AttributeListImpl::getValueByName(const OUString& sName) throw  (RuntimeException)
365 {
366 	vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
367 
368 	for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
369 		if( (*ii).sName == sName ) {
370 			return (*ii).sValue;
371 		}
372 	}
373 	return OUString();
374 }
375 
376 
377 
AttributeListImpl()378 AttributeListImpl::AttributeListImpl()
379 {
380 	m_pImpl = new AttributeListImpl_impl;
381 }
382 
383 
384 
~AttributeListImpl()385 AttributeListImpl::~AttributeListImpl()
386 {
387 	delete m_pImpl;
388 }
389 
390 
addAttribute(const OUString & sName,const OUString & sType,const OUString & sValue)391 void AttributeListImpl::addAttribute( 	const OUString &sName ,
392 										const OUString &sType ,
393 										const OUString &sValue )
394 {
395 	m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) );
396 }
397 
clear()398 void AttributeListImpl::clear()
399 {
400 	m_pImpl->vecAttribute.clear();
401 }
402 
403 
404 //--------------------------------------
405 // helper function for writing
406 // ensures that linebreaks are inserted
407 // when writing a long text.
408 // Note: this implementation may be a bit slow,
409 // but it shows, how the SAX-Writer handles the allowLineBreak calls.
410 //--------------------------------------
writeParagraphHelper(const Reference<XExtendedDocumentHandler> & r,const OUString & s)411 void writeParagraphHelper(
412 	const  Reference< XExtendedDocumentHandler > &r ,
413 	const OUString & s)
414 {
415 	int nMax = s.getLength();
416 	int nStart = 0;
417 
418 	Sequence<sal_uInt16> seq( s.getLength() );
419 	memcpy( seq.getArray() , s.getStr() , s.getLength() * sizeof( sal_uInt16 ) );
420 
421 	for( int n = 1 ; n < nMax ; n++ ){
422 		if( 32 == seq.getArray()[n] ) {
423 			r->allowLineBreak();
424 			r->characters( s.copy( nStart , n - nStart ) );
425 			nStart = n;
426 		}
427 	}
428 	r->allowLineBreak();
429 	r->characters( s.copy( nStart , n - nStart ) );
430 }
431 
432 
433 //---------------------------------
434 // helper implementation for SAX-Writer
435 // writes data to a file
436 //--------------------------------
437 class OFileWriter :
438 		public WeakImplHelper1< XOutputStream >
439 {
440 public:
OFileWriter(char * pcFile)441 	OFileWriter( char *pcFile ) { strncpy( m_pcFile , pcFile, 256 - 1 ); m_f = 0; }
442 
443 
444 public:
445     virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
446 		throw  (NotConnectedException, BufferSizeExceededException, RuntimeException);
447     virtual void SAL_CALL flush(void)
448 		throw  (NotConnectedException, BufferSizeExceededException, RuntimeException);
449     virtual void SAL_CALL closeOutput(void)
450 		throw  (NotConnectedException, BufferSizeExceededException, RuntimeException);
451 private:
452 	char m_pcFile[256];
453 	FILE *m_f;
454 };
455 
456 
writeBytes(const Sequence<sal_Int8> & aData)457 void OFileWriter::writeBytes(const Sequence< sal_Int8 >& aData)
458 	throw  (NotConnectedException, BufferSizeExceededException, RuntimeException)
459 {
460 	if( ! m_f ) {
461 		m_f = fopen( m_pcFile , "w" );
462 	}
463 
464 	fwrite( aData.getConstArray() , 1 , aData.getLength() , m_f );
465 }
466 
467 
flush(void)468 void OFileWriter::flush(void)
469 	throw  (NotConnectedException, BufferSizeExceededException, RuntimeException)
470 {
471 	fflush( m_f );
472 }
473 
closeOutput(void)474 void OFileWriter::closeOutput(void)
475 	throw  (NotConnectedException, BufferSizeExceededException, RuntimeException)
476 {
477 	fclose( m_f );
478 	m_f = 0;
479 }
480 
481 
482 
483 // Needed to switch on solaris threads
484 #ifdef SOLARIS
485 extern "C" void ChangeGlobalInit();
486 #endif
main(int argc,char ** argv)487 int main (int argc, char **argv)
488 {
489 
490 	if( argc < 3) {
491 		printf( "usage : saxdemo inputfile outputfile\n" );
492 		exit( 0 );
493 	}
494 #ifdef SOLARIS
495 	// switch on threads in solaris
496 	ChangeGlobalInit();
497 #endif
498 
499 	// create service manager
500 	Reference< XMultiServiceFactory > xSMgr = createRegistryServiceFactory(
501 		OUString( RTL_CONSTASCII_USTRINGPARAM( "applicat.rdb" )) );
502 
503 	Reference < XImplementationRegistration > xReg;
504 	try
505 	{
506 		// Create registration service
507 		Reference < XInterface > x = xSMgr->createInstance(
508 			OUString::createFromAscii( "com.sun.star.registry.ImplementationRegistration" ) );
509 		xReg = Reference<  XImplementationRegistration > ( x , UNO_QUERY );
510 	}
511 	catch( Exception & ) {
512 		printf( "Couldn't create ImplementationRegistration service\n" );
513 		exit(1);
514 	}
515 
516 	OString sTestName;
517 	try
518 	{
519 		// Load dll for the tested component
520 		OUString aDllName =
521             OUString::createFromAscii( "sax.uno" SAL_DLLEXTENSION );
522 		xReg->registerImplementation(
523 			OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ),
524 			aDllName,
525 			Reference< XSimpleRegistry > ()  );
526 	}
527 	catch( Exception &e ) {
528 		printf( "Couldn't reach sax dll\n" );
529 		printf( "%s\n" , OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).getStr() );
530 
531 		exit(1);
532 	}
533 
534 
535 	//--------------------------------
536 	// parser demo
537 	// read xml from a file and count elements
538 	//--------------------------------
539 	Reference< XInterface > x = xSMgr->createInstance(
540 		OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ) );
541 	if( x.is() )
542 	{
543 		Reference< XParser > rParser( x , UNO_QUERY );
544 
545 		// create and connect the document handler to the parser
546 		TestDocumentHandler *pDocHandler = new TestDocumentHandler( );
547 
548 		Reference < XDocumentHandler >	rDocHandler( (XDocumentHandler *) pDocHandler );
549 		Reference< XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler );
550 
551 		rParser->setDocumentHandler( rDocHandler );
552 		rParser->setEntityResolver( rEntityResolver );
553 
554 		// create the input stream
555 		InputSource source;
556 		source.aInputStream = createStreamFromFile( argv[1] );
557 		source.sSystemId 	= OUString::createFromAscii( argv[1] );
558 
559 		try
560 		{
561 			// start parsing
562 			rParser->parseStream( source );
563 		}
564 
565 		catch( Exception & e )
566 		{
567 			OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
568 			printf( "Exception during parsing : %s\n" ,  o1.getStr() );
569 		}
570 	}
571 	else
572 	{
573 		printf( "couln't create sax-parser component\n" );
574 	}
575 
576 
577 	//----------------------
578 	// The SAX-Writer demo
579 	//----------------------
580 	x= xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ) );
581 	if( x.is() )
582 	{
583 		printf( "start writing to %s\n" , argv[2] );
584 
585 		OFileWriter *pw = new OFileWriter( argv[2] );
586 		Reference< XActiveDataSource > source( x , UNO_QUERY );
587 		source->setOutputStream( Reference< XOutputStream> ( (XOutputStream*) pw ) );
588 
589 		AttributeListImpl *pList = new AttributeListImpl;
590 		Reference< XAttributeList > rList( (XAttributeList *) pList );
591 
592 		Reference< XExtendedDocumentHandler > r( x , UNO_QUERY );
593 		r->startDocument();
594 
595 		pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg1" )),
596 							 OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) ,
597 							 OUString( RTL_CONSTASCII_USTRINGPARAM("foo\n	u")) );
598 		pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg2")) ,
599 							 OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) ,
600 							 OUString( RTL_CONSTASCII_USTRINGPARAM("foo2")) );
601 
602 		r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1"))  , rList );
603 		// tells the writer to insert a linefeed
604 		r->ignorableWhitespace( OUString() );
605 
606 		r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) );
607 		r->ignorableWhitespace( OUString() );
608 
609 		r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) , rList );
610 		r->ignorableWhitespace( OUString() );
611 
612 		// the enpassant must be converted & -> &amp;
613 		r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("&#252;")) );
614 		r->ignorableWhitespace( OUString() );
615 
616 		// '>' must not be converted
617 		r->startCDATA();
618 		r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM(" > foo < "))  );
619 		r->endCDATA();
620 		r->ignorableWhitespace( OUString() );
621 
622 		OUString testParagraph = OUString( RTL_CONSTASCII_USTRINGPARAM(
623 			"This is only a test to check, if the writer inserts line feeds "
624 			"if needed or if the writer puts the whole text into one line." ));
625 		writeParagraphHelper( r , testParagraph );
626 
627 		r->ignorableWhitespace( OUString() );
628 		r->comment( OUString( RTL_CONSTASCII_USTRINGPARAM("This is a comment !")) );
629 		r->ignorableWhitespace( OUString() );
630 
631 		r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest"))  , rList );
632 		r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) );
633 		r->ignorableWhitespace( OUString() );
634 
635 		r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) );
636 		r->ignorableWhitespace( OUString() );
637 
638 		r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) );
639 		r->endDocument();
640 
641 		printf( "finished writing\n" );
642 	}
643 	else
644 	{
645 		printf( "couln't create sax-writer component\n" );
646 	}
647 }
648