Line data Source code
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 <boost/shared_ptr.hpp>
25 :
26 : #include <osl/diagnose.h>
27 : #include <rtl/ustrbuf.hxx>
28 :
29 : #include <com/sun/star/xml/sax/FastToken.hpp>
30 :
31 : #include <comphelper/attributelist.hxx>
32 :
33 : #include <node.hxx>
34 : #include <attr.hxx>
35 : #include <elementlist.hxx>
36 : #include <attributesmap.hxx>
37 : #include <document.hxx>
38 :
39 : #include "../events/mutationevent.hxx"
40 :
41 : using namespace css::uno;
42 : using namespace css::xml::dom;
43 : using namespace css::xml::dom::events;
44 : using namespace css::xml::sax;
45 :
46 : namespace DOM
47 : {
48 :
49 597947 : CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex,
50 : xmlNodePtr const pNode)
51 597947 : : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode)
52 : {
53 597947 : }
54 :
55 107606 : void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler)
56 : {
57 107606 : if (!i_xHandler.is()) throw RuntimeException();
58 : comphelper::AttributeList *pAttrs =
59 107606 : new comphelper::AttributeList();
60 107606 : OUString type = "";
61 : // add namespace definitions to attributes
62 113051 : for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != 0; pNs = pNs->next) {
63 5445 : const xmlChar *pPrefix = pNs->prefix ? pNs->prefix : reinterpret_cast<const xmlChar*>("");
64 : OUString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
65 5445 : strlen(reinterpret_cast<const char*>(pPrefix)),
66 5445 : RTL_TEXTENCODING_UTF8);
67 5445 : OUString name = (prefix.isEmpty())
68 10890 : ? OUString( "xmlns" ) : "xmlns:" + prefix;
69 5445 : const xmlChar *pHref = pNs->href;
70 : OUString val(reinterpret_cast<const sal_Char*>(pHref),
71 5445 : strlen(reinterpret_cast<const char*>(pHref)),
72 10890 : RTL_TEXTENCODING_UTF8);
73 5445 : pAttrs->AddAttribute(name, type, val);
74 5445 : }
75 : // add attributes
76 252654 : for (xmlAttrPtr pAttr = m_aNodePtr->properties;
77 : pAttr != 0; pAttr = pAttr->next) {
78 145048 : ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
79 290096 : reinterpret_cast<xmlNodePtr>(pAttr));
80 : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
81 290096 : OUString prefix = pNode->getPrefix();
82 145048 : OUString name = (prefix.isEmpty())
83 125068 : ? pNode->getLocalName()
84 415164 : : prefix + ":" + pNode->getLocalName();
85 290096 : OUString val = pNode->getNodeValue();
86 145048 : pAttrs->AddAttribute(name, type, val);
87 145048 : }
88 215212 : OUString prefix = getPrefix();
89 107606 : OUString name = (prefix.isEmpty())
90 562 : ? getLocalName()
91 215774 : : prefix + ":" + getLocalName();
92 215212 : Reference< XAttributeList > xAttrList(pAttrs);
93 107606 : i_xHandler->startElement(name, xAttrList);
94 : // recurse
95 216379 : for (xmlNodePtr pChild = m_aNodePtr->children;
96 : pChild != 0; pChild = pChild->next) {
97 : ::rtl::Reference<CNode> const pNode(
98 108773 : GetOwnerDocument().GetCNode(pChild));
99 : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
100 108773 : pNode->saxify(i_xHandler);
101 108773 : }
102 215212 : i_xHandler->endElement(name);
103 107606 : }
104 :
105 317841 : void CElement::fastSaxify( Context& i_rContext )
106 : {
107 317841 : if (!i_rContext.mxDocHandler.is()) throw RuntimeException();
108 317841 : pushContext(i_rContext);
109 317841 : addNamespaces(i_rContext,m_aNodePtr);
110 :
111 : // add attributes
112 317841 : i_rContext.mxAttribList->clear();
113 708184 : for (xmlAttrPtr pAttr = m_aNodePtr->properties;
114 : pAttr != 0; pAttr = pAttr->next) {
115 390343 : ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
116 780686 : reinterpret_cast<xmlNodePtr>(pAttr));
117 : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
118 :
119 390343 : const xmlChar* xName = pAttr->name;
120 390343 : sal_Int32 nAttributeToken=FastToken::DONTKNOW;
121 :
122 390343 : 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 120 : reinterpret_cast<char const *>(xName) );
126 : else
127 390223 : nAttributeToken = getToken( i_rContext, reinterpret_cast<char const *>(xName) );
128 :
129 390343 : if( nAttributeToken != FastToken::DONTKNOW )
130 : i_rContext.mxAttribList->add( nAttributeToken,
131 390244 : OUStringToOString(pNode->getNodeValue(),
132 390244 : RTL_TEXTENCODING_UTF8));
133 390343 : }
134 :
135 317841 : const xmlChar* xPrefix = m_aNodePtr->ns ? m_aNodePtr->ns->prefix : reinterpret_cast<const xmlChar*>("");
136 317841 : const xmlChar* xName = m_aNodePtr->name;
137 317841 : sal_Int32 nElementToken=FastToken::DONTKNOW;
138 317841 : if( strlen(reinterpret_cast<char const *>(xPrefix)) )
139 317840 : nElementToken = getTokenWithPrefix( i_rContext, reinterpret_cast<char const *>(xPrefix), reinterpret_cast<char const *>(xName) );
140 : else
141 1 : nElementToken = getToken( i_rContext, reinterpret_cast<char const *>(xName) );
142 :
143 317841 : Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler);
144 : try
145 : {
146 317841 : Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList.get() );
147 317841 : if( nElementToken == FastToken::DONTKNOW )
148 : {
149 139 : const OUString aNamespace;
150 : const OUString aElementName( reinterpret_cast<char const *>(xPrefix),
151 139 : strlen(reinterpret_cast<char const *>(xPrefix)),
152 278 : RTL_TEXTENCODING_UTF8 );
153 :
154 139 : if( xParentHandler.is() )
155 36 : i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
156 : else
157 103 : i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
158 :
159 139 : if( i_rContext.mxCurrentHandler.is() )
160 139 : i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr );
161 : }
162 : else
163 : {
164 317702 : if( xParentHandler.is() )
165 306266 : i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr );
166 : else
167 11436 : i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr );
168 :
169 317702 : if( i_rContext.mxCurrentHandler.is() )
170 162602 : i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr );
171 317841 : }
172 : }
173 0 : catch( Exception& )
174 : {}
175 :
176 : // recurse
177 642586 : for (xmlNodePtr pChild = m_aNodePtr->children;
178 : pChild != 0; pChild = pChild->next) {
179 : ::rtl::Reference<CNode> const pNode(
180 324745 : GetOwnerDocument().GetCNode(pChild));
181 : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
182 324745 : pNode->fastSaxify(i_rContext);
183 324745 : }
184 :
185 317841 : if( i_rContext.mxCurrentHandler.is() ) try
186 : {
187 162602 : if( nElementToken != FastToken::DONTKNOW )
188 162602 : i_rContext.mxCurrentHandler->endFastElement( nElementToken );
189 : else
190 : {
191 0 : const OUString aNamespace;
192 : const OUString aElementName( reinterpret_cast<char const *>(xPrefix),
193 0 : strlen(reinterpret_cast<char const *>(xPrefix)),
194 0 : RTL_TEXTENCODING_UTF8 );
195 :
196 0 : i_rContext.mxCurrentHandler->endUnknownElement( aNamespace, aElementName );
197 : }
198 : }
199 0 : catch( Exception& )
200 : {}
201 :
202 : // restore after children have been processed
203 317841 : i_rContext.mxCurrentHandler = xParentHandler;
204 317841 : popContext(i_rContext);
205 317841 : }
206 :
207 75032 : bool CElement::IsChildTypeAllowed(NodeType const nodeType)
208 : {
209 75032 : switch (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:
216 75031 : return true;
217 : case NodeType_ATTRIBUTE_NODE:
218 : /* this is not relly 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 */
222 1 : return true;
223 : default:
224 0 : return false;
225 : }
226 : }
227 :
228 :
229 : /**
230 : Retrieves an attribute value by name.
231 : return empty string if attribute is not set
232 : */
233 6 : OUString SAL_CALL CElement::getAttribute(OUString const& name)
234 : throw (RuntimeException, std::exception)
235 : {
236 6 : ::osl::MutexGuard const g(m_rMutex);
237 :
238 6 : if (0 == m_aNodePtr) {
239 0 : return OUString();
240 : }
241 : // search properties
242 12 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
243 : ::boost::shared_ptr<xmlChar const> const pValue(
244 12 : xmlGetProp(m_aNodePtr, reinterpret_cast<xmlChar const *>(o1.getStr())), xmlFree);
245 : OUString const ret( (pValue)
246 5 : ? OUString(reinterpret_cast<sal_Char const*>(pValue.get()),
247 5 : strlen(reinterpret_cast<char const*>(pValue.get())),
248 : RTL_TEXTENCODING_UTF8)
249 22 : : OUString() );
250 12 : return ret;
251 : }
252 :
253 : /**
254 : Retrieves an attribute node by name.
255 : */
256 14 : Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name)
257 : throw (RuntimeException, std::exception)
258 : {
259 14 : ::osl::MutexGuard const g(m_rMutex);
260 :
261 14 : if (0 == m_aNodePtr) {
262 0 : return 0;
263 : }
264 28 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
265 : xmlChar const*const pName =
266 14 : reinterpret_cast<xmlChar const*>(o1.getStr());
267 14 : xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
268 14 : if (0 == pAttr) {
269 2 : return 0;
270 : }
271 : Reference< XAttr > const xRet(
272 12 : static_cast< XNode* >(GetOwnerDocument().GetCNode(
273 36 : reinterpret_cast<xmlNodePtr>(pAttr)).get()),
274 24 : UNO_QUERY_THROW);
275 26 : return xRet;
276 : }
277 :
278 : /**
279 : Retrieves an Attr node by local name and namespace URI.
280 : */
281 50660 : Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS(
282 : const OUString& namespaceURI, const OUString& localName)
283 : throw (RuntimeException, std::exception)
284 : {
285 50660 : ::osl::MutexGuard const g(m_rMutex);
286 :
287 50660 : if (0 == m_aNodePtr) {
288 0 : return 0;
289 : }
290 101320 : OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
291 : xmlChar const*const pName =
292 50660 : reinterpret_cast<xmlChar const*>(o1.getStr());
293 101320 : OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
294 : xmlChar const*const pNS =
295 50660 : reinterpret_cast<xmlChar const*>(o2.getStr());
296 50660 : xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS);
297 50660 : if (0 == pAttr) {
298 2 : return 0;
299 : }
300 : Reference< XAttr > const xRet(
301 50658 : static_cast< XNode* >(GetOwnerDocument().GetCNode(
302 151974 : reinterpret_cast<xmlNodePtr>(pAttr)).get()),
303 101316 : UNO_QUERY_THROW);
304 101318 : return xRet;
305 : }
306 :
307 : /**
308 : Retrieves an attribute value by local name and namespace URI.
309 : return empty string if attribute is not set
310 : */
311 : OUString SAL_CALL
312 108648 : CElement::getAttributeNS(
313 : OUString const& namespaceURI, OUString const& localName)
314 : throw (RuntimeException, std::exception)
315 : {
316 108648 : ::osl::MutexGuard const g(m_rMutex);
317 :
318 108648 : if (0 == m_aNodePtr) {
319 0 : return OUString();
320 : }
321 217296 : OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
322 : xmlChar const*const pName =
323 108648 : reinterpret_cast<xmlChar const*>(o1.getStr());
324 217296 : OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
325 : xmlChar const*const pNS =
326 108648 : reinterpret_cast<xmlChar const*>(o2.getStr());
327 : ::boost::shared_ptr<xmlChar const> const pValue(
328 217296 : xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree);
329 108648 : if (0 == pValue) {
330 82101 : return OUString();
331 : }
332 26547 : OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()),
333 26547 : strlen(reinterpret_cast<char const*>(pValue.get())),
334 79641 : RTL_TEXTENCODING_UTF8);
335 135195 : return ret;
336 : }
337 :
338 : /**
339 : Returns a NodeList of all descendant Elements with a given tag name,
340 : in the order in which they are
341 : encountered in a preorder traversal of this Element tree.
342 : */
343 : Reference< XNodeList > SAL_CALL
344 3 : CElement::getElementsByTagName(OUString const& rLocalName)
345 : throw (RuntimeException, std::exception)
346 : {
347 3 : ::osl::MutexGuard const g(m_rMutex);
348 :
349 : Reference< XNodeList > const xList(
350 3 : new CElementList(this, m_rMutex, rLocalName));
351 3 : return xList;
352 : }
353 :
354 : /**
355 : Returns a NodeList of all the descendant Elements with a given local
356 : name and namespace URI in the order in which they are encountered in
357 : a preorder traversal of this Element tree.
358 : */
359 : Reference< XNodeList > SAL_CALL
360 2 : CElement::getElementsByTagNameNS(
361 : OUString const& rNamespaceURI, OUString const& rLocalName)
362 : throw (RuntimeException, std::exception)
363 : {
364 2 : ::osl::MutexGuard const g(m_rMutex);
365 :
366 : Reference< XNodeList > const xList(
367 2 : new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI));
368 2 : return xList;
369 : }
370 :
371 : /**
372 : The name of the element.
373 : */
374 14760 : OUString SAL_CALL CElement::getTagName()
375 : throw (RuntimeException, std::exception)
376 : {
377 14760 : ::osl::MutexGuard const g(m_rMutex);
378 :
379 14760 : if (0 == m_aNodePtr) {
380 0 : return OUString();
381 : }
382 : OUString const ret(reinterpret_cast<char const *>(m_aNodePtr->name),
383 29520 : strlen(reinterpret_cast<char const *>(m_aNodePtr->name)), RTL_TEXTENCODING_UTF8);
384 29520 : return ret;
385 : }
386 :
387 :
388 : /**
389 : Returns true when an attribute with a given name is specified on this
390 : element or has a default value, false otherwise.
391 : */
392 2 : sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name)
393 : throw (RuntimeException, std::exception)
394 : {
395 2 : ::osl::MutexGuard const g(m_rMutex);
396 :
397 4 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
398 2 : xmlChar const *xName = reinterpret_cast<xmlChar const *>(o1.getStr());
399 4 : return (m_aNodePtr != NULL && xmlHasProp(m_aNodePtr, xName) != NULL);
400 : }
401 :
402 : /**
403 : Returns true when an attribute with a given local name and namespace
404 : URI is specified on this element or has a default value, false otherwise.
405 : */
406 2 : sal_Bool SAL_CALL CElement::hasAttributeNS(
407 : OUString const& namespaceURI, OUString const& localName)
408 : throw (RuntimeException, std::exception)
409 : {
410 2 : ::osl::MutexGuard const g(m_rMutex);
411 :
412 4 : OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
413 2 : xmlChar const *xName = reinterpret_cast<xmlChar const *>(o1.getStr());
414 4 : OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
415 2 : xmlChar const *xNs = reinterpret_cast<xmlChar const *>(o2.getStr());
416 4 : return (m_aNodePtr != NULL && xmlHasNsProp(m_aNodePtr, xName, xNs) != NULL);
417 : }
418 :
419 : /**
420 : Removes an attribute by name.
421 : */
422 2 : void SAL_CALL CElement::removeAttribute(OUString const& name)
423 : throw (RuntimeException, DOMException, std::exception)
424 : {
425 2 : ::osl::MutexGuard const g(m_rMutex);
426 :
427 2 : if (0 == m_aNodePtr) {
428 2 : return;
429 : }
430 4 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
431 : xmlChar const*const pName =
432 2 : reinterpret_cast<xmlChar const*>(o1.getStr());
433 2 : xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
434 2 : if (0 == xmlUnsetProp(m_aNodePtr, pName)) {
435 1 : ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
436 2 : reinterpret_cast<xmlNodePtr>(pAttr), false));
437 1 : if (pCNode.is()) {
438 0 : pCNode->invalidate(); // freed by xmlUnsetProp
439 1 : }
440 2 : }
441 : }
442 :
443 : /**
444 : Removes an attribute by local name and namespace URI.
445 : */
446 2 : void SAL_CALL CElement::removeAttributeNS(
447 : OUString const& namespaceURI, OUString const& localName)
448 : throw (RuntimeException, DOMException, std::exception)
449 : {
450 2 : ::osl::MutexGuard const g(m_rMutex);
451 :
452 2 : if (0 == m_aNodePtr) {
453 2 : return;
454 : }
455 4 : OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
456 : xmlChar const*const pName =
457 2 : reinterpret_cast<xmlChar const*>(o1.getStr());
458 4 : OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
459 : xmlChar const*const pURI =
460 2 : reinterpret_cast<xmlChar const*>(o2.getStr());
461 : xmlNsPtr const pNs =
462 2 : xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI);
463 2 : xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI);
464 2 : if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) {
465 1 : ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
466 2 : reinterpret_cast<xmlNodePtr>(pAttr), false));
467 1 : if (pCNode.is()) {
468 0 : pCNode->invalidate(); // freed by xmlUnsetNsProp
469 1 : }
470 2 : }
471 : }
472 :
473 : /**
474 : Removes the specified attribute node.
475 : */
476 : Reference< XAttr > SAL_CALL
477 6 : CElement::removeAttributeNode(Reference< XAttr > const& oldAttr)
478 : throw (RuntimeException, DOMException, std::exception)
479 : {
480 6 : ::osl::MutexGuard const g(m_rMutex);
481 :
482 6 : if (0 == m_aNodePtr) {
483 0 : return 0;
484 : }
485 :
486 : ::rtl::Reference<CNode> const pCNode(
487 12 : CNode::GetImplementation(Reference<XNode>(oldAttr.get())));
488 6 : if (!pCNode.is()) { throw RuntimeException(); }
489 :
490 5 : xmlNodePtr const pNode = pCNode->GetNodePtr();
491 5 : xmlAttrPtr const pAttr = reinterpret_cast<xmlAttrPtr>(pNode);
492 5 : if (!pAttr) { throw RuntimeException(); }
493 :
494 5 : if (pAttr->parent != m_aNodePtr)
495 : {
496 1 : DOMException e;
497 1 : e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
498 1 : throw e;
499 : }
500 4 : if (pAttr->doc != m_aNodePtr->doc)
501 : {
502 0 : DOMException e;
503 0 : e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
504 0 : throw e;
505 : }
506 :
507 8 : Reference< XAttr > aAttr;
508 4 : if (!oldAttr->getNamespaceURI().isEmpty()) {
509 2 : OUStringBuffer qname(oldAttr->getPrefix());
510 2 : if (!qname.isEmpty()) {
511 1 : qname.append(':');
512 : }
513 2 : qname.append(oldAttr->getName());
514 10 : aAttr = GetOwnerDocument().createAttributeNS(
515 10 : oldAttr->getNamespaceURI(), qname.makeStringAndClear());
516 : } else {
517 2 : aAttr = GetOwnerDocument().createAttribute(oldAttr->getName());
518 : }
519 4 : aAttr->setValue(oldAttr->getValue());
520 4 : xmlRemoveProp(pAttr);
521 4 : pCNode->invalidate(); // freed by xmlRemoveProp
522 :
523 10 : return aAttr;
524 : }
525 :
526 : /**
527 : Adds a new attribute node.
528 : */
529 : Reference< XAttr >
530 6 : CElement::setAttributeNode_Impl_Lock(
531 : Reference< XAttr > const& xNewAttr, bool const bNS)
532 : {
533 6 : if (xNewAttr->getOwnerDocument() != getOwnerDocument()) {
534 0 : DOMException e;
535 0 : e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
536 0 : throw e;
537 : }
538 :
539 6 : ::osl::ClearableMutexGuard guard(m_rMutex);
540 :
541 6 : if (0 == m_aNodePtr) {
542 0 : throw RuntimeException();
543 : }
544 :
545 : // get the implementation
546 : CAttr *const pCAttr = dynamic_cast<CAttr*>(
547 6 : CNode::GetImplementation(xNewAttr));
548 6 : if (!pCAttr) { throw RuntimeException(); }
549 : xmlAttrPtr const pAttr =
550 6 : reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr());
551 6 : if (!pAttr) { throw RuntimeException(); }
552 :
553 : // check whether the attribute is not in use by another element
554 6 : if (pAttr->parent) {
555 2 : DOMException e;
556 2 : e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR;
557 2 : throw e;
558 : }
559 :
560 4 : xmlAttrPtr res = NULL;
561 : xmlChar const*const pContent(
562 4 : (pAttr->children) ? pAttr->children->content : 0);
563 :
564 4 : if (bNS) {
565 2 : xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
566 2 : res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent);
567 : } else {
568 2 : res = xmlNewProp(m_aNodePtr, pAttr->name, pContent);
569 : }
570 :
571 : // get the new attr node
572 : Reference< XAttr > const xAttr(
573 4 : static_cast< XNode* >(GetOwnerDocument().GetCNode(
574 12 : reinterpret_cast<xmlNodePtr>(res)).get()),
575 4 : UNO_QUERY_THROW);
576 :
577 : // attribute addition event
578 : // dispatch DOMAttrModified event
579 8 : Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
580 4 : Reference< XMutationEvent > event(docevent->createEvent(
581 8 : "DOMAttrModified"), UNO_QUERY);
582 4 : event->initMutationEvent("DOMAttrModified",
583 : sal_True, sal_False, xAttr,
584 8 : OUString(), xAttr->getValue(), xAttr->getName(),
585 12 : AttrChangeType_ADDITION);
586 :
587 4 : guard.clear(); // release mutex before calling event handlers
588 :
589 4 : dispatchEvent(event);
590 4 : dispatchSubtreeModified();
591 :
592 10 : return xAttr;
593 : }
594 :
595 : Reference< XAttr >
596 3 : CElement::setAttributeNode(const Reference< XAttr >& newAttr)
597 : throw (RuntimeException, DOMException, std::exception)
598 : {
599 3 : return setAttributeNode_Impl_Lock(newAttr, false);
600 : }
601 :
602 : /**
603 : Adds a new attribute.
604 : */
605 : Reference< XAttr >
606 3 : CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr)
607 : throw (RuntimeException, DOMException, std::exception)
608 : {
609 3 : return setAttributeNode_Impl_Lock(newAttr, true);
610 : }
611 :
612 : /**
613 : Adds a new attribute.
614 : */
615 : void SAL_CALL
616 9 : CElement::setAttribute(OUString const& name, OUString const& value)
617 : throw (RuntimeException, DOMException, std::exception)
618 : {
619 9 : ::osl::ClearableMutexGuard guard(m_rMutex);
620 :
621 18 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
622 9 : xmlChar const *xName = reinterpret_cast<xmlChar const *>(o1.getStr());
623 18 : OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
624 9 : xmlChar const *xValue = reinterpret_cast<xmlChar const *>(o2.getStr());
625 :
626 9 : if (0 == m_aNodePtr) {
627 0 : throw RuntimeException();
628 : }
629 18 : OUString oldValue;
630 9 : AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
631 : ::boost::shared_ptr<xmlChar const> const pOld(
632 18 : xmlGetProp(m_aNodePtr, xName), xmlFree);
633 9 : if (pOld == 0) {
634 9 : aChangeType = AttrChangeType_ADDITION;
635 9 : xmlNewProp(m_aNodePtr, xName, xValue);
636 : } else {
637 0 : oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
638 0 : strlen(reinterpret_cast<char const*>(pOld.get())),
639 0 : RTL_TEXTENCODING_UTF8);
640 0 : xmlSetProp(m_aNodePtr, xName, xValue);
641 : }
642 :
643 : // dispatch DOMAttrModified event
644 18 : Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
645 9 : Reference< XMutationEvent > event(docevent->createEvent(
646 18 : "DOMAttrModified"), UNO_QUERY);
647 9 : event->initMutationEvent("DOMAttrModified",
648 : sal_True, sal_False,
649 9 : Reference< XNode >(getAttributeNode(name), UNO_QUERY),
650 18 : oldValue, value, name, aChangeType);
651 :
652 9 : guard.clear(); // release mutex before calling event handlers
653 9 : dispatchEvent(event);
654 18 : dispatchSubtreeModified();
655 9 : }
656 :
657 : /**
658 : Adds a new attribute.
659 : */
660 : void SAL_CALL
661 50655 : CElement::setAttributeNS(OUString const& namespaceURI,
662 : OUString const& qualifiedName, OUString const& value)
663 : throw (RuntimeException, DOMException, std::exception)
664 : {
665 50655 : if (namespaceURI.isEmpty()) throw RuntimeException();
666 :
667 50655 : ::osl::ClearableMutexGuard guard(m_rMutex);
668 :
669 101310 : OString o1, o2, o3, o4, o5;
670 50655 : xmlChar const *xPrefix = NULL;
671 50655 : xmlChar const *xLName = NULL;
672 50655 : o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8);
673 50655 : xmlChar const *xQName = reinterpret_cast<xmlChar const *>(o1.getStr());
674 50655 : sal_Int32 idx = qualifiedName.indexOf(':');
675 50655 : if (idx != -1)
676 : {
677 101306 : o2 = OUStringToOString(
678 : qualifiedName.copy(0,idx),
679 50653 : RTL_TEXTENCODING_UTF8);
680 50653 : xPrefix = reinterpret_cast<xmlChar const *>(o2.getStr());
681 101306 : o3 = OUStringToOString(
682 : qualifiedName.copy(idx+1),
683 50653 : RTL_TEXTENCODING_UTF8);
684 50653 : xLName = reinterpret_cast<xmlChar const *>(o3.getStr());
685 : } else {
686 2 : xPrefix = reinterpret_cast<xmlChar const *>("");
687 2 : xLName = xQName;
688 : }
689 50655 : o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
690 50655 : o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
691 50655 : xmlChar const *xURI= reinterpret_cast<xmlChar const *>(o4.getStr());
692 50655 : xmlChar const *xValue = reinterpret_cast<xmlChar const *>(o5.getStr());
693 :
694 50655 : if (0 == m_aNodePtr) {
695 0 : throw RuntimeException();
696 : }
697 :
698 : //find the right namespace
699 50655 : xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix);
700 : // if no namespace found, create a new one
701 50655 : if (pNs == NULL) {
702 990 : pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix);
703 : }
704 :
705 50655 : if (strcmp(reinterpret_cast<char const *>(pNs->href), reinterpret_cast<char const *>(xURI)) != 0) {
706 : // ambiguous ns prefix
707 0 : throw RuntimeException();
708 : }
709 :
710 : // found namespace matches
711 :
712 101310 : OUString oldValue;
713 50655 : AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
714 : ::boost::shared_ptr<xmlChar const> const pOld(
715 101310 : xmlGetNsProp(m_aNodePtr, xLName, pNs->href), xmlFree);
716 50655 : if (pOld == 0) {
717 50639 : aChangeType = AttrChangeType_ADDITION;
718 50639 : xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue);
719 : } else {
720 32 : oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
721 16 : strlen(reinterpret_cast<char const*>(pOld.get())),
722 16 : RTL_TEXTENCODING_UTF8);
723 16 : xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue);
724 : }
725 : // dispatch DOMAttrModified event
726 101310 : Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
727 50655 : Reference< XMutationEvent > event(docevent->createEvent(
728 101310 : "DOMAttrModified"), UNO_QUERY);
729 50655 : event->initMutationEvent(
730 : "DOMAttrModified", sal_True, sal_False,
731 50655 : Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString(reinterpret_cast<char const *>(xLName), strlen(reinterpret_cast<char const *>(xLName)), RTL_TEXTENCODING_UTF8)), UNO_QUERY),
732 101310 : oldValue, value, qualifiedName, aChangeType);
733 :
734 50655 : guard.clear(); // release mutex before calling event handlers
735 50655 : dispatchEvent(event);
736 101310 : dispatchSubtreeModified();
737 50655 : }
738 :
739 : Reference< XNamedNodeMap > SAL_CALL
740 41891 : CElement::getAttributes() throw (RuntimeException, std::exception)
741 : {
742 41891 : ::osl::MutexGuard const g(m_rMutex);
743 :
744 : Reference< XNamedNodeMap > const xMap(
745 41891 : new CAttributesMap(this, m_rMutex));
746 41891 : return xMap;
747 : }
748 :
749 7201 : OUString SAL_CALL CElement::getNodeName()throw (RuntimeException, std::exception)
750 : {
751 7201 : return getLocalName();
752 : }
753 :
754 114830 : OUString SAL_CALL CElement::getLocalName()throw (RuntimeException, std::exception)
755 : {
756 114830 : ::osl::MutexGuard const g(m_rMutex);
757 :
758 114830 : OUString aName;
759 114830 : if (m_aNodePtr != NULL)
760 : {
761 114830 : const xmlChar* xName = m_aNodePtr->name;
762 114830 : aName = OUString(reinterpret_cast<const char*>(xName), strlen(reinterpret_cast<const char*>(xName)), RTL_TEXTENCODING_UTF8);
763 : }
764 114830 : return aName;
765 : }
766 :
767 1 : OUString SAL_CALL CElement::getNodeValue() throw (RuntimeException, std::exception)
768 : {
769 1 : return OUString();
770 : }
771 : }
772 :
773 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|