Branch data Line data Source code
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 : : #if defined(_MSC_VER) && (_MSC_VER > 1310)
20 : : #pragma warning(disable : 4701)
21 : : #endif
22 : :
23 : : #include "saxbuilder.hxx"
24 : :
25 : : #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
26 : :
27 : :
28 : : namespace DOM
29 : : {
30 : 199 : Reference< XInterface > CSAXDocumentBuilder::_getInstance(const Reference< XMultiServiceFactory >& rSMgr)
31 : : {
32 [ + - ][ + - ]: 199 : return static_cast< XSAXDocumentBuilder* >(new CSAXDocumentBuilder(rSMgr));
33 : : }
34 : :
35 : : const char* CSAXDocumentBuilder::aImplementationName = "com.sun.star.comp.xml.dom.SAXDocumentBuilder";
36 : : const char* CSAXDocumentBuilder::aSupportedServiceNames[] = {
37 : : "com.sun.star.xml.dom.SAXDocumentBuilder",
38 : : NULL
39 : : };
40 : :
41 : 199 : CSAXDocumentBuilder::CSAXDocumentBuilder(const Reference< XMultiServiceFactory >& mgr)
42 : : : m_aServiceManager(mgr)
43 [ + - ][ + - ]: 199 : , m_aState( SAXDocumentBuilderState_READY)
[ + - ][ + - ]
[ + - ]
44 : 199 : {}
45 : :
46 : 321 : OUString CSAXDocumentBuilder::_getImplementationName()
47 : : {
48 : 321 : return OUString::createFromAscii(aImplementationName);
49 : : }
50 : 65 : Sequence<OUString> CSAXDocumentBuilder::_getSupportedServiceNames()
51 : : {
52 : 65 : Sequence<OUString> aSequence;
53 [ + + ]: 130 : for (int i=0; aSupportedServiceNames[i]!=NULL; i++) {
54 [ + - ]: 65 : aSequence.realloc(i+1);
55 [ + - ]: 65 : aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i]));
56 : : }
57 : 65 : return aSequence;
58 : : }
59 : :
60 : 0 : Sequence< OUString > SAL_CALL CSAXDocumentBuilder::getSupportedServiceNames()
61 : : throw (RuntimeException)
62 : : {
63 : 0 : return CSAXDocumentBuilder::_getSupportedServiceNames();
64 : : }
65 : :
66 : 0 : OUString SAL_CALL CSAXDocumentBuilder::getImplementationName()
67 : : throw (RuntimeException)
68 : : {
69 : 0 : return CSAXDocumentBuilder::_getImplementationName();
70 : : }
71 : :
72 : 0 : sal_Bool SAL_CALL CSAXDocumentBuilder::supportsService(const OUString& aServiceName)
73 : : throw (RuntimeException)
74 : : {
75 [ # # ]: 0 : Sequence< OUString > supported = CSAXDocumentBuilder::_getSupportedServiceNames();
76 [ # # ]: 0 : for (sal_Int32 i=0; i<supported.getLength(); i++)
77 : : {
78 [ # # ][ # # ]: 0 : if (supported[i] == aServiceName) return sal_True;
79 : : }
80 [ # # ]: 0 : return sal_False;
81 : : }
82 : :
83 : :
84 : 0 : SAXDocumentBuilderState SAL_CALL CSAXDocumentBuilder::getState()
85 : : throw (RuntimeException)
86 : : {
87 [ # # ]: 0 : ::osl::MutexGuard g(m_Mutex);
88 : :
89 [ # # ]: 0 : return m_aState;
90 : : }
91 : :
92 : 0 : void SAL_CALL CSAXDocumentBuilder::reset()
93 : : throw (RuntimeException)
94 : : {
95 [ # # ]: 0 : ::osl::MutexGuard g(m_Mutex);
96 : :
97 [ # # ]: 0 : m_aDocument = Reference< XDocument >();
98 [ # # ]: 0 : m_aFragment = Reference< XDocumentFragment >();
99 [ # # ][ # # ]: 0 : while (!m_aNodeStack.empty()) m_aNodeStack.pop();
100 [ # # ][ # # ]: 0 : while (!m_aNSStack.empty()) m_aNSStack.pop();
101 [ # # ]: 0 : m_aState = SAXDocumentBuilderState_READY;
102 : 0 : }
103 : :
104 : 197 : Reference< XDocument > SAL_CALL CSAXDocumentBuilder::getDocument()
105 : : throw (RuntimeException)
106 : : {
107 [ + - ]: 197 : ::osl::MutexGuard g(m_Mutex);
108 : :
109 [ - + ]: 197 : if (m_aState != SAXDocumentBuilderState_DOCUMENT_FINISHED)
110 [ # # ]: 0 : throw RuntimeException();
111 : :
112 [ + - ]: 197 : return m_aDocument;
113 : : }
114 : :
115 : 0 : Reference< XDocumentFragment > SAL_CALL CSAXDocumentBuilder::getDocumentFragment()
116 : : throw (RuntimeException)
117 : : {
118 [ # # ]: 0 : ::osl::MutexGuard g(m_Mutex);
119 : :
120 [ # # ]: 0 : if (m_aState != SAXDocumentBuilderState_FRAGMENT_FINISHED)
121 [ # # ]: 0 : throw RuntimeException();
122 [ # # ]: 0 : return m_aFragment;
123 : : }
124 : :
125 : 0 : void SAL_CALL CSAXDocumentBuilder::startDocumentFragment(const Reference< XDocument >& ownerDoc)
126 : : throw (RuntimeException)
127 : : {
128 [ # # ]: 0 : ::osl::MutexGuard g(m_Mutex);
129 : :
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 [ # # ]: 0 : if (!m_aState == SAXDocumentBuilderState_READY)
133 [ # # ]: 0 : throw RuntimeException();
134 : :
135 [ # # ]: 0 : m_aDocument = ownerDoc;
136 [ # # ][ # # ]: 0 : Reference< XDocumentFragment > aFragment = m_aDocument->createDocumentFragment();
137 [ # # ][ # # ]: 0 : m_aNodeStack.push(Reference< XNode >(aFragment, UNO_QUERY));
138 [ # # ]: 0 : m_aFragment = aFragment;
139 [ # # ]: 0 : m_aState = SAXDocumentBuilderState_BUILDING_FRAGMENT;
140 : 0 : }
141 : :
142 : 0 : void SAL_CALL CSAXDocumentBuilder::endDocumentFragment()
143 : : throw (RuntimeException)
144 : : {
145 [ # # ]: 0 : ::osl::MutexGuard g(m_Mutex);
146 : :
147 : : // there should only be the document left on the node stack
148 [ # # ]: 0 : if (m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
149 [ # # ]: 0 : throw RuntimeException();
150 : :
151 [ # # ]: 0 : Reference< XNode > aNode = m_aNodeStack.top();
152 [ # # ][ # # ]: 0 : if ( aNode->getNodeType() != NodeType_DOCUMENT_FRAGMENT_NODE)
[ # # ]
153 [ # # ]: 0 : throw RuntimeException();
154 [ # # ]: 0 : m_aNodeStack.pop();
155 [ # # ]: 0 : m_aState = SAXDocumentBuilderState_FRAGMENT_FINISHED;
156 : 0 : }
157 : :
158 : : // document handler
159 : :
160 : 197 : void SAL_CALL CSAXDocumentBuilder::startDocument() throw (RuntimeException, SAXException)
161 : : {
162 [ + - ]: 197 : ::osl::MutexGuard g(m_Mutex);
163 : :
164 : : // start a new document and push it onto the stack
165 : : // we have to be in a clean state to do this
166 [ - + ]: 197 : if (!m_aState == SAXDocumentBuilderState_READY)
167 [ # # ]: 0 : throw SAXException();
168 : :
169 [ + - ]: 197 : Reference< XDocumentBuilder > aBuilder(m_aServiceManager->createInstance(
170 [ + - ][ + - ]: 197 : "com.sun.star.xml.dom.DocumentBuilder"), UNO_QUERY_THROW);
171 [ + - ][ + - ]: 197 : Reference< XDocument > aDocument = aBuilder->newDocument();
172 [ + - ][ + - ]: 197 : m_aNodeStack.push(Reference< XNode >(aDocument, UNO_QUERY));
173 [ + - ]: 197 : m_aDocument = aDocument;
174 [ + - ]: 197 : m_aState = SAXDocumentBuilderState_BUILDING_DOCUMENT;
175 : 197 : }
176 : :
177 : 197 : void SAL_CALL CSAXDocumentBuilder::endDocument() throw (RuntimeException, SAXException)
178 : : {
179 [ + - ]: 197 : ::osl::MutexGuard g(m_Mutex);
180 : :
181 : : // there should only be the document left on the node stack
182 [ - + ][ - + ]: 197 : if (!m_aState == SAXDocumentBuilderState_BUILDING_DOCUMENT)
183 [ # # ]: 0 : throw SAXException();
184 : :
185 [ + - ]: 197 : Reference< XNode > aNode = m_aNodeStack.top();
186 [ + - ][ - + ]: 197 : if ( aNode->getNodeType() != NodeType_DOCUMENT_NODE)
[ + - ]
187 [ # # ]: 0 : throw SAXException();
188 [ + - ]: 197 : m_aNodeStack.pop();
189 [ + - ]: 197 : m_aState = SAXDocumentBuilderState_DOCUMENT_FINISHED;
190 : 197 : }
191 : :
192 : 1936 : void SAL_CALL CSAXDocumentBuilder::startElement(const OUString& aName, const Reference< XAttributeList>& attribs)
193 : : throw (RuntimeException, SAXException)
194 : : {
195 [ + - ]: 1936 : ::osl::MutexGuard g(m_Mutex);
196 : :
197 [ - + ][ # # ]: 1936 : if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
198 : : m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
199 : : {
200 [ # # ]: 0 : throw SAXException();
201 : : }
202 : :
203 : : // start with mappings in effect for last level
204 [ + - ]: 1936 : NSMap aNSMap;
205 [ + + ]: 1936 : if (!m_aNSStack.empty())
206 [ + - ][ + - ]: 1739 : aNSMap = NSMap(m_aNSStack.top());
[ + - ]
207 : :
208 : : // handle xmlns: attributes and add to mappings
209 : 1936 : OUString attr_qname;
210 : 1936 : OUString attr_value;
211 : 1936 : OUString newprefix;
212 [ + - ]: 1936 : AttrMap aAttrMap;
213 : 1936 : sal_Int32 idx=-1;
214 [ + - ][ + - ]: 1936 : sal_Int16 nAttributes = attribs->getLength();
215 [ + + ]: 4724 : for (sal_Int16 i=0; i<nAttributes; i++)
216 : : {
217 [ + - ][ + - ]: 2788 : attr_qname = attribs->getNameByIndex(i);
218 [ + - ][ + - ]: 2788 : attr_value = attribs->getValueByIndex(i);
219 : : // new prefix mapping
220 [ + + ]: 2788 : if (attr_qname.indexOf("xmlns:") == 0)
221 : : {
222 : 1342 : newprefix = attr_qname.copy(attr_qname.indexOf(':')+1);
223 [ + - ]: 1342 : aNSMap.insert(NSMap::value_type(newprefix, attr_value));
224 : : }
225 [ - + ]: 1446 : else if ( attr_qname == "xmlns" )
226 : : {
227 : : // new default prefix
228 [ # # ]: 0 : aNSMap.insert(NSMap::value_type(OUString(), attr_value));
229 : : }
230 : : else
231 : : {
232 [ + - ]: 1446 : aAttrMap.insert(AttrMap::value_type(attr_qname, attr_value));
233 : : }
234 : : }
235 : :
236 : : // does the element have a prefix?
237 : 1936 : OUString aPrefix;
238 : 1936 : OUString aURI;
239 : 1936 : Reference< XElement > aElement;
240 : 1936 : idx = aName.indexOf(':');
241 [ + + ]: 1936 : if (idx != -1)
242 : : {
243 : 1934 : aPrefix = aName.copy(0, idx);
244 : : }
245 : : else
246 : 2 : aPrefix = OUString();
247 : :
248 [ + - ]: 1936 : NSMap::const_iterator result = aNSMap.find(aPrefix);
249 [ + + ]: 1936 : if ( result != aNSMap.end())
250 : : {
251 : : // found a URI for prefix
252 : : // qualified name
253 [ + - ][ + - ]: 1934 : aElement = m_aDocument->createElementNS( result->second, aName);
[ + - ]
254 : : }
255 : : else
256 : : {
257 : : // no URI for prefix
258 [ + - ][ + - ]: 2 : aElement = m_aDocument->createElement(aName);
[ + - ]
259 : : }
260 : : aElement = Reference< XElement > (
261 [ + - ][ + - ]: 1936 : m_aNodeStack.top()->appendChild(Reference< XNode >(aElement, UNO_QUERY)),
262 [ + - ][ + - ]: 1936 : UNO_QUERY);
[ + - ][ + - ]
263 [ + - ][ + - ]: 1936 : m_aNodeStack.push(Reference< XNode >(aElement, UNO_QUERY));
264 : :
265 : : // set non xmlns attributes
266 : 1936 : aPrefix = OUString();
267 : 1936 : aURI = OUString();
268 : 1936 : AttrMap::const_iterator a = aAttrMap.begin();
269 [ + + ]: 3382 : while (a != aAttrMap.end())
270 : : {
271 : 1446 : attr_qname = a->first;
272 : 1446 : attr_value = a->second;
273 : 1446 : idx = attr_qname.indexOf(':');
274 [ + - ]: 1446 : if (idx != -1)
275 : 1446 : aPrefix = attr_qname.copy(0, idx);
276 : : else
277 : 0 : aPrefix = OUString();
278 : :
279 [ + - ]: 1446 : result = aNSMap.find(aPrefix);
280 [ + - ]: 1446 : if (result != aNSMap.end())
281 : : {
282 : : // set attribute with namespace
283 [ + - ][ + - ]: 1446 : aElement->setAttributeNS(result->second, attr_qname, attr_value);
284 : : }
285 : : else
286 : : {
287 : : // set attribute without namespace
288 [ # # ][ # # ]: 0 : aElement->setAttribute(attr_qname, attr_value);
289 : : }
290 : 1446 : ++a;
291 : : }
292 [ + - ][ + - ]: 1936 : m_aNSStack.push(aNSMap);
293 : 1936 : }
294 : :
295 : 1936 : void SAL_CALL CSAXDocumentBuilder::endElement(const OUString& aName)
296 : : throw (RuntimeException, SAXException)
297 : : {
298 [ + - ]: 1936 : ::osl::MutexGuard g(m_Mutex);
299 : :
300 : : // pop the current element from the stack
301 [ - + ][ # # ]: 1936 : if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
302 : : m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
303 [ # # ]: 0 : throw SAXException();
304 : :
305 [ + - ]: 1936 : Reference< XNode > aNode(m_aNodeStack.top());
306 [ + - ][ - + ]: 1936 : if (aNode->getNodeType() != NodeType_ELEMENT_NODE)
[ + - ]
307 [ # # ]: 0 : throw SAXException();
308 : :
309 [ + - ]: 1936 : Reference< XElement > aElement(aNode, UNO_QUERY);
310 : 1936 : OUString aRefName;
311 [ + - ][ + - ]: 1936 : OUString aPrefix = aElement->getPrefix();
312 [ + + ]: 1936 : if (!aPrefix.isEmpty())
313 [ + - ][ + - ]: 1934 : aRefName = aPrefix + ":" + aElement->getTagName();
314 : : else
315 [ + - ][ + - ]: 2 : aRefName = aElement->getTagName();
316 [ - + ]: 1936 : if (aRefName != aName) // consistency check
317 [ # # ]: 0 : throw SAXException();
318 : :
319 : : // pop it
320 [ + - ]: 1936 : m_aNodeStack.pop();
321 [ + - ][ + - ]: 1936 : m_aNSStack.pop();
322 : 1936 : }
323 : :
324 : 1259 : void SAL_CALL CSAXDocumentBuilder::characters(const OUString& aChars)
325 : : throw (RuntimeException, SAXException)
326 : : {
327 [ + - ]: 1259 : ::osl::MutexGuard g(m_Mutex);
328 : :
329 : : // append text node to the current top element
330 [ - + ][ # # ]: 1259 : if (m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
331 : : m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
332 [ # # ]: 0 : throw SAXException();
333 : :
334 [ + - ][ + - ]: 1259 : Reference< XText > aText = m_aDocument->createTextNode(aChars);
335 [ + - ][ + - ]: 1259 : m_aNodeStack.top()->appendChild(Reference< XNode >(aText, UNO_QUERY));
[ + - ][ + - ]
[ + - ]
336 : 1259 : }
337 : :
338 : 0 : void SAL_CALL CSAXDocumentBuilder::ignorableWhitespace(const OUString& )
339 : : throw (RuntimeException, SAXException)
340 : : {
341 [ # # ]: 0 : ::osl::MutexGuard g(m_Mutex);
342 : :
343 : : // ignore ignorable whitespace
344 [ # # ][ # # ]: 0 : if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
345 : : m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
346 [ # # ][ # # ]: 0 : throw SAXException();
347 : 0 : }
348 : :
349 : 0 : void SAL_CALL CSAXDocumentBuilder::processingInstruction(const OUString& aTarget, const OUString& aData)
350 : : throw (RuntimeException, SAXException)
351 : : {
352 [ # # ]: 0 : ::osl::MutexGuard g(m_Mutex);
353 : :
354 : : // append PI node to the current top
355 [ # # ][ # # ]: 0 : if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
356 : : m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
357 [ # # ]: 0 : throw SAXException();
358 : :
359 [ # # ]: 0 : Reference< XProcessingInstruction > aInstruction = m_aDocument->createProcessingInstruction(
360 [ # # ]: 0 : aTarget, aData);
361 [ # # ][ # # ]: 0 : m_aNodeStack.top()->appendChild(Reference< XNode >(aInstruction, UNO_QUERY));
[ # # ][ # # ]
[ # # ]
362 : 0 : }
363 : :
364 : 0 : void SAL_CALL CSAXDocumentBuilder::setDocumentLocator(const Reference< XLocator >& aLocator)
365 : : throw (RuntimeException, SAXException)
366 : : {
367 [ # # ]: 0 : ::osl::MutexGuard g(m_Mutex);
368 : :
369 : : // set the document locator...
370 [ # # ][ # # ]: 0 : m_aLocator = aLocator;
371 : 0 : }
372 : : }
373 : :
374 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|