void NamedNodeMap::setAttributes(const NamedNodeMap& other) { // clone all attributes in the other map, but attach to our element if (!m_element) return; // If assigning the map changes the id attribute, we need to call // updateId. Attribute* oldId = getAttributeItem(m_element->document()->idAttributeName()); Attribute* newId = other.getAttributeItem(m_element->document()->idAttributeName()); if (oldId || newId) m_element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom); Attribute* oldName = getAttributeItem(HTMLNames::nameAttr); Attribute* newName = other.getAttributeItem(HTMLNames::nameAttr); if (oldName || newName) m_element->updateName(oldName ? oldName->value() : nullAtom, newName ? newName->value() : nullAtom); clearAttributes(); unsigned newLength = other.length(); m_attributes.resize(newLength); for (unsigned i = 0; i < newLength; i++) m_attributes[i] = other.m_attributes[i]->clone(); // FIXME: This is wasteful. The class list could be preserved on a copy, and we // wouldn't have to waste time reparsing the attribute. // The derived class, HTMLNamedNodeMap, which manages a parsed class list for the CLASS attribute, // will update its member variable when parse attribute is called. for (unsigned i = 0; i < newLength; i++) m_element->attributeChanged(m_attributes[i].get(), true); }
Value FunLang::evaluate() const { String lang = arg(0)->evaluate().toString(); Attribute* languageAttribute = 0; Node* node = evaluationContext().node.get(); while (node) { NamedNodeMap* attrs = node->attributes(); if (attrs) languageAttribute = attrs->getAttributeItem(XMLNames::langAttr); if (languageAttribute) break; node = node->parentNode(); } if (!languageAttribute) return BOOL_TO_VALUE_CAST false; String langValue = languageAttribute->value(); while (true) { if (equalIgnoringCase(langValue, lang)) return BOOL_TO_VALUE_CAST true; // Remove suffixes one by one. size_t index = langValue.reverseFind('-'); if (index == notFound) break; langValue = langValue.left(index); } return BOOL_TO_VALUE_CAST false; }
bool areIdenticalElements(const Node* first, const Node* second) { // check that tag name and all attribute names and values are identical if (!first->isElementNode() || !second->isElementNode()) return false; if (!toElement(first)->tagQName().matches(toElement(second)->tagQName())) return false; NamedNodeMap* firstMap = toElement(first)->attributes(); NamedNodeMap* secondMap = toElement(second)->attributes(); unsigned firstLength = firstMap->length(); if (firstLength != secondMap->length()) return false; for (unsigned i = 0; i < firstLength; i++) { Attribute* attribute = firstMap->attributeItem(i); Attribute* secondAttribute = secondMap->getAttributeItem(attribute->name()); if (!secondAttribute || attribute->value() != secondAttribute->value()) return false; } return true; }
void HTMLConstructionSite::mergeAttributesFromTokenIntoElement(AtomicHTMLToken& token, Element* element) { if (!token.attributes()) return; NamedNodeMap* attributes = element->attributes(false); for (unsigned i = 0; i < token.attributes()->length(); ++i) { Attribute* attribute = token.attributes()->attributeItem(i); if (!attributes->getAttributeItem(attribute->name())) element->setAttribute(attribute->name(), attribute->value()); } }