bump product version to 4.1.6.2
[LibreOffice.git] / unoxml / source / dom / saxbuilder.cxx
blob459cd6bb9ee970751eb56a6560177ce10e68585a
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>
29 namespace DOM
31 Reference< XInterface > CSAXDocumentBuilder::_getInstance(const Reference< XMultiServiceFactory >& rSMgr)
33 return static_cast< XSAXDocumentBuilder* >(new CSAXDocumentBuilder(rSMgr));
36 const char* CSAXDocumentBuilder::aImplementationName = "com.sun.star.comp.xml.dom.SAXDocumentBuilder";
37 const char* CSAXDocumentBuilder::aSupportedServiceNames[] = {
38 "com.sun.star.xml.dom.SAXDocumentBuilder",
39 NULL
42 CSAXDocumentBuilder::CSAXDocumentBuilder(const Reference< XMultiServiceFactory >& mgr)
43 : m_aServiceManager(mgr)
44 , m_aState( SAXDocumentBuilderState_READY)
47 OUString CSAXDocumentBuilder::_getImplementationName()
49 return OUString::createFromAscii(aImplementationName);
51 Sequence<OUString> CSAXDocumentBuilder::_getSupportedServiceNames()
53 Sequence<OUString> aSequence;
54 for (int i=0; aSupportedServiceNames[i]!=NULL; i++) {
55 aSequence.realloc(i+1);
56 aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i]));
58 return aSequence;
61 Sequence< OUString > SAL_CALL CSAXDocumentBuilder::getSupportedServiceNames()
62 throw (RuntimeException)
64 return CSAXDocumentBuilder::_getSupportedServiceNames();
67 OUString SAL_CALL CSAXDocumentBuilder::getImplementationName()
68 throw (RuntimeException)
70 return CSAXDocumentBuilder::_getImplementationName();
73 sal_Bool SAL_CALL CSAXDocumentBuilder::supportsService(const OUString& aServiceName)
74 throw (RuntimeException)
76 Sequence< OUString > supported = CSAXDocumentBuilder::_getSupportedServiceNames();
77 for (sal_Int32 i=0; i<supported.getLength(); i++)
79 if (supported[i] == aServiceName) return sal_True;
81 return sal_False;
85 SAXDocumentBuilderState SAL_CALL CSAXDocumentBuilder::getState()
86 throw (RuntimeException)
88 ::osl::MutexGuard g(m_Mutex);
90 return m_aState;
93 void SAL_CALL CSAXDocumentBuilder::reset()
94 throw (RuntimeException)
96 ::osl::MutexGuard g(m_Mutex);
98 m_aDocument = Reference< XDocument >();
99 m_aFragment = Reference< XDocumentFragment >();
100 while (!m_aNodeStack.empty()) m_aNodeStack.pop();
101 while (!m_aNSStack.empty()) m_aNSStack.pop();
102 m_aState = SAXDocumentBuilderState_READY;
105 Reference< XDocument > SAL_CALL CSAXDocumentBuilder::getDocument()
106 throw (RuntimeException)
108 ::osl::MutexGuard g(m_Mutex);
110 if (m_aState != SAXDocumentBuilderState_DOCUMENT_FINISHED)
111 throw RuntimeException();
113 return m_aDocument;
116 Reference< XDocumentFragment > SAL_CALL CSAXDocumentBuilder::getDocumentFragment()
117 throw (RuntimeException)
119 ::osl::MutexGuard g(m_Mutex);
121 if (m_aState != SAXDocumentBuilderState_FRAGMENT_FINISHED)
122 throw RuntimeException();
123 return m_aFragment;
126 void SAL_CALL CSAXDocumentBuilder::startDocumentFragment(const Reference< XDocument >& ownerDoc)
127 throw (RuntimeException)
129 ::osl::MutexGuard g(m_Mutex);
131 // start a new document fragment and push it onto the stack
132 // we have to be in a clean state to do this
133 if (!m_aState == SAXDocumentBuilderState_READY)
134 throw RuntimeException();
136 m_aDocument = ownerDoc;
137 Reference< XDocumentFragment > aFragment = m_aDocument->createDocumentFragment();
138 m_aNodeStack.push(Reference< XNode >(aFragment, UNO_QUERY));
139 m_aFragment = aFragment;
140 m_aState = SAXDocumentBuilderState_BUILDING_FRAGMENT;
143 void SAL_CALL CSAXDocumentBuilder::endDocumentFragment()
144 throw (RuntimeException)
146 ::osl::MutexGuard g(m_Mutex);
148 // there should only be the document left on the node stack
149 if (m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
150 throw RuntimeException();
152 Reference< XNode > aNode = m_aNodeStack.top();
153 if ( aNode->getNodeType() != NodeType_DOCUMENT_FRAGMENT_NODE)
154 throw RuntimeException();
155 m_aNodeStack.pop();
156 m_aState = SAXDocumentBuilderState_FRAGMENT_FINISHED;
159 // document handler
161 void SAL_CALL CSAXDocumentBuilder::startDocument() throw (RuntimeException, SAXException)
163 ::osl::MutexGuard g(m_Mutex);
165 // start a new document and push it onto the stack
166 // we have to be in a clean state to do this
167 if (!m_aState == SAXDocumentBuilderState_READY)
168 throw SAXException();
170 Reference< XDocumentBuilder > aBuilder(DocumentBuilder::create(comphelper::getComponentContext(m_aServiceManager)));
171 Reference< XDocument > aDocument = aBuilder->newDocument();
172 m_aNodeStack.push(Reference< XNode >(aDocument, UNO_QUERY));
173 m_aDocument = aDocument;
174 m_aState = SAXDocumentBuilderState_BUILDING_DOCUMENT;
177 void SAL_CALL CSAXDocumentBuilder::endDocument() throw (RuntimeException, SAXException)
179 ::osl::MutexGuard g(m_Mutex);
181 // there should only be the document left on the node stack
182 if (!m_aState == SAXDocumentBuilderState_BUILDING_DOCUMENT)
183 throw SAXException();
185 Reference< XNode > aNode = m_aNodeStack.top();
186 if ( aNode->getNodeType() != NodeType_DOCUMENT_NODE)
187 throw SAXException();
188 m_aNodeStack.pop();
189 m_aState = SAXDocumentBuilderState_DOCUMENT_FINISHED;
192 void SAL_CALL CSAXDocumentBuilder::startElement(const OUString& aName, const Reference< XAttributeList>& attribs)
193 throw (RuntimeException, SAXException)
195 ::osl::MutexGuard g(m_Mutex);
197 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
198 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
200 throw SAXException();
203 // start with mappings in effect for last level
204 NSMap aNSMap;
205 if (!m_aNSStack.empty())
206 aNSMap = NSMap(m_aNSStack.top());
208 // handle xmlns: attributes and add to mappings
209 OUString attr_qname;
210 OUString attr_value;
211 OUString newprefix;
212 AttrMap aAttrMap;
213 sal_Int32 idx=-1;
214 sal_Int16 nAttributes = attribs->getLength();
215 for (sal_Int16 i=0; i<nAttributes; i++)
217 attr_qname = attribs->getNameByIndex(i);
218 attr_value = attribs->getValueByIndex(i);
219 // new prefix mapping
220 if (attr_qname.indexOf("xmlns:") == 0)
222 newprefix = attr_qname.copy(attr_qname.indexOf(':')+1);
223 aNSMap.insert(NSMap::value_type(newprefix, attr_value));
225 else if ( attr_qname == "xmlns" )
227 // new default prefix
228 aNSMap.insert(NSMap::value_type(OUString(), attr_value));
230 else
232 aAttrMap.insert(AttrMap::value_type(attr_qname, attr_value));
236 // does the element have a prefix?
237 OUString aPrefix;
238 OUString aURI;
239 Reference< XElement > aElement;
240 idx = aName.indexOf(':');
241 if (idx != -1)
243 aPrefix = aName.copy(0, idx);
245 else
246 aPrefix = OUString();
248 NSMap::const_iterator result = aNSMap.find(aPrefix);
249 if ( result != aNSMap.end())
251 // found a URI for prefix
252 // qualified name
253 aElement = m_aDocument->createElementNS( result->second, aName);
255 else
257 // no URI for prefix
258 aElement = m_aDocument->createElement(aName);
260 aElement = Reference< XElement > (
261 m_aNodeStack.top()->appendChild(Reference< XNode >(aElement, UNO_QUERY)),
262 UNO_QUERY);
263 m_aNodeStack.push(Reference< XNode >(aElement, UNO_QUERY));
265 // set non xmlns attributes
266 aPrefix = OUString();
267 aURI = OUString();
268 AttrMap::const_iterator a = aAttrMap.begin();
269 while (a != aAttrMap.end())
271 attr_qname = a->first;
272 attr_value = a->second;
273 idx = attr_qname.indexOf(':');
274 if (idx != -1)
275 aPrefix = attr_qname.copy(0, idx);
276 else
277 aPrefix = OUString();
279 result = aNSMap.find(aPrefix);
280 if (result != aNSMap.end())
282 // set attribute with namespace
283 aElement->setAttributeNS(result->second, attr_qname, attr_value);
285 else
287 // set attribute without namespace
288 aElement->setAttribute(attr_qname, attr_value);
290 ++a;
292 m_aNSStack.push(aNSMap);
295 void SAL_CALL CSAXDocumentBuilder::endElement(const OUString& aName)
296 throw (RuntimeException, SAXException)
298 ::osl::MutexGuard g(m_Mutex);
300 // pop the current element from the stack
301 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
302 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
303 throw SAXException();
305 Reference< XNode > aNode(m_aNodeStack.top());
306 if (aNode->getNodeType() != NodeType_ELEMENT_NODE)
307 throw SAXException();
309 Reference< XElement > aElement(aNode, UNO_QUERY);
310 OUString aRefName;
311 OUString aPrefix = aElement->getPrefix();
312 if (!aPrefix.isEmpty())
313 aRefName = aPrefix + ":" + aElement->getTagName();
314 else
315 aRefName = aElement->getTagName();
316 if (aRefName != aName) // consistency check
317 throw SAXException();
319 // pop it
320 m_aNodeStack.pop();
321 m_aNSStack.pop();
324 void SAL_CALL CSAXDocumentBuilder::characters(const OUString& aChars)
325 throw (RuntimeException, SAXException)
327 ::osl::MutexGuard g(m_Mutex);
329 // append text node to the current top element
330 if (m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
331 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
332 throw SAXException();
334 Reference< XText > aText = m_aDocument->createTextNode(aChars);
335 m_aNodeStack.top()->appendChild(Reference< XNode >(aText, UNO_QUERY));
338 void SAL_CALL CSAXDocumentBuilder::ignorableWhitespace(const OUString& )
339 throw (RuntimeException, SAXException)
341 ::osl::MutexGuard g(m_Mutex);
343 // ignore ignorable whitespace
344 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
345 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
346 throw SAXException();
349 void SAL_CALL CSAXDocumentBuilder::processingInstruction(const OUString& aTarget, const OUString& aData)
350 throw (RuntimeException, SAXException)
352 ::osl::MutexGuard g(m_Mutex);
354 // append PI node to the current top
355 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
356 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
357 throw SAXException();
359 Reference< XProcessingInstruction > aInstruction = m_aDocument->createProcessingInstruction(
360 aTarget, aData);
361 m_aNodeStack.top()->appendChild(Reference< XNode >(aInstruction, UNO_QUERY));
364 void SAL_CALL CSAXDocumentBuilder::setDocumentLocator(const Reference< XLocator >& aLocator)
365 throw (RuntimeException, SAXException)
367 ::osl::MutexGuard g(m_Mutex);
369 // set the document locator...
370 m_aLocator = aLocator;
374 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */