1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/XPropertySet.hpp>
22 #include <com/sun/star/document/XFilter.hpp>
23 #include <com/sun/star/document/XExporter.hpp>
24 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
25 #include <com/sun/star/document/XGraphicStorageHandler.hpp>
26 #include <com/sun/star/document/XEmbeddedObjectResolver.hpp>
27 #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
28 #include <com/sun/star/frame/Desktop.hpp>
29 #include <com/sun/star/frame/XStorable.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <com/sun/star/system/SystemShellExecute.hpp>
33 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
34 #include <com/sun/star/task/InteractionHandler.hpp>
35 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
36 #include <com/sun/star/xml/XImportFilter.hpp>
37 #include <com/sun/star/xml/XExportFilter.hpp>
38 #include <com/sun/star/xml/sax/Writer.hpp>
40 #include <comphelper/oslfile2streamwrap.hxx>
41 #include <vcl/svapp.hxx>
42 #include <sfx2/filedlghelper.hxx>
43 #include <osl/file.hxx>
44 #include <unotools/tempfile.hxx>
45 #include <tools/diagnose_ex.h>
46 #include <tools/debug.hxx>
47 #include <tools/urlobj.hxx>
48 #include <comphelper/processfactory.hxx>
50 #include "xmlfiltercommon.hxx"
51 #include "xmlfiltertestdialog.hxx"
56 using namespace comphelper
;
57 using namespace com::sun::star::lang
;
58 using namespace com::sun::star::beans
;
59 using namespace com::sun::star::container
;
60 using namespace com::sun::star::document
;
61 using namespace com::sun::star::frame
;
62 using namespace com::sun::star::task
;
63 using namespace com::sun::star::uno
;
64 using namespace com::sun::star::io
;
65 using namespace com::sun::star::system
;
66 using namespace com::sun::star::xml
;
67 using namespace com::sun::star::xml::sax
;
71 class GlobalEventListenerImpl
: public ::cppu::WeakImplHelper
< css::document::XDocumentEventListener
>
74 explicit GlobalEventListenerImpl( XMLFilterTestDialog
* pDialog
);
76 // XDocumentEventListener
77 virtual void SAL_CALL
documentEventOccured( const css::document::DocumentEvent
& Event
) override
;
79 // lang::XEventListener
80 virtual void SAL_CALL
disposing( const css::lang::EventObject
& Source
) override
;
82 XMLFilterTestDialog
* mpDialog
;
87 GlobalEventListenerImpl::GlobalEventListenerImpl( XMLFilterTestDialog
* pDialog
)
92 void SAL_CALL
GlobalEventListenerImpl::documentEventOccured( const css::document::DocumentEvent
& Event
)
94 ::SolarMutexGuard aGuard
;
95 if( Event
.EventName
== "OnFocus" || Event
.EventName
== "OnUnload" )
97 Reference
< XComponent
> xComp( Event
.Source
, UNO_QUERY
);
98 mpDialog
->updateCurrentDocumentButtonState( &xComp
);
102 void SAL_CALL
GlobalEventListenerImpl::disposing( const css::lang::EventObject
& /* Source */ )
106 /** returns true if the given component supports the given service */
107 static bool checkComponent( Reference
< XComponent
> const & rxComponent
, const OUString
& rServiceName
)
111 Reference
< XServiceInfo
> xInfo( rxComponent
, UNO_QUERY
);
114 if( xInfo
->supportsService( rServiceName
) )
116 // special case for impress documents which supports same service as draw documents
117 if ( rServiceName
== "com.sun.star.drawing.DrawingDocument" )
119 // so if we want a draw we need to check if it's not an impress
120 if( !xInfo
->supportsService("com.sun.star.presentation.PresentationDocument") )
130 catch( const Exception
& )
132 TOOLS_WARN_EXCEPTION("filter.xslt", "");
138 XMLFilterTestDialog::XMLFilterTestDialog(weld::Window
* pParent
,
139 const Reference
<XComponentContext
>& rxContext
)
140 : GenericDialogController(pParent
, "filter/ui/testxmlfilter.ui", "TestXMLFilterDialog")
141 , mxContext(rxContext
)
142 , m_xExport(m_xBuilder
->weld_widget("export"))
143 , m_xFTExportXSLTFile(m_xBuilder
->weld_label("exportxsltfile"))
144 , m_xPBExportBrowse(m_xBuilder
->weld_button("exportbrowse"))
145 , m_xPBCurrentDocument(m_xBuilder
->weld_button("currentdocument"))
146 , m_xFTNameOfCurrentFile(m_xBuilder
->weld_label("currentfilename"))
147 , m_xImport(m_xBuilder
->weld_widget("import"))
148 , m_xFTImportXSLTFile(m_xBuilder
->weld_label("importxsltfile"))
149 , m_xFTImportTemplate(m_xBuilder
->weld_label("templateimport"))
150 , m_xFTImportTemplateFile(m_xBuilder
->weld_label("importxslttemplate"))
151 , m_xCBXDisplaySource(m_xBuilder
->weld_check_button("displaysource"))
152 , m_xPBImportBrowse(m_xBuilder
->weld_button("importbrowse"))
153 , m_xPBRecentFile(m_xBuilder
->weld_button("recentfile"))
154 , m_xFTNameOfRecentFile(m_xBuilder
->weld_label("recentfilename"))
155 , m_xPBClose(m_xBuilder
->weld_button("close"))
157 m_xPBExportBrowse
->connect_clicked(LINK( this, XMLFilterTestDialog
, ClickHdl_Impl
) );
158 m_xPBCurrentDocument
->connect_clicked(LINK( this, XMLFilterTestDialog
, ClickHdl_Impl
) );
159 m_xPBImportBrowse
->connect_clicked(LINK( this, XMLFilterTestDialog
, ClickHdl_Impl
) );
160 m_xPBRecentFile
->connect_clicked(LINK( this, XMLFilterTestDialog
, ClickHdl_Impl
) );
161 m_xPBClose
->connect_clicked(LINK( this, XMLFilterTestDialog
, ClickHdl_Impl
) );
163 m_sDialogTitle
= m_xDialog
->get_title();
167 mxGlobalBroadcaster
= theGlobalEventBroadcaster::get(mxContext
);
168 mxGlobalEventListener
= new GlobalEventListenerImpl( this );
169 mxGlobalBroadcaster
->addDocumentEventListener( mxGlobalEventListener
);
171 catch( const Exception
& )
173 TOOLS_WARN_EXCEPTION("filter.xslt", "");
177 XMLFilterTestDialog::~XMLFilterTestDialog()
181 if( mxGlobalBroadcaster
.is() )
182 mxGlobalBroadcaster
->removeDocumentEventListener( mxGlobalEventListener
);
184 catch( const Exception
& )
186 TOOLS_WARN_EXCEPTION("filter.xslt", "");
190 void XMLFilterTestDialog::test( const filter_info_impl
& rFilterInfo
)
192 m_xFilterInfo
.reset(new filter_info_impl( rFilterInfo
));
194 m_sImportRecentFile
.clear();
201 static OUString
getFileNameFromURL( OUString
const & rURL
)
203 INetURLObject
aURL( rURL
);
204 OUString
aName( aURL
.getName(INetURLObject::LAST_SEGMENT
, true, INetURLObject::DecodeMechanism::WithCharset
) );
208 void XMLFilterTestDialog::updateCurrentDocumentButtonState( Reference
< XComponent
> const * pRef
/* = NULL */ )
210 if( pRef
&& pRef
->is() )
212 if( checkComponent( *pRef
, m_xFilterInfo
->maDocumentService
) )
213 mxLastFocusModel
= *pRef
;
216 bool bExport
= (m_xFilterInfo
->maFlags
& 2) == 2;
217 Reference
< XComponent
> xCurrentDocument
;
219 xCurrentDocument
= getFrontMostDocument( m_xFilterInfo
->maDocumentService
);
220 m_xPBCurrentDocument
->set_sensitive( bExport
&& xCurrentDocument
.is() );
221 m_xFTNameOfCurrentFile
->set_sensitive( bExport
&& xCurrentDocument
.is() );
223 if( !xCurrentDocument
.is() )
227 Reference
< XDocumentPropertiesSupplier
> xDPS( xCurrentDocument
, UNO_QUERY
);
230 Reference
< XDocumentProperties
> xProps( xDPS
->getDocumentProperties() );
233 aTitle
= xProps
->getTitle();
237 if( aTitle
.isEmpty() )
239 Reference
< XStorable
> xStorable( xCurrentDocument
, UNO_QUERY
);
242 if( xStorable
->hasLocation() )
244 OUString
aURL( xStorable
->getLocation() );
245 aTitle
= getFileNameFromURL( aURL
);
250 m_xFTNameOfCurrentFile
->set_label( aTitle
);
253 void XMLFilterTestDialog::initDialog()
255 DBG_ASSERT( m_xFilterInfo
, "i need a filter I can test!" );
256 if( nullptr == m_xFilterInfo
)
259 OUString
aTitle( m_sDialogTitle
);
260 aTitle
= aTitle
.replaceFirst( "%s", m_xFilterInfo
->maFilterName
);
261 m_xDialog
->set_title( aTitle
);
263 bool bImport
= (m_xFilterInfo
->maFlags
& 1) == 1;
264 bool bExport
= (m_xFilterInfo
->maFlags
& 2) == 2;
266 updateCurrentDocumentButtonState();
268 m_xExport
->set_sensitive(bExport
);
269 m_xFTExportXSLTFile
->set_label( getFileNameFromURL( m_xFilterInfo
->maExportXSLT
) );
272 m_xImport
->set_sensitive(bImport
);
273 m_xFTImportTemplate
->set_sensitive(bImport
&& !m_xFilterInfo
->maImportTemplate
.isEmpty());
274 m_xFTImportTemplateFile
->set_sensitive(bImport
&& !m_xFilterInfo
->maImportTemplate
.isEmpty());
275 m_xPBRecentFile
->set_sensitive(bImport
&& !m_sImportRecentFile
.isEmpty());
276 m_xFTNameOfRecentFile
->set_sensitive(bImport
&& !m_sImportRecentFile
.isEmpty());
278 m_xFTImportXSLTFile
->set_label( getFileNameFromURL( m_xFilterInfo
->maImportXSLT
) );
279 m_xFTImportTemplateFile
->set_label( getFileNameFromURL( m_xFilterInfo
->maImportTemplate
) );
280 m_xFTNameOfRecentFile
->set_label( getFileNameFromURL( m_sImportRecentFile
) );
283 void XMLFilterTestDialog::onExportBrowse()
287 // Open Fileopen-Dialog
288 ::sfx2::FileDialogHelper
aDlg(
289 css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE
,
290 FileDialogFlags::NONE
, m_xDialog
.get());
292 Reference
< XNameAccess
> xFilterContainer( mxContext
->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", mxContext
), UNO_QUERY
);
293 Reference
< XNameAccess
> xTypeDetection( mxContext
->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", mxContext
), UNO_QUERY
);
294 if( xFilterContainer
.is() && xTypeDetection
.is() )
296 const Sequence
< OUString
> aFilterNames( xFilterContainer
->getElementNames() );
298 for( OUString
const & filterName
: aFilterNames
)
300 Sequence
< PropertyValue
> aValues
;
302 Any
aAny( xFilterContainer
->getByName( filterName
) );
303 if( !(aAny
>>= aValues
) )
306 OUString aInterfaceName
;
307 OUString aType
, aService
;
308 sal_Int32
nFlags( 0 );
312 for( const PropertyValue
& rValue
: std::as_const(aValues
) )
314 if ( rValue
.Name
== "Type" )
316 rValue
.Value
>>= aType
;
319 else if ( rValue
.Name
== "DocumentService" )
321 rValue
.Value
>>= aService
;
324 else if ( rValue
.Name
== "Flags" )
326 rValue
.Value
>>= nFlags
;
329 else if ( rValue
.Name
== "UIName" )
331 rValue
.Value
>>= aInterfaceName
;
339 if( (nFound
== 15) && (!aType
.isEmpty() && aService
== m_xFilterInfo
->maDocumentService
) )
341 // see if this filter is not suppressed in dialog
342 if( (nFlags
& 0x1000) == 0 )
344 aAny
= xTypeDetection
->getByName( aType
);
345 Sequence
< PropertyValue
> aValues2
;
347 if( aAny
>>= aValues2
)
350 for( const PropertyValue
& rProp
: std::as_const(aValues2
) )
352 if ( rProp
.Name
== "Extensions" )
354 Sequence
< OUString
> aExtensions
;
355 if( rProp
.Value
>>= aExtensions
)
357 const sal_Int32
nCount( aExtensions
.getLength() );
358 OUString
* pExtensions
= aExtensions
.getArray();
360 for( n
= 0; n
< nCount
; n
++ )
364 aExtension
+= "*." + *pExtensions
++;
370 OUString
aFilterName( aInterfaceName
+ " (" + aExtension
+ ")" );
372 aDlg
.AddFilter( aFilterName
, aExtension
);
374 if( (nFlags
& 0x100) == 0x100 )
375 aDlg
.SetCurrentFilter( aFilterName
);
383 aDlg
.SetDisplayDirectory( m_sExportRecentFile
);
385 if ( aDlg
.Execute() == ERRCODE_NONE
)
387 m_sExportRecentFile
= aDlg
.GetPath();
389 Reference
< XDesktop2
> xLoader
= Desktop::create( mxContext
);
390 Reference
< XInteractionHandler2
> xInter
= InteractionHandler::createWithParent(mxContext
, nullptr);
391 Sequence
< PropertyValue
> aArguments(1);
392 aArguments
[0].Name
= "InteractionHandler";
393 aArguments
[0].Value
<<= xInter
;
394 Reference
< XComponent
> xComp( xLoader
->loadComponentFromURL( m_sExportRecentFile
, "_default", 0, aArguments
) );
401 catch(const Exception
&)
403 TOOLS_WARN_EXCEPTION("filter.xslt", "");
409 void XMLFilterTestDialog::onExportCurrentDocument()
411 doExport( getFrontMostDocument( m_xFilterInfo
->maDocumentService
) );
414 void XMLFilterTestDialog::doExport( const Reference
< XComponent
>& xComp
)
418 Reference
< XStorable
> xStorable( xComp
, UNO_QUERY
);
421 OUString
const ext(".xml");
422 utl::TempFile
aTempFile(OUString(), true, &ext
);
423 OUString
aTempFileURL( aTempFile
.GetURL() );
425 const application_info_impl
* pAppInfo
= getApplicationInfo( m_xFilterInfo
->maExportService
);
428 File
aOutputFile( aTempFileURL
);
429 /* File::RC rc = */ aOutputFile
.open( osl_File_OpenFlag_Write
);
431 // create xslt exporter
432 Reference
< XOutputStream
> xIS( new comphelper::OSLOutputStreamWrapper( aOutputFile
) );
433 int bUseDocType
= m_xFilterInfo
->maDocType
.isEmpty() ? 0 : 1;
434 Sequence
< PropertyValue
> aSourceData( 2 + bUseDocType
);
438 aSourceData
[i
].Name
= "OutputStream";
439 aSourceData
[i
++].Value
<<= xIS
;
441 aSourceData
[i
].Name
= "Indent";
442 aSourceData
[i
++].Value
<<= true;
446 aSourceData
[i
].Name
= "DocType_Public";
447 aSourceData
[i
++].Value
<<= m_xFilterInfo
->maDocType
;
450 Reference
< XExportFilter
> xExporter( mxContext
->getServiceManager()->createInstanceWithContext( "com.sun.star.documentconversion.XSLTFilter", mxContext
), UNO_QUERY
);
451 Reference
< XDocumentHandler
> xHandler( xExporter
, UNO_QUERY
);
454 Sequence
< OUString
> aFilterUserData( m_xFilterInfo
->getFilterUserData() );
455 xExporter
->exporter( aSourceData
, aFilterUserData
);
457 Reference
< XMultiServiceFactory
> xDocFac( xComp
, UNO_QUERY
);
459 Reference
< XEmbeddedObjectResolver
> xObjectResolver
;
460 Reference
<XGraphicStorageHandler
> xGraphicStorageHandler
;
466 xGraphicStorageHandler
.set(xDocFac
->createInstance("com.sun.star.document.ExportGraphicStorageHandler"), UNO_QUERY
);
467 xObjectResolver
.set( xDocFac
->createInstance("com.sun.star.document.ExportEmbeddedObjectResolver"), UNO_QUERY
);
469 catch( const Exception
& )
474 Sequence
< Any
> aArgs( 1 + ( xGraphicStorageHandler
.is() ? 1 : 0 ) + ( xObjectResolver
.is() ? 1 : 0 ) );
475 Any
* pArgs
= aArgs
.getArray();
476 if (xGraphicStorageHandler
.is())
477 *pArgs
++ <<= xGraphicStorageHandler
;
479 if (xObjectResolver
.is())
480 *pArgs
++ <<= xObjectResolver
;
482 // *pArgs++ <<= xInfoSet;
485 Reference
< XFilter
> xFilter( mxContext
->getServiceManager()->createInstanceWithArgumentsAndContext( pAppInfo
->maXMLExporter
, aArgs
, mxContext
), UNO_QUERY
);
488 Reference
< XExporter
> xExporter2( xFilter
, UNO_QUERY
);
489 if( xExporter2
.is() )
491 xExporter2
->setSourceDocument( xComp
);
493 Sequence
< PropertyValue
> aDescriptor( 1 );
494 aDescriptor
[0].Name
= "FileName";
495 aDescriptor
[0].Value
<<= aTempFileURL
;
497 if( xFilter
->filter( aDescriptor
) )
498 displayXMLFile( aTempFileURL
);
505 catch( const Exception
& )
507 TOOLS_WARN_EXCEPTION("filter.xslt", "");
511 void XMLFilterTestDialog::displayXMLFile( const OUString
& rURL
)
513 Reference
< XSystemShellExecute
> xSystemShellExecute(
514 SystemShellExecute::create(comphelper::getProcessComponentContext()) );
515 xSystemShellExecute
->execute( rURL
, OUString(), SystemShellExecuteFlags::URIS_ONLY
);
518 void XMLFilterTestDialog::onImportBrowse()
520 // Open Fileopen-Dialog
521 ::sfx2::FileDialogHelper
aDlg(
522 css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE
,
523 FileDialogFlags::NONE
, m_xDialog
.get());
524 OUString
aFilterName( m_xFilterInfo
->maInterfaceName
);
525 OUString aExtensions
;
528 int nCurrentIndex
= 0;
529 for( int i
= 0; nLastIndex
!= -1; i
++ )
531 nLastIndex
= m_xFilterInfo
->maExtension
.indexOf( ';', nLastIndex
);
538 if( nLastIndex
== -1 )
541 aExtensions
+= m_xFilterInfo
->maExtension
.subView( nCurrentIndex
);
545 aExtensions
+= m_xFilterInfo
->maExtension
.subView( nCurrentIndex
, nLastIndex
- nCurrentIndex
);
546 nCurrentIndex
= nLastIndex
+ 1;
547 nLastIndex
= nCurrentIndex
;
551 aFilterName
+= " (" + aExtensions
+ ")";
553 aDlg
.AddFilter( aFilterName
, aExtensions
);
554 aDlg
.SetDisplayDirectory( m_sImportRecentFile
);
556 if ( aDlg
.Execute() == ERRCODE_NONE
)
558 m_sImportRecentFile
= aDlg
.GetPath();
559 import( m_sImportRecentFile
);
565 void XMLFilterTestDialog::import( const OUString
& rURL
)
569 Reference
< XDesktop2
> xLoader
= Desktop::create( mxContext
);
570 Reference
< XInteractionHandler2
> xInter
= InteractionHandler::createWithParent(mxContext
, nullptr);
572 Sequence
< PropertyValue
> aArguments(2);
573 aArguments
[0].Name
= "FilterName";
574 aArguments
[0].Value
<<= m_xFilterInfo
->maFilterName
;
575 aArguments
[1].Name
= "InteractionHandler";
576 aArguments
[1].Value
<<= xInter
;
578 xLoader
->loadComponentFromURL( rURL
, "_default", 0, aArguments
);
580 if( m_xCBXDisplaySource
->get_active() )
582 OUString
const ext(".xml");
583 TempFile
aTempFile(OUString(), true, &ext
);
584 OUString
aTempFileURL( aTempFile
.GetURL() );
586 Reference
< XImportFilter
> xImporter( mxContext
->getServiceManager()->createInstanceWithContext( "com.sun.star.documentconversion.XSLTFilter", mxContext
), UNO_QUERY
);
589 osl::File
aInputFile( rURL
);
590 aInputFile
.open( osl_File_OpenFlag_Read
);
592 Reference
< XInputStream
> xIS( new comphelper::OSLInputStreamWrapper( aInputFile
) );
594 Sequence
< PropertyValue
> aSourceData( 3 );
597 aSourceData
[i
].Name
= "InputStream";
598 aSourceData
[i
++].Value
<<= xIS
;
600 aSourceData
[i
].Name
= "FileName";
601 aSourceData
[i
++].Value
<<= rURL
;
603 aSourceData
[i
].Name
= "Indent";
604 aSourceData
[i
++].Value
<<= true;
606 Reference
< XWriter
> xWriter
= Writer::create( mxContext
);
608 File
aOutputFile( aTempFileURL
);
609 aOutputFile
.open( osl_File_OpenFlag_Write
);
611 Reference
< XOutputStream
> xOS( new OSLOutputStreamWrapper( aOutputFile
) );
612 xWriter
->setOutputStream( xOS
);
614 Sequence
< OUString
> aFilterUserData( m_xFilterInfo
->getFilterUserData() );
615 xImporter
->importer( aSourceData
, xWriter
, aFilterUserData
);
618 displayXMLFile( aTempFileURL
);
621 catch(const Exception
&)
623 TOOLS_WARN_EXCEPTION("filter.xslt", "");
627 IMPL_LINK(XMLFilterTestDialog
, ClickHdl_Impl
, weld::Button
&, rButton
, void )
629 if (m_xPBExportBrowse
.get() == &rButton
)
633 else if (m_xPBCurrentDocument
.get() == &rButton
)
635 onExportCurrentDocument();
637 else if (m_xPBImportBrowse
.get() == &rButton
)
641 else if (m_xPBRecentFile
.get() == &rButton
)
643 import( m_sImportRecentFile
);
645 else if (m_xPBClose
.get() == &rButton
)
647 m_xDialog
->response(RET_CLOSE
);
651 /** returns the front most open component that supports the given service */
652 Reference
< XComponent
> XMLFilterTestDialog::getFrontMostDocument( const OUString
& rServiceName
)
654 Reference
< XComponent
> xRet
;
658 Reference
< XDesktop2
> xDesktop
= Desktop::create( mxContext
);
659 Reference
< XComponent
> xTest( mxLastFocusModel
);
660 if( checkComponent( xTest
, rServiceName
) )
666 xTest
= xDesktop
->getCurrentComponent();
668 if( checkComponent( xTest
, rServiceName
) )
674 Reference
< XEnumerationAccess
> xAccess( xDesktop
->getComponents() );
677 Reference
< XEnumeration
> xEnum( xAccess
->createEnumeration() );
680 while( xEnum
->hasMoreElements() )
682 if( (xEnum
->nextElement() >>= xTest
) && xTest
.is() )
684 if( checkComponent( xTest
, rServiceName
) )
696 catch( const Exception
& )
698 TOOLS_WARN_EXCEPTION("filter.xslt", "");
704 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */