2012-03-30 9 views
3

greifen Ich möchte ein paar tausend XML-Dateien von einer Website analysieren (ich habe die Erlaubnis) und müssen SAX verwenden, um zu vermeiden, die Datei im Speicher zu laden. Dann speichern Sie sie in einer CSV-Datei.Wie man Element Inhalt mit Nokogiri mit SAX

Die XML-Dateien wie folgt aussieht:

<?xml version="1.0" encoding="UTF-8"?><educationInfo xmlns="http://skolverket.se/education/info/1.2" xmlns:ct="http://skolverket.se/education/commontypes/1.2" xmlns:nya="http://vhs.se/NyA-emil-extensions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expires="2013-08-01" id="info.uh.su.HIA80D" lastEdited="2011-10-13T10:10:05" xsi:schemaLocation="http://skolverket.se/education/info/1.2 educationinfo.xsd"> 
    <titles> 
    <title xml:lang="sv">Arkivvetenskap</title> 
    <title xml:lang="en">Archival science</title> 
    </titles> 
    <identifier>HIA80D</identifier> 
    <educationLevelDetails> 
    <typeOfLevel>uoh</typeOfLevel> 
    <typeOfResponsibleBody>statlig</typeOfResponsibleBody> 
    <academic> 
     <course> 
     <type>avancerad</type> 
     </course> 
    </academic> 
    </educationLevelDetails> 
    <credits> 
    <exact>60</exact> 
    </credits> 
    <degrees> 
    <degree>Ingen examen</degree> 
    </degrees> 
    <prerequisites> 
    <academic>uh</academic> 
    </prerequisites> 
    <subjects> 
    <subject> 
     <code source="vhs">10.300</code> 
    </subject> 
    </subjects> 
    <descriptions> 
    <ct:description xml:lang="sv"> 
     <ct:text>Arkivvetenskap rör villkoren för befintliga arkiv och modern arkivbildning med fokus på arkivarieyrkets arbetsuppgifter: bevara, tillgängliggöra och styra information. Under ett år behandlas bl a informations- och dokumenthantering, arkivredovisning, gallring, lagstiftning och arkivteori. I kursen ingår praktik, där man under handledning får arbeta med olika arkivarieuppgifter.</ct:text> 
    </ct:description> 
    </descriptions> 
</educationInfo> 

ich diese Code-Vorlage zu verwenden, meine Kommentare für Fragen prüfen:

class InfoData < Nokogiri::XML::SAX::Document 

    def initialize 
    # do one-time setup here, called as part of Class.new 
    # But what should I use hashes or arrays? 
    end 

    def start_element(name, attributes = []) 
    # check the element name here and create an active record object if appropriate 
    # How do I grab specific element like: ct:text ? 
    # how do I grab root-element? 
    end 

    def characters(s) 
    # save the characters that appear here and possibly use them in the current tag object 
    end 

    def end_element(name) 
    # check the tag name and possibly use the characters you've collected 
    # and save your activerecord object now 
    end 

end 

parser = Nokogiri::XML::SAX::Parser.new(InfoData.new) 

# How do I parse every xml-link? 
parser.parse_file('') 

ich diese Methode schrieb die Links zu packen, aber don‘ t wissen, in der Klasse, wo es zu benutzen, oder wenn ich es dort verwenden soll:

@items = Set.new 
def get_links(url) 
    doc = Nokogiri::HTML(open(url)) 
    doc.xpath('//a/@href').each do |url| 
    item = {} 
    item[:url] = url.content 
    items << item 
end 
+0

Wenn dieses XML-Beispiel eine vollständige XML-Datei ist, würde ich das DOM anstatt SAX verwenden, weil es ein bisschen einfacher ist. Heutzutage haben die meisten Hosts mehrere Gigabyte RAM, was SAX weniger wichtig macht. BIG-XML-Dateien werden von SAX schneller verarbeitet, aber Ihre Entwicklungszeit wird wahrscheinlich länger dauern. –

+0

@theTinMan Ich habe versucht, es mit DOM zu analysieren und es wird nicht funktionieren. es über 46000 xml Dateien. Der richtige Weg, um SAX-Parsing zu verwenden. – SHUMAcupcake

Antwort

0
require 'nokogiri' 

class LinkGrabber < Nokogiri::XML::SAX::Document 
    def start_element(name, attrs = []) 
    if name == 'a' 
     puts Hash[attrs]['href'] 
    end 
    end 
end 

parser = Nokogiri::XML::SAX::Parser.new(LinkGrabber.new) 
parser.parse(File.read(ARGV[0], 'rb')) 

Jetzt können Sie diese in einer Pipeline verwenden:

find . -name "*.xml" -print0 | xargs -P 20 -0 -L 1 ruby parse.rb > links 

Aber das tut Start Rubin jedes Mal. Sie sollten also jruby verwenden (was sowieso schneller ist) und threach.

+0

[Unix-Pipeline] (http://en.wikipedia.org/wiki/Pipeline_ (Unix)) – Reactormonk

+0

genial Kumpel. Was ist eine Pipeline und haben Sie das XML-Dokument oder nur die Links analysiert? – SHUMAcupcake

+0

Dieser Teil von 'SAX' nimmt alle Elemente mit dem Namen' 'a'' und' puts' ihr Attribut '' href' '. Die Pipeline enthält einige "Xargs" und parallele Prozessmagie, ich würde empfehlen, die jruby-Lösung zu verwenden, weil es reiner Rubin ist. Es macht keinen Sinn, das mit dem normalen Rubin zu machen, weil MRT keine echten Threads unterstützt. Mit jruby können Sie alle Ihre Kerne verwenden. – Reactormonk

-1

vielleicht kann diese Arbeit:

require 'open-uri' 

    def get_links(url) 

      doc = Nokogiri::HTML(open(url)) 

      doc.xpath('//a/@href').each do |href| 

      parser.parse_io(open(href)) 

      end 

    end 
+0

'Nokogiri :: HTML (open (url))' ist falsch für ein XML-Dokument. 'Nokogiri :: HTML' entspannt den Parser, um HTMLs notorischen Mangel an Standards zu ermöglichen. Verwenden Sie stattdessen 'Nokogiri :: XML()', um das XML zu analysieren, um den strikten Parser zu verwenden. –

+0

Kein '# xpath' in SAX. Das ist DOM. – Reactormonk