Branch data 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 : 108199 : CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex,
45 : : xmlNodePtr const pNode)
46 [ + - ]: 108199 : : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode)
47 : : {
48 : 108199 : }
49 : :
50 : 404 : void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler)
51 : : {
52 [ - + ][ # # ]: 404 : if (!i_xHandler.is()) throw RuntimeException();
53 : : comphelper::AttributeList *pAttrs =
54 [ + - ]: 404 : new comphelper::AttributeList();
55 : 404 : OUString type = "";
56 : : // add namespace definitions to attributes
57 [ + + ]: 877 : for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != 0; pNs = pNs->next) {
58 : 473 : const xmlChar *pPrefix = pNs->prefix;
59 : : OUString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
60 : 473 : strlen(reinterpret_cast<const char*>(pPrefix)),
61 [ + - ]: 473 : RTL_TEXTENCODING_UTF8);
62 : 473 : OUString name = (prefix.isEmpty())
63 [ + - ][ + - ]: 473 : ? OUString( "xmlns" ) : OUString( "xmlns:" ) + prefix;
[ - + ][ - + ]
64 : 473 : const xmlChar *pHref = pNs->href;
65 : : OUString val(reinterpret_cast<const sal_Char*>(pHref),
66 : 473 : strlen(reinterpret_cast<const char*>(pHref)),
67 [ + - ]: 473 : RTL_TEXTENCODING_UTF8);
68 [ + - ]: 473 : pAttrs->AddAttribute(name, type, val);
69 : 473 : }
70 : : // add attributes
71 [ + + ]: 765 : for (xmlAttrPtr pAttr = m_aNodePtr->properties;
72 : : pAttr != 0; pAttr = pAttr->next) {
73 [ + - ]: 361 : ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
74 [ + - ]: 361 : reinterpret_cast<xmlNodePtr>(pAttr));
75 : : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
76 [ + - ]: 361 : OUString prefix = pNode->getPrefix();
77 : 361 : OUString name = (prefix.isEmpty())
78 : 0 : ? pNode->getLocalName()
79 [ + - ][ + - ]: 361 : : prefix + OUString(static_cast<sal_Unicode>(':')) + pNode->getLocalName();
[ + - ][ + - ]
[ # # # #
# # ]
[ - + # # ]
80 [ + - ]: 361 : OUString val = pNode->getNodeValue();
81 [ + - ]: 361 : pAttrs->AddAttribute(name, type, val);
82 : 361 : }
83 [ + - ]: 404 : OUString prefix = getPrefix();
84 : 404 : OUString name = (prefix.isEmpty())
85 : 2 : ? getLocalName()
86 [ + - ][ + - ]: 404 : : prefix + OUString(static_cast<sal_Unicode>(':')) + getLocalName();
[ + + ][ + + ]
[ + + ][ # #
# # # # ]
[ + + ]
87 [ + - ][ + - ]: 404 : Reference< XAttributeList > xAttrList(pAttrs);
88 [ + - ][ + - ]: 404 : i_xHandler->startElement(name, xAttrList);
89 : : // recurse
90 [ + + ]: 1002 : for (xmlNodePtr pChild = m_aNodePtr->children;
91 : : pChild != 0; pChild = pChild->next) {
92 : : ::rtl::Reference<CNode> const pNode(
93 [ + - ][ + - ]: 598 : GetOwnerDocument().GetCNode(pChild));
94 : : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
95 [ + - ]: 598 : pNode->saxify(i_xHandler);
96 : 598 : }
97 [ + - ][ + - ]: 404 : i_xHandler->endElement(name);
98 : 404 : }
99 : :
100 : 2580 : void CElement::fastSaxify( Context& i_rContext )
101 : : {
102 [ - + ][ # # ]: 2580 : if (!i_rContext.mxDocHandler.is()) throw RuntimeException();
103 [ + - ]: 2580 : pushContext(i_rContext);
104 [ + - ]: 2580 : addNamespaces(i_rContext,m_aNodePtr);
105 : :
106 : : // add attributes
107 [ + - ]: 2580 : i_rContext.mxAttribList->clear();
108 [ + + ]: 5877 : for (xmlAttrPtr pAttr = m_aNodePtr->properties;
109 : : pAttr != 0; pAttr = pAttr->next) {
110 [ + - ]: 3297 : ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
111 [ + - ]: 3297 : reinterpret_cast<xmlNodePtr>(pAttr));
112 : : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
113 : :
114 : 3297 : const xmlChar* xName = pAttr->name;
115 : 3297 : sal_Int32 nAttributeToken=FastToken::DONTKNOW;
116 : :
117 [ - + ][ # # ]: 3297 : if( pAttr->ns && strlen((char*)pAttr->ns->prefix) )
118 : : nAttributeToken = getTokenWithPrefix( i_rContext,
119 : : (sal_Char*)pAttr->ns->prefix,
120 [ # # ]: 0 : (sal_Char*)xName );
121 : : else
122 [ + - ]: 3297 : nAttributeToken = getToken( i_rContext, (sal_Char*)xName );
123 : :
124 [ + - ]: 3297 : if( nAttributeToken != FastToken::DONTKNOW )
125 : : i_rContext.mxAttribList->add( nAttributeToken,
126 : 3297 : OUStringToOString(pNode->getNodeValue(),
127 [ + - ][ + - ]: 3297 : RTL_TEXTENCODING_UTF8));
[ + - ]
128 : 3297 : }
129 : :
130 [ + - ]: 2580 : const xmlChar* xPrefix = m_aNodePtr->ns ? m_aNodePtr->ns->prefix : (const xmlChar*)"";
131 : 2580 : const xmlChar* xName = m_aNodePtr->name;
132 : 2580 : sal_Int32 nElementToken=FastToken::DONTKNOW;
133 [ + - ]: 2580 : if( strlen((char*)xPrefix) )
134 [ + - ]: 2580 : nElementToken = getTokenWithPrefix( i_rContext, (sal_Char*)xPrefix, (sal_Char*)xName );
135 : : else
136 [ # # ]: 0 : nElementToken = getToken( i_rContext, (sal_Char*)xName );
137 : :
138 : 2580 : Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler);
139 : : try
140 : : {
141 [ + - ][ + - ]: 2580 : Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList.get() );
142 [ - + ]: 2580 : if( nElementToken == FastToken::DONTKNOW )
143 : : {
144 : 0 : const OUString aNamespace;
145 : : const OUString aElementName( (sal_Char*)xPrefix,
146 : 0 : strlen((char*)xPrefix),
147 [ # # ]: 0 : RTL_TEXTENCODING_UTF8 );
148 : :
149 [ # # ]: 0 : if( xParentHandler.is() )
150 [ # # ][ # # ]: 0 : i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
[ # # ]
151 : : else
152 [ # # ][ # # ]: 0 : i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
[ # # ]
153 : :
154 [ # # ]: 0 : if( i_rContext.mxCurrentHandler.is() )
155 [ # # ][ # # ]: 0 : i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr );
156 : : }
157 : : else
158 : : {
159 [ + + ]: 2580 : if( xParentHandler.is() )
160 [ + - ][ + - ]: 2352 : i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr );
[ + - ]
161 : : else
162 [ + - ][ + - ]: 228 : i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr );
[ + - ]
163 : :
164 [ + + ]: 2580 : if( i_rContext.mxCurrentHandler.is() )
165 [ + - ][ + - ]: 1272 : i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr );
166 [ # # ]: 2580 : }
167 : : }
168 [ # # ]: 0 : catch( Exception& )
169 : : {}
170 : :
171 : : // recurse
172 [ + + ]: 5808 : for (xmlNodePtr pChild = m_aNodePtr->children;
173 : : pChild != 0; pChild = pChild->next) {
174 : : ::rtl::Reference<CNode> const pNode(
175 [ + - ][ + - ]: 3228 : GetOwnerDocument().GetCNode(pChild));
176 : : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
177 [ + - ]: 3228 : pNode->fastSaxify(i_rContext);
178 : 3228 : }
179 : :
180 [ + + ]: 2580 : if( i_rContext.mxCurrentHandler.is() ) try
181 : : {
182 [ + - ]: 1272 : if( nElementToken != FastToken::DONTKNOW )
183 [ + - ][ + - ]: 1272 : 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 [ + - ]: 2580 : i_rContext.mxCurrentHandler = xParentHandler;
199 [ + - ]: 2580 : popContext(i_rContext);
200 : 2580 : }
201 : :
202 : 37273 : bool CElement::IsChildTypeAllowed(NodeType const nodeType)
203 : : {
204 [ + + - ]: 37273 : 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 : 37271 : 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 : 2 : return true;
218 : : default:
219 : 37273 : 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 : 5426 : OUString SAL_CALL CElement::getAttribute(OUString const& name)
229 : : throw (RuntimeException)
230 : : {
231 [ + - ]: 5426 : ::osl::MutexGuard const g(m_rMutex);
232 : :
233 [ - + ]: 5426 : if (0 == m_aNodePtr) {
234 : 0 : return ::rtl::OUString();
235 : : }
236 : : // search properties
237 [ + - ]: 5426 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
238 : : ::boost::shared_ptr<xmlChar const> const pValue(
239 [ + - ][ + - ]: 5426 : xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()), xmlFree);
240 : : OUString const ret( (pValue)
241 : 502 : ? OUString(reinterpret_cast<sal_Char const*>(pValue.get()),
242 : 502 : strlen(reinterpret_cast<char const*>(pValue.get())),
243 : : RTL_TEXTENCODING_UTF8)
244 [ + + + - ]: 5928 : : OUString() );
245 [ + - ][ + - ]: 5426 : return ret;
246 : : }
247 : :
248 : : /**
249 : : Retrieves an attribute node by name.
250 : : */
251 : 2694 : Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name)
252 : : throw (RuntimeException)
253 : : {
254 [ + - ]: 2694 : ::osl::MutexGuard const g(m_rMutex);
255 : :
256 [ - + ]: 2694 : if (0 == m_aNodePtr) {
257 [ # # ]: 0 : return 0;
258 : : }
259 [ + - ]: 2694 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
260 : : xmlChar const*const pName =
261 : 2694 : reinterpret_cast<xmlChar const*>(o1.getStr());
262 [ + - ]: 2694 : xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
263 [ + + ]: 2694 : if (0 == pAttr) {
264 [ + - ]: 4 : return 0;
265 : : }
266 : : Reference< XAttr > const xRet(
267 [ + - ]: 2690 : static_cast< XNode* >(GetOwnerDocument().GetCNode(
268 [ + - ][ + - ]: 5380 : reinterpret_cast<xmlNodePtr>(pAttr)).get()),
269 [ + - ]: 2690 : UNO_QUERY_THROW);
270 [ + - ]: 2694 : return xRet;
271 : : }
272 : :
273 : : /**
274 : : Retrieves an Attr node by local name and namespace URI.
275 : : */
276 : 17648 : Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS(
277 : : const OUString& namespaceURI, const OUString& localName)
278 : : throw (RuntimeException)
279 : : {
280 [ + - ]: 17648 : ::osl::MutexGuard const g(m_rMutex);
281 : :
282 [ - + ]: 17648 : if (0 == m_aNodePtr) {
283 [ # # ]: 0 : return 0;
284 : : }
285 [ + - ]: 17648 : OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
286 : : xmlChar const*const pName =
287 : 17648 : reinterpret_cast<xmlChar const*>(o1.getStr());
288 [ + - ]: 17648 : OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
289 : : xmlChar const*const pNS =
290 : 17648 : reinterpret_cast<xmlChar const*>(o2.getStr());
291 [ + - ]: 17648 : xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS);
292 [ + + ]: 17648 : if (0 == pAttr) {
293 [ + - ]: 4 : return 0;
294 : : }
295 : : Reference< XAttr > const xRet(
296 [ + - ]: 17644 : static_cast< XNode* >(GetOwnerDocument().GetCNode(
297 [ + - ][ + - ]: 35288 : reinterpret_cast<xmlNodePtr>(pAttr)).get()),
298 [ + - ]: 17644 : UNO_QUERY_THROW);
299 [ + - ]: 17648 : 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 : 7884 : CElement::getAttributeNS(
308 : : OUString const& namespaceURI, OUString const& localName)
309 : : throw (RuntimeException)
310 : : {
311 [ + - ]: 7884 : ::osl::MutexGuard const g(m_rMutex);
312 : :
313 [ - + ]: 7884 : if (0 == m_aNodePtr) {
314 : 0 : return ::rtl::OUString();
315 : : }
316 [ + - ]: 7884 : OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
317 : : xmlChar const*const pName =
318 : 7884 : reinterpret_cast<xmlChar const*>(o1.getStr());
319 [ + - ]: 7884 : OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
320 : : xmlChar const*const pNS =
321 : 7884 : reinterpret_cast<xmlChar const*>(o2.getStr());
322 : : ::boost::shared_ptr<xmlChar const> const pValue(
323 [ + - ][ + - ]: 7884 : xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree);
324 [ + + ]: 7884 : if (0 == pValue) {
325 : 5843 : return ::rtl::OUString();
326 : : }
327 : 2041 : OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()),
328 : 2041 : strlen(reinterpret_cast<char const*>(pValue.get())),
329 [ + - ]: 2041 : RTL_TEXTENCODING_UTF8);
330 [ + - ][ + - ]: 7884 : 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 : 6 : CElement::getElementsByTagName(OUString const& rLocalName)
340 : : throw (RuntimeException)
341 : : {
342 [ + - ]: 6 : ::osl::MutexGuard const g(m_rMutex);
343 : :
344 : : Reference< XNodeList > const xList(
345 [ + - ][ + - ]: 6 : new CElementList(this, m_rMutex, rLocalName));
[ + - ]
346 [ + - ]: 6 : 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 : 4 : CElement::getElementsByTagNameNS(
356 : : OUString const& rNamespaceURI, OUString const& rLocalName)
357 : : throw (RuntimeException)
358 : : {
359 [ + - ]: 4 : ::osl::MutexGuard const g(m_rMutex);
360 : :
361 : : Reference< XNodeList > const xList(
362 [ + - ][ + - ]: 4 : new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI));
[ + - ]
363 [ + - ]: 4 : return xList;
364 : : }
365 : :
366 : : /**
367 : : The name of the element.
368 : : */
369 : 11491 : OUString SAL_CALL CElement::getTagName()
370 : : throw (RuntimeException)
371 : : {
372 [ + - ]: 11491 : ::osl::MutexGuard const g(m_rMutex);
373 : :
374 [ - + ]: 11491 : if (0 == m_aNodePtr) {
375 : 0 : return ::rtl::OUString();
376 : : }
377 : : OUString const ret((sal_Char*)m_aNodePtr->name,
378 [ + - ]: 11491 : strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8);
379 [ + - ]: 11491 : 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 : 4 : sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name)
388 : : throw (RuntimeException)
389 : : {
390 [ + - ]: 4 : ::osl::MutexGuard const g(m_rMutex);
391 : :
392 [ + - ]: 4 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
393 : 4 : 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 : 4 : sal_Bool SAL_CALL CElement::hasAttributeNS(
402 : : OUString const& namespaceURI, OUString const& localName)
403 : : throw (RuntimeException)
404 : : {
405 [ + - ]: 4 : ::osl::MutexGuard const g(m_rMutex);
406 : :
407 [ + - ]: 4 : OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
408 : 4 : xmlChar *xName = (xmlChar*)o1.getStr();
409 [ + - ]: 4 : OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
410 : 4 : 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 : 4 : void SAL_CALL CElement::removeAttribute(OUString const& name)
418 : : throw (RuntimeException, DOMException)
419 : : {
420 [ + - ]: 4 : ::osl::MutexGuard const g(m_rMutex);
421 : :
422 [ - + ]: 4 : if (0 == m_aNodePtr) {
423 : 4 : return;
424 : : }
425 [ + - ]: 4 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
426 : : xmlChar const*const pName =
427 : 4 : reinterpret_cast<xmlChar const*>(o1.getStr());
428 [ + - ]: 4 : xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
429 [ + - ][ + + ]: 4 : if (0 == xmlUnsetProp(m_aNodePtr, pName)) {
430 [ + - ]: 2 : ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
431 [ + - ]: 2 : reinterpret_cast<xmlNodePtr>(pAttr), false));
432 [ - + ]: 2 : if (pCNode.is()) {
433 [ # # ]: 0 : pCNode->invalidate(); // freed by xmlUnsetProp
434 : 2 : }
435 [ + - ][ + - ]: 4 : }
436 : : }
437 : :
438 : : /**
439 : : Removes an attribute by local name and namespace URI.
440 : : */
441 : 4 : void SAL_CALL CElement::removeAttributeNS(
442 : : OUString const& namespaceURI, OUString const& localName)
443 : : throw (RuntimeException, DOMException)
444 : : {
445 [ + - ]: 4 : ::osl::MutexGuard const g(m_rMutex);
446 : :
447 [ - + ]: 4 : if (0 == m_aNodePtr) {
448 : 4 : return;
449 : : }
450 [ + - ]: 4 : OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
451 : : xmlChar const*const pName =
452 : 4 : reinterpret_cast<xmlChar const*>(o1.getStr());
453 [ + - ]: 4 : OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
454 : : xmlChar const*const pURI =
455 : 4 : reinterpret_cast<xmlChar const*>(o2.getStr());
456 : : xmlNsPtr const pNs =
457 [ + - ]: 4 : xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI);
458 [ + - ]: 4 : xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI);
459 [ + - ][ + + ]: 4 : if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) {
460 [ + - ]: 2 : ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
461 [ + - ]: 2 : reinterpret_cast<xmlNodePtr>(pAttr), false));
462 [ - + ]: 2 : if (pCNode.is()) {
463 [ # # ]: 0 : pCNode->invalidate(); // freed by xmlUnsetNsProp
464 : 2 : }
465 [ + - ][ + - ]: 4 : }
466 : : }
467 : :
468 : : /**
469 : : Removes the specified attribute node.
470 : : */
471 : : Reference< XAttr > SAL_CALL
472 : 12 : CElement::removeAttributeNode(Reference< XAttr > const& oldAttr)
473 : : throw (RuntimeException, DOMException)
474 : : {
475 [ + - ]: 12 : ::osl::MutexGuard const g(m_rMutex);
476 : :
477 [ - + ]: 12 : 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 [ + - ][ + + ]: 12 : if (!pCNode.is()) { throw RuntimeException(); }
484 : :
485 : 10 : xmlNodePtr const pNode = pCNode->GetNodePtr();
486 : 10 : xmlAttrPtr const pAttr = (xmlAttrPtr) pNode;
487 [ # # ][ - + ]: 10 : if (!pAttr) { throw RuntimeException(); }
488 : :
489 [ + + ]: 10 : if (pAttr->parent != m_aNodePtr)
490 : : {
491 [ + - ]: 2 : DOMException e;
492 : 2 : e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
493 [ + - ]: 2 : throw e;
494 : : }
495 [ - + ]: 8 : 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 [ + - ][ + + ]: 8 : if (!oldAttr->getNamespaceURI().isEmpty()) {
[ + - ]
504 [ + - ][ + - ]: 4 : ::rtl::OUStringBuffer qname(oldAttr->getPrefix());
[ + - ]
505 [ + + ]: 4 : if (0 != qname.getLength()) {
506 [ + - ]: 2 : qname.append(sal_Unicode(':'));
507 : : }
508 [ + - ][ + - ]: 4 : qname.append(oldAttr->getName());
[ + - ]
509 [ + - ]: 4 : aAttr = GetOwnerDocument().createAttributeNS(
510 [ + - ][ + - ]: 4 : oldAttr->getNamespaceURI(), qname.makeStringAndClear());
[ + - ][ + - ]
[ + - ]
511 : : } else {
512 [ + - ][ + - ]: 4 : aAttr = GetOwnerDocument().createAttribute(oldAttr->getName());
[ + - ][ + - ]
[ + - ]
513 : : }
514 [ + - ][ + - ]: 8 : aAttr->setValue(oldAttr->getValue());
[ + - ][ + - ]
515 [ + - ]: 8 : xmlRemoveProp(pAttr);
516 [ + - ]: 8 : pCNode->invalidate(); // freed by xmlRemoveProp
517 : :
518 [ + - ]: 12 : return aAttr;
519 : : }
520 : :
521 : : /**
522 : : Adds a new attribute node.
523 : : */
524 : : Reference< XAttr >
525 : 12 : CElement::setAttributeNode_Impl_Lock(
526 : : Reference< XAttr > const& xNewAttr, bool const bNS)
527 : : {
528 [ + - ][ + - ]: 12 : if (xNewAttr->getOwnerDocument() != getOwnerDocument()) {
[ + - ][ + - ]
[ - + ]
529 [ # # ]: 0 : DOMException e;
530 : 0 : e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
531 [ # # ]: 0 : throw e;
532 : : }
533 : :
534 [ + - ]: 12 : ::osl::ClearableMutexGuard guard(m_rMutex);
535 : :
536 [ - + ]: 12 : if (0 == m_aNodePtr) {
537 [ # # ]: 0 : throw RuntimeException();
538 : : }
539 : :
540 : : // get the implementation
541 : : CAttr *const pCAttr = dynamic_cast<CAttr*>(
542 [ + - ][ - + ]: 12 : CNode::GetImplementation(xNewAttr));
543 [ - + ][ # # ]: 12 : if (!pCAttr) { throw RuntimeException(); }
544 : : xmlAttrPtr const pAttr =
545 : 12 : reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr());
546 [ # # ][ - + ]: 12 : if (!pAttr) { throw RuntimeException(); }
547 : :
548 : : // check whether the attribute is not in use by another element
549 [ + + ]: 12 : if (pAttr->parent) {
550 [ + - ]: 4 : DOMException e;
551 : 4 : e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR;
552 [ + - ]: 4 : throw e;
553 : : }
554 : :
555 : 8 : xmlAttrPtr res = NULL;
556 : : xmlChar const*const pContent(
557 [ + + ]: 8 : (pAttr->children) ? pAttr->children->content : 0);
558 : :
559 [ + + ]: 8 : if (bNS) {
560 [ + - ]: 4 : xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
561 [ + - ]: 4 : res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent);
562 : : } else {
563 [ + - ]: 4 : res = xmlNewProp(m_aNodePtr, pAttr->name, pContent);
564 : : }
565 : :
566 : : // get the new attr node
567 : : Reference< XAttr > const xAttr(
568 [ + - ]: 8 : static_cast< XNode* >(GetOwnerDocument().GetCNode(
569 [ + - ][ + - ]: 16 : reinterpret_cast<xmlNodePtr>(res)).get()),
570 [ + - ]: 8 : UNO_QUERY_THROW);
571 : :
572 : : // attribute addition event
573 : : // dispatch DOMAttrModified event
574 [ + - ][ + - ]: 8 : Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
575 [ + - ]: 8 : Reference< XMutationEvent > event(docevent->createEvent(
576 [ + - ][ + - ]: 8 : "DOMAttrModified"), UNO_QUERY);
577 [ + - ]: 8 : event->initMutationEvent("DOMAttrModified",
578 : : sal_True, sal_False, Reference< XNode >(xAttr, UNO_QUERY),
579 [ + - ][ + - ]: 16 : OUString(), xAttr->getValue(), xAttr->getName(),
580 [ + - ][ + - ]: 16 : AttrChangeType_ADDITION);
[ + - ][ + - ]
581 : :
582 [ + - ]: 8 : guard.clear(); // release mutex before calling event handlers
583 : :
584 [ + - ][ + - ]: 8 : dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
585 [ + - ]: 8 : dispatchSubtreeModified();
586 : :
587 [ + - ]: 12 : return xAttr;
588 : : }
589 : :
590 : : Reference< XAttr >
591 : 6 : CElement::setAttributeNode(const Reference< XAttr >& newAttr)
592 : : throw (RuntimeException, DOMException)
593 : : {
594 : 6 : return setAttributeNode_Impl_Lock(newAttr, false);
595 : : }
596 : :
597 : : /**
598 : : Adds a new attribute.
599 : : */
600 : : Reference< XAttr >
601 : 6 : CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr)
602 : : throw (RuntimeException, DOMException)
603 : : {
604 : 6 : return setAttributeNode_Impl_Lock(newAttr, true);
605 : : }
606 : :
607 : : /**
608 : : Adds a new attribute.
609 : : */
610 : : void SAL_CALL
611 : 2684 : CElement::setAttribute(OUString const& name, OUString const& value)
612 : : throw (RuntimeException, DOMException)
613 : : {
614 [ + - ]: 2684 : ::osl::ClearableMutexGuard guard(m_rMutex);
615 : :
616 [ + - ]: 2684 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
617 : 2684 : xmlChar *xName = (xmlChar*)o1.getStr();
618 [ + - ]: 2684 : OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
619 : 2684 : xmlChar *xValue = (xmlChar*)o2.getStr();
620 : :
621 [ - + ]: 2684 : if (0 == m_aNodePtr) {
622 [ # # ]: 0 : throw RuntimeException();
623 : : }
624 : 2684 : OUString oldValue;
625 : 2684 : AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
626 : : ::boost::shared_ptr<xmlChar const> const pOld(
627 [ + - ][ + - ]: 2684 : xmlGetProp(m_aNodePtr, xName), xmlFree);
628 [ + - ]: 2684 : if (pOld == NULL) {
629 : 2684 : aChangeType = AttrChangeType_ADDITION;
630 [ + - ]: 2684 : 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 [ + - ][ + - ]: 2684 : Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
640 [ + - ]: 2684 : Reference< XMutationEvent > event(docevent->createEvent(
641 [ + - ][ + - ]: 2684 : "DOMAttrModified"), UNO_QUERY);
642 [ + - ]: 2684 : event->initMutationEvent("DOMAttrModified",
643 : : sal_True, sal_False,
644 : 2684 : Reference< XNode >(getAttributeNode(name), UNO_QUERY),
645 [ + - ][ + - ]: 2684 : oldValue, value, name, aChangeType);
[ + - ]
646 : :
647 [ + - ]: 2684 : guard.clear(); // release mutex before calling event handlers
648 [ + - ][ + - ]: 2684 : dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
649 [ + - ][ + - ]: 2684 : dispatchSubtreeModified();
[ + - ]
650 : 2684 : }
651 : :
652 : : /**
653 : : Adds a new attribute.
654 : : */
655 : : void SAL_CALL
656 : 17638 : CElement::setAttributeNS(OUString const& namespaceURI,
657 : : OUString const& qualifiedName, OUString const& value)
658 : : throw (RuntimeException, DOMException)
659 : : {
660 [ - + ][ # # ]: 17638 : if (namespaceURI.isEmpty()) throw RuntimeException();
661 : :
662 [ + - ]: 17638 : ::osl::ClearableMutexGuard guard(m_rMutex);
663 : :
664 : 17638 : OString o1, o2, o3, o4, o5;
665 : 17638 : xmlChar *xPrefix = NULL;
666 : 17638 : xmlChar *xLName = NULL;
667 [ + - ]: 17638 : o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8);
668 : 17638 : xmlChar *xQName = (xmlChar*)o1.getStr();
669 : 17638 : sal_Int32 idx = qualifiedName.indexOf(':');
670 [ + + ]: 17638 : if (idx != -1)
671 : : {
672 : : o2 = OUStringToOString(
673 : : qualifiedName.copy(0,idx),
674 [ + - ]: 17634 : RTL_TEXTENCODING_UTF8);
675 : 17634 : xPrefix = (xmlChar*)o2.getStr();
676 : : o3 = OUStringToOString(
677 : : qualifiedName.copy(idx+1),
678 [ + - ]: 17634 : RTL_TEXTENCODING_UTF8);
679 : 17634 : xLName = (xmlChar*)o3.getStr();
680 : : } else {
681 : 4 : xPrefix = (xmlChar*)"";
682 : 4 : xLName = xQName;
683 : : }
684 [ + - ]: 17638 : o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
685 [ + - ]: 17638 : o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
686 : 17638 : xmlChar *xURI= (xmlChar*)o4.getStr();
687 : 17638 : xmlChar *xValue = (xmlChar*)o5.getStr();
688 : :
689 [ - + ]: 17638 : if (0 == m_aNodePtr) {
690 [ # # ]: 0 : throw RuntimeException();
691 : : }
692 : :
693 : : //find the right namespace
694 [ + - ]: 17638 : xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix);
695 : : // if no namespace found, create a new one
696 [ + + ]: 17638 : if (pNs == NULL) {
697 [ + - ]: 106 : pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix);
698 : : }
699 : :
700 [ - + ]: 17638 : if (strcmp((char*)pNs->href, (char*)xURI) != 0) {
701 : : // ambiguous ns prefix
702 [ # # ]: 0 : throw RuntimeException();
703 : : }
704 : :
705 : : // found namespace matches
706 : :
707 : 17638 : OUString oldValue;
708 : 17638 : AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
709 : : ::boost::shared_ptr<xmlChar const> const pOld(
710 [ + - ][ + - ]: 17638 : xmlGetNsProp(m_aNodePtr, xLName, pNs->href), xmlFree);
711 [ + - ]: 17638 : if (pOld == NULL) {
712 : 17638 : aChangeType = AttrChangeType_ADDITION;
713 [ + - ]: 17638 : xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue);
714 : : } else {
715 : 0 : oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
716 : 0 : strlen(reinterpret_cast<char const*>(pOld.get())),
717 [ # # ]: 0 : RTL_TEXTENCODING_UTF8);
718 [ # # ]: 0 : xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue);
719 : : }
720 : : // dispatch DOMAttrModified event
721 [ + - ][ + - ]: 17638 : Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
722 [ + - ]: 17638 : Reference< XMutationEvent > event(docevent->createEvent(
723 [ + - ][ + - ]: 17638 : "DOMAttrModified"), UNO_QUERY);
724 [ + - ]: 17638 : event->initMutationEvent(
725 : : "DOMAttrModified", sal_True, sal_False,
726 : 17638 : Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY),
727 [ + - ][ + - ]: 17638 : oldValue, value, qualifiedName, aChangeType);
[ + - ][ + - ]
728 : :
729 [ + - ]: 17638 : guard.clear(); // release mutex before calling event handlers
730 [ + - ][ + - ]: 17638 : dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
731 [ + - ][ + - ]: 17638 : dispatchSubtreeModified();
[ + - ]
732 : 17638 : }
733 : :
734 : : Reference< XNamedNodeMap > SAL_CALL
735 : 334 : CElement::getAttributes() throw (RuntimeException)
736 : : {
737 [ + - ]: 334 : ::osl::MutexGuard const g(m_rMutex);
738 : :
739 : : Reference< XNamedNodeMap > const xMap(
740 [ + - ][ + - ]: 334 : new CAttributesMap(this, m_rMutex));
[ + - ]
741 [ + - ]: 334 : return xMap;
742 : : }
743 : :
744 : 14 : OUString SAL_CALL CElement::getNodeName()throw (RuntimeException)
745 : : {
746 : 14 : return getLocalName();
747 : : }
748 : :
749 : 432 : OUString SAL_CALL CElement::getLocalName()throw (RuntimeException)
750 : : {
751 [ + - ]: 432 : ::osl::MutexGuard const g(m_rMutex);
752 : :
753 : 432 : OUString aName;
754 [ + - ]: 432 : if (m_aNodePtr != NULL)
755 : : {
756 : 432 : const xmlChar* xName = m_aNodePtr->name;
757 [ + - ]: 432 : aName = OUString((const sal_Char*)xName, strlen((const char*)xName), RTL_TEXTENCODING_UTF8);
758 : : }
759 [ + - ]: 432 : return aName;
760 : : }
761 : :
762 : 2 : OUString SAL_CALL CElement::getNodeValue() throw (RuntimeException)
763 : : {
764 : 2 : 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: */
|