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/sax/FastToken.hpp>
31 #include <comphelper/attributelist.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
;
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();
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
);
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())
91 : prefix
+ ":" + getLocalName();
92 Reference
< XAttributeList
> xAttrList(pAttrs
);
93 i_xHandler
->startElement(name
, xAttrList
);
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
);
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
) );
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
) );
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
);
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
);
164 if( xParentHandler
.is() )
165 i_rContext
.mxCurrentHandler
= xParentHandler
->createFastChildContext( nElementToken
, xAttr
);
167 i_rContext
.mxCurrentHandler
= i_rContext
.mxDocHandler
->createFastChildContext( nElementToken
, xAttr
);
169 if( i_rContext
.mxCurrentHandler
.is() )
170 i_rContext
.mxCurrentHandler
->startFastElement( nElementToken
, xAttr
);
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
);
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
);
202 // restore after children have been processed
203 i_rContext
.mxCurrentHandler
= xParentHandler
;
204 popContext(i_rContext
);
207 bool CElement::IsChildTypeAllowed(NodeType
const 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
:
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 */
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
) {
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
)
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
) {
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
) {
269 Reference
< XAttr
> const xRet(
270 static_cast< XNode
* >(GetOwnerDocument().GetCNode(
271 reinterpret_cast<xmlNodePtr
>(pAttr
)).get()),
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
) {
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
) {
297 Reference
< XAttr
> const xRet(
298 static_cast< XNode
* >(GetOwnerDocument().GetCNode(
299 reinterpret_cast<xmlNodePtr
>(pAttr
)).get()),
305 Retrieves an attribute value by local name and namespace URI.
306 return empty string if attribute is not set
309 CElement::getAttributeNS(
310 OUString
const& namespaceURI
, OUString
const& localName
)
312 ::osl::MutexGuard
const g(m_rMutex
);
314 if (nullptr == m_aNodePtr
) {
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
) {
328 OUString
const ret(reinterpret_cast<sal_Char
const*>(pValue
.get()),
329 strlen(reinterpret_cast<char const*>(pValue
.get())),
330 RTL_TEXTENCODING_UTF8
);
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
));
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
));
366 The name of the element.
368 OUString SAL_CALL
CElement::getTagName()
370 ::osl::MutexGuard
const g(m_rMutex
);
372 if (nullptr == m_aNodePtr
) {
375 OUString
const ret(reinterpret_cast<char const *>(m_aNodePtr
->name
),
376 strlen(reinterpret_cast<char const *>(m_aNodePtr
->name
)), RTL_TEXTENCODING_UTF8
);
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
) {
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));
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
) {
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());
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));
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
) {
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
)
485 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
488 if (pAttr
->doc
!= m_aNodePtr
->doc
)
491 e
.Code
= DOMExceptionType_WRONG_DOCUMENT_ERR
;
495 Reference
< XAttr
> aAttr
;
496 if (!oldAttr
->getNamespaceURI().isEmpty()) {
497 OUStringBuffer
qname(oldAttr
->getPrefix());
498 if (!qname
.isEmpty()) {
501 qname
.append(oldAttr
->getName());
502 aAttr
= GetOwnerDocument().createAttributeNS(
503 oldAttr
->getNamespaceURI(), qname
.makeStringAndClear());
505 aAttr
= GetOwnerDocument().createAttribute(oldAttr
->getName());
507 aAttr
->setValue(oldAttr
->getValue());
508 xmlRemoveProp(pAttr
);
509 pCNode
->invalidate(); // freed by xmlRemoveProp
515 Adds a new attribute node.
518 CElement::setAttributeNode_Impl_Lock(
519 Reference
< XAttr
> const& xNewAttr
, bool const bNS
)
521 if (xNewAttr
->getOwnerDocument() != getOwnerDocument()) {
523 e
.Code
= DOMExceptionType_WRONG_DOCUMENT_ERR
;
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
544 e
.Code
= DOMExceptionType_INUSE_ATTRIBUTE_ERR
;
548 xmlAttrPtr res
= nullptr;
549 xmlChar
const*const pContent(
550 (pAttr
->children
) ? pAttr
->children
->content
: nullptr);
553 xmlNsPtr
const pNs( pCAttr
->GetNamespace(m_aNodePtr
) );
554 res
= xmlNewNsProp(m_aNodePtr
, pNs
, pAttr
->name
, pContent
);
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()),
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",
572 OUString(), xAttr
->getValue(), xAttr
->getName(),
573 AttrChangeType_ADDITION
);
575 guard
.clear(); // release mutex before calling event handlers
577 dispatchEvent(event
);
578 dispatchSubtreeModified();
584 CElement::setAttributeNode(const Reference
< XAttr
>& newAttr
)
586 return setAttributeNode_Impl_Lock(newAttr
, false);
590 Adds a new attribute.
593 CElement::setAttributeNodeNS(const Reference
< XAttr
>& newAttr
)
595 return setAttributeNode_Impl_Lock(newAttr
, true);
599 Adds a new attribute.
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();
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
);
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",
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.
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(':');
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());
670 pPrefix
= reinterpret_cast<xmlChar
const *>("");
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
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
);
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
));
733 OUString SAL_CALL
CElement::getNodeName()
735 return getLocalName();
738 OUString SAL_CALL
CElement::getLocalName()
740 ::osl::MutexGuard
const g(m_rMutex
);
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
);
751 OUString SAL_CALL
CElement::getNodeValue()
757 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */