diff options
-rw-r--r-- | beautifulsoup/element.py | 51 | ||||
-rw-r--r-- | tests/test_tree.py | 8 |
2 files changed, 18 insertions, 41 deletions
diff --git a/beautifulsoup/element.py b/beautifulsoup/element.py index d37124f..6af27a8 100644 --- a/beautifulsoup/element.py +++ b/beautifulsoup/element.py @@ -420,19 +420,14 @@ class Tag(PageElement): self.parserClass = parser.__class__ self.name = name if attrs == None: - attrs = [] - if isinstance(attrs, types.DictType): - self.attrMap = attrs + attrs = {} + else: + attrs = dict(attrs) self.attrs = attrs self.contents = [] self.setup(parent, previous) self.hidden = False - if isinstance(attrs, types.DictType): - self.attrs = [kv for kv in attrs.items()] - else: - self.attrs = list(attrs) - # Set up any substitutions, such as the charset in a META tag. self.contains_substitutions = builder.set_up_substitutions(self) @@ -478,15 +473,15 @@ class Tag(PageElement): """Returns the value of the 'key' attribute for the tag, or the value given for 'default' if it doesn't have that attribute.""" - return self._getAttrMap().get(key, default) + return self.attrs.get(key, default) def has_key(self, key): - return self._getAttrMap().has_key(key) + return self.attrs.has_key(key) def __getitem__(self, key): """tag[key] returns the value of the 'key' attribute for the tag, and throws an exception if it's not there.""" - return self._getAttrMap()[key] + return self.attrs[key] def __iter__(self): "Iterating over a tag iterates over its contents." @@ -506,27 +501,12 @@ class Tag(PageElement): def __setitem__(self, key, value): """Setting tag[key] sets the value of the 'key' attribute for the tag.""" - self._getAttrMap() - self.attrMap[key] = value - found = False - for i in range(0, len(self.attrs)): - if self.attrs[i][0] == key: - self.attrs[i] = (key, value) - found = True - if not found: - self.attrs.append((key, value)) - self._getAttrMap()[key] = value + self.attrs[key] = value def __delitem__(self, key): "Deleting tag[key] deletes all 'key' attributes for the tag." - for item in self.attrs: - if item[0] == key: - self.attrs.remove(item) - #We don't break because bad HTML can define the same - #attribute multiple times. - self._getAttrMap() - if self.attrMap.has_key(key): - del self.attrMap[key] + if self.attrs.has_key(key): + del self.attrs[key] def __call__(self, *args, **kwargs): """Calling a tag like a function is the same as calling its @@ -589,7 +569,7 @@ class Tag(PageElement): """ attrs = [] if self.attrs: - for key, val in self.attrs: + for key, val in sorted(self.attrs.items()): if val is None: decoded = key else: @@ -718,17 +698,6 @@ class Tag(PageElement): findAll = find_all # BS3 findChildren = find_all # BS2 - #Private methods - - def _getAttrMap(self): - """Initializes a map representation of this tag's attributes, - if not already initialized.""" - if not getattr(self, 'attrMap'): - self.attrMap = {} - for (key, value) in self.attrs: - self.attrMap[key] = value - return self.attrMap - #Generator methods @property def children(self): diff --git a/tests/test_tree.py b/tests/test_tree.py index f9163f1..ea10367 100644 --- a/tests/test_tree.py +++ b/tests/test_tree.py @@ -741,6 +741,14 @@ class TestElementObjects(SoupTest): self.assertTrue(soup.foo.has_key('attr')) self.assertFalse(soup.foo.has_key('attr2')) + def test_attributes_come_out_in_alphabetical_order(self): + markup = '<b a="1" z="5" m="3" f="2" y="4"></b>' + self.assertSoupEquals(markup, '<b a="1" f="2" m="3" y="4" z="5"></b>') + + def test_multiple_values_for_the_same_attribute_are_collapsed(self): + markup = '<b b="20" a="1" b="10" a="2" a="3" a="4"></b>' + self.assertSoupEquals(markup, '<b a="1" b="20"></b>') + def test_string(self): # A tag that contains only a text node makes that node # available as .string. |