// Evaluate NodeTest without considering merged predicates. static inline bool nodeMatchesBasicTest(Node* node, Step::Axis axis, const Step::NodeTest& nodeTest) { switch (nodeTest.kind()) { case Step::NodeTest::TextNodeTest: return node->nodeType() == Node::TEXT_NODE || node->nodeType() == Node::CDATA_SECTION_NODE; case Step::NodeTest::CommentNodeTest: return node->nodeType() == Node::COMMENT_NODE; case Step::NodeTest::ProcessingInstructionNodeTest: { const AtomicString& name = nodeTest.data(); return node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE && (name.isEmpty() || node->nodeName() == name); } case Step::NodeTest::AnyNodeTest: return true; case Step::NodeTest::NameTest: { const AtomicString& name = nodeTest.data(); const AtomicString& namespaceURI = nodeTest.namespaceURI(); if (axis == Step::AttributeAxis) { ASSERT(node->isAttributeNode()); // In XPath land, namespace nodes are not accessible on the attribute axis. if (node->namespaceURI() == XMLNSNames::xmlnsNamespaceURI) return false; if (name == starAtom) return namespaceURI.isEmpty() || node->namespaceURI() == namespaceURI; return node->localName() == name && node->namespaceURI() == namespaceURI; } // Node test on the namespace axis is not implemented yet, the caller has a check for it. ASSERT(axis != Step::NamespaceAxis); // For other axes, the principal node type is element. ASSERT(primaryNodeType(axis) == Node::ELEMENT_NODE); if (node->nodeType() != Node::ELEMENT_NODE) return false; if (name == starAtom) return namespaceURI.isEmpty() || namespaceURI == node->namespaceURI(); if (node->document().isHTMLDocument()) { if (node->isHTMLElement()) { // Paths without namespaces should match HTML elements in HTML documents despite those having an XHTML namespace. Names are compared case-insensitively. return equalIgnoringCase(toElement(node)->localName(), name) && (namespaceURI.isNull() || namespaceURI == node->namespaceURI()); } // An expression without any prefix shouldn't match no-namespace nodes (because HTML5 says so). return toElement(node)->hasLocalName(name) && namespaceURI == node->namespaceURI() && !namespaceURI.isNull(); } return toElement(node)->hasLocalName(name) && namespaceURI == node->namespaceURI(); } } ASSERT_NOT_REACHED(); return false; }
bool Step::nodeMatches(Node* node) const { switch (m_nodeTest.kind()) { case NodeTest::TextNodeTest: return node->nodeType() == Node::TEXT_NODE || node->nodeType() == Node::CDATA_SECTION_NODE; case NodeTest::CommentNodeTest: return node->nodeType() == Node::COMMENT_NODE; case NodeTest::ProcessingInstructionNodeTest: { const String& name = m_nodeTest.data(); return node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE && (name.isEmpty() || node->nodeName() == name); } case NodeTest::ElementNodeTest: return node->isElementNode(); case NodeTest::AnyNodeTest: return true; case NodeTest::NameTest: { const String& name = m_nodeTest.data(); const String& namespaceURI = m_nodeTest.namespaceURI(); if (m_axis == AttributeAxis) { ASSERT(node->isAttributeNode()); // In XPath land, namespace nodes are not accessible on the attribute axis. if (node->namespaceURI() == "http://www.w3.org/2000/xmlns/") return false; if (name == "*") return namespaceURI.isEmpty() || node->namespaceURI() == namespaceURI; return node->localName() == name && node->namespaceURI() == namespaceURI; } if (m_axis == NamespaceAxis) { // Node test on the namespace axis is not implemented yet return false; } if (name == "*") return node->nodeType() == primaryNodeType(m_axis) && (namespaceURI.isEmpty() || namespaceURI == node->namespaceURI()); // We use tagQName here because we don't want the element name in uppercase // like we get with HTML elements. // Paths without namespaces should match HTML elements in HTML documents despite those having an XHTML namespace. return node->nodeType() == Node::ELEMENT_NODE && static_cast<Element*>(node)->tagQName().localName() == name && ((node->isHTMLElement() && node->document()->isHTMLDocument() && namespaceURI.isNull()) || namespaceURI == node->namespaceURI()); } } ASSERT_NOT_REACHED(); return false; }