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 <com/sun/star/lang/XServiceInfo.hpp>
21 #include <com/sun/star/xml/sax/XParser.hpp>
22 #include <com/sun/star/xml/sax/FastParser.hpp>
23 #include <com/sun/star/lang/XInitialization.hpp>
24 #include <com/sun/star/beans/Pair.hpp>
25 #include <comphelper/attributelist.hxx>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <rtl/ref.hxx>
33 using namespace ::cppu
;
37 using namespace xml::sax
;
42 class NamespaceHandler
: public WeakImplHelper
< XFastNamespaceHandler
>
45 struct NamespaceDefine
48 OUString m_aNamespaceURI
;
50 NamespaceDefine( const OUString
& rPrefix
, const OUString
& rNamespaceURI
) : m_aPrefix( rPrefix
), m_aNamespaceURI( rNamespaceURI
) {}
52 vector
< unique_ptr
< NamespaceDefine
> > m_aNamespaceDefines
;
56 void addNSDeclAttributes( rtl::Reference
< comphelper::AttributeList
> const & rAttrList
);
58 //XFastNamespaceHandler
59 virtual void SAL_CALL
registerNamespace( const OUString
& rNamespacePrefix
, const OUString
& rNamespaceURI
) override
;
60 virtual OUString SAL_CALL
getNamespaceURI( const OUString
& rNamespacePrefix
) override
;
63 NamespaceHandler::NamespaceHandler()
67 void NamespaceHandler::addNSDeclAttributes( rtl::Reference
< comphelper::AttributeList
> const & rAttrList
)
69 for(const auto& aNamespaceDefine
: m_aNamespaceDefines
)
71 OUString
& rPrefix
= aNamespaceDefine
->m_aPrefix
;
72 OUString
& rNamespaceURI
= aNamespaceDefine
->m_aNamespaceURI
;
74 if ( rPrefix
.isEmpty() )
77 sDecl
= "xmlns:" + rPrefix
;
78 rAttrList
->AddAttribute( sDecl
, "CDATA", rNamespaceURI
);
80 m_aNamespaceDefines
.clear();
83 void NamespaceHandler::registerNamespace( const OUString
& rNamespacePrefix
, const OUString
& rNamespaceURI
)
85 m_aNamespaceDefines
.push_back( std::make_unique
<NamespaceDefine
>(
86 rNamespacePrefix
, rNamespaceURI
) );
89 OUString
NamespaceHandler::getNamespaceURI( const OUString
&/* rNamespacePrefix */ )
94 class SaxLegacyFastParser
: public WeakImplHelper
< XInitialization
, XServiceInfo
, XParser
>
97 rtl::Reference
< NamespaceHandler
> m_aNamespaceHandler
;
99 SaxLegacyFastParser();
101 // css::lang::XInitialization:
102 virtual void SAL_CALL
initialize(css::uno::Sequence
<css::uno::Any
> const& rArguments
) override
;
104 // The SAX-Parser-Interface
105 virtual void SAL_CALL
parseStream( const InputSource
& structSource
) override
;
106 virtual void SAL_CALL
setDocumentHandler(const Reference
< XDocumentHandler
> & xHandler
) override
;
107 virtual void SAL_CALL
setErrorHandler(const Reference
< XErrorHandler
> & xHandler
) override
;
108 virtual void SAL_CALL
setDTDHandler(const Reference
< XDTDHandler
> & xHandler
) override
;
109 virtual void SAL_CALL
setEntityResolver(const Reference
< XEntityResolver
>& xResolver
) override
;
110 virtual void SAL_CALL
setLocale( const Locale
&locale
) override
;
113 OUString SAL_CALL
getImplementationName() override
;
114 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
115 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
118 Reference
< XFastParser
> m_xParser
;
119 Reference
< XDocumentHandler
> m_xDocumentHandler
;
120 Reference
< XFastTokenHandler
> m_xTokenHandler
;
125 class CallbackDocumentHandler
: public WeakImplHelper
< XFastDocumentHandler
>
128 Reference
< XDocumentHandler
> m_xDocumentHandler
;
129 Reference
< XFastTokenHandler
> m_xTokenHandler
;
130 rtl::Reference
< NamespaceHandler
> m_aNamespaceHandler
;
131 OUString
getNamespacePrefixFromToken( sal_Int32 nToken
);
132 OUString
getNameFromToken( sal_Int32 nToken
);
134 static const OUString aDefaultNamespace
;
135 static const OUString aNamespaceSeparator
;
138 CallbackDocumentHandler( Reference
< XDocumentHandler
> const & xDocumentHandler
,
139 rtl::Reference
< NamespaceHandler
> const & rNamespaceHandler
,
140 Reference
< XFastTokenHandler
> const & xTokenHandler
);
142 // XFastDocumentHandler
143 virtual void SAL_CALL
startDocument() override
;
144 virtual void SAL_CALL
endDocument() override
;
145 virtual void SAL_CALL
processingInstruction( const OUString
& rTarget
, const OUString
& rData
) override
;
146 virtual void SAL_CALL
setDocumentLocator( const Reference
< XLocator
>& xLocator
) override
;
148 // XFastContextHandler
149 virtual void SAL_CALL
startFastElement( sal_Int32 nElement
, const Reference
< XFastAttributeList
>& Attribs
) override
;
150 virtual void SAL_CALL
startUnknownElement( const OUString
& Namespace
, const OUString
& Name
, const Reference
< XFastAttributeList
>& Attribs
) override
;
151 virtual void SAL_CALL
endFastElement( sal_Int32 Element
) override
;
152 virtual void SAL_CALL
endUnknownElement( const OUString
& Namespace
, const OUString
& Name
) override
;
153 virtual Reference
< XFastContextHandler
> SAL_CALL
createFastChildContext( sal_Int32 nElement
, const Reference
< XFastAttributeList
>& Attribs
) override
;
154 virtual Reference
< XFastContextHandler
> SAL_CALL
createUnknownChildContext( const OUString
& Namespace
, const OUString
& Name
, const Reference
< XFastAttributeList
>& Attribs
) override
;
155 virtual void SAL_CALL
characters( const OUString
& aChars
) override
;
159 const OUString
CallbackDocumentHandler::aDefaultNamespace
= OUString("");
160 const OUString
CallbackDocumentHandler::aNamespaceSeparator
= OUString(":");
162 OUString
CallbackDocumentHandler::getNamespacePrefixFromToken( sal_Int32 nToken
)
164 if ( ( nToken
& 0xffff0000 ) != 0 )
166 Sequence
< sal_Int8
> aSeq
= m_xTokenHandler
->getUTF8Identifier( nToken
& 0xffff0000 );
167 return OUString( reinterpret_cast< const char* >(
168 aSeq
.getConstArray() ), aSeq
.getLength(), RTL_TEXTENCODING_UTF8
);
174 OUString
CallbackDocumentHandler::getNameFromToken( sal_Int32 nToken
)
176 Sequence
< sal_Int8
> aSeq
= m_xTokenHandler
->getUTF8Identifier( nToken
& 0xffff );
177 return OUString( reinterpret_cast< const char* >(
178 aSeq
.getConstArray() ), aSeq
.getLength(), RTL_TEXTENCODING_UTF8
);
181 CallbackDocumentHandler::CallbackDocumentHandler( Reference
< XDocumentHandler
> const & xDocumentHandler
,
182 rtl::Reference
< NamespaceHandler
> const & rNamespaceHandler
,
183 Reference
< XFastTokenHandler
> const & xTokenHandler
)
185 m_xDocumentHandler
.set( xDocumentHandler
);
186 m_aNamespaceHandler
.set( rNamespaceHandler
.get() );
187 m_xTokenHandler
.set( xTokenHandler
);
190 void SAL_CALL
CallbackDocumentHandler::startDocument()
192 if ( m_xDocumentHandler
.is() )
193 m_xDocumentHandler
->startDocument();
196 void SAL_CALL
CallbackDocumentHandler::endDocument()
198 if ( m_xDocumentHandler
.is() )
199 m_xDocumentHandler
->endDocument();
202 void SAL_CALL
CallbackDocumentHandler::processingInstruction( const OUString
& rTarget
, const OUString
& rData
)
204 if ( m_xDocumentHandler
.is() )
205 m_xDocumentHandler
->processingInstruction( rTarget
, rData
);
208 void SAL_CALL
CallbackDocumentHandler::setDocumentLocator( const Reference
< XLocator
>& xLocator
)
210 if ( m_xDocumentHandler
.is() )
211 m_xDocumentHandler
->setDocumentLocator( xLocator
);
214 void SAL_CALL
CallbackDocumentHandler::startFastElement( sal_Int32 nElement
, const Reference
< XFastAttributeList
>& Attribs
)
216 const OUString
& rPrefix
= CallbackDocumentHandler::getNamespacePrefixFromToken( nElement
);
217 const OUString
& rLocalName
= CallbackDocumentHandler::getNameFromToken( nElement
);
218 startUnknownElement( aDefaultNamespace
, (rPrefix
.isEmpty())? rLocalName
: rPrefix
+ aNamespaceSeparator
+ rLocalName
, Attribs
);
221 void SAL_CALL
CallbackDocumentHandler::startUnknownElement( const OUString
& /*Namespace*/, const OUString
& Name
, const Reference
< XFastAttributeList
>& Attribs
)
223 if ( m_xDocumentHandler
.is() )
225 rtl::Reference
< comphelper::AttributeList
> rAttrList
= new comphelper::AttributeList
;
226 m_aNamespaceHandler
->addNSDeclAttributes( rAttrList
);
228 const Sequence
< xml::FastAttribute
> fastAttribs
= Attribs
->getFastAttributes();
229 for (const auto& rAttr
: fastAttribs
)
231 const OUString
& rAttrValue
= rAttr
.Value
;
232 sal_Int32 nToken
= rAttr
.Token
;
233 const OUString
& rAttrNamespacePrefix
= CallbackDocumentHandler::getNamespacePrefixFromToken( nToken
);
234 OUString sAttrName
= CallbackDocumentHandler::getNameFromToken( nToken
);
235 if ( !rAttrNamespacePrefix
.isEmpty() )
236 sAttrName
= rAttrNamespacePrefix
+ aNamespaceSeparator
+ sAttrName
;
238 rAttrList
->AddAttribute( sAttrName
, "CDATA", rAttrValue
);
241 const Sequence
< xml::Attribute
> unknownAttribs
= Attribs
->getUnknownAttributes();
242 for (const auto& rAttr
: unknownAttribs
)
244 const OUString
& rAttrValue
= rAttr
.Value
;
245 const OUString
& rAttrName
= rAttr
.Name
;
247 rAttrList
->AddAttribute( rAttrName
, "CDATA", rAttrValue
);
249 m_xDocumentHandler
->startElement( Name
, rAttrList
.get() );
253 void SAL_CALL
CallbackDocumentHandler::endFastElement( sal_Int32 nElement
)
255 const OUString
& rPrefix
= CallbackDocumentHandler::getNamespacePrefixFromToken( nElement
);
256 const OUString
& rLocalName
= CallbackDocumentHandler::getNameFromToken( nElement
);
257 endUnknownElement( aDefaultNamespace
, (rPrefix
.isEmpty())? rLocalName
: rPrefix
+ aNamespaceSeparator
+ rLocalName
);
261 void SAL_CALL
CallbackDocumentHandler::endUnknownElement( const OUString
& /*Namespace*/, const OUString
& Name
)
263 if ( m_xDocumentHandler
.is() )
265 m_xDocumentHandler
->endElement( Name
);
269 Reference
< XFastContextHandler
> SAL_CALL
CallbackDocumentHandler::createFastChildContext( sal_Int32
/* nElement */, const Reference
< XFastAttributeList
>&/* Attribs */ )
275 Reference
< XFastContextHandler
> SAL_CALL
CallbackDocumentHandler::createUnknownChildContext( const OUString
&/* Namespace */, const OUString
&/* Name */, const Reference
< XFastAttributeList
>&/* Attribs */ )
280 void SAL_CALL
CallbackDocumentHandler::characters( const OUString
& aChars
)
282 if ( m_xDocumentHandler
.is() )
283 m_xDocumentHandler
->characters( aChars
);
286 SaxLegacyFastParser::SaxLegacyFastParser( ) : m_aNamespaceHandler( new NamespaceHandler
)
288 m_xParser
= FastParser::create(
289 ::comphelper::getProcessComponentContext() );
290 m_xParser
->setNamespaceHandler( m_aNamespaceHandler
.get() );
293 void SAL_CALL
SaxLegacyFastParser::initialize(Sequence
< Any
> const& rArguments
)
295 if (rArguments
.hasElements())
297 Reference
< XFastTokenHandler
> xTokenHandler
;
299 if ( ( rArguments
[0] >>= xTokenHandler
) && xTokenHandler
.is() )
301 m_xTokenHandler
.set( xTokenHandler
);
303 else if ( ( rArguments
[0] >>= str
) && "registerNamespaces" == str
)
305 css::beans::Pair
< OUString
, sal_Int32
> rPair
;
306 for (sal_Int32 i
= 1; i
< rArguments
.getLength(); i
++ )
308 rArguments
[i
] >>= rPair
;
309 m_xParser
->registerNamespace( rPair
.First
, rPair
.Second
);
314 uno::Reference
<lang::XInitialization
> const xInit(m_xParser
,
315 uno::UNO_QUERY_THROW
);
316 xInit
->initialize( rArguments
);
321 void SaxLegacyFastParser::parseStream( const InputSource
& structSource
)
323 m_xParser
->setFastDocumentHandler( new CallbackDocumentHandler( m_xDocumentHandler
.get(),
324 m_aNamespaceHandler
.get(), m_xTokenHandler
.get() ) );
325 m_xParser
->setTokenHandler( m_xTokenHandler
);
326 m_xParser
->parseStream( structSource
);
329 void SaxLegacyFastParser::setDocumentHandler( const Reference
< XDocumentHandler
> & xHandler
)
331 m_xDocumentHandler
= xHandler
;
334 void SaxLegacyFastParser::setErrorHandler( const Reference
< XErrorHandler
> & xHandler
)
336 m_xParser
->setErrorHandler( xHandler
);
339 void SaxLegacyFastParser::setDTDHandler( const Reference
< XDTDHandler
> &/* xHandler */ )
344 void SaxLegacyFastParser::setEntityResolver( const Reference
< XEntityResolver
>& xResolver
)
346 m_xParser
->setEntityResolver( xResolver
);
349 void SaxLegacyFastParser::setLocale( const Locale
&locale
)
351 m_xParser
->setLocale( locale
);
354 OUString
SaxLegacyFastParser::getImplementationName()
356 return "com.sun.star.comp.extensions.xml.sax.LegacyFastParser";
359 sal_Bool
SaxLegacyFastParser::supportsService(const OUString
& ServiceName
)
361 return cppu::supportsService(this, ServiceName
);
364 Sequence
< OUString
> SaxLegacyFastParser::getSupportedServiceNames()
366 Sequence
<OUString
> seq
{ "com.sun.star.xml.sax.LegacyFastParser" };
372 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
373 com_sun_star_comp_extensions_xml_sax_LegacyFastParser_get_implementation(
374 css::uno::XComponentContext
*,
375 css::uno::Sequence
<css::uno::Any
> const &)
377 return cppu::acquire(new SaxLegacyFastParser
);
380 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */