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

Generated by: LCOV version 1.10