|  | /************************************************************** | 
|  | * | 
|  | * Licensed to the Apache Software Foundation (ASF) under one | 
|  | * or more contributor license agreements.  See the NOTICE file | 
|  | * distributed with this work for additional information | 
|  | * regarding copyright ownership.  The ASF licenses this file | 
|  | * to you under the Apache License, Version 2.0 (the | 
|  | * "License"); you may not use this file except in compliance | 
|  | * with the License.  You may obtain a copy of the License at | 
|  | * | 
|  | *   http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, | 
|  | * software distributed under the License is distributed on an | 
|  | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
|  | * KIND, either express or implied.  See the License for the | 
|  | * specific language governing permissions and limitations | 
|  | * under the License. | 
|  | * | 
|  | *************************************************************/ | 
|  |  | 
|  |  | 
|  |  | 
|  | #include <element.hxx> | 
|  |  | 
|  | #include <string.h> | 
|  |  | 
|  | #include <boost/shared_ptr.hpp> | 
|  |  | 
|  | #include <rtl/ustrbuf.hxx> | 
|  |  | 
|  | #include <com/sun/star/xml/sax/FastToken.hdl> | 
|  |  | 
|  | #include <comphelper/attributelist.hxx> | 
|  |  | 
|  | #include <node.hxx> | 
|  | #include <attr.hxx> | 
|  | #include <elementlist.hxx> | 
|  | #include <attributesmap.hxx> | 
|  | #include <document.hxx> | 
|  |  | 
|  | #include "../events/mutationevent.hxx" | 
|  |  | 
|  |  | 
|  | namespace DOM | 
|  | { | 
|  |  | 
|  | CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex, | 
|  | xmlNodePtr const pNode) | 
|  | : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode) | 
|  | { | 
|  | } | 
|  |  | 
|  | void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler) | 
|  | { | 
|  | if (!i_xHandler.is()) throw RuntimeException(); | 
|  | comphelper::AttributeList *pAttrs = | 
|  | new comphelper::AttributeList(); | 
|  | OUString type = OUString::createFromAscii(""); | 
|  | // add namespace definitions to attributes | 
|  | for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != 0; pNs = pNs->next) { | 
|  | const xmlChar *pPrefix = pNs->prefix; | 
|  | OUString prefix(reinterpret_cast<const sal_Char*>(pPrefix), | 
|  | strlen(reinterpret_cast<const char*>(pPrefix)), | 
|  | RTL_TEXTENCODING_UTF8); | 
|  | OUString name = (prefix.equalsAscii("")) | 
|  | ? OUString::createFromAscii("xmlns") | 
|  | : OUString::createFromAscii("xmlns:") + prefix; | 
|  | const xmlChar *pHref = pNs->href; | 
|  | OUString val(reinterpret_cast<const sal_Char*>(pHref), | 
|  | strlen(reinterpret_cast<const char*>(pHref)), | 
|  | RTL_TEXTENCODING_UTF8); | 
|  | pAttrs->AddAttribute(name, type, val); | 
|  | } | 
|  | // add attributes | 
|  | for (xmlAttrPtr pAttr = m_aNodePtr->properties; | 
|  | pAttr != 0; pAttr = pAttr->next) { | 
|  | ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( | 
|  | reinterpret_cast<xmlNodePtr>(pAttr)); | 
|  | OSL_ENSURE(pNode != 0, "CNode::get returned 0"); | 
|  | OUString prefix = pNode->getPrefix(); | 
|  | OUString name = (prefix.getLength() == 0) | 
|  | ? pNode->getLocalName() | 
|  | : prefix + OUString(static_cast<sal_Unicode>(':')) + pNode->getLocalName(); | 
|  | OUString val  = pNode->getNodeValue(); | 
|  | pAttrs->AddAttribute(name, type, val); | 
|  | } | 
|  | OUString prefix = getPrefix(); | 
|  | OUString name = (prefix.getLength() == 0) | 
|  | ? getLocalName() | 
|  | : prefix + OUString(static_cast<sal_Unicode>(':')) + getLocalName(); | 
|  | Reference< XAttributeList > xAttrList(pAttrs); | 
|  | i_xHandler->startElement(name, xAttrList); | 
|  | // recurse | 
|  | for (xmlNodePtr pChild = m_aNodePtr->children; | 
|  | pChild != 0; pChild = pChild->next) { | 
|  | ::rtl::Reference<CNode> const pNode( | 
|  | GetOwnerDocument().GetCNode(pChild)); | 
|  | OSL_ENSURE(pNode != 0, "CNode::get returned 0"); | 
|  | pNode->saxify(i_xHandler); | 
|  | } | 
|  | i_xHandler->endElement(name); | 
|  | } | 
|  |  | 
|  | void CElement::fastSaxify( Context& i_rContext ) | 
|  | { | 
|  | if (!i_rContext.mxDocHandler.is()) throw RuntimeException(); | 
|  | pushContext(i_rContext); | 
|  | addNamespaces(i_rContext,m_aNodePtr); | 
|  |  | 
|  | // add attributes | 
|  | i_rContext.mxAttribList->clear(); | 
|  | for (xmlAttrPtr pAttr = m_aNodePtr->properties; | 
|  | pAttr != 0; pAttr = pAttr->next) { | 
|  | ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( | 
|  | reinterpret_cast<xmlNodePtr>(pAttr)); | 
|  | OSL_ENSURE(pNode != 0, "CNode::get returned 0"); | 
|  |  | 
|  | const xmlChar* xName = pAttr->name; | 
|  | sal_Int32 nAttributeToken=FastToken::DONTKNOW; | 
|  |  | 
|  | if( pAttr->ns && strlen((char*)pAttr->ns->prefix) ) | 
|  | nAttributeToken = getTokenWithPrefix( i_rContext, | 
|  | (sal_Char*)pAttr->ns->prefix, | 
|  | (sal_Char*)xName ); | 
|  | else | 
|  | nAttributeToken = getToken( i_rContext, (sal_Char*)xName ); | 
|  |  | 
|  | if( nAttributeToken != FastToken::DONTKNOW ) | 
|  | i_rContext.mxAttribList->add( nAttributeToken, | 
|  | OUStringToOString(pNode->getNodeValue(), | 
|  | RTL_TEXTENCODING_UTF8)); | 
|  | } | 
|  |  | 
|  | const xmlChar* xPrefix = m_aNodePtr->ns ? m_aNodePtr->ns->prefix : (const xmlChar*)""; | 
|  | const xmlChar* xName = m_aNodePtr->name; | 
|  | sal_Int32 nElementToken=FastToken::DONTKNOW; | 
|  | if( strlen((char*)xPrefix) ) | 
|  | nElementToken = getTokenWithPrefix( i_rContext, (sal_Char*)xPrefix, (sal_Char*)xName ); | 
|  | else | 
|  | nElementToken = getToken( i_rContext, (sal_Char*)xName ); | 
|  |  | 
|  | Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler); | 
|  | try | 
|  | { | 
|  | Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList.get() ); | 
|  | if( nElementToken == FastToken::DONTKNOW ) | 
|  | { | 
|  | const OUString aNamespace; | 
|  | const OUString aElementName( (sal_Char*)xPrefix, | 
|  | strlen((char*)xPrefix), | 
|  | RTL_TEXTENCODING_UTF8 ); | 
|  |  | 
|  | if( xParentHandler.is() ) | 
|  | i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr ); | 
|  | else | 
|  | i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr ); | 
|  |  | 
|  | if( i_rContext.mxCurrentHandler.is() ) | 
|  | i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr ); | 
|  | } | 
|  | else | 
|  | { | 
|  | if( xParentHandler.is() ) | 
|  | i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr ); | 
|  | else | 
|  | i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr ); | 
|  |  | 
|  | if( i_rContext.mxCurrentHandler.is() ) | 
|  | i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr ); | 
|  | } | 
|  | } | 
|  | catch( Exception& ) | 
|  | {} | 
|  |  | 
|  | // recurse | 
|  | for (xmlNodePtr pChild = m_aNodePtr->children; | 
|  | pChild != 0; pChild = pChild->next) { | 
|  | ::rtl::Reference<CNode> const pNode( | 
|  | GetOwnerDocument().GetCNode(pChild)); | 
|  | OSL_ENSURE(pNode != 0, "CNode::get returned 0"); | 
|  | pNode->fastSaxify(i_rContext); | 
|  | } | 
|  |  | 
|  | if( i_rContext.mxCurrentHandler.is() ) try | 
|  | { | 
|  | if( nElementToken != FastToken::DONTKNOW ) | 
|  | i_rContext.mxCurrentHandler->endFastElement( nElementToken ); | 
|  | else | 
|  | { | 
|  | const OUString aNamespace; | 
|  | const OUString aElementName( (sal_Char*)xPrefix, | 
|  | strlen((char*)xPrefix), | 
|  | RTL_TEXTENCODING_UTF8 ); | 
|  |  | 
|  | i_rContext.mxCurrentHandler->endUnknownElement( aNamespace, aElementName ); | 
|  | } | 
|  | } | 
|  | catch( Exception& ) | 
|  | {} | 
|  |  | 
|  | // restore after children have been processed | 
|  | i_rContext.mxCurrentHandler = xParentHandler; | 
|  | popContext(i_rContext); | 
|  | } | 
|  |  | 
|  | bool CElement::IsChildTypeAllowed(NodeType const nodeType) | 
|  | { | 
|  | switch (nodeType) { | 
|  | case NodeType_ELEMENT_NODE: | 
|  | case NodeType_TEXT_NODE: | 
|  | case NodeType_COMMENT_NODE: | 
|  | case NodeType_PROCESSING_INSTRUCTION_NODE: | 
|  | case NodeType_CDATA_SECTION_NODE: | 
|  | case NodeType_ENTITY_REFERENCE_NODE: | 
|  | return true; | 
|  | case NodeType_ATTRIBUTE_NODE: | 
|  | /* this is not relly allowed by the DOM spec, but this | 
|  | implementation has evidently supported it (by special case | 
|  | handling, so the attribute does not actually become a child) | 
|  | so allow it for backward compatiblity */ | 
|  | return true; | 
|  | default: | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | Retrieves an attribute value by name. | 
|  | return empty string if attribute is not set | 
|  | */ | 
|  | OUString SAL_CALL CElement::getAttribute(OUString const& name) | 
|  | throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | return ::rtl::OUString(); | 
|  | } | 
|  | // search properties | 
|  | OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); | 
|  | ::boost::shared_ptr<xmlChar const> const pValue( | 
|  | xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()), xmlFree); | 
|  | OUString const ret( (pValue) | 
|  | ?   OUString(reinterpret_cast<sal_Char const*>(pValue.get()), | 
|  | strlen(reinterpret_cast<char const*>(pValue.get())), | 
|  | RTL_TEXTENCODING_UTF8) | 
|  | :   OUString() ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /** | 
|  | Retrieves an attribute node by name. | 
|  | */ | 
|  | Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name) | 
|  | throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | return 0; | 
|  | } | 
|  | OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar const*const pName = | 
|  | reinterpret_cast<xmlChar const*>(o1.getStr()); | 
|  | xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); | 
|  | if (0 == pAttr) { | 
|  | return 0; | 
|  | } | 
|  | Reference< XAttr > const xRet( | 
|  | static_cast< XNode* >(GetOwnerDocument().GetCNode( | 
|  | reinterpret_cast<xmlNodePtr>(pAttr)).get()), | 
|  | UNO_QUERY_THROW); | 
|  | return xRet; | 
|  | } | 
|  |  | 
|  | /** | 
|  | Retrieves an Attr node by local name and namespace URI. | 
|  | */ | 
|  | Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS( | 
|  | const OUString& namespaceURI, const OUString& localName) | 
|  | throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | return 0; | 
|  | } | 
|  | OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar const*const pName = | 
|  | reinterpret_cast<xmlChar const*>(o1.getStr()); | 
|  | OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar const*const pNS = | 
|  | reinterpret_cast<xmlChar const*>(o2.getStr()); | 
|  | xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS); | 
|  | if (0 == pAttr) { | 
|  | return 0; | 
|  | } | 
|  | Reference< XAttr > const xRet( | 
|  | static_cast< XNode* >(GetOwnerDocument().GetCNode( | 
|  | reinterpret_cast<xmlNodePtr>(pAttr)).get()), | 
|  | UNO_QUERY_THROW); | 
|  | return xRet; | 
|  | } | 
|  |  | 
|  | /** | 
|  | Retrieves an attribute value by local name and namespace URI. | 
|  | return empty string if attribute is not set | 
|  | */ | 
|  | OUString SAL_CALL | 
|  | CElement::getAttributeNS( | 
|  | OUString const& namespaceURI, OUString const& localName) | 
|  | throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | return ::rtl::OUString(); | 
|  | } | 
|  | OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar const*const pName = | 
|  | reinterpret_cast<xmlChar const*>(o1.getStr()); | 
|  | OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar const*const pNS = | 
|  | reinterpret_cast<xmlChar const*>(o2.getStr()); | 
|  | ::boost::shared_ptr<xmlChar const> const pValue( | 
|  | xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree); | 
|  | if (0 == pValue) { | 
|  | return ::rtl::OUString(); | 
|  | } | 
|  | OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()), | 
|  | strlen(reinterpret_cast<char const*>(pValue.get())), | 
|  | RTL_TEXTENCODING_UTF8); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /** | 
|  | Returns a NodeList of all descendant Elements with a given tag name, | 
|  | in the order in which they are | 
|  | encountered in a preorder traversal of this Element tree. | 
|  | */ | 
|  | Reference< XNodeList > SAL_CALL | 
|  | CElement::getElementsByTagName(OUString const& rLocalName) | 
|  | throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | Reference< XNodeList > const xList( | 
|  | new CElementList(this, m_rMutex, rLocalName)); | 
|  | return xList; | 
|  | } | 
|  |  | 
|  | /** | 
|  | Returns a NodeList of all the descendant Elements with a given local | 
|  | name and namespace URI in the order in which they are encountered in | 
|  | a preorder traversal of this Element tree. | 
|  | */ | 
|  | Reference< XNodeList > SAL_CALL | 
|  | CElement::getElementsByTagNameNS( | 
|  | OUString const& rNamespaceURI, OUString const& rLocalName) | 
|  | throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | Reference< XNodeList > const xList( | 
|  | new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI)); | 
|  | return xList; | 
|  | } | 
|  |  | 
|  | /** | 
|  | The name of the element. | 
|  | */ | 
|  | OUString SAL_CALL CElement::getTagName() | 
|  | throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | return ::rtl::OUString(); | 
|  | } | 
|  | OUString const ret((sal_Char*)m_aNodePtr->name, | 
|  | strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | Returns true when an attribute with a given name is specified on this | 
|  | element or has a default value, false otherwise. | 
|  | */ | 
|  | sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name) | 
|  | throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar *xName = (xmlChar*)o1.getStr(); | 
|  | return (m_aNodePtr != NULL && xmlHasProp(m_aNodePtr, xName) != NULL); | 
|  | } | 
|  |  | 
|  | /** | 
|  | Returns true when an attribute with a given local name and namespace | 
|  | URI is specified on this element or has a default value, false otherwise. | 
|  | */ | 
|  | sal_Bool SAL_CALL CElement::hasAttributeNS( | 
|  | OUString const& namespaceURI, OUString const& localName) | 
|  | throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar *xName = (xmlChar*)o1.getStr(); | 
|  | OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar *xNs = (xmlChar*)o2.getStr(); | 
|  | return (m_aNodePtr != NULL && xmlHasNsProp(m_aNodePtr, xName, xNs) != NULL); | 
|  | } | 
|  |  | 
|  | /** | 
|  | Removes an attribute by name. | 
|  | */ | 
|  | void SAL_CALL CElement::removeAttribute(OUString const& name) | 
|  | throw (RuntimeException, DOMException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | return; | 
|  | } | 
|  | OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar const*const pName = | 
|  | reinterpret_cast<xmlChar const*>(o1.getStr()); | 
|  | xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); | 
|  | if (0 == xmlUnsetProp(m_aNodePtr, pName)) { | 
|  | ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( | 
|  | reinterpret_cast<xmlNodePtr>(pAttr), false)); | 
|  | if (pCNode.is()) { | 
|  | pCNode->invalidate(); // freed by xmlUnsetProp | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | Removes an attribute by local name and namespace URI. | 
|  | */ | 
|  | void SAL_CALL CElement::removeAttributeNS( | 
|  | OUString const& namespaceURI, OUString const& localName) | 
|  | throw (RuntimeException, DOMException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | return; | 
|  | } | 
|  | OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar const*const pName = | 
|  | reinterpret_cast<xmlChar const*>(o1.getStr()); | 
|  | OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar const*const pURI = | 
|  | reinterpret_cast<xmlChar const*>(o2.getStr()); | 
|  | xmlNsPtr const pNs = | 
|  | xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI); | 
|  | xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI); | 
|  | if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) { | 
|  | ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( | 
|  | reinterpret_cast<xmlNodePtr>(pAttr), false)); | 
|  | if (pCNode.is()) { | 
|  | pCNode->invalidate(); // freed by xmlUnsetNsProp | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | Removes the specified attribute node. | 
|  | */ | 
|  | Reference< XAttr > SAL_CALL | 
|  | CElement::removeAttributeNode(Reference< XAttr > const& oldAttr) | 
|  | throw (RuntimeException, DOMException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | ::rtl::Reference<CNode> const pCNode( | 
|  | CNode::GetImplementation(Reference<XNode>(oldAttr.get()))); | 
|  | if (!pCNode.is()) { throw RuntimeException(); } | 
|  |  | 
|  | xmlNodePtr const pNode = pCNode->GetNodePtr(); | 
|  | xmlAttrPtr const pAttr = (xmlAttrPtr) pNode; | 
|  | if (!pAttr) { throw RuntimeException(); } | 
|  |  | 
|  | if (pAttr->parent != m_aNodePtr) | 
|  | { | 
|  | DOMException e; | 
|  | e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; | 
|  | throw e; | 
|  | } | 
|  | if (pAttr->doc != m_aNodePtr->doc) | 
|  | { | 
|  | DOMException e; | 
|  | e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; | 
|  | throw e; | 
|  | } | 
|  |  | 
|  | Reference< XAttr > aAttr; | 
|  | if (oldAttr->getNamespaceURI().getLength() > 0) { | 
|  | ::rtl::OUStringBuffer qname(oldAttr->getPrefix()); | 
|  | if (0 != qname.getLength()) { | 
|  | qname.append(sal_Unicode(':')); | 
|  | } | 
|  | qname.append(oldAttr->getName()); | 
|  | aAttr = GetOwnerDocument().createAttributeNS( | 
|  | oldAttr->getNamespaceURI(), qname.makeStringAndClear()); | 
|  | } else { | 
|  | aAttr = GetOwnerDocument().createAttribute(oldAttr->getName()); | 
|  | } | 
|  | aAttr->setValue(oldAttr->getValue()); | 
|  | xmlRemoveProp(pAttr); | 
|  | pCNode->invalidate(); // freed by xmlRemoveProp | 
|  |  | 
|  | return aAttr; | 
|  | } | 
|  |  | 
|  | /** | 
|  | Adds a new attribute node. | 
|  | */ | 
|  | Reference< XAttr > | 
|  | CElement::setAttributeNode_Impl_Lock( | 
|  | Reference< XAttr > const& xNewAttr, bool const bNS) | 
|  | { | 
|  | if (xNewAttr->getOwnerDocument() != getOwnerDocument()) { | 
|  | DOMException e; | 
|  | e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; | 
|  | throw e; | 
|  | } | 
|  |  | 
|  | ::osl::ClearableMutexGuard guard(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | throw RuntimeException(); | 
|  | } | 
|  |  | 
|  | // get the implementation | 
|  | CAttr *const pCAttr = dynamic_cast<CAttr*>( | 
|  | CNode::GetImplementation(xNewAttr)); | 
|  | if (!pCAttr) { throw RuntimeException(); } | 
|  | xmlAttrPtr const pAttr = | 
|  | reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr()); | 
|  | if (!pAttr) { throw RuntimeException(); } | 
|  |  | 
|  | // check whether the attribute is not in use by another element | 
|  | if (pAttr->parent) { | 
|  | DOMException e; | 
|  | e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR; | 
|  | throw e; | 
|  | } | 
|  |  | 
|  | xmlAttrPtr res = NULL; | 
|  | xmlChar const*const pContent( | 
|  | (pAttr->children) ? pAttr->children->content : 0); | 
|  |  | 
|  | if (bNS) { | 
|  | xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) ); | 
|  | res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent); | 
|  | } else { | 
|  | res = xmlNewProp(m_aNodePtr, pAttr->name, pContent); | 
|  | } | 
|  |  | 
|  | // get the new attr node | 
|  | Reference< XAttr > const xAttr( | 
|  | static_cast< XNode* >(GetOwnerDocument().GetCNode( | 
|  | reinterpret_cast<xmlNodePtr>(res)).get()), | 
|  | UNO_QUERY_THROW); | 
|  |  | 
|  | // attribute adition event | 
|  | // dispatch DOMAttrModified event | 
|  | Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); | 
|  | Reference< XMutationEvent > event(docevent->createEvent( | 
|  | OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); | 
|  | event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), | 
|  | sal_True, sal_False, Reference< XNode >(xAttr, UNO_QUERY), | 
|  | OUString(), xAttr->getValue(), xAttr->getName(), | 
|  | AttrChangeType_ADDITION); | 
|  |  | 
|  | guard.clear(); // release mutex before calling event handlers | 
|  |  | 
|  | dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); | 
|  | dispatchSubtreeModified(); | 
|  |  | 
|  | return xAttr; | 
|  | } | 
|  |  | 
|  | Reference< XAttr > | 
|  | CElement::setAttributeNode(const Reference< XAttr >& newAttr) | 
|  | throw (RuntimeException, DOMException) | 
|  | { | 
|  | return setAttributeNode_Impl_Lock(newAttr, false); | 
|  | } | 
|  |  | 
|  | /** | 
|  | Adds a new attribute. | 
|  | */ | 
|  | Reference< XAttr > | 
|  | CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr) | 
|  | throw (RuntimeException, DOMException) | 
|  | { | 
|  | return setAttributeNode_Impl_Lock(newAttr, true); | 
|  | } | 
|  |  | 
|  | /** | 
|  | Adds a new attribute. | 
|  | */ | 
|  | void SAL_CALL | 
|  | CElement::setAttribute(OUString const& name, OUString const& value) | 
|  | throw (RuntimeException, DOMException) | 
|  | { | 
|  | ::osl::ClearableMutexGuard guard(m_rMutex); | 
|  |  | 
|  | OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar *xName = (xmlChar*)o1.getStr(); | 
|  | OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar *xValue = (xmlChar*)o2.getStr(); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | throw RuntimeException(); | 
|  | } | 
|  | OUString oldValue; | 
|  | AttrChangeType aChangeType = AttrChangeType_MODIFICATION; | 
|  | ::boost::shared_ptr<xmlChar const> const pOld( | 
|  | xmlGetProp(m_aNodePtr, xName), xmlFree); | 
|  | if (pOld == NULL) { | 
|  | aChangeType = AttrChangeType_ADDITION; | 
|  | xmlNewProp(m_aNodePtr, xName, xValue); | 
|  | } else { | 
|  | oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), | 
|  | strlen(reinterpret_cast<char const*>(pOld.get())), | 
|  | RTL_TEXTENCODING_UTF8); | 
|  | xmlSetProp(m_aNodePtr, xName, xValue); | 
|  | } | 
|  |  | 
|  | // dispatch DOMAttrModified event | 
|  | Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); | 
|  | Reference< XMutationEvent > event(docevent->createEvent( | 
|  | OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); | 
|  | event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), | 
|  | sal_True, sal_False, | 
|  | Reference< XNode >(getAttributeNode(name), UNO_QUERY), | 
|  | oldValue, value, name, aChangeType); | 
|  |  | 
|  | guard.clear(); // release mutex before calling event handlers | 
|  | dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); | 
|  | dispatchSubtreeModified(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | Adds a new attribute. | 
|  | */ | 
|  | void SAL_CALL | 
|  | CElement::setAttributeNS(OUString const& namespaceURI, | 
|  | OUString const& qualifiedName, OUString const& value) | 
|  | throw (RuntimeException, DOMException) | 
|  | { | 
|  | if (namespaceURI.getLength() == 0) throw RuntimeException(); | 
|  |  | 
|  | ::osl::ClearableMutexGuard guard(m_rMutex); | 
|  |  | 
|  | OString o1, o2, o3, o4, o5; | 
|  | xmlChar *xPrefix = NULL; | 
|  | xmlChar *xLName = NULL; | 
|  | o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar *xQName = (xmlChar*)o1.getStr(); | 
|  | sal_Int32 idx = qualifiedName.indexOf(':'); | 
|  | if (idx != -1) | 
|  | { | 
|  | o2 = OUStringToOString( | 
|  | qualifiedName.copy(0,idx), | 
|  | RTL_TEXTENCODING_UTF8); | 
|  | xPrefix = (xmlChar*)o2.getStr(); | 
|  | o3 = OUStringToOString( | 
|  | qualifiedName.copy(idx+1), | 
|  | RTL_TEXTENCODING_UTF8); | 
|  | xLName = (xmlChar*)o3.getStr(); | 
|  | }  else { | 
|  | xPrefix = (xmlChar*)""; | 
|  | xLName = xQName; | 
|  | } | 
|  | o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); | 
|  | o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar *xURI= (xmlChar*)o4.getStr(); | 
|  | xmlChar *xValue = (xmlChar*)o5.getStr(); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | throw RuntimeException(); | 
|  | } | 
|  |  | 
|  | //find the right namespace | 
|  | xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix); | 
|  | // if no namespace found, create a new one | 
|  | if (pNs == NULL) { | 
|  | pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix); | 
|  | } | 
|  |  | 
|  | if (strcmp((char*)pNs->href, (char*)xURI) != 0) { | 
|  | // ambiguous ns prefix | 
|  | throw RuntimeException(); | 
|  | } | 
|  |  | 
|  | // found namespace matches | 
|  |  | 
|  | OUString oldValue; | 
|  | AttrChangeType aChangeType = AttrChangeType_MODIFICATION; | 
|  | ::boost::shared_ptr<xmlChar const> const pOld( | 
|  | xmlGetNsProp(m_aNodePtr, xLName, pNs->href), xmlFree); | 
|  | if (pOld == NULL) { | 
|  | aChangeType = AttrChangeType_ADDITION; | 
|  | xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue); | 
|  | } else { | 
|  | oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), | 
|  | strlen(reinterpret_cast<char const*>(pOld.get())), | 
|  | RTL_TEXTENCODING_UTF8); | 
|  | xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue); | 
|  | } | 
|  | // dispatch DOMAttrModified event | 
|  | Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); | 
|  | Reference< XMutationEvent > event(docevent->createEvent( | 
|  | OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); | 
|  | event->initMutationEvent( | 
|  | OUString::createFromAscii("DOMAttrModified"), | 
|  | sal_True, sal_False, | 
|  | Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY), | 
|  | oldValue, value, qualifiedName, aChangeType); | 
|  |  | 
|  | guard.clear(); // release mutex before calling event handlers | 
|  | dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); | 
|  | dispatchSubtreeModified(); | 
|  | } | 
|  |  | 
|  | Reference< XNamedNodeMap > SAL_CALL | 
|  | CElement::getAttributes() throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | Reference< XNamedNodeMap > const xMap( | 
|  | new CAttributesMap(this, m_rMutex)); | 
|  | return xMap; | 
|  | } | 
|  |  | 
|  | OUString SAL_CALL CElement::getNodeName()throw (RuntimeException) | 
|  | { | 
|  | return getLocalName(); | 
|  | } | 
|  |  | 
|  | OUString SAL_CALL CElement::getLocalName()throw (RuntimeException) | 
|  | { | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | OUString aName; | 
|  | if (m_aNodePtr != NULL) | 
|  | { | 
|  | const xmlChar* xName = m_aNodePtr->name; | 
|  | aName = OUString((const sal_Char*)xName, strlen((const char*)xName), RTL_TEXTENCODING_UTF8); | 
|  | } | 
|  | return aName; | 
|  | } | 
|  |  | 
|  | OUString SAL_CALL CElement::getNodeValue() throw (RuntimeException) | 
|  | { | 
|  | return OUString(); | 
|  | } | 
|  |  | 
|  | void SAL_CALL CElement::setElementName(const OUString& aName) | 
|  | throw (RuntimeException, DOMException) | 
|  | { | 
|  | if ((aName.getLength() <= 0) || | 
|  | (0 <= aName.indexOf(OUString::createFromAscii(":")))) | 
|  | { | 
|  | DOMException e; | 
|  | e.Code = DOMExceptionType_INVALID_CHARACTER_ERR; | 
|  | throw e; | 
|  | } | 
|  |  | 
|  | ::osl::MutexGuard const g(m_rMutex); | 
|  |  | 
|  | if (0 == m_aNodePtr) { | 
|  | throw RuntimeException(); | 
|  | } | 
|  | OString oName = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); | 
|  | xmlChar *xName = (xmlChar*)oName.getStr(); | 
|  | xmlNodeSetName(m_aNodePtr, xName); | 
|  | } | 
|  |  | 
|  | } |