Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Support for explicit xpath option

Default xpath for non-root nodes matches all descendants. Sometimes,
you only want to match the immediate child. The ability to specify
xpath will cover this and other cases.
  • Loading branch information...
commit dbaaebc675dae7104d2c3581056d14d87d4cb362 1 parent 444994b
@teleological authored
View
8 lib/happymapper.rb
@@ -97,9 +97,11 @@ def parse(xml, options = {})
namespace = @namespace || (node.namespaces && node.namespaces.default)
namespace = "#{DEFAULT_NS}:#{namespace}" if namespace
- xpath = root ? '/' : './/'
- xpath += "#{DEFAULT_NS}:" if namespace
- xpath += tag_name
+ unless xpath = options[:xpath]
+ xpath = root ? '/' : './/'
+ xpath += "#{DEFAULT_NS}:" if namespace
+ xpath += tag_name
+ end
nodes = node.find(xpath, Array(namespace))
collection = nodes.collect do |n|
View
29 spec/fixtures/intrade.xml
@@ -0,0 +1,29 @@
+<tsResponse requestOp="getUserMessages" resultCode="0" timestamp="1329416249820"
+ timetaken="475">
+ <msg msgID="123456">
+ <msgID>123456</msgID>
+ <conID>789012</conID>
+ <symbol>2012.PIGS.FLY</symbol>
+ <readFlag>false</readFlag>
+ <type>T</type>
+ <msg>345678901</msg>
+ <price>13.0</price>
+ <quantity>100</quantity>
+ <side>B</side>
+ <timestamp>1329415852000</timestamp>
+ </msg>
+ <msg msgID="123460">
+ <msgID>123460</msgID>
+ <conID>789013</conID>
+ <symbol>2012.SNOWBALL.INFERNO.MELT</symbol>
+ <readFlag>false</readFlag>
+ <type>T</type>
+ <msg>345678933</msg>
+ <price>13.0</price>
+ <quantity>100</quantity>
+ <side>S</side>
+ <timestamp>1329415873000</timestamp>
+ </msg>
+ <faildesc>Ok</faildesc>
+ <sessionData>10R3M1p5um0010r5174m37c0n53C737uR401p151C1N931175300031U5m0073mp0r1Nc1010UN7u71480R3370010R3m49n44119u4U73N1M40M1n1MV3n14M9U15n057Ru03X3Rc174710Nu114Mc01480r15n151u74119U1P3x34C0mm000C0n539u470u154u731ruR30010r1Nr3PR3h3n03R171Nv01up7473v31173553C111Um0010R33ufU9147nu114P4R147Ur3XC3P73uR51n70CC43C47CuP104747n0nPR0103N75un71ncu1p49U10fF1C140353rUn7m011174N1M103571480Rum</sessionData>
+</tsResponse>
View
13 spec/happymapper_spec.rb
@@ -350,6 +350,19 @@ class Thing
# tree.people.first.id.should == 'KWQS-BBQ'
end
+ it "should support :xpath option" do
+ message_box = Intrade::Messages.parse(fixture_file('intrade.xml'))
+ message_box.timestamp.should == Time.at(1329416249)
+ message_box.error_message.should == "Ok"
+
+ # default xpath would default to './/msg', which would include
+ # nested nodes which are also named "msg", so xpath is
+ # explicitly supplied as option :xpath => './msg'
+ message_box.messages.should have(2).messages
+ message_box.messages[0].message_id.should == 123456
+ message_box.messages[1].message_id.should == 123460
+ end
+
describe 'nested elements with namespaces' do
module Namespaces
class Info
View
37 spec/support/models.rb
@@ -299,4 +299,39 @@ class Note
content :body
end
-end
+end
+
+module Intrade
+ class EpochMillis
+ def self.parse(millis); Time.at(millis.to_i / 1000); end
+ end
+
+ class Message
+ include HappyMapper
+
+ tag 'msg'
+ attribute :message_id, Integer, :tag => 'msgID'
+ element :contract_id, Integer, :tag => 'conID'
+ element :symbol, String, :tag => 'symbol'
+ element :is_read, Boolean, :tag => 'readFlag'
+ element :type, String, :tag => 'type'
+ element :text, String, :tag => 'msg'
+ element :price, Float, :tag => 'price'
+ element :quantity, Integer, :tag => 'quantity'
+ element :side, String, :tag => 'side'
+ element :timestamp, EpochMillis, :tag => 'timestamp', :parser => :parse
+ end
+
+ class Messages
+ include HappyMapper
+
+ tag 'tsResponse'
+ attribute :operation, String, :tag => 'requestOp'
+ attribute :timestamp, EpochMillis, :tag => 'timestamp', :parser => :parse
+ attribute :result_code, Integer, :tag => 'resultCode'
+ element :error_message, String, :tag => 'faildesc'
+ element :session_key, String, :tag => 'sessionData'
+ has_many :messages, Message, :tag => 'msg', :xpath => './msg'
+ end
+end
+
Please sign in to comment.
Something went wrong with that request. Please try again.