mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-20 08:18:55 +00:00
LibWeb+LibXML: Preserve element attribute order in XML documents
We now use OrderedHashMap instead of HashMap to ensure that attributes on XML elements retain their original order.
This commit is contained in:
parent
da88db04cf
commit
b7595013c1
Notes:
github-actions[bot]
2025-08-22 09:37:04 +00:00
Author: https://github.com/awesomekling
Commit: b7595013c1
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5944
7 changed files with 22 additions and 6 deletions
|
@ -92,7 +92,7 @@ void XMLDocumentBuilder::set_doctype(XML::Doctype doctype)
|
||||||
m_document->insert_before(document_type, m_document->first_child(), false);
|
m_document->insert_before(document_type, m_document->first_child(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XMLDocumentBuilder::element_start(const XML::Name& name, HashMap<XML::Name, ByteString> const& attributes)
|
void XMLDocumentBuilder::element_start(const XML::Name& name, OrderedHashMap<XML::Name, ByteString> const& attributes)
|
||||||
{
|
{
|
||||||
if (m_has_error)
|
if (m_has_error)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
private:
|
private:
|
||||||
virtual void set_source(ByteString) override;
|
virtual void set_source(ByteString) override;
|
||||||
virtual void set_doctype(XML::Doctype) override;
|
virtual void set_doctype(XML::Doctype) override;
|
||||||
virtual void element_start(XML::Name const& name, HashMap<XML::Name, ByteString> const& attributes) override;
|
virtual void element_start(XML::Name const& name, OrderedHashMap<XML::Name, ByteString> const& attributes) override;
|
||||||
virtual void element_end(XML::Name const& name) override;
|
virtual void element_end(XML::Name const& name) override;
|
||||||
virtual void text(StringView data) override;
|
virtual void text(StringView data) override;
|
||||||
virtual void comment(StringView data) override;
|
virtual void comment(StringView data) override;
|
||||||
|
|
|
@ -29,7 +29,7 @@ struct Node {
|
||||||
};
|
};
|
||||||
struct Element {
|
struct Element {
|
||||||
Name name;
|
Name name;
|
||||||
HashMap<Name, ByteString> attributes;
|
OrderedHashMap<Name, ByteString> attributes;
|
||||||
Vector<NonnullOwnPtr<Node>> children;
|
Vector<NonnullOwnPtr<Node>> children;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -700,7 +700,7 @@ ErrorOr<NonnullOwnPtr<Node>, ParseError> Parser::parse_empty_element_tag()
|
||||||
TRY(expect("<"sv));
|
TRY(expect("<"sv));
|
||||||
|
|
||||||
auto name = TRY(parse_name());
|
auto name = TRY(parse_name());
|
||||||
HashMap<Name, ByteString> attributes;
|
OrderedHashMap<Name, ByteString> attributes;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (auto result = skip_whitespace(Required::Yes); result.is_error())
|
if (auto result = skip_whitespace(Required::Yes); result.is_error())
|
||||||
|
@ -854,7 +854,7 @@ ErrorOr<NonnullOwnPtr<Node>, ParseError> Parser::parse_start_tag()
|
||||||
auto accept = accept_rule();
|
auto accept = accept_rule();
|
||||||
|
|
||||||
auto name = TRY(parse_name());
|
auto name = TRY(parse_name());
|
||||||
HashMap<Name, ByteString> attributes;
|
OrderedHashMap<Name, ByteString> attributes;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (auto result = skip_whitespace(Required::Yes); result.is_error())
|
if (auto result = skip_whitespace(Required::Yes); result.is_error())
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct Listener {
|
||||||
virtual void set_doctype(XML::Doctype) { }
|
virtual void set_doctype(XML::Doctype) { }
|
||||||
virtual void document_start() { }
|
virtual void document_start() { }
|
||||||
virtual void document_end() { }
|
virtual void document_end() { }
|
||||||
virtual void element_start(Name const&, HashMap<Name, ByteString> const&) { }
|
virtual void element_start(Name const&, OrderedHashMap<Name, ByteString> const&) { }
|
||||||
virtual void element_end(Name const&) { }
|
virtual void element_end(Name const&) { }
|
||||||
virtual void text(StringView) { }
|
virtual void text(StringView) { }
|
||||||
virtual void cdata_section(StringView) { }
|
virtual void cdata_section(StringView) { }
|
||||||
|
|
5
Tests/LibWeb/Text/expected/XML/attribute-order.txt
Normal file
5
Tests/LibWeb/Text/expected/XML/attribute-order.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
e
|
11
Tests/LibWeb/Text/input/XML/attribute-order.html
Normal file
11
Tests/LibWeb/Text/input/XML/attribute-order.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!doctype html>
|
||||||
|
<script src="../include.js"></script>
|
||||||
|
<script>
|
||||||
|
test(() => {
|
||||||
|
const doc = new DOMParser().parseFromString(`<xml><foo a='1' b='2' c='3' d='4' e='5'/></xml>`, "application/xml");
|
||||||
|
const e = doc.firstChild.firstChild;
|
||||||
|
for (const a of e.attributes) {
|
||||||
|
println(a.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue