class SecEdgar::FilingParser
Attributes
xsd_uri[R]
Public Class Methods
new(filing)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 5 def initialize(filing) @xsd_uri = 'lib/sec4/ownership4Document.xsd.xml' @filing = filing @content = filing.content end
Public Instance Methods
content()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 11 def content if @content.start_with?('-----BEGIN PRIVACY-ENHANCED MESSAGE-----') @content = strip_privacy_wrapper(@content) end @content end
derivative_transactions()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 47 def derivative_transactions doc.derivative_transactions ||= [] end
doc()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 18 def doc @doc ||= SecEdgar::OwnershipDocument.new end
footnotes()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 39 def footnotes doc.footnotes ||= [] end
parse(&error_blk)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 22 def parse(&error_blk) if block_given? && !xml_valid? error_blk.call(xml_errors) puts "Error: returning NilObjectDocument #{ @filing.link }" return SecEdgar::NilOwnershipDocument.new end footnotes | transactions | derivative_transactions # eager init parse_doc(xml_doc) parse_issuer(xml_doc.xpath('//issuer')) parse_owner(xml_doc.xpath('//reportingOwner')) parse_non_derivative_table(xml_doc.xpath('//nonDerivativeTable')) parse_derivative_table(xml_doc.xpath('//derivativeTable')) parse_footnotes(xml_doc.xpath('//footnotes')) doc end
transactions()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 43 def transactions doc.transactions ||= [] end
xml_filing()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 51 def xml_filing Nokogiri::XML(xml_doc.to_xml) end
Private Instance Methods
parse_derivative_table(el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 128 def parse_derivative_table(el) el.xpath('//derivativeTransaction').each do |transaction_el| parse_derivative_transaction(transaction_el) end end
parse_derivative_transaction(el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 88 def parse_derivative_transaction(el) transaction = SecEdgar::DerivativeTransaction.new transaction.security_title = el.xpath('securityTitle').text.strip transaction.transaction_date = Date.parse(el.xpath('transactionDate').text) transaction.conversion_or_exercise_price = el.xpath('conversionOrExercisePrice').text.to_f unless (expiration_date = el.xpath('expirationDate/value').text).blank? transaction.expiration_date = Date.parse(expiration_date) end unless (exercise_date = el.xpath('exerciseDate/value').text).blank? transaction.exercise_date = Date.parse(exercise_date) end parse_transaction_amounts(transaction, el.xpath('transactionAmounts')) parse_transaction_ownership_nature(transaction, el.xpath('ownershipNature')) parse_transaction_coding(transaction, el.xpath('transactionCoding')) parse_transaction_underlying(transaction, el.xpath('underlyingSecurity')) # post transaction amounts transaction.shares_after = el .xpath('postTransactionAmounts/sharesOwnedFollowingTransaction/value') .text .to_f derivative_transactions << transaction end
parse_doc(el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 160 def parse_doc(el) doc.schema_version = el.xpath('//schemaVersion').text doc.document_type = el.xpath('//documentType').text doc.not_subject_to_section_16 = (el.xpath('//notSubjectToSection16').text == '1' || el.xpath('//notSubjectToSection16').text == 'true') doc.period_of_report = Date.parse(el.xpath('//periodOfReport').text) # p doc.period_of_report rescue ArgumentError => e puts "parse_doc error: #{ el.inspect }" puts e raise e end
parse_footnote(el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 81 def parse_footnote(el) footnote = SecEdgar::Footnote.new footnote.content = el.text.strip footnote.id = el.attribute("id").value footnotes << footnote end
parse_footnotes(el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 134 def parse_footnotes(el) el.xpath('//footnote').each do |note_el| parse_footnote(note_el) end end
parse_issuer(el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 174 def parse_issuer(el) doc.issuer_cik = el.xpath('//issuerCik').text doc.issuer_name = el.xpath('//issuerName').text doc.issuer_trading_symbol = el.xpath('//issuerTradingSymbol').text end
parse_non_derivative_table(el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 122 def parse_non_derivative_table(el) el.xpath('//nonDerivativeTransaction').each do |transaction_el| parse_transaction(transaction_el) end end
parse_owner(el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 180 def parse_owner(el) doc.owner_cik = el.xpath('//rptOwnerCik').text doc.owner_name = el.xpath('//rptOwnerName').text doc.is_director = el.xpath('//isDirector').text == '1' doc.is_ten_percent_owner = el.xpath('//isTenPercentOwner').text == '1' doc.is_other = el.xpath('//isOther').text == '1' doc.is_officer = (el.xpath('//isOfficer').text == '1' || el.xpath('//isOfficer').text.downcase == 'true') doc.officer_title = el.xpath('//officerTitle').text address = SecEdgar::Address.new address.street1 = el.xpath('//rptOwnerStreet1').text address.street2 = el.xpath('//rptOwnerStreet2').text address.city = el.xpath('//rptOwnerCity').text address.state = el.xpath('//rptOwnerState').text address.zip = el.xpath('//rptOwnerZipCode').text address.state_description = el.xpath('//rptOwnerStateDescription').text doc.owner_address = address end
parse_transaction(el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 64 def parse_transaction(el) transaction = SecEdgar::Transaction.new transaction.security_title = el.xpath('securityTitle').text.strip transaction.transaction_date = Date.parse(el.xpath('transactionDate').text) parse_transaction_amounts(transaction, el.xpath('transactionAmounts')) parse_transaction_ownership_nature(transaction, el.xpath('ownershipNature')) parse_transaction_coding(transaction, el.xpath('transactionCoding')) # post transaction amounts transaction.shares_after = el .xpath('postTransactionAmounts/sharesOwnedFollowingTransaction/value') .text .to_f transactions << transaction end
parse_transaction_amounts(transaction, el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 140 def parse_transaction_amounts(transaction, el) transaction.acquired_or_disposed_code = el.xpath('transactionAcquiredDisposedCode/value').text transaction.shares = el.xpath('transactionShares/value').text.to_f transaction.price_per_share = el.xpath('transactionPricePerShare/value').text.to_f end
parse_transaction_coding(transaction, el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 149 def parse_transaction_coding(transaction, el) transaction.code = el.xpath('transactionCode').text transaction.form_type = el.xpath('transactionFormType').text transaction.equity_swap_involved = el.xpath('equitySwapInvolved').text == '1' end
parse_transaction_ownership_nature(transaction, el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 155 def parse_transaction_ownership_nature(transaction, el) transaction.nature_of_ownership = el.xpath('natureOfOwnership/value').text transaction.direct_or_indirect_code = el.xpath('directOrIndirectOwnership/value').text end
parse_transaction_underlying(transaction, el)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 116 def parse_transaction_underlying(transaction, el) transaction.underlying_security_title = el.xpath('underlyingSecurityTitle/value').text transaction.underlying_security_shares = el.xpath('underlyingSecurityShares/value').text.to_f end
strip_privacy_wrapper(raw)
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 57 def strip_privacy_wrapper(raw) lines = raw.split("\n") lines.shift until lines.first.start_with?('<SEC-DOCUMENT>') lines.pop if lines.last.start_with?('-----END PRIVACY-ENHANCED MESSAGE--') lines.join("\n") end
xml_doc()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 201 def xml_doc Nokogiri::XML(content).xpath('//ownershipDocument') end
xml_errors()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 213 def xml_errors @errors ||= xml_schema.validate(xml_filing) end
xml_schema()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 205 def xml_schema @schema ||= Nokogiri::XML::Schema(IO.read(xsd_uri)) end
xml_valid?()
click to toggle source
# File lib/sec_edgar/filing_parser.rb, line 209 def xml_valid? xml_errors.empty? && !content.blank? end