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 24 #include <element.hxx> 25 26 #include <string.h> 27 28 #include <boost/shared_ptr.hpp> 29 30 #include <rtl/ustrbuf.hxx> 31 32 #include <com/sun/star/xml/sax/FastToken.hdl> 33 34 #include <comphelper/attributelist.hxx> 35 36 #include <node.hxx> 37 #include <attr.hxx> 38 #include <elementlist.hxx> 39 #include <attributesmap.hxx> 40 #include <document.hxx> 41 42 #include "../events/mutationevent.hxx" 43 44 45 namespace DOM 46 { 47 CElement(CDocument const & rDocument,::osl::Mutex const & rMutex,xmlNodePtr const pNode)48 CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex, 49 xmlNodePtr const pNode) 50 : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode) 51 { 52 } 53 saxify(const Reference<XDocumentHandler> & i_xHandler)54 void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler) 55 { 56 if (!i_xHandler.is()) throw RuntimeException(); 57 comphelper::AttributeList *pAttrs = 58 new comphelper::AttributeList(); 59 OUString type = OUString::createFromAscii(""); 60 // add namespace definitions to attributes 61 for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != 0; pNs = pNs->next) { 62 const xmlChar *pPrefix = pNs->prefix; 63 OUString prefix(reinterpret_cast<const sal_Char*>(pPrefix), 64 strlen(reinterpret_cast<const char*>(pPrefix)), 65 RTL_TEXTENCODING_UTF8); 66 OUString name = (prefix.equalsAscii("")) 67 ? OUString::createFromAscii("xmlns") 68 : OUString::createFromAscii("xmlns:") + prefix; 69 const xmlChar *pHref = pNs->href; 70 OUString val(reinterpret_cast<const sal_Char*>(pHref), 71 strlen(reinterpret_cast<const char*>(pHref)), 72 RTL_TEXTENCODING_UTF8); 73 pAttrs->AddAttribute(name, type, val); 74 } 75 // add attributes 76 for (xmlAttrPtr pAttr = m_aNodePtr->properties; 77 pAttr != 0; pAttr = pAttr->next) { 78 ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( 79 reinterpret_cast<xmlNodePtr>(pAttr)); 80 OSL_ENSURE(pNode != 0, "CNode::get returned 0"); 81 OUString prefix = pNode->getPrefix(); 82 OUString name = (prefix.getLength() == 0) 83 ? pNode->getLocalName() 84 : prefix + OUString(static_cast<sal_Unicode>(':')) + pNode->getLocalName(); 85 OUString val = pNode->getNodeValue(); 86 pAttrs->AddAttribute(name, type, val); 87 } 88 OUString prefix = getPrefix(); 89 OUString name = (prefix.getLength() == 0) 90 ? getLocalName() 91 : prefix + OUString(static_cast<sal_Unicode>(':')) + getLocalName(); 92 Reference< XAttributeList > xAttrList(pAttrs); 93 i_xHandler->startElement(name, xAttrList); 94 // recurse 95 for (xmlNodePtr pChild = m_aNodePtr->children; 96 pChild != 0; pChild = pChild->next) { 97 ::rtl::Reference<CNode> const pNode( 98 GetOwnerDocument().GetCNode(pChild)); 99 OSL_ENSURE(pNode != 0, "CNode::get returned 0"); 100 pNode->saxify(i_xHandler); 101 } 102 i_xHandler->endElement(name); 103 } 104 fastSaxify(Context & i_rContext)105 void CElement::fastSaxify( Context& i_rContext ) 106 { 107 if (!i_rContext.mxDocHandler.is()) throw RuntimeException(); 108 pushContext(i_rContext); 109 addNamespaces(i_rContext,m_aNodePtr); 110 111 // add attributes 112 i_rContext.mxAttribList->clear(); 113 for (xmlAttrPtr pAttr = m_aNodePtr->properties; 114 pAttr != 0; pAttr = pAttr->next) { 115 ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( 116 reinterpret_cast<xmlNodePtr>(pAttr)); 117 OSL_ENSURE(pNode != 0, "CNode::get returned 0"); 118 119 const xmlChar* xName = pAttr->name; 120 sal_Int32 nAttributeToken=FastToken::DONTKNOW; 121 122 if( pAttr->ns && strlen((char*)pAttr->ns->prefix) ) 123 nAttributeToken = getTokenWithPrefix( i_rContext, 124 (sal_Char*)pAttr->ns->prefix, 125 (sal_Char*)xName ); 126 else 127 nAttributeToken = getToken( i_rContext, (sal_Char*)xName ); 128 129 if( nAttributeToken != FastToken::DONTKNOW ) 130 i_rContext.mxAttribList->add( nAttributeToken, 131 OUStringToOString(pNode->getNodeValue(), 132 RTL_TEXTENCODING_UTF8)); 133 } 134 135 const xmlChar* xPrefix = m_aNodePtr->ns ? m_aNodePtr->ns->prefix : (const xmlChar*)""; 136 const xmlChar* xName = m_aNodePtr->name; 137 sal_Int32 nElementToken=FastToken::DONTKNOW; 138 if( strlen((char*)xPrefix) ) 139 nElementToken = getTokenWithPrefix( i_rContext, (sal_Char*)xPrefix, (sal_Char*)xName ); 140 else 141 nElementToken = getToken( i_rContext, (sal_Char*)xName ); 142 143 Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler); 144 try 145 { 146 Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList.get() ); 147 if( nElementToken == FastToken::DONTKNOW ) 148 { 149 const OUString aNamespace; 150 const OUString aElementName( (sal_Char*)xPrefix, 151 strlen((char*)xPrefix), 152 RTL_TEXTENCODING_UTF8 ); 153 154 if( xParentHandler.is() ) 155 i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr ); 156 else 157 i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr ); 158 159 if( i_rContext.mxCurrentHandler.is() ) 160 i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr ); 161 } 162 else 163 { 164 if( xParentHandler.is() ) 165 i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr ); 166 else 167 i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr ); 168 169 if( i_rContext.mxCurrentHandler.is() ) 170 i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr ); 171 } 172 } 173 catch( Exception& ) 174 {} 175 176 // recurse 177 for (xmlNodePtr pChild = m_aNodePtr->children; 178 pChild != 0; pChild = pChild->next) { 179 ::rtl::Reference<CNode> const pNode( 180 GetOwnerDocument().GetCNode(pChild)); 181 OSL_ENSURE(pNode != 0, "CNode::get returned 0"); 182 pNode->fastSaxify(i_rContext); 183 } 184 185 if( i_rContext.mxCurrentHandler.is() ) try 186 { 187 if( nElementToken != FastToken::DONTKNOW ) 188 i_rContext.mxCurrentHandler->endFastElement( nElementToken ); 189 else 190 { 191 const OUString aNamespace; 192 const OUString aElementName( (sal_Char*)xPrefix, 193 strlen((char*)xPrefix), 194 RTL_TEXTENCODING_UTF8 ); 195 196 i_rContext.mxCurrentHandler->endUnknownElement( aNamespace, aElementName ); 197 } 198 } 199 catch( Exception& ) 200 {} 201 202 // restore after children have been processed 203 i_rContext.mxCurrentHandler = xParentHandler; 204 popContext(i_rContext); 205 } 206 IsChildTypeAllowed(NodeType const nodeType)207 bool CElement::IsChildTypeAllowed(NodeType const nodeType) 208 { 209 switch (nodeType) { 210 case NodeType_ELEMENT_NODE: 211 case NodeType_TEXT_NODE: 212 case NodeType_COMMENT_NODE: 213 case NodeType_PROCESSING_INSTRUCTION_NODE: 214 case NodeType_CDATA_SECTION_NODE: 215 case NodeType_ENTITY_REFERENCE_NODE: 216 return true; 217 case NodeType_ATTRIBUTE_NODE: 218 /* this is not relly allowed by the DOM spec, but this 219 implementation has evidently supported it (by special case 220 handling, so the attribute does not actually become a child) 221 so allow it for backward compatibility */ 222 return true; 223 default: 224 return false; 225 } 226 } 227 228 229 /** 230 Retrieves an attribute value by name. 231 return empty string if attribute is not set 232 */ getAttribute(OUString const & name)233 OUString SAL_CALL CElement::getAttribute(OUString const& name) 234 throw (RuntimeException) 235 { 236 ::osl::MutexGuard const g(m_rMutex); 237 238 if (0 == m_aNodePtr) { 239 return ::rtl::OUString(); 240 } 241 // search properties 242 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); 243 ::boost::shared_ptr<xmlChar const> const pValue( 244 xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()), xmlFree); 245 OUString const ret( (pValue) 246 ? OUString(reinterpret_cast<sal_Char const*>(pValue.get()), 247 strlen(reinterpret_cast<char const*>(pValue.get())), 248 RTL_TEXTENCODING_UTF8) 249 : OUString() ); 250 return ret; 251 } 252 253 /** 254 Retrieves an attribute node by name. 255 */ getAttributeNode(OUString const & name)256 Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name) 257 throw (RuntimeException) 258 { 259 ::osl::MutexGuard const g(m_rMutex); 260 261 if (0 == m_aNodePtr) { 262 return 0; 263 } 264 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); 265 xmlChar const*const pName = 266 reinterpret_cast<xmlChar const*>(o1.getStr()); 267 xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); 268 if (0 == pAttr) { 269 return 0; 270 } 271 Reference< XAttr > const xRet( 272 static_cast< XNode* >(GetOwnerDocument().GetCNode( 273 reinterpret_cast<xmlNodePtr>(pAttr)).get()), 274 UNO_QUERY_THROW); 275 return xRet; 276 } 277 278 /** 279 Retrieves an Attr node by local name and namespace URI. 280 */ getAttributeNodeNS(const OUString & namespaceURI,const OUString & localName)281 Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS( 282 const OUString& namespaceURI, const OUString& localName) 283 throw (RuntimeException) 284 { 285 ::osl::MutexGuard const g(m_rMutex); 286 287 if (0 == m_aNodePtr) { 288 return 0; 289 } 290 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); 291 xmlChar const*const pName = 292 reinterpret_cast<xmlChar const*>(o1.getStr()); 293 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); 294 xmlChar const*const pNS = 295 reinterpret_cast<xmlChar const*>(o2.getStr()); 296 xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS); 297 if (0 == pAttr) { 298 return 0; 299 } 300 Reference< XAttr > const xRet( 301 static_cast< XNode* >(GetOwnerDocument().GetCNode( 302 reinterpret_cast<xmlNodePtr>(pAttr)).get()), 303 UNO_QUERY_THROW); 304 return xRet; 305 } 306 307 /** 308 Retrieves an attribute value by local name and namespace URI. 309 return empty string if attribute is not set 310 */ 311 OUString SAL_CALL getAttributeNS(OUString const & namespaceURI,OUString const & localName)312 CElement::getAttributeNS( 313 OUString const& namespaceURI, OUString const& localName) 314 throw (RuntimeException) 315 { 316 ::osl::MutexGuard const g(m_rMutex); 317 318 if (0 == m_aNodePtr) { 319 return ::rtl::OUString(); 320 } 321 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); 322 xmlChar const*const pName = 323 reinterpret_cast<xmlChar const*>(o1.getStr()); 324 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); 325 xmlChar const*const pNS = 326 reinterpret_cast<xmlChar const*>(o2.getStr()); 327 ::boost::shared_ptr<xmlChar const> const pValue( 328 xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree); 329 if (0 == pValue) { 330 return ::rtl::OUString(); 331 } 332 OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()), 333 strlen(reinterpret_cast<char const*>(pValue.get())), 334 RTL_TEXTENCODING_UTF8); 335 return ret; 336 } 337 338 /** 339 Returns a NodeList of all descendant Elements with a given tag name, 340 in the order in which they are 341 encountered in a preorder traversal of this Element tree. 342 */ 343 Reference< XNodeList > SAL_CALL getElementsByTagName(OUString const & rLocalName)344 CElement::getElementsByTagName(OUString const& rLocalName) 345 throw (RuntimeException) 346 { 347 ::osl::MutexGuard const g(m_rMutex); 348 349 Reference< XNodeList > const xList( 350 new CElementList(this, m_rMutex, rLocalName)); 351 return xList; 352 } 353 354 /** 355 Returns a NodeList of all the descendant Elements with a given local 356 name and namespace URI in the order in which they are encountered in 357 a preorder traversal of this Element tree. 358 */ 359 Reference< XNodeList > SAL_CALL getElementsByTagNameNS(OUString const & rNamespaceURI,OUString const & rLocalName)360 CElement::getElementsByTagNameNS( 361 OUString const& rNamespaceURI, OUString const& rLocalName) 362 throw (RuntimeException) 363 { 364 ::osl::MutexGuard const g(m_rMutex); 365 366 Reference< XNodeList > const xList( 367 new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI)); 368 return xList; 369 } 370 371 /** 372 The name of the element. 373 */ getTagName()374 OUString SAL_CALL CElement::getTagName() 375 throw (RuntimeException) 376 { 377 ::osl::MutexGuard const g(m_rMutex); 378 379 if (0 == m_aNodePtr) { 380 return ::rtl::OUString(); 381 } 382 OUString const ret((sal_Char*)m_aNodePtr->name, 383 strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8); 384 return ret; 385 } 386 387 388 /** 389 Returns true when an attribute with a given name is specified on this 390 element or has a default value, false otherwise. 391 */ hasAttribute(OUString const & name)392 sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name) 393 throw (RuntimeException) 394 { 395 ::osl::MutexGuard const g(m_rMutex); 396 397 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); 398 xmlChar *xName = (xmlChar*)o1.getStr(); 399 return (m_aNodePtr != NULL && xmlHasProp(m_aNodePtr, xName) != NULL); 400 } 401 402 /** 403 Returns true when an attribute with a given local name and namespace 404 URI is specified on this element or has a default value, false otherwise. 405 */ hasAttributeNS(OUString const & namespaceURI,OUString const & localName)406 sal_Bool SAL_CALL CElement::hasAttributeNS( 407 OUString const& namespaceURI, OUString const& localName) 408 throw (RuntimeException) 409 { 410 ::osl::MutexGuard const g(m_rMutex); 411 412 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); 413 xmlChar *xName = (xmlChar*)o1.getStr(); 414 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); 415 xmlChar *xNs = (xmlChar*)o2.getStr(); 416 return (m_aNodePtr != NULL && xmlHasNsProp(m_aNodePtr, xName, xNs) != NULL); 417 } 418 419 /** 420 Removes an attribute by name. 421 */ removeAttribute(OUString const & name)422 void SAL_CALL CElement::removeAttribute(OUString const& name) 423 throw (RuntimeException, DOMException) 424 { 425 ::osl::MutexGuard const g(m_rMutex); 426 427 if (0 == m_aNodePtr) { 428 return; 429 } 430 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); 431 xmlChar const*const pName = 432 reinterpret_cast<xmlChar const*>(o1.getStr()); 433 xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); 434 if (0 == xmlUnsetProp(m_aNodePtr, pName)) { 435 ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( 436 reinterpret_cast<xmlNodePtr>(pAttr), false)); 437 if (pCNode.is()) { 438 pCNode->invalidate(); // freed by xmlUnsetProp 439 } 440 } 441 } 442 443 /** 444 Removes an attribute by local name and namespace URI. 445 */ removeAttributeNS(OUString const & namespaceURI,OUString const & localName)446 void SAL_CALL CElement::removeAttributeNS( 447 OUString const& namespaceURI, OUString const& localName) 448 throw (RuntimeException, DOMException) 449 { 450 ::osl::MutexGuard const g(m_rMutex); 451 452 if (0 == m_aNodePtr) { 453 return; 454 } 455 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); 456 xmlChar const*const pName = 457 reinterpret_cast<xmlChar const*>(o1.getStr()); 458 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); 459 xmlChar const*const pURI = 460 reinterpret_cast<xmlChar const*>(o2.getStr()); 461 xmlNsPtr const pNs = 462 xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI); 463 xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI); 464 if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) { 465 ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( 466 reinterpret_cast<xmlNodePtr>(pAttr), false)); 467 if (pCNode.is()) { 468 pCNode->invalidate(); // freed by xmlUnsetNsProp 469 } 470 } 471 } 472 473 /** 474 Removes the specified attribute node. 475 */ 476 Reference< XAttr > SAL_CALL removeAttributeNode(Reference<XAttr> const & oldAttr)477 CElement::removeAttributeNode(Reference< XAttr > const& oldAttr) 478 throw (RuntimeException, DOMException) 479 { 480 ::osl::MutexGuard const g(m_rMutex); 481 482 if (0 == m_aNodePtr) { 483 return 0; 484 } 485 486 ::rtl::Reference<CNode> const pCNode( 487 CNode::GetImplementation(Reference<XNode>(oldAttr.get()))); 488 if (!pCNode.is()) { throw RuntimeException(); } 489 490 xmlNodePtr const pNode = pCNode->GetNodePtr(); 491 xmlAttrPtr const pAttr = (xmlAttrPtr) pNode; 492 if (!pAttr) { throw RuntimeException(); } 493 494 if (pAttr->parent != m_aNodePtr) 495 { 496 DOMException e; 497 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; 498 throw e; 499 } 500 if (pAttr->doc != m_aNodePtr->doc) 501 { 502 DOMException e; 503 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; 504 throw e; 505 } 506 507 Reference< XAttr > aAttr; 508 if (oldAttr->getNamespaceURI().getLength() > 0) { 509 ::rtl::OUStringBuffer qname(oldAttr->getPrefix()); 510 if (0 != qname.getLength()) { 511 qname.append(sal_Unicode(':')); 512 } 513 qname.append(oldAttr->getName()); 514 aAttr = GetOwnerDocument().createAttributeNS( 515 oldAttr->getNamespaceURI(), qname.makeStringAndClear()); 516 } else { 517 aAttr = GetOwnerDocument().createAttribute(oldAttr->getName()); 518 } 519 aAttr->setValue(oldAttr->getValue()); 520 xmlRemoveProp(pAttr); 521 pCNode->invalidate(); // freed by xmlRemoveProp 522 523 return aAttr; 524 } 525 526 /** 527 Adds a new attribute node. 528 */ 529 Reference< XAttr > setAttributeNode_Impl_Lock(Reference<XAttr> const & xNewAttr,bool const bNS)530 CElement::setAttributeNode_Impl_Lock( 531 Reference< XAttr > const& xNewAttr, bool const bNS) 532 { 533 if (xNewAttr->getOwnerDocument() != getOwnerDocument()) { 534 DOMException e; 535 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; 536 throw e; 537 } 538 539 ::osl::ClearableMutexGuard guard(m_rMutex); 540 541 if (0 == m_aNodePtr) { 542 throw RuntimeException(); 543 } 544 545 // get the implementation 546 CAttr *const pCAttr = dynamic_cast<CAttr*>( 547 CNode::GetImplementation(xNewAttr)); 548 if (!pCAttr) { throw RuntimeException(); } 549 xmlAttrPtr const pAttr = 550 reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr()); 551 if (!pAttr) { throw RuntimeException(); } 552 553 // check whether the attribute is not in use by another element 554 if (pAttr->parent) { 555 DOMException e; 556 e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR; 557 throw e; 558 } 559 560 xmlAttrPtr res = NULL; 561 xmlChar const*const pContent( 562 (pAttr->children) ? pAttr->children->content : 0); 563 564 if (bNS) { 565 xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) ); 566 res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent); 567 } else { 568 res = xmlNewProp(m_aNodePtr, pAttr->name, pContent); 569 } 570 571 // get the new attr node 572 Reference< XAttr > const xAttr( 573 static_cast< XNode* >(GetOwnerDocument().GetCNode( 574 reinterpret_cast<xmlNodePtr>(res)).get()), 575 UNO_QUERY_THROW); 576 577 // attribute adition event 578 // dispatch DOMAttrModified event 579 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); 580 Reference< XMutationEvent > event(docevent->createEvent( 581 OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); 582 event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), 583 sal_True, sal_False, Reference< XNode >(xAttr, UNO_QUERY), 584 OUString(), xAttr->getValue(), xAttr->getName(), 585 AttrChangeType_ADDITION); 586 587 guard.clear(); // release mutex before calling event handlers 588 589 dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); 590 dispatchSubtreeModified(); 591 592 return xAttr; 593 } 594 595 Reference< XAttr > setAttributeNode(const Reference<XAttr> & newAttr)596 CElement::setAttributeNode(const Reference< XAttr >& newAttr) 597 throw (RuntimeException, DOMException) 598 { 599 return setAttributeNode_Impl_Lock(newAttr, false); 600 } 601 602 /** 603 Adds a new attribute. 604 */ 605 Reference< XAttr > setAttributeNodeNS(const Reference<XAttr> & newAttr)606 CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr) 607 throw (RuntimeException, DOMException) 608 { 609 return setAttributeNode_Impl_Lock(newAttr, true); 610 } 611 612 /** 613 Adds a new attribute. 614 */ 615 void SAL_CALL setAttribute(OUString const & name,OUString const & value)616 CElement::setAttribute(OUString const& name, OUString const& value) 617 throw (RuntimeException, DOMException) 618 { 619 ::osl::ClearableMutexGuard guard(m_rMutex); 620 621 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); 622 xmlChar *xName = (xmlChar*)o1.getStr(); 623 OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); 624 xmlChar *xValue = (xmlChar*)o2.getStr(); 625 626 if (0 == m_aNodePtr) { 627 throw RuntimeException(); 628 } 629 OUString oldValue; 630 AttrChangeType aChangeType = AttrChangeType_MODIFICATION; 631 ::boost::shared_ptr<xmlChar const> const pOld( 632 xmlGetProp(m_aNodePtr, xName), xmlFree); 633 if( !bool(pOld)) { 634 aChangeType = AttrChangeType_ADDITION; 635 xmlNewProp(m_aNodePtr, xName, xValue); 636 } else { 637 oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), 638 strlen(reinterpret_cast<char const*>(pOld.get())), 639 RTL_TEXTENCODING_UTF8); 640 xmlSetProp(m_aNodePtr, xName, xValue); 641 } 642 643 // dispatch DOMAttrModified event 644 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); 645 Reference< XMutationEvent > event(docevent->createEvent( 646 OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); 647 event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), 648 sal_True, sal_False, 649 Reference< XNode >(getAttributeNode(name), UNO_QUERY), 650 oldValue, value, name, aChangeType); 651 652 guard.clear(); // release mutex before calling event handlers 653 dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); 654 dispatchSubtreeModified(); 655 } 656 657 /** 658 Adds a new attribute. 659 */ 660 void SAL_CALL setAttributeNS(OUString const & namespaceURI,OUString const & qualifiedName,OUString const & value)661 CElement::setAttributeNS(OUString const& namespaceURI, 662 OUString const& qualifiedName, OUString const& value) 663 throw (RuntimeException, DOMException) 664 { 665 if (namespaceURI.getLength() == 0) throw RuntimeException(); 666 667 ::osl::ClearableMutexGuard guard(m_rMutex); 668 669 OString o1, o2, o3, o4, o5; 670 xmlChar *xPrefix = NULL; 671 xmlChar *xLName = NULL; 672 o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8); 673 xmlChar *xQName = (xmlChar*)o1.getStr(); 674 sal_Int32 idx = qualifiedName.indexOf(':'); 675 if (idx != -1) 676 { 677 o2 = OUStringToOString( 678 qualifiedName.copy(0,idx), 679 RTL_TEXTENCODING_UTF8); 680 xPrefix = (xmlChar*)o2.getStr(); 681 o3 = OUStringToOString( 682 qualifiedName.copy(idx+1), 683 RTL_TEXTENCODING_UTF8); 684 xLName = (xmlChar*)o3.getStr(); 685 } else { 686 xPrefix = (xmlChar*)""; 687 xLName = xQName; 688 } 689 o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); 690 o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); 691 xmlChar *xURI= (xmlChar*)o4.getStr(); 692 xmlChar *xValue = (xmlChar*)o5.getStr(); 693 694 if (0 == m_aNodePtr) { 695 throw RuntimeException(); 696 } 697 698 //find the right namespace 699 xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix); 700 // if no namespace found, create a new one 701 if (pNs == NULL) { 702 pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix); 703 } 704 705 if (strcmp((char*)pNs->href, (char*)xURI) != 0) { 706 // ambiguous ns prefix 707 throw RuntimeException(); 708 } 709 710 // found namespace matches 711 712 OUString oldValue; 713 AttrChangeType aChangeType = AttrChangeType_MODIFICATION; 714 ::boost::shared_ptr<xmlChar const> const pOld( 715 xmlGetNsProp(m_aNodePtr, xLName, pNs->href), xmlFree); 716 if( !bool(pOld)) { 717 aChangeType = AttrChangeType_ADDITION; 718 xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue); 719 } else { 720 oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), 721 strlen(reinterpret_cast<char const*>(pOld.get())), 722 RTL_TEXTENCODING_UTF8); 723 xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue); 724 } 725 // dispatch DOMAttrModified event 726 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); 727 Reference< XMutationEvent > event(docevent->createEvent( 728 OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); 729 event->initMutationEvent( 730 OUString::createFromAscii("DOMAttrModified"), 731 sal_True, sal_False, 732 Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY), 733 oldValue, value, qualifiedName, aChangeType); 734 735 guard.clear(); // release mutex before calling event handlers 736 dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); 737 dispatchSubtreeModified(); 738 } 739 740 Reference< XNamedNodeMap > SAL_CALL getAttributes()741 CElement::getAttributes() throw (RuntimeException) 742 { 743 ::osl::MutexGuard const g(m_rMutex); 744 745 Reference< XNamedNodeMap > const xMap( 746 new CAttributesMap(this, m_rMutex)); 747 return xMap; 748 } 749 getNodeName()750 OUString SAL_CALL CElement::getNodeName()throw (RuntimeException) 751 { 752 return getLocalName(); 753 } 754 getLocalName()755 OUString SAL_CALL CElement::getLocalName()throw (RuntimeException) 756 { 757 ::osl::MutexGuard const g(m_rMutex); 758 759 OUString aName; 760 if (m_aNodePtr != NULL) 761 { 762 const xmlChar* xName = m_aNodePtr->name; 763 aName = OUString((const sal_Char*)xName, strlen((const char*)xName), RTL_TEXTENCODING_UTF8); 764 } 765 return aName; 766 } 767 getNodeValue()768 OUString SAL_CALL CElement::getNodeValue() throw (RuntimeException) 769 { 770 return OUString(); 771 } 772 setElementName(const OUString & aName)773 void SAL_CALL CElement::setElementName(const OUString& aName) 774 throw (RuntimeException, DOMException) 775 { 776 if ((aName.getLength() <= 0) || 777 (0 <= aName.indexOf(OUString::createFromAscii(":")))) 778 { 779 DOMException e; 780 e.Code = DOMExceptionType_INVALID_CHARACTER_ERR; 781 throw e; 782 } 783 784 ::osl::MutexGuard const g(m_rMutex); 785 786 if (0 == m_aNodePtr) { 787 throw RuntimeException(); 788 } 789 OString oName = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); 790 xmlChar *xName = (xmlChar*)oName.getStr(); 791 xmlNodeSetName(m_aNodePtr, xName); 792 } 793 794 } 795