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>
32 #include <comphelper/servicehelper.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
;
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();
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
);
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())
92 : prefix
+ ":" + getLocalName();
93 Reference
< XAttributeList
> xAttrList(pAttrs
);
94 i_xHandler
->startElement(name
, xAttrList
);
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
);
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
) );
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
) );
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
);
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
);
165 if( xParentHandler
.is() )
166 i_rContext
.mxCurrentHandler
= xParentHandler
->createFastChildContext( nElementToken
, xAttr
);
168 i_rContext
.mxCurrentHandler
= i_rContext
.mxDocHandler
->createFastChildContext( nElementToken
, xAttr
);
170 if( i_rContext
.mxCurrentHandler
.is() )
171 i_rContext
.mxCurrentHandler
->startFastElement( nElementToken
, xAttr
);
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
);
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
);
203 // restore after children have been processed
204 i_rContext
.mxCurrentHandler
= xParentHandler
;
205 popContext(i_rContext
);
208 bool CElement::IsChildTypeAllowed(NodeType
const 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
:
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 */
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
) {
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
)
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
) {
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
) {
270 Reference
< XAttr
> const xRet(
271 static_cast< XNode
* >(GetOwnerDocument().GetCNode(
272 reinterpret_cast<xmlNodePtr
>(pAttr
)).get()),
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
) {
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
) {
298 Reference
< XAttr
> const xRet(
299 static_cast< XNode
* >(GetOwnerDocument().GetCNode(
300 reinterpret_cast<xmlNodePtr
>(pAttr
)).get()),
306 Retrieves an attribute value by local name and namespace URI.
307 return empty string if attribute is not set
310 CElement::getAttributeNS(
311 OUString
const& namespaceURI
, OUString
const& localName
)
313 ::osl::MutexGuard
const g(m_rMutex
);
315 if (nullptr == m_aNodePtr
) {
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
) {
329 OUString
const ret(reinterpret_cast<sal_Char
const*>(pValue
.get()),
330 strlen(reinterpret_cast<char const*>(pValue
.get())),
331 RTL_TEXTENCODING_UTF8
);
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
));
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
));
367 The name of the element.
369 OUString SAL_CALL
CElement::getTagName()
371 ::osl::MutexGuard
const g(m_rMutex
);
373 if (nullptr == m_aNodePtr
) {
376 OUString
const ret(reinterpret_cast<char const *>(m_aNodePtr
->name
),
377 strlen(reinterpret_cast<char const *>(m_aNodePtr
->name
)), RTL_TEXTENCODING_UTF8
);
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
) {
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));
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
) {
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());
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));
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
) {
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
)
486 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
489 if (pAttr
->doc
!= m_aNodePtr
->doc
)
492 e
.Code
= DOMExceptionType_WRONG_DOCUMENT_ERR
;
496 Reference
< XAttr
> aAttr
;
497 if (!oldAttr
->getNamespaceURI().isEmpty()) {
498 OUStringBuffer
qname(oldAttr
->getPrefix());
499 if (!qname
.isEmpty()) {
502 qname
.append(oldAttr
->getName());
503 aAttr
= GetOwnerDocument().createAttributeNS(
504 oldAttr
->getNamespaceURI(), qname
.makeStringAndClear());
506 aAttr
= GetOwnerDocument().createAttribute(oldAttr
->getName());
508 aAttr
->setValue(oldAttr
->getValue());
509 xmlRemoveProp(pAttr
);
510 pCNode
->invalidate(); // freed by xmlRemoveProp
516 Adds a new attribute node.
519 CElement::setAttributeNode_Impl_Lock(
520 Reference
< XAttr
> const& xNewAttr
, bool const bNS
)
522 if (xNewAttr
->getOwnerDocument() != getOwnerDocument()) {
524 e
.Code
= DOMExceptionType_WRONG_DOCUMENT_ERR
;
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
545 e
.Code
= DOMExceptionType_INUSE_ATTRIBUTE_ERR
;
549 xmlAttrPtr res
= nullptr;
550 xmlChar
const*const pContent(
551 (pAttr
->children
) ? pAttr
->children
->content
: nullptr);
554 xmlNsPtr
const pNs( pCAttr
->GetNamespace(m_aNodePtr
) );
555 res
= xmlNewNsProp(m_aNodePtr
, pNs
, pAttr
->name
, pContent
);
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()),
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",
573 OUString(), xAttr
->getValue(), xAttr
->getName(),
574 AttrChangeType_ADDITION
);
576 guard
.clear(); // release mutex before calling event handlers
578 dispatchEvent(event
);
579 dispatchSubtreeModified();
585 CElement::setAttributeNode(const Reference
< XAttr
>& newAttr
)
587 return setAttributeNode_Impl_Lock(newAttr
, false);
591 Adds a new attribute.
594 CElement::setAttributeNodeNS(const Reference
< XAttr
>& newAttr
)
596 return setAttributeNode_Impl_Lock(newAttr
, true);
600 Adds a new attribute.
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();
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
);
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",
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.
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(':');
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());
671 pPrefix
= reinterpret_cast<xmlChar
const *>("");
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
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
);
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
));
734 OUString SAL_CALL
CElement::getNodeName()
736 return getLocalName();
739 OUString SAL_CALL
CElement::getLocalName()
741 ::osl::MutexGuard
const g(m_rMutex
);
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
);
752 OUString SAL_CALL
CElement::getNodeValue()
758 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */