| /************************************************************** |
| * |
| * 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( !bool(pOld)) { |
| 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( !bool(pOld)) { |
| 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); |
| } |
| |
| } |