build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / unoxml / source / dom / saxbuilder.cxx
blob786f3700b9f06dcb4015794a07b66b091961cbd4
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 .
19 #ifdef _MSC_VER
20 #pragma warning(disable : 4701)
21 #endif
23 #include "saxbuilder.hxx"
25 #include <com/sun/star/xml/dom/DocumentBuilder.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <cppuhelper/supportsservice.hxx>
29 using namespace css::lang;
30 using namespace css::uno;
31 using namespace css::xml::dom;
32 using namespace css::xml::sax;
34 namespace DOM
36 Reference< XInterface > CSAXDocumentBuilder::_getInstance(const Reference< XMultiServiceFactory >& rSMgr)
38 return static_cast< XSAXDocumentBuilder* >(new CSAXDocumentBuilder(rSMgr));
41 const char* CSAXDocumentBuilder::aImplementationName = "com.sun.star.comp.xml.dom.SAXDocumentBuilder";
42 const char* CSAXDocumentBuilder::aSupportedServiceNames[] = {
43 "com.sun.star.xml.dom.SAXDocumentBuilder",
44 nullptr
47 CSAXDocumentBuilder::CSAXDocumentBuilder(const Reference< XMultiServiceFactory >& mgr)
48 : m_aServiceManager(mgr)
49 , m_aState( SAXDocumentBuilderState_READY)
52 OUString CSAXDocumentBuilder::_getImplementationName()
54 return OUString::createFromAscii(aImplementationName);
56 Sequence<OUString> CSAXDocumentBuilder::_getSupportedServiceNames()
58 Sequence<OUString> aSequence;
59 for (int i=0; aSupportedServiceNames[i]!=nullptr; i++) {
60 aSequence.realloc(i+1);
61 aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i]));
63 return aSequence;
66 Sequence< OUString > SAL_CALL CSAXDocumentBuilder::getSupportedServiceNames()
67 throw (RuntimeException, std::exception)
69 return CSAXDocumentBuilder::_getSupportedServiceNames();
72 OUString SAL_CALL CSAXDocumentBuilder::getImplementationName()
73 throw (RuntimeException, std::exception)
75 return CSAXDocumentBuilder::_getImplementationName();
78 sal_Bool SAL_CALL CSAXDocumentBuilder::supportsService(const OUString& aServiceName)
79 throw (RuntimeException, std::exception)
81 return cppu::supportsService(this, aServiceName);
84 SAXDocumentBuilderState SAL_CALL CSAXDocumentBuilder::getState()
85 throw (RuntimeException, std::exception)
87 ::osl::MutexGuard g(m_Mutex);
89 return m_aState;
92 void SAL_CALL CSAXDocumentBuilder::reset()
93 throw (RuntimeException, std::exception)
95 ::osl::MutexGuard g(m_Mutex);
97 m_aDocument.clear();
98 m_aFragment.clear();
99 while (!m_aNodeStack.empty()) m_aNodeStack.pop();
100 while (!m_aNSStack.empty()) m_aNSStack.pop();
101 m_aState = SAXDocumentBuilderState_READY;
104 Reference< XDocument > SAL_CALL CSAXDocumentBuilder::getDocument()
105 throw (RuntimeException, std::exception)
107 ::osl::MutexGuard g(m_Mutex);
109 if (m_aState != SAXDocumentBuilderState_DOCUMENT_FINISHED)
110 throw RuntimeException();
112 return m_aDocument;
115 Reference< XDocumentFragment > SAL_CALL CSAXDocumentBuilder::getDocumentFragment()
116 throw (RuntimeException, std::exception)
118 ::osl::MutexGuard g(m_Mutex);
120 if (m_aState != SAXDocumentBuilderState_FRAGMENT_FINISHED)
121 throw RuntimeException();
122 return m_aFragment;
125 void SAL_CALL CSAXDocumentBuilder::startDocumentFragment(const Reference< XDocument >& ownerDoc)
126 throw (RuntimeException, std::exception)
128 ::osl::MutexGuard g(m_Mutex);
130 // start a new document fragment and push it onto the stack
131 // we have to be in a clean state to do this
132 if (m_aState != SAXDocumentBuilderState_READY)
133 throw RuntimeException();
135 m_aDocument = ownerDoc;
136 Reference< XDocumentFragment > aFragment = m_aDocument->createDocumentFragment();
137 m_aNodeStack.push(aFragment);
138 m_aFragment = aFragment;
139 m_aState = SAXDocumentBuilderState_BUILDING_FRAGMENT;
142 void SAL_CALL CSAXDocumentBuilder::endDocumentFragment()
143 throw (RuntimeException, std::exception)
145 ::osl::MutexGuard g(m_Mutex);
147 // there should only be the document left on the node stack
148 if (m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
149 throw RuntimeException();
151 Reference< XNode > aNode = m_aNodeStack.top();
152 if ( aNode->getNodeType() != NodeType_DOCUMENT_FRAGMENT_NODE)
153 throw RuntimeException();
154 m_aNodeStack.pop();
155 m_aState = SAXDocumentBuilderState_FRAGMENT_FINISHED;
158 // document handler
160 void SAL_CALL CSAXDocumentBuilder::startDocument() throw (RuntimeException, SAXException, std::exception)
162 ::osl::MutexGuard g(m_Mutex);
164 // start a new document and push it onto the stack
165 // we have to be in a clean state to do this
166 if (m_aState != SAXDocumentBuilderState_READY)
167 throw SAXException();
169 Reference< XDocumentBuilder > aBuilder(DocumentBuilder::create(comphelper::getComponentContext(m_aServiceManager)));
170 Reference< XDocument > aDocument = aBuilder->newDocument();
171 m_aNodeStack.push(aDocument);
172 m_aDocument = aDocument;
173 m_aState = SAXDocumentBuilderState_BUILDING_DOCUMENT;
176 void SAL_CALL CSAXDocumentBuilder::endDocument() throw (RuntimeException, SAXException, std::exception)
178 ::osl::MutexGuard g(m_Mutex);
180 // there should only be the document left on the node stack
181 if (m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT)
182 throw SAXException();
184 Reference< XNode > aNode = m_aNodeStack.top();
185 if ( aNode->getNodeType() != NodeType_DOCUMENT_NODE)
186 throw SAXException();
187 m_aNodeStack.pop();
188 m_aState = SAXDocumentBuilderState_DOCUMENT_FINISHED;
191 void SAL_CALL CSAXDocumentBuilder::startElement(const OUString& aName, const Reference< XAttributeList>& attribs)
192 throw (RuntimeException, SAXException, std::exception)
194 ::osl::MutexGuard g(m_Mutex);
196 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
197 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
199 throw SAXException();
202 // start with mappings in effect for last level
203 NSMap aNSMap;
204 if (!m_aNSStack.empty())
205 aNSMap = NSMap(m_aNSStack.top());
207 // handle xmlns: attributes and add to mappings
208 OUString attr_qname;
209 OUString attr_value;
210 OUString newprefix;
211 AttrMap aAttrMap;
212 sal_Int32 idx=-1;
213 sal_Int16 nAttributes = attribs->getLength();
214 for (sal_Int16 i=0; i<nAttributes; i++)
216 attr_qname = attribs->getNameByIndex(i);
217 attr_value = attribs->getValueByIndex(i);
218 // new prefix mapping
219 if (attr_qname.startsWith("xmlns:"))
221 newprefix = attr_qname.copy(attr_qname.indexOf(':')+1);
222 aNSMap.insert(NSMap::value_type(newprefix, attr_value));
224 else if ( attr_qname == "xmlns" )
226 // new default prefix
227 aNSMap.insert(NSMap::value_type(OUString(), attr_value));
229 else
231 aAttrMap.insert(AttrMap::value_type(attr_qname, attr_value));
235 // does the element have a prefix?
236 OUString aPrefix;
237 OUString aURI;
238 Reference< XElement > aElement;
239 idx = aName.indexOf(':');
240 if (idx != -1)
242 aPrefix = aName.copy(0, idx);
244 else
245 aPrefix.clear();
247 NSMap::const_iterator result = aNSMap.find(aPrefix);
248 if ( result != aNSMap.end())
250 // found a URI for prefix
251 // qualified name
252 aElement = m_aDocument->createElementNS( result->second, aName);
254 else
256 // no URI for prefix
257 aElement = m_aDocument->createElement(aName);
259 aElement.set( m_aNodeStack.top()->appendChild(aElement), UNO_QUERY);
260 m_aNodeStack.push(aElement);
262 // set non xmlns attributes
263 aPrefix.clear();
264 aURI.clear();
265 AttrMap::const_iterator a = aAttrMap.begin();
266 while (a != aAttrMap.end())
268 attr_qname = a->first;
269 attr_value = a->second;
270 idx = attr_qname.indexOf(':');
271 if (idx != -1)
272 aPrefix = attr_qname.copy(0, idx);
273 else
274 aPrefix.clear();
276 result = aNSMap.find(aPrefix);
277 if (result != aNSMap.end())
279 // set attribute with namespace
280 aElement->setAttributeNS(result->second, attr_qname, attr_value);
282 else
284 // set attribute without namespace
285 aElement->setAttribute(attr_qname, attr_value);
287 ++a;
289 m_aNSStack.push(aNSMap);
292 void SAL_CALL CSAXDocumentBuilder::endElement(const OUString& aName)
293 throw (RuntimeException, SAXException, std::exception)
295 ::osl::MutexGuard g(m_Mutex);
297 // pop the current element from the stack
298 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
299 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
300 throw SAXException();
302 Reference< XNode > aNode(m_aNodeStack.top());
303 if (aNode->getNodeType() != NodeType_ELEMENT_NODE)
304 throw SAXException();
306 Reference< XElement > aElement(aNode, UNO_QUERY);
307 OUString aRefName;
308 OUString aPrefix = aElement->getPrefix();
309 if (!aPrefix.isEmpty())
310 aRefName = aPrefix + ":" + aElement->getTagName();
311 else
312 aRefName = aElement->getTagName();
313 if (aRefName != aName) // consistency check
314 throw SAXException();
316 // pop it
317 m_aNodeStack.pop();
318 m_aNSStack.pop();
321 void SAL_CALL CSAXDocumentBuilder::characters(const OUString& aChars)
322 throw (RuntimeException, SAXException, std::exception)
324 ::osl::MutexGuard g(m_Mutex);
326 // append text node to the current top element
327 if (m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
328 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
329 throw SAXException();
331 Reference< XText > aText = m_aDocument->createTextNode(aChars);
332 m_aNodeStack.top()->appendChild(aText);
335 void SAL_CALL CSAXDocumentBuilder::ignorableWhitespace(const OUString& )
336 throw (RuntimeException, SAXException, std::exception)
338 ::osl::MutexGuard g(m_Mutex);
340 // ignore ignorable whitespace
341 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
342 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
343 throw SAXException();
346 void SAL_CALL CSAXDocumentBuilder::processingInstruction(const OUString& aTarget, const OUString& aData)
347 throw (RuntimeException, SAXException, std::exception)
349 ::osl::MutexGuard g(m_Mutex);
351 // append PI node to the current top
352 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
353 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
354 throw SAXException();
356 Reference< XProcessingInstruction > aInstruction = m_aDocument->createProcessingInstruction(
357 aTarget, aData);
358 m_aNodeStack.top()->appendChild(aInstruction);
361 void SAL_CALL CSAXDocumentBuilder::setDocumentLocator(const Reference< XLocator >& aLocator)
362 throw (RuntimeException, SAXException, std::exception)
364 ::osl::MutexGuard g(m_Mutex);
366 // set the document locator...
367 m_aLocator = aLocator;
371 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */