1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
26 #include <osl/diagnose.h>
27 #include <rtl/ustrbuf.hxx>
29 #include <com/sun/star/xml/dom/DOMException.hpp>
30 #include <com/sun/star/xml/dom/events/XMutationEvent.hpp>
31 #include <com/sun/star/xml/sax/FastToken.hpp>
33 #include <comphelper/attributelist.hxx>
34 #include <comphelper/servicehelper.hxx>
38 #include "elementlist.hxx"
39 #include "attributesmap.hxx"
40 #include "document.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
;
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 rtl::Reference
<comphelper::AttributeList
> pAttrs
=
60 new comphelper::AttributeList();
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 char*>(pPrefix
),
65 strlen(reinterpret_cast<const char*>(pPrefix
)),
66 RTL_TEXTENCODING_UTF8
);
67 OUString name
= (prefix
.isEmpty())
68 ? u
"xmlns"_ustr
: "xmlns:" + prefix
;
69 const xmlChar
*pHref
= pNs
->href
;
70 OUString
val(reinterpret_cast<const char*>(pHref
),
71 strlen(reinterpret_cast<const char*>(pHref
)),
72 RTL_TEXTENCODING_UTF8
);
73 pAttrs
->AddAttribute(name
, val
);
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
, val
);
88 OUString prefix
= getPrefix();
89 OUString name
= (prefix
.isEmpty())
91 : prefix
+ ":" + getLocalName();
92 i_xHandler
->startElement(name
, pAttrs
);
94 for (xmlNodePtr pChild
= m_aNodePtr
->children
;
95 pChild
!= nullptr; pChild
= pChild
->next
) {
96 ::rtl::Reference
<CNode
> const pNode(
97 GetOwnerDocument().GetCNode(pChild
));
98 OSL_ENSURE(pNode
!= nullptr, "CNode::get returned 0");
99 pNode
->saxify(i_xHandler
);
101 i_xHandler
->endElement(name
);
104 void CElement::fastSaxify( Context
& i_rContext
)
106 if (!i_rContext
.mxDocHandler
.is()) throw RuntimeException();
107 pushContext(i_rContext
);
108 addNamespaces(i_rContext
,m_aNodePtr
);
111 i_rContext
.mxAttribList
->clear();
112 for (xmlAttrPtr pAttr
= m_aNodePtr
->properties
;
113 pAttr
!= nullptr; pAttr
= pAttr
->next
) {
114 ::rtl::Reference
<CNode
> const pNode
= GetOwnerDocument().GetCNode(
115 reinterpret_cast<xmlNodePtr
>(pAttr
));
116 OSL_ENSURE(pNode
!= nullptr, "CNode::get returned 0");
118 const xmlChar
* pName
= pAttr
->name
;
119 sal_Int32 nAttributeToken
=FastToken::DONTKNOW
;
121 if( pAttr
->ns
&& strlen(reinterpret_cast<char const *>(pAttr
->ns
->prefix
)) )
122 nAttributeToken
= getTokenWithPrefix( i_rContext
,
123 reinterpret_cast<char const *>(pAttr
->ns
->prefix
),
124 reinterpret_cast<char const *>(pName
) );
126 nAttributeToken
= getToken( i_rContext
, reinterpret_cast<char const *>(pName
) );
128 if( nAttributeToken
!= FastToken::DONTKNOW
)
129 i_rContext
.mxAttribList
->add( nAttributeToken
,
130 OUStringToOString(pNode
->getNodeValue(),
131 RTL_TEXTENCODING_UTF8
));
134 const xmlChar
* pPrefix
= (m_aNodePtr
->ns
&& m_aNodePtr
->ns
->prefix
) ? m_aNodePtr
->ns
->prefix
: reinterpret_cast<const xmlChar
*>("");
135 const xmlChar
* pName
= m_aNodePtr
->name
;
136 sal_Int32 nElementToken
=FastToken::DONTKNOW
;
137 if( strlen(reinterpret_cast<char const *>(pPrefix
)) )
138 nElementToken
= getTokenWithPrefix( i_rContext
, reinterpret_cast<char const *>(pPrefix
), reinterpret_cast<char const *>(pName
) );
140 nElementToken
= getToken( i_rContext
, reinterpret_cast<char const *>(pName
) );
142 Reference
<XFastContextHandler
> xParentHandler(i_rContext
.mxCurrentHandler
);
145 Reference
< XFastAttributeList
> xAttr( i_rContext
.mxAttribList
);
146 if( nElementToken
== FastToken::DONTKNOW
)
148 const OUString aNamespace
;
149 const OUString
aElementName( reinterpret_cast<char const *>(pPrefix
),
150 strlen(reinterpret_cast<char const *>(pPrefix
)),
151 RTL_TEXTENCODING_UTF8
);
153 if( xParentHandler
.is() )
154 i_rContext
.mxCurrentHandler
= xParentHandler
->createUnknownChildContext( aNamespace
, aElementName
, xAttr
);
156 i_rContext
.mxCurrentHandler
= i_rContext
.mxDocHandler
->createUnknownChildContext( aNamespace
, aElementName
, xAttr
);
158 if( i_rContext
.mxCurrentHandler
.is() )
159 i_rContext
.mxCurrentHandler
->startUnknownElement( aNamespace
, aElementName
, xAttr
);
163 if( xParentHandler
.is() )
164 i_rContext
.mxCurrentHandler
= xParentHandler
->createFastChildContext( nElementToken
, xAttr
);
166 i_rContext
.mxCurrentHandler
= i_rContext
.mxDocHandler
->createFastChildContext( nElementToken
, xAttr
);
168 if( i_rContext
.mxCurrentHandler
.is() )
169 i_rContext
.mxCurrentHandler
->startFastElement( nElementToken
, xAttr
);
176 for (xmlNodePtr pChild
= m_aNodePtr
->children
;
177 pChild
!= nullptr; pChild
= pChild
->next
) {
178 ::rtl::Reference
<CNode
> const pNode(
179 GetOwnerDocument().GetCNode(pChild
));
180 OSL_ENSURE(pNode
!= nullptr, "CNode::get returned 0");
181 pNode
->fastSaxify(i_rContext
);
184 if( i_rContext
.mxCurrentHandler
.is() ) try
186 if( nElementToken
!= FastToken::DONTKNOW
)
187 i_rContext
.mxCurrentHandler
->endFastElement( nElementToken
);
190 const OUString
aElementName( reinterpret_cast<char const *>(pPrefix
),
191 strlen(reinterpret_cast<char const *>(pPrefix
)),
192 RTL_TEXTENCODING_UTF8
);
194 i_rContext
.mxCurrentHandler
->endUnknownElement( u
""_ustr
, aElementName
);
200 // restore after children have been processed
201 i_rContext
.mxCurrentHandler
= std::move(xParentHandler
);
202 popContext(i_rContext
);
205 bool CElement::IsChildTypeAllowed(NodeType
const nodeType
, NodeType
const*const)
208 case NodeType_ELEMENT_NODE
:
209 case NodeType_TEXT_NODE
:
210 case NodeType_COMMENT_NODE
:
211 case NodeType_PROCESSING_INSTRUCTION_NODE
:
212 case NodeType_CDATA_SECTION_NODE
:
213 case NodeType_ENTITY_REFERENCE_NODE
:
215 case NodeType_ATTRIBUTE_NODE
:
216 /* this is not really allowed by the DOM spec, but this
217 implementation has evidently supported it (by special case
218 handling, so the attribute does not actually become a child)
219 so allow it for backward compatibility */
228 Retrieves an attribute value by name.
229 return empty string if attribute is not set
231 OUString SAL_CALL
CElement::getAttribute(OUString
const& name
)
233 ::osl::MutexGuard
const g(m_rMutex
);
235 if (nullptr == m_aNodePtr
) {
239 OString o1
= OUStringToOString(name
, RTL_TEXTENCODING_UTF8
);
240 std::shared_ptr
<xmlChar
const> const pValue(
241 xmlGetProp(m_aNodePtr
, reinterpret_cast<xmlChar
const *>(o1
.getStr())), xmlFree
);
242 OUString
const ret( pValue
243 ? OUString(reinterpret_cast<char const*>(pValue
.get()),
244 strlen(reinterpret_cast<char const*>(pValue
.get())),
245 RTL_TEXTENCODING_UTF8
)
251 Retrieves an attribute node by name.
253 Reference
< XAttr
> SAL_CALL
CElement::getAttributeNode(OUString
const& name
)
255 ::osl::MutexGuard
const g(m_rMutex
);
257 if (nullptr == m_aNodePtr
) {
260 OString o1
= OUStringToOString(name
, RTL_TEXTENCODING_UTF8
);
261 xmlChar
const*const pName
=
262 reinterpret_cast<xmlChar
const*>(o1
.getStr());
263 xmlAttrPtr
const pAttr
= xmlHasProp(m_aNodePtr
, pName
);
264 if (nullptr == pAttr
) {
267 Reference
< XAttr
> const xRet(
268 static_cast< XNode
* >(GetOwnerDocument().GetCNode(
269 reinterpret_cast<xmlNodePtr
>(pAttr
)).get()),
275 Retrieves an Attr node by local name and namespace URI.
277 Reference
< XAttr
> SAL_CALL
CElement::getAttributeNodeNS(
278 const OUString
& namespaceURI
, const OUString
& localName
)
280 ::osl::MutexGuard
const g(m_rMutex
);
282 if (nullptr == m_aNodePtr
) {
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 (nullptr == pAttr
) {
295 Reference
< XAttr
> const xRet(
296 static_cast< XNode
* >(GetOwnerDocument().GetCNode(
297 reinterpret_cast<xmlNodePtr
>(pAttr
)).get()),
303 Retrieves an attribute value by local name and namespace URI.
304 return empty string if attribute is not set
307 CElement::getAttributeNS(
308 OUString
const& namespaceURI
, OUString
const& localName
)
310 ::osl::MutexGuard
const g(m_rMutex
);
312 if (nullptr == m_aNodePtr
) {
315 OString o1
= OUStringToOString(localName
, RTL_TEXTENCODING_UTF8
);
316 xmlChar
const*const pName
=
317 reinterpret_cast<xmlChar
const*>(o1
.getStr());
318 OString o2
= OUStringToOString(namespaceURI
, RTL_TEXTENCODING_UTF8
);
319 xmlChar
const*const pNS
=
320 reinterpret_cast<xmlChar
const*>(o2
.getStr());
321 std::shared_ptr
<xmlChar
const> const pValue(
322 xmlGetNsProp(m_aNodePtr
, pName
, pNS
), xmlFree
);
323 if (nullptr == pValue
) {
326 OUString
const ret(reinterpret_cast<char const*>(pValue
.get()),
327 strlen(reinterpret_cast<char const*>(pValue
.get())),
328 RTL_TEXTENCODING_UTF8
);
333 Returns a NodeList of all descendant Elements with a given tag name,
334 in the order in which they are
335 encountered in a preorder traversal of this Element tree.
337 Reference
< XNodeList
> SAL_CALL
338 CElement::getElementsByTagName(OUString
const& rLocalName
)
340 ::osl::MutexGuard
const g(m_rMutex
);
342 Reference
< XNodeList
> const xList(
343 new CElementList(this, m_rMutex
, rLocalName
));
348 Returns a NodeList of all the descendant Elements with a given local
349 name and namespace URI in the order in which they are encountered in
350 a preorder traversal of this Element tree.
352 Reference
< XNodeList
> SAL_CALL
353 CElement::getElementsByTagNameNS(
354 OUString
const& rNamespaceURI
, OUString
const& rLocalName
)
356 ::osl::MutexGuard
const g(m_rMutex
);
358 Reference
< XNodeList
> const xList(
359 new CElementList(this, m_rMutex
, rLocalName
, &rNamespaceURI
));
364 The name of the element.
366 OUString SAL_CALL
CElement::getTagName()
368 ::osl::MutexGuard
const g(m_rMutex
);
370 if (nullptr == m_aNodePtr
) {
373 OUString
const ret(reinterpret_cast<char const *>(m_aNodePtr
->name
),
374 strlen(reinterpret_cast<char const *>(m_aNodePtr
->name
)), RTL_TEXTENCODING_UTF8
);
380 Returns true when an attribute with a given name is specified on this
381 element or has a default value, false otherwise.
383 sal_Bool SAL_CALL
CElement::hasAttribute(OUString
const& name
)
385 ::osl::MutexGuard
const g(m_rMutex
);
387 OString o1
= OUStringToOString(name
, RTL_TEXTENCODING_UTF8
);
388 xmlChar
const *pName
= reinterpret_cast<xmlChar
const *>(o1
.getStr());
389 return (m_aNodePtr
!= nullptr && xmlHasProp(m_aNodePtr
, pName
) != nullptr);
393 Returns true when an attribute with a given local name and namespace
394 URI is specified on this element or has a default value, false otherwise.
396 sal_Bool SAL_CALL
CElement::hasAttributeNS(
397 OUString
const& namespaceURI
, OUString
const& localName
)
399 ::osl::MutexGuard
const g(m_rMutex
);
401 OString o1
= OUStringToOString(localName
, RTL_TEXTENCODING_UTF8
);
402 xmlChar
const *pName
= reinterpret_cast<xmlChar
const *>(o1
.getStr());
403 OString o2
= OUStringToOString(namespaceURI
, RTL_TEXTENCODING_UTF8
);
404 xmlChar
const *pNs
= reinterpret_cast<xmlChar
const *>(o2
.getStr());
405 return (m_aNodePtr
!= nullptr && xmlHasNsProp(m_aNodePtr
, pName
, pNs
) != nullptr);
409 Removes an attribute by name.
411 void SAL_CALL
CElement::removeAttribute(OUString
const& name
)
413 ::osl::MutexGuard
const g(m_rMutex
);
415 if (nullptr == m_aNodePtr
) {
418 OString o1
= OUStringToOString(name
, RTL_TEXTENCODING_UTF8
);
419 xmlChar
const*const pName
=
420 reinterpret_cast<xmlChar
const*>(o1
.getStr());
421 xmlAttrPtr
const pAttr
= xmlHasProp(m_aNodePtr
, pName
);
422 if (0 == xmlUnsetProp(m_aNodePtr
, pName
)) {
423 ::rtl::Reference
<CNode
> const pCNode(GetOwnerDocument().GetCNode(
424 reinterpret_cast<xmlNodePtr
>(pAttr
), false));
426 pCNode
->invalidate(); // freed by xmlUnsetProp
432 Removes an attribute by local name and namespace URI.
434 void SAL_CALL
CElement::removeAttributeNS(
435 OUString
const& namespaceURI
, OUString
const& localName
)
437 ::osl::MutexGuard
const g(m_rMutex
);
439 if (nullptr == m_aNodePtr
) {
442 OString o1
= OUStringToOString(localName
, RTL_TEXTENCODING_UTF8
);
443 xmlChar
const*const pName
=
444 reinterpret_cast<xmlChar
const*>(o1
.getStr());
445 OString o2
= OUStringToOString(namespaceURI
, RTL_TEXTENCODING_UTF8
);
446 xmlChar
const*const pURI
=
447 reinterpret_cast<xmlChar
const*>(o2
.getStr());
449 xmlSearchNsByHref(m_aNodePtr
->doc
, m_aNodePtr
, pURI
);
450 xmlAttrPtr
const pAttr
= xmlHasNsProp(m_aNodePtr
, pName
, pURI
);
451 if (0 == xmlUnsetNsProp(m_aNodePtr
, pNs
, pName
)) {
452 ::rtl::Reference
<CNode
> const pCNode(GetOwnerDocument().GetCNode(
453 reinterpret_cast<xmlNodePtr
>(pAttr
), false));
455 pCNode
->invalidate(); // freed by xmlUnsetNsProp
461 Removes the specified attribute node.
463 Reference
< XAttr
> SAL_CALL
464 CElement::removeAttributeNode(Reference
< XAttr
> const& oldAttr
)
466 ::osl::MutexGuard
const g(m_rMutex
);
468 if (nullptr == m_aNodePtr
) {
472 ::rtl::Reference
<CNode
> const pCNode(
473 dynamic_cast<CNode
*>(oldAttr
.get()));
474 if (!pCNode
.is()) { throw RuntimeException(); }
476 xmlNodePtr
const pNode
= pCNode
->GetNodePtr();
477 xmlAttrPtr
const pAttr
= reinterpret_cast<xmlAttrPtr
>(pNode
);
478 if (!pAttr
) { throw RuntimeException(); }
480 if (pAttr
->parent
!= m_aNodePtr
)
483 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
486 if (pAttr
->doc
!= m_aNodePtr
->doc
)
489 e
.Code
= DOMExceptionType_WRONG_DOCUMENT_ERR
;
493 Reference
< XAttr
> aAttr
;
494 if (!oldAttr
->getNamespaceURI().isEmpty()) {
495 OUStringBuffer
qname(oldAttr
->getPrefix());
496 if (!qname
.isEmpty()) {
499 qname
.append(oldAttr
->getName());
500 aAttr
= GetOwnerDocument().createAttributeNS(
501 oldAttr
->getNamespaceURI(), qname
.makeStringAndClear());
503 aAttr
= GetOwnerDocument().createAttribute(oldAttr
->getName());
505 aAttr
->setValue(oldAttr
->getValue());
506 xmlRemoveProp(pAttr
);
507 pCNode
->invalidate(); // freed by xmlRemoveProp
513 Adds a new attribute node.
516 CElement::setAttributeNode_Impl_Lock(
517 Reference
< XAttr
> const& xNewAttr
, bool const bNS
)
519 if (xNewAttr
->getOwnerDocument() != getOwnerDocument()) {
521 e
.Code
= DOMExceptionType_WRONG_DOCUMENT_ERR
;
525 ::osl::ClearableMutexGuard
guard(m_rMutex
);
527 if (nullptr == m_aNodePtr
) {
528 throw RuntimeException();
531 // get the implementation
532 CAttr
*const pCAttr
= dynamic_cast<CAttr
*>(xNewAttr
.get());
533 if (!pCAttr
) { throw RuntimeException(); }
534 xmlAttrPtr
const pAttr
=
535 reinterpret_cast<xmlAttrPtr
>(pCAttr
->GetNodePtr());
536 if (!pAttr
) { throw RuntimeException(); }
538 // check whether the attribute is not in use by another element
541 e
.Code
= DOMExceptionType_INUSE_ATTRIBUTE_ERR
;
545 xmlAttrPtr res
= nullptr;
546 xmlChar
const*const pContent(
547 (pAttr
->children
) ? pAttr
->children
->content
: nullptr);
550 xmlNsPtr
const pNs( pCAttr
->GetNamespace(m_aNodePtr
) );
551 res
= xmlNewNsProp(m_aNodePtr
, pNs
, pAttr
->name
, pContent
);
553 res
= xmlNewProp(m_aNodePtr
, pAttr
->name
, pContent
);
556 // get the new attr node
557 Reference
< XAttr
> const xAttr(
558 static_cast< XNode
* >(GetOwnerDocument().GetCNode(
559 reinterpret_cast<xmlNodePtr
>(res
)).get()),
562 // attribute addition event
563 // dispatch DOMAttrModified event
564 Reference
< XDocumentEvent
> docevent(getOwnerDocument(), UNO_QUERY
);
565 Reference
< XMutationEvent
> event(docevent
->createEvent(
566 u
"DOMAttrModified"_ustr
), UNO_QUERY
);
567 event
->initMutationEvent(u
"DOMAttrModified"_ustr
,
569 OUString(), xAttr
->getValue(), xAttr
->getName(),
570 AttrChangeType_ADDITION
);
572 guard
.clear(); // release mutex before calling event handlers
574 dispatchEvent(event
);
575 dispatchSubtreeModified();
581 CElement::setAttributeNode(const Reference
< XAttr
>& newAttr
)
583 return setAttributeNode_Impl_Lock(newAttr
, false);
587 Adds a new attribute.
590 CElement::setAttributeNodeNS(const Reference
< XAttr
>& newAttr
)
592 return setAttributeNode_Impl_Lock(newAttr
, true);
596 Adds a new attribute.
599 CElement::setAttribute(OUString
const& name
, OUString
const& value
)
601 ::osl::ClearableMutexGuard
guard(m_rMutex
);
603 OString o1
= OUStringToOString(name
, RTL_TEXTENCODING_UTF8
);
604 xmlChar
const *pName
= reinterpret_cast<xmlChar
const *>(o1
.getStr());
605 OString o2
= OUStringToOString(value
, RTL_TEXTENCODING_UTF8
);
606 xmlChar
const *pValue
= reinterpret_cast<xmlChar
const *>(o2
.getStr());
608 if (nullptr == m_aNodePtr
) {
609 throw RuntimeException();
612 AttrChangeType aChangeType
= AttrChangeType_MODIFICATION
;
613 std::shared_ptr
<xmlChar
const> const pOld(
614 xmlGetProp(m_aNodePtr
, pName
), xmlFree
);
615 if (pOld
== nullptr) {
616 aChangeType
= AttrChangeType_ADDITION
;
617 xmlNewProp(m_aNodePtr
, pName
, pValue
);
619 oldValue
= OUString(reinterpret_cast<char const*>(pOld
.get()),
620 strlen(reinterpret_cast<char const*>(pOld
.get())),
621 RTL_TEXTENCODING_UTF8
);
622 xmlSetProp(m_aNodePtr
, pName
, pValue
);
625 // dispatch DOMAttrModified event
626 Reference
< XDocumentEvent
> docevent(getOwnerDocument(), UNO_QUERY
);
627 Reference
< XMutationEvent
> event(docevent
->createEvent(
628 u
"DOMAttrModified"_ustr
), UNO_QUERY
);
629 event
->initMutationEvent(u
"DOMAttrModified"_ustr
,
631 getAttributeNode(name
),
632 oldValue
, value
, name
, aChangeType
);
634 guard
.clear(); // release mutex before calling event handlers
635 dispatchEvent(event
);
636 dispatchSubtreeModified();
640 Adds a new attribute.
643 CElement::setAttributeNS(OUString
const& namespaceURI
,
644 OUString
const& qualifiedName
, OUString
const& value
)
646 if (namespaceURI
.isEmpty()) throw RuntimeException();
648 ::osl::ClearableMutexGuard
guard(m_rMutex
);
650 OString o1
, o2
, o3
, o4
, o5
;
651 xmlChar
const *pPrefix
= nullptr;
652 xmlChar
const *pLName
= nullptr;
653 o1
= OUStringToOString(qualifiedName
, RTL_TEXTENCODING_UTF8
);
654 xmlChar
const *pQName
= reinterpret_cast<xmlChar
const *>(o1
.getStr());
655 sal_Int32 idx
= qualifiedName
.indexOf(':');
658 o2
= OUStringToOString(
659 qualifiedName
.subView(0,idx
),
660 RTL_TEXTENCODING_UTF8
);
661 pPrefix
= reinterpret_cast<xmlChar
const *>(o2
.getStr());
662 o3
= OUStringToOString(
663 qualifiedName
.subView(idx
+1),
664 RTL_TEXTENCODING_UTF8
);
665 pLName
= reinterpret_cast<xmlChar
const *>(o3
.getStr());
667 pPrefix
= reinterpret_cast<xmlChar
const *>("");
670 o4
= OUStringToOString(namespaceURI
, RTL_TEXTENCODING_UTF8
);
671 o5
= OUStringToOString(value
, RTL_TEXTENCODING_UTF8
);
672 xmlChar
const *pURI
= reinterpret_cast<xmlChar
const *>(o4
.getStr());
673 xmlChar
const *pValue
= reinterpret_cast<xmlChar
const *>(o5
.getStr());
675 if (nullptr == m_aNodePtr
) {
676 throw RuntimeException();
679 //find the right namespace
680 xmlNsPtr pNs
= xmlSearchNs(m_aNodePtr
->doc
, m_aNodePtr
, pPrefix
);
681 // if no namespace found, create a new one
682 if (pNs
== nullptr) {
683 pNs
= xmlNewNs(m_aNodePtr
, pURI
, pPrefix
);
686 if (strcmp(reinterpret_cast<char const *>(pNs
->href
), reinterpret_cast<char const *>(pURI
)) != 0) {
687 // ambiguous ns prefix
688 throw RuntimeException();
691 // found namespace matches
694 AttrChangeType aChangeType
= AttrChangeType_MODIFICATION
;
695 std::shared_ptr
<xmlChar
const> const pOld(
696 xmlGetNsProp(m_aNodePtr
, pLName
, pNs
->href
), xmlFree
);
697 if (pOld
== nullptr) {
698 aChangeType
= AttrChangeType_ADDITION
;
699 xmlNewNsProp(m_aNodePtr
, pNs
, pLName
, pValue
);
701 oldValue
= OUString(reinterpret_cast<char const*>(pOld
.get()),
702 strlen(reinterpret_cast<char const*>(pOld
.get())),
703 RTL_TEXTENCODING_UTF8
);
704 xmlSetNsProp(m_aNodePtr
, pNs
, pLName
, pValue
);
706 // dispatch DOMAttrModified event
707 Reference
< XDocumentEvent
> docevent(getOwnerDocument(), UNO_QUERY
);
708 Reference
< XMutationEvent
> event(docevent
->createEvent(
709 u
"DOMAttrModified"_ustr
), UNO_QUERY
);
710 event
->initMutationEvent(
711 u
"DOMAttrModified"_ustr
, true, false,
712 getAttributeNodeNS(namespaceURI
, OUString(reinterpret_cast<char const *>(pLName
), strlen(reinterpret_cast<char const *>(pLName
)), RTL_TEXTENCODING_UTF8
)),
713 oldValue
, value
, qualifiedName
, aChangeType
);
715 guard
.clear(); // release mutex before calling event handlers
716 dispatchEvent(event
);
717 dispatchSubtreeModified();
720 Reference
< XNamedNodeMap
> SAL_CALL
721 CElement::getAttributes()
723 ::osl::MutexGuard
const g(m_rMutex
);
725 Reference
< XNamedNodeMap
> const xMap(
726 new CAttributesMap(this, m_rMutex
));
730 OUString SAL_CALL
CElement::getNodeName()
732 return getLocalName();
735 OUString SAL_CALL
CElement::getLocalName()
737 ::osl::MutexGuard
const g(m_rMutex
);
740 if (m_aNodePtr
!= nullptr)
742 const xmlChar
* pName
= m_aNodePtr
->name
;
743 aName
= OUString(reinterpret_cast<const char*>(pName
), strlen(reinterpret_cast<const char*>(pName
)), RTL_TEXTENCODING_UTF8
);
748 OUString SAL_CALL
CElement::getNodeValue()
754 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */