LCOV - code coverage report
Current view: top level - unoxml/source/dom - element.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 343 384 89.3 %
Date: 2014-11-03 Functions: 25 26 96.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10