void Step::nodesInAxis(Node* context, NodeSet& nodes) const { ASSERT(nodes.isEmpty()); switch (m_axis) { case ChildAxis: if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children. return; for (Node* n = context->firstChild(); n; n = n->nextSibling()) if (nodeMatches(n)) nodes.append(n); return; case DescendantAxis: if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children. return; for (Node* n = context->firstChild(); n; n = n->traverseNextNode(context)) if (nodeMatches(n)) nodes.append(n); return; case ParentAxis: if (context->isAttributeNode()) { Node* n = static_cast<Attr*>(context)->ownerElement(); if (nodeMatches(n)) nodes.append(n); } else { Node* n = context->parentNode(); if (n && nodeMatches(n)) nodes.append(n); } return; case AncestorAxis: { Node* n = context; if (context->isAttributeNode()) { n = static_cast<Attr*>(context)->ownerElement(); if (nodeMatches(n)) nodes.append(n); } for (n = n->parentNode(); n; n = n->parentNode()) if (nodeMatches(n)) nodes.append(n); nodes.reverse(); return; } case FollowingSiblingAxis: if (context->nodeType() == Node::ATTRIBUTE_NODE || context->nodeType() == Node::XPATH_NAMESPACE_NODE) return; for (Node* n = context->nextSibling(); n; n = n->nextSibling()) if (nodeMatches(n)) nodes.append(n); return; case PrecedingSiblingAxis: if (context->nodeType() == Node::ATTRIBUTE_NODE || context->nodeType() == Node::XPATH_NAMESPACE_NODE) return; for (Node* n = context->previousSibling(); n; n = n->previousSibling()) if (nodeMatches(n)) nodes.append(n); nodes.reverse(); return; case FollowingAxis: if (context->isAttributeNode()) { Node* p = static_cast<Attr*>(context)->ownerElement(); while ((p = p->traverseNextNode())) if (nodeMatches(p)) nodes.append(p); } else { for (Node* p = context; !isRootDomNode(p); p = p->parentNode()) { for (Node* n = p->nextSibling(); n; n = n->nextSibling()) { if (nodeMatches(n)) nodes.append(n); for (Node* c = n->firstChild(); c; c = c->traverseNextNode(n)) if (nodeMatches(c)) nodes.append(c); } } } return; case PrecedingAxis: if (context->isAttributeNode()) context = static_cast<Attr*>(context)->ownerElement(); for (Node* p = context; !isRootDomNode(p); p = p->parentNode()) { for (Node* n = p->previousSibling(); n ; n = n->previousSibling()) { if (nodeMatches(n)) nodes.append(n); for (Node* c = n->firstChild(); c; c = c->traverseNextNode(n)) if (nodeMatches(c)) nodes.append(c); } } nodes.markSorted(false); return; case AttributeAxis: { if (context->nodeType() != Node::ELEMENT_NODE) return; // Avoid lazily creating attribute nodes for attributes that we do not need anyway. if (m_nodeTest.kind() == NodeTest::NameTest && m_nodeTest.data() != "*") { RefPtr<Node> n = static_cast<Element*>(context)->getAttributeNodeNS(m_nodeTest.namespaceURI(), m_nodeTest.data()); if (n && n->namespaceURI() != "http://www.w3.org/2000/xmlns/") // In XPath land, namespace nodes are not accessible on the attribute axis. nodes.append(n.release()); return; } NamedAttrMap* attrs = context->attributes(); if (!attrs) return; for (unsigned long i = 0; i < attrs->length(); ++i) { RefPtr<Node> n = attrs->item(i); if (nodeMatches(n.get())) nodes.append(n.release()); } return; } case NamespaceAxis: // XPath namespace nodes are not implemented yet. return; case SelfAxis: if (nodeMatches(context)) nodes.append(context); return; case DescendantOrSelfAxis: if (nodeMatches(context)) nodes.append(context); if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children. return; for (Node* n = context->firstChild(); n; n = n->traverseNextNode(context)) if (nodeMatches(n)) nodes.append(n); return; case AncestorOrSelfAxis: { if (nodeMatches(context)) nodes.append(context); Node* n = context; if (context->isAttributeNode()) { n = static_cast<Attr*>(context)->ownerElement(); if (nodeMatches(n)) nodes.append(n); } for (n = n->parentNode(); n; n = n->parentNode()) if (nodeMatches(n)) nodes.append(n); nodes.reverse(); return; } } ASSERT_NOT_REACHED(); }