String stringValue(Node* node) { switch (node->nodeType()) { case Node::ATTRIBUTE_NODE: case Node::PROCESSING_INSTRUCTION_NODE: case Node::COMMENT_NODE: case Node::TEXT_NODE: case Node::CDATA_SECTION_NODE: case Node::XPATH_NAMESPACE_NODE: return node->nodeValue(); default: if (isRootDomNode(node) || node->nodeType() == Node::ELEMENT_NODE) { StringBuilder result; result.reserveCapacity(1024); for (Node* n = node->firstChild(); n; n = NodeTraversal::next(*n, node)) { if (n->isTextNode()) { const String& nodeValue = n->nodeValue(); result.append(nodeValue); } } return result.toString(); } } return String(); }
String stringValue(Node* node) { switch (node->nodeType()) { case Node::ATTRIBUTE_NODE: case Node::PROCESSING_INSTRUCTION_NODE: case Node::COMMENT_NODE: case Node::TEXT_NODE: case Node::CDATA_SECTION_NODE: case Node::XPATH_NAMESPACE_NODE: return node->nodeValue(); default: if (isRootDomNode(node) || node->nodeType() == Node::ELEMENT_NODE) return TextNodeTraversal::contentsAsString(node); } return String(); }
// Result nodes are ordered in axis order. Node test (including merged predicates) is applied. 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, ChildAxis, m_nodeTest)) 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 = NodeTraversal::next(*n, context)) if (nodeMatches(n, DescendantAxis, m_nodeTest)) nodes.append(n); return; case ParentAxis: if (context->isAttributeNode()) { Element* n = toAttr(context)->ownerElement(); if (nodeMatches(n, ParentAxis, m_nodeTest)) nodes.append(n); } else { ContainerNode* n = context->parentNode(); if (n && nodeMatches(n, ParentAxis, m_nodeTest)) nodes.append(n); } return; case AncestorAxis: { Node* n = context; if (context->isAttributeNode()) { n = toAttr(context)->ownerElement(); if (nodeMatches(n, AncestorAxis, m_nodeTest)) nodes.append(n); } for (n = n->parentNode(); n; n = n->parentNode()) if (nodeMatches(n, AncestorAxis, m_nodeTest)) nodes.append(n); nodes.markSorted(false); 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, FollowingSiblingAxis, m_nodeTest)) 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, PrecedingSiblingAxis, m_nodeTest)) nodes.append(n); nodes.markSorted(false); return; case FollowingAxis: if (context->isAttributeNode()) { Node* p = toAttr(context)->ownerElement(); while ((p = NodeTraversal::next(*p))) { if (nodeMatches(p, FollowingAxis, m_nodeTest)) 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, FollowingAxis, m_nodeTest)) nodes.append(n); for (Node* c = n->firstChild(); c; c = NodeTraversal::next(*c, n)) if (nodeMatches(c, FollowingAxis, m_nodeTest)) nodes.append(c); } } } return; case PrecedingAxis: { if (context->isAttributeNode()) context = toAttr(context)->ownerElement(); Node* n = context; while (ContainerNode* parent = n->parentNode()) { for (n = NodeTraversal::previous(*n); n != parent; n = NodeTraversal::previous(*n)) if (nodeMatches(n, PrecedingAxis, m_nodeTest)) nodes.append(n); n = parent; } nodes.markSorted(false); return; } case AttributeAxis: { if (!context->isElementNode()) return; Element* contextElement = toElement(context); // Avoid lazily creating attribute nodes for attributes that we do not need anyway. if (m_nodeTest.kind() == NodeTest::NameTest && m_nodeTest.data() != starAtom) { RefPtr<Node> n = contextElement->getAttributeNodeNS(m_nodeTest.namespaceURI(), m_nodeTest.data()); if (n && n->namespaceURI() != XMLNSNames::xmlnsNamespaceURI) { // In XPath land, namespace nodes are not accessible on the attribute axis. if (nodeMatches(n.get(), AttributeAxis, m_nodeTest)) // Still need to check merged predicates. nodes.append(n.release()); } return; } if (!contextElement->hasAttributes()) return; for (unsigned i = 0; i < contextElement->attributeCount(); ++i) { RefPtr<Attr> attr = contextElement->ensureAttr(contextElement->attributeItem(i)->name()); if (nodeMatches(attr.get(), AttributeAxis, m_nodeTest)) nodes.append(attr.release()); } return; } case NamespaceAxis: // XPath namespace nodes are not implemented yet. return; case SelfAxis: if (nodeMatches(context, SelfAxis, m_nodeTest)) nodes.append(context); return; case DescendantOrSelfAxis: if (nodeMatches(context, DescendantOrSelfAxis, m_nodeTest)) nodes.append(context); if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children. return; for (Node* n = context->firstChild(); n; n = NodeTraversal::next(*n, context)) if (nodeMatches(n, DescendantOrSelfAxis, m_nodeTest)) nodes.append(n); return; case AncestorOrSelfAxis: { if (nodeMatches(context, AncestorOrSelfAxis, m_nodeTest)) nodes.append(context); Node* n = context; if (context->isAttributeNode()) { n = toAttr(context)->ownerElement(); if (nodeMatches(n, AncestorOrSelfAxis, m_nodeTest)) nodes.append(n); } for (n = n->parentNode(); n; n = n->parentNode()) if (nodeMatches(n, AncestorOrSelfAxis, m_nodeTest)) nodes.append(n); nodes.markSorted(false); return; } } ASSERT_NOT_REACHED(); }
// Result nodes are ordered in axis order. Node test (including merged // predicates) is applied. void Step::nodesInAxis(EvaluationContext& evaluationContext, Node* context, NodeSet& nodes) const { ASSERT(nodes.isEmpty()); switch (m_axis) { case ChildAxis: // In XPath model, attribute nodes do not have children. if (context->isAttributeNode()) return; for (Node* n = context->firstChild(); n; n = n->nextSibling()) { if (nodeMatches(evaluationContext, n, ChildAxis, nodeTest())) nodes.append(n); } return; case DescendantAxis: // In XPath model, attribute nodes do not have children. if (context->isAttributeNode()) return; for (Node* n = context->firstChild(); n; n = NodeTraversal::next(*n, context)) { if (nodeMatches(evaluationContext, n, DescendantAxis, nodeTest())) nodes.append(n); } return; case ParentAxis: if (context->isAttributeNode()) { Element* n = toAttr(context)->ownerElement(); if (nodeMatches(evaluationContext, n, ParentAxis, nodeTest())) nodes.append(n); } else { ContainerNode* n = context->parentNode(); if (n && nodeMatches(evaluationContext, n, ParentAxis, nodeTest())) nodes.append(n); } return; case AncestorAxis: { Node* n = context; if (context->isAttributeNode()) { n = toAttr(context)->ownerElement(); if (nodeMatches(evaluationContext, n, AncestorAxis, nodeTest())) nodes.append(n); } for (n = n->parentNode(); n; n = n->parentNode()) { if (nodeMatches(evaluationContext, n, AncestorAxis, nodeTest())) nodes.append(n); } nodes.markSorted(false); return; } case FollowingSiblingAxis: if (context->nodeType() == Node::ATTRIBUTE_NODE) return; for (Node* n = context->nextSibling(); n; n = n->nextSibling()) { if (nodeMatches(evaluationContext, n, FollowingSiblingAxis, nodeTest())) nodes.append(n); } return; case PrecedingSiblingAxis: if (context->nodeType() == Node::ATTRIBUTE_NODE) return; for (Node* n = context->previousSibling(); n; n = n->previousSibling()) { if (nodeMatches(evaluationContext, n, PrecedingSiblingAxis, nodeTest())) nodes.append(n); } nodes.markSorted(false); return; case FollowingAxis: if (context->isAttributeNode()) { for (Node* p = NodeTraversal::next(*toAttr(context)->ownerElement()); p; p = NodeTraversal::next(*p)) { if (nodeMatches(evaluationContext, p, FollowingAxis, nodeTest())) nodes.append(p); } } else { for (Node* p = context; !isRootDomNode(p); p = p->parentNode()) { for (Node* n = p->nextSibling(); n; n = n->nextSibling()) { if (nodeMatches(evaluationContext, n, FollowingAxis, nodeTest())) nodes.append(n); for (Node* c = n->firstChild(); c; c = NodeTraversal::next(*c, n)) { if (nodeMatches(evaluationContext, c, FollowingAxis, nodeTest())) nodes.append(c); } } } } return; case PrecedingAxis: { if (context->isAttributeNode()) context = toAttr(context)->ownerElement(); Node* n = context; while (ContainerNode* parent = n->parentNode()) { for (n = NodeTraversal::previous(*n); n != parent; n = NodeTraversal::previous(*n)) { if (nodeMatches(evaluationContext, n, PrecedingAxis, nodeTest())) nodes.append(n); } n = parent; } nodes.markSorted(false); return; } case AttributeAxis: { if (!context->isElementNode()) return; Element* contextElement = toElement(context); // Avoid lazily creating attribute nodes for attributes that we do not // need anyway. if (nodeTest().kind() == NodeTest::NameTest && nodeTest().data() != starAtom) { RefPtrWillBeRawPtr<Node> n = contextElement->getAttributeNodeNS(nodeTest().namespaceURI(), nodeTest().data()); // In XPath land, namespace nodes are not accessible on the attribute axis. if (n && n->namespaceURI() != XMLNSNames::xmlnsNamespaceURI) { // Still need to check merged predicates. if (nodeMatches(evaluationContext, n.get(), AttributeAxis, nodeTest())) nodes.append(n.release()); } return; } AttributeCollection attributes = contextElement->attributes(); AttributeCollection::iterator end = attributes.end(); for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) { RefPtrWillBeRawPtr<Attr> attr = contextElement->ensureAttr(it->name()); if (nodeMatches(evaluationContext, attr.get(), AttributeAxis, nodeTest())) nodes.append(attr.release()); } return; } case NamespaceAxis: // XPath namespace nodes are not implemented. return; case SelfAxis: if (nodeMatches(evaluationContext, context, SelfAxis, nodeTest())) nodes.append(context); return; case DescendantOrSelfAxis: if (nodeMatches(evaluationContext, context, DescendantOrSelfAxis, nodeTest())) nodes.append(context); // In XPath model, attribute nodes do not have children. if (context->isAttributeNode()) return; for (Node* n = context->firstChild(); n; n = NodeTraversal::next(*n, context)) { if (nodeMatches(evaluationContext, n, DescendantOrSelfAxis, nodeTest())) nodes.append(n); } return; case AncestorOrSelfAxis: { if (nodeMatches(evaluationContext, context, AncestorOrSelfAxis, nodeTest())) nodes.append(context); Node* n = context; if (context->isAttributeNode()) { n = toAttr(context)->ownerElement(); if (nodeMatches(evaluationContext, n, AncestorOrSelfAxis, nodeTest())) nodes.append(n); } for (n = n->parentNode(); n; n = n->parentNode()) { if (nodeMatches(evaluationContext, n, AncestorOrSelfAxis, nodeTest())) nodes.append(n); } nodes.markSorted(false); return; } } ASSERT_NOT_REACHED(); }
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(); }