Skip to content

Commit

Permalink
Merge pull request #231 from petersen/fix-namespace-prefix-collisions
Browse files Browse the repository at this point in the history
fix namespace prefix collisions
  • Loading branch information
mvz committed May 1, 2024
2 parents 01eb1db + e790d94 commit 7a2374f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/happymapper/class_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ def parse(xml, options = {})
node = xml.root

# merge any namespaces found on the xml node into the namespace hash
namespaces = namespaces.merge(xml.collect_namespaces)
namespaces = namespaces.merge(xml.collect_namespaces).merge(node.namespaces)

# if the node name is equal to the tag name then the we are parsing the
# root element and that is important to record so that we can apply
Expand Down
42 changes: 42 additions & 0 deletions spec/features/mixed_namespaces_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ class Address
has_one :postcode, String, namespace: "different"
has_one :city, String, namespace: nil
end

class RootCollision
include HappyMapper

register_namespace "xmlns", "http://www.unicornland.com/prefix"

tag :address

has_many :streets, String, tag: "street"
end
end

RSpec.describe "A document with mixed namespaces" do
Expand Down Expand Up @@ -59,4 +69,36 @@ class Address
it "city" do
expect(address.city).to eq "Oldenburg"
end

describe "and xmlns prefix collisions" do
# Nokogiri calls out a potential problem with Nokogiri::Document.collect_namespaces
# if the XML document has duplicate prefixes with different namespaces.
# This document triggers the problem - the `xmlns` namespace will be overwritten
# with the `http://override.com/breaks` value, so the root node won't be found.
# The failure manifests as `nil` being returned from .parse.
let(:collision_document) do
<<~XML
<?xml version="1.0" encoding="UTF-8"?>
<address location='home' xmlns="http://www.unicornland.com/prefix"
xmlns:override="http://override.com/breaks">
<street>Milchstrasse</street>
<street>Another Street</street>
<housenumber xmlns="http://override.com/breaks">23</housenumber>
<housenumber xmlns="http://override.com/breaks">55</housenumber>
<housenumber xmlns="http://override.com/breaks">88</housenumber>
<different:postcode>26131</different:postcode>
<different:city>Oldenburg</different:city>
<housenumber xmlns="http://override.com/breaks">99</housenumber>
</address>
XML
end

let(:root_collision) do
MixedNamespaces::RootCollision.parse(collision_document)
end

it "has the correct streets" do
expect(root_collision.streets).to eq ["Milchstrasse", "Another Street"]
end
end
end

0 comments on commit 7a2374f

Please sign in to comment.