Bump version to 6.4-15
[LibreOffice.git] / unoxml / source / dom / element.cxx
blobe5e82b2613cd1d3734a46fe18e9c6f552c91ffc4
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>
32 #include <comphelper/servicehelper.hxx>
34 #include <node.hxx>
35 #include "attr.hxx"
36 #include "elementlist.hxx"
37 #include "attributesmap.hxx"
38 #include "document.hxx"
40 #include <mutationevent.hxx>
42 using namespace css::uno;
43 using namespace css::xml::dom;
44 using namespace css::xml::dom::events;
45 using namespace css::xml::sax;
47 namespace DOM
50 CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex,
51 xmlNodePtr const pNode)
52 : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode)
56 void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler)
58 if (!i_xHandler.is()) throw RuntimeException();
59 comphelper::AttributeList *pAttrs =
60 new comphelper::AttributeList();
61 OUString type = "";
62 // add namespace definitions to attributes
63 for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != nullptr; pNs = pNs->next) {
64 const xmlChar *pPrefix = pNs->prefix ? pNs->prefix : reinterpret_cast<const xmlChar*>("");
65 OUString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
66 strlen(reinterpret_cast<const char*>(pPrefix)),
67 RTL_TEXTENCODING_UTF8);
68 OUString name = (prefix.isEmpty())
69 ? OUString( "xmlns" ) : "xmlns:" + prefix;
70 const xmlChar *pHref = pNs->href;
71 OUString val(reinterpret_cast<const sal_Char*>(pHref),
72 strlen(reinterpret_cast<const char*>(pHref)),
73 RTL_TEXTENCODING_UTF8);
74 pAttrs->AddAttribute(name, type, val);
76 // add attributes
77 for (xmlAttrPtr pAttr = m_aNodePtr->properties;
78 pAttr != nullptr; pAttr = pAttr->next) {
79 ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
80 reinterpret_cast<xmlNodePtr>(pAttr));
81 OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
82 OUString prefix = pNode->getPrefix();
83 OUString name = (prefix.isEmpty())
84 ? pNode->getLocalName()
85 : prefix + ":" + pNode->getLocalName();
86 OUString val = pNode->getNodeValue();
87 pAttrs->AddAttribute(name, type, val);
89 OUString prefix = getPrefix();
90 OUString name = (prefix.isEmpty())
91 ? getLocalName()
92 : prefix + ":" + getLocalName();
93 Reference< XAttributeList > xAttrList(pAttrs);
94 i_xHandler->startElement(name, xAttrList);
95 // recurse
96 for (xmlNodePtr pChild = m_aNodePtr->children;
97 pChild != nullptr; pChild = pChild->next) {
98 ::rtl::Reference<CNode> const pNode(
99 GetOwnerDocument().GetCNode(pChild));
100 OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
101 pNode->saxify(i_xHandler);
103 i_xHandler->endElement(name);
106 void CElement::fastSaxify( Context& i_rContext )
108 if (!i_rContext.mxDocHandler.is()) throw RuntimeException();
109 pushContext(i_rContext);
110 addNamespaces(i_rContext,m_aNodePtr);
112 // add attributes
113 i_rContext.mxAttribList->clear();
114 for (xmlAttrPtr pAttr = m_aNodePtr->properties;
115 pAttr != nullptr; pAttr = pAttr->next) {
116 ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
117 reinterpret_cast<xmlNodePtr>(pAttr));
118 OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
120 const xmlChar* pName = pAttr->name;
121 sal_Int32 nAttributeToken=FastToken::DONTKNOW;
123 if( pAttr->ns && strlen(reinterpret_cast<char const *>(pAttr->ns->prefix)) )
124 nAttributeToken = getTokenWithPrefix( i_rContext,
125 reinterpret_cast<char const *>(pAttr->ns->prefix),
126 reinterpret_cast<char const *>(pName) );
127 else
128 nAttributeToken = getToken( i_rContext, reinterpret_cast<char const *>(pName) );
130 if( nAttributeToken != FastToken::DONTKNOW )
131 i_rContext.mxAttribList->add( nAttributeToken,
132 OUStringToOString(pNode->getNodeValue(),
133 RTL_TEXTENCODING_UTF8));
136 const xmlChar* pPrefix = (m_aNodePtr->ns && m_aNodePtr->ns->prefix) ? m_aNodePtr->ns->prefix : reinterpret_cast<const xmlChar*>("");
137 const xmlChar* pName = m_aNodePtr->name;
138 sal_Int32 nElementToken=FastToken::DONTKNOW;
139 if( strlen(reinterpret_cast<char const *>(pPrefix)) )
140 nElementToken = getTokenWithPrefix( i_rContext, reinterpret_cast<char const *>(pPrefix), reinterpret_cast<char const *>(pName) );
141 else
142 nElementToken = getToken( i_rContext, reinterpret_cast<char const *>(pName) );
144 Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler);
147 Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList.get() );
148 if( nElementToken == FastToken::DONTKNOW )
150 const OUString aNamespace;
151 const OUString aElementName( reinterpret_cast<char const *>(pPrefix),
152 strlen(reinterpret_cast<char const *>(pPrefix)),
153 RTL_TEXTENCODING_UTF8 );
155 if( xParentHandler.is() )
156 i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
157 else
158 i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
160 if( i_rContext.mxCurrentHandler.is() )
161 i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr );
163 else
165 if( xParentHandler.is() )
166 i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr );
167 else
168 i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr );
170 if( i_rContext.mxCurrentHandler.is() )
171 i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr );
174 catch( Exception& )
177 // recurse
178 for (xmlNodePtr pChild = m_aNodePtr->children;
179 pChild != nullptr; pChild = pChild->next) {
180 ::rtl::Reference<CNode> const pNode(
181 GetOwnerDocument().GetCNode(pChild));
182 OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
183 pNode->fastSaxify(i_rContext);
186 if( i_rContext.mxCurrentHandler.is() ) try
188 if( nElementToken != FastToken::DONTKNOW )
189 i_rContext.mxCurrentHandler->endFastElement( nElementToken );
190 else
192 const OUString aNamespace;
193 const OUString aElementName( reinterpret_cast<char const *>(pPrefix),
194 strlen(reinterpret_cast<char const *>(pPrefix)),
195 RTL_TEXTENCODING_UTF8 );
197 i_rContext.mxCurrentHandler->endUnknownElement( aNamespace, aElementName );
200 catch( Exception& )
203 // restore after children have been processed
204 i_rContext.mxCurrentHandler = xParentHandler;
205 popContext(i_rContext);
208 bool CElement::IsChildTypeAllowed(NodeType const nodeType)
210 switch (nodeType) {
211 case NodeType_ELEMENT_NODE:
212 case NodeType_TEXT_NODE:
213 case NodeType_COMMENT_NODE:
214 case NodeType_PROCESSING_INSTRUCTION_NODE:
215 case NodeType_CDATA_SECTION_NODE:
216 case NodeType_ENTITY_REFERENCE_NODE:
217 return true;
218 case NodeType_ATTRIBUTE_NODE:
219 /* this is not really allowed by the DOM spec, but this
220 implementation has evidently supported it (by special case
221 handling, so the attribute does not actually become a child)
222 so allow it for backward compatibility */
223 return true;
224 default:
225 return false;
231 Retrieves an attribute value by name.
232 return empty string if attribute is not set
234 OUString SAL_CALL CElement::getAttribute(OUString const& name)
236 ::osl::MutexGuard const g(m_rMutex);
238 if (nullptr == m_aNodePtr) {
239 return OUString();
241 // search properties
242 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
243 std::shared_ptr<xmlChar const> const pValue(
244 xmlGetProp(m_aNodePtr, reinterpret_cast<xmlChar const *>(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;
254 Retrieves an attribute node by name.
256 Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name)
258 ::osl::MutexGuard const g(m_rMutex);
260 if (nullptr == m_aNodePtr) {
261 return nullptr;
263 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
264 xmlChar const*const pName =
265 reinterpret_cast<xmlChar const*>(o1.getStr());
266 xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
267 if (nullptr == pAttr) {
268 return nullptr;
270 Reference< XAttr > const xRet(
271 static_cast< XNode* >(GetOwnerDocument().GetCNode(
272 reinterpret_cast<xmlNodePtr>(pAttr)).get()),
273 UNO_QUERY_THROW);
274 return xRet;
278 Retrieves an Attr node by local name and namespace URI.
280 Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS(
281 const OUString& namespaceURI, const OUString& localName)
283 ::osl::MutexGuard const g(m_rMutex);
285 if (nullptr == m_aNodePtr) {
286 return nullptr;
288 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
289 xmlChar const*const pName =
290 reinterpret_cast<xmlChar const*>(o1.getStr());
291 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
292 xmlChar const*const pNS =
293 reinterpret_cast<xmlChar const*>(o2.getStr());
294 xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS);
295 if (nullptr == pAttr) {
296 return nullptr;
298 Reference< XAttr > const xRet(
299 static_cast< XNode* >(GetOwnerDocument().GetCNode(
300 reinterpret_cast<xmlNodePtr>(pAttr)).get()),
301 UNO_QUERY_THROW);
302 return xRet;
306 Retrieves an attribute value by local name and namespace URI.
307 return empty string if attribute is not set
309 OUString SAL_CALL
310 CElement::getAttributeNS(
311 OUString const& namespaceURI, OUString const& localName)
313 ::osl::MutexGuard const g(m_rMutex);
315 if (nullptr == m_aNodePtr) {
316 return OUString();
318 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
319 xmlChar const*const pName =
320 reinterpret_cast<xmlChar const*>(o1.getStr());
321 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
322 xmlChar const*const pNS =
323 reinterpret_cast<xmlChar const*>(o2.getStr());
324 std::shared_ptr<xmlChar const> const pValue(
325 xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree);
326 if (nullptr == pValue) {
327 return OUString();
329 OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()),
330 strlen(reinterpret_cast<char const*>(pValue.get())),
331 RTL_TEXTENCODING_UTF8);
332 return ret;
336 Returns a NodeList of all descendant Elements with a given tag name,
337 in the order in which they are
338 encountered in a preorder traversal of this Element tree.
340 Reference< XNodeList > SAL_CALL
341 CElement::getElementsByTagName(OUString const& rLocalName)
343 ::osl::MutexGuard const g(m_rMutex);
345 Reference< XNodeList > const xList(
346 new CElementList(this, m_rMutex, rLocalName));
347 return xList;
351 Returns a NodeList of all the descendant Elements with a given local
352 name and namespace URI in the order in which they are encountered in
353 a preorder traversal of this Element tree.
355 Reference< XNodeList > SAL_CALL
356 CElement::getElementsByTagNameNS(
357 OUString const& rNamespaceURI, OUString const& rLocalName)
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()
371 ::osl::MutexGuard const g(m_rMutex);
373 if (nullptr == m_aNodePtr) {
374 return OUString();
376 OUString const ret(reinterpret_cast<char const *>(m_aNodePtr->name),
377 strlen(reinterpret_cast<char const *>(m_aNodePtr->name)), RTL_TEXTENCODING_UTF8);
378 return ret;
383 Returns true when an attribute with a given name is specified on this
384 element or has a default value, false otherwise.
386 sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name)
388 ::osl::MutexGuard const g(m_rMutex);
390 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
391 xmlChar const *pName = reinterpret_cast<xmlChar const *>(o1.getStr());
392 return (m_aNodePtr != nullptr && xmlHasProp(m_aNodePtr, pName) != nullptr);
396 Returns true when an attribute with a given local name and namespace
397 URI is specified on this element or has a default value, false otherwise.
399 sal_Bool SAL_CALL CElement::hasAttributeNS(
400 OUString const& namespaceURI, OUString const& localName)
402 ::osl::MutexGuard const g(m_rMutex);
404 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
405 xmlChar const *pName = reinterpret_cast<xmlChar const *>(o1.getStr());
406 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
407 xmlChar const *pNs = reinterpret_cast<xmlChar const *>(o2.getStr());
408 return (m_aNodePtr != nullptr && xmlHasNsProp(m_aNodePtr, pName, pNs) != nullptr);
412 Removes an attribute by name.
414 void SAL_CALL CElement::removeAttribute(OUString const& name)
416 ::osl::MutexGuard const g(m_rMutex);
418 if (nullptr == m_aNodePtr) {
419 return;
421 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
422 xmlChar const*const pName =
423 reinterpret_cast<xmlChar const*>(o1.getStr());
424 xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
425 if (0 == xmlUnsetProp(m_aNodePtr, pName)) {
426 ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
427 reinterpret_cast<xmlNodePtr>(pAttr), false));
428 if (pCNode.is()) {
429 pCNode->invalidate(); // freed by xmlUnsetProp
435 Removes an attribute by local name and namespace URI.
437 void SAL_CALL CElement::removeAttributeNS(
438 OUString const& namespaceURI, OUString const& localName)
440 ::osl::MutexGuard const g(m_rMutex);
442 if (nullptr == m_aNodePtr) {
443 return;
445 OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
446 xmlChar const*const pName =
447 reinterpret_cast<xmlChar const*>(o1.getStr());
448 OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
449 xmlChar const*const pURI =
450 reinterpret_cast<xmlChar const*>(o2.getStr());
451 xmlNsPtr const pNs =
452 xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI);
453 xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI);
454 if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) {
455 ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
456 reinterpret_cast<xmlNodePtr>(pAttr), false));
457 if (pCNode.is()) {
458 pCNode->invalidate(); // freed by xmlUnsetNsProp
464 Removes the specified attribute node.
466 Reference< XAttr > SAL_CALL
467 CElement::removeAttributeNode(Reference< XAttr > const& oldAttr)
469 ::osl::MutexGuard const g(m_rMutex);
471 if (nullptr == m_aNodePtr) {
472 return nullptr;
475 ::rtl::Reference<CNode> const pCNode(
476 comphelper::getUnoTunnelImplementation<CNode>(Reference<XNode>(oldAttr.get())));
477 if (!pCNode.is()) { throw RuntimeException(); }
479 xmlNodePtr const pNode = pCNode->GetNodePtr();
480 xmlAttrPtr const pAttr = reinterpret_cast<xmlAttrPtr>(pNode);
481 if (!pAttr) { throw RuntimeException(); }
483 if (pAttr->parent != m_aNodePtr)
485 DOMException e;
486 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
487 throw e;
489 if (pAttr->doc != m_aNodePtr->doc)
491 DOMException e;
492 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
493 throw e;
496 Reference< XAttr > aAttr;
497 if (!oldAttr->getNamespaceURI().isEmpty()) {
498 OUStringBuffer qname(oldAttr->getPrefix());
499 if (!qname.isEmpty()) {
500 qname.append(':');
502 qname.append(oldAttr->getName());
503 aAttr = GetOwnerDocument().createAttributeNS(
504 oldAttr->getNamespaceURI(), qname.makeStringAndClear());
505 } else {
506 aAttr = GetOwnerDocument().createAttribute(oldAttr->getName());
508 aAttr->setValue(oldAttr->getValue());
509 xmlRemoveProp(pAttr);
510 pCNode->invalidate(); // freed by xmlRemoveProp
512 return aAttr;
516 Adds a new attribute node.
518 Reference< XAttr >
519 CElement::setAttributeNode_Impl_Lock(
520 Reference< XAttr > const& xNewAttr, bool const bNS)
522 if (xNewAttr->getOwnerDocument() != getOwnerDocument()) {
523 DOMException e;
524 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
525 throw e;
528 ::osl::ClearableMutexGuard guard(m_rMutex);
530 if (nullptr == m_aNodePtr) {
531 throw RuntimeException();
534 // get the implementation
535 CAttr *const pCAttr = dynamic_cast<CAttr*>(
536 comphelper::getUnoTunnelImplementation<CNode>(xNewAttr));
537 if (!pCAttr) { throw RuntimeException(); }
538 xmlAttrPtr const pAttr =
539 reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr());
540 if (!pAttr) { throw RuntimeException(); }
542 // check whether the attribute is not in use by another element
543 if (pAttr->parent) {
544 DOMException e;
545 e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR;
546 throw e;
549 xmlAttrPtr res = nullptr;
550 xmlChar const*const pContent(
551 (pAttr->children) ? pAttr->children->content : nullptr);
553 if (bNS) {
554 xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
555 res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent);
556 } else {
557 res = xmlNewProp(m_aNodePtr, pAttr->name, pContent);
560 // get the new attr node
561 Reference< XAttr > const xAttr(
562 static_cast< XNode* >(GetOwnerDocument().GetCNode(
563 reinterpret_cast<xmlNodePtr>(res)).get()),
564 UNO_QUERY_THROW);
566 // attribute addition event
567 // dispatch DOMAttrModified event
568 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
569 Reference< XMutationEvent > event(docevent->createEvent(
570 "DOMAttrModified"), UNO_QUERY);
571 event->initMutationEvent("DOMAttrModified",
572 true, false, xAttr,
573 OUString(), xAttr->getValue(), xAttr->getName(),
574 AttrChangeType_ADDITION);
576 guard.clear(); // release mutex before calling event handlers
578 dispatchEvent(event);
579 dispatchSubtreeModified();
581 return xAttr;
584 Reference< XAttr >
585 CElement::setAttributeNode(const Reference< XAttr >& newAttr)
587 return setAttributeNode_Impl_Lock(newAttr, false);
591 Adds a new attribute.
593 Reference< XAttr >
594 CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr)
596 return setAttributeNode_Impl_Lock(newAttr, true);
600 Adds a new attribute.
602 void SAL_CALL
603 CElement::setAttribute(OUString const& name, OUString const& value)
605 ::osl::ClearableMutexGuard guard(m_rMutex);
607 OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
608 xmlChar const *pName = reinterpret_cast<xmlChar const *>(o1.getStr());
609 OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
610 xmlChar const *pValue = reinterpret_cast<xmlChar const *>(o2.getStr());
612 if (nullptr == m_aNodePtr) {
613 throw RuntimeException();
615 OUString oldValue;
616 AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
617 std::shared_ptr<xmlChar const> const pOld(
618 xmlGetProp(m_aNodePtr, pName), xmlFree);
619 if (pOld == nullptr) {
620 aChangeType = AttrChangeType_ADDITION;
621 xmlNewProp(m_aNodePtr, pName, pValue);
622 } else {
623 oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
624 strlen(reinterpret_cast<char const*>(pOld.get())),
625 RTL_TEXTENCODING_UTF8);
626 xmlSetProp(m_aNodePtr, pName, pValue);
629 // dispatch DOMAttrModified event
630 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
631 Reference< XMutationEvent > event(docevent->createEvent(
632 "DOMAttrModified"), UNO_QUERY);
633 event->initMutationEvent("DOMAttrModified",
634 true, false,
635 getAttributeNode(name),
636 oldValue, value, name, aChangeType);
638 guard.clear(); // release mutex before calling event handlers
639 dispatchEvent(event);
640 dispatchSubtreeModified();
644 Adds a new attribute.
646 void SAL_CALL
647 CElement::setAttributeNS(OUString const& namespaceURI,
648 OUString const& qualifiedName, OUString const& value)
650 if (namespaceURI.isEmpty()) throw RuntimeException();
652 ::osl::ClearableMutexGuard guard(m_rMutex);
654 OString o1, o2, o3, o4, o5;
655 xmlChar const *pPrefix = nullptr;
656 xmlChar const *pLName = nullptr;
657 o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8);
658 xmlChar const *pQName = reinterpret_cast<xmlChar const *>(o1.getStr());
659 sal_Int32 idx = qualifiedName.indexOf(':');
660 if (idx != -1)
662 o2 = OUStringToOString(
663 qualifiedName.copy(0,idx),
664 RTL_TEXTENCODING_UTF8);
665 pPrefix = reinterpret_cast<xmlChar const *>(o2.getStr());
666 o3 = OUStringToOString(
667 qualifiedName.copy(idx+1),
668 RTL_TEXTENCODING_UTF8);
669 pLName = reinterpret_cast<xmlChar const *>(o3.getStr());
670 } else {
671 pPrefix = reinterpret_cast<xmlChar const *>("");
672 pLName = pQName;
674 o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
675 o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
676 xmlChar const *pURI= reinterpret_cast<xmlChar const *>(o4.getStr());
677 xmlChar const *pValue = reinterpret_cast<xmlChar const *>(o5.getStr());
679 if (nullptr == m_aNodePtr) {
680 throw RuntimeException();
683 //find the right namespace
684 xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, pPrefix);
685 // if no namespace found, create a new one
686 if (pNs == nullptr) {
687 pNs = xmlNewNs(m_aNodePtr, pURI, pPrefix);
690 if (strcmp(reinterpret_cast<char const *>(pNs->href), reinterpret_cast<char const *>(pURI)) != 0) {
691 // ambiguous ns prefix
692 throw RuntimeException();
695 // found namespace matches
697 OUString oldValue;
698 AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
699 std::shared_ptr<xmlChar const> const pOld(
700 xmlGetNsProp(m_aNodePtr, pLName, pNs->href), xmlFree);
701 if (pOld == nullptr) {
702 aChangeType = AttrChangeType_ADDITION;
703 xmlNewNsProp(m_aNodePtr, pNs, pLName, pValue);
704 } else {
705 oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
706 strlen(reinterpret_cast<char const*>(pOld.get())),
707 RTL_TEXTENCODING_UTF8);
708 xmlSetNsProp(m_aNodePtr, pNs, pLName, pValue);
710 // dispatch DOMAttrModified event
711 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
712 Reference< XMutationEvent > event(docevent->createEvent(
713 "DOMAttrModified"), UNO_QUERY);
714 event->initMutationEvent(
715 "DOMAttrModified", true, false,
716 getAttributeNodeNS(namespaceURI, OUString(reinterpret_cast<char const *>(pLName), strlen(reinterpret_cast<char const *>(pLName)), RTL_TEXTENCODING_UTF8)),
717 oldValue, value, qualifiedName, aChangeType);
719 guard.clear(); // release mutex before calling event handlers
720 dispatchEvent(event);
721 dispatchSubtreeModified();
724 Reference< XNamedNodeMap > SAL_CALL
725 CElement::getAttributes()
727 ::osl::MutexGuard const g(m_rMutex);
729 Reference< XNamedNodeMap > const xMap(
730 new CAttributesMap(this, m_rMutex));
731 return xMap;
734 OUString SAL_CALL CElement::getNodeName()
736 return getLocalName();
739 OUString SAL_CALL CElement::getLocalName()
741 ::osl::MutexGuard const g(m_rMutex);
743 OUString aName;
744 if (m_aNodePtr != nullptr)
746 const xmlChar* pName = m_aNodePtr->name;
747 aName = OUString(reinterpret_cast<const char*>(pName), strlen(reinterpret_cast<const char*>(pName)), RTL_TEXTENCODING_UTF8);
749 return aName;
752 OUString SAL_CALL CElement::getNodeValue()
754 return OUString();
758 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */