Skip to content

Commit

Permalink
Rework namespaces to work for namespaces declared inline.
Browse files Browse the repository at this point in the history
This changes how namespaces are declared from previous versions. Instead of declaring the namespace prefix in the mapping, you must declare the namespace URL.

  class Foo
    include HappyMapper
    namespace http://example.com/v2
  end
  • Loading branch information
bkeepers committed Jul 15, 2009
1 parent 3c7e930 commit 374850a
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 55 deletions.
19 changes: 4 additions & 15 deletions lib/happymapper.rb
Expand Up @@ -66,9 +66,6 @@ def tag_name
end

def parse(xml, options = {})
# locally scoped copy of namespace for this parse run
namespace = @namespace

if xml.is_a?(XML::Node)
node = xml
else
Expand All @@ -81,22 +78,14 @@ def parse(xml, options = {})
root = node.name == tag_name
end

# This is the entry point into the parsing pipeline, so the default
# namespace prefix registered here will propagate down
namespaces = node.namespaces
if namespaces && namespaces.default
already_assigned = namespaces.definitions.detect do |defn|
namespaces.default && namespaces.default.href == defn.href && defn.prefix
end
namespaces.default_prefix = DEFAULT_NS unless already_assigned
namespace ||= DEFAULT_NS
end
namespace = @namespace || (node.namespaces && node.namespaces.default)
namespace = "#{DEFAULT_NS}:#{namespace}" if namespace

xpath = root ? '/' : './/'
xpath += "#{namespace}:" if namespace
xpath += "#{DEFAULT_NS}:" if namespace
xpath += tag_name

nodes = node.find(xpath)
nodes = node.find(xpath, Array(namespace))
collection = nodes.collect do |n|
obj = new

Expand Down
13 changes: 6 additions & 7 deletions lib/happymapper/item.rb
Expand Up @@ -59,7 +59,7 @@ def from_xml_node(node, namespace)
def xpath(namespace = self.namespace)
xpath = ''
xpath += './/' if options[:deep]
xpath += "#{namespace}:" if namespace
xpath += "#{DEFAULT_NS}:" if namespace
xpath += tag
# puts "xpath: #{xpath}"
xpath
Expand Down Expand Up @@ -129,16 +129,15 @@ def constantize(type)

def find(node, namespace, &block)
# this node has a custom namespace (that is present in the doc)
if self.namespace && node.namespaces.find_by_prefix(self.namespace)
# from the class definition
namespace = self.namespace
elsif options[:namespace] && node.namespaces.find_by_prefix(options[:namespace])
if self.namespace
namespace = "#{DEFAULT_NS}:#{self.namespace}"
elsif options[:namespace]
# from an element definition
namespace = options[:namespace]
namespace = "#{DEFAULT_NS}:#{options[:namespace]}"
end

if element?
result = node.find_first(xpath(namespace))
result = node.find_first(xpath(namespace), namespace)
# puts "vfxn: #{xpath} #{result.inspect}"
if result
value = yield(result)
Expand Down
14 changes: 0 additions & 14 deletions spec/fixtures/nested_namespaces.xml
Expand Up @@ -6,22 +6,8 @@
<embeddedXMLContent>
<ns1:alert xmlns:ns1="http://schemas.google.com/analytics/2009">
<ns1:identifier>CDC-2006-183</ns1:identifier>
<ns1:sender>2.16.840.1.114222.4.20.1.1</ns1:sender>
<ns1:sent>2006-11-07T21:25:16.5127Z </ns1:sent>
<ns1:status>Test</ns1:status>
<ns1:msgType>Update</ns1:msgType>
<ns1:references>2.16.840.1.114222.4.20.1.1,CDC-2006-182,2006-11-05T13:02:42.1219Z</ns1:references>
<ns1:scope>Restricted</ns1:scope>
<ns1:info>
<ns1:category>Health</ns1:category>
<ns1:event>HAN</ns1:event>
<ns1:urgency>Expected</ns1:urgency>
<ns1:severity>Severe</ns1:severity>
<ns1:certainty>Very Likely</ns1:certainty>
<ns1:senderName>Centers for Disease Control and Prevention</ns1:senderName>
<ns1:headline>Cases of Vibrio vulnificus identified among Hurrican Katrina evacuees</ns1:headline>
<ns1:description>To date, seven people in the area effected by Hurricane Katrina have been reported ill from the bacterial disease Vibrio vulnificus.</ns1:description>
<ns1:instruction>Please distribute to health providers and officials within your jurisdiction as deemed appropriate</ns1:instruction>
</ns1:info>
</ns1:alert>
</embeddedXMLContent>
Expand Down
4 changes: 2 additions & 2 deletions spec/happymapper_item_spec.rb
Expand Up @@ -65,8 +65,8 @@ class Bar; end

it "should prepend namespace if namespace exists" do
item = HappyMapper::Item.new(:foo, String, :tag => 'foobar')
item.namespace = 'v2'
item.xpath.should == 'v2:foobar'
item.namespace = 'http://example.com'
item.xpath.should == 'happymapper:foobar'
end
end

Expand Down
51 changes: 34 additions & 17 deletions spec/happymapper_spec.rb
Expand Up @@ -7,7 +7,7 @@ class Property
include HappyMapper

tag 'property'
namespace 'dxp'
namespace 'http://schemas.google.com/analytics/2009'
attribute :name, String
attribute :value, String
end
Expand All @@ -19,7 +19,7 @@ class Entry
element :id, String
element :updated, DateTime
element :title, String
element :table_id, String, :namespace => 'dxp', :tag => 'tableId'
element :table_id, String, :namespace => 'http://schemas.google.com/analytics/2009', :tag => 'tableId'
has_many :properties, Property
end

Expand Down Expand Up @@ -84,7 +84,7 @@ class Address
include HappyMapper

tag 'Address'
namespace 'v2'
namespace 'http://fedex.com/ws/track/v2'
element :city, String, :tag => 'City'
element :state, String, :tag => 'StateOrProvinceCode'
element :zip, String, :tag => 'PostalCode'
Expand All @@ -96,7 +96,7 @@ class Event
include HappyMapper

tag 'Events'
namespace 'v2'
namespace 'http://fedex.com/ws/track/v2'
element :timestamp, String, :tag => 'Timestamp'
element :eventtype, String, :tag => 'EventType'
element :eventdescription, String, :tag => 'EventDescription'
Expand All @@ -107,7 +107,7 @@ class PackageWeight
include HappyMapper

tag 'PackageWeight'
namespace 'v2'
namespace 'http://fedex.com/ws/track/v2'
element :units, String, :tag => 'Units'
element :value, Integer, :tag => 'Value'
end
Expand All @@ -116,7 +116,7 @@ class TrackDetails
include HappyMapper

tag 'TrackDetails'
namespace 'v2'
namespace 'http://fedex.com/ws/track/v2'
element :tracking_number, String, :tag => 'TrackingNumber'
element :status_code, String, :tag => 'StatusCode'
element :status_desc, String, :tag => 'StatusDescription'
Expand All @@ -131,7 +131,7 @@ class Notification
include HappyMapper

tag 'Notifications'
namespace 'v2'
namespace 'http://fedex.com/ws/track/v2'
element :severity, String, :tag => 'Severity'
element :source, String, :tag => 'Source'
element :code, Integer, :tag => 'Code'
Expand All @@ -143,15 +143,15 @@ class TransactionDetail
include HappyMapper

tag 'TransactionDetail'
namespace 'v2'
namespace 'http://fedex.com/ws/track/v2'
element :cust_tran_id, String, :tag => 'CustomerTransactionId'
end

class TrackReply
include HappyMapper

tag 'TrackReply'
namespace 'v2'
namespace 'http://fedex.com/ws/track/v2'
element :highest_severity, String, :tag => 'HighestSeverity'
element :more_data, Boolean, :tag => 'MoreData'
has_many :notifications, Notification, :tag => 'Notifications'
Expand Down Expand Up @@ -215,7 +215,7 @@ class CurrentWeather
include HappyMapper

tag 'ob'
namespace 'aws'
namespace 'http://www.aws.com/aws'
element :temperature, Integer, :tag => 'temp'
element :feels_like, Integer, :tag => 'feels-like'
element :current_condition, String, :tag => 'current-condition', :attributes => {:icon => String}
Expand Down Expand Up @@ -243,7 +243,7 @@ class Item
element :asin, String, :tag => 'ASIN'
element :detail_page_url, URI, :tag => 'DetailPageURL', :parser => :parse
element :manufacturer, String, :tag => 'Manufacturer', :deep => true
element :point, String, :tag => 'point', :namespace => 'georss'
element :point, String, :tag => 'point', :namespace => 'http://www.georss.org/georss'
element :product_group, ProductGroup, :tag => 'ProductGroup', :deep => true, :parser => :new, :raw => true
end

Expand Down Expand Up @@ -579,13 +579,20 @@ class Thing
# tree.people.first.id.should == 'KWQS-BBQ'
end

describe '' do
describe 'nested elements with namespaces' do
module Namespaces
class Info
include HappyMapper
namespace 'http://schemas.google.com/analytics/2009'
element :category, String
end

class Alert
include HappyMapper
namespace 'ns1'
namespace 'http://schemas.google.com/analytics/2009'

element :identifier, String
has_one :info, Info
end
class Distribution
include HappyMapper
Expand All @@ -594,11 +601,21 @@ class Distribution
has_one :alert, Alert
end
end

def mapping
@mapping ||= Namespaces::Distribution.parse(fixture_file('nested_namespaces.xml'))
end

it "should parse documents with inline namespace" do
lambda {
Namespaces::Distribution.parse(fixture_file('nested_namespaces.xml'))
}.should_not raise_error
it "should parse elements with inline namespace" do
lambda { mapping }.should_not raise_error
end

it "should map elements with inline namespace" do
mapping.alert.identifier.should == 'CDC-2006-183'
end

it "should map sub elements of with nested namespace" do
mapping.alert.info.category.should == 'Health'
end
end

Expand Down

0 comments on commit 374850a

Please sign in to comment.