Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / unoxml / source / dom / element.cxx
blobf7cae19fdbdcff8fb5aca4e81b9f731c99d6eae6
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 <memory>
26 #include <osl/diagnose.h>
27 #include <rtl/ustrbuf.hxx>
29 #include <com/sun/star/xml/sax/FastToken.hpp>
31 #include <comphelper/attributelist.hxx>
33 #include <node.hxx>
34 #include "attr.hxx"
35 #include "elementlist.hxx"
36 #include "attributesmap.hxx"
37 #include "document.hxx"
39 #include <mutationevent.hxx>
41 using namespace css::uno;
42 using namespace css::xml::dom;
43 using namespace css::xml::dom::events;
44 using namespace css::xml::sax;
46 namespace DOM
49 CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex,
50 xmlNodePtr const pNode)
51 : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode)
55 void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler)
57 if (!i_xHandler.is()) throw RuntimeException();
58 comphelper::AttributeList *pAttrs =
59 new comphelper::AttributeList();
60 OUString type = "";
61 // add namespace definitions to attributes
62 for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != nullptr; pNs = pNs->next) {
63 const xmlChar *pPrefix = pNs->prefix ? pNs->prefix : reinterpret_cast<const xmlChar*>("");
64 OUString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
65 strlen(reinterpret_cast<const char*>(pPrefix)),
66 RTL_TEXTENCODING_UTF8);
67 OUString name = (prefix.isEmpty())
68 ? OUString( "xmlns" ) : "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);
75 // add attributes
76 for (xmlAttrPtr pAttr = m_aNodePtr->properties;
77 pAttr != nullptr; pAttr = pAttr->next) {
78 ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
79 reinterpret_cast<xmlNodePtr>(pAttr));
80 OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
81 OUString prefix = pNode->getPrefix();
82 OUString name = (prefix.isEmpty())
83 ? pNode->getLocalName()
84 : prefix + ":" + pNode->getLocalName();
85 OUString val = pNode->getNodeValue();
86 pAttrs->AddAttribute(name, type, val);
88 OUString prefix = getPrefix();
89 OUString name = (prefix.isEmpty())
90 ? getLocalName()
91 : prefix + ":" + getLocalName();
92 Reference< XAttributeList > xAttrList(pAttrs);
93 i_xHandler->startElement(name, xAttrList);
94 // recurse
95 for (xmlNodePtr pChild = m_aNodePtr->children;
96 pChild != nullptr; pChild = pChild->next) {
97 ::rtl::Reference<CNode> const pNode(
98 GetOwnerDocument().GetCNode(pChild));
99 OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
100 pNode->saxify(i_xHandler);
102 i_xHandler->endElement(name);
105 void CElement::fastSaxify( Context& i_rContext )
107 if (!i_rContext.mxDocHandler.is()) throw RuntimeException();
108 pushContext(i_rContext);
109 addNamespaces(i_rContext,m_aNodePtr);
111 // add attributes
112 i_rContext.mxAttribList->clear();
113 for (xmlAttrPtr pAttr = m_aNodePtr->properties;
114 pAttr != nullptr; pAttr = pAttr->next) {
115 ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
116 reinterpret_cast<xmlNodePtr>(pAttr));
117 OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
119 const xmlChar* pName = pAttr->name;
120 sal_Int32 nAttributeToken=FastToken::DONTKNOW;
122 if( pAttr->ns && strlen(reinterpret_cast<char const *>(pAttr->ns->prefix)) )
123 nAttributeToken = getTokenWithPrefix( i_rContext,
124 reinterpret_cast<char const *>(pAttr->ns->prefix),
125 reinterpret_cast<char const *>(pName) );
126 else
127 nAttributeToken = getToken( i_rContext, reinterpret_cast<char const *>(pName) );
129 if( nAttributeToken != FastToken::DONTKNOW )
130 i_rContext.mxAttribList->add( nAttributeToken,
131 OUStringToOString(pNode->getNodeValue(),
132 RTL_TEXTENCODING_UTF8));
135 const xmlChar* pPrefix = (m_aNodePtr->ns && m_aNodePtr->ns->prefix) ? m_aNodePtr->ns->prefix : reinterpret_cast<const xmlChar*>("");
136 const xmlChar* pName = m_aNodePtr->name;
137 sal_Int32 nElementToken=FastToken::DONTKNOW;
138 if( strlen(reinterpret_cast<char const *>(pPrefix)) )
139 nElementToken = getTokenWithPrefix( i_rContext, reinterpret_cast<char const *>(pPrefix), reinterpret_cast<char const *>(pName) );
140 else
141 nElementToken = getToken( i_rContext, reinterpret_cast<char const *>(pName) );
143 Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler);
146 Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList.get() );
147 if( nElementToken == FastToken::DONTKNOW )
149 const OUString aNamespace;
150 const OUString aElementName( reinterpret_cast<char const *>(pPrefix),
151 strlen(reinterpret_cast<char const *>(pPrefix)),
152 RTL_TEXTENCODING_UTF8 );
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 );
159 if( i_rContext.mxCurrentHandler.is() )
160 i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr );
162 else
164 if( xParentHandler.is() )
165 i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr );
166 else
167 i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr );
169 if( i_rContext.mxCurrentHandler.is() )
170 i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr );
173 catch( Exception& )
176 // recurse
177 for (xmlNodePtr pChild = m_aNodePtr->children;
178 pChild != nullptr; pChild = pChild->next) {
179 ::rtl::Reference<CNode> const pNode(
180 GetOwnerDocument().GetCNode(pChild));
181 OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
182 pNode->fastSaxify(i_rContext);
185 if( i_rContext.mxCurrentHandler.is() ) try
187 if( nElementToken != FastToken::DONTKNOW )
188 i_rContext.mxCurrentHandler->endFastElement( nElementToken );
189 else
191 const OUString aNamespace;
192 const OUString aElementName( reinterpret_cast<char const *>(pPrefix),
193 strlen(reinterpret_cast<char const *>(pPrefix)),
194 RTL_TEXTENCODING_UTF8 );
196 i_rContext.mxCurrentHandler->endUnknownElement( aNamespace, aElementName );
199 catch( Exception& )
202 // restore after children have been processed
203 i_rContext.mxCurrentHandler = xParentHandler;
204 popContext(i_rContext);
207 bool CElement::IsChildTypeAllowed(NodeType const nodeType)
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 really 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;
230 Retrieves an attribute value by name.
231 return empty string if attribute is not set
233 OUString SAL_CALL CElement::getAttribute(OUString const& name)
235 ::osl::MutexGuard const g(m_rMutex);
237 if (nullptr == m_aNodePtr) {
238 return OUString();
240 // search properties
241 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
242 std::shared_ptr<xmlChar const> const pValue(
243 xmlGetProp(m_aNodePtr, reinterpret_cast<xmlChar const *>(o1.getStr())), xmlFree);
244 OUString const ret( pValue
245 ? OUString(reinterpret_cast<sal_Char const*>(pValue.get()),
246 strlen(reinterpret_cast<char const*>(pValue.get())),
247 RTL_TEXTENCODING_UTF8)
248 : OUString() );
249 return ret;
253 Retrieves an attribute node by name.
255 Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name)
257 ::osl::MutexGuard const g(m_rMutex);
259 if (nullptr == m_aNodePtr) {
260 return nullptr;
262 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
263 xmlChar const*const pName =
264 reinterpret_cast<xmlChar const*>(o1.getStr());
265 xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
266 if (nullptr == pAttr) {
267 return nullptr;
269 Reference< XAttr > const xRet(
270 static_cast< XNode* >(GetOwnerDocument().GetCNode(
271 reinterpret_cast<xmlNodePtr>(pAttr)).get()),
272 UNO_QUERY_THROW);
273 return xRet;
277 Retrieves an Attr node by local name and namespace URI.
279 Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS(
280 const OUString& namespaceURI, const OUString& localName)
282 ::osl::MutexGuard const g(m_rMutex);
284 if (nullptr == m_aNodePtr) {
285 return nullptr;
287 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
288 xmlChar const*const pName =
289 reinterpret_cast<xmlChar const*>(o1.getStr());
290 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
291 xmlChar const*const pNS =
292 reinterpret_cast<xmlChar const*>(o2.getStr());
293 xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS);
294 if (nullptr == pAttr) {
295 return nullptr;
297 Reference< XAttr > const xRet(
298 static_cast< XNode* >(GetOwnerDocument().GetCNode(
299 reinterpret_cast<xmlNodePtr>(pAttr)).get()),
300 UNO_QUERY_THROW);
301 return xRet;
305 Retrieves an attribute value by local name and namespace URI.
306 return empty string if attribute is not set
308 OUString SAL_CALL
309 CElement::getAttributeNS(
310 OUString const& namespaceURI, OUString const& localName)
312 ::osl::MutexGuard const g(m_rMutex);
314 if (nullptr == m_aNodePtr) {
315 return OUString();
317 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
318 xmlChar const*const pName =
319 reinterpret_cast<xmlChar const*>(o1.getStr());
320 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
321 xmlChar const*const pNS =
322 reinterpret_cast<xmlChar const*>(o2.getStr());
323 std::shared_ptr<xmlChar const> const pValue(
324 xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree);
325 if (nullptr == pValue) {
326 return OUString();
328 OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()),
329 strlen(reinterpret_cast<char const*>(pValue.get())),
330 RTL_TEXTENCODING_UTF8);
331 return ret;
335 Returns a NodeList of all descendant Elements with a given tag name,
336 in the order in which they are
337 encountered in a preorder traversal of this Element tree.
339 Reference< XNodeList > SAL_CALL
340 CElement::getElementsByTagName(OUString const& rLocalName)
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)
358 ::osl::MutexGuard const g(m_rMutex);
360 Reference< XNodeList > const xList(
361 new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI));
362 return xList;
366 The name of the element.
368 OUString SAL_CALL CElement::getTagName()
370 ::osl::MutexGuard const g(m_rMutex);
372 if (nullptr == m_aNodePtr) {
373 return OUString();
375 OUString const ret(reinterpret_cast<char const *>(m_aNodePtr->name),
376 strlen(reinterpret_cast<char const *>(m_aNodePtr->name)), RTL_TEXTENCODING_UTF8);
377 return ret;
382 Returns true when an attribute with a given name is specified on this
383 element or has a default value, false otherwise.
385 sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name)
387 ::osl::MutexGuard const g(m_rMutex);
389 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
390 xmlChar const *pName = reinterpret_cast<xmlChar const *>(o1.getStr());
391 return (m_aNodePtr != nullptr && xmlHasProp(m_aNodePtr, pName) != nullptr);
395 Returns true when an attribute with a given local name and namespace
396 URI is specified on this element or has a default value, false otherwise.
398 sal_Bool SAL_CALL CElement::hasAttributeNS(
399 OUString const& namespaceURI, OUString const& localName)
401 ::osl::MutexGuard const g(m_rMutex);
403 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
404 xmlChar const *pName = reinterpret_cast<xmlChar const *>(o1.getStr());
405 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
406 xmlChar const *pNs = reinterpret_cast<xmlChar const *>(o2.getStr());
407 return (m_aNodePtr != nullptr && xmlHasNsProp(m_aNodePtr, pName, pNs) != nullptr);
411 Removes an attribute by name.
413 void SAL_CALL CElement::removeAttribute(OUString const& name)
415 ::osl::MutexGuard const g(m_rMutex);
417 if (nullptr == m_aNodePtr) {
418 return;
420 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
421 xmlChar const*const pName =
422 reinterpret_cast<xmlChar const*>(o1.getStr());
423 xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
424 if (0 == xmlUnsetProp(m_aNodePtr, pName)) {
425 ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
426 reinterpret_cast<xmlNodePtr>(pAttr), false));
427 if (pCNode.is()) {
428 pCNode->invalidate(); // freed by xmlUnsetProp
434 Removes an attribute by local name and namespace URI.
436 void SAL_CALL CElement::removeAttributeNS(
437 OUString const& namespaceURI, OUString const& localName)
439 ::osl::MutexGuard const g(m_rMutex);
441 if (nullptr == m_aNodePtr) {
442 return;
444 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
445 xmlChar const*const pName =
446 reinterpret_cast<xmlChar const*>(o1.getStr());
447 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
448 xmlChar const*const pURI =
449 reinterpret_cast<xmlChar const*>(o2.getStr());
450 xmlNsPtr const pNs =
451 xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI);
452 xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI);
453 if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) {
454 ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
455 reinterpret_cast<xmlNodePtr>(pAttr), false));
456 if (pCNode.is()) {
457 pCNode->invalidate(); // freed by xmlUnsetNsProp
463 Removes the specified attribute node.
465 Reference< XAttr > SAL_CALL
466 CElement::removeAttributeNode(Reference< XAttr > const& oldAttr)
468 ::osl::MutexGuard const g(m_rMutex);
470 if (nullptr == m_aNodePtr) {
471 return nullptr;
474 ::rtl::Reference<CNode> const pCNode(
475 CNode::GetImplementation(Reference<XNode>(oldAttr.get())));
476 if (!pCNode.is()) { throw RuntimeException(); }
478 xmlNodePtr const pNode = pCNode->GetNodePtr();
479 xmlAttrPtr const pAttr = reinterpret_cast<xmlAttrPtr>(pNode);
480 if (!pAttr) { throw RuntimeException(); }
482 if (pAttr->parent != m_aNodePtr)
484 DOMException e;
485 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
486 throw e;
488 if (pAttr->doc != m_aNodePtr->doc)
490 DOMException e;
491 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
492 throw e;
495 Reference< XAttr > aAttr;
496 if (!oldAttr->getNamespaceURI().isEmpty()) {
497 OUStringBuffer qname(oldAttr->getPrefix());
498 if (!qname.isEmpty()) {
499 qname.append(':');
501 qname.append(oldAttr->getName());
502 aAttr = GetOwnerDocument().createAttributeNS(
503 oldAttr->getNamespaceURI(), qname.makeStringAndClear());
504 } else {
505 aAttr = GetOwnerDocument().createAttribute(oldAttr->getName());
507 aAttr->setValue(oldAttr->getValue());
508 xmlRemoveProp(pAttr);
509 pCNode->invalidate(); // freed by xmlRemoveProp
511 return aAttr;
515 Adds a new attribute node.
517 Reference< XAttr >
518 CElement::setAttributeNode_Impl_Lock(
519 Reference< XAttr > const& xNewAttr, bool const bNS)
521 if (xNewAttr->getOwnerDocument() != getOwnerDocument()) {
522 DOMException e;
523 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
524 throw e;
527 ::osl::ClearableMutexGuard guard(m_rMutex);
529 if (nullptr == m_aNodePtr) {
530 throw RuntimeException();
533 // get the implementation
534 CAttr *const pCAttr = dynamic_cast<CAttr*>(
535 CNode::GetImplementation(xNewAttr));
536 if (!pCAttr) { throw RuntimeException(); }
537 xmlAttrPtr const pAttr =
538 reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr());
539 if (!pAttr) { throw RuntimeException(); }
541 // check whether the attribute is not in use by another element
542 if (pAttr->parent) {
543 DOMException e;
544 e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR;
545 throw e;
548 xmlAttrPtr res = nullptr;
549 xmlChar const*const pContent(
550 (pAttr->children) ? pAttr->children->content : nullptr);
552 if (bNS) {
553 xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
554 res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent);
555 } else {
556 res = xmlNewProp(m_aNodePtr, pAttr->name, pContent);
559 // get the new attr node
560 Reference< XAttr > const xAttr(
561 static_cast< XNode* >(GetOwnerDocument().GetCNode(
562 reinterpret_cast<xmlNodePtr>(res)).get()),
563 UNO_QUERY_THROW);
565 // attribute addition event
566 // dispatch DOMAttrModified event
567 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
568 Reference< XMutationEvent > event(docevent->createEvent(
569 "DOMAttrModified"), UNO_QUERY);
570 event->initMutationEvent("DOMAttrModified",
571 true, false, xAttr,
572 OUString(), xAttr->getValue(), xAttr->getName(),
573 AttrChangeType_ADDITION);
575 guard.clear(); // release mutex before calling event handlers
577 dispatchEvent(event);
578 dispatchSubtreeModified();
580 return xAttr;
583 Reference< XAttr >
584 CElement::setAttributeNode(const Reference< XAttr >& newAttr)
586 return setAttributeNode_Impl_Lock(newAttr, false);
590 Adds a new attribute.
592 Reference< XAttr >
593 CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr)
595 return setAttributeNode_Impl_Lock(newAttr, true);
599 Adds a new attribute.
601 void SAL_CALL
602 CElement::setAttribute(OUString const& name, OUString const& value)
604 ::osl::ClearableMutexGuard guard(m_rMutex);
606 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
607 xmlChar const *pName = reinterpret_cast<xmlChar const *>(o1.getStr());
608 OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
609 xmlChar const *pValue = reinterpret_cast<xmlChar const *>(o2.getStr());
611 if (nullptr == m_aNodePtr) {
612 throw RuntimeException();
614 OUString oldValue;
615 AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
616 std::shared_ptr<xmlChar const> const pOld(
617 xmlGetProp(m_aNodePtr, pName), xmlFree);
618 if (pOld == nullptr) {
619 aChangeType = AttrChangeType_ADDITION;
620 xmlNewProp(m_aNodePtr, pName, pValue);
621 } else {
622 oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
623 strlen(reinterpret_cast<char const*>(pOld.get())),
624 RTL_TEXTENCODING_UTF8);
625 xmlSetProp(m_aNodePtr, pName, pValue);
628 // dispatch DOMAttrModified event
629 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
630 Reference< XMutationEvent > event(docevent->createEvent(
631 "DOMAttrModified"), UNO_QUERY);
632 event->initMutationEvent("DOMAttrModified",
633 true, false,
634 Reference< XNode >(getAttributeNode(name), UNO_QUERY),
635 oldValue, value, name, aChangeType);
637 guard.clear(); // release mutex before calling event handlers
638 dispatchEvent(event);
639 dispatchSubtreeModified();
643 Adds a new attribute.
645 void SAL_CALL
646 CElement::setAttributeNS(OUString const& namespaceURI,
647 OUString const& qualifiedName, OUString const& value)
649 if (namespaceURI.isEmpty()) throw RuntimeException();
651 ::osl::ClearableMutexGuard guard(m_rMutex);
653 OString o1, o2, o3, o4, o5;
654 xmlChar const *pPrefix = nullptr;
655 xmlChar const *pLName = nullptr;
656 o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8);
657 xmlChar const *pQName = reinterpret_cast<xmlChar const *>(o1.getStr());
658 sal_Int32 idx = qualifiedName.indexOf(':');
659 if (idx != -1)
661 o2 = OUStringToOString(
662 qualifiedName.copy(0,idx),
663 RTL_TEXTENCODING_UTF8);
664 pPrefix = reinterpret_cast<xmlChar const *>(o2.getStr());
665 o3 = OUStringToOString(
666 qualifiedName.copy(idx+1),
667 RTL_TEXTENCODING_UTF8);
668 pLName = reinterpret_cast<xmlChar const *>(o3.getStr());
669 } else {
670 pPrefix = reinterpret_cast<xmlChar const *>("");
671 pLName = pQName;
673 o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
674 o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
675 xmlChar const *pURI= reinterpret_cast<xmlChar const *>(o4.getStr());
676 xmlChar const *pValue = reinterpret_cast<xmlChar const *>(o5.getStr());
678 if (nullptr == m_aNodePtr) {
679 throw RuntimeException();
682 //find the right namespace
683 xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, pPrefix);
684 // if no namespace found, create a new one
685 if (pNs == nullptr) {
686 pNs = xmlNewNs(m_aNodePtr, pURI, pPrefix);
689 if (strcmp(reinterpret_cast<char const *>(pNs->href), reinterpret_cast<char const *>(pURI)) != 0) {
690 // ambiguous ns prefix
691 throw RuntimeException();
694 // found namespace matches
696 OUString oldValue;
697 AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
698 std::shared_ptr<xmlChar const> const pOld(
699 xmlGetNsProp(m_aNodePtr, pLName, pNs->href), xmlFree);
700 if (pOld == nullptr) {
701 aChangeType = AttrChangeType_ADDITION;
702 xmlNewNsProp(m_aNodePtr, pNs, pLName, pValue);
703 } else {
704 oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
705 strlen(reinterpret_cast<char const*>(pOld.get())),
706 RTL_TEXTENCODING_UTF8);
707 xmlSetNsProp(m_aNodePtr, pNs, pLName, pValue);
709 // dispatch DOMAttrModified event
710 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
711 Reference< XMutationEvent > event(docevent->createEvent(
712 "DOMAttrModified"), UNO_QUERY);
713 event->initMutationEvent(
714 "DOMAttrModified", true, false,
715 Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString(reinterpret_cast<char const *>(pLName), strlen(reinterpret_cast<char const *>(pLName)), RTL_TEXTENCODING_UTF8)), UNO_QUERY),
716 oldValue, value, qualifiedName, aChangeType);
718 guard.clear(); // release mutex before calling event handlers
719 dispatchEvent(event);
720 dispatchSubtreeModified();
723 Reference< XNamedNodeMap > SAL_CALL
724 CElement::getAttributes()
726 ::osl::MutexGuard const g(m_rMutex);
728 Reference< XNamedNodeMap > const xMap(
729 new CAttributesMap(this, m_rMutex));
730 return xMap;
733 OUString SAL_CALL CElement::getNodeName()
735 return getLocalName();
738 OUString SAL_CALL CElement::getLocalName()
740 ::osl::MutexGuard const g(m_rMutex);
742 OUString aName;
743 if (m_aNodePtr != nullptr)
745 const xmlChar* pName = m_aNodePtr->name;
746 aName = OUString(reinterpret_cast<const char*>(pName), strlen(reinterpret_cast<const char*>(pName)), RTL_TEXTENCODING_UTF8);
748 return aName;
751 OUString SAL_CALL CElement::getNodeValue()
753 return OUString();
757 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */