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