| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights
reserved. |
| 3 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. | 3 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 : m_nodes(nodes) | 100 : m_nodes(nodes) |
| 101 , m_range(range) | 101 , m_range(range) |
| 102 , m_resolveURLsMethod(resolveUrlsMethod) | 102 , m_resolveURLsMethod(resolveUrlsMethod) |
| 103 { | 103 { |
| 104 } | 104 } |
| 105 | 105 |
| 106 MarkupAccumulator::~MarkupAccumulator() | 106 MarkupAccumulator::~MarkupAccumulator() |
| 107 { | 107 { |
| 108 } | 108 } |
| 109 | 109 |
| 110 String MarkupAccumulator::serializeNodes(Node* targetNode, EChildrenOnly childre
nOnly, Vector<QualifiedName>* tagNamesToSkip) | 110 String MarkupAccumulator::serializeNodes(Node& targetNode, EChildrenOnly childre
nOnly, Vector<QualifiedName>* tagNamesToSkip) |
| 111 { | 111 { |
| 112 serializeNodesWithNamespaces(targetNode, childrenOnly, 0, tagNamesToSkip); | 112 serializeNodesWithNamespaces(targetNode, childrenOnly, 0, tagNamesToSkip); |
| 113 return m_markup.toString(); | 113 return m_markup.toString(); |
| 114 } | 114 } |
| 115 | 115 |
| 116 void MarkupAccumulator::serializeNodesWithNamespaces(Node* targetNode, EChildren
Only childrenOnly, const Namespaces* namespaces, Vector<QualifiedName>* tagNames
ToSkip) | 116 void MarkupAccumulator::serializeNodesWithNamespaces(Node& targetNode, EChildren
Only childrenOnly, const Namespaces* namespaces, Vector<QualifiedName>* tagNames
ToSkip) |
| 117 { | 117 { |
| 118 if (tagNamesToSkip) { | 118 if (tagNamesToSkip) { |
| 119 for (size_t i = 0; i < tagNamesToSkip->size(); ++i) { | 119 for (size_t i = 0; i < tagNamesToSkip->size(); ++i) { |
| 120 if (targetNode->hasTagName(tagNamesToSkip->at(i))) | 120 if (targetNode.hasTagName(tagNamesToSkip->at(i))) |
| 121 return; | 121 return; |
| 122 } | 122 } |
| 123 } | 123 } |
| 124 | 124 |
| 125 Namespaces namespaceHash; | 125 Namespaces namespaceHash; |
| 126 if (namespaces) | 126 if (namespaces) |
| 127 namespaceHash = *namespaces; | 127 namespaceHash = *namespaces; |
| 128 | 128 |
| 129 if (!childrenOnly) | 129 if (!childrenOnly) |
| 130 appendStartTag(targetNode, &namespaceHash); | 130 appendStartTag(targetNode, &namespaceHash); |
| 131 | 131 |
| 132 if (!(targetNode->document().isHTMLDocument() && elementCannotHaveEndTag(tar
getNode))) { | 132 if (!(targetNode.document().isHTMLDocument() && elementCannotHaveEndTag(targ
etNode))) { |
| 133 Node* current = targetNode->hasTagName(templateTag) ? toHTMLTemplateElem
ent(targetNode)->content()->firstChild() : targetNode->firstChild(); | 133 Node* current = targetNode.hasTagName(templateTag) ? toHTMLTemplateEleme
nt(targetNode).content()->firstChild() : targetNode.firstChild(); |
| 134 for ( ; current; current = current->nextSibling()) | 134 for ( ; current; current = current->nextSibling()) |
| 135 serializeNodesWithNamespaces(current, IncludeNode, &namespaceHash, t
agNamesToSkip); | 135 serializeNodesWithNamespaces(*current, IncludeNode, &namespaceHash,
tagNamesToSkip); |
| 136 } | 136 } |
| 137 | 137 |
| 138 if (!childrenOnly) | 138 if (!childrenOnly) |
| 139 appendEndTag(targetNode); | 139 appendEndTag(targetNode); |
| 140 } | 140 } |
| 141 | 141 |
| 142 String MarkupAccumulator::resolveURLIfNeeded(const Element* element, const Strin
g& urlString) const | 142 String MarkupAccumulator::resolveURLIfNeeded(const Element& element, const Strin
g& urlString) const |
| 143 { | 143 { |
| 144 switch (m_resolveURLsMethod) { | 144 switch (m_resolveURLsMethod) { |
| 145 case ResolveAllURLs: | 145 case ResolveAllURLs: |
| 146 return element->document().completeURL(urlString).string(); | 146 return element.document().completeURL(urlString).string(); |
| 147 | 147 |
| 148 case ResolveNonLocalURLs: | 148 case ResolveNonLocalURLs: |
| 149 if (!element->document().url().isLocalFile()) | 149 if (!element.document().url().isLocalFile()) |
| 150 return element->document().completeURL(urlString).string(); | 150 return element.document().completeURL(urlString).string(); |
| 151 break; | 151 break; |
| 152 | 152 |
| 153 case DoNotResolveURLs: | 153 case DoNotResolveURLs: |
| 154 break; | 154 break; |
| 155 } | 155 } |
| 156 return urlString; | 156 return urlString; |
| 157 } | 157 } |
| 158 | 158 |
| 159 void MarkupAccumulator::appendString(const String& string) | 159 void MarkupAccumulator::appendString(const String& string) |
| 160 { | 160 { |
| 161 m_markup.append(string); | 161 m_markup.append(string); |
| 162 } | 162 } |
| 163 | 163 |
| 164 void MarkupAccumulator::appendStartTag(Node* node, Namespaces* namespaces) | 164 void MarkupAccumulator::appendStartTag(Node& node, Namespaces* namespaces) |
| 165 { | 165 { |
| 166 appendStartMarkup(m_markup, node, namespaces); | 166 appendStartMarkup(m_markup, node, namespaces); |
| 167 if (m_nodes) | 167 if (m_nodes) |
| 168 m_nodes->append(node); | 168 m_nodes->append(&node); |
| 169 } | 169 } |
| 170 | 170 |
| 171 void MarkupAccumulator::appendEndTag(Node* node) | 171 void MarkupAccumulator::appendEndTag(const Node& node) |
| 172 { | 172 { |
| 173 appendEndMarkup(m_markup, node); | 173 appendEndMarkup(m_markup, node); |
| 174 } | 174 } |
| 175 | 175 |
| 176 size_t MarkupAccumulator::totalLength(const Vector<String>& strings) | 176 size_t MarkupAccumulator::totalLength(const Vector<String>& strings) |
| 177 { | 177 { |
| 178 size_t length = 0; | 178 size_t length = 0; |
| 179 for (size_t i = 0; i < strings.size(); ++i) | 179 for (size_t i = 0; i < strings.size(); ++i) |
| 180 length += strings[i].length(); | 180 length += strings[i].length(); |
| 181 return length; | 181 return length; |
| 182 } | 182 } |
| 183 | 183 |
| 184 void MarkupAccumulator::concatenateMarkup(StringBuilder& result) | 184 void MarkupAccumulator::concatenateMarkup(StringBuilder& result) |
| 185 { | 185 { |
| 186 result.append(m_markup); | 186 result.append(m_markup); |
| 187 } | 187 } |
| 188 | 188 |
| 189 void MarkupAccumulator::appendAttributeValue(StringBuilder& result, const String
& attribute, bool documentIsHTML) | 189 void MarkupAccumulator::appendAttributeValue(StringBuilder& result, const String
& attribute, bool documentIsHTML) |
| 190 { | 190 { |
| 191 appendCharactersReplacingEntities(result, attribute, 0, attribute.length(), | 191 appendCharactersReplacingEntities(result, attribute, 0, attribute.length(), |
| 192 documentIsHTML ? EntityMaskInHTMLAttributeValue : EntityMaskInAttributeV
alue); | 192 documentIsHTML ? EntityMaskInHTMLAttributeValue : EntityMaskInAttributeV
alue); |
| 193 } | 193 } |
| 194 | 194 |
| 195 void MarkupAccumulator::appendCustomAttributes(StringBuilder&, Element*, Namespa
ces*) | 195 void MarkupAccumulator::appendCustomAttributes(StringBuilder&, const Element&, N
amespaces*) |
| 196 { | 196 { |
| 197 } | 197 } |
| 198 | 198 |
| 199 void MarkupAccumulator::appendQuotedURLAttributeValue(StringBuilder& result, con
st Element* element, const Attribute& attribute) | 199 void MarkupAccumulator::appendQuotedURLAttributeValue(StringBuilder& result, con
st Element& element, const Attribute& attribute) |
| 200 { | 200 { |
| 201 ASSERT(element->isURLAttribute(attribute)); | 201 ASSERT(element.isURLAttribute(attribute)); |
| 202 const String resolvedURLString = resolveURLIfNeeded(element, attribute.value
()); | 202 const String resolvedURLString = resolveURLIfNeeded(element, attribute.value
()); |
| 203 UChar quoteChar = '"'; | 203 UChar quoteChar = '"'; |
| 204 String strippedURLString = resolvedURLString.stripWhiteSpace(); | 204 String strippedURLString = resolvedURLString.stripWhiteSpace(); |
| 205 if (protocolIsJavaScript(strippedURLString)) { | 205 if (protocolIsJavaScript(strippedURLString)) { |
| 206 // minimal escaping for javascript urls | 206 // minimal escaping for javascript urls |
| 207 if (strippedURLString.contains('"')) { | 207 if (strippedURLString.contains('"')) { |
| 208 if (strippedURLString.contains('\'')) | 208 if (strippedURLString.contains('\'')) |
| 209 strippedURLString.replaceWithLiteral('"', """); | 209 strippedURLString.replaceWithLiteral('"', """); |
| 210 else | 210 else |
| 211 quoteChar = '\''; | 211 quoteChar = '\''; |
| 212 } | 212 } |
| 213 result.append(quoteChar); | 213 result.append(quoteChar); |
| 214 result.append(strippedURLString); | 214 result.append(strippedURLString); |
| 215 result.append(quoteChar); | 215 result.append(quoteChar); |
| 216 return; | 216 return; |
| 217 } | 217 } |
| 218 | 218 |
| 219 // FIXME: This does not fully match other browsers. Firefox percent-escapes
non-ASCII characters for innerHTML. | 219 // FIXME: This does not fully match other browsers. Firefox percent-escapes
non-ASCII characters for innerHTML. |
| 220 result.append(quoteChar); | 220 result.append(quoteChar); |
| 221 appendAttributeValue(result, resolvedURLString, false); | 221 appendAttributeValue(result, resolvedURLString, false); |
| 222 result.append(quoteChar); | 222 result.append(quoteChar); |
| 223 } | 223 } |
| 224 | 224 |
| 225 bool MarkupAccumulator::shouldAddNamespaceElement(const Element* element) | 225 bool MarkupAccumulator::shouldAddNamespaceElement(const Element& element) |
| 226 { | 226 { |
| 227 // Don't add namespace attribute if it is already defined for this elem. | 227 // Don't add namespace attribute if it is already defined for this elem. |
| 228 const AtomicString& prefix = element->prefix(); | 228 const AtomicString& prefix = element.prefix(); |
| 229 if (prefix.isEmpty()) | 229 if (prefix.isEmpty()) |
| 230 return !element->hasAttribute(xmlnsAtom); | 230 return !element.hasAttribute(xmlnsAtom); |
| 231 | 231 |
| 232 DEFINE_STATIC_LOCAL(String, xmlnsWithColon, ("xmlns:")); | 232 DEFINE_STATIC_LOCAL(String, xmlnsWithColon, ("xmlns:")); |
| 233 return !element->hasAttribute(xmlnsWithColon + prefix); | 233 return !element.hasAttribute(xmlnsWithColon + prefix); |
| 234 } | 234 } |
| 235 | 235 |
| 236 bool MarkupAccumulator::shouldAddNamespaceAttribute(const Attribute& attribute,
Namespaces& namespaces) | 236 bool MarkupAccumulator::shouldAddNamespaceAttribute(const Attribute& attribute,
Namespaces& namespaces) |
| 237 { | 237 { |
| 238 // Don't add namespace attributes twice | 238 // Don't add namespace attributes twice |
| 239 if (attribute.name() == XMLNSNames::xmlnsAttr) { | 239 if (attribute.name() == XMLNSNames::xmlnsAttr) { |
| 240 namespaces.set(emptyAtom.impl(), attribute.value().impl()); | 240 namespaces.set(emptyAtom.impl(), attribute.value().impl()); |
| 241 return false; | 241 return false; |
| 242 } | 242 } |
| 243 | 243 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 266 result.append(':'); | 266 result.append(':'); |
| 267 result.append(prefix); | 267 result.append(prefix); |
| 268 } | 268 } |
| 269 | 269 |
| 270 result.appendLiteral("=\""); | 270 result.appendLiteral("=\""); |
| 271 appendAttributeValue(result, namespaceURI, false); | 271 appendAttributeValue(result, namespaceURI, false); |
| 272 result.append('"'); | 272 result.append('"'); |
| 273 } | 273 } |
| 274 } | 274 } |
| 275 | 275 |
| 276 EntityMask MarkupAccumulator::entityMaskForText(Text* text) const | 276 EntityMask MarkupAccumulator::entityMaskForText(const Text& text) const |
| 277 { | 277 { |
| 278 if (!text->document().isHTMLDocument()) | 278 if (!text.document().isHTMLDocument()) |
| 279 return EntityMaskInPCDATA; | 279 return EntityMaskInPCDATA; |
| 280 | 280 |
| 281 const QualifiedName* parentName = 0; | 281 const QualifiedName* parentName = 0; |
| 282 if (text->parentElement()) | 282 if (text.parentElement()) |
| 283 parentName = &(text->parentElement())->tagQName(); | 283 parentName = &(text.parentElement())->tagQName(); |
| 284 | 284 |
| 285 if (parentName && (*parentName == scriptTag || *parentName == styleTag || *p
arentName == xmpTag)) | 285 if (parentName && (*parentName == scriptTag || *parentName == styleTag || *p
arentName == xmpTag)) |
| 286 return EntityMaskInCDATA; | 286 return EntityMaskInCDATA; |
| 287 return EntityMaskInHTMLPCDATA; | 287 return EntityMaskInHTMLPCDATA; |
| 288 } | 288 } |
| 289 | 289 |
| 290 void MarkupAccumulator::appendText(StringBuilder& result, Text* text) | 290 void MarkupAccumulator::appendText(StringBuilder& result, Text& text) |
| 291 { | 291 { |
| 292 const String& str = text->data(); | 292 const String& str = text.data(); |
| 293 unsigned length = str.length(); | 293 unsigned length = str.length(); |
| 294 unsigned start = 0; | 294 unsigned start = 0; |
| 295 | 295 |
| 296 if (m_range) { | 296 if (m_range) { |
| 297 if (text == m_range->endContainer()) | 297 if (text == m_range->endContainer()) |
| 298 length = m_range->endOffset(); | 298 length = m_range->endOffset(); |
| 299 if (text == m_range->startContainer()) { | 299 if (text == m_range->startContainer()) { |
| 300 start = m_range->startOffset(); | 300 start = m_range->startOffset(); |
| 301 length -= start; | 301 length -= start; |
| 302 } | 302 } |
| 303 } | 303 } |
| 304 appendCharactersReplacingEntities(result, str, start, length, entityMaskForT
ext(text)); | 304 appendCharactersReplacingEntities(result, str, start, length, entityMaskForT
ext(text)); |
| 305 } | 305 } |
| 306 | 306 |
| 307 void MarkupAccumulator::appendComment(StringBuilder& result, const String& comme
nt) | 307 void MarkupAccumulator::appendComment(StringBuilder& result, const String& comme
nt) |
| 308 { | 308 { |
| 309 // FIXME: Comment content is not escaped, but XMLSerializer (and possibly ot
her callers) should raise an exception if it includes "-->". | 309 // FIXME: Comment content is not escaped, but XMLSerializer (and possibly ot
her callers) should raise an exception if it includes "-->". |
| 310 result.appendLiteral("<!--"); | 310 result.appendLiteral("<!--"); |
| 311 result.append(comment); | 311 result.append(comment); |
| 312 result.appendLiteral("-->"); | 312 result.appendLiteral("-->"); |
| 313 } | 313 } |
| 314 | 314 |
| 315 void MarkupAccumulator::appendXMLDeclaration(StringBuilder& result, const Docume
nt* document) | 315 void MarkupAccumulator::appendXMLDeclaration(StringBuilder& result, const Docume
nt& document) |
| 316 { | 316 { |
| 317 if (!document->hasXMLDeclaration()) | 317 if (!document.hasXMLDeclaration()) |
| 318 return; | 318 return; |
| 319 | 319 |
| 320 result.appendLiteral("<?xml version=\""); | 320 result.appendLiteral("<?xml version=\""); |
| 321 result.append(document->xmlVersion()); | 321 result.append(document.xmlVersion()); |
| 322 const String& encoding = document->xmlEncoding(); | 322 const String& encoding = document.xmlEncoding(); |
| 323 if (!encoding.isEmpty()) { | 323 if (!encoding.isEmpty()) { |
| 324 result.appendLiteral("\" encoding=\""); | 324 result.appendLiteral("\" encoding=\""); |
| 325 result.append(encoding); | 325 result.append(encoding); |
| 326 } | 326 } |
| 327 if (document->xmlStandaloneStatus() != Document::StandaloneUnspecified) { | 327 if (document.xmlStandaloneStatus() != Document::StandaloneUnspecified) { |
| 328 result.appendLiteral("\" standalone=\""); | 328 result.appendLiteral("\" standalone=\""); |
| 329 if (document->xmlStandalone()) | 329 if (document.xmlStandalone()) |
| 330 result.appendLiteral("yes"); | 330 result.appendLiteral("yes"); |
| 331 else | 331 else |
| 332 result.appendLiteral("no"); | 332 result.appendLiteral("no"); |
| 333 } | 333 } |
| 334 | 334 |
| 335 result.appendLiteral("\"?>"); | 335 result.appendLiteral("\"?>"); |
| 336 } | 336 } |
| 337 | 337 |
| 338 void MarkupAccumulator::appendDocumentType(StringBuilder& result, const Document
Type* n) | 338 void MarkupAccumulator::appendDocumentType(StringBuilder& result, const Document
Type& n) |
| 339 { | 339 { |
| 340 if (n->name().isEmpty()) | 340 if (n.name().isEmpty()) |
| 341 return; | 341 return; |
| 342 | 342 |
| 343 result.appendLiteral("<!DOCTYPE "); | 343 result.appendLiteral("<!DOCTYPE "); |
| 344 result.append(n->name()); | 344 result.append(n.name()); |
| 345 if (!n->publicId().isEmpty()) { | 345 if (!n.publicId().isEmpty()) { |
| 346 result.appendLiteral(" PUBLIC \""); | 346 result.appendLiteral(" PUBLIC \""); |
| 347 result.append(n->publicId()); | 347 result.append(n.publicId()); |
| 348 result.append('"'); | 348 result.append('"'); |
| 349 if (!n->systemId().isEmpty()) { | 349 if (!n.systemId().isEmpty()) { |
| 350 result.appendLiteral(" \""); | 350 result.appendLiteral(" \""); |
| 351 result.append(n->systemId()); | 351 result.append(n.systemId()); |
| 352 result.append('"'); | 352 result.append('"'); |
| 353 } | 353 } |
| 354 } else if (!n->systemId().isEmpty()) { | 354 } else if (!n.systemId().isEmpty()) { |
| 355 result.appendLiteral(" SYSTEM \""); | 355 result.appendLiteral(" SYSTEM \""); |
| 356 result.append(n->systemId()); | 356 result.append(n.systemId()); |
| 357 result.append('"'); | 357 result.append('"'); |
| 358 } | 358 } |
| 359 if (!n->internalSubset().isEmpty()) { | 359 if (!n.internalSubset().isEmpty()) { |
| 360 result.appendLiteral(" ["); | 360 result.appendLiteral(" ["); |
| 361 result.append(n->internalSubset()); | 361 result.append(n.internalSubset()); |
| 362 result.append(']'); | 362 result.append(']'); |
| 363 } | 363 } |
| 364 result.append('>'); | 364 result.append('>'); |
| 365 } | 365 } |
| 366 | 366 |
| 367 void MarkupAccumulator::appendProcessingInstruction(StringBuilder& result, const
String& target, const String& data) | 367 void MarkupAccumulator::appendProcessingInstruction(StringBuilder& result, const
String& target, const String& data) |
| 368 { | 368 { |
| 369 // FIXME: PI data is not escaped, but XMLSerializer (and possibly other call
ers) this should raise an exception if it includes "?>". | 369 // FIXME: PI data is not escaped, but XMLSerializer (and possibly other call
ers) this should raise an exception if it includes "?>". |
| 370 result.appendLiteral("<?"); | 370 result.appendLiteral("<?"); |
| 371 result.append(target); | 371 result.append(target); |
| 372 result.append(' '); | 372 result.append(' '); |
| 373 result.append(data); | 373 result.append(data); |
| 374 result.appendLiteral("?>"); | 374 result.appendLiteral("?>"); |
| 375 } | 375 } |
| 376 | 376 |
| 377 void MarkupAccumulator::appendElement(StringBuilder& result, Element* element, N
amespaces* namespaces) | 377 void MarkupAccumulator::appendElement(StringBuilder& result, Element& element, N
amespaces* namespaces) |
| 378 { | 378 { |
| 379 appendOpenTag(result, element, namespaces); | 379 appendOpenTag(result, element, namespaces); |
| 380 | 380 |
| 381 if (element->hasAttributes()) { | 381 if (element.hasAttributes()) { |
| 382 unsigned length = element->attributeCount(); | 382 unsigned length = element.attributeCount(); |
| 383 for (unsigned int i = 0; i < length; i++) | 383 for (unsigned int i = 0; i < length; i++) |
| 384 appendAttribute(result, element, *element->attributeItem(i), namespa
ces); | 384 appendAttribute(result, element, *element.attributeItem(i), namespac
es); |
| 385 } | 385 } |
| 386 | 386 |
| 387 // Give an opportunity to subclasses to add their own attributes. | 387 // Give an opportunity to subclasses to add their own attributes. |
| 388 appendCustomAttributes(result, element, namespaces); | 388 appendCustomAttributes(result, element, namespaces); |
| 389 | 389 |
| 390 appendCloseTag(result, element); | 390 appendCloseTag(result, element); |
| 391 } | 391 } |
| 392 | 392 |
| 393 void MarkupAccumulator::appendOpenTag(StringBuilder& result, Element* element, N
amespaces* namespaces) | 393 void MarkupAccumulator::appendOpenTag(StringBuilder& result, const Element& elem
ent, Namespaces* namespaces) |
| 394 { | 394 { |
| 395 result.append('<'); | 395 result.append('<'); |
| 396 result.append(element->nodeNamePreservingCase()); | 396 result.append(element.nodeNamePreservingCase()); |
| 397 if (!element->document().isHTMLDocument() && namespaces && shouldAddNamespac
eElement(element)) | 397 if (!element.document().isHTMLDocument() && namespaces && shouldAddNamespace
Element(element)) |
| 398 appendNamespace(result, element->prefix(), element->namespaceURI(), *nam
espaces); | 398 appendNamespace(result, element.prefix(), element.namespaceURI(), *names
paces); |
| 399 } | 399 } |
| 400 | 400 |
| 401 void MarkupAccumulator::appendCloseTag(StringBuilder& result, Element* element) | 401 void MarkupAccumulator::appendCloseTag(StringBuilder& result, const Element& ele
ment) |
| 402 { | 402 { |
| 403 if (shouldSelfClose(element)) { | 403 if (shouldSelfClose(element)) { |
| 404 if (element->isHTMLElement()) | 404 if (element.isHTMLElement()) |
| 405 result.append(' '); // XHTML 1.0 <-> HTML compatibility. | 405 result.append(' '); // XHTML 1.0 <-> HTML compatibility. |
| 406 result.append('/'); | 406 result.append('/'); |
| 407 } | 407 } |
| 408 result.append('>'); | 408 result.append('>'); |
| 409 } | 409 } |
| 410 | 410 |
| 411 static inline bool attributeIsInSerializedNamespace(const Attribute& attribute) | 411 static inline bool attributeIsInSerializedNamespace(const Attribute& attribute) |
| 412 { | 412 { |
| 413 return attribute.namespaceURI() == XMLNames::xmlNamespaceURI | 413 return attribute.namespaceURI() == XMLNames::xmlNamespaceURI |
| 414 || attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI | 414 || attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI |
| 415 || attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI; | 415 || attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI; |
| 416 } | 416 } |
| 417 | 417 |
| 418 void MarkupAccumulator::appendAttribute(StringBuilder& result, Element* element,
const Attribute& attribute, Namespaces* namespaces) | 418 void MarkupAccumulator::appendAttribute(StringBuilder& result, const Element& el
ement, const Attribute& attribute, Namespaces* namespaces) |
| 419 { | 419 { |
| 420 bool documentIsHTML = element->document().isHTMLDocument(); | 420 bool documentIsHTML = element.document().isHTMLDocument(); |
| 421 | 421 |
| 422 result.append(' '); | 422 result.append(' '); |
| 423 | 423 |
| 424 if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) | 424 if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) |
| 425 result.append(attribute.name().localName()); | 425 result.append(attribute.name().localName()); |
| 426 else { | 426 else { |
| 427 QualifiedName prefixedName = attribute.name(); | 427 QualifiedName prefixedName = attribute.name(); |
| 428 if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) { | 428 if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) { |
| 429 if (!attribute.prefix()) | 429 if (!attribute.prefix()) |
| 430 prefixedName.setPrefix(xlinkAtom); | 430 prefixedName.setPrefix(xlinkAtom); |
| 431 } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) { | 431 } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) { |
| 432 if (!attribute.prefix()) | 432 if (!attribute.prefix()) |
| 433 prefixedName.setPrefix(xmlAtom); | 433 prefixedName.setPrefix(xmlAtom); |
| 434 } else if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) { | 434 } else if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) { |
| 435 if (attribute.name() != XMLNSNames::xmlnsAttr && !attribute.prefix()
) | 435 if (attribute.name() != XMLNSNames::xmlnsAttr && !attribute.prefix()
) |
| 436 prefixedName.setPrefix(xmlnsAtom); | 436 prefixedName.setPrefix(xmlnsAtom); |
| 437 } | 437 } |
| 438 result.append(prefixedName.toString()); | 438 result.append(prefixedName.toString()); |
| 439 } | 439 } |
| 440 | 440 |
| 441 result.append('='); | 441 result.append('='); |
| 442 | 442 |
| 443 if (element->isURLAttribute(attribute)) | 443 if (element.isURLAttribute(attribute)) |
| 444 appendQuotedURLAttributeValue(result, element, attribute); | 444 appendQuotedURLAttributeValue(result, element, attribute); |
| 445 else { | 445 else { |
| 446 result.append('"'); | 446 result.append('"'); |
| 447 appendAttributeValue(result, attribute.value(), documentIsHTML); | 447 appendAttributeValue(result, attribute.value(), documentIsHTML); |
| 448 result.append('"'); | 448 result.append('"'); |
| 449 } | 449 } |
| 450 | 450 |
| 451 if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute,
*namespaces)) | 451 if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute,
*namespaces)) |
| 452 appendNamespace(result, attribute.prefix(), attribute.namespaceURI(), *n
amespaces); | 452 appendNamespace(result, attribute.prefix(), attribute.namespaceURI(), *n
amespaces); |
| 453 } | 453 } |
| 454 | 454 |
| 455 void MarkupAccumulator::appendCDATASection(StringBuilder& result, const String&
section) | 455 void MarkupAccumulator::appendCDATASection(StringBuilder& result, const String&
section) |
| 456 { | 456 { |
| 457 // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly othe
r callers) should raise an exception if it includes "]]>". | 457 // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly othe
r callers) should raise an exception if it includes "]]>". |
| 458 result.appendLiteral("<![CDATA["); | 458 result.appendLiteral("<![CDATA["); |
| 459 result.append(section); | 459 result.append(section); |
| 460 result.appendLiteral("]]>"); | 460 result.appendLiteral("]]>"); |
| 461 } | 461 } |
| 462 | 462 |
| 463 void MarkupAccumulator::appendStartMarkup(StringBuilder& result, const Node* nod
e, Namespaces* namespaces) | 463 void MarkupAccumulator::appendStartMarkup(StringBuilder& result, Node& node, Nam
espaces* namespaces) |
| 464 { | 464 { |
| 465 switch (node->nodeType()) { | 465 switch (node.nodeType()) { |
| 466 case Node::TEXT_NODE: | 466 case Node::TEXT_NODE: |
| 467 appendText(result, toText(const_cast<Node*>(node))); | 467 appendText(result, toText(node)); |
| 468 break; | 468 break; |
| 469 case Node::COMMENT_NODE: | 469 case Node::COMMENT_NODE: |
| 470 appendComment(result, toComment(node)->data()); | 470 appendComment(result, toComment(node).data()); |
| 471 break; | 471 break; |
| 472 case Node::DOCUMENT_NODE: | 472 case Node::DOCUMENT_NODE: |
| 473 appendXMLDeclaration(result, toDocument(node)); | 473 appendXMLDeclaration(result, toDocument(node)); |
| 474 break; | 474 break; |
| 475 case Node::DOCUMENT_FRAGMENT_NODE: | 475 case Node::DOCUMENT_FRAGMENT_NODE: |
| 476 break; | 476 break; |
| 477 case Node::DOCUMENT_TYPE_NODE: | 477 case Node::DOCUMENT_TYPE_NODE: |
| 478 appendDocumentType(result, toDocumentType(node)); | 478 appendDocumentType(result, toDocumentType(node)); |
| 479 break; | 479 break; |
| 480 case Node::PROCESSING_INSTRUCTION_NODE: | 480 case Node::PROCESSING_INSTRUCTION_NODE: |
| 481 appendProcessingInstruction(result, toProcessingInstruction(node)->targe
t(), toProcessingInstruction(node)->data()); | 481 appendProcessingInstruction(result, toProcessingInstruction(node).target
(), toProcessingInstruction(node).data()); |
| 482 break; | 482 break; |
| 483 case Node::ELEMENT_NODE: | 483 case Node::ELEMENT_NODE: |
| 484 appendElement(result, toElement(const_cast<Node*>(node)), namespaces); | 484 appendElement(result, toElement(node), namespaces); |
| 485 break; | 485 break; |
| 486 case Node::CDATA_SECTION_NODE: | 486 case Node::CDATA_SECTION_NODE: |
| 487 appendCDATASection(result, toCDATASection(node)->data()); | 487 appendCDATASection(result, toCDATASection(node).data()); |
| 488 break; | 488 break; |
| 489 case Node::ATTRIBUTE_NODE: | 489 case Node::ATTRIBUTE_NODE: |
| 490 ASSERT_NOT_REACHED(); | 490 ASSERT_NOT_REACHED(); |
| 491 break; | 491 break; |
| 492 } | 492 } |
| 493 } | 493 } |
| 494 | 494 |
| 495 // Rules of self-closure | 495 // Rules of self-closure |
| 496 // 1. No elements in HTML documents use the self-closing syntax. | 496 // 1. No elements in HTML documents use the self-closing syntax. |
| 497 // 2. Elements w/ children never self-close because they use a separate end tag. | 497 // 2. Elements w/ children never self-close because they use a separate end tag. |
| 498 // 3. HTML elements which do not have a "forbidden" end tag will close with a se
parate end tag. | 498 // 3. HTML elements which do not have a "forbidden" end tag will close with a se
parate end tag. |
| 499 // 4. Other elements self-close. | 499 // 4. Other elements self-close. |
| 500 bool MarkupAccumulator::shouldSelfClose(const Node* node) | 500 bool MarkupAccumulator::shouldSelfClose(const Node& node) |
| 501 { | 501 { |
| 502 if (node->document().isHTMLDocument()) | 502 if (node.document().isHTMLDocument()) |
| 503 return false; | 503 return false; |
| 504 if (node->hasChildNodes()) | 504 if (node.hasChildNodes()) |
| 505 return false; | 505 return false; |
| 506 if (node->isHTMLElement() && !elementCannotHaveEndTag(node)) | 506 if (node.isHTMLElement() && !elementCannotHaveEndTag(node)) |
| 507 return false; | 507 return false; |
| 508 return true; | 508 return true; |
| 509 } | 509 } |
| 510 | 510 |
| 511 bool MarkupAccumulator::elementCannotHaveEndTag(const Node* node) | 511 bool MarkupAccumulator::elementCannotHaveEndTag(const Node& node) |
| 512 { | 512 { |
| 513 if (!node->isHTMLElement()) | 513 if (!node.isHTMLElement()) |
| 514 return false; | 514 return false; |
| 515 | 515 |
| 516 // FIXME: ieForbidsInsertHTML may not be the right function to call here | 516 // FIXME: ieForbidsInsertHTML may not be the right function to call here |
| 517 // ieForbidsInsertHTML is used to disallow setting innerHTML/outerHTML | 517 // ieForbidsInsertHTML is used to disallow setting innerHTML/outerHTML |
| 518 // or createContextualFragment. It does not necessarily align with | 518 // or createContextualFragment. It does not necessarily align with |
| 519 // which elements should be serialized w/o end tags. | 519 // which elements should be serialized w/o end tags. |
| 520 return toHTMLElement(node)->ieForbidsInsertHTML(); | 520 return toHTMLElement(node).ieForbidsInsertHTML(); |
| 521 } | 521 } |
| 522 | 522 |
| 523 void MarkupAccumulator::appendEndMarkup(StringBuilder& result, const Node* node) | 523 void MarkupAccumulator::appendEndMarkup(StringBuilder& result, const Node& node) |
| 524 { | 524 { |
| 525 if (!node->isElementNode() || shouldSelfClose(node) || (!node->hasChildNodes
() && elementCannotHaveEndTag(node))) | 525 if (!node.isElementNode() || shouldSelfClose(node) || (!node.hasChildNodes()
&& elementCannotHaveEndTag(node))) |
| 526 return; | 526 return; |
| 527 | 527 |
| 528 result.appendLiteral("</"); | 528 result.appendLiteral("</"); |
| 529 result.append(toElement(node)->nodeNamePreservingCase()); | 529 result.append(toElement(node).nodeNamePreservingCase()); |
| 530 result.append('>'); | 530 result.append('>'); |
| 531 } | 531 } |
| 532 | 532 |
| 533 } | 533 } |
| OLD | NEW |