[perl] efficiente methode om datastream te parsen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • TrailBlazer
  • Registratie: Oktober 2000
  • Laatst online: 28-06 09:50

TrailBlazer

Karnemelk FTW

Topicstarter
Voor een monitoring applicatie krijg ik een stroom xml entries binnen die ik moet verwerken. Omdat de datastroom oneindig is moet ik elke keer na een bepaalde hoeveelheid data (chunk) de entries verwerken. De tcp sessie eindigt dus ook nooit. Ik zit er nu mee hoe ik dit efficient kan doen.

de data heeft het volgende format
<a><b><c id="123">alarm1</c><c id="124">alarm2</c></b></a>

het gaat me dan om de tekst binnen de <c></c> tags inclusief deze tags. Het aantal c tags binnen de <b> tags kan verschillen. Het kan ook voorkomen dat de string niet volledig is met een sluittag omdat deze in de volgende chunk pas komt bijvoorbeeld
<a><b><c id="123">alarm1</c><c id="124">ala

de volgende chunk is dan bijvoorbeeld
rm2</c></b></a><a><b><c id="124">alarm3</c></b></a>

Mijn idee is om eerst de <a><b></b></a> weg te gooien.
Vervolgens met de volgende code de alarmen stuk voor stuk te parsen
Perl:
1
2
3
4
5
$alarms=$alarms . $chunkdata
while ($alarms=~s/(<c id="\d+">.+?<\/c>)(.*)/$2/) {
#$1 bevat het eerste alarm en kan ik gaan verwerken.
#$alarms bevat dan het restje wat geen volledig alarm is.
}

in $alarms plaats ik de info met nieuwe alarmen uit de nieuwe chunk ($chunkdata). Hier plaats ik het restje van de vorige alarmen voor indien dat over is
Iemand een ander idee om dit aan te pakken of is dit wel een efficiënte manier om zoiets aan te pakken?

Acties:
  • 0 Henk 'm!

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 28-06 18:09

voodooless

Sound is no voodoo!

Een SAX parser zou hier waarschijnlijk goed werken, zie http://www.xml.com/pub/a/2001/02/14/perlsax.html voor een voorbeeld (ben verder geen Perl expert ofzo).

Do diamonds shine on the dark side of the moon :?


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Dit lijkt mij ook een vreemde manier van werken, XML::SAX of het oudere XML::Parser gebruiken en niet met vreemde chunks werken lijkt me handiger. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • TrailBlazer
  • Registratie: Oktober 2000
  • Laatst online: 28-06 09:50

TrailBlazer

Karnemelk FTW

Topicstarter
Ik zal er eens naar kijken ik was die ook al tegengekomen alleen ik heb het idee dat het systeem wat de berichten verstuurt zich niet helemaal aan de richtlijnen houdt.
Die chunks moet ik trouwens wel houden. Omdat de stroom alarmen nooit ophoudt moet ik tussentijds die data uit die datastroom verwerken.

[ Voor 29% gewijzigd door TrailBlazer op 05-01-2012 17:13 ]


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 17:45

Creepy

Tactical Espionage Splatterer

Eeh, dat is toch precies wat een SAX parser doet? Die parset een stream en geeft event's/callbacks af. Die handelt dus dat hele chunking gebeuren voor je af.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • TrailBlazer
  • Registratie: Oktober 2000
  • Laatst online: 28-06 09:50

TrailBlazer

Karnemelk FTW

Topicstarter
* TrailBlazer gaat nog eens naar die SAX parser kijken.
ben een redelijke programmeer noob van netwerken kan ik je wel alles vertellen :p

[ Voor 39% gewijzigd door TrailBlazer op 05-01-2012 17:40 ]


Acties:
  • 0 Henk 'm!

  • TrailBlazer
  • Registratie: Oktober 2000
  • Laatst online: 28-06 09:50

TrailBlazer

Karnemelk FTW

Topicstarter
Ik zit nu even te kijken naar XML::Parser die kan als input een open socket gebruiken. Nu vraag ik me af hoe ik het best dat socket kan maken? Ik gebruik nu LWP::Useragent om makkelijk mijn request te maken maar die geeft geen socket. Anders maar gewoon met IO::Socket en dan zelf mijn request maken.

Acties:
  • 0 Henk 'm!

  • ZpAz
  • Registratie: September 2005
  • Nu online
Het zou (geen ervaring met Perl) zo kunnen zijn dat XML::Parser pas gaat parsen als er een geheel XML document binnen is. Aangezien het een stream is gaat dat dus niet werken.

SAX is the way to go.

Tweakers Time Machine Browser Extension | Chrome : Firefox


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
XML::Parser kan zowel in tree als in stream modus (http://perl-xml.sourceforge.net/faq/#xml_parser ), maar SAX is natuurlijk handiger omdat dat net zoals DOM een standaardmethode is die in meerdere talen werkt. XML::SAX::Expat lijkt mij het handigst zo te zien. parse_uri lijkt me handig, of is er geen sprake van HTTP?

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • TrailBlazer
  • Registratie: Oktober 2000
  • Laatst online: 28-06 09:50

TrailBlazer

Karnemelk FTW

Topicstarter
jongens to be honest snap ik maar de helft van wat jullie posten maar langzaamaan kom ik er wel. Anyway ik heb nu een socket waarop alle XML binnenkomt. Ik ga me nu even rustig verdiepen in dat hele SAX verhaal.
Thanks zo ver.

Acties:
  • 0 Henk 'm!

  • TrailBlazer
  • Registratie: Oktober 2000
  • Laatst online: 28-06 09:50

TrailBlazer

Karnemelk FTW

Topicstarter
Ondertussen heb ik die socket gekoppeld aan XML::Parser. Alleen die apparatuur wat de berichten stuurt stuurt wat extra info mee.
XML:
1
2
3
4
188
 <configMoChangeEvent cookie="" inEid="21033525"> 
<inConfig> <etherPIo  dn="sys/switch-B/slot-1/switch-ether/port-1" operSpeed="203"  status="modified"/> </inConfig> 
</configMoChangeEvent>

het gaat dus om die 188 die er boven staat. Daar gaat uiteraard de XML::Parser van op zijn bek omdat het niet binnen tags staat.

[ Voor 9% gewijzigd door TrailBlazer op 06-01-2012 11:04 ]


Acties:
  • 0 Henk 'm!

  • TrailBlazer
  • Registratie: Oktober 2000
  • Laatst online: 28-06 09:50

TrailBlazer

Karnemelk FTW

Topicstarter
Ondertussen netjes een SAX parser er in gehangen alleen het blijft dus misgaan omdat die data niet conform de specs is. Die decimale waarde is dus de lengte van de data die gaat volgen.

Acties:
  • 0 Henk 'm!

Anoniem: 26306

Dan moet je eigenlijk een wrapper maken die dat afvangt. Je moet zorgen dat er een aparte routine is die bij het lezen eerste een integer leest en vervolgens een aantal characters dat gelijk is aan die integer. En dát moet je dus naar je SAX parser sturen.

Acties:
  • 0 Henk 'm!

  • TrailBlazer
  • Registratie: Oktober 2000
  • Laatst online: 28-06 09:50

TrailBlazer

Karnemelk FTW

Topicstarter
Ik heb het inderdaad opgelost door met standaard regexen de input data te filteren en die vervolgens als string naar de SAX parser te sturen. Nu begrijp ik enkel nog niet hoe die handlers werken om ook daadwerkelijk wat zinnige info terug te krijgen. Als ik met Data Dumper kijk zie ik dit
print Dumper($element)
code:
1
2
3
4
5
6
7
$VAR1 = {
          'Prefix' => '',
          'LocalName' => 'inConfig',
          'Attributes' => {},
          'Name' => 'inConfig',
          'NamespaceURI' => ''
        };

alleen
print "Local $element{'LocalName'} \n";

geeft een uninitialized value $element{"LocalName"}
:?

uitendelijk kan ik die zo opvragen

$element->{LocalName}

[ Voor 4% gewijzigd door TrailBlazer op 08-01-2012 19:27 ]

Pagina: 1