1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <sal/config.h>
21
22 #include <xml_import.hxx>
23
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>
32
33 #include <memory>
34 #include <unordered_map>
35 #include <vector>
36
37 using namespace ::osl;
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::uno;
40
41 namespace xmlscript
42 {
43
44 const sal_Int32 UID_UNKNOWN = -1;
45
46 typedef std::unordered_map< OUString, sal_Int32 > t_OUString2LongMap;
47
48 namespace {
49
50 struct PrefixEntry
51 {
52 ::std::vector< sal_Int32 > m_Uids;
53
PrefixEntryxmlscript::__anonbb827f270111::PrefixEntry54 PrefixEntry()
55 { m_Uids.reserve( 4 ); }
56 };
57
58 }
59
60 typedef std::unordered_map<
61 OUString, std::unique_ptr<PrefixEntry> > t_OUString2PrefixMap;
62
63 namespace {
64
65 struct ElementEntry
66 {
67 Reference< xml::input::XElement > m_xElement;
68 ::std::vector< OUString > m_prefixes;
69
ElementEntryxmlscript::__anonbb827f270211::ElementEntry70 ElementEntry()
71 { m_prefixes.reserve( 2 ); }
72 };
73
74 class ExtendedAttributes;
75
76 class MGuard
77 {
78 Mutex * m_pMutex;
79 public:
MGuard(std::unique_ptr<Mutex> const & pMutex)80 explicit MGuard( std::unique_ptr<Mutex> const & pMutex )
81 : m_pMutex( pMutex.get() )
82 { if (m_pMutex) m_pMutex->acquire(); }
~MGuard()83 ~MGuard() noexcept
84 { if (m_pMutex) m_pMutex->release(); }
85 };
86
87 class DocumentHandlerImpl :
88 public ::cppu::WeakImplHelper< xml::sax::XDocumentHandler,
89 xml::input::XNamespaceMapping,
90 lang::XInitialization,
91 css::lang::XServiceInfo >
92 {
93 friend class ExtendedAttributes;
94
95 Reference< xml::input::XRoot > m_xRoot;
96
97 t_OUString2LongMap m_URI2Uid;
98 sal_Int32 m_uid_count;
99
100 sal_Int32 m_nLastURI_lookup;
101 OUString m_aLastURI_lookup;
102
103 t_OUString2PrefixMap m_prefixes;
104 sal_Int32 m_nLastPrefix_lookup;
105 OUString m_aLastPrefix_lookup;
106
107 std::vector< ElementEntry > m_elements;
108 sal_Int32 m_nSkipElements;
109
110 std::unique_ptr<Mutex> m_pMutex;
111
112 inline Reference< xml::input::XElement > getCurrentElement() const;
113
114 inline sal_Int32 getUidByURI( OUString const & rURI );
115 inline sal_Int32 getUidByPrefix( OUString const & rPrefix );
116
117 inline void pushPrefix(
118 OUString const & rPrefix, OUString const & rURI );
119 inline void popPrefix( OUString const & rPrefix );
120
121 inline void getElementName(
122 OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName );
123
124 public:
125 DocumentHandlerImpl(
126 Reference< xml::input::XRoot > const & xRoot,
127 bool bSingleThreadedUse );
128
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;
134
135 // XInitialization
136 virtual void SAL_CALL initialize(
137 Sequence< Any > const & arguments ) override;
138
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;
155
156 // XNamespaceMapping
157 virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri ) override;
158 virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid ) override;
159 };
160
161 }
162
163 constexpr OUStringLiteral g_sXMLNS_PREFIX_UNKNOWN( u"<<< unknown prefix >>>" );
164 constexpr OUStringLiteral g_sXMLNS( u"xmlns" );
165
166
DocumentHandlerImpl(Reference<xml::input::XRoot> const & xRoot,bool bSingleThreadedUse)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 )
177 {
178 m_elements.reserve( 10 );
179
180 if (! bSingleThreadedUse)
181 m_pMutex.reset(new Mutex);
182 }
183
184 inline Reference< xml::input::XElement >
getCurrentElement() const185 DocumentHandlerImpl::getCurrentElement() const
186 {
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;
192 }
193
getUidByURI(OUString const & rURI)194 inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI )
195 {
196 MGuard guard( m_pMutex );
197 if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI)
198 {
199 t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) );
200 if (iFind != m_URI2Uid.end()) // id found
201 {
202 m_nLastURI_lookup = iFind->second;
203 m_aLastURI_lookup = rURI;
204 }
205 else
206 {
207 m_nLastURI_lookup = m_uid_count;
208 ++m_uid_count;
209 m_URI2Uid[ rURI ] = m_nLastURI_lookup;
210 m_aLastURI_lookup = rURI;
211 }
212 }
213 return m_nLastURI_lookup;
214 }
215
getUidByPrefix(OUString const & rPrefix)216 inline sal_Int32 DocumentHandlerImpl::getUidByPrefix(
217 OUString const & rPrefix )
218 {
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)
222 {
223 t_OUString2PrefixMap::const_iterator iFind(
224 m_prefixes.find( rPrefix ) );
225 if (iFind != m_prefixes.end())
226 {
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;
231 }
232 else
233 {
234 m_nLastPrefix_lookup = UID_UNKNOWN;
235 m_aLastPrefix_lookup = g_sXMLNS_PREFIX_UNKNOWN;
236 }
237 }
238 return m_nLastPrefix_lookup;
239 }
240
pushPrefix(OUString const & rPrefix,OUString const & rURI)241 inline void DocumentHandlerImpl::pushPrefix(
242 OUString const & rPrefix, OUString const & rURI )
243 {
244 // lookup id for URI
245 sal_Int32 nUid = getUidByURI( rURI );
246
247 // mark prefix with id
248 t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) );
249 if (iFind == m_prefixes.end()) // unused prefix
250 {
251 PrefixEntry * pEntry = new PrefixEntry();
252 pEntry->m_Uids.push_back( nUid ); // latest id for prefix
253 m_prefixes[rPrefix].reset(pEntry);
254 }
255 else
256 {
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);
260 }
261
262 m_aLastPrefix_lookup = rPrefix;
263 m_nLastPrefix_lookup = nUid;
264 }
265
popPrefix(OUString const & rPrefix)266 inline void DocumentHandlerImpl::popPrefix(
267 OUString const & rPrefix )
268 {
269 t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) );
270 if (iFind != m_prefixes.end()) // unused prefix
271 {
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
275 {
276 m_prefixes.erase(iFind);
277 }
278 }
279
280 m_nLastPrefix_lookup = UID_UNKNOWN;
281 m_aLastPrefix_lookup = g_sXMLNS_PREFIX_UNKNOWN;
282 }
283
getElementName(OUString const & rQName,sal_Int32 * pUid,OUString * pLocalName)284 inline void DocumentHandlerImpl::getElementName(
285 OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName )
286 {
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() );
291 }
292
293 namespace {
294
295 class ExtendedAttributes :
296 public ::cppu::WeakImplHelper< xml::input::XAttributes >
297 {
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;
303
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 );
311
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;
330 };
331
332 }
333
ExtendedAttributes(sal_Int32 nAttributes,std::unique_ptr<sal_Int32[]> pUids,std::unique_ptr<OUString[]> pLocalNames,std::unique_ptr<OUString[]> pQNames,Reference<xml::sax::XAttributeList> const & xAttributeList)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 ] )
344 {
345 for ( sal_Int32 nPos = 0; nPos < nAttributes; ++nPos )
346 {
347 m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos );
348 }
349 }
350
351 // XServiceInfo
352
getImplementationName()353 OUString DocumentHandlerImpl::getImplementationName()
354 {
355 return "com.sun.star.comp.xml.input.SaxDocumentHandler";
356 }
357
supportsService(OUString const & servicename)358 sal_Bool DocumentHandlerImpl::supportsService( OUString const & servicename )
359 {
360 return cppu::supportsService(this, servicename);
361 }
362
getSupportedServiceNames()363 Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames()
364 {
365 return { "com.sun.star.xml.input.SaxDocumentHandler" };
366 }
367
368 // XInitialization
369
initialize(Sequence<Any> const & arguments)370 void DocumentHandlerImpl::initialize(
371 Sequence< Any > const & arguments )
372 {
373 MGuard guard( m_pMutex );
374 Reference< xml::input::XRoot > xRoot;
375 if (arguments.getLength() != 1 ||
376 !(arguments[ 0 ] >>= xRoot) ||
377 !xRoot.is())
378 {
379 throw RuntimeException( "missing root instance!" );
380 }
381 m_xRoot = xRoot;
382 }
383
384 // XNamespaceMapping
385
getUidByUri(OUString const & Uri)386 sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri )
387 {
388 sal_Int32 uid = getUidByURI( Uri );
389 SAL_WARN_IF( uid == UID_UNKNOWN, "xmlscript.xmlhelper", "uid UNKNOWN");
390 return uid;
391 }
392
getUriByUid(sal_Int32 Uid)393 OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid )
394 {
395 MGuard guard( m_pMutex );
396 for (const auto& rURIUid : m_URI2Uid)
397 {
398 if (rURIUid.second == Uid)
399 return rURIUid.first;
400 }
401 throw container::NoSuchElementException( "no such xmlns uid!" , static_cast< OWeakObject * >(this) );
402 }
403
404 // XDocumentHandler
405
startDocument()406 void DocumentHandlerImpl::startDocument()
407 {
408 m_xRoot->startDocument( static_cast< xml::input::XNamespaceMapping * >( this ) );
409 }
410
endDocument()411 void DocumentHandlerImpl::endDocument()
412 {
413 m_xRoot->endDocument();
414 }
415
startElement(OUString const & rQElementName,Reference<xml::sax::XAttributeList> const & xAttribs)416 void DocumentHandlerImpl::startElement(
417 OUString const & rQElementName,
418 Reference< xml::sax::XAttributeList > const & xAttribs )
419 {
420 Reference< xml::input::XElement > xCurrentElement;
421 Reference< xml::input::XAttributes > xAttributes;
422 sal_Int32 nUid;
423 OUString aLocalName;
424 ElementEntry elementEntry;
425
426 { // guard start:
427 MGuard aGuard( m_pMutex );
428 // currently skipping elements and waiting for end tags?
429 if (m_nSkipElements > 0)
430 {
431 ++m_nSkipElements; // wait for another end tag
432 SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName << "\" ...");
433 return;
434 }
435
436 sal_Int16 nAttribs = xAttribs->getLength();
437
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 ]);
443
444 // first recognize all xmlns attributes
445 sal_Int16 nPos;
446 for ( nPos = 0; nPos < nAttribs; ++nPos )
447 {
448 // mark attribute to be collected further
449 // on with attribute's uid and current prefix
450 pUids[ nPos ] = 0; // modified
451
452 pQNames[ nPos ] = xAttribs->getNameByIndex( nPos );
453 OUString const & rQAttributeName = pQNames[ nPos ];
454
455 if (rQAttributeName.startsWith( g_sXMLNS ))
456 {
457 if (rQAttributeName.getLength() == 5) // set default namespace
458 {
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;
467 }
468 else if (':' == rQAttributeName[ 5 ]) // set prefix
469 {
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;
476 }
477 // else just a name starting with xmlns, but no prefix
478 }
479 }
480
481 // now read out attribute prefixes (all namespace prefixes have been set)
482 for ( nPos = 0; nPos < nAttribs; ++nPos )
483 {
484 if (pUids[ nPos ] >= 0) // no xmlns: attribute
485 {
486 OUString const & rQAttributeName = pQNames[ nPos ];
487 SAL_WARN_IF(rQAttributeName.startsWith( "xmlns:" ), "xmlscript.xmlhelper", "### unexpected xmlns!" );
488
489 // collect attribute's uid and current prefix
490 sal_Int32 nColonPos = rQAttributeName.indexOf( ':' );
491 if (nColonPos >= 0)
492 {
493 pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos );
494 pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 );
495 }
496 else
497 {
498 pPrefixes[ nPos ].clear();
499 pLocalNames[ nPos ] = rQAttributeName;
500 // leave local names unmodified
501 }
502 pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] );
503 }
504 }
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);
509
510 getElementName( rQElementName, &nUid, &aLocalName );
511
512 // create new child context and append to list
513 if (! m_elements.empty())
514 xCurrentElement = m_elements.back().m_xElement;
515 } // :guard end
516
517 if (xCurrentElement.is())
518 {
519 elementEntry.m_xElement =
520 xCurrentElement->startChildElement( nUid, aLocalName, xAttributes );
521 }
522 else
523 {
524 elementEntry.m_xElement =
525 m_xRoot->startRootElement( nUid, aLocalName, xAttributes );
526 }
527
528 {
529 MGuard aGuard( m_pMutex );
530 if (elementEntry.m_xElement.is())
531 {
532 m_elements.push_back( std::move(elementEntry) );
533 }
534 else
535 {
536 ++m_nSkipElements;
537
538 // pop prefixes
539 for (sal_Int32 nPos = elementEntry.m_prefixes.size(); nPos--;)
540 popPrefix(elementEntry.m_prefixes[nPos]);
541
542 SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName << "\" ...");
543 }
544 }
545 }
546
endElement(OUString const & rQElementName)547 void DocumentHandlerImpl::endElement(
548 OUString const & rQElementName )
549 {
550 Reference< xml::input::XElement > xCurrentElement;
551 {
552 MGuard aGuard( m_pMutex );
553 if (m_nSkipElements)
554 {
555 --m_nSkipElements;
556 SAL_INFO("xmlscript.xmlhelper", "### received endElement() for \"" << rQElementName << "\".");
557 return;
558 }
559
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;
564
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
572
573 // pop prefixes
574 for ( sal_Int32 nPos = rEntry.m_prefixes.size(); nPos--; )
575 {
576 popPrefix( rEntry.m_prefixes[ nPos ] );
577 }
578 m_elements.pop_back();
579 }
580 xCurrentElement->endElement();
581 }
582
characters(OUString const & rChars)583 void DocumentHandlerImpl::characters( OUString const & rChars )
584 {
585 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
586 if (xCurrentElement.is())
587 xCurrentElement->characters( rChars );
588 }
589
ignorableWhitespace(OUString const & rWhitespaces)590 void DocumentHandlerImpl::ignorableWhitespace(
591 OUString const & rWhitespaces )
592 {
593 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
594 if (xCurrentElement.is())
595 xCurrentElement->ignorableWhitespace( rWhitespaces );
596 }
597
processingInstruction(OUString const & rTarget,OUString const & rData)598 void DocumentHandlerImpl::processingInstruction(
599 OUString const & rTarget, OUString const & rData )
600 {
601 Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
602 if (xCurrentElement.is())
603 xCurrentElement->processingInstruction( rTarget, rData );
604 else
605 m_xRoot->processingInstruction( rTarget, rData );
606 }
607
setDocumentLocator(Reference<xml::sax::XLocator> const & xLocator)608 void DocumentHandlerImpl::setDocumentLocator(
609 Reference< xml::sax::XLocator > const & xLocator )
610 {
611 m_xRoot->setDocumentLocator( xLocator );
612 }
613
614 // XAttributes
615
getIndexByQName(OUString const & rQName)616 sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName )
617 {
618 for ( sal_Int32 nPos = m_nAttributes; nPos--; )
619 {
620 if (m_pQNames[ nPos ] == rQName)
621 {
622 return nPos;
623 }
624 }
625 return -1;
626 }
627
getLength()628 sal_Int32 ExtendedAttributes::getLength()
629 {
630 return m_nAttributes;
631 }
632
getLocalNameByIndex(sal_Int32 nIndex)633 OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex )
634 {
635 if (nIndex < m_nAttributes)
636 return m_pLocalNames[ nIndex ];
637 else
638 return OUString();
639 }
640
getQNameByIndex(sal_Int32 nIndex)641 OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex )
642 {
643 if (nIndex < m_nAttributes)
644 return m_pQNames[ nIndex ];
645 else
646 return OUString();
647 }
648
getTypeByIndex(sal_Int32 nIndex)649 OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex )
650 {
651 SAL_WARN_IF( nIndex >= m_nAttributes , "xmlscript.xmlhelper", "nIndex is bigger then m_nAttributes");
652 return OUString(); // unsupported
653 }
654
getValueByIndex(sal_Int32 nIndex)655 OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex )
656 {
657 if (nIndex < m_nAttributes)
658 return m_pValues[ nIndex ];
659 else
660 return OUString();
661 }
662
getIndexByUidName(sal_Int32 nUid,OUString const & rLocalName)663 sal_Int32 ExtendedAttributes::getIndexByUidName(
664 sal_Int32 nUid, OUString const & rLocalName )
665 {
666 for ( sal_Int32 nPos = m_nAttributes; nPos--; )
667 {
668 if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
669 {
670 return nPos;
671 }
672 }
673 return -1;
674 }
675
getUidByIndex(sal_Int32 nIndex)676 sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex )
677 {
678 if (nIndex < m_nAttributes)
679 return m_pUids[ nIndex ];
680 else
681 return -1;
682 }
683
getValueByUidName(sal_Int32 nUid,OUString const & rLocalName)684 OUString ExtendedAttributes::getValueByUidName(
685 sal_Int32 nUid, OUString const & rLocalName )
686 {
687 for ( sal_Int32 nPos = m_nAttributes; nPos--; )
688 {
689 if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
690 {
691 return m_pValues[ nPos ];
692 }
693 }
694 return OUString();
695 }
696
createDocumentHandler(Reference<xml::input::XRoot> const & xRoot)697 Reference< xml::sax::XDocumentHandler > createDocumentHandler(
698 Reference< xml::input::XRoot > const & xRoot )
699 {
700 SAL_WARN_IF( !xRoot.is(), "xmlscript.xmlhelper", "xRoot is NULL" );
701 if (xRoot.is())
702 {
703 return new DocumentHandlerImpl(xRoot, true /* mt use */);
704 }
705 return Reference< xml::sax::XDocumentHandler >();
706 }
707
708 }
709
710 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
com_sun_star_comp_xml_input_SaxDocumentHandler_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)711 com_sun_star_comp_xml_input_SaxDocumentHandler_get_implementation(
712 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const& )
713 {
714 return cppu::acquire(new xmlscript::DocumentHandlerImpl({}, false /* mt use */));
715 }
716
717 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
718