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 .
20 #include <sal/config.h>
22 #include <unoservices.hxx>
23 #include <xml_import.hxx>
25 #include <cppuhelper/implbase.hxx>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <com/sun/star/container/NoSuchElementException.hpp>
28 #include <com/sun/star/xml/input/XAttributes.hpp>
29 #include <com/sun/star/lang/XInitialization.hpp>
30 #include <com/sun/star/uno/XComponentContext.hpp>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <sal/log.hxx>
35 #include <unordered_map>
38 using namespace ::osl
;
39 using namespace ::com::sun::star
;
40 using namespace ::com::sun::star::uno
;
45 const sal_Int32 UID_UNKNOWN
= -1;
47 Sequence
< OUString
> getSupportedServiceNames_DocumentHandlerImpl()
49 return Sequence
< OUString
> { "com.sun.star.xml.input.SaxDocumentHandler" };
52 OUString
getImplementationName_DocumentHandlerImpl()
54 return "com.sun.star.comp.xml.input.SaxDocumentHandler";
57 typedef std::unordered_map
< OUString
, sal_Int32
> t_OUString2LongMap
;
61 ::std::vector
< sal_Int32
> m_Uids
;
64 { m_Uids
.reserve( 4 ); }
67 typedef std::unordered_map
<
68 OUString
, std::unique_ptr
<PrefixEntry
> > t_OUString2PrefixMap
;
72 Reference
< xml::input::XElement
> m_xElement
;
73 ::std::vector
< OUString
> m_prefixes
;
76 { m_prefixes
.reserve( 2 ); }
79 class ExtendedAttributes
;
85 explicit MGuard( std::unique_ptr
<Mutex
> const & pMutex
)
86 : m_pMutex( pMutex
.get() )
87 { if (m_pMutex
) m_pMutex
->acquire(); }
89 { if (m_pMutex
) m_pMutex
->release(); }
92 class DocumentHandlerImpl
:
93 public ::cppu::WeakImplHelper
< xml::sax::XDocumentHandler
,
94 xml::input::XNamespaceMapping
,
95 lang::XInitialization
,
96 css::lang::XServiceInfo
>
98 friend class ExtendedAttributes
;
100 Reference
< xml::input::XRoot
> m_xRoot
;
102 t_OUString2LongMap m_URI2Uid
;
103 sal_Int32 m_uid_count
;
105 sal_Int32 m_nLastURI_lookup
;
106 OUString m_aLastURI_lookup
;
108 t_OUString2PrefixMap m_prefixes
;
109 sal_Int32 m_nLastPrefix_lookup
;
110 OUString m_aLastPrefix_lookup
;
112 std::vector
< ElementEntry
> m_elements
;
113 sal_Int32 m_nSkipElements
;
115 std::unique_ptr
<Mutex
> m_pMutex
;
117 inline Reference
< xml::input::XElement
> getCurrentElement() const;
119 inline sal_Int32
getUidByURI( OUString
const & rURI
);
120 inline sal_Int32
getUidByPrefix( OUString
const & rPrefix
);
122 inline void pushPrefix(
123 OUString
const & rPrefix
, OUString
const & rURI
);
124 inline void popPrefix( OUString
const & rPrefix
);
126 inline void getElementName(
127 OUString
const & rQName
, sal_Int32
* pUid
, OUString
* pLocalName
);
131 Reference
< xml::input::XRoot
> const & xRoot
,
132 bool bSingleThreadedUse
);
135 virtual OUString SAL_CALL
getImplementationName() override
;
136 virtual sal_Bool SAL_CALL
supportsService(
137 OUString
const & servicename
) override
;
138 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
141 virtual void SAL_CALL
initialize(
142 Sequence
< Any
> const & arguments
) override
;
145 virtual void SAL_CALL
startDocument() override
;
146 virtual void SAL_CALL
endDocument() override
;
147 virtual void SAL_CALL
startElement(
148 OUString
const & rQElementName
,
149 Reference
< xml::sax::XAttributeList
> const & xAttribs
) override
;
150 virtual void SAL_CALL
endElement(
151 OUString
const & rQElementName
) override
;
152 virtual void SAL_CALL
characters(
153 OUString
const & rChars
) override
;
154 virtual void SAL_CALL
ignorableWhitespace(
155 OUString
const & rWhitespaces
) override
;
156 virtual void SAL_CALL
processingInstruction(
157 OUString
const & rTarget
, OUString
const & rData
) override
;
158 virtual void SAL_CALL
setDocumentLocator(
159 Reference
< xml::sax::XLocator
> const & xLocator
) override
;
162 virtual sal_Int32 SAL_CALL
getUidByUri( OUString
const & Uri
) override
;
163 virtual OUString SAL_CALL
getUriByUid( sal_Int32 Uid
) override
;
166 static OUString
const g_sXMLNS_PREFIX_UNKNOWN( "<<< unknown prefix >>>" );
167 static OUString
const g_sXMLNS( "xmlns" );
170 DocumentHandlerImpl::DocumentHandlerImpl(
171 Reference
< xml::input::XRoot
> const & xRoot
,
172 bool bSingleThreadedUse
)
175 m_nLastURI_lookup( UID_UNKNOWN
),
176 m_aLastURI_lookup( "<<< unknown URI >>>" ),
177 m_nLastPrefix_lookup( UID_UNKNOWN
),
178 m_aLastPrefix_lookup( "<<< unknown URI >>>" ),
181 m_elements
.reserve( 10 );
183 if (! bSingleThreadedUse
)
184 m_pMutex
.reset(new Mutex
);
187 inline Reference
< xml::input::XElement
>
188 DocumentHandlerImpl::getCurrentElement() const
190 MGuard
aGuard( m_pMutex
);
191 if (m_elements
.empty())
192 return Reference
< xml::input::XElement
>();
194 return m_elements
.back().m_xElement
;
197 inline sal_Int32
DocumentHandlerImpl::getUidByURI( OUString
const & rURI
)
199 MGuard
guard( m_pMutex
);
200 if (m_nLastURI_lookup
== UID_UNKNOWN
|| m_aLastURI_lookup
!= rURI
)
202 t_OUString2LongMap::const_iterator
iFind( m_URI2Uid
.find( rURI
) );
203 if (iFind
!= m_URI2Uid
.end()) // id found
205 m_nLastURI_lookup
= iFind
->second
;
206 m_aLastURI_lookup
= rURI
;
210 m_nLastURI_lookup
= m_uid_count
;
212 m_URI2Uid
[ rURI
] = m_nLastURI_lookup
;
213 m_aLastURI_lookup
= rURI
;
216 return m_nLastURI_lookup
;
219 inline sal_Int32
DocumentHandlerImpl::getUidByPrefix(
220 OUString
const & rPrefix
)
222 // commonly the last added prefix is used often for several tags...
224 if (m_nLastPrefix_lookup
== UID_UNKNOWN
|| m_aLastPrefix_lookup
!= rPrefix
)
226 t_OUString2PrefixMap::const_iterator
iFind(
227 m_prefixes
.find( rPrefix
) );
228 if (iFind
!= m_prefixes
.end())
230 const PrefixEntry
& rPrefixEntry
= *iFind
->second
;
231 SAL_WARN_IF( rPrefixEntry
.m_Uids
.empty(), "xmlscript.xmlhelper", "rPrefixEntry.m_Uids is empty" );
232 m_nLastPrefix_lookup
= rPrefixEntry
.m_Uids
.back();
233 m_aLastPrefix_lookup
= rPrefix
;
237 m_nLastPrefix_lookup
= UID_UNKNOWN
;
238 m_aLastPrefix_lookup
= g_sXMLNS_PREFIX_UNKNOWN
;
241 return m_nLastPrefix_lookup
;
244 inline void DocumentHandlerImpl::pushPrefix(
245 OUString
const & rPrefix
, OUString
const & rURI
)
248 sal_Int32 nUid
= getUidByURI( rURI
);
250 // mark prefix with id
251 t_OUString2PrefixMap::const_iterator
iFind( m_prefixes
.find( rPrefix
) );
252 if (iFind
== m_prefixes
.end()) // unused prefix
254 PrefixEntry
* pEntry
= new PrefixEntry();
255 pEntry
->m_Uids
.push_back( nUid
); // latest id for prefix
256 m_prefixes
[rPrefix
].reset(pEntry
);
260 PrefixEntry
& rEntry
= *iFind
->second
;
261 SAL_WARN_IF(rEntry
.m_Uids
.empty(), "xmlscript.xmlhelper", "pEntry->m_Uids is empty");
262 rEntry
.m_Uids
.push_back(nUid
);
265 m_aLastPrefix_lookup
= rPrefix
;
266 m_nLastPrefix_lookup
= nUid
;
269 inline void DocumentHandlerImpl::popPrefix(
270 OUString
const & rPrefix
)
272 t_OUString2PrefixMap::iterator
iFind( m_prefixes
.find( rPrefix
) );
273 if (iFind
!= m_prefixes
.end()) // unused prefix
275 PrefixEntry
& rEntry
= *iFind
->second
;
276 rEntry
.m_Uids
.pop_back(); // pop last id for prefix
277 if (rEntry
.m_Uids
.empty()) // erase prefix key
279 m_prefixes
.erase(iFind
);
283 m_nLastPrefix_lookup
= UID_UNKNOWN
;
284 m_aLastPrefix_lookup
= g_sXMLNS_PREFIX_UNKNOWN
;
287 inline void DocumentHandlerImpl::getElementName(
288 OUString
const & rQName
, sal_Int32
* pUid
, OUString
* pLocalName
)
290 sal_Int32 nColonPos
= rQName
.indexOf( ':' );
291 *pLocalName
= (nColonPos
>= 0 ? rQName
.copy( nColonPos
+1 ) : rQName
);
292 *pUid
= getUidByPrefix(
293 nColonPos
>= 0 ? rQName
.copy( 0, nColonPos
) : OUString() );
296 class ExtendedAttributes
:
297 public ::cppu::WeakImplHelper
< xml::input::XAttributes
>
299 sal_Int32
const m_nAttributes
;
300 std::unique_ptr
<sal_Int32
[]> m_pUids
;
301 std::unique_ptr
<OUString
[]> m_pLocalNames
;
302 std::unique_ptr
<OUString
[]> m_pQNames
;
303 std::unique_ptr
<OUString
[]> m_pValues
;
306 inline ExtendedAttributes(
307 sal_Int32 nAttributes
,
308 std::unique_ptr
<sal_Int32
[]> pUids
,
309 std::unique_ptr
<OUString
[]> pLocalNames
,
310 std::unique_ptr
<OUString
[]> pQNames
,
311 Reference
< xml::sax::XAttributeList
> const & xAttributeList
);
314 virtual sal_Int32 SAL_CALL
getLength() override
;
315 virtual sal_Int32 SAL_CALL
getIndexByQName(
316 OUString
const & rQName
) override
;
317 virtual sal_Int32 SAL_CALL
getIndexByUidName(
318 sal_Int32 nUid
, OUString
const & rLocalName
) override
;
319 virtual OUString SAL_CALL
getQNameByIndex(
320 sal_Int32 nIndex
) override
;
321 virtual sal_Int32 SAL_CALL
getUidByIndex(
322 sal_Int32 nIndex
) override
;
323 virtual OUString SAL_CALL
getLocalNameByIndex(
324 sal_Int32 nIndex
) override
;
325 virtual OUString SAL_CALL
getValueByIndex(
326 sal_Int32 nIndex
) override
;
327 virtual OUString SAL_CALL
getValueByUidName(
328 sal_Int32 nUid
, OUString
const & rLocalName
) override
;
329 virtual OUString SAL_CALL
getTypeByIndex(
330 sal_Int32 nIndex
) override
;
333 inline ExtendedAttributes::ExtendedAttributes(
334 sal_Int32 nAttributes
,
335 std::unique_ptr
<sal_Int32
[]> pUids
,
336 std::unique_ptr
<OUString
[]> pLocalNames
, std::unique_ptr
<OUString
[]> pQNames
,
337 Reference
< xml::sax::XAttributeList
> const & xAttributeList
)
338 : m_nAttributes( nAttributes
)
339 , m_pUids( std::move(pUids
) )
340 , m_pLocalNames( std::move(pLocalNames
) )
341 , m_pQNames( std::move(pQNames
) )
342 , m_pValues( new OUString
[ nAttributes
] )
344 for ( sal_Int32 nPos
= 0; nPos
< nAttributes
; ++nPos
)
346 m_pValues
[ nPos
] = xAttributeList
->getValueByIndex( nPos
);
352 OUString
DocumentHandlerImpl::getImplementationName()
354 return getImplementationName_DocumentHandlerImpl();
357 sal_Bool
DocumentHandlerImpl::supportsService( OUString
const & servicename
)
359 return cppu::supportsService(this, servicename
);
362 Sequence
< OUString
> DocumentHandlerImpl::getSupportedServiceNames()
364 return getSupportedServiceNames_DocumentHandlerImpl();
369 void DocumentHandlerImpl::initialize(
370 Sequence
< Any
> const & arguments
)
372 MGuard
guard( m_pMutex
);
373 Reference
< xml::input::XRoot
> xRoot
;
374 if (arguments
.getLength() != 1 ||
375 !(arguments
[ 0 ] >>= xRoot
) ||
378 throw RuntimeException( "missing root instance!" );
385 sal_Int32
DocumentHandlerImpl::getUidByUri( OUString
const & Uri
)
387 sal_Int32 uid
= getUidByURI( Uri
);
388 SAL_WARN_IF( uid
== UID_UNKNOWN
, "xmlscript.xmlhelper", "uid UNKNOWN");
392 OUString
DocumentHandlerImpl::getUriByUid( sal_Int32 Uid
)
394 MGuard
guard( m_pMutex
);
395 for (const auto& rURIUid
: m_URI2Uid
)
397 if (rURIUid
.second
== Uid
)
398 return rURIUid
.first
;
400 throw container::NoSuchElementException( "no such xmlns uid!" , static_cast< OWeakObject
* >(this) );
405 void DocumentHandlerImpl::startDocument()
407 m_xRoot
->startDocument( static_cast< xml::input::XNamespaceMapping
* >( this ) );
410 void DocumentHandlerImpl::endDocument()
412 m_xRoot
->endDocument();
415 void DocumentHandlerImpl::startElement(
416 OUString
const & rQElementName
,
417 Reference
< xml::sax::XAttributeList
> const & xAttribs
)
419 Reference
< xml::input::XElement
> xCurrentElement
;
420 Reference
< xml::input::XAttributes
> xAttributes
;
423 ElementEntry elementEntry
;
426 MGuard
aGuard( m_pMutex
);
427 // currently skipping elements and waiting for end tags?
428 if (m_nSkipElements
> 0)
430 ++m_nSkipElements
; // wait for another end tag
431 SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName
<< "\" ...");
435 sal_Int16 nAttribs
= xAttribs
->getLength();
437 // save all namespace ids
438 std::unique_ptr
<sal_Int32
[]> pUids(new sal_Int32
[ nAttribs
]);
439 std::unique_ptr
<OUString
[]> pPrefixes(new OUString
[ nAttribs
]);
440 std::unique_ptr
<OUString
[]> pLocalNames(new OUString
[ nAttribs
]);
441 std::unique_ptr
<OUString
[]> pQNames(new OUString
[ nAttribs
]);
443 // first recognize all xmlns attributes
445 for ( nPos
= 0; nPos
< nAttribs
; ++nPos
)
447 // mark attribute to be collected further
448 // on with attribute's uid and current prefix
449 pUids
[ nPos
] = 0; // modified
451 pQNames
[ nPos
] = xAttribs
->getNameByIndex( nPos
);
452 OUString
const & rQAttributeName
= pQNames
[ nPos
];
454 if (rQAttributeName
.startsWith( g_sXMLNS
))
456 if (rQAttributeName
.getLength() == 5) // set default namespace
458 OUString aDefNamespacePrefix
;
461 xAttribs
->getValueByIndex( nPos
) );
462 elementEntry
.m_prefixes
.push_back( aDefNamespacePrefix
);
463 pUids
[ nPos
] = UID_UNKNOWN
;
464 pPrefixes
[ nPos
] = g_sXMLNS
;
465 pLocalNames
[ nPos
] = aDefNamespacePrefix
;
467 else if (':' == rQAttributeName
[ 5 ]) // set prefix
469 OUString
aPrefix( rQAttributeName
.copy( 6 ) );
470 pushPrefix( aPrefix
, xAttribs
->getValueByIndex( nPos
) );
471 elementEntry
.m_prefixes
.push_back( aPrefix
);
472 pUids
[ nPos
] = UID_UNKNOWN
;
473 pPrefixes
[ nPos
] = g_sXMLNS
;
474 pLocalNames
[ nPos
] = aPrefix
;
476 // else just a name starting with xmlns, but no prefix
480 // now read out attribute prefixes (all namespace prefixes have been set)
481 for ( nPos
= 0; nPos
< nAttribs
; ++nPos
)
483 if (pUids
[ nPos
] >= 0) // no xmlns: attribute
485 OUString
const & rQAttributeName
= pQNames
[ nPos
];
486 SAL_WARN_IF(rQAttributeName
.startsWith( "xmlns:" ), "xmlscript.xmlhelper", "### unexpected xmlns!" );
488 // collect attribute's uid and current prefix
489 sal_Int32 nColonPos
= rQAttributeName
.indexOf( ':' );
492 pPrefixes
[ nPos
] = rQAttributeName
.copy( 0, nColonPos
);
493 pLocalNames
[ nPos
] = rQAttributeName
.copy( nColonPos
+1 );
497 pPrefixes
[ nPos
].clear();
498 pLocalNames
[ nPos
] = rQAttributeName
;
499 // leave local names unmodified
501 pUids
[ nPos
] = getUidByPrefix( pPrefixes
[ nPos
] );
505 // ownership of arrays belongs to attribute list
506 xAttributes
= new ExtendedAttributes(nAttribs
, std::move(pUids
), std::move(pLocalNames
),
507 std::move(pQNames
), xAttribs
);
509 getElementName( rQElementName
, &nUid
, &aLocalName
);
511 // create new child context and append to list
512 if (! m_elements
.empty())
513 xCurrentElement
= m_elements
.back().m_xElement
;
516 if (xCurrentElement
.is())
518 elementEntry
.m_xElement
=
519 xCurrentElement
->startChildElement( nUid
, aLocalName
, xAttributes
);
523 elementEntry
.m_xElement
=
524 m_xRoot
->startRootElement( nUid
, aLocalName
, xAttributes
);
528 MGuard
aGuard( m_pMutex
);
529 if (elementEntry
.m_xElement
.is())
531 m_elements
.push_back( std::move(elementEntry
) );
538 for (sal_Int32 nPos
= elementEntry
.m_prefixes
.size(); nPos
--;)
539 popPrefix(elementEntry
.m_prefixes
[nPos
]);
541 SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName
<< "\" ...");
546 void DocumentHandlerImpl::endElement(
547 OUString
const & rQElementName
)
549 Reference
< xml::input::XElement
> xCurrentElement
;
551 MGuard
aGuard( m_pMutex
);
555 SAL_INFO("xmlscript.xmlhelper", "### received endElement() for \"" << rQElementName
<< "\".");
560 SAL_WARN_IF( m_elements
.empty(), "xmlscript.xmlhelper", "m_elements is empty" );
561 ElementEntry
& rEntry
= m_elements
.back();
562 xCurrentElement
= rEntry
.m_xElement
;
564 #if OSL_DEBUG_LEVEL > 0
567 getElementName( rQElementName
, &nUid
, &aLocalName
);
568 SAL_WARN_IF( xCurrentElement
->getLocalName() != aLocalName
, "xmlscript.xmlhelper", "xCurrentElement->getLocalName() != aLocalName" );
569 SAL_WARN_IF( xCurrentElement
->getUid() != nUid
, "xmlscript.xmlhelper", "xCurrentElement->getUid() != nUid" );
573 for ( sal_Int32 nPos
= rEntry
.m_prefixes
.size(); nPos
--; )
575 popPrefix( rEntry
.m_prefixes
[ nPos
] );
577 m_elements
.pop_back();
579 xCurrentElement
->endElement();
582 void DocumentHandlerImpl::characters( OUString
const & rChars
)
584 Reference
< xml::input::XElement
> xCurrentElement( getCurrentElement() );
585 if (xCurrentElement
.is())
586 xCurrentElement
->characters( rChars
);
589 void DocumentHandlerImpl::ignorableWhitespace(
590 OUString
const & rWhitespaces
)
592 Reference
< xml::input::XElement
> xCurrentElement( getCurrentElement() );
593 if (xCurrentElement
.is())
594 xCurrentElement
->ignorableWhitespace( rWhitespaces
);
597 void DocumentHandlerImpl::processingInstruction(
598 OUString
const & rTarget
, OUString
const & rData
)
600 Reference
< xml::input::XElement
> xCurrentElement( getCurrentElement() );
601 if (xCurrentElement
.is())
602 xCurrentElement
->processingInstruction( rTarget
, rData
);
604 m_xRoot
->processingInstruction( rTarget
, rData
);
607 void DocumentHandlerImpl::setDocumentLocator(
608 Reference
< xml::sax::XLocator
> const & xLocator
)
610 m_xRoot
->setDocumentLocator( xLocator
);
615 sal_Int32
ExtendedAttributes::getIndexByQName( OUString
const & rQName
)
617 for ( sal_Int32 nPos
= m_nAttributes
; nPos
--; )
619 if (m_pQNames
[ nPos
] == rQName
)
627 sal_Int32
ExtendedAttributes::getLength()
629 return m_nAttributes
;
632 OUString
ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex
)
634 if (nIndex
< m_nAttributes
)
635 return m_pLocalNames
[ nIndex
];
640 OUString
ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex
)
642 if (nIndex
< m_nAttributes
)
643 return m_pQNames
[ nIndex
];
648 OUString
ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex
)
650 SAL_WARN_IF( nIndex
>= m_nAttributes
, "xmlscript.xmlhelper", "nIndex is bigger then m_nAttributes");
651 return OUString(); // unsupported
654 OUString
ExtendedAttributes::getValueByIndex( sal_Int32 nIndex
)
656 if (nIndex
< m_nAttributes
)
657 return m_pValues
[ nIndex
];
662 sal_Int32
ExtendedAttributes::getIndexByUidName(
663 sal_Int32 nUid
, OUString
const & rLocalName
)
665 for ( sal_Int32 nPos
= m_nAttributes
; nPos
--; )
667 if (m_pUids
[ nPos
] == nUid
&& m_pLocalNames
[ nPos
] == rLocalName
)
675 sal_Int32
ExtendedAttributes::getUidByIndex( sal_Int32 nIndex
)
677 if (nIndex
< m_nAttributes
)
678 return m_pUids
[ nIndex
];
683 OUString
ExtendedAttributes::getValueByUidName(
684 sal_Int32 nUid
, OUString
const & rLocalName
)
686 for ( sal_Int32 nPos
= m_nAttributes
; nPos
--; )
688 if (m_pUids
[ nPos
] == nUid
&& m_pLocalNames
[ nPos
] == rLocalName
)
690 return m_pValues
[ nPos
];
696 Reference
< xml::sax::XDocumentHandler
> createDocumentHandler(
697 Reference
< xml::input::XRoot
> const & xRoot
)
699 SAL_WARN_IF( !xRoot
.is(), "xmlscript.xmlhelper", "xRoot is NULL" );
702 return new DocumentHandlerImpl(xRoot
, true /* mt use */);
704 return Reference
< xml::sax::XDocumentHandler
>();
707 Reference
< XInterface
> create_DocumentHandlerImpl(
708 SAL_UNUSED_PARAMETER Reference
< XComponentContext
> const & )
710 return static_cast< ::cppu::OWeakObject
* >(
711 new DocumentHandlerImpl(
712 Reference
< xml::input::XRoot
>(), false /* mt use */ ) );
717 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */