Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / xmlscript / source / xml_helper / xml_impctx.cxx
blobe382632437179405642ee27f4dd695cc638aac5d
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 <mutex>
35 #include <optional>
36 #include <unordered_map>
37 #include <vector>
39 using namespace ::osl;
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::uno;
43 namespace xmlscript
46 const sal_Int32 UID_UNKNOWN = -1;
48 typedef std::unordered_map< OUString, sal_Int32 > t_OUString2LongMap;
50 namespace {
52 struct PrefixEntry
54 ::std::vector< sal_Int32 > m_Uids;
56 PrefixEntry()
57 { m_Uids.reserve( 4 ); }
62 typedef std::unordered_map<
63 OUString, std::unique_ptr<PrefixEntry> > t_OUString2PrefixMap;
65 namespace {
67 struct ElementEntry
69 Reference< xml::input::XElement > m_xElement;
70 ::std::vector< OUString > m_prefixes;
72 ElementEntry()
73 { m_prefixes.reserve( 2 ); }
76 class ExtendedAttributes;
78 class MGuard
80 std::mutex * m_pMutex;
81 public:
82 explicit MGuard( std::optional<std::mutex> & oMutex )
83 : m_pMutex( oMutex ? &*oMutex : nullptr )
84 { if (m_pMutex) m_pMutex->lock(); }
85 ~MGuard() noexcept
86 { if (m_pMutex) m_pMutex->unlock(); }
89 class DocumentHandlerImpl :
90 public ::cppu::WeakImplHelper< xml::sax::XDocumentHandler,
91 xml::input::XNamespaceMapping,
92 lang::XInitialization,
93 css::lang::XServiceInfo >
95 friend class ExtendedAttributes;
97 Reference< xml::input::XRoot > m_xRoot;
99 t_OUString2LongMap m_URI2Uid;
100 sal_Int32 m_uid_count;
102 sal_Int32 m_nLastURI_lookup;
103 OUString m_aLastURI_lookup;
105 t_OUString2PrefixMap m_prefixes;
106 sal_Int32 m_nLastPrefix_lookup;
107 OUString m_aLastPrefix_lookup;
109 std::vector< ElementEntry > m_elements;
110 sal_Int32 m_nSkipElements;
112 mutable std::optional<std::mutex> m_oMutex;
114 inline Reference< xml::input::XElement > getCurrentElement() const;
116 inline sal_Int32 getUidByURI( OUString const & rURI );
117 inline sal_Int32 getUidByPrefix( OUString const & rPrefix );
119 inline void pushPrefix(
120 OUString const & rPrefix, OUString const & rURI );
121 inline void popPrefix( OUString const & rPrefix );
123 inline void getElementName(
124 OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName );
126 public:
127 DocumentHandlerImpl(
128 Reference< xml::input::XRoot > const & xRoot,
129 bool bSingleThreadedUse );
131 // XServiceInfo
132 virtual OUString SAL_CALL getImplementationName() override;
133 virtual sal_Bool SAL_CALL supportsService(
134 OUString const & servicename ) override;
135 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
137 // XInitialization
138 virtual void SAL_CALL initialize(
139 Sequence< Any > const & arguments ) override;
141 // XDocumentHandler
142 virtual void SAL_CALL startDocument() override;
143 virtual void SAL_CALL endDocument() override;
144 virtual void SAL_CALL startElement(
145 OUString const & rQElementName,
146 Reference< xml::sax::XAttributeList > const & xAttribs ) override;
147 virtual void SAL_CALL endElement(
148 OUString const & rQElementName ) override;
149 virtual void SAL_CALL characters(
150 OUString const & rChars ) override;
151 virtual void SAL_CALL ignorableWhitespace(
152 OUString const & rWhitespaces ) override;
153 virtual void SAL_CALL processingInstruction(
154 OUString const & rTarget, OUString const & rData ) override;
155 virtual void SAL_CALL setDocumentLocator(
156 Reference< xml::sax::XLocator > const & xLocator ) override;
158 // XNamespaceMapping
159 virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri ) override;
160 virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid ) override;
165 constexpr OUStringLiteral g_sXMLNS_PREFIX_UNKNOWN( u"<<< unknown prefix >>>" );
166 constexpr OUStringLiteral g_sXMLNS( u"xmlns" );
169 DocumentHandlerImpl::DocumentHandlerImpl(
170 Reference< xml::input::XRoot > const & xRoot,
171 bool bSingleThreadedUse )
172 : m_xRoot( xRoot ),
173 m_uid_count( 0 ),
174 m_nLastURI_lookup( UID_UNKNOWN ),
175 m_aLastURI_lookup( "<<< unknown URI >>>" ),
176 m_nLastPrefix_lookup( UID_UNKNOWN ),
177 m_aLastPrefix_lookup( "<<< unknown URI >>>" ),
178 m_nSkipElements( 0 )
180 m_elements.reserve( 10 );
182 if (! bSingleThreadedUse)
183 m_oMutex.emplace();
186 inline Reference< xml::input::XElement >
187 DocumentHandlerImpl::getCurrentElement() const
189 MGuard aGuard( m_oMutex );
190 if (m_elements.empty())
191 return Reference< xml::input::XElement >();
192 else
193 return m_elements.back().m_xElement;
196 inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI )
198 MGuard guard( m_oMutex );
199 if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI)
201 t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) );
202 if (iFind != m_URI2Uid.end()) // id found
204 m_nLastURI_lookup = iFind->second;
205 m_aLastURI_lookup = rURI;
207 else
209 m_nLastURI_lookup = m_uid_count;
210 ++m_uid_count;
211 m_URI2Uid[ rURI ] = m_nLastURI_lookup;
212 m_aLastURI_lookup = rURI;
215 return m_nLastURI_lookup;
218 inline sal_Int32 DocumentHandlerImpl::getUidByPrefix(
219 OUString const & rPrefix )
221 // commonly the last added prefix is used often for several tags...
222 // good guess
223 if (m_nLastPrefix_lookup == UID_UNKNOWN || m_aLastPrefix_lookup != rPrefix)
225 t_OUString2PrefixMap::const_iterator iFind(
226 m_prefixes.find( rPrefix ) );
227 if (iFind != m_prefixes.end())
229 const PrefixEntry & rPrefixEntry = *iFind->second;
230 SAL_WARN_IF( rPrefixEntry.m_Uids.empty(), "xmlscript.xmlhelper", "rPrefixEntry.m_Uids is empty" );
231 m_nLastPrefix_lookup = rPrefixEntry.m_Uids.back();
232 m_aLastPrefix_lookup = rPrefix;
234 else
236 m_nLastPrefix_lookup = UID_UNKNOWN;
237 m_aLastPrefix_lookup = g_sXMLNS_PREFIX_UNKNOWN;
240 return m_nLastPrefix_lookup;
243 inline void DocumentHandlerImpl::pushPrefix(
244 OUString const & rPrefix, OUString const & rURI )
246 // lookup id for URI
247 sal_Int32 nUid = getUidByURI( rURI );
249 // mark prefix with id
250 t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) );
251 if (iFind == m_prefixes.end()) // unused prefix
253 PrefixEntry * pEntry = new PrefixEntry();
254 pEntry->m_Uids.push_back( nUid ); // latest id for prefix
255 m_prefixes[rPrefix].reset(pEntry);
257 else
259 PrefixEntry& rEntry = *iFind->second;
260 SAL_WARN_IF(rEntry.m_Uids.empty(), "xmlscript.xmlhelper", "pEntry->m_Uids is empty");
261 rEntry.m_Uids.push_back(nUid);
264 m_aLastPrefix_lookup = rPrefix;
265 m_nLastPrefix_lookup = nUid;
268 inline void DocumentHandlerImpl::popPrefix(
269 OUString const & rPrefix )
271 t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) );
272 if (iFind != m_prefixes.end()) // unused prefix
274 PrefixEntry& rEntry = *iFind->second;
275 rEntry.m_Uids.pop_back(); // pop last id for prefix
276 if (rEntry.m_Uids.empty()) // erase prefix key
278 m_prefixes.erase(iFind);
282 m_nLastPrefix_lookup = UID_UNKNOWN;
283 m_aLastPrefix_lookup = g_sXMLNS_PREFIX_UNKNOWN;
286 inline void DocumentHandlerImpl::getElementName(
287 OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName )
289 sal_Int32 nColonPos = rQName.indexOf( ':' );
290 *pLocalName = (nColonPos >= 0 ? rQName.copy( nColonPos +1 ) : rQName);
291 *pUid = getUidByPrefix(
292 nColonPos >= 0 ? rQName.copy( 0, nColonPos ) : OUString() );
295 namespace {
297 class ExtendedAttributes :
298 public ::cppu::WeakImplHelper< xml::input::XAttributes >
300 sal_Int32 const m_nAttributes;
301 std::unique_ptr<sal_Int32[]> m_pUids;
302 std::unique_ptr<OUString[]> m_pLocalNames;
303 std::unique_ptr<OUString[]> m_pQNames;
304 std::unique_ptr<OUString[]> m_pValues;
306 public:
307 inline ExtendedAttributes(
308 sal_Int32 nAttributes,
309 std::unique_ptr<sal_Int32[]> pUids,
310 std::unique_ptr<OUString[]> pLocalNames,
311 std::unique_ptr<OUString[]> pQNames,
312 Reference< xml::sax::XAttributeList > const & xAttributeList );
314 // XAttributes
315 virtual sal_Int32 SAL_CALL getLength() override;
316 virtual sal_Int32 SAL_CALL getIndexByQName(
317 OUString const & rQName ) override;
318 virtual sal_Int32 SAL_CALL getIndexByUidName(
319 sal_Int32 nUid, OUString const & rLocalName ) override;
320 virtual OUString SAL_CALL getQNameByIndex(
321 sal_Int32 nIndex ) override;
322 virtual sal_Int32 SAL_CALL getUidByIndex(
323 sal_Int32 nIndex ) override;
324 virtual OUString SAL_CALL getLocalNameByIndex(
325 sal_Int32 nIndex ) override;
326 virtual OUString SAL_CALL getValueByIndex(
327 sal_Int32 nIndex ) override;
328 virtual OUString SAL_CALL getValueByUidName(
329 sal_Int32 nUid, OUString const & rLocalName ) override;
330 virtual OUString SAL_CALL getTypeByIndex(
331 sal_Int32 nIndex ) override;
336 inline ExtendedAttributes::ExtendedAttributes(
337 sal_Int32 nAttributes,
338 std::unique_ptr<sal_Int32[]> pUids,
339 std::unique_ptr<OUString[]> pLocalNames, std::unique_ptr<OUString[]> pQNames,
340 Reference< xml::sax::XAttributeList > const & xAttributeList )
341 : m_nAttributes( nAttributes )
342 , m_pUids( std::move(pUids) )
343 , m_pLocalNames( std::move(pLocalNames) )
344 , m_pQNames( std::move(pQNames) )
345 , m_pValues( new OUString[ nAttributes ] )
347 for ( sal_Int32 nPos = 0; nPos < nAttributes; ++nPos )
349 m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos );
353 // XServiceInfo
355 OUString DocumentHandlerImpl::getImplementationName()
357 return "com.sun.star.comp.xml.input.SaxDocumentHandler";
360 sal_Bool DocumentHandlerImpl::supportsService( OUString const & servicename )
362 return cppu::supportsService(this, servicename);
365 Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames()
367 return { "com.sun.star.xml.input.SaxDocumentHandler" };
370 // XInitialization
372 void DocumentHandlerImpl::initialize(
373 Sequence< Any > const & arguments )
375 MGuard guard( m_oMutex );
376 Reference< xml::input::XRoot > xRoot;
377 if (arguments.getLength() != 1 ||
378 !(arguments[ 0 ] >>= xRoot) ||
379 !xRoot.is())
381 throw RuntimeException( "missing root instance!" );
383 m_xRoot = xRoot;
386 // XNamespaceMapping
388 sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri )
390 sal_Int32 uid = getUidByURI( Uri );
391 SAL_WARN_IF( uid == UID_UNKNOWN, "xmlscript.xmlhelper", "uid UNKNOWN");
392 return uid;
395 OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid )
397 MGuard guard( m_oMutex );
398 for (const auto& rURIUid : m_URI2Uid)
400 if (rURIUid.second == Uid)
401 return rURIUid.first;
403 throw container::NoSuchElementException( "no such xmlns uid!" , getXWeak() );
406 // XDocumentHandler
408 void DocumentHandlerImpl::startDocument()
410 m_xRoot->startDocument( static_cast< xml::input::XNamespaceMapping * >( this ) );
413 void DocumentHandlerImpl::endDocument()
415 m_xRoot->endDocument();
418 void DocumentHandlerImpl::startElement(
419 OUString const & rQElementName,
420 Reference< xml::sax::XAttributeList > const & xAttribs )
422 Reference< xml::input::XElement > xCurrentElement;
423 Reference< xml::input::XAttributes > xAttributes;
424 sal_Int32 nUid;
425 OUString aLocalName;
426 ElementEntry elementEntry;
428 { // guard start:
429 MGuard aGuard( m_oMutex );
430 // currently skipping elements and waiting for end tags?
431 if (m_nSkipElements > 0)
433 ++m_nSkipElements; // wait for another end tag
434 SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName << "\" ...");
435 return;
438 sal_Int16 nAttribs = xAttribs->getLength();
440 // save all namespace ids
441 std::unique_ptr<sal_Int32[]> pUids(new sal_Int32[ nAttribs ]);
442 std::unique_ptr<OUString[]> pPrefixes(new OUString[ nAttribs ]);
443 std::unique_ptr<OUString[]> pLocalNames(new OUString[ nAttribs ]);
444 std::unique_ptr<OUString[]> pQNames(new OUString[ nAttribs ]);
446 // first recognize all xmlns attributes
447 sal_Int16 nPos;
448 for ( nPos = 0; nPos < nAttribs; ++nPos )
450 // mark attribute to be collected further
451 // on with attribute's uid and current prefix
452 pUids[ nPos ] = 0; // modified
454 pQNames[ nPos ] = xAttribs->getNameByIndex( nPos );
455 OUString const & rQAttributeName = pQNames[ nPos ];
457 if (rQAttributeName.startsWith( g_sXMLNS ))
459 if (rQAttributeName.getLength() == 5) // set default namespace
461 OUString aDefNamespacePrefix;
462 pushPrefix(
463 aDefNamespacePrefix,
464 xAttribs->getValueByIndex( nPos ) );
465 elementEntry.m_prefixes.push_back( aDefNamespacePrefix );
466 pUids[ nPos ] = UID_UNKNOWN;
467 pPrefixes[ nPos ] = g_sXMLNS;
468 pLocalNames[ nPos ] = aDefNamespacePrefix;
470 else if (':' == rQAttributeName[ 5 ]) // set prefix
472 OUString aPrefix( rQAttributeName.copy( 6 ) );
473 pushPrefix( aPrefix, xAttribs->getValueByIndex( nPos ) );
474 elementEntry.m_prefixes.push_back( aPrefix );
475 pUids[ nPos ] = UID_UNKNOWN;
476 pPrefixes[ nPos ] = g_sXMLNS;
477 pLocalNames[ nPos ] = aPrefix;
479 // else just a name starting with xmlns, but no prefix
483 // now read out attribute prefixes (all namespace prefixes have been set)
484 for ( nPos = 0; nPos < nAttribs; ++nPos )
486 if (pUids[ nPos ] >= 0) // no xmlns: attribute
488 OUString const & rQAttributeName = pQNames[ nPos ];
489 SAL_WARN_IF(rQAttributeName.startsWith( "xmlns:" ), "xmlscript.xmlhelper", "### unexpected xmlns!" );
491 // collect attribute's uid and current prefix
492 sal_Int32 nColonPos = rQAttributeName.indexOf( ':' );
493 if (nColonPos >= 0)
495 pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos );
496 pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 );
498 else
500 pPrefixes[ nPos ].clear();
501 pLocalNames[ nPos ] = rQAttributeName;
502 // leave local names unmodified
504 pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] );
507 pPrefixes.reset();
508 // ownership of arrays belongs to attribute list
509 xAttributes = new ExtendedAttributes(nAttribs, std::move(pUids), std::move(pLocalNames),
510 std::move(pQNames), xAttribs);
512 getElementName( rQElementName, &nUid, &aLocalName );
514 // create new child context and append to list
515 if (! m_elements.empty())
516 xCurrentElement = m_elements.back().m_xElement;
517 } // :guard end
519 if (xCurrentElement.is())
521 elementEntry.m_xElement =
522 xCurrentElement->startChildElement( nUid, aLocalName, xAttributes );
524 else
526 elementEntry.m_xElement =
527 m_xRoot->startRootElement( nUid, aLocalName, xAttributes );
531 MGuard aGuard( m_oMutex );
532 if (elementEntry.m_xElement.is())
534 m_elements.push_back( std::move(elementEntry) );
536 else
538 ++m_nSkipElements;
540 // pop prefixes
541 for (sal_Int32 nPos = elementEntry.m_prefixes.size(); nPos--;)
542 popPrefix(elementEntry.m_prefixes[nPos]);
544 SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName << "\" ...");
549 void DocumentHandlerImpl::endElement(
550 OUString const & rQElementName )
552 Reference< xml::input::XElement > xCurrentElement;
554 MGuard aGuard( m_oMutex );
555 if (m_nSkipElements)
557 --m_nSkipElements;
558 SAL_INFO("xmlscript.xmlhelper", "### received endElement() for \"" << rQElementName << "\".");
559 return;
562 // popping context
563 SAL_WARN_IF( m_elements.empty(), "xmlscript.xmlhelper", "m_elements is empty" );
564 ElementEntry& rEntry = m_elements.back();
565 xCurrentElement = rEntry.m_xElement;
567 #if OSL_DEBUG_LEVEL > 0
568 sal_Int32 nUid;
569 OUString aLocalName;
570 getElementName( rQElementName, &nUid, &aLocalName );
571 SAL_WARN_IF( xCurrentElement->getLocalName() != aLocalName, "xmlscript.xmlhelper", "xCurrentElement->getLocalName() != aLocalName" );
572 SAL_WARN_IF( xCurrentElement->getUid() != nUid, "xmlscript.xmlhelper", "xCurrentElement->getUid() != nUid" );
573 #endif
575 // pop prefixes
576 for ( sal_Int32 nPos = rEntry.m_prefixes.size(); nPos--; )
578 popPrefix( rEntry.m_prefixes[ nPos ] );
580 m_elements.pop_back();
582 xCurrentElement->endElement();
585 void DocumentHandlerImpl::characters( OUString const & rChars )
587 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
588 if (xCurrentElement.is())
589 xCurrentElement->characters( rChars );
592 void DocumentHandlerImpl::ignorableWhitespace(
593 OUString const & rWhitespaces )
595 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
596 if (xCurrentElement.is())
597 xCurrentElement->ignorableWhitespace( rWhitespaces );
600 void DocumentHandlerImpl::processingInstruction(
601 OUString const & rTarget, OUString const & rData )
603 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
604 if (xCurrentElement.is())
605 xCurrentElement->processingInstruction( rTarget, rData );
606 else
607 m_xRoot->processingInstruction( rTarget, rData );
610 void DocumentHandlerImpl::setDocumentLocator(
611 Reference< xml::sax::XLocator > const & xLocator )
613 m_xRoot->setDocumentLocator( xLocator );
616 // XAttributes
618 sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName )
620 for ( sal_Int32 nPos = m_nAttributes; nPos--; )
622 if (m_pQNames[ nPos ] == rQName)
624 return nPos;
627 return -1;
630 sal_Int32 ExtendedAttributes::getLength()
632 return m_nAttributes;
635 OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex )
637 if (nIndex < m_nAttributes)
638 return m_pLocalNames[ nIndex ];
639 else
640 return OUString();
643 OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex )
645 if (nIndex < m_nAttributes)
646 return m_pQNames[ nIndex ];
647 else
648 return OUString();
651 OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex )
653 SAL_WARN_IF( nIndex >= m_nAttributes , "xmlscript.xmlhelper", "nIndex is bigger then m_nAttributes");
654 return OUString(); // unsupported
657 OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex )
659 if (nIndex < m_nAttributes)
660 return m_pValues[ nIndex ];
661 else
662 return OUString();
665 sal_Int32 ExtendedAttributes::getIndexByUidName(
666 sal_Int32 nUid, OUString const & rLocalName )
668 for ( sal_Int32 nPos = m_nAttributes; nPos--; )
670 if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
672 return nPos;
675 return -1;
678 sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex )
680 if (nIndex < m_nAttributes)
681 return m_pUids[ nIndex ];
682 else
683 return -1;
686 OUString ExtendedAttributes::getValueByUidName(
687 sal_Int32 nUid, OUString const & rLocalName )
689 for ( sal_Int32 nPos = m_nAttributes; nPos--; )
691 if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
693 return m_pValues[ nPos ];
696 return OUString();
699 Reference< xml::sax::XDocumentHandler > createDocumentHandler(
700 Reference< xml::input::XRoot > const & xRoot )
702 SAL_WARN_IF( !xRoot.is(), "xmlscript.xmlhelper", "xRoot is NULL" );
703 if (xRoot.is())
705 return new DocumentHandlerImpl(xRoot, true /* mt use */);
707 return Reference< xml::sax::XDocumentHandler >();
712 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
713 com_sun_star_comp_xml_input_SaxDocumentHandler_get_implementation(
714 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const& )
716 return cppu::acquire(new xmlscript::DocumentHandlerImpl({}, false /* mt use */));
719 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */