bump product version to 4.1.6.2
[LibreOffice.git] / unoxml / source / dom / element.cxx
blob0149ca972768e50409b13b3dde087adbe2d3c16c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <element.hxx>
22 #include <string.h>
24 #include <boost/shared_ptr.hpp>
26 #include <rtl/ustrbuf.hxx>
28 #include <com/sun/star/xml/sax/FastToken.hpp>
30 #include <comphelper/attributelist.hxx>
32 #include <node.hxx>
33 #include <attr.hxx>
34 #include <elementlist.hxx>
35 #include <attributesmap.hxx>
36 #include <document.hxx>
38 #include "../events/mutationevent.hxx"
41 namespace DOM
44 CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex,
45 xmlNodePtr const pNode)
46 : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode)
50 void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler)
52 if (!i_xHandler.is()) throw RuntimeException();
53 comphelper::AttributeList *pAttrs =
54 new comphelper::AttributeList();
55 OUString type = "";
56 // add namespace definitions to attributes
57 for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != 0; pNs = pNs->next) {
58 const xmlChar *pPrefix = pNs->prefix;
59 OUString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
60 strlen(reinterpret_cast<const char*>(pPrefix)),
61 RTL_TEXTENCODING_UTF8);
62 OUString name = (prefix.isEmpty())
63 ? OUString( "xmlns" ) : OUString( "xmlns:" ) + prefix;
64 const xmlChar *pHref = pNs->href;
65 OUString val(reinterpret_cast<const sal_Char*>(pHref),
66 strlen(reinterpret_cast<const char*>(pHref)),
67 RTL_TEXTENCODING_UTF8);
68 pAttrs->AddAttribute(name, type, val);
70 // add attributes
71 for (xmlAttrPtr pAttr = m_aNodePtr->properties;
72 pAttr != 0; pAttr = pAttr->next) {
73 ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
74 reinterpret_cast<xmlNodePtr>(pAttr));
75 OSL_ENSURE(pNode != 0, "CNode::get returned 0");
76 OUString prefix = pNode->getPrefix();
77 OUString name = (prefix.isEmpty())
78 ? pNode->getLocalName()
79 : prefix + OUString(static_cast<sal_Unicode>(':')) + pNode->getLocalName();
80 OUString val = pNode->getNodeValue();
81 pAttrs->AddAttribute(name, type, val);
83 OUString prefix = getPrefix();
84 OUString name = (prefix.isEmpty())
85 ? getLocalName()
86 : prefix + OUString(static_cast<sal_Unicode>(':')) + getLocalName();
87 Reference< XAttributeList > xAttrList(pAttrs);
88 i_xHandler->startElement(name, xAttrList);
89 // recurse
90 for (xmlNodePtr pChild = m_aNodePtr->children;
91 pChild != 0; pChild = pChild->next) {
92 ::rtl::Reference<CNode> const pNode(
93 GetOwnerDocument().GetCNode(pChild));
94 OSL_ENSURE(pNode != 0, "CNode::get returned 0");
95 pNode->saxify(i_xHandler);
97 i_xHandler->endElement(name);
100 void CElement::fastSaxify( Context& i_rContext )
102 if (!i_rContext.mxDocHandler.is()) throw RuntimeException();
103 pushContext(i_rContext);
104 addNamespaces(i_rContext,m_aNodePtr);
106 // add attributes
107 i_rContext.mxAttribList->clear();
108 for (xmlAttrPtr pAttr = m_aNodePtr->properties;
109 pAttr != 0; pAttr = pAttr->next) {
110 ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
111 reinterpret_cast<xmlNodePtr>(pAttr));
112 OSL_ENSURE(pNode != 0, "CNode::get returned 0");
114 const xmlChar* xName = pAttr->name;
115 sal_Int32 nAttributeToken=FastToken::DONTKNOW;
117 if( pAttr->ns && strlen((char*)pAttr->ns->prefix) )
118 nAttributeToken = getTokenWithPrefix( i_rContext,
119 (sal_Char*)pAttr->ns->prefix,
120 (sal_Char*)xName );
121 else
122 nAttributeToken = getToken( i_rContext, (sal_Char*)xName );
124 if( nAttributeToken != FastToken::DONTKNOW )
125 i_rContext.mxAttribList->add( nAttributeToken,
126 OUStringToOString(pNode->getNodeValue(),
127 RTL_TEXTENCODING_UTF8));
130 const xmlChar* xPrefix = m_aNodePtr->ns ? m_aNodePtr->ns->prefix : (const xmlChar*)"";
131 const xmlChar* xName = m_aNodePtr->name;
132 sal_Int32 nElementToken=FastToken::DONTKNOW;
133 if( strlen((char*)xPrefix) )
134 nElementToken = getTokenWithPrefix( i_rContext, (sal_Char*)xPrefix, (sal_Char*)xName );
135 else
136 nElementToken = getToken( i_rContext, (sal_Char*)xName );
138 Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler);
141 Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList.get() );
142 if( nElementToken == FastToken::DONTKNOW )
144 const OUString aNamespace;
145 const OUString aElementName( (sal_Char*)xPrefix,
146 strlen((char*)xPrefix),
147 RTL_TEXTENCODING_UTF8 );
149 if( xParentHandler.is() )
150 i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
151 else
152 i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
154 if( i_rContext.mxCurrentHandler.is() )
155 i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr );
157 else
159 if( xParentHandler.is() )
160 i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr );
161 else
162 i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr );
164 if( i_rContext.mxCurrentHandler.is() )
165 i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr );
168 catch( Exception& )
171 // recurse
172 for (xmlNodePtr pChild = m_aNodePtr->children;
173 pChild != 0; pChild = pChild->next) {
174 ::rtl::Reference<CNode> const pNode(
175 GetOwnerDocument().GetCNode(pChild));
176 OSL_ENSURE(pNode != 0, "CNode::get returned 0");
177 pNode->fastSaxify(i_rContext);
180 if( i_rContext.mxCurrentHandler.is() ) try
182 if( nElementToken != FastToken::DONTKNOW )
183 i_rContext.mxCurrentHandler->endFastElement( nElementToken );
184 else
186 const OUString aNamespace;
187 const OUString aElementName( (sal_Char*)xPrefix,
188 strlen((char*)xPrefix),
189 RTL_TEXTENCODING_UTF8 );
191 i_rContext.mxCurrentHandler->endUnknownElement( aNamespace, aElementName );
194 catch( Exception& )
197 // restore after children have been processed
198 i_rContext.mxCurrentHandler = xParentHandler;
199 popContext(i_rContext);
202 bool CElement::IsChildTypeAllowed(NodeType const nodeType)
204 switch (nodeType) {
205 case NodeType_ELEMENT_NODE:
206 case NodeType_TEXT_NODE:
207 case NodeType_COMMENT_NODE:
208 case NodeType_PROCESSING_INSTRUCTION_NODE:
209 case NodeType_CDATA_SECTION_NODE:
210 case NodeType_ENTITY_REFERENCE_NODE:
211 return true;
212 case NodeType_ATTRIBUTE_NODE:
213 /* this is not relly allowed by the DOM spec, but this
214 implementation has evidently supported it (by special case
215 handling, so the attribute does not actually become a child)
216 so allow it for backward compatiblity */
217 return true;
218 default:
219 return false;
225 Retrieves an attribute value by name.
226 return empty string if attribute is not set
228 OUString SAL_CALL CElement::getAttribute(OUString const& name)
229 throw (RuntimeException)
231 ::osl::MutexGuard const g(m_rMutex);
233 if (0 == m_aNodePtr) {
234 return OUString();
236 // search properties
237 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
238 ::boost::shared_ptr<xmlChar const> const pValue(
239 xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()), xmlFree);
240 OUString const ret( (pValue)
241 ? OUString(reinterpret_cast<sal_Char const*>(pValue.get()),
242 strlen(reinterpret_cast<char const*>(pValue.get())),
243 RTL_TEXTENCODING_UTF8)
244 : OUString() );
245 return ret;
249 Retrieves an attribute node by name.
251 Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name)
252 throw (RuntimeException)
254 ::osl::MutexGuard const g(m_rMutex);
256 if (0 == m_aNodePtr) {
257 return 0;
259 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
260 xmlChar const*const pName =
261 reinterpret_cast<xmlChar const*>(o1.getStr());
262 xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
263 if (0 == pAttr) {
264 return 0;
266 Reference< XAttr > const xRet(
267 static_cast< XNode* >(GetOwnerDocument().GetCNode(
268 reinterpret_cast<xmlNodePtr>(pAttr)).get()),
269 UNO_QUERY_THROW);
270 return xRet;
274 Retrieves an Attr node by local name and namespace URI.
276 Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS(
277 const OUString& namespaceURI, const OUString& localName)
278 throw (RuntimeException)
280 ::osl::MutexGuard const g(m_rMutex);
282 if (0 == m_aNodePtr) {
283 return 0;
285 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
286 xmlChar const*const pName =
287 reinterpret_cast<xmlChar const*>(o1.getStr());
288 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
289 xmlChar const*const pNS =
290 reinterpret_cast<xmlChar const*>(o2.getStr());
291 xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS);
292 if (0 == pAttr) {
293 return 0;
295 Reference< XAttr > const xRet(
296 static_cast< XNode* >(GetOwnerDocument().GetCNode(
297 reinterpret_cast<xmlNodePtr>(pAttr)).get()),
298 UNO_QUERY_THROW);
299 return xRet;
303 Retrieves an attribute value by local name and namespace URI.
304 return empty string if attribute is not set
306 OUString SAL_CALL
307 CElement::getAttributeNS(
308 OUString const& namespaceURI, OUString const& localName)
309 throw (RuntimeException)
311 ::osl::MutexGuard const g(m_rMutex);
313 if (0 == m_aNodePtr) {
314 return OUString();
316 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
317 xmlChar const*const pName =
318 reinterpret_cast<xmlChar const*>(o1.getStr());
319 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
320 xmlChar const*const pNS =
321 reinterpret_cast<xmlChar const*>(o2.getStr());
322 ::boost::shared_ptr<xmlChar const> const pValue(
323 xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree);
324 if (0 == pValue) {
325 return OUString();
327 OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()),
328 strlen(reinterpret_cast<char const*>(pValue.get())),
329 RTL_TEXTENCODING_UTF8);
330 return ret;
334 Returns a NodeList of all descendant Elements with a given tag name,
335 in the order in which they are
336 encountered in a preorder traversal of this Element tree.
338 Reference< XNodeList > SAL_CALL
339 CElement::getElementsByTagName(OUString const& rLocalName)
340 throw (RuntimeException)
342 ::osl::MutexGuard const g(m_rMutex);
344 Reference< XNodeList > const xList(
345 new CElementList(this, m_rMutex, rLocalName));
346 return xList;
350 Returns a NodeList of all the descendant Elements with a given local
351 name and namespace URI in the order in which they are encountered in
352 a preorder traversal of this Element tree.
354 Reference< XNodeList > SAL_CALL
355 CElement::getElementsByTagNameNS(
356 OUString const& rNamespaceURI, OUString const& rLocalName)
357 throw (RuntimeException)
359 ::osl::MutexGuard const g(m_rMutex);
361 Reference< XNodeList > const xList(
362 new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI));
363 return xList;
367 The name of the element.
369 OUString SAL_CALL CElement::getTagName()
370 throw (RuntimeException)
372 ::osl::MutexGuard const g(m_rMutex);
374 if (0 == m_aNodePtr) {
375 return OUString();
377 OUString const ret((sal_Char*)m_aNodePtr->name,
378 strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8);
379 return ret;
384 Returns true when an attribute with a given name is specified on this
385 element or has a default value, false otherwise.
387 sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name)
388 throw (RuntimeException)
390 ::osl::MutexGuard const g(m_rMutex);
392 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
393 xmlChar *xName = (xmlChar*)o1.getStr();
394 return (m_aNodePtr != NULL && xmlHasProp(m_aNodePtr, xName) != NULL);
398 Returns true when an attribute with a given local name and namespace
399 URI is specified on this element or has a default value, false otherwise.
401 sal_Bool SAL_CALL CElement::hasAttributeNS(
402 OUString const& namespaceURI, OUString const& localName)
403 throw (RuntimeException)
405 ::osl::MutexGuard const g(m_rMutex);
407 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
408 xmlChar *xName = (xmlChar*)o1.getStr();
409 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
410 xmlChar *xNs = (xmlChar*)o2.getStr();
411 return (m_aNodePtr != NULL && xmlHasNsProp(m_aNodePtr, xName, xNs) != NULL);
415 Removes an attribute by name.
417 void SAL_CALL CElement::removeAttribute(OUString const& name)
418 throw (RuntimeException, DOMException)
420 ::osl::MutexGuard const g(m_rMutex);
422 if (0 == m_aNodePtr) {
423 return;
425 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
426 xmlChar const*const pName =
427 reinterpret_cast<xmlChar const*>(o1.getStr());
428 xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
429 if (0 == xmlUnsetProp(m_aNodePtr, pName)) {
430 ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
431 reinterpret_cast<xmlNodePtr>(pAttr), false));
432 if (pCNode.is()) {
433 pCNode->invalidate(); // freed by xmlUnsetProp
439 Removes an attribute by local name and namespace URI.
441 void SAL_CALL CElement::removeAttributeNS(
442 OUString const& namespaceURI, OUString const& localName)
443 throw (RuntimeException, DOMException)
445 ::osl::MutexGuard const g(m_rMutex);
447 if (0 == m_aNodePtr) {
448 return;
450 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
451 xmlChar const*const pName =
452 reinterpret_cast<xmlChar const*>(o1.getStr());
453 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
454 xmlChar const*const pURI =
455 reinterpret_cast<xmlChar const*>(o2.getStr());
456 xmlNsPtr const pNs =
457 xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI);
458 xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI);
459 if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) {
460 ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
461 reinterpret_cast<xmlNodePtr>(pAttr), false));
462 if (pCNode.is()) {
463 pCNode->invalidate(); // freed by xmlUnsetNsProp
469 Removes the specified attribute node.
471 Reference< XAttr > SAL_CALL
472 CElement::removeAttributeNode(Reference< XAttr > const& oldAttr)
473 throw (RuntimeException, DOMException)
475 ::osl::MutexGuard const g(m_rMutex);
477 if (0 == m_aNodePtr) {
478 return 0;
481 ::rtl::Reference<CNode> const pCNode(
482 CNode::GetImplementation(Reference<XNode>(oldAttr.get())));
483 if (!pCNode.is()) { throw RuntimeException(); }
485 xmlNodePtr const pNode = pCNode->GetNodePtr();
486 xmlAttrPtr const pAttr = (xmlAttrPtr) pNode;
487 if (!pAttr) { throw RuntimeException(); }
489 if (pAttr->parent != m_aNodePtr)
491 DOMException e;
492 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
493 throw e;
495 if (pAttr->doc != m_aNodePtr->doc)
497 DOMException e;
498 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
499 throw e;
502 Reference< XAttr > aAttr;
503 if (!oldAttr->getNamespaceURI().isEmpty()) {
504 OUStringBuffer qname(oldAttr->getPrefix());
505 if (0 != qname.getLength()) {
506 qname.append(sal_Unicode(':'));
508 qname.append(oldAttr->getName());
509 aAttr = GetOwnerDocument().createAttributeNS(
510 oldAttr->getNamespaceURI(), qname.makeStringAndClear());
511 } else {
512 aAttr = GetOwnerDocument().createAttribute(oldAttr->getName());
514 aAttr->setValue(oldAttr->getValue());
515 xmlRemoveProp(pAttr);
516 pCNode->invalidate(); // freed by xmlRemoveProp
518 return aAttr;
522 Adds a new attribute node.
524 Reference< XAttr >
525 CElement::setAttributeNode_Impl_Lock(
526 Reference< XAttr > const& xNewAttr, bool const bNS)
528 if (xNewAttr->getOwnerDocument() != getOwnerDocument()) {
529 DOMException e;
530 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
531 throw e;
534 ::osl::ClearableMutexGuard guard(m_rMutex);
536 if (0 == m_aNodePtr) {
537 throw RuntimeException();
540 // get the implementation
541 CAttr *const pCAttr = dynamic_cast<CAttr*>(
542 CNode::GetImplementation(xNewAttr));
543 if (!pCAttr) { throw RuntimeException(); }
544 xmlAttrPtr const pAttr =
545 reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr());
546 if (!pAttr) { throw RuntimeException(); }
548 // check whether the attribute is not in use by another element
549 if (pAttr->parent) {
550 DOMException e;
551 e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR;
552 throw e;
555 xmlAttrPtr res = NULL;
556 xmlChar const*const pContent(
557 (pAttr->children) ? pAttr->children->content : 0);
559 if (bNS) {
560 xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
561 res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent);
562 } else {
563 res = xmlNewProp(m_aNodePtr, pAttr->name, pContent);
566 // get the new attr node
567 Reference< XAttr > const xAttr(
568 static_cast< XNode* >(GetOwnerDocument().GetCNode(
569 reinterpret_cast<xmlNodePtr>(res)).get()),
570 UNO_QUERY_THROW);
572 // attribute addition event
573 // dispatch DOMAttrModified event
574 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
575 Reference< XMutationEvent > event(docevent->createEvent(
576 "DOMAttrModified"), UNO_QUERY);
577 event->initMutationEvent("DOMAttrModified",
578 sal_True, sal_False, Reference< XNode >(xAttr, UNO_QUERY),
579 OUString(), xAttr->getValue(), xAttr->getName(),
580 AttrChangeType_ADDITION);
582 guard.clear(); // release mutex before calling event handlers
584 dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
585 dispatchSubtreeModified();
587 return xAttr;
590 Reference< XAttr >
591 CElement::setAttributeNode(const Reference< XAttr >& newAttr)
592 throw (RuntimeException, DOMException)
594 return setAttributeNode_Impl_Lock(newAttr, false);
598 Adds a new attribute.
600 Reference< XAttr >
601 CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr)
602 throw (RuntimeException, DOMException)
604 return setAttributeNode_Impl_Lock(newAttr, true);
608 Adds a new attribute.
610 void SAL_CALL
611 CElement::setAttribute(OUString const& name, OUString const& value)
612 throw (RuntimeException, DOMException)
614 ::osl::ClearableMutexGuard guard(m_rMutex);
616 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
617 xmlChar *xName = (xmlChar*)o1.getStr();
618 OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
619 xmlChar *xValue = (xmlChar*)o2.getStr();
621 if (0 == m_aNodePtr) {
622 throw RuntimeException();
624 OUString oldValue;
625 AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
626 ::boost::shared_ptr<xmlChar const> const pOld(
627 xmlGetProp(m_aNodePtr, xName), xmlFree);
628 if (pOld == NULL) {
629 aChangeType = AttrChangeType_ADDITION;
630 xmlNewProp(m_aNodePtr, xName, xValue);
631 } else {
632 oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
633 strlen(reinterpret_cast<char const*>(pOld.get())),
634 RTL_TEXTENCODING_UTF8);
635 xmlSetProp(m_aNodePtr, xName, xValue);
638 // dispatch DOMAttrModified event
639 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
640 Reference< XMutationEvent > event(docevent->createEvent(
641 "DOMAttrModified"), UNO_QUERY);
642 event->initMutationEvent("DOMAttrModified",
643 sal_True, sal_False,
644 Reference< XNode >(getAttributeNode(name), UNO_QUERY),
645 oldValue, value, name, aChangeType);
647 guard.clear(); // release mutex before calling event handlers
648 dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
649 dispatchSubtreeModified();
653 Adds a new attribute.
655 void SAL_CALL
656 CElement::setAttributeNS(OUString const& namespaceURI,
657 OUString const& qualifiedName, OUString const& value)
658 throw (RuntimeException, DOMException)
660 if (namespaceURI.isEmpty()) throw RuntimeException();
662 ::osl::ClearableMutexGuard guard(m_rMutex);
664 OString o1, o2, o3, o4, o5;
665 xmlChar *xPrefix = NULL;
666 xmlChar *xLName = NULL;
667 o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8);
668 xmlChar *xQName = (xmlChar*)o1.getStr();
669 sal_Int32 idx = qualifiedName.indexOf(':');
670 if (idx != -1)
672 o2 = OUStringToOString(
673 qualifiedName.copy(0,idx),
674 RTL_TEXTENCODING_UTF8);
675 xPrefix = (xmlChar*)o2.getStr();
676 o3 = OUStringToOString(
677 qualifiedName.copy(idx+1),
678 RTL_TEXTENCODING_UTF8);
679 xLName = (xmlChar*)o3.getStr();
680 } else {
681 xPrefix = (xmlChar*)"";
682 xLName = xQName;
684 o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
685 o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
686 xmlChar *xURI= (xmlChar*)o4.getStr();
687 xmlChar *xValue = (xmlChar*)o5.getStr();
689 if (0 == m_aNodePtr) {
690 throw RuntimeException();
693 //find the right namespace
694 xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix);
695 // if no namespace found, create a new one
696 if (pNs == NULL) {
697 pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix);
700 if (strcmp((char*)pNs->href, (char*)xURI) != 0) {
701 // ambiguous ns prefix
702 throw RuntimeException();
705 // found namespace matches
707 OUString oldValue;
708 AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
709 ::boost::shared_ptr<xmlChar const> const pOld(
710 xmlGetNsProp(m_aNodePtr, xLName, pNs->href), xmlFree);
711 if (pOld == NULL) {
712 aChangeType = AttrChangeType_ADDITION;
713 xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue);
714 } else {
715 oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
716 strlen(reinterpret_cast<char const*>(pOld.get())),
717 RTL_TEXTENCODING_UTF8);
718 xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue);
720 // dispatch DOMAttrModified event
721 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
722 Reference< XMutationEvent > event(docevent->createEvent(
723 "DOMAttrModified"), UNO_QUERY);
724 event->initMutationEvent(
725 "DOMAttrModified", sal_True, sal_False,
726 Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY),
727 oldValue, value, qualifiedName, aChangeType);
729 guard.clear(); // release mutex before calling event handlers
730 dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
731 dispatchSubtreeModified();
734 Reference< XNamedNodeMap > SAL_CALL
735 CElement::getAttributes() throw (RuntimeException)
737 ::osl::MutexGuard const g(m_rMutex);
739 Reference< XNamedNodeMap > const xMap(
740 new CAttributesMap(this, m_rMutex));
741 return xMap;
744 OUString SAL_CALL CElement::getNodeName()throw (RuntimeException)
746 return getLocalName();
749 OUString SAL_CALL CElement::getLocalName()throw (RuntimeException)
751 ::osl::MutexGuard const g(m_rMutex);
753 OUString aName;
754 if (m_aNodePtr != NULL)
756 const xmlChar* xName = m_aNodePtr->name;
757 aName = OUString((const sal_Char*)xName, strlen((const char*)xName), RTL_TEXTENCODING_UTF8);
759 return aName;
762 OUString SAL_CALL CElement::getNodeValue() throw (RuntimeException)
764 return OUString();
767 void SAL_CALL CElement::setElementName(const OUString& aName)
768 throw (RuntimeException, DOMException)
770 if (aName.isEmpty() || (0 <= aName.indexOf(':')))
772 DOMException e;
773 e.Code = DOMExceptionType_INVALID_CHARACTER_ERR;
774 throw e;
777 ::osl::MutexGuard const g(m_rMutex);
779 if (0 == m_aNodePtr) {
780 throw RuntimeException();
782 OString oName = OUStringToOString(aName, RTL_TEXTENCODING_UTF8);
783 xmlChar *xName = (xmlChar*)oName.getStr();
784 xmlNodeSetName(m_aNodePtr, xName);
789 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */