2013-05-29 4 views
5

में विशाल टेक्स्ट नोड्स के साथ एक्सएमएल पढ़ने का व्यावहारिक तरीका विशाल टेक्स्ट नोड्स, युक्त XML डेटा फ़ाइलों का सामना करने के बाद मैंने अपने डेटा प्रोसेसिंग स्क्रिप्ट में पढ़ने और उनका मूल्यांकन करने के कुछ तरीकों की तलाश की।पर्ल

<?xml version="1.0" encoding="UTF-8"?> 
<hoomd_xml version="1.4"> 
    <configuration> 
     <position> 
     -0.101000 0.011000 -40.000000 
     -0.077000 0.008000 -40.469000 
     -0.008000 0.001000 -40.934000 
     -0.301000 0.033000 -41.157000 
     0.213000 -0.023000 -41.348000 
     ... 
     ... 300,000 to 500,000 lines may follow >> 
     ... 
     -0.140000 0.015000 -42.556000 
     </position> 

     <next_huge_section_of_the_same_pattern> 
     ... 
     ... 
     ... 
     </next_huge_section_of_the_same_pattern> 

    </configuration> 
</hoomd_xml> 

प्रत्येक एक्सएमएल फ़ाइलें कई बहुत बड़े पाठ नोड्स शामिल है और 60MB और 100 एमबी के आधार पर के बीच आकार है:

एक्सएमएल फ़ाइलें आणविक मॉडलिंग के लिए अनुप्रयोगों एक इस संरचना (उदाहरण) है 3 डी समन्वय फ़ाइलें हैं विषय सूचि।

मैं XML::Simple पहले का उपयोग कर भोले approch की कोशिश की लेकिन लोडर हमेशा के लिए ले शुरू में फ़ाइल को पार्स करने होगा:

... 
my $data = $xml->XMLin('structure_80mb.xml'); 
... 

और "आंतरिक त्रुटि: विशाल इनपुट देखने" के साथ बंद करो, तो इस दृष्टिकोण 'isn टी बहुत व्यावहारिक।

अगले कोशिश पढ़ने के लिए XML::LibXML उपयोग करने के लिए था - लेकिन यहाँ, प्रारंभिक लोडर त्रुटि संदेश के साथ तुरंत जमानत होगा "पार्सर त्रुटि: xmlSAX2Characters: विशाल पाठ नोड"।

stackoverflow पर इस विषय पर लिख Befor, मैं खुद के लिए aq & घ पार्सर ने लिखा है और इसके माध्यम से फाइल भेजी (अदिश $xml में xx एमबी xml फ़ाइल slurping के बाद):

... 
# read the <position> data from in-memory xml file 
my @Coord = xml_parser_hack('position', $xml); 
... 

जो एक सरणी प्रत्येक पंक्ति का डेटा देता है, सेकंड के भीतर पूरा करता है और इस तरह दिखता है:

sub xml_parser_hack { 
my ($tagname, $xml) = @_; 
return() unless $xml =~ /^</; 

my @Data =(); 
my ($p0, $p1) = (undef,undef); 
$p0 = $+[0] if $xml =~ /^<$tagname[^>]*>[^\r\n]*[r\n]+/msg; # start tag 
$p1 = $-[0] if $xml =~ /^<\/$tagname[^>]*>/msg;    # end tag 
return() unless defined $p0 && defined $p1; 
my @Lines = split /[\r\n]+/, substr $xml, $p0, $p1-$p0; 
for my $line (@Lines) { 
    push @Data, [ split /\s+/, $line ]; 
} 
return @Data; 
} 

यह अब तक ठीक काम करता है लेकिन 'उत्पादन के लिए तैयार' नहीं माना जा सकता है, ज़ाहिर है,।

प्रश्न: मैं पर्ल मॉड्यूल का उपयोग कर फ़ाइल कैसे पढ़ूं? मैं कौन सा मॉड्यूल चुनूँगा?

अग्रिम

RBO


परिशिष्ट में धन्यवाद: choroba की टिप्पणी को पढ़ने के बाद, मैं एक्सएमएल में गहरी देखा :: LibXML। फ़ाइल का उद्घाटन my $reader = XML::LibXML::Reader->new(location =>'structure_80mb.xml'); काम करता है, जो मैंने पहले सोचा था। त्रुटि तब होती है अगर मैं टैग नीचे पाठ नोड तक पहुँचने का प्रयास:

... 
while ($reader->read) { 
    # bails out in the loop iteration after accessing the <position> tag, 
    # if the position's text node is accessed 
    # -- xmlSAX2Characters: huge text node --- 
... 
+5

http://search.cpan.org/~mirod/XML-Twig -3.44/Twig.pm - पेड़ मोड में विशाल एक्सएमएल दस्तावेजों को संसाधित करने के लिए perl मॉड्यूल। –

+1

आपने XML :: LibXML के साथ फ़ाइल कैसे खोली? यह 100 एमबी की फाइलों के लिए मेरे लिए काम करता है। – choroba

+0

@choroba - धन्यवाद, मैंने फिर से जांच की - और विषय को अपडेट किया। –

उत्तर

1

मैं XML का उपयोग एक जवाब :: LibXML अनुकरण करने के लिए कर रहा था। इसे आज़माएं, और मुझे बताएं कि यह काम नहीं करता है। मैं position तत्व में एक से अधिक 500k लाइनों के साथ एक XML दस्तावेज़ बनाया जाता है, और मैं इसे पार्स और यह की सामग्री को मुद्रित करने में सक्षम था:

use strict; 
use warnings; 
use XML::LibXML; 

my $xml = XML::LibXML->load_xml(location => '/perl/test.xml'); 
my $nodes = $xml->findnodes('/hoomd_xml/configuration/position'); 
print $nodes->[0]->textContent . "\n"; 
print scalar(@{$nodes}) . "\n"; 

मैं findnodes उपयोग कर रहा हूँ सब बाहर निकलने के लिए एक XPath अभिव्यक्ति का उपयोग करने के लिए नोड्स जो मैं चाहता हूं। $nodes सिर्फ एक सरणी रेफरी है, इसलिए आप अपने दस्तावेज़ में वास्तव में कितने नोड्स के आधार पर इसके माध्यम से लूप कर सकते हैं।

+0

धन्यवाद! लेकिन मेरा एक्सएमएल :: LibXML 2.0018 Win64 फ़ाइल लोड नहीं कर सकता है। '$ xml = XML :: LibXML-> load_xml (location => $ fn)' तुरंत विफल हो जाता है w/'पार्सर त्रुटि: xmlSAX2Characters: विशाल टेक्स्ट नोड'। जबकि '$ xml = XML :: LibXML :: Reader-> नया (स्थान => $ fn) 'फ़ाइल लोड करता है, लेकिन इसमें विधि नहीं है:' ऑब्जेक्ट विधि का पता नहीं लगाया जा सकता" पैकेज के माध्यम से findnodes "एक्सएमएल: : LibXML :: रीडर "'। –

+0

@rubberboots क्या आप libxml का उपयोग कर रहे हैं जिसका संस्करण आप उपयोग कर रहे हैं? आप इसे अपनी पर्ल स्क्रिप्ट के अंदर 'XML :: LibXML :: LIBXML_DOTTED_VERSION' प्रिंट करके प्राप्त कर सकते हैं। – Joel

+0

मैंने nwellnhof द्वारा प्रस्तावित 'विशाल' विकल्प जोड़ा। अब आपके 'खोज नोड्स' पूरी तरह से काम करता है। धन्यवाद। –

2

huge पार्सर विकल्प के साथ XML::LibXML का प्रयास करें:

my $doc = XML::LibXML->load_xml(
    location => 'structure_80mb.xml', 
    huge  => 1, 
); 

या, आप का उपयोग करने के XML::LibXML::Reader चाहते हैं:

my $reader = XML::LibXML::Reader->new(
    location => 'structure_80mb.xml', 
    huge  => 1, 
); 
+0

यह है! 'विशाल' विकल्प के साथ, जोएल के 'खोज नोड' कॉल के साथ संयुक्त, पढ़ने और प्रसंस्करण LibXML के माध्यम से सेकंड में किया जाता है। आपका बहुत बहुत धन्यवाद! –