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