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