Update ooo320-m1
[ooovba.git] / unoxml / source / dom / saxbuilder.cxx
blob9836ba56c67834fc8b68c3023fddd62e07d47253
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: saxbuilder.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #if defined(_MSC_VER) && (_MSC_VER > 1310)
31 #pragma warning(disable : 4701)
32 #endif
34 #include "node.hxx"
35 #include "saxbuilder.hxx"
36 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
37 #include <libxml/tree.h>
38 #include <com/sun/star/uno/Sequence.h>
40 namespace DOM
42 Reference< XInterface > CSAXDocumentBuilder::_getInstance(const Reference< XMultiServiceFactory >& rSMgr)
44 return static_cast< XSAXDocumentBuilder* >(new CSAXDocumentBuilder(rSMgr));
47 const char* CSAXDocumentBuilder::aImplementationName = "com.sun.star.comp.xml.dom.SAXDocumentBuilder";
48 const char* CSAXDocumentBuilder::aSupportedServiceNames[] = {
49 "com.sun.star.xml.dom.SAXDocumentBuilder",
50 NULL
53 CSAXDocumentBuilder::CSAXDocumentBuilder(const Reference< XMultiServiceFactory >& mgr)
54 : m_aServiceManager(mgr)
55 , m_aState( SAXDocumentBuilderState_READY)
58 OUString CSAXDocumentBuilder::_getImplementationName()
60 return OUString::createFromAscii(aImplementationName);
62 Sequence<OUString> CSAXDocumentBuilder::_getSupportedServiceNames()
64 Sequence<OUString> aSequence;
65 for (int i=0; aSupportedServiceNames[i]!=NULL; i++) {
66 aSequence.realloc(i+1);
67 aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i]));
69 return aSequence;
72 Sequence< OUString > SAL_CALL CSAXDocumentBuilder::getSupportedServiceNames()
73 throw (RuntimeException)
75 return CSAXDocumentBuilder::_getSupportedServiceNames();
78 OUString SAL_CALL CSAXDocumentBuilder::getImplementationName()
79 throw (RuntimeException)
81 return CSAXDocumentBuilder::_getImplementationName();
84 sal_Bool SAL_CALL CSAXDocumentBuilder::supportsService(const OUString& aServiceName)
85 throw (RuntimeException)
87 Sequence< OUString > supported = CSAXDocumentBuilder::_getSupportedServiceNames();
88 for (sal_Int32 i=0; i<supported.getLength(); i++)
90 if (supported[i] == aServiceName) return sal_True;
92 return sal_False;
96 SAXDocumentBuilderState SAL_CALL CSAXDocumentBuilder::getState()
97 throw (RuntimeException)
99 return m_aState;
102 void SAL_CALL CSAXDocumentBuilder::reset()
103 throw (RuntimeException)
105 m_aDocument = Reference< XDocument >();
106 m_aFragment = Reference< XDocumentFragment >();
107 while (!m_aNodeStack.empty()) m_aNodeStack.pop();
108 while (!m_aNSStack.empty()) m_aNSStack.pop();
109 m_aState = SAXDocumentBuilderState_READY;
112 Reference< XDocument > SAL_CALL CSAXDocumentBuilder::getDocument()
113 throw (RuntimeException)
115 if (m_aState != SAXDocumentBuilderState_DOCUMENT_FINISHED)
116 throw RuntimeException();
118 return m_aDocument;
121 Reference< XDocumentFragment > SAL_CALL CSAXDocumentBuilder::getDocumentFragment()
122 throw (RuntimeException)
124 if (m_aState != SAXDocumentBuilderState_FRAGMENT_FINISHED)
125 throw RuntimeException();
126 return m_aFragment;
129 void SAL_CALL CSAXDocumentBuilder::startDocumentFragment(const Reference< XDocument >& ownerDoc)
130 throw (RuntimeException)
132 // start a new document fragment and push it onto the stack
133 // we have to be in a clean state to do this
134 if (!m_aState == SAXDocumentBuilderState_READY)
135 throw RuntimeException();
137 m_aDocument = ownerDoc;
138 Reference< XDocumentFragment > aFragment = m_aDocument->createDocumentFragment();
139 m_aNodeStack.push(Reference< XNode >(aFragment, UNO_QUERY));
140 m_aFragment = aFragment;
141 m_aState = SAXDocumentBuilderState_BUILDING_FRAGMENT;
144 void SAL_CALL CSAXDocumentBuilder::endDocumentFragment()
145 throw (RuntimeException)
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)
163 // start a new document and push it onto the stack
164 // we have to be in a clean state to do this
165 if (!m_aState == SAXDocumentBuilderState_READY)
166 throw SAXException();
168 Reference< XDocumentBuilder > aBuilder(m_aServiceManager->createInstance(
169 OUString::createFromAscii("com.sun.star.xml.dom.DocumentBuilder")), UNO_QUERY_THROW);
170 Reference< XDocument > aDocument = aBuilder->newDocument();
171 m_aNodeStack.push(Reference< XNode >(aDocument, UNO_QUERY));
172 m_aDocument = aDocument;
173 m_aState = SAXDocumentBuilderState_BUILDING_DOCUMENT;
176 void SAL_CALL CSAXDocumentBuilder::endDocument() throw (RuntimeException, SAXException)
178 // there should only be the document left on the node stack
179 if (!m_aState == SAXDocumentBuilderState_BUILDING_DOCUMENT)
180 throw SAXException();
182 Reference< XNode > aNode = m_aNodeStack.top();
183 if ( aNode->getNodeType() != NodeType_DOCUMENT_NODE)
184 throw SAXException();
185 m_aNodeStack.pop();
186 m_aState = SAXDocumentBuilderState_DOCUMENT_FINISHED;
189 void SAL_CALL CSAXDocumentBuilder::startElement(const OUString& aName, const Reference< XAttributeList>& attribs)
190 throw (RuntimeException, SAXException)
192 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
193 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
195 throw SAXException();
198 // start with mappings in effect for last level
199 NSMap aNSMap;
200 if (!m_aNSStack.empty())
201 aNSMap = NSMap(m_aNSStack.top());
203 // handle xmlns: attributes and add to mappings
204 OUString attr_qname;
205 OUString attr_value;
206 OUString newprefix;
207 AttrMap aAttrMap;
208 sal_Int32 idx=-1;
209 sal_Int16 nAttributes = attribs->getLength();
210 for (sal_Int16 i=0; i<nAttributes; i++)
212 attr_qname = attribs->getNameByIndex(i);
213 attr_value = attribs->getValueByIndex(i);
214 // new prefix mapping
215 if (attr_qname.indexOf(OUString::createFromAscii("xmlns:")) == 0)
217 newprefix = attr_qname.copy(attr_qname.indexOf(':')+1);
218 aNSMap.insert(NSMap::value_type(newprefix, attr_value));
220 else if (attr_qname == OUString::createFromAscii("xmlns"))
222 // new default prefix
223 aNSMap.insert(NSMap::value_type(OUString(), attr_value));
225 else
227 aAttrMap.insert(AttrMap::value_type(attr_qname, attr_value));
231 // does the element have a prefix?
232 OUString aPrefix;
233 OUString aURI;
234 Reference< XElement > aElement;
235 idx = aName.indexOf(':');
236 if (idx != -1)
238 aPrefix = aName.copy(0, idx);
240 else
241 aPrefix = OUString();
243 NSMap::const_iterator result = aNSMap.find(aPrefix);
244 if ( result != aNSMap.end())
246 // found a URI for prefix
247 aElement = m_aDocument->createElementNS( result->second, aName); // qualified name
249 else
251 // no URI for prefix
252 aElement = m_aDocument->createElement(aName);
254 aElement = Reference< XElement > (
255 m_aNodeStack.top()->appendChild(Reference< XNode >(aElement, UNO_QUERY)),
256 UNO_QUERY);
257 m_aNodeStack.push(Reference< XNode >(aElement, UNO_QUERY));
259 // set non xmlns attributes
260 aPrefix = OUString();
261 aURI = OUString();
262 AttrMap::const_iterator a = aAttrMap.begin();
263 while (a != aAttrMap.end())
265 attr_qname = a->first;
266 attr_value = a->second;
267 idx = attr_qname.indexOf(':');
268 if(idx != -1)
270 aPrefix = attr_qname.copy(0, idx);
272 else
273 aPrefix = OUString();
275 result = aNSMap.find(aPrefix);
276 if (result != aNSMap.end())
278 // set attribute with namespace
279 aElement->setAttributeNS(result->second, attr_qname, attr_value);
280 } else {
281 // set attribute without namespace
282 aElement->setAttribute(attr_qname, attr_value);
284 a++;
286 m_aNSStack.push(aNSMap);
289 void SAL_CALL CSAXDocumentBuilder::endElement(const OUString& aName)
290 throw (RuntimeException, SAXException)
292 // pop the current element from the stack
293 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
294 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
295 throw SAXException();
297 Reference< XNode > aNode(m_aNodeStack.top());
298 if (aNode->getNodeType() != NodeType_ELEMENT_NODE)
299 throw SAXException();
301 Reference< XElement > aElement(aNode, UNO_QUERY);
302 OUString aRefName;
303 OUString aPrefix = aElement->getPrefix();
304 if (aPrefix.getLength() > 0)
305 aRefName = aPrefix + OUString::createFromAscii(":") + aElement->getTagName();
306 else
307 aRefName = aElement->getTagName();
308 if (aRefName != aName) // consistency check
309 throw SAXException();
311 // pop it
312 m_aNodeStack.pop();
313 m_aNSStack.pop();
316 void SAL_CALL CSAXDocumentBuilder::characters(const OUString& aChars)
317 throw (RuntimeException, SAXException)
319 // append text node to the current top element
320 if (m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
321 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
322 throw SAXException();
324 Reference< XText > aText = m_aDocument->createTextNode(aChars);
325 m_aNodeStack.top()->appendChild(Reference< XNode >(aText, UNO_QUERY));
328 void SAL_CALL CSAXDocumentBuilder::ignorableWhitespace(const OUString& )
329 throw (RuntimeException, SAXException)
331 // ignore ignorable whitespace
332 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
333 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
334 throw SAXException();
337 void SAL_CALL CSAXDocumentBuilder::processingInstruction(const OUString& aTarget, const OUString& aData)
338 throw (RuntimeException, SAXException)
340 // append PI node to the current top
341 if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
342 m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
343 throw SAXException();
345 Reference< XProcessingInstruction > aInstruction = m_aDocument->createProcessingInstruction(
346 aTarget, aData);
347 m_aNodeStack.top()->appendChild(Reference< XNode >(aInstruction, UNO_QUERY));
350 void SAL_CALL CSAXDocumentBuilder::setDocumentLocator(const Reference< XLocator >& aLocator)
351 throw (RuntimeException, SAXException)
353 // set the document locator...
354 m_aLocator = aLocator;