2 * This file is part of the DOM implementation for KDE.
4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5 * (C) 1999 Antti Koivisto (koivisto@kde.org)
6 * (C) 2001 Dirk Mueller (mueller@kde.org)
7 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
28 #include "ChildNodeList.h"
29 #include "DOMImplementation.h"
31 #include "ExceptionCode.h"
33 #include "NamedAttrMap.h"
35 #include "htmlediting.h"
36 #include "HTMLNames.h"
37 #include "kjs_binding.h"
38 #include "RenderObject.h"
39 #include "TextStream.h"
43 using namespace HTMLNames;
46 * NodeList which lists all Nodes in a document with a given tag name
48 class TagNodeList : public NodeList
51 TagNodeList(Node *n, const AtomicString& namespaceURI, const AtomicString& localName);
53 // DOM methods overridden from parent classes
54 virtual unsigned length() const;
55 virtual Node *item (unsigned index) const;
57 // Other methods (not part of DOM)
60 virtual bool nodeMatches(Node *testNode) const;
62 AtomicString m_namespaceURI;
63 AtomicString m_localName;
66 TagNodeList::TagNodeList(Node *n, const AtomicString& namespaceURI, const AtomicString& localName)
68 m_namespaceURI(namespaceURI),
69 m_localName(localName)
73 unsigned TagNodeList::length() const
75 return recursiveLength();
78 Node *TagNodeList::item(unsigned index) const
80 return recursiveItem(index);
83 bool TagNodeList::nodeMatches(Node *testNode) const
85 if (!testNode->isElementNode())
88 if (m_namespaceURI != starAtom && m_namespaceURI != testNode->namespaceURI())
91 return m_localName == starAtom || m_localName == testNode->localName();
96 struct NodeImplCounter {
98 ~NodeImplCounter() { if (count != 0) fprintf(stderr, "LEAK: %d Node\n", count); }
100 int NodeImplCounter::count = 0;
101 static NodeImplCounter nodeImplCounter;
104 Node::Node(Document *doc)
116 m_hasChangedChild(false),
123 m_inActiveChain(false),
124 m_styleElement(false),
129 ++NodeImplCounter::count;
133 void Node::setDocument(Document *doc)
144 --NodeImplCounter::count;
150 m_previous->setNextSibling(0);
152 m_next->setPreviousSibling(0);
155 String Node::nodeValue() const
160 void Node::setNodeValue( const String &/*_nodeValue*/, ExceptionCode& ec)
162 // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
163 if (isReadOnlyNode()) {
164 ec = NO_MODIFICATION_ALLOWED_ERR;
168 // be default nodeValue is null, so setting it has no effect
171 PassRefPtr<NodeList> Node::childNodes()
173 return new ChildNodeList(this);
176 Node *Node::firstChild() const
181 Node *Node::lastChild() const
186 Node *Node::lastDescendant() const
188 Node *n = const_cast<Node *>(this);
189 while (n && n->lastChild())
194 Node* Node::firstDescendant() const
196 Node *n = const_cast<Node *>(this);
197 while (n && n->firstChild())
202 bool Node::insertBefore(PassRefPtr<Node>, Node*, ExceptionCode& ec)
204 ec = HIERARCHY_REQUEST_ERR;
208 bool Node::replaceChild(PassRefPtr<Node>, Node*, ExceptionCode& ec)
210 ec = HIERARCHY_REQUEST_ERR;
214 bool Node::removeChild(Node*, ExceptionCode& ec)
220 bool Node::appendChild(PassRefPtr<Node>, ExceptionCode& ec)
222 ec = HIERARCHY_REQUEST_ERR;
226 void Node::remove(ExceptionCode& ec)
229 if (Node *p = parentNode())
230 p->removeChild(this, ec);
232 ec = HIERARCHY_REQUEST_ERR;
236 bool Node::hasChildNodes( ) const
241 void Node::normalize ()
243 ExceptionCode ec = 0;
244 Node *child = firstChild();
246 if (isElementNode()) {
247 // Normalize any attribute children we might have
248 Element *element = static_cast<Element *>(this);
249 NamedAttrMap *attrMap = element->attributes();
252 unsigned numAttrs = attrMap->length();
254 for (unsigned i = 0; i < numAttrs; i++) {
255 Attribute *attribute = attrMap->attributeItem(i);
256 Attr *attr = attribute->attr();
264 // Recursively go through the subtree beneath us, normalizing all nodes. In the case
265 // where there are two adjacent text nodes, they are merged together
267 Node *nextChild = child->nextSibling();
269 if (nextChild && child->nodeType() == TEXT_NODE && nextChild->nodeType() == TEXT_NODE) {
270 // Current child and the next one are both text nodes... merge them
271 Text *currentText = static_cast<Text*>(child);
272 Text *nextText = static_cast<Text*>(nextChild);
274 currentText->appendData(nextText->data(),ec);
278 nextChild->remove(ec);
288 // Check if we have a single empty text node left and remove it if so
289 child = firstChild();
290 if (child && !child->nextSibling() && child->isTextNode()) {
291 Text *text = static_cast<Text*>(child);
292 if (text->data().isEmpty())
297 const AtomicString& Node::prefix() const
299 // For nodes other than elements and attributes, the prefix is always null
303 void Node::setPrefix(const AtomicString &/*_prefix*/, ExceptionCode& ec)
305 // The spec says that for nodes other than elements and attributes, prefix is always null.
306 // It does not say what to do when the user tries to set the prefix on another type of
307 // node, however mozilla throws a NAMESPACE_ERR exception
311 const AtomicString& Node::localName() const
316 const AtomicString& Node::namespaceURI() const
321 ContainerNode* Node::addChild(PassRefPtr<Node>)
326 bool Node::isContentEditable() const
328 return parent() && parent()->isContentEditable();
331 bool Node::isContentRichlyEditable() const
333 return parent() && parent()->isContentRichlyEditable();
336 IntRect Node::getRect() const
339 if (renderer() && renderer()->absolutePosition(_x, _y))
340 return IntRect( _x, _y, renderer()->width(), renderer()->height() + renderer()->borderTopExtra() + renderer()->borderBottomExtra());
345 void Node::setChanged(bool b)
347 if (b && !attached()) // changed compared to what?
352 Node *p = parentNode();
354 p->setHasChangedChild( true );
357 document()->setDocumentChanged(true);
361 bool Node::isFocusable() const
366 bool Node::isKeyboardFocusable(KeyboardEvent*) const
368 return isFocusable();
371 bool Node::isMouseFocusable() const
373 return isFocusable();
376 unsigned Node::nodeIndex() const
378 Node *_tempNode = previousSibling();
380 for( count=0; _tempNode; count++ )
381 _tempNode = _tempNode->previousSibling();
385 void Node::registerNodeList(NodeList* list)
388 m_nodeLists = new NodeListSet;
389 m_nodeLists->add(list);
392 void Node::unregisterNodeList(NodeList* list)
396 m_nodeLists->remove(list);
399 void Node::notifyLocalNodeListsAttributeChanged()
404 NodeListSet::iterator end = m_nodeLists->end();
405 for (NodeListSet::iterator i = m_nodeLists->begin(); i != end; ++i)
406 (*i)->rootNodeAttributeChanged();
409 void Node::notifyNodeListsAttributeChanged()
411 for (Node *n = this; n; n = n->parentNode())
412 n->notifyLocalNodeListsAttributeChanged();
415 void Node::notifyLocalNodeListsChildrenChanged()
420 NodeListSet::iterator end = m_nodeLists->end();
421 for (NodeListSet::iterator i = m_nodeLists->begin(); i != end; ++i)
422 (*i)->rootNodeChildrenChanged();
425 void Node::notifyNodeListsChildrenChanged()
427 for (Node *n = this; n; n = n->parentNode())
428 n->notifyLocalNodeListsChildrenChanged();
431 unsigned Node::childNodeCount() const
436 Node *Node::childNode(unsigned /*index*/) const
441 Node *Node::traverseNextNode(const Node *stayWithin) const
444 assert(!stayWithin || firstChild()->isDescendantOf(stayWithin));
447 if (this == stayWithin)
450 assert(!stayWithin || nextSibling()->isDescendantOf(stayWithin));
451 return nextSibling();
453 const Node *n = this;
454 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
457 assert(!stayWithin || !n->nextSibling() || n->nextSibling()->isDescendantOf(stayWithin));
458 return n->nextSibling();
463 Node *Node::traverseNextSibling(const Node *stayWithin) const
465 if (this == stayWithin)
468 assert(!stayWithin || nextSibling()->isDescendantOf(stayWithin));
469 return nextSibling();
471 const Node *n = this;
472 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
475 assert(!stayWithin || !n->nextSibling() || n->nextSibling()->isDescendantOf(stayWithin));
476 return n->nextSibling();
481 Node *Node::traversePreviousNode(const Node *stayWithin) const
483 if (this == stayWithin)
485 if (previousSibling()) {
486 Node *n = previousSibling();
487 while (n->lastChild())
494 Node *Node::traversePreviousNodePostOrder(const Node *stayWithin) const
497 assert(!stayWithin || lastChild()->isDescendantOf(stayWithin));
500 if (this == stayWithin)
502 if (previousSibling()) {
503 assert(!stayWithin || previousSibling()->isDescendantOf(stayWithin));
504 return previousSibling();
506 const Node *n = this;
507 while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
510 assert(!stayWithin || !n->previousSibling() || n->previousSibling()->isDescendantOf(stayWithin));
511 return n->previousSibling();
516 void Node::checkSetPrefix(const AtomicString &_prefix, ExceptionCode& ec)
518 // Perform error checking as required by spec for setting Node.prefix. Used by
519 // Element::setPrefix() and Attr::setPrefix()
521 // FIXME: Implement support for INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
523 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
524 if (isReadOnlyNode()) {
525 ec = NO_MODIFICATION_ALLOWED_ERR;
529 // FIXME: Implement NAMESPACE_ERR: - Raised if the specified prefix is malformed
530 // We have to comment this out, since it's used for attributes and tag names, and we've only
531 // switched one over.
533 // - if the namespaceURI of this node is null,
534 // - if the specified prefix is "xml" and the namespaceURI of this node is different from
535 // "http://www.w3.org/XML/1998/namespace",
536 // - if this node is an attribute and the specified prefix is "xmlns" and
537 // the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
538 // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
539 if ((namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
540 (_prefix == "xml" && String(document()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
546 void Node::checkAddChild(Node *newChild, ExceptionCode& ec)
548 // Perform error checking as required by spec for adding a new child. Used by
549 // appendChild(), replaceChild() and insertBefore()
551 // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
557 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
558 if (isReadOnlyNode()) {
559 ec = NO_MODIFICATION_ALLOWED_ERR;
563 bool shouldAdoptChild = false;
565 // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
566 // created this node.
567 // We assume that if newChild is a DocumentFragment, all children are created from the same document
568 // as the fragment itself (otherwise they could not have been added as children)
569 if (newChild->document() != document()) {
570 // but if the child is not in a document yet then loosen the
571 // restriction, so that e.g. creating an element with the Option()
572 // constructor and then adding it to a different document works,
573 // as it does in Mozilla and Mac IE.
574 if (!newChild->inDocument()) {
575 shouldAdoptChild = true;
577 ec = WRONG_DOCUMENT_ERR;
582 // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
583 // newChild node, or if the node to append is one of this node's ancestors.
585 // check for ancestor/same node
586 if (newChild == this || isDescendantOf(newChild)) {
587 ec = HIERARCHY_REQUEST_ERR;
591 if (newChild->nodeType() != DOCUMENT_FRAGMENT_NODE) {
592 if (!childTypeAllowed(newChild->nodeType())) {
593 ec = HIERARCHY_REQUEST_ERR;
598 for (Node *n = newChild->firstChild(); n; n = n->nextSibling()) {
599 if (!childTypeAllowed(n->nodeType())) {
600 ec = HIERARCHY_REQUEST_ERR;
606 // change the document pointer of newChild and all of its children to be the new document
607 if (shouldAdoptChild) {
608 for (Node* node = newChild; node; node = node->traverseNextNode(newChild)) {
609 KJS::ScriptInterpreter::updateDOMNodeDocument(node, node->document(), document());
610 node->setDocument(document());
615 bool Node::isDescendantOf(const Node *other) const
617 // Return true if other is an ancestor of this, otherwise false
620 for (const Node *n = parentNode(); n; n = n->parentNode()) {
627 bool Node::childAllowed( Node *newChild )
629 return childTypeAllowed(newChild->nodeType());
632 Node::StyleChange Node::diff( RenderStyle *s1, RenderStyle *s2 ) const
634 // FIXME: The behavior of this function is just totally wrong. It doesn't handle
635 // explicit inheritance of non-inherited properties and so you end up not re-resolving
636 // style in cases where you need to.
637 StyleChange ch = NoInherit;
638 EDisplay display1 = s1 ? s1->display() : NONE;
639 bool fl1 = s1 && s1->hasPseudoStyle(RenderStyle::FIRST_LETTER);
640 EDisplay display2 = s2 ? s2->display() : NONE;
641 bool fl2 = s2 && s2->hasPseudoStyle(RenderStyle::FIRST_LETTER);
643 if (display1 != display2 || fl1 != fl2)
649 else if (s1->inheritedNotEqual(s2))
652 // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
653 // because setStyle will do the right thing with anything else.
654 if (ch == NoChange && s1->hasPseudoStyle(RenderStyle::BEFORE)) {
655 RenderStyle* ps2 = s2->getPseudoStyle(RenderStyle::BEFORE);
659 RenderStyle* ps1 = s1->getPseudoStyle(RenderStyle::BEFORE);
660 ch = ps1 && *ps1 == *ps2 ? NoChange : NoInherit;
663 if (ch == NoChange && s1->hasPseudoStyle(RenderStyle::AFTER)) {
664 RenderStyle* ps2 = s2->getPseudoStyle(RenderStyle::AFTER);
668 RenderStyle* ps1 = s1->getPseudoStyle(RenderStyle::AFTER);
669 ch = ps2 && *ps1 == *ps2 ? NoChange : NoInherit;
677 void Node::dump(TextStream *stream, DeprecatedString ind) const
679 // ### implement dump() for all appropriate subclasses
681 if (m_hasId) { *stream << " hasId"; }
682 if (m_hasClass) { *stream << " hasClass"; }
683 if (m_hasStyle) { *stream << " hasStyle"; }
684 if (m_specified) { *stream << " specified"; }
685 if (m_focused) { *stream << " focused"; }
686 if (m_active) { *stream << " active"; }
687 if (m_styleElement) { *stream << " styleElement"; }
688 if (m_implicit) { *stream << " implicit"; }
690 *stream << " tabIndex=" << m_tabIndex;
693 Node *child = firstChild();
695 *stream << ind << child->nodeName().deprecatedString().ascii() << ": ";
696 child->dump(stream,ind+" ");
697 child = child->nextSibling();
705 assert(!renderer() || (renderer()->style() && renderer()->parent()));
706 document()->incDOMTreeVersion();
710 void Node::willRemove()
719 renderer()->destroy();
722 Document* doc = document();
724 doc->hoveredNodeDetached(this);
726 doc->activeChainNodeDetached(this);
727 doc->incDOMTreeVersion();
731 m_inActiveChain = false;
736 void Node::insertedIntoDocument()
739 insertedIntoTree(false);
742 void Node::removedFromDocument()
744 setInDocument(false);
745 removedFromTree(false);
748 void Node::childrenChanged()
752 bool Node::isReadOnlyNode()
754 // Entity & Entity Reference nodes and their descendants are read-only
757 if (n->nodeType() == ENTITY_NODE || n->nodeType() == ENTITY_REFERENCE_NODE)
764 Node *Node::previousEditable() const
766 Node *node = previousLeafNode();
768 if (node->isContentEditable())
770 node = node->previousLeafNode();
775 // Offset specifies the child node to start at. If it is past
776 // the last child, it specifies to start at next sibling.
777 Node *Node::nextEditable(int offset) const
782 node = (offset >= (int)childNodeCount()) ? nextSibling() : childNode(offset)->nextLeafNode();
784 node = nextLeafNode();
786 if (node->isContentEditable())
788 node = node->nextLeafNode();
793 Node *Node::nextEditable() const
795 Node *node = nextLeafNode();
797 if (node->isContentEditable())
799 node = node->nextLeafNode();
804 RenderObject * Node::previousRenderer()
806 for (Node *n = previousSibling(); n; n = n->previousSibling()) {
808 return n->renderer();
813 RenderObject * Node::nextRenderer()
815 // Avoid an O(n^2) problem with this function by not checking for nextRenderer() when the parent element hasn't even
816 // been attached yet.
817 if (parent() && !parent()->attached())
820 for (Node *n = nextSibling(); n; n = n->nextSibling()) {
822 return n->renderer();
827 // FIXME: This code is used by editing. Seems like it could move over there and not pollute Node.
828 Node *Node::previousNodeConsideringAtomicNodes() const
830 if (previousSibling()) {
831 Node *n = previousSibling();
832 while (!isAtomicNode(n) && n->lastChild())
836 else if (parentNode()) {
844 Node *Node::nextNodeConsideringAtomicNodes() const
846 if (!isAtomicNode(this) && firstChild())
849 return nextSibling();
850 const Node *n = this;
851 while (n && !n->nextSibling())
854 return n->nextSibling();
858 Node *Node::previousLeafNode() const
860 Node *node = previousNodeConsideringAtomicNodes();
862 if (isAtomicNode(node))
864 node = node->previousNodeConsideringAtomicNodes();
869 Node *Node::nextLeafNode() const
871 Node *node = nextNodeConsideringAtomicNodes();
873 if (isAtomicNode(node))
875 node = node->nextNodeConsideringAtomicNodes();
880 void Node::createRendererIfNeeded()
882 if (!document()->shouldCreateRenderers())
888 Node *parent = parentNode();
891 RenderObject *parentRenderer = parent->renderer();
892 if (parentRenderer && parentRenderer->canHaveChildren()
894 && parent->childShouldCreateRenderer(this)
897 RenderStyle* style = styleForRenderer(parentRenderer);
898 if (rendererIsNeeded(style)) {
899 setRenderer(createRenderer(document()->renderArena(), style));
901 renderer()->setStyle(style);
902 parentRenderer->addChild(renderer(), nextRenderer());
905 style->deref(document()->renderArena());
909 RenderStyle *Node::styleForRenderer(RenderObject *parent)
911 RenderStyle *style = parent->style();
916 bool Node::rendererIsNeeded(RenderStyle *style)
918 return (document()->documentElement() == this) || (style->display() != NONE);
921 RenderObject *Node::createRenderer(RenderArena *arena, RenderStyle *style)
927 RenderStyle* Node::renderStyle() const
929 return m_renderer ? m_renderer->style() : 0;
932 void Node::setRenderStyle(RenderStyle* s)
935 m_renderer->setStyle(s);
938 int Node::maxOffset() const
943 // FIXME: Shouldn't these functions be in the editing code? Code that asks questions about HTML in the core DOM class
944 // is obviously misplaced.
945 int Node::caretMinOffset() const
947 return renderer() ? renderer()->caretMinOffset() : 0;
950 int Node::caretMaxOffset() const
952 return renderer() ? renderer()->caretMaxOffset() : 1;
955 unsigned Node::caretMaxRenderedOffset() const
957 return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
960 int Node::previousOffset (int current) const
962 return renderer() ? renderer()->previousOffset(current) : current - 1;
965 int Node::nextOffset (int current) const
967 return renderer() ? renderer()->nextOffset(current) : current + 1;
970 Node* Node::shadowAncestorNode()
974 if (n->isShadowNode())
975 return n->shadowParentNode();
981 bool Node::isBlockFlow() const
983 return renderer() && renderer()->isBlockFlow();
986 bool Node::isBlockFlowOrBlockTable() const
988 return renderer() && (renderer()->isBlockFlow() || renderer()->isTable() && !renderer()->isInline());
991 bool Node::isEditableBlock() const
993 return isContentEditable() && isBlockFlow();
996 Element *Node::enclosingBlockFlowOrTableElement() const
998 Node *n = const_cast<Node *>(this);
999 if (isBlockFlowOrBlockTable())
1000 return static_cast<Element *>(n);
1003 n = n->parentNode();
1006 if (n->isBlockFlowOrBlockTable() || n->hasTagName(bodyTag))
1007 return static_cast<Element *>(n);
1012 Element *Node::enclosingBlockFlowElement() const
1014 Node *n = const_cast<Node *>(this);
1016 return static_cast<Element *>(n);
1019 n = n->parentNode();
1022 if (n->isBlockFlow() || n->hasTagName(bodyTag))
1023 return static_cast<Element *>(n);
1028 Element *Node::enclosingInlineElement() const
1030 Node *n = const_cast<Node *>(this);
1034 p = n->parentNode();
1035 if (!p || p->isBlockFlow() || p->hasTagName(bodyTag))
1036 return static_cast<Element *>(n);
1037 // Also stop if any previous sibling is a block
1038 for (Node *sibling = n->previousSibling(); sibling; sibling = sibling->previousSibling()) {
1039 if (sibling->isBlockFlow())
1040 return static_cast<Element *>(n);
1044 ASSERT_NOT_REACHED();
1048 Element* Node::rootEditableElement() const
1050 Element* result = 0;
1051 for (Node* n = const_cast<Node*>(this); n && n->isContentEditable(); n = n->parentNode()) {
1052 if (n->isElementNode())
1053 result = static_cast<Element*>(n);
1054 if (n->hasTagName(bodyTag))
1060 bool Node::inSameContainingBlockFlowElement(Node *n)
1062 return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1065 // FIXME: End of obviously misplaced HTML editing functions. Try to move these out of Node.
1067 PassRefPtr<NodeList> Node::getElementsByTagName(const String& name)
1069 return getElementsByTagNameNS("*", name);
1072 PassRefPtr<NodeList> Node::getElementsByTagNameNS(const String &namespaceURI, const String &localName)
1074 if (namespaceURI.isNull() || localName.isNull())
1075 return 0; // FIXME: Who relies on getting 0 instead of a node list in this case?
1077 String name = localName;
1078 if (document()->isHTMLDocument())
1079 name = localName.lower();
1080 return new TagNodeList(this, AtomicString(namespaceURI), AtomicString(name));
1083 bool Node::isSupported(const String &feature, const String &version)
1085 return DOMImplementation::instance()->hasFeature(feature, version);
1088 Document *Node::ownerDocument() const
1090 Document *doc = document();
1091 return doc == this ? 0 : doc;
1094 bool Node::hasAttributes() const
1099 NamedAttrMap *Node::attributes() const
1104 bool Node::isEqualNode(Node *other) const
1109 if (nodeType() != other->nodeType())
1112 if (nodeName() != other->nodeName())
1115 if (localName() != other->localName())
1118 if (namespaceURI() != other->namespaceURI())
1121 if (prefix() != other->prefix())
1124 if (nodeValue() != other->nodeValue())
1127 NamedAttrMap *attrs = attributes();
1128 NamedAttrMap *otherAttrs = other->attributes();
1130 if (!attrs && otherAttrs)
1133 if (attrs && !attrs->mapsEquivalent(otherAttrs))
1136 Node *child = firstChild();
1137 Node *otherChild = other->firstChild();
1140 if (!child->isEqualNode(otherChild))
1143 child = child->nextSibling();
1144 otherChild = otherChild->nextSibling();
1150 // FIXME: For DocumentType nodes we should check equality on
1151 // the entities and notations NamedNodeMaps as well.
1156 bool Node::isDefaultNamespace(const String &namespaceURI) const
1158 // Implemented according to
1159 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#isDefaultNamespaceAlgo
1161 switch (nodeType()) {
1162 case ELEMENT_NODE: {
1163 const Element *elem = static_cast<const Element *>(this);
1165 if (elem->prefix().isNull())
1166 return elem->namespaceURI() == namespaceURI;
1168 if (elem->hasAttributes()) {
1169 NamedAttrMap *attrs = elem->attributes();
1171 for (unsigned i = 0; i < attrs->length(); i++) {
1172 Attribute *attr = attrs->attributeItem(i);
1174 if (attr->localName() == "xmlns")
1175 return attr->value() == namespaceURI;
1179 if (Element* ancestor = ancestorElement())
1180 return ancestor->isDefaultNamespace(namespaceURI);
1185 return static_cast <const Document *>(this)->documentElement()->isDefaultNamespace(namespaceURI);
1188 case DOCUMENT_TYPE_NODE:
1189 case DOCUMENT_FRAGMENT_NODE:
1191 case ATTRIBUTE_NODE: {
1192 const Attr *attr = static_cast<const Attr *>(this);
1193 if (attr->ownerElement())
1194 return attr->ownerElement()->isDefaultNamespace(namespaceURI);
1198 if (Element* ancestor = ancestorElement())
1199 return ancestor->isDefaultNamespace(namespaceURI);
1204 String Node::lookupPrefix(const String &namespaceURI) const
1206 // Implemented according to
1207 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespacePrefixAlgo
1209 if (namespaceURI.isEmpty())
1212 switch (nodeType()) {
1214 return lookupNamespacePrefix(namespaceURI, static_cast<const Element *>(this));
1216 return static_cast<const Document *>(this)->documentElement()->lookupPrefix(namespaceURI);
1219 case DOCUMENT_FRAGMENT_NODE:
1220 case DOCUMENT_TYPE_NODE:
1222 case ATTRIBUTE_NODE: {
1223 const Attr *attr = static_cast<const Attr *>(this);
1224 if (attr->ownerElement())
1225 return attr->ownerElement()->lookupPrefix(namespaceURI);
1229 if (Element* ancestor = ancestorElement())
1230 return ancestor->lookupPrefix(namespaceURI);
1235 String Node::lookupNamespaceURI(const String &prefix) const
1237 // Implemented according to
1238 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
1240 if (!prefix.isNull() && prefix.isEmpty())
1243 switch (nodeType()) {
1244 case ELEMENT_NODE: {
1245 const Element *elem = static_cast<const Element *>(this);
1247 if (!elem->namespaceURI().isNull() && elem->prefix() == prefix)
1248 return elem->namespaceURI();
1250 if (elem->hasAttributes()) {
1251 NamedAttrMap *attrs = elem->attributes();
1253 for (unsigned i = 0; i < attrs->length(); i++) {
1254 Attribute *attr = attrs->attributeItem(i);
1256 if (attr->prefix() == "xmlns" && attr->localName() == prefix) {
1257 if (!attr->value().isEmpty())
1258 return attr->value();
1261 } else if (attr->localName() == "xmlns" && prefix.isNull()) {
1262 if (!attr->value().isEmpty())
1263 return attr->value();
1269 if (Element* ancestor = ancestorElement())
1270 return ancestor->lookupNamespaceURI(prefix);
1274 return static_cast<const Document *>(this)->documentElement()->lookupNamespaceURI(prefix);
1277 case DOCUMENT_TYPE_NODE:
1278 case DOCUMENT_FRAGMENT_NODE:
1280 case ATTRIBUTE_NODE: {
1281 const Attr *attr = static_cast<const Attr *>(this);
1283 if (attr->ownerElement())
1284 return attr->ownerElement()->lookupNamespaceURI(prefix);
1289 if (Element* ancestor = ancestorElement())
1290 return ancestor->lookupNamespaceURI(prefix);
1295 String Node::lookupNamespacePrefix(const String &_namespaceURI, const Element *originalElement) const
1297 if (_namespaceURI.isNull())
1300 if (originalElement->lookupNamespaceURI(prefix()) == _namespaceURI)
1303 if (hasAttributes()) {
1304 NamedAttrMap *attrs = attributes();
1306 for (unsigned i = 0; i < attrs->length(); i++) {
1307 Attribute *attr = attrs->attributeItem(i);
1309 if (attr->prefix() == "xmlns" &&
1310 attr->value() == _namespaceURI &&
1311 originalElement->lookupNamespaceURI(attr->localName()) == _namespaceURI)
1312 return attr->localName();
1316 if (Element* ancestor = ancestorElement())
1317 return ancestor->lookupNamespacePrefix(_namespaceURI, originalElement);
1321 String Node::textContent(bool convertBRsToNewlines) const
1323 switch (nodeType()) {
1325 case CDATA_SECTION_NODE:
1327 case PROCESSING_INSTRUCTION_NODE:
1331 if (hasTagName(brTag) &&
1332 convertBRsToNewlines)
1334 case ATTRIBUTE_NODE:
1336 case ENTITY_REFERENCE_NODE:
1337 case DOCUMENT_FRAGMENT_NODE: {
1340 for (Node *child = firstChild(); child; child = child->nextSibling()) {
1341 if (child->nodeType() == COMMENT_NODE || child->nodeType() == PROCESSING_INSTRUCTION_NODE)
1344 s += child->textContent(convertBRsToNewlines);
1351 case DOCUMENT_TYPE_NODE:
1358 void Node::setTextContent(const String &text, ExceptionCode& ec)
1360 switch (nodeType()) {
1362 case CDATA_SECTION_NODE:
1364 case PROCESSING_INSTRUCTION_NODE:
1365 setNodeValue(text, ec);
1368 case ATTRIBUTE_NODE:
1370 case ENTITY_REFERENCE_NODE:
1371 case DOCUMENT_FRAGMENT_NODE: {
1372 ContainerNode *container = static_cast<ContainerNode *>(this);
1374 container->removeChildren();
1376 if (!text.isEmpty())
1377 appendChild(document()->createTextNode(text), ec);
1381 case DOCUMENT_TYPE_NODE:
1389 Element* Node::ancestorElement() const
1391 // In theory, there can be EntityReference nodes between elements, but this is currently not supported.
1392 for (Node* n = parentNode(); n; n = n->parentNode()) {
1393 if (n->isElementNode())
1394 return static_cast<Element*>(n);
1399 bool Node::offsetInCharacters() const
1406 static void appendAttributeDesc(const Node *node, String &string, const QualifiedName& name, DeprecatedString attrDesc)
1408 if (node->isElementNode()) {
1409 String attr = static_cast<const Element *>(node)->getAttribute(name);
1410 if (!attr.isEmpty()) {
1417 void Node::showNode(const char* prefix) const
1422 DeprecatedString value = nodeValue().deprecatedString();
1423 value.replace('\\', "\\\\");
1424 value.replace('\n', "\\n");
1425 fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().deprecatedString().utf8().data(), this, value.utf8().data());
1428 appendAttributeDesc(this, attrs, classAttr, " CLASS=");
1429 appendAttributeDesc(this, attrs, styleAttr, " STYLE=");
1430 fprintf(stderr, "%s%s\t%p%s\n", prefix, nodeName().deprecatedString().utf8().data(), this, attrs.deprecatedString().ascii());
1434 void Node::showTreeForThis() const
1436 showTreeAndMark(this, "*");
1439 void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char * markedLabel2) const
1441 const Node* rootNode;
1442 const Node* node = this;
1443 while (node->parentNode() && !node->hasTagName(bodyTag))
1444 node = node->parentNode();
1447 for (node = rootNode; node; node = node->traverseNextNode()) {
1448 if (node == markedNode1)
1449 fprintf(stderr, "%s", markedLabel1);
1450 if (node == markedNode2)
1451 fprintf(stderr, "%s", markedLabel2);
1453 for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentNode())
1454 fprintf(stderr, "\t");
1459 void Node::formatForDebugger(char *buffer, unsigned length) const
1465 if (s.length() == 0)
1470 strncpy(buffer, result.deprecatedString().latin1(), length - 1);
1479 void showTree(const WebCore::Node* node)
1482 node->showTreeForThis();