24#include <libxml/xmlstring.h>
28#include <osl/mutex.hxx>
29#include <osl/diagnose.h>
32#include <com/sun/star/xml/dom/DOMException.hpp>
33#include <com/sun/star/xml/dom/events/XMutationEvent.hpp>
34#include <com/sun/star/xml/sax/FastToken.hpp>
45using namespace css::uno;
46using namespace css::xml::dom;
47using namespace css::xml::dom::events;
48using namespace css::xml::sax;
57 Context::NamespaceVectorType::value_type aVal = io_rContext.
maNamespaces.back();
69 for (xmlNsPtr pNs = pNode->nsDef; pNs !=
nullptr; pNs = pNs->next) {
70 const xmlChar *pPrefix = pNs->prefix;
72 OString
prefix(
reinterpret_cast<const char*
>(pPrefix),
73 pPrefix ? strlen(
reinterpret_cast<const char*
>(pPrefix)) : 0);
74 const xmlChar *pHref = pNs->href;
75 OUString val(
reinterpret_cast<const char*
>(pHref),
76 strlen(
reinterpret_cast<const char*
>(pHref)),
77 RTL_TEXTENCODING_UTF8);
79 Context::NamespaceMapType::iterator aIter=
89 SAL_INFO(
"unoxml",
"Added with token " << aIter->second);
96 const Sequence<sal_Int8>
aSeq(
reinterpret_cast<sal_Int8 const *
>(pToken), strlen( pToken ) );
102 sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
106 SAL_INFO(
"unoxml",
"getTokenWithPrefix(): prefix " << pPrefix <<
", name " <<
pName);
108 Context::NamespaceVectorType::value_type::const_iterator aIter;
109 if( (aIter=std::find_if(rContext.
maNamespaces.back().begin(),
114 nNamespaceToken = aIter->mnToken;
116 if( nNameToken == FastToken::DONTKNOW )
117 nNamespaceToken = FastToken::DONTKNOW;
119 nNamespaceToken |= nNameToken;
122 return nNamespaceToken;
126 CNode::CNode(CDocument
const& rDocument, ::osl::Mutex
const& rMutex,
127 NodeType const& reNodeType, xmlNodePtr
const& rpNode)
129 , m_aNodeType(reNodeType)
134 ? &const_cast<CDocument&>(rDocument) : nullptr )
137 OSL_ASSERT(m_aNodePtr);
140 void CNode::invalidate()
148 xmlFreeNode(m_aNodePtr);
150 m_aNodePtr =
nullptr;
156 if (NodeType_DOCUMENT_NODE == m_aNodeType) {
159 ::osl::MutexGuard
const g(m_rMutex);
164 CDocument & CNode::GetOwnerDocument()
172 xmlNodePtr
const aNode, xmlNsPtr
const oldNs, xmlNsPtr
const newNs)
175 xmlNodePtr cur = aNode;
176 while (cur !=
nullptr)
178 if (cur->ns == oldNs)
180 if (cur->type == XML_ELEMENT_NODE)
182 xmlAttrPtr curAttr = cur->properties;
183 while(curAttr !=
nullptr)
185 if (curAttr->ns == oldNs)
187 curAttr = curAttr->next;
195 void nscleanup(
const xmlNodePtr aNode,
const xmlNodePtr aParent)
197 xmlNodePtr cur = aNode;
200 if (cur !=
nullptr && cur->type == XML_ELEMENT_NODE)
202 xmlAttrPtr curAttr = cur->properties;
203 while(curAttr !=
nullptr)
205 if (curAttr->ns !=
nullptr)
207 xmlNsPtr
ns = xmlSearchNs(cur->doc, aParent, curAttr->ns->prefix);
211 curAttr = curAttr->next;
215 while (cur !=
nullptr)
218 if (cur->ns !=
nullptr)
220 xmlNsPtr
ns = xmlSearchNs(cur->doc, aParent, cur->ns->prefix);
221 if (
ns !=
nullptr &&
ns != cur->ns && strcmp(
reinterpret_cast<char const *
>(
ns->href),
reinterpret_cast<char const *
>(cur->ns->href))==0)
223 xmlNsPtr curDef = cur->nsDef;
224 xmlNsPtr *refp = &(cur->nsDef);
225 while (curDef !=
nullptr)
227 ns = xmlSearchNs(cur->doc, aParent, curDef->prefix);
228 if (
ns !=
nullptr &&
ns != curDef && strcmp(
reinterpret_cast<char const *
>(
ns->href),
reinterpret_cast<char const *
>(curDef->href))==0)
233 *refp = curDef->next;
237 refp = &(curDef->next);
238 curDef = curDef->next;
247 void CNode::saxify(
const Reference< XDocumentHandler >& i_xHandler)
253 void CNode::fastSaxify(Context& io_rContext)
265 void CNode::checkNoParent(Reference<XNode>
const& xNode){
266 if (xNode->getParentNode() != Reference<XNode>(
this)){
268 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
272 void CNode::checkNoParent(
const xmlNodePtr pNode){
273 if (pNode->parent !=
nullptr){
275 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
279 void CNode::checkSameOwner(Reference<XNode>
const& xNode){
280 if (xNode->getOwnerDocument() != getOwnerDocument()) {
282 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
290 Reference< XNode > SAL_CALL CNode::appendChild(
291 Reference< XNode >
const& xNewChild)
293 ::osl::ClearableMutexGuard guard(m_rMutex);
295 if (
nullptr == m_aNodePtr) {
return nullptr; }
297 CNode *
const pNewChild(
dynamic_cast<CNode*
>(xNewChild.get()));
299 xmlNodePtr
const cur = pNewChild->GetNodePtr();
304 if (cur->doc != m_aNodePtr->doc) {
306 e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
310 if (cur == m_aNodePtr) {
312 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
317 if (!IsChildTypeAllowed(pNewChild->m_aNodeType,
nullptr)) {
319 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
324 xmlNodePtr res =
nullptr;
325 if (cur->type == XML_ATTRIBUTE_NODE)
327 xmlChar
const*
const pChildren((cur->children)
328 ? cur->children->content
329 :
reinterpret_cast<xmlChar const*
>(
""));
330 CAttr *
const pCAttr(
dynamic_cast<CAttr *
>(pNewChild));
332 xmlNsPtr
const pNs( pCAttr->GetNamespace(m_aNodePtr) );
334 res =
reinterpret_cast<xmlNodePtr
>(
335 xmlNewNsProp(m_aNodePtr, pNs, cur->name, pChildren));
337 res =
reinterpret_cast<xmlNodePtr
>(
338 xmlNewProp(m_aNodePtr, cur->name, pChildren));
343 res = xmlAddChild(m_aNodePtr, cur);
348 if (res && (cur != res)) {
349 pNewChild->invalidate();
353 if (!res) {
return nullptr; }
362 if (!pNode.is()) {
return nullptr; }
367 pNode->m_bUnlinked =
false;
368 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
369 Reference< XMutationEvent > event(docevent->createEvent(
370 "DOMNodeInserted"), UNO_QUERY);
371 event->initMutationEvent(
"DOMNodeInserted",
true,
false,
this,
372 OUString(), OUString(), OUString(), AttrChangeType(0) );
378 dispatchEvent(event);
380 dispatchSubtreeModified();
389 Reference< XNode > SAL_CALL CNode::cloneNode(
sal_Bool bDeep)
391 ::osl::MutexGuard
const g(m_rMutex);
393 if (
nullptr == m_aNodePtr) {
397 xmlCopyNode(m_aNodePtr, bDeep ? 1 : 0));
398 if (!pNode.is()) {
return nullptr; }
399 pNode->m_bUnlinked =
true;
407 Reference< XNamedNodeMap > SAL_CALL CNode::getAttributes()
410 return Reference< XNamedNodeMap>();
416 Reference< XNodeList > SAL_CALL CNode::getChildNodes()
418 ::osl::MutexGuard
const g(m_rMutex);
420 if (
nullptr == m_aNodePtr) {
423 Reference< XNodeList >
const xNodeList(
new CChildList(
this, m_rMutex));
430 Reference< XNode > SAL_CALL CNode::getFirstChild()
432 ::osl::MutexGuard
const g(m_rMutex);
434 if (
nullptr == m_aNodePtr) {
437 return GetOwnerDocument().GetCNode(m_aNodePtr->children);
443 Reference< XNode > SAL_CALL CNode::getLastChild()
445 ::osl::MutexGuard
const g(m_rMutex);
447 if (
nullptr == m_aNodePtr) {
450 return GetOwnerDocument().GetCNode(xmlGetLastChild(m_aNodePtr));
456 OUString SAL_CALL CNode::getLocalName()
466 OUString SAL_CALL CNode::getNamespaceURI()
468 ::osl::MutexGuard
const g(m_rMutex);
471 if (m_aNodePtr !=
nullptr &&
472 (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
473 m_aNodePtr->ns !=
nullptr)
475 const xmlChar* pHref = m_aNodePtr->ns->href;
476 aURI = OUString(
reinterpret_cast<char const *
>(pHref), strlen(
reinterpret_cast<char const *
>(pHref)), RTL_TEXTENCODING_UTF8);
484 Reference< XNode > SAL_CALL CNode::getNextSibling()
486 ::osl::MutexGuard
const g(m_rMutex);
488 if (
nullptr == m_aNodePtr) {
491 return GetOwnerDocument().GetCNode(m_aNodePtr->next);
497 OUString SAL_CALL CNode::getNodeName()
523 NodeType SAL_CALL CNode::getNodeType()
525 ::osl::MutexGuard
const g(m_rMutex);
533 OUString SAL_CALL CNode::getNodeValue()
541 Reference< XDocument > SAL_CALL CNode::getOwnerDocument()
543 ::osl::MutexGuard
const g(m_rMutex);
545 if (
nullptr == m_aNodePtr) {
548 Reference< XDocument >
const xDoc(& GetOwnerDocument());
555 Reference< XNode > SAL_CALL CNode::getParentNode()
557 ::osl::MutexGuard
const g(m_rMutex);
559 if (
nullptr == m_aNodePtr) {
562 return GetOwnerDocument().GetCNode(m_aNodePtr->parent);
568 OUString SAL_CALL CNode::getPrefix()
570 ::osl::MutexGuard
const g(m_rMutex);
573 if (m_aNodePtr !=
nullptr &&
574 (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
575 m_aNodePtr->ns !=
nullptr)
577 const xmlChar* pPrefix = m_aNodePtr->ns->prefix;
578 if( pPrefix !=
nullptr )
579 aPrefix = OUString(
reinterpret_cast<char const *
>(pPrefix), strlen(
reinterpret_cast<char const *
>(pPrefix)), RTL_TEXTENCODING_UTF8);
588 Reference< XNode > SAL_CALL CNode::getPreviousSibling()
590 ::osl::MutexGuard
const g(m_rMutex);
592 if (
nullptr == m_aNodePtr) {
595 return GetOwnerDocument().GetCNode(m_aNodePtr->prev);
601 sal_Bool SAL_CALL CNode::hasAttributes()
603 ::osl::MutexGuard
const g(m_rMutex);
605 return (m_aNodePtr !=
nullptr && m_aNodePtr->properties !=
nullptr);
611 sal_Bool SAL_CALL CNode::hasChildNodes()
613 ::osl::MutexGuard
const g(m_rMutex);
615 return (m_aNodePtr !=
nullptr && m_aNodePtr->children !=
nullptr);
621 Reference< XNode > SAL_CALL CNode::insertBefore(
622 const Reference< XNode >& newChild,
const Reference< XNode >& refChild)
626 checkSameOwner(newChild);
628 if (refChild->getParentNode() != Reference< XNode >(
this)) {
630 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
634 ::osl::ClearableMutexGuard guard(m_rMutex);
636 CNode *
const pNewNode(
dynamic_cast<CNode*
>(newChild.get()));
637 CNode *
const pRefNode(
dynamic_cast<CNode*
>(refChild.get()));
639 xmlNodePtr
const pNewChild(pNewNode->GetNodePtr());
640 xmlNodePtr
const pRefChild(pRefNode->GetNodePtr());
643 if (pNewChild == m_aNodePtr) {
645 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
649 checkNoParent(pNewChild);
651 if (!IsChildTypeAllowed(pNewNode->m_aNodeType,
nullptr)) {
653 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
658 if (XML_ATTRIBUTE_NODE == pNewChild->type) {
660 return appendChild(newChild);
663 xmlNodePtr cur = m_aNodePtr->children;
666 while (cur !=
nullptr)
668 if (cur == pRefChild) {
670 pNewChild->next = cur;
671 pNewChild->prev = cur->prev;
672 cur->prev = pNewChild;
673 if (pNewChild->prev !=
nullptr) {
674 pNewChild->prev->next = pNewChild;
676 pNewChild->parent = cur->parent;
677 if (pNewChild->parent->children == cur) {
678 pNewChild->parent->children = pNewChild;
681 pNewNode->m_bUnlinked =
false;
693 sal_Bool SAL_CALL CNode::isSupported(
const OUString& ,
const OUString& )
695 OSL_ENSURE(
false,
"CNode::isSupported: not implemented (#i113683#)");
706 void SAL_CALL CNode::normalize()
709 OSL_ENSURE(
false,
"CNode::normalize: not implemented (#i113683#)");
716 Reference< XNode > SAL_CALL
717 CNode::removeChild(
const Reference< XNode >& xOldChild)
719 if (!xOldChild.is()) {
723 checkSameOwner(xOldChild);
725 if (xOldChild->getParentNode() != Reference< XNode >(
this)) {
727 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
731 ::osl::ClearableMutexGuard guard(m_rMutex);
735 Reference<XNode> xReturn( xOldChild );
739 xmlNodePtr
const old = pOld->GetNodePtr();
742 if( old->type == XML_ATTRIBUTE_NODE )
744 xmlAttrPtr pAttr =
reinterpret_cast<xmlAttrPtr
>(old);
745 xmlRemoveProp( pAttr );
752 pOld->m_bUnlinked =
true;
763 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
764 Reference< XMutationEvent > event(docevent->createEvent(
765 "DOMNodeRemoved"), UNO_QUERY);
766 event->initMutationEvent(
"DOMNodeRemoved",
770 OUString(), OUString(), OUString(), AttrChangeType(0) );
776 dispatchEvent(event);
778 dispatchSubtreeModified();
787 Reference< XNode > SAL_CALL CNode::replaceChild(
788 Reference< XNode >
const& xNewChild,
789 Reference< XNode >
const& xOldChild)
791 if (!xOldChild.is() || !xNewChild.is()) {
795 checkSameOwner(xNewChild);
797 if (xOldChild->getParentNode() != Reference< XNode >(
this)) {
799 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
803 ::osl::ClearableMutexGuard guard(m_rMutex);
808 xmlNodePtr
const pOld = pOldNode->GetNodePtr();
809 xmlNodePtr
const pNew = pNewNode->GetNodePtr();
812 if (pNew == m_aNodePtr) {
814 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
820 if (!IsChildTypeAllowed(pNewNode->m_aNodeType, &pOldNode->m_aNodeType)) {
822 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
826 if( pOld->type == XML_ATTRIBUTE_NODE )
829 if ( pOld->type != pNew->type )
832 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
836 xmlAttrPtr pAttr =
reinterpret_cast<xmlAttrPtr
>(pOld);
837 xmlRemoveProp( pAttr );
838 pOldNode->invalidate();
839 appendChild(xNewChild);
844 xmlNodePtr cur = m_aNodePtr->children;
846 while (cur !=
nullptr)
851 pNew->prev = pOld->prev;
852 if (pNew->prev !=
nullptr)
853 pNew->prev->next = pNew;
854 pNew->next = pOld->next;
855 if (pNew->next !=
nullptr)
856 pNew->next->prev = pNew;
857 pNew->parent = pOld->parent;
858 assert(pNew->parent &&
"coverity[var_deref_op] pNew->parent cannot be NULL here");
859 if(pNew->parent->children == pOld)
860 pNew->parent->children = pNew;
861 if(pNew->parent->last == pOld)
862 pNew->parent->last = pNew;
863 pOld->next =
nullptr;
864 pOld->prev =
nullptr;
865 pOld->parent =
nullptr;
866 pOldNode->m_bUnlinked =
true;
867 pNewNode->m_bUnlinked =
false;
874 dispatchSubtreeModified();
879 void CNode::dispatchSubtreeModified()
885 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
886 Reference< XMutationEvent > event(docevent->createEvent(
887 "DOMSubtreeModified"), UNO_QUERY);
888 event->initMutationEvent(
889 "DOMSubtreeModified",
true,
890 false, Reference< XNode >(),
891 OUString(), OUString(), OUString(), AttrChangeType(0) );
892 dispatchEvent(event);
898 void SAL_CALL CNode::setNodeValue(
const OUString& )
903 e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
910 void SAL_CALL CNode::setPrefix(
const OUString& prefix)
912 ::osl::MutexGuard
const g(m_rMutex);
914 if ((
nullptr == m_aNodePtr) ||
915 ((m_aNodePtr->type != XML_ELEMENT_NODE) &&
916 (m_aNodePtr->type != XML_ATTRIBUTE_NODE)))
919 e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
923 xmlChar
const *pBuf =
reinterpret_cast<xmlChar
const *
>(o1.getStr());
924 if (m_aNodePtr !=
nullptr && m_aNodePtr->ns !=
nullptr)
926 xmlFree(
const_cast<xmlChar *
>(m_aNodePtr->ns->prefix));
927 m_aNodePtr->ns->prefix = xmlStrdup(pBuf);
933 void SAL_CALL CNode::addEventListener(
const OUString& eventType,
934 const Reference< css::xml::dom::events::XEventListener >& listener,
937 ::osl::MutexGuard
const g(m_rMutex);
939 CDocument & rDocument(GetOwnerDocument());
940 events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
941 rDispatcher.addListener(m_aNodePtr, eventType, listener, useCapture);
944 void SAL_CALL CNode::removeEventListener(
const OUString& eventType,
945 const Reference< css::xml::dom::events::XEventListener >& listener,
948 ::osl::MutexGuard
const g(m_rMutex);
950 CDocument & rDocument(GetOwnerDocument());
951 events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
952 rDispatcher.removeListener(m_aNodePtr, eventType, listener, useCapture);
955 sal_Bool SAL_CALL CNode::dispatchEvent(
const Reference< XEvent >& evt)
957 CDocument * pDocument;
958 events::CEventDispatcher * pDispatcher;
961 ::osl::MutexGuard
const g(m_rMutex);
963 pDocument = & GetOwnerDocument();
964 pDispatcher = & pDocument->GetEventDispatcher();
968 pDispatcher->dispatchEvent(*pDocument, m_rMutex, pNode,
this, evt);
Reference< XOfficeDatabaseDocument > m_xDocument
Sequence< sal_Int8 > aSeq
#define SAL_INFO(area, stream)
void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent)
eliminate redundant namespace declarations
static void lcl_nsexchange(xmlNodePtr const aNode, xmlNsPtr const oldNs, xmlNsPtr const newNs)
void popContext(Context &io_rContext)
void pushContext(Context &io_rContext)
sal_Int32 getTokenWithPrefix(const Context &rContext, const char *pPrefix, const char *pName)
sal_Int32 getToken(const Context &rContext, const char *pToken)
void addNamespaces(Context &io_rContext, xmlNodePtr pNode)
add namespaces on this node to context
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
rtl::Reference< sax_fastparser::FastTokenHandlerBase > mxTokenHandler
NamespaceVectorType maNamespaces
outer vector: xml context; inner vector: current NS
NamespaceMapType maNamespaceMap