LibreOffice Module unoxml (master) 1
element.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include "element.hxx"
21
22#include <string.h>
23
24#include <memory>
25
26#include <osl/diagnose.h>
27#include <rtl/ustrbuf.hxx>
28
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>
32
35
36#include <node.hxx>
37#include "attr.hxx"
38#include "elementlist.hxx"
39#include "attributesmap.hxx"
40#include "document.hxx"
41
42using namespace css::uno;
43using namespace css::xml::dom;
44using namespace css::xml::dom::events;
45using namespace css::xml::sax;
46
47namespace DOM
48{
49
50 CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex,
51 xmlNodePtr const pNode)
52 : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode)
53 {
54 }
55
56 void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler)
57 {
58 if (!i_xHandler.is()) throw RuntimeException();
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 ? OUString( "xmlns" ) : "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);
74 }
75 // add attributes
76 for (xmlAttrPtr pAttr = m_aNodePtr->properties;
77 pAttr != nullptr; pAttr = pAttr->next) {
78 ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
79 reinterpret_cast<xmlNodePtr>(pAttr));
80 OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
81 OUString prefix = pNode->getPrefix();
82 OUString name = (prefix.isEmpty())
83 ? pNode->getLocalName()
84 : prefix + ":" + pNode->getLocalName();
85 OUString val = pNode->getNodeValue();
86 pAttrs->AddAttribute(name, val);
87 }
88 OUString prefix = getPrefix();
89 OUString name = (prefix.isEmpty())
90 ? getLocalName()
91 : prefix + ":" + getLocalName();
92 i_xHandler->startElement(name, pAttrs);
93 // recurse
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);
100 }
101 i_xHandler->endElement(name);
102 }
103
104 void CElement::fastSaxify( Context& i_rContext )
105 {
106 if (!i_rContext.mxDocHandler.is()) throw RuntimeException();
107 pushContext(i_rContext);
108 addNamespaces(i_rContext,m_aNodePtr);
109
110 // add attributes
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");
117
118 const xmlChar* pName = pAttr->name;
119 sal_Int32 nAttributeToken=FastToken::DONTKNOW;
120
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) );
125 else
126 nAttributeToken = getToken( i_rContext, reinterpret_cast<char const *>(pName) );
127
128 if( nAttributeToken != FastToken::DONTKNOW )
129 i_rContext.mxAttribList->add( nAttributeToken,
130 OUStringToOString(pNode->getNodeValue(),
131 RTL_TEXTENCODING_UTF8));
132 }
133
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) );
139 else
140 nElementToken = getToken( i_rContext, reinterpret_cast<char const *>(pName) );
141
142 Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler);
143 try
144 {
145 Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList );
146 if( nElementToken == FastToken::DONTKNOW )
147 {
148 const OUString aNamespace;
149 const OUString aElementName( reinterpret_cast<char const *>(pPrefix),
150 strlen(reinterpret_cast<char const *>(pPrefix)),
151 RTL_TEXTENCODING_UTF8 );
152
153 if( xParentHandler.is() )
154 i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
155 else
156 i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
157
158 if( i_rContext.mxCurrentHandler.is() )
159 i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr );
160 }
161 else
162 {
163 if( xParentHandler.is() )
164 i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr );
165 else
166 i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr );
167
168 if( i_rContext.mxCurrentHandler.is() )
169 i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr );
170 }
171 }
172 catch( Exception& )
173 {}
174
175 // recurse
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);
182 }
183
184 if( i_rContext.mxCurrentHandler.is() ) try
185 {
186 if( nElementToken != FastToken::DONTKNOW )
187 i_rContext.mxCurrentHandler->endFastElement( nElementToken );
188 else
189 {
190 const OUString aElementName( reinterpret_cast<char const *>(pPrefix),
191 strlen(reinterpret_cast<char const *>(pPrefix)),
192 RTL_TEXTENCODING_UTF8 );
193
194 i_rContext.mxCurrentHandler->endUnknownElement( "", aElementName );
195 }
196 }
197 catch( Exception& )
198 {}
199
200 // restore after children have been processed
201 i_rContext.mxCurrentHandler = xParentHandler;
202 popContext(i_rContext);
203 }
204
205 bool CElement::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const)
206 {
207 switch (nodeType) {
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:
214 return true;
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 */
220 return true;
221 default:
222 return false;
223 }
224 }
225
226
231 OUString SAL_CALL CElement::getAttribute(OUString const& name)
232 {
233 ::osl::MutexGuard const g(m_rMutex);
234
235 if (nullptr == m_aNodePtr) {
236 return OUString();
237 }
238 // search properties
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)
246 : OUString() );
247 return ret;
248 }
249
253 Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name)
254 {
255 ::osl::MutexGuard const g(m_rMutex);
256
257 if (nullptr == m_aNodePtr) {
258 return nullptr;
259 }
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) {
265 return nullptr;
266 }
267 Reference< XAttr > const xRet(
268 static_cast< XNode* >(GetOwnerDocument().GetCNode(
269 reinterpret_cast<xmlNodePtr>(pAttr)).get()),
270 UNO_QUERY_THROW);
271 return xRet;
272 }
273
277 Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS(
278 const OUString& namespaceURI, const OUString& localName)
279 {
280 ::osl::MutexGuard const g(m_rMutex);
281
282 if (nullptr == m_aNodePtr) {
283 return nullptr;
284 }
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) {
293 return nullptr;
294 }
295 Reference< XAttr > const xRet(
296 static_cast< XNode* >(GetOwnerDocument().GetCNode(
297 reinterpret_cast<xmlNodePtr>(pAttr)).get()),
298 UNO_QUERY_THROW);
299 return xRet;
300 }
301
306 OUString SAL_CALL
308 OUString const& namespaceURI, OUString const& localName)
309 {
310 ::osl::MutexGuard const g(m_rMutex);
311
312 if (nullptr == m_aNodePtr) {
313 return OUString();
314 }
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) {
324 return OUString();
325 }
326 OUString const ret(reinterpret_cast<char const*>(pValue.get()),
327 strlen(reinterpret_cast<char const*>(pValue.get())),
328 RTL_TEXTENCODING_UTF8);
329 return ret;
330 }
331
337 Reference< XNodeList > SAL_CALL
338 CElement::getElementsByTagName(OUString const& rLocalName)
339 {
340 ::osl::MutexGuard const g(m_rMutex);
341
342 Reference< XNodeList > const xList(
343 new CElementList(this, m_rMutex, rLocalName));
344 return xList;
345 }
346
352 Reference< XNodeList > SAL_CALL
354 OUString const& rNamespaceURI, OUString const& rLocalName)
355 {
356 ::osl::MutexGuard const g(m_rMutex);
357
358 Reference< XNodeList > const xList(
359 new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI));
360 return xList;
361 }
362
366 OUString SAL_CALL CElement::getTagName()
367 {
368 ::osl::MutexGuard const g(m_rMutex);
369
370 if (nullptr == m_aNodePtr) {
371 return OUString();
372 }
373 OUString const ret(reinterpret_cast<char const *>(m_aNodePtr->name),
374 strlen(reinterpret_cast<char const *>(m_aNodePtr->name)), RTL_TEXTENCODING_UTF8);
375 return ret;
376 }
377
378
383 sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name)
384 {
385 ::osl::MutexGuard const g(m_rMutex);
386
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);
390 }
391
397 OUString const& namespaceURI, OUString const& localName)
398 {
399 ::osl::MutexGuard const g(m_rMutex);
400
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);
406 }
407
411 void SAL_CALL CElement::removeAttribute(OUString const& name)
412 {
413 ::osl::MutexGuard const g(m_rMutex);
414
415 if (nullptr == m_aNodePtr) {
416 return;
417 }
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));
425 if (pCNode.is()) {
426 pCNode->invalidate(); // freed by xmlUnsetProp
427 }
428 }
429 }
430
435 OUString const& namespaceURI, OUString const& localName)
436 {
437 ::osl::MutexGuard const g(m_rMutex);
438
439 if (nullptr == m_aNodePtr) {
440 return;
441 }
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());
448 xmlNsPtr const pNs =
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));
454 if (pCNode.is()) {
455 pCNode->invalidate(); // freed by xmlUnsetNsProp
456 }
457 }
458 }
459
463 Reference< XAttr > SAL_CALL
464 CElement::removeAttributeNode(Reference< XAttr > const& oldAttr)
465 {
466 ::osl::MutexGuard const g(m_rMutex);
467
468 if (nullptr == m_aNodePtr) {
469 return nullptr;
470 }
471
472 ::rtl::Reference<CNode> const pCNode(
473 dynamic_cast<CNode*>(oldAttr.get()));
474 if (!pCNode.is()) { throw RuntimeException(); }
475
476 xmlNodePtr const pNode = pCNode->GetNodePtr();
477 xmlAttrPtr const pAttr = reinterpret_cast<xmlAttrPtr>(pNode);
478 if (!pAttr) { throw RuntimeException(); }
479
480 if (pAttr->parent != m_aNodePtr)
481 {
482 DOMException e;
483 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
484 throw e;
485 }
486 if (pAttr->doc != m_aNodePtr->doc)
487 {
488 DOMException e;
489 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
490 throw e;
491 }
492
493 Reference< XAttr > aAttr;
494 if (!oldAttr->getNamespaceURI().isEmpty()) {
495 OUStringBuffer qname(oldAttr->getPrefix());
496 if (!qname.isEmpty()) {
497 qname.append(':');
498 }
499 qname.append(oldAttr->getName());
500 aAttr = GetOwnerDocument().createAttributeNS(
501 oldAttr->getNamespaceURI(), qname.makeStringAndClear());
502 } else {
503 aAttr = GetOwnerDocument().createAttribute(oldAttr->getName());
504 }
505 aAttr->setValue(oldAttr->getValue());
506 xmlRemoveProp(pAttr);
507 pCNode->invalidate(); // freed by xmlRemoveProp
508
509 return aAttr;
510 }
511
515 Reference< XAttr >
517 Reference< XAttr > const& xNewAttr, bool const bNS)
518 {
519 if (xNewAttr->getOwnerDocument() != getOwnerDocument()) {
520 DOMException e;
521 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
522 throw e;
523 }
524
525 ::osl::ClearableMutexGuard guard(m_rMutex);
526
527 if (nullptr == m_aNodePtr) {
528 throw RuntimeException();
529 }
530
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(); }
537
538 // check whether the attribute is not in use by another element
539 if (pAttr->parent) {
540 DOMException e;
541 e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR;
542 throw e;
543 }
544
545 xmlAttrPtr res = nullptr;
546 xmlChar const*const pContent(
547 (pAttr->children) ? pAttr->children->content : nullptr);
548
549 if (bNS) {
550 xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
551 res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent);
552 } else {
553 res = xmlNewProp(m_aNodePtr, pAttr->name, pContent);
554 }
555
556 // get the new attr node
557 Reference< XAttr > const xAttr(
558 static_cast< XNode* >(GetOwnerDocument().GetCNode(
559 reinterpret_cast<xmlNodePtr>(res)).get()),
560 UNO_QUERY_THROW);
561
562 // attribute addition event
563 // dispatch DOMAttrModified event
564 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
565 Reference< XMutationEvent > event(docevent->createEvent(
566 "DOMAttrModified"), UNO_QUERY);
567 event->initMutationEvent("DOMAttrModified",
568 true, false, xAttr,
569 OUString(), xAttr->getValue(), xAttr->getName(),
570 AttrChangeType_ADDITION);
571
572 guard.clear(); // release mutex before calling event handlers
573
574 dispatchEvent(event);
575 dispatchSubtreeModified();
576
577 return xAttr;
578 }
579
580 Reference< XAttr >
581 CElement::setAttributeNode(const Reference< XAttr >& newAttr)
582 {
583 return setAttributeNode_Impl_Lock(newAttr, false);
584 }
585
589 Reference< XAttr >
590 CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr)
591 {
592 return setAttributeNode_Impl_Lock(newAttr, true);
593 }
594
598 void SAL_CALL
599 CElement::setAttribute(OUString const& name, OUString const& value)
600 {
601 ::osl::ClearableMutexGuard guard(m_rMutex);
602
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());
607
608 if (nullptr == m_aNodePtr) {
609 throw RuntimeException();
610 }
611 OUString oldValue;
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);
618 } else {
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);
623 }
624
625 // dispatch DOMAttrModified event
626 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
627 Reference< XMutationEvent > event(docevent->createEvent(
628 "DOMAttrModified"), UNO_QUERY);
629 event->initMutationEvent("DOMAttrModified",
630 true, false,
632 oldValue, value, name, aChangeType);
633
634 guard.clear(); // release mutex before calling event handlers
635 dispatchEvent(event);
636 dispatchSubtreeModified();
637 }
638
642 void SAL_CALL
643 CElement::setAttributeNS(OUString const& namespaceURI,
644 OUString const& qualifiedName, OUString const& value)
645 {
646 if (namespaceURI.isEmpty()) throw RuntimeException();
647
648 ::osl::ClearableMutexGuard guard(m_rMutex);
649
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(':');
656 if (idx != -1)
657 {
659 qualifiedName.subView(0,idx),
660 RTL_TEXTENCODING_UTF8);
661 pPrefix = reinterpret_cast<xmlChar const *>(o2.getStr());
663 qualifiedName.subView(idx+1),
664 RTL_TEXTENCODING_UTF8);
665 pLName = reinterpret_cast<xmlChar const *>(o3.getStr());
666 } else {
667 pPrefix = reinterpret_cast<xmlChar const *>("");
668 pLName = pQName;
669 }
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());
674
675 if (nullptr == m_aNodePtr) {
676 throw RuntimeException();
677 }
678
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);
684 }
685
686 if (strcmp(reinterpret_cast<char const *>(pNs->href), reinterpret_cast<char const *>(pURI)) != 0) {
687 // ambiguous ns prefix
688 throw RuntimeException();
689 }
690
691 // found namespace matches
692
693 OUString oldValue;
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);
700 } else {
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);
705 }
706 // dispatch DOMAttrModified event
707 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
708 Reference< XMutationEvent > event(docevent->createEvent(
709 "DOMAttrModified"), UNO_QUERY);
710 event->initMutationEvent(
711 "DOMAttrModified", 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);
714
715 guard.clear(); // release mutex before calling event handlers
716 dispatchEvent(event);
717 dispatchSubtreeModified();
718 }
719
720 Reference< XNamedNodeMap > SAL_CALL
722 {
723 ::osl::MutexGuard const g(m_rMutex);
724
725 Reference< XNamedNodeMap > const xMap(
726 new CAttributesMap(this, m_rMutex));
727 return xMap;
728 }
729
730 OUString SAL_CALL CElement::getNodeName()
731 {
732 return getLocalName();
733 }
734
735 OUString SAL_CALL CElement::getLocalName()
736 {
737 ::osl::MutexGuard const g(m_rMutex);
738
739 OUString aName;
740 if (m_aNodePtr != nullptr)
741 {
742 const xmlChar* pName = m_aNodePtr->name;
743 aName = OUString(reinterpret_cast<const char*>(pName), strlen(reinterpret_cast<const char*>(pName)), RTL_TEXTENCODING_UTF8);
744 }
745 return aName;
746 }
747
748 OUString SAL_CALL CElement::getNodeValue()
749 {
750 return OUString();
751 }
752}
753
754/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const char * pName
xmlNsPtr GetNamespace(xmlNodePtr const pNode)
return the libxml namespace corresponding to m_pNamespace on pNode
Definition: attr.cxx:47
virtual void SAL_CALL removeAttributeNS(const OUString &namespaceURI, const OUString &localName) override
Removes an attribute by local name and namespace URI.
Definition: element.cxx:434
virtual void fastSaxify(Context &i_rContext) override
Definition: element.cxx:104
virtual css::uno::Reference< css::xml::dom::XAttr > SAL_CALL removeAttributeNode(const css::uno::Reference< css::xml::dom::XAttr > &oldAttr) override
Removes the specified attribute node.
Definition: element.cxx:464
virtual OUString SAL_CALL getAttribute(const OUString &name) override
Retrieves an attribute value by name.
Definition: element.cxx:231
virtual css::uno::Reference< css::xml::dom::XNodeList > SAL_CALL getElementsByTagNameNS(const OUString &namespaceURI, const OUString &localName) override
Returns a NodeList of all the descendant Elements with a given local name and namespace URI in the or...
Definition: element.cxx:353
virtual OUString SAL_CALL getNodeValue() override
Definition: element.cxx:748
virtual OUString SAL_CALL getNodeName() override
Definition: element.cxx:730
virtual css::uno::Reference< css::xml::dom::XNodeList > SAL_CALL getElementsByTagName(const OUString &name) override
Returns a NodeList of all descendant Elements with a given tag name, in the order in which they are e...
Definition: element.cxx:338
virtual css::uno::Reference< css::xml::dom::XAttr > SAL_CALL setAttributeNodeNS(const css::uno::Reference< css::xml::dom::XAttr > &newAttr) override
Adds a new attribute.
Definition: element.cxx:590
virtual css::uno::Reference< css::xml::dom::XNamedNodeMap > SAL_CALL getAttributes() override
Definition: element.cxx:721
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType, css::xml::dom::NodeType const *) override
Definition: element.cxx:205
virtual void SAL_CALL removeAttribute(const OUString &name) override
Removes an attribute by name.
Definition: element.cxx:411
virtual void SAL_CALL setAttribute(const OUString &name, const OUString &value) override
Adds a new attribute.
Definition: element.cxx:599
virtual OUString SAL_CALL getLocalName() override
Definition: element.cxx:735
virtual OUString SAL_CALL getPrefix() override
Definition: element.hxx:195
CElement(CDocument const &rDocument, ::osl::Mutex const &rMutex, xmlNodePtr const pNode)
Definition: element.cxx:50
virtual void SAL_CALL setAttributeNS(const OUString &namespaceURI, const OUString &qualifiedName, const OUString &value) override
Adds a new attribute.
Definition: element.cxx:643
virtual css::uno::Reference< css::xml::dom::XAttr > SAL_CALL setAttributeNode(const css::uno::Reference< css::xml::dom::XAttr > &newAttr) override
Adds a new attribute node.
Definition: element.cxx:581
virtual css::uno::Reference< css::xml::dom::XAttr > SAL_CALL getAttributeNodeNS(const OUString &namespaceURI, const OUString &localName) override
Retrieves an Attr node by local name and namespace URI.
Definition: element.cxx:277
virtual OUString SAL_CALL getAttributeNS(const OUString &namespaceURI, const OUString &localName) override
Retrieves an attribute value by local name and namespace URI.
Definition: element.cxx:307
virtual OUString SAL_CALL getTagName() override
The name of the element.
Definition: element.cxx:366
virtual css::uno::Reference< css::xml::dom::XAttr > SAL_CALL getAttributeNode(const OUString &name) override
Retrieves an attribute node by name.
Definition: element.cxx:253
virtual css::uno::Reference< css::xml::dom::XDocument > SAL_CALL getOwnerDocument() override
Definition: element.hxx:187
virtual sal_Bool SAL_CALL hasAttributeNS(const OUString &namespaceURI, const OUString &localName) override
Returns true when an attribute with a given local name and namespace URI is specified on this element...
Definition: element.cxx:396
virtual void saxify(const css::uno::Reference< css::xml::sax::XDocumentHandler > &i_xHandler) override
Definition: element.cxx:56
css::uno::Reference< css::xml::dom::XAttr > setAttributeNode_Impl_Lock(css::uno::Reference< css::xml::dom::XAttr > const &xNewAttr, bool const bNS)
Adds a new attribute node.
Definition: element.cxx:516
virtual sal_Bool SAL_CALL hasAttribute(const OUString &name) override
Returns true when an attribute with a given name is specified on this element or has a default value,...
Definition: element.cxx:383
Any value
::osl::Mutex & m_rMutex
const char * name
const sal_uInt16 idx[]
OUString aName
Definition: attr.cxx:38
::cppu::ImplInheritanceHelper< CNode, css::xml::dom::XElement > CElement_Base
Definition: element.hxx:35
void popContext(Context &io_rContext)
Definition: node.cxx:61
void pushContext(Context &io_rContext)
Definition: node.cxx:52
sal_Int32 getTokenWithPrefix(const Context &rContext, const char *pPrefix, const char *pName)
Definition: node.cxx:100
sal_Int32 getToken(const Context &rContext, const char *pToken)
Definition: node.cxx:94
void addNamespaces(Context &io_rContext, xmlNodePtr pNode)
add namespaces on this node to context
Definition: node.cxx:66
@ Exception
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
NodeType
css::uno::Reference< css::xml::sax::XFastContextHandler > mxCurrentHandler
Definition: node.hxx:75
css::uno::Reference< css::xml::sax::XFastDocumentHandler > mxDocHandler
Definition: node.hxx:76
::rtl::Reference< sax_fastparser::FastAttributeList > mxAttribList
Definition: node.hxx:74
unsigned char sal_Bool