update credits
[LibreOffice.git] / xmlscript / source / xml_helper / xml_impctx.cxx
blob1520235c26c633ed9f0964ef54d70703e175da6c
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 .
20 #include <sal/config.h>
22 #include <xml_import.hxx>
24 #include <cppuhelper/implbase.hxx>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <com/sun/star/container/NoSuchElementException.hpp>
27 #include <com/sun/star/xml/input/XAttributes.hpp>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <com/sun/star/uno/XComponentContext.hpp>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <sal/log.hxx>
33 #include <memory>
34 #include <unordered_map>
35 #include <vector>
37 using namespace ::osl;
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::uno;
41 namespace xmlscript
44 const sal_Int32 UID_UNKNOWN = -1;
46 typedef std::unordered_map< OUString, sal_Int32 > t_OUString2LongMap;
48 namespace {
50 struct PrefixEntry
52 ::std::vector< sal_Int32 > m_Uids;
54 PrefixEntry()
55 { m_Uids.reserve( 4 ); }
60 typedef std::unordered_map<
61 OUString, std::unique_ptr<PrefixEntry> > t_OUString2PrefixMap;
63 namespace {
65 struct ElementEntry
67 Reference< xml::input::XElement > m_xElement;
68 ::std::vector< OUString > m_prefixes;
70 ElementEntry()
71 { m_prefixes.reserve( 2 ); }
74 class ExtendedAttributes;
76 class MGuard
78 Mutex * m_pMutex;
79 public:
80 explicit MGuard( std::unique_ptr<Mutex> const & pMutex )
81 : m_pMutex( pMutex.get() )
82 { if (m_pMutex) m_pMutex->acquire(); }
83 ~MGuard() throw ()
84 { if (m_pMutex) m_pMutex->release(); }
87 class DocumentHandlerImpl :
88 public ::cppu::WeakImplHelper< xml::sax::XDocumentHandler,
89 xml::input::XNamespaceMapping,
90 lang::XInitialization,
91 css::lang::XServiceInfo >
93 friend class ExtendedAttributes;
95 Reference< xml::input::XRoot > m_xRoot;
97 t_OUString2LongMap m_URI2Uid;
98 sal_Int32 m_uid_count;
100 sal_Int32 m_nLastURI_lookup;
101 OUString m_aLastURI_lookup;
103 t_OUString2PrefixMap m_prefixes;
104 sal_Int32 m_nLastPrefix_lookup;
105 OUString m_aLastPrefix_lookup;
107 std::vector< ElementEntry > m_elements;
108 sal_Int32 m_nSkipElements;
110 std::unique_ptr<Mutex> m_pMutex;
112 inline Reference< xml::input::XElement > getCurrentElement() const;
114 inline sal_Int32 getUidByURI( OUString const & rURI );
115 inline sal_Int32 getUidByPrefix( OUString const & rPrefix );
117 inline void pushPrefix(
118 OUString const & rPrefix, OUString const & rURI );
119 inline void popPrefix( OUString const & rPrefix );
121 inline void getElementName(
122 OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName );
124 public:
125 DocumentHandlerImpl(
126 Reference< xml::input::XRoot > const & xRoot,
127 bool bSingleThreadedUse );
129 // XServiceInfo
130 virtual OUString SAL_CALL getImplementationName() override;
131 virtual sal_Bool SAL_CALL supportsService(
132 OUString const & servicename ) override;
133 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
135 // XInitialization
136 virtual void SAL_CALL initialize(
137 Sequence< Any > const & arguments ) override;
139 // XDocumentHandler
140 virtual void SAL_CALL startDocument() override;
141 virtual void SAL_CALL endDocument() override;
142 virtual void SAL_CALL startElement(
143 OUString const & rQElementName,
144 Reference< xml::sax::XAttributeList > const & xAttribs ) override;
145 virtual void SAL_CALL endElement(
146 OUString const & rQElementName ) override;
147 virtual void SAL_CALL characters(
148 OUString const & rChars ) override;
149 virtual void SAL_CALL ignorableWhitespace(
150 OUString const & rWhitespaces ) override;
151 virtual void SAL_CALL processingInstruction(
152 OUString const & rTarget, OUString const & rData ) override;
153 virtual void SAL_CALL setDocumentLocator(
154 Reference< xml::sax::XLocator > const & xLocator ) override;
156 // XNamespaceMapping
157 virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri ) override;
158 virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid ) override;
163 constexpr OUStringLiteral g_sXMLNS_PREFIX_UNKNOWN( u"<<< unknown prefix >>>" );
164 constexpr OUStringLiteral g_sXMLNS( u"xmlns" );
167 DocumentHandlerImpl::DocumentHandlerImpl(
168 Reference< xml::input::XRoot > const & xRoot,
169 bool bSingleThreadedUse )
170 : m_xRoot( xRoot ),
171 m_uid_count( 0 ),
172 m_nLastURI_lookup( UID_UNKNOWN ),
173 m_aLastURI_lookup( "<<< unknown URI >>>" ),
174 m_nLastPrefix_lookup( UID_UNKNOWN ),
175 m_aLastPrefix_lookup( "<<< unknown URI >>>" ),
176 m_nSkipElements( 0 )
178 m_elements.reserve( 10 );
180 if (! bSingleThreadedUse)
181 m_pMutex.reset(new Mutex);
184 inline Reference< xml::input::XElement >
185 DocumentHandlerImpl::getCurrentElement() const
187 MGuard aGuard( m_pMutex );
188 if (m_elements.empty())
189 return Reference< xml::input::XElement >();
190 else
191 return m_elements.back().m_xElement;
194 inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI )
196 MGuard guard( m_pMutex );
197 if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI)
199 t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) );
200 if (iFind != m_URI2Uid.end()) // id found
202 m_nLastURI_lookup = iFind->second;
203 m_aLastURI_lookup = rURI;
205 else
207 m_nLastURI_lookup = m_uid_count;
208 ++m_uid_count;
209 m_URI2Uid[ rURI ] = m_nLastURI_lookup;
210 m_aLastURI_lookup = rURI;
213 return m_nLastURI_lookup;
216 inline sal_Int32 DocumentHandlerImpl::getUidByPrefix(
217 OUString const & rPrefix )
219 // commonly the last added prefix is used often for several tags...
220 // good guess
221 if (m_nLastPrefix_lookup == UID_UNKNOWN || m_aLastPrefix_lookup != rPrefix)
223 t_OUString2PrefixMap::const_iterator iFind(
224 m_prefixes.find( rPrefix ) );
225 if (iFind != m_prefixes.end())
227 const PrefixEntry & rPrefixEntry = *iFind->second;
228 SAL_WARN_IF( rPrefixEntry.m_Uids.empty(), "xmlscript.xmlhelper", "rPrefixEntry.m_Uids is empty" );
229 m_nLastPrefix_lookup = rPrefixEntry.m_Uids.back();
230 m_aLastPrefix_lookup = rPrefix;
232 else
234 m_nLastPrefix_lookup = UID_UNKNOWN;
235 m_aLastPrefix_lookup = g_sXMLNS_PREFIX_UNKNOWN;
238 return m_nLastPrefix_lookup;
241 inline void DocumentHandlerImpl::pushPrefix(
242 OUString const & rPrefix, OUString const & rURI )
244 // lookup id for URI
245 sal_Int32 nUid = getUidByURI( rURI );
247 // mark prefix with id
248 t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) );
249 if (iFind == m_prefixes.end()) // unused prefix
251 PrefixEntry * pEntry = new PrefixEntry();
252 pEntry->m_Uids.push_back( nUid ); // latest id for prefix
253 m_prefixes[rPrefix].reset(pEntry);
255 else
257 PrefixEntry& rEntry = *iFind->second;
258 SAL_WARN_IF(rEntry.m_Uids.empty(), "xmlscript.xmlhelper", "pEntry->m_Uids is empty");
259 rEntry.m_Uids.push_back(nUid);
262 m_aLastPrefix_lookup = rPrefix;
263 m_nLastPrefix_lookup = nUid;
266 inline void DocumentHandlerImpl::popPrefix(
267 OUString const & rPrefix )
269 t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) );
270 if (iFind != m_prefixes.end()) // unused prefix
272 PrefixEntry& rEntry = *iFind->second;
273 rEntry.m_Uids.pop_back(); // pop last id for prefix
274 if (rEntry.m_Uids.empty()) // erase prefix key
276 m_prefixes.erase(iFind);
280 m_nLastPrefix_lookup = UID_UNKNOWN;
281 m_aLastPrefix_lookup = g_sXMLNS_PREFIX_UNKNOWN;
284 inline void DocumentHandlerImpl::getElementName(
285 OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName )
287 sal_Int32 nColonPos = rQName.indexOf( ':' );
288 *pLocalName = (nColonPos >= 0 ? rQName.copy( nColonPos +1 ) : rQName);
289 *pUid = getUidByPrefix(
290 nColonPos >= 0 ? rQName.copy( 0, nColonPos ) : OUString() );
293 namespace {
295 class ExtendedAttributes :
296 public ::cppu::WeakImplHelper< xml::input::XAttributes >
298 sal_Int32 const m_nAttributes;
299 std::unique_ptr<sal_Int32[]> m_pUids;
300 std::unique_ptr<OUString[]> m_pLocalNames;
301 std::unique_ptr<OUString[]> m_pQNames;
302 std::unique_ptr<OUString[]> m_pValues;
304 public:
305 inline ExtendedAttributes(
306 sal_Int32 nAttributes,
307 std::unique_ptr<sal_Int32[]> pUids,
308 std::unique_ptr<OUString[]> pLocalNames,
309 std::unique_ptr<OUString[]> pQNames,
310 Reference< xml::sax::XAttributeList > const & xAttributeList );
312 // XAttributes
313 virtual sal_Int32 SAL_CALL getLength() override;
314 virtual sal_Int32 SAL_CALL getIndexByQName(
315 OUString const & rQName ) override;
316 virtual sal_Int32 SAL_CALL getIndexByUidName(
317 sal_Int32 nUid, OUString const & rLocalName ) override;
318 virtual OUString SAL_CALL getQNameByIndex(
319 sal_Int32 nIndex ) override;
320 virtual sal_Int32 SAL_CALL getUidByIndex(
321 sal_Int32 nIndex ) override;
322 virtual OUString SAL_CALL getLocalNameByIndex(
323 sal_Int32 nIndex ) override;
324 virtual OUString SAL_CALL getValueByIndex(
325 sal_Int32 nIndex ) override;
326 virtual OUString SAL_CALL getValueByUidName(
327 sal_Int32 nUid, OUString const & rLocalName ) override;
328 virtual OUString SAL_CALL getTypeByIndex(
329 sal_Int32 nIndex ) override;
334 inline ExtendedAttributes::ExtendedAttributes(
335 sal_Int32 nAttributes,
336 std::unique_ptr<sal_Int32[]> pUids,
337 std::unique_ptr<OUString[]> pLocalNames, std::unique_ptr<OUString[]> pQNames,
338 Reference< xml::sax::XAttributeList > const & xAttributeList )
339 : m_nAttributes( nAttributes )
340 , m_pUids( std::move(pUids) )
341 , m_pLocalNames( std::move(pLocalNames) )
342 , m_pQNames( std::move(pQNames) )
343 , m_pValues( new OUString[ nAttributes ] )
345 for ( sal_Int32 nPos = 0; nPos < nAttributes; ++nPos )
347 m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos );
351 // XServiceInfo
353 OUString DocumentHandlerImpl::getImplementationName()
355 return "com.sun.star.comp.xml.input.SaxDocumentHandler";
358 sal_Bool DocumentHandlerImpl::supportsService( OUString const & servicename )
360 return cppu::supportsService(this, servicename);
363 Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames()
365 return { "com.sun.star.xml.input.SaxDocumentHandler" };
368 // XInitialization
370 void DocumentHandlerImpl::initialize(
371 Sequence< Any > const & arguments )
373 MGuard guard( m_pMutex );
374 Reference< xml::input::XRoot > xRoot;
375 if (arguments.getLength() != 1 ||
376 !(arguments[ 0 ] >>= xRoot) ||
377 !xRoot.is())
379 throw RuntimeException( "missing root instance!" );
381 m_xRoot = xRoot;
384 // XNamespaceMapping
386 sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri )
388 sal_Int32 uid = getUidByURI( Uri );
389 SAL_WARN_IF( uid == UID_UNKNOWN, "xmlscript.xmlhelper", "uid UNKNOWN");
390 return uid;
393 OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid )
395 MGuard guard( m_pMutex );
396 for (const auto& rURIUid : m_URI2Uid)
398 if (rURIUid.second == Uid)
399 return rURIUid.first;
401 throw container::NoSuchElementException( "no such xmlns uid!" , static_cast< OWeakObject * >(this) );
404 // XDocumentHandler
406 void DocumentHandlerImpl::startDocument()
408 m_xRoot->startDocument( static_cast< xml::input::XNamespaceMapping * >( this ) );
411 void DocumentHandlerImpl::endDocument()
413 m_xRoot->endDocument();
416 void DocumentHandlerImpl::startElement(
417 OUString const & rQElementName,
418 Reference< xml::sax::XAttributeList > const & xAttribs )
420 Reference< xml::input::XElement > xCurrentElement;
421 Reference< xml::input::XAttributes > xAttributes;
422 sal_Int32 nUid;
423 OUString aLocalName;
424 ElementEntry elementEntry;
426 { // guard start:
427 MGuard aGuard( m_pMutex );
428 // currently skipping elements and waiting for end tags?
429 if (m_nSkipElements > 0)
431 ++m_nSkipElements; // wait for another end tag
432 SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName << "\" ...");
433 return;
436 sal_Int16 nAttribs = xAttribs->getLength();
438 // save all namespace ids
439 std::unique_ptr<sal_Int32[]> pUids(new sal_Int32[ nAttribs ]);
440 std::unique_ptr<OUString[]> pPrefixes(new OUString[ nAttribs ]);
441 std::unique_ptr<OUString[]> pLocalNames(new OUString[ nAttribs ]);
442 std::unique_ptr<OUString[]> pQNames(new OUString[ nAttribs ]);
444 // first recognize all xmlns attributes
445 sal_Int16 nPos;
446 for ( nPos = 0; nPos < nAttribs; ++nPos )
448 // mark attribute to be collected further
449 // on with attribute's uid and current prefix
450 pUids[ nPos ] = 0; // modified
452 pQNames[ nPos ] = xAttribs->getNameByIndex( nPos );
453 OUString const & rQAttributeName = pQNames[ nPos ];
455 if (rQAttributeName.startsWith( g_sXMLNS ))
457 if (rQAttributeName.getLength() == 5) // set default namespace
459 OUString aDefNamespacePrefix;
460 pushPrefix(
461 aDefNamespacePrefix,
462 xAttribs->getValueByIndex( nPos ) );
463 elementEntry.m_prefixes.push_back( aDefNamespacePrefix );
464 pUids[ nPos ] = UID_UNKNOWN;
465 pPrefixes[ nPos ] = g_sXMLNS;
466 pLocalNames[ nPos ] = aDefNamespacePrefix;
468 else if (':' == rQAttributeName[ 5 ]) // set prefix
470 OUString aPrefix( rQAttributeName.copy( 6 ) );
471 pushPrefix( aPrefix, xAttribs->getValueByIndex( nPos ) );
472 elementEntry.m_prefixes.push_back( aPrefix );
473 pUids[ nPos ] = UID_UNKNOWN;
474 pPrefixes[ nPos ] = g_sXMLNS;
475 pLocalNames[ nPos ] = aPrefix;
477 // else just a name starting with xmlns, but no prefix
481 // now read out attribute prefixes (all namespace prefixes have been set)
482 for ( nPos = 0; nPos < nAttribs; ++nPos )
484 if (pUids[ nPos ] >= 0) // no xmlns: attribute
486 OUString const & rQAttributeName = pQNames[ nPos ];
487 SAL_WARN_IF(rQAttributeName.startsWith( "xmlns:" ), "xmlscript.xmlhelper", "### unexpected xmlns!" );
489 // collect attribute's uid and current prefix
490 sal_Int32 nColonPos = rQAttributeName.indexOf( ':' );
491 if (nColonPos >= 0)
493 pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos );
494 pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 );
496 else
498 pPrefixes[ nPos ].clear();
499 pLocalNames[ nPos ] = rQAttributeName;
500 // leave local names unmodified
502 pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] );
505 pPrefixes.reset();
506 // ownership of arrays belongs to attribute list
507 xAttributes = new ExtendedAttributes(nAttribs, std::move(pUids), std::move(pLocalNames),
508 std::move(pQNames), xAttribs);
510 getElementName( rQElementName, &nUid, &aLocalName );
512 // create new child context and append to list
513 if (! m_elements.empty())
514 xCurrentElement = m_elements.back().m_xElement;
515 } // :guard end
517 if (xCurrentElement.is())
519 elementEntry.m_xElement =
520 xCurrentElement->startChildElement( nUid, aLocalName, xAttributes );
522 else
524 elementEntry.m_xElement =
525 m_xRoot->startRootElement( nUid, aLocalName, xAttributes );
529 MGuard aGuard( m_pMutex );
530 if (elementEntry.m_xElement.is())
532 m_elements.push_back( std::move(elementEntry) );
534 else
536 ++m_nSkipElements;
538 // pop prefixes
539 for (sal_Int32 nPos = elementEntry.m_prefixes.size(); nPos--;)
540 popPrefix(elementEntry.m_prefixes[nPos]);
542 SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName << "\" ...");
547 void DocumentHandlerImpl::endElement(
548 OUString const & rQElementName )
550 Reference< xml::input::XElement > xCurrentElement;
552 MGuard aGuard( m_pMutex );
553 if (m_nSkipElements)
555 --m_nSkipElements;
556 SAL_INFO("xmlscript.xmlhelper", "### received endElement() for \"" << rQElementName << "\".");
557 return;
560 // popping context
561 SAL_WARN_IF( m_elements.empty(), "xmlscript.xmlhelper", "m_elements is empty" );
562 ElementEntry& rEntry = m_elements.back();
563 xCurrentElement = rEntry.m_xElement;
565 #if OSL_DEBUG_LEVEL > 0
566 sal_Int32 nUid;
567 OUString aLocalName;
568 getElementName( rQElementName, &nUid, &aLocalName );
569 SAL_WARN_IF( xCurrentElement->getLocalName() != aLocalName, "xmlscript.xmlhelper", "xCurrentElement->getLocalName() != aLocalName" );
570 SAL_WARN_IF( xCurrentElement->getUid() != nUid, "xmlscript.xmlhelper", "xCurrentElement->getUid() != nUid" );
571 #endif
573 // pop prefixes
574 for ( sal_Int32 nPos = rEntry.m_prefixes.size(); nPos--; )
576 popPrefix( rEntry.m_prefixes[ nPos ] );
578 m_elements.pop_back();
580 xCurrentElement->endElement();
583 void DocumentHandlerImpl::characters( OUString const & rChars )
585 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
586 if (xCurrentElement.is())
587 xCurrentElement->characters( rChars );
590 void DocumentHandlerImpl::ignorableWhitespace(
591 OUString const & rWhitespaces )
593 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
594 if (xCurrentElement.is())
595 xCurrentElement->ignorableWhitespace( rWhitespaces );
598 void DocumentHandlerImpl::processingInstruction(
599 OUString const & rTarget, OUString const & rData )
601 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
602 if (xCurrentElement.is())
603 xCurrentElement->processingInstruction( rTarget, rData );
604 else
605 m_xRoot->processingInstruction( rTarget, rData );
608 void DocumentHandlerImpl::setDocumentLocator(
609 Reference< xml::sax::XLocator > const & xLocator )
611 m_xRoot->setDocumentLocator( xLocator );
614 // XAttributes
616 sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName )
618 for ( sal_Int32 nPos = m_nAttributes; nPos--; )
620 if (m_pQNames[ nPos ] == rQName)
622 return nPos;
625 return -1;
628 sal_Int32 ExtendedAttributes::getLength()
630 return m_nAttributes;
633 OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex )
635 if (nIndex < m_nAttributes)
636 return m_pLocalNames[ nIndex ];
637 else
638 return OUString();
641 OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex )
643 if (nIndex < m_nAttributes)
644 return m_pQNames[ nIndex ];
645 else
646 return OUString();
649 OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex )
651 SAL_WARN_IF( nIndex >= m_nAttributes , "xmlscript.xmlhelper", "nIndex is bigger then m_nAttributes");
652 return OUString(); // unsupported
655 OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex )
657 if (nIndex < m_nAttributes)
658 return m_pValues[ nIndex ];
659 else
660 return OUString();
663 sal_Int32 ExtendedAttributes::getIndexByUidName(
664 sal_Int32 nUid, OUString const & rLocalName )
666 for ( sal_Int32 nPos = m_nAttributes; nPos--; )
668 if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
670 return nPos;
673 return -1;
676 sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex )
678 if (nIndex < m_nAttributes)
679 return m_pUids[ nIndex ];
680 else
681 return -1;
684 OUString ExtendedAttributes::getValueByUidName(
685 sal_Int32 nUid, OUString const & rLocalName )
687 for ( sal_Int32 nPos = m_nAttributes; nPos--; )
689 if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
691 return m_pValues[ nPos ];
694 return OUString();
697 Reference< xml::sax::XDocumentHandler > createDocumentHandler(
698 Reference< xml::input::XRoot > const & xRoot )
700 SAL_WARN_IF( !xRoot.is(), "xmlscript.xmlhelper", "xRoot is NULL" );
701 if (xRoot.is())
703 return new DocumentHandlerImpl(xRoot, true /* mt use */);
705 return Reference< xml::sax::XDocumentHandler >();
710 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
711 com_sun_star_comp_xml_input_SaxDocumentHandler_get_implementation(
712 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const& )
714 return cppu::acquire(static_cast<cppu::OWeakObject*>(new xmlscript::DocumentHandlerImpl(
715 Reference< xml::input::XRoot >(), false /* mt use */ )));
718 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */