void MarkupAccumulator::serializeNodesWithNamespaces(Node& targetNode, EChildrenOnly childrenOnly, const Namespaces* namespaces, Vector<QualifiedName>* tagNamesToSkip) { if (tagNamesToSkip) { for (size_t i = 0; i < tagNamesToSkip->size(); ++i) { if (targetNode.hasTagName(tagNamesToSkip->at(i))) return; } } Namespaces namespaceHash; if (namespaces) namespaceHash = *namespaces; if (!childrenOnly) appendStartTag(targetNode, &namespaceHash); if (!(serializeAsHTMLDocument(targetNode) && elementCannotHaveEndTag(targetNode))) { Node* current = isHTMLTemplateElement(targetNode) ? toHTMLTemplateElement(targetNode).content()->firstChild() : targetNode.firstChild(); for ( ; current; current = current->nextSibling()) serializeNodesWithNamespaces(*current, IncludeNode, &namespaceHash, tagNamesToSkip); } if (!childrenOnly) appendEndTag(targetNode); }
void MarkupAccumulator::serializeNodesWithNamespaces(Node* targetNode, Node* nodeToSkip, EChildrenOnly childrenOnly, const Namespaces* namespaces, Vector<QualifiedName>* tagNamesToSkip) { if (targetNode == nodeToSkip) return; if (tagNamesToSkip) { for (size_t i = 0; i < tagNamesToSkip->size(); ++i) { if (targetNode->hasTagName(tagNamesToSkip->at(i))) return; } } Namespaces namespaceHash; if (namespaces) namespaceHash = *namespaces; if (!childrenOnly) appendStartTag(targetNode, &namespaceHash); if (!(targetNode->document()->isHTMLDocument() && elementCannotHaveEndTag(targetNode))) { #if ENABLE(TEMPLATE_ELEMENT) Node* current = targetNode->hasTagName(templateTag) ? toHTMLTemplateElement(targetNode)->content()->firstChild() : targetNode->firstChild(); #else Node* current = targetNode->firstChild(); #endif for ( ; current; current = current->nextSibling()) serializeNodesWithNamespaces(current, nodeToSkip, IncludeNode, &namespaceHash, tagNamesToSkip); } if (!childrenOnly) appendEndTag(targetNode); }
void MarkupAccumulator::serializeNodesWithNamespaces(Node* node, Node* nodeToSkip, EChildrenOnly childrenOnly, const Namespaces* namespaces) { if (node == nodeToSkip) return; Namespaces namespaceHash; if (namespaces) namespaceHash = *namespaces; if (!childrenOnly) appendStartTag(node, &namespaceHash); if (!(node->document()->isHTMLDocument() && elementCannotHaveEndTag(node))) { for (Node* current = node->firstChild(); current; current = current->nextSibling()) serializeNodesWithNamespaces(current, nodeToSkip, IncludeNode, &namespaceHash); } if (!childrenOnly) appendEndTag(node); }
void MarkupAccumulator::serializeNodesWithNamespaces(Node& targetNode, Node* nodeToSkip, EChildrenOnly childrenOnly, const Namespaces* namespaces, Vector<QualifiedName>* tagNamesToSkip) { if (&targetNode == nodeToSkip) return; if (tagNamesToSkip && targetNode.isElementNode()) { for (size_t i = 0; i < tagNamesToSkip->size(); ++i) { if (targetNode.hasTagName(tagNamesToSkip->at(i))) return; } } Namespaces namespaceHash; if (namespaces) namespaceHash = *namespaces; else if (inXMLFragmentSerialization()) { // Make sure xml prefix and namespace are always known to uphold the constraints listed at http://www.w3.org/TR/xml-names11/#xmlReserved. namespaceHash.set(xmlAtom.impl(), XMLNames::xmlNamespaceURI.impl()); namespaceHash.set(XMLNames::xmlNamespaceURI.impl(), xmlAtom.impl()); } if (!childrenOnly) appendStartTag(targetNode, &namespaceHash); if (!(targetNode.document().isHTMLDocument() && elementCannotHaveEndTag(targetNode))) { #if ENABLE(TEMPLATE_ELEMENT) Node* current = targetNode.hasTagName(templateTag) ? toHTMLTemplateElement(targetNode).content()->firstChild() : targetNode.firstChild(); #else Node* current = targetNode.firstChild(); #endif for ( ; current; current = current->nextSibling()) serializeNodesWithNamespaces(*current, nodeToSkip, IncludeNode, &namespaceHash, tagNamesToSkip); } if (!childrenOnly) appendEndTag(targetNode); }
Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, Node* pastEnd, NodeTraversalMode traversalMode) { const bool shouldEmit = traversalMode == EmitString; Vector<RawPtr<ContainerNode> > ancestorsToClose; Node* next; Node* lastClosed = 0; for (Node* n = startNode; n != pastEnd; n = next) { // According to <rdar://problem/5730668>, it is possible for n to blow // past pastEnd and become null here. This shouldn't be possible. // This null check will prevent crashes (but create too much markup) // and the ASSERT will hopefully lead us to understanding the problem. ASSERT(n); if (!n) break; next = NodeTraversal::next(*n); bool openedTag = false; if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd) // Don't write out empty block containers that aren't fully selected. continue; if (!n->renderer() && m_shouldAnnotate != AnnotateForNavigationTransition) { next = NodeTraversal::nextSkippingChildren(*n); // Don't skip over pastEnd. if (pastEnd && pastEnd->isDescendantOf(n)) next = pastEnd; } else { // Add the node to the markup if we're not skipping the descendants if (shouldEmit) appendStartTag(*n); // If node has no children, close the tag now. if (n->isContainerNode() && toContainerNode(n)->hasChildren()) { openedTag = true; ancestorsToClose.append(toContainerNode(n)); } else { if (shouldEmit && n->isElementNode()) appendEndTag(toElement(*n)); lastClosed = n; } } // If we didn't insert open tag and there's no more siblings or we're at the end of the traversal, take care of ancestors. // FIXME: What happens if we just inserted open tag and reached the end? if (!openedTag && (!n->nextSibling() || next == pastEnd)) { // Close up the ancestors. while (!ancestorsToClose.isEmpty()) { ContainerNode* ancestor = ancestorsToClose.last(); ASSERT(ancestor); if (next != pastEnd && next->isDescendantOf(ancestor)) break; // Not at the end of the range, close ancestors up to sibling of next node. if (shouldEmit && ancestor->isElementNode()) appendEndTag(toElement(*ancestor)); lastClosed = ancestor; ancestorsToClose.removeLast(); } // Surround the currently accumulated markup with markup for ancestors we never opened as we leave the subtree(s) rooted at those ancestors. ContainerNode* nextParent = next ? next->parentNode() : 0; if (next != pastEnd && n != nextParent) { Node* lastAncestorClosedOrSelf = n->isDescendantOf(lastClosed) ? lastClosed : n; for (ContainerNode* parent = lastAncestorClosedOrSelf->parentNode(); parent && parent != nextParent; parent = parent->parentNode()) { // All ancestors that aren't in the ancestorsToClose list should either be a) unrendered: if (!parent->renderer()) continue; // or b) ancestors that we never encountered during a pre-order traversal starting at startNode: ASSERT(startNode->isDescendantOf(parent)); if (shouldEmit) wrapWithNode(*parent); lastClosed = parent; } } } } return lastClosed; }