1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: node.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
34 #include "element.hxx"
36 #include "cdatasection.hxx"
37 #include "entityreference.hxx"
39 #include "processinginstruction.hxx"
40 #include "comment.hxx"
41 #include "document.hxx"
42 #include "documenttype.hxx"
43 #include "documentfragment.hxx"
44 #include "notation.hxx"
45 #include "childlist.hxx"
48 #include <com/sun/star/xml/sax/FastToken.hpp>
50 #include "../events/eventdispatcher.hxx"
51 #include "../events/mutationevent.hxx"
53 #include <boost/bind.hpp>
58 void pushContext(Context
& io_rContext
)
60 io_rContext
.maNamespaces
.push_back(
61 io_rContext
.maNamespaces
.back());
64 void popContext(Context
& io_rContext
)
66 io_rContext
.maNamespaces
.pop_back();
69 void addNamespaces(Context
& io_rContext
, xmlNodePtr pNode
)
71 // add node's namespaces to current context
72 for (xmlNsPtr pNs
= pNode
->nsDef
; pNs
!= 0; pNs
= pNs
->next
) {
73 const xmlChar
*pPrefix
= pNs
->prefix
;
74 OString
prefix(reinterpret_cast<const sal_Char
*>(pPrefix
),
75 strlen(reinterpret_cast<const char*>(pPrefix
)));
76 const xmlChar
*pHref
= pNs
->href
;
77 OUString
val(reinterpret_cast<const sal_Char
*>(pHref
),
78 strlen(reinterpret_cast<const char*>(pHref
)),
79 RTL_TEXTENCODING_UTF8
);
81 OSL_TRACE("Trying to add namespace %s (prefix %s)",
82 (const char*)pHref
, (const char*)pPrefix
);
84 Context::NamespaceMapType::iterator aIter
=
85 io_rContext
.maNamespaceMap
.find(val
);
86 if( aIter
!= io_rContext
.maNamespaceMap
.end() )
88 Context::Namespace aNS
;
89 aNS
.maPrefix
= prefix
;
90 aNS
.mnToken
= aIter
->second
;
91 aNS
.maNamespaceURL
= val
;
93 io_rContext
.maNamespaces
.back().push_back(aNS
);
95 OSL_TRACE("Added with token 0x%x", aIter
->second
);
100 sal_Int32
getToken( const Context
& rContext
, const sal_Char
* pToken
)
102 const Sequence
<sal_Int8
> aSeq( (sal_Int8
*)pToken
, strlen( pToken
) );
103 return rContext
.mxTokenHandler
->getTokenFromUTF8( aSeq
);
106 sal_Int32
getTokenWithPrefix( const Context
& rContext
, const sal_Char
* pPrefix
, const sal_Char
* pName
)
108 sal_Int32 nNamespaceToken
= FastToken::DONTKNOW
;
109 OString
prefix(pPrefix
,
110 strlen(reinterpret_cast<const char*>(pPrefix
)));
112 OSL_TRACE("getTokenWithPrefix(): prefix %s, name %s",
113 (const char*)pPrefix
, (const char*)pName
);
115 Context::NamespaceVectorType::value_type::const_iterator aIter
;
116 if( (aIter
=std::find_if(rContext
.maNamespaces
.back().begin(),
117 rContext
.maNamespaces
.back().end(),
118 boost::bind(std::equal_to
<OString
>(),
119 boost::bind(&Context::Namespace::getPrefix
,
121 boost::cref(prefix
)))) != rContext
.maNamespaces
.back().end() )
123 nNamespaceToken
= aIter
->mnToken
;
124 sal_Int32 nNameToken
= getToken( rContext
, pName
);
125 if( nNameToken
!= FastToken::DONTKNOW
)
126 nNamespaceToken
|= nNameToken
;
129 return nNamespaceToken
;
133 nodemap_t
CNode::theNodeMap
;
135 void CNode::remove(const xmlNodePtr aNode
)
137 nodemap_t::iterator i
= CNode::theNodeMap
.find(aNode
);
138 if (i
!= CNode::theNodeMap
.end())
140 // CNode *pNode = i->second;
141 CNode::theNodeMap
.erase(i
);
146 CNode
* CNode::get(const xmlNodePtr aNode
, sal_Bool bCreate
)
152 //check whether there is already an instance for this node
153 nodemap_t::const_iterator i
= CNode::theNodeMap
.find(aNode
);
154 if (i
!= CNode::theNodeMap
.end())
160 // there is not yet an instance wrapping this node,
161 // create it and store it in the map
162 if (!bCreate
) return NULL
;
166 case XML_ELEMENT_NODE
:
167 // m_aNodeType = NodeType::ELEMENT_NODE;
168 pNode
= static_cast< CNode
* >(new CElement(aNode
));
171 // m_aNodeType = NodeType::TEXT_NODE;
172 pNode
= static_cast< CNode
* >(new CText(aNode
));
174 case XML_CDATA_SECTION_NODE
:
175 // m_aNodeType = NodeType::CDATA_SECTION_NODE;
176 pNode
= static_cast< CNode
* >(new CCDATASection(aNode
));
178 case XML_ENTITY_REF_NODE
:
179 // m_aNodeType = NodeType::ENTITY_REFERENCE_NODE;
180 pNode
= static_cast< CNode
* >(new CEntityReference(aNode
));
182 case XML_ENTITY_NODE
:
183 // m_aNodeType = NodeType::ENTITY_NODE;
184 pNode
= static_cast< CNode
* >(new CEntity((xmlEntityPtr
)aNode
));
187 // m_aNodeType = NodeType::PROCESSING_INSTRUCTION_NODE;
188 pNode
= static_cast< CNode
* >(new CProcessingInstruction(aNode
));
190 case XML_COMMENT_NODE
:
191 // m_aNodeType = NodeType::COMMENT_NODE;
192 pNode
= static_cast< CNode
* >(new CComment(aNode
));
194 case XML_DOCUMENT_NODE
:
195 // m_aNodeType = NodeType::DOCUMENT_NODE;
196 pNode
= static_cast< CNode
* >(new CDocument((xmlDocPtr
)aNode
));
198 case XML_DOCUMENT_TYPE_NODE
:
200 // m_aNodeType = NodeType::DOCUMENT_TYPE_NODE;
201 pNode
= static_cast< CNode
* >(new CDocumentType((xmlDtdPtr
)aNode
));
203 case XML_DOCUMENT_FRAG_NODE
:
204 // m_aNodeType = NodeType::DOCUMENT_FRAGMENT_NODE;
205 pNode
= static_cast< CNode
* >(new CDocumentFragment(aNode
));
207 case XML_NOTATION_NODE
:
208 // m_aNodeType = NodeType::NOTATION_NODE;
209 pNode
= static_cast< CNode
* >(new CNotation((xmlNotationPtr
)aNode
));
211 case XML_ATTRIBUTE_NODE
:
212 // m_aNodeType = NodeType::NOTATION_NODE;
213 pNode
= static_cast< CNode
* >(new CAttr((xmlAttrPtr
)aNode
));
215 // unsopported node types
216 case XML_HTML_DOCUMENT_NODE
:
217 case XML_ELEMENT_DECL
:
218 case XML_ATTRIBUTE_DECL
:
219 case XML_ENTITY_DECL
:
220 case XML_NAMESPACE_DECL
:
228 if(CNode::theNodeMap
.insert(nodemap_t::value_type(aNode
, pNode
)).second
)
230 // insertion done, register node with document
231 xmlDocPtr doc
= aNode
->doc
;
234 CDocument
* pDoc
= static_cast< CDocument
* >(CNode::get((xmlNodePtr
)doc
));
235 pDoc
->addnode(aNode
);
238 // if insertion failed, delete the new instance and return null
244 OSL_ENSURE(pNode
, "no node produced during CNode::get!");
248 xmlNodePtr
CNode::getNodePtr(const Reference
< XNode
>& aNode
)
251 CNode
* pNode
=dynamic_cast<CNode
*>(aNode
.get());
253 return pNode
->m_aNodePtr
;
264 void CNode::init_node(const xmlNodePtr aNode
)
268 // keep containing document alive
269 // (if we are not that document ourselves)
270 if (m_aNodePtr
->type
!= XML_DOCUMENT_NODE
)
271 m_rDocument
= getOwnerDocument();
276 //remove from list if this wrapper goes away
278 CNode::remove(m_aNodePtr
);
281 static void _nsexchange(const xmlNodePtr aNode
, xmlNsPtr oldNs
, xmlNsPtr newNs
)
283 // recursively exchange any references to oldNs with references to newNs
284 xmlNodePtr cur
= aNode
;
287 if (cur
->ns
== oldNs
)
289 if (cur
->type
== XML_ELEMENT_NODE
)
291 xmlAttrPtr curAttr
= cur
->properties
;
294 if (curAttr
->ns
== oldNs
)
296 curAttr
= curAttr
->next
;
298 _nsexchange(cur
->children
, oldNs
, newNs
);
304 /*static*/ void _nscleanup(const xmlNodePtr aNode
, const xmlNodePtr aParent
)
306 xmlNodePtr cur
= aNode
;
309 if (cur
!= NULL
&& cur
->type
== XML_ELEMENT_NODE
)
311 xmlAttrPtr curAttr
= cur
->properties
;
314 if (curAttr
->ns
!= NULL
)
316 xmlNsPtr ns
= xmlSearchNs(cur
->doc
, aParent
, curAttr
->ns
->prefix
);
320 curAttr
= curAttr
->next
;
326 _nscleanup(cur
->children
, cur
);
329 xmlNsPtr ns
= xmlSearchNs(cur
->doc
, aParent
, cur
->ns
->prefix
);
330 if (ns
!= NULL
&& ns
!= cur
->ns
&& strcmp((char*)ns
->href
, (char*)cur
->ns
->href
)==0)
332 xmlNsPtr curDef
= cur
->nsDef
;
333 xmlNsPtr
*refp
= &(cur
->nsDef
); // insert point
334 while (curDef
!= NULL
)
336 ns
= xmlSearchNs(cur
->doc
, aParent
, curDef
->prefix
);
337 if (ns
!= NULL
&& ns
!= curDef
&& strcmp((char*)ns
->href
, (char*)curDef
->href
)==0)
339 // reconnect ns pointers in sub-tree to newly found ns before
340 // removing redundant nsdecl to prevent dangling pointers.
341 _nsexchange(cur
, curDef
, ns
);
342 *refp
= curDef
->next
;
346 refp
= &(curDef
->next
);
347 curDef
= curDef
->next
;
356 void SAL_CALL
CNode::saxify(
357 const Reference
< XDocumentHandler
>& i_xHandler
) {
358 if (!i_xHandler
.is()) throw RuntimeException();
359 // default: do nothing
362 void SAL_CALL
CNode::fastSaxify(Context
& io_rContext
) {
363 if (!io_rContext
.mxDocHandler
.is()) throw RuntimeException();
364 // default: do nothing
368 Adds the node newChild to the end of the list of children of this node.
370 Reference
< XNode
> CNode::appendChild(const Reference
< XNode
>& newChild
)
371 throw (RuntimeException
, DOMException
)
373 Reference
< XNode
> aNode
;
374 if (m_aNodePtr
!= NULL
) {
375 xmlNodePtr cur
= CNode::getNodePtr(newChild
.get());
378 // from other document
379 if (cur
->doc
!= m_aNodePtr
->doc
) {
381 e
.Code
= DOMExceptionType_WRONG_DOCUMENT_ERR
;
385 if (cur
== m_aNodePtr
) {
387 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
390 // already has parant and is not attribute
391 if (cur
->parent
!= NULL
&& cur
->type
!= XML_ATTRIBUTE_NODE
) {
393 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
397 // check whether this is an attribute node so we remove it's
398 // carrier node if it has one
399 xmlNodePtr res
= NULL
;
400 if (cur
->type
== XML_ATTRIBUTE_NODE
)
402 if (cur
->parent
!= NULL
)
404 if (m_aNodePtr
->type
!= XML_ELEMENT_NODE
||
405 strcmp((char*)cur
->parent
->name
, "__private") != 0)
408 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
412 xmlNsPtr pAttrNs
= cur
->ns
;
413 xmlNsPtr pParentNs
= xmlSearchNs(m_aNodePtr
->doc
, m_aNodePtr
, pAttrNs
->prefix
);
414 if (pParentNs
== NULL
|| strcmp((char*)pParentNs
->href
, (char*)pAttrNs
->href
) != 0)
415 pParentNs
= xmlNewNs(m_aNodePtr
, pAttrNs
->href
, pAttrNs
->prefix
);
417 if (cur
->children
!= NULL
)
418 res
= (xmlNodePtr
)xmlNewNsProp(m_aNodePtr
, pParentNs
, cur
->name
, cur
->children
->content
);
420 res
= (xmlNodePtr
)xmlNewProp(m_aNodePtr
, cur
->name
, (xmlChar
*) "");
422 xmlFreeNode(cur
->parent
);
427 if (cur
->children
!= NULL
)
428 res
= (xmlNodePtr
)xmlNewProp(m_aNodePtr
, cur
->name
, cur
->children
->content
);
430 res
= (xmlNodePtr
)xmlNewProp(m_aNodePtr
, cur
->name
, (xmlChar
*) "");
435 res
= xmlAddChild(m_aNodePtr
, cur
);
438 // libxml can do optimizations, when appending nodes.
439 // if res != cur, something was optimized and the newchild-wrapper
444 // use custom ns cleanup instaead of
445 // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr);
446 // because that will not remove unneeded ns decls
447 _nscleanup(res
, m_aNodePtr
);
449 aNode
= Reference
< XNode
>(CNode::get(res
));
451 //XXX check for errors
453 // dispatch DOMNodeInserted event, target is the new node
454 // this node is the related node
458 Reference
< XDocumentEvent
> docevent(getOwnerDocument(), UNO_QUERY
);
459 Reference
< XMutationEvent
> event(docevent
->createEvent(
460 OUString::createFromAscii("DOMNodeInserted")), UNO_QUERY
);
461 event
->initMutationEvent(OUString::createFromAscii("DOMNodeInserted")
462 , sal_True
, sal_False
, Reference
< XNode
>(CNode::get(m_aNodePtr
)),
463 OUString(), OUString(), OUString(), (AttrChangeType
)0 );
464 dispatchEvent(Reference
< XEvent
>(event
, UNO_QUERY
));
466 // dispatch subtree modified for this node
467 dispatchSubtreeModified();
473 Returns a duplicate of this node, i.e., serves as a generic copy
474 constructor for nodes.
476 Reference
< XNode
> CNode::cloneNode(sal_Bool bDeep
)
477 throw (RuntimeException
)
479 Reference
< XNode
> aNode
;
480 if (m_aNodePtr
!= NULL
)
482 aNode
= Reference
< XNode
>(CNode::get(
483 xmlCopyNode (m_aNodePtr
, static_cast< int >(bDeep
))
486 //XXX check for errors
491 A NamedNodeMap containing the attributes of this node (if it is an Element)
494 Reference
< XNamedNodeMap
> CNode::getAttributes()
495 throw (RuntimeException
)
497 // return empty reference
498 // only element node may override this impl
499 return Reference
< XNamedNodeMap
>();
501 // get all children that are attributes
503 Reference< NamedNodeMap > aNodeMap(new AttributeNamedNodeMap(m_aNodePtr), UNO_QUERY);
509 A NodeList that contains all children of this node.
511 Reference
< XNodeList
> CNode::getChildNodes()
512 throw (RuntimeException
)
514 Reference
< XNodeList
> aNodeList
;
515 if (m_aNodePtr
!= NULL
)
517 aNodeList
= Reference
< XNodeList
>(new CChildList(CNode::get(m_aNodePtr
)));
519 // XXX check for errors?
524 The first child of this node.
526 Reference
< XNode
> CNode::getFirstChild()
527 throw (RuntimeException
)
529 Reference
< XNode
> aNode
;
530 if (m_aNodePtr
!= NULL
) {
531 aNode
= Reference
< XNode
>(CNode::get(m_aNodePtr
->children
));
537 The last child of this node.
539 Reference
< XNode
> SAL_CALL
CNode::getLastChild()
540 throw (RuntimeException
)
542 Reference
< XNode
> aNode
;
543 if (m_aNodePtr
!= NULL
) {
544 aNode
= Reference
< XNode
>(CNode::get(xmlGetLastChild(m_aNodePtr
)));
550 Returns the local part of the qualified name of this node.
552 OUString SAL_CALL
CNode::getLocalName()
553 throw (RuntimeException
)
557 --> Element / Attribute
558 if(m_aNodePtr != NULL && (m_aNodeType == NodeType::ATTRIBUTE_NODE
559 || m_aNodeType == NodeType::ELEMENT_NODE))
561 aName = OUString(m_aNodePtr->name, RTL_TEXTENCODING_UTF8);
570 The namespace URI of this node, or null if it is unspecified.
572 OUString SAL_CALL
CNode::getNamespaceURI()
573 throw (RuntimeException
)
576 if (m_aNodePtr
!= NULL
&&
577 (m_aNodePtr
->type
== XML_ELEMENT_NODE
|| m_aNodePtr
->type
== XML_ATTRIBUTE_NODE
) &&
578 m_aNodePtr
->ns
!= NULL
)
580 const xmlChar
* xHref
= m_aNodePtr
->ns
->href
;
581 aURI
= OUString((sal_Char
*)xHref
, strlen((char*)xHref
), RTL_TEXTENCODING_UTF8
);
587 The node immediately following this node.
589 Reference
< XNode
> SAL_CALL
CNode::getNextSibling()
590 throw (RuntimeException
)
592 Reference
< XNode
> aNode
;
593 if(m_aNodePtr
!= NULL
)
595 aNode
= Reference
< XNode
>(CNode::get(m_aNodePtr
->next
));
601 The name of this node, depending on its type; see the table above.
603 OUString SAL_CALL
CNode::getNodeName()
604 throw (RuntimeException
)
607 Interface nodeName nodeValue attributes
608 --------------------------------------------------------------------------------------
609 Attr name of attribute value of attribute null
610 CDATASection "#cdata-section" content of the CDATA Section null
611 Comment "#comment" content of the comment null
612 Document "#document" null null
613 DocumentFragment "#document-fragment" null null
614 DocumentType document type name null null
615 Element tag name null NamedNodeMap
616 Entity entity name null null
617 EntityReference name of entity null null
619 Notation notation name null null
620 Processing\ target entire content excluding null
621 Instruction the target
622 Text "#text" content of the text node null
629 A code representing the type of the underlying object, as defined above.
631 NodeType SAL_CALL
CNode::getNodeType()
632 throw (RuntimeException
)
638 The value of this node, depending on its type; see the table above.
640 OUString SAL_CALL
CNode::getNodeValue()
641 throw (RuntimeException
)
648 The Document object associated with this node.
650 Reference
< XDocument
> SAL_CALL
CNode::getOwnerDocument()
651 throw (RuntimeException
)
653 Reference
<XDocument
> aDoc
;
654 if (m_aNodePtr
!= NULL
)
656 aDoc
= Reference
< XDocument
>(static_cast< CDocument
* >(
657 CNode::get((xmlNodePtr
)m_aNodePtr
->doc
)));
664 The parent of this node.
666 Reference
< XNode
> SAL_CALL
CNode::getParentNode()
667 throw (RuntimeException
)
669 Reference
<XNode
> aNode
;
670 if (m_aNodePtr
!= NULL
)
672 aNode
= Reference
< XNode
>(CNode::get(m_aNodePtr
->parent
));
678 The namespace prefix of this node, or null if it is unspecified.
680 OUString SAL_CALL
CNode::getPrefix()
681 throw (RuntimeException
)
684 if (m_aNodePtr
!= NULL
&&
685 (m_aNodePtr
->type
== XML_ELEMENT_NODE
|| m_aNodePtr
->type
== XML_ATTRIBUTE_NODE
) &&
686 m_aNodePtr
->ns
!= NULL
)
688 const xmlChar
* xPrefix
= m_aNodePtr
->ns
->prefix
;
689 if( xPrefix
!= NULL
)
690 aPrefix
= OUString((sal_Char
*)xPrefix
, strlen((char*)xPrefix
), RTL_TEXTENCODING_UTF8
);
697 The node immediately preceding this node.
699 Reference
< XNode
> SAL_CALL
CNode::getPreviousSibling()
700 throw (RuntimeException
)
702 Reference
< XNode
> aNode
;
703 if (m_aNodePtr
!= NULL
)
705 aNode
= Reference
< XNode
>(CNode::get(m_aNodePtr
->prev
));
711 Returns whether this node (if it is an element) has any attributes.
713 sal_Bool SAL_CALL
CNode::hasAttributes()
714 throw (RuntimeException
)
716 return (m_aNodePtr
!= NULL
&& m_aNodePtr
->properties
!= NULL
);
720 Returns whether this node has any children.
722 sal_Bool SAL_CALL
CNode::hasChildNodes()
723 throw (RuntimeException
)
725 return (m_aNodePtr
!= NULL
&& m_aNodePtr
->children
!= NULL
);
729 Inserts the node newChild before the existing child node refChild.
731 Reference
< XNode
> SAL_CALL
CNode::insertBefore(
732 const Reference
< XNode
>& newChild
, const Reference
< XNode
>& refChild
)
733 throw (RuntimeException
, DOMException
)
736 if (newChild
->getOwnerDocument() != getOwnerDocument()) {
738 e
.Code
= DOMExceptionType_WRONG_DOCUMENT_ERR
;
741 if (refChild
->getParentNode() != Reference
< XNode
>(this)) {
743 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
747 xmlNodePtr pRefChild
= CNode::getNodePtr(refChild
.get());
748 xmlNodePtr pNewChild
= CNode::getNodePtr(newChild
.get());
749 xmlNodePtr cur
= m_aNodePtr
->children
;
751 //search cild before which to insert
754 if (cur
== pRefChild
) {
756 pNewChild
->next
= cur
;
757 pNewChild
->prev
= cur
->prev
;
758 cur
->prev
= pNewChild
;
759 if( pNewChild
->prev
!= NULL
)
760 pNewChild
->prev
->next
= pNewChild
;
768 Tests whether the DOM implementation implements a specific feature and
769 that feature is supported by this node.
771 sal_Bool SAL_CALL
CNode::isSupported(const OUString
& /*feature*/, const OUString
& /*ver*/)
772 throw (RuntimeException
)
779 Puts all Text nodes in the full depth of the sub-tree underneath this
780 Node, including attribute nodes, into a "normal" form where only structure
781 (e.g., elements, comments, processing instructions, CDATA sections, and
782 entity references) separates Text nodes, i.e., there are neither adjacent
783 Text nodes nor empty Text nodes.
785 void SAL_CALL
CNode::normalize()
786 throw (RuntimeException
)
788 //XXX combine adjacent text nodes and remove empty ones
792 Removes the child node indicated by oldChild from the list of children,
795 Reference
< XNode
> SAL_CALL
CNode::removeChild(const Reference
< XNode
>& oldChild
)
796 throw (RuntimeException
, DOMException
)
799 if (oldChild
->getParentNode() != Reference
< XNode
>(this)) {
801 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
805 Reference
<XNode
> xReturn( oldChild
);
807 xmlNodePtr old
= CNode::getNodePtr(oldChild
);
809 if( old
->type
== XML_ATTRIBUTE_NODE
)
811 xmlAttrPtr pAttr
= (xmlAttrPtr
) old
;
812 xmlRemoveProp( pAttr
);
819 if (m_aNodePtr
->last
== old
)
820 m_aNodePtr
->last
= old
->prev
;
822 xmlNodePtr cur
= m_aNodePtr
->children
;
823 //find old node in child list
828 // unlink node from list
829 if (cur
->prev
!= NULL
)
830 cur
->prev
->next
= cur
->next
;
831 if (cur
->next
!= NULL
)
832 cur
->next
->prev
= cur
->prev
;
833 if (cur
->parent
!= NULL
&& cur
->parent
->children
== cur
)
834 cur
->parent
->children
= cur
->next
;
844 * Fired when a node is being removed from its parent node.
845 * This event is dispatched before the node is removed from the tree.
846 * The target of this event is the node being removed.
849 * Context Info: relatedNode holds the parent node
853 Reference
< XDocumentEvent
> docevent(getOwnerDocument(), UNO_QUERY
);
854 Reference
< XMutationEvent
> event(docevent
->createEvent(
855 OUString::createFromAscii("DOMNodeRemoved")), UNO_QUERY
);
856 event
->initMutationEvent(OUString::createFromAscii("DOMNodeRemoved"), sal_True
,
857 sal_False
, Reference
< XNode
>(CNode::get(m_aNodePtr
)),
858 OUString(), OUString(), OUString(), (AttrChangeType
)0 );
859 dispatchEvent(Reference
< XEvent
>(event
, UNO_QUERY
));
861 // subtree modofied for this node
862 dispatchSubtreeModified();
868 Replaces the child node oldChild with newChild in the list of children,
869 and returns the oldChild node.
871 Reference
< XNode
> SAL_CALL
CNode::replaceChild(
872 const Reference
< XNode
>& newChild
, const Reference
< XNode
>& oldChild
)
873 throw (RuntimeException
, DOMException
)
875 // XXX check node types
877 if (oldChild
->getParentNode() != Reference
< XNode
>(this)) {
879 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
884 Reference< XNode > aNode = removeChild(oldChild);
885 appendChild(newChild);
887 xmlNodePtr pOld
= CNode::getNodePtr(oldChild
);
888 xmlNodePtr pNew
= CNode::getNodePtr(newChild
);
890 if( pOld
->type
== XML_ATTRIBUTE_NODE
)
892 // can only replace attribute with attribute
893 if ( pOld
->type
!= pNew
->type
)
896 e
.Code
= DOMExceptionType_HIERARCHY_REQUEST_ERR
;
900 xmlAttrPtr pAttr
= (xmlAttrPtr
)pOld
;
901 xmlRemoveProp( pAttr
);
902 appendChild( newChild
);
907 xmlNodePtr cur
= m_aNodePtr
->children
;
908 //find old node in child list
914 pNew
->prev
= pOld
->prev
;
915 if (pNew
->prev
!= NULL
)
916 pNew
->prev
->next
= pNew
;
917 pNew
->next
= pOld
->next
;
918 if (pNew
->next
!= NULL
)
919 pNew
->next
->prev
= pNew
;
920 pNew
->parent
= pOld
->parent
;
921 if(pNew
->parent
->children
== pOld
)
922 pNew
->parent
->children
= pNew
;
923 if(pNew
->parent
->last
== pOld
)
924 pNew
->parent
->last
= pNew
;
933 dispatchSubtreeModified();
938 void CNode::dispatchSubtreeModified()
940 // dispatch DOMSubtreeModified
941 // target is _this_ node
942 Reference
< XDocumentEvent
> docevent(getOwnerDocument(), UNO_QUERY
);
943 Reference
< XMutationEvent
> event(docevent
->createEvent(
944 OUString::createFromAscii("DOMSubtreeModified")), UNO_QUERY
);
945 event
->initMutationEvent(OUString::createFromAscii("DOMSubtreeModified"), sal_True
,
946 sal_False
, Reference
< XNode
>(),
947 OUString(), OUString(), OUString(), (AttrChangeType
)0 );
948 dispatchEvent(Reference
< XEvent
>(event
, UNO_QUERY
));
952 The value of this node, depending on its type; see the table above.
954 void SAL_CALL
CNode::setNodeValue(const OUString
& /*nodeValue*/)
955 throw (RuntimeException
, DOMException
)
957 // use specific node implememntation
958 // if we end up down here, something went wrong
960 e
.Code
= DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR
;
965 The namespace prefix of this node, or null if it is unspecified.
967 void SAL_CALL
CNode::setPrefix(const OUString
& prefix
)
968 throw (RuntimeException
, DOMException
)
970 OString o1
= OUStringToOString(prefix
, RTL_TEXTENCODING_UTF8
);
971 xmlChar
*pBuf
= (xmlChar
*)o1
.getStr();
973 // XXX free old string? (leak?)
974 if (m_aNodePtr
!= NULL
&& m_aNodePtr
->ns
!= NULL
)
976 m_aNodePtr
->ns
->prefix
= pBuf
;
982 void SAL_CALL
CNode::addEventListener(const OUString
& eventType
,
983 const Reference
< com::sun::star::xml::dom::events::XEventListener
>& listener
,
985 throw (RuntimeException
)
987 events::CEventDispatcher::addListener(m_aNodePtr
, eventType
, listener
, useCapture
);
990 void SAL_CALL
CNode::removeEventListener(const OUString
& eventType
,
991 const Reference
< com::sun::star::xml::dom::events::XEventListener
>& listener
,
993 throw (RuntimeException
)
995 events::CEventDispatcher::removeListener(m_aNodePtr
, eventType
, listener
, useCapture
);
998 sal_Bool SAL_CALL
CNode::dispatchEvent(const Reference
< XEvent
>& evt
)
999 throw(RuntimeException
, EventException
)
1001 events::CEventDispatcher::dispatchEvent(m_aNodePtr
, evt
);