[LinuxFocus-icon]
<--  | Ana Sayfa  | Erişimdüzeni  | İçindekiler  | Arama

Duyumlar | Belgelikler | Bağlantılar | LF Nedir
Bu makalenin farklı dillerde bulunduğu adresler: English  Castellano  Deutsch  Francais  Italiano  Nederlands  Portugues  Russian  Turkce  

[Photo of the Author]
Guido Socher (homepage)

Yazar hakkında:

Oldukça esnek ve hızlı bir betik yazım dili olması sebebi ile Guido Perl'den hoşlanmaktadır. Perl'ün açıkkod ile yürüdüğünüzde tanıdığı imkanları ve özgürlüğü ifade eden "Bunu yapmak için birden fazla yolumuz var" sloganını sever.



Türkçe'ye çeviri:
İnanç Özçubukçu <inanco(at)atlas.net.tr>

İçerik:

 

Managing HTML with Perl, HTML::TagReader

[Illustration]

Özet:

Eğer 10 HTML sayfasından fazla bir sanal yöreyi idare etmek isterseniz size destek amaçlı bazı yazılımlara ihtiyaç olduğunu göreceksiniz.
Birçok alışılagelmiş yazılım dosyaları satır satır (karakter karakter) okur. Maalesef satırların SGML/XML/HTML dosyalarında bir anlamı yoktur. SGML/XML/HTML dosyaları Etiket tabanlıdır. HTML::TagReader bir dosyayı Etiket ile işletmek için bir bileşendir.

Bu yazı Perl'ü biraz bildiğinizi varsaymaktadır. Eğer Perl öğrenmek istiyorsanız my Perl tutorials (January 2000) adresine bir göz atın.

_________________ _________________ _________________

 

Giriş

Alışıla gelmiş dosyalar satır temellidir. Örnek olarak Unix'teki /etc/hosts, /etc/passwd tanımlama dosyaları gibi. Satır satır veri girmek ve düzeltmek için fonksiyonlarınızın olduğu daha da eski işletim sistemleri vardır.
SGML/XML/HTML dosyaları Etiket temellidir. Burada satırların bir anlamı yoktur ama yine de dosya editörleri ve insanlar halen bir şekilde satır tabanlıdırlar.

Özellikle büyük HTML dosyaları genelde bir dizi HTML kodu içeren satırlardan oluşur. "Tidy" gibi bazı araçlar html'yi yorumlatıp okunabilir yaparlar. Biz HTML dahi olsa satırlar yerine Etiket kullanmaktayız. Bunu C-kodu ile mukayese edebilirsiniz. Teorik olarak tüm kodu basit bir satırda yazabilirsiniz. Kimse bunu yapmaz. Yoksa okunamaz olur.
Bu sebeple bir HTML yazım denetçisinin "ERROR after tag 4123" yazmasından çok "ERROR: line ..." yazmasını beklersiniz. Bunun sebebi yazım aracınızın belirtilen satıra kolaylıkla atlayabilmesidir.

Burada ihtiyaç olan güzel ve kolay bir yolla HTML dosyasını Etiket Etiket olarak işlemek ve halen satır numaralarını tutmaktır..  

Muhtemel bir çözüm

Bir dosyayı Perl'de okumanın en alışılmış yolu while(<FILEHANDLE>) işletimcisi kullanmaktır. Bu veriyi satır satır okuyacak ve her satırı $_ değişkenine aktaracaktır. Perl neden bunu yapıyor? Perl, "\n" satır sonunu ifade eden içe yönelik INPUT_RECORD_SEPARATOR olarak adlandırılan bir değişkene sahiptir. Eğer $/=">" olarak atarsanız Perl ">" 'ı "satır sonu" gibi kullanacaktır. Aşağıdaki komut satırı Perl betiği sonunda hep ">" olacak şekilde html dosyasını yeniden biçimlendirecektir :

perl -ne 'sub BEGIN{$/=">";} s/\s+/ /g; print "$_\n";' file.html

Bir HTML dosyası şuna benzer

<html><p>some text here</p></html>
will become
<html>
<p>
some text here</p>
</html>
Önemli olan yine de okunulabilirlik değildir. Yazılım geliştirici için önemli olan verinin kodundaki fonksiyonlarından Etiket Etiket geçmesidir. Bununla birlikte asıl HTML ayrı satırlarda "a" ve "href" içerse bile bir "<a href= ..." aramak kolay olacak.

"$/" (INPUT_RECORD_SEPARATOR) 'ı değiştirmek işlemde artışa sebep olmaz ve oldukça hızlıdır. Yine aynı şekilde karşılaştırma işletimcisini ve alışılmış deyimleri bir seri gibi kullanmak ve dosyayı alışılmış deyimlerle işlemek mümkündür. Bu biraz daha karmaşık ve yavaş olmakla birlikte sıklıkla kullanılmaktadır.

Sorun nerede?? Bu yazının başlığı dedi ki HTML::TagReader fakat ben sürekli ilave modüller gerektirmeyen daha basit çözümlerden bahsediyorum. Bu çözümde yanlış olan bir şeyler olmalı: Diğer bir deyişle "$/" (INPUT_RECORD_SEPARATOR) kullanmak sadece özel durumlarda mümkündür.

Elimde neyi tartıştığımızı gösterir çok yararlı bir örnek program var. Her ne kadar "$/"ı "<"ye atasa da web tarayıcıları yanlış konmuş "<" yi ">" gibi destekleyemez. Bu sebeple ">" yerine yanlış "<" yerleştirilmiş web sayfası daha azdır. Program tr_tagcontentgrep(click to view) olarak adlandırılmakta ve satır numarasının kaydının nasıl tutulduğunu da kod içerisinde görebilirsiniz. tr_tagcontentgrep, Etiket birçok satırdan oluşuyor olsa bile, bir dizi (ör: "img") "grep" etmek için kullanılabilir. Şuna benzer:

tr_tagcontentgrep -l img file.html
index.html:53: <IMG src="../images/transpix.gif" alt="">
index.html:257: <IMG SRC="../Logo.gif" width=128 height=53>

 

HTML::TagReader

HTML::TagReader iki sorunu INPUT_RECORD_SEPARATOR 'ı uyarlamakla çözümler ve aynı zamanda düz yazıları Etiket'lerden ayırmak için çok daha hoş bir yol sunar. Yüklü bir HTML:Parser gibi ağır değildir ve html kodunu işletince size istediğiniz şeyi sunar:Etiket Etiket okuma yöntemidir.

Bu kadar laf yeter. İşte nasıl kullanacağınız. Önce kodunuz içerisine modülü yüklemek için
use HTML::TagReader;
yazmalısınız. Sonuçta
my $p=new HTML::TagReader "filename";
kullanarak "dosyaismi" dosyasını açarız ve $p içerisindeki nesneyi getiririz. Bir sonraki Etiket'i almak için şimdi $p->gettag(0) veya $p->getbytoken(0) çağırabiliriz. getbytoken Etiket'ler arasındaki düz yazıları verirken gettag sadece Etiket'leri döndürür (< ve > arasındaki iş) ve onun ne olduğunu size söyler (Etiket veya düz yazı). Bu fonksiyonla html dosyalarını işletmek oldukça basittir. Aslen geniş bir sanal yöreyi yönetmektir. Tüm yazım şekline man page of HTML::TagReader adresinden erişilebilir.

Şimdi gerçek bir örnek program. Döküman numarasına göre döküman başlığı basmakta:
#!/usr/bin/perl -w
use strict;
use HTML::TagReader;
#
die "USAGE: htmltitle file.html [file2.html...]\n" unless($ARGV[0]);
my $printnow=0;
my ($tagOrText,$tagtype,$linenumber,$column);
#
for my $file (@ARGV){
  my $p=new HTML::TagReader "$file";
  # read the file with getbytoken:
  while(($tagOrText,$tagtype,$linenumber,$column) = $p->getbytoken(0)){
  if ($tagtype eq "title"){
    $printnow=1;
    print "${file}:${linenumber}:${column}: ";
    next;
  }
  next unless($printnow);
  if ($tagtype eq "/title" || $tagtype eq "/head" ){
    $printnow=0;
    print "\n";
    next;
  }
  $tagOrText=~s/\s+/ /; #kill newline, double space and tabs
  print $tagOrText;
  }
}
# vim: set sw=4 ts=4 si et:
Nasıl çalışıyor? <title> yada <Title> yada <TITLE> ($tagtype olarak "title"a eşit olarak döndüler) bulduğumuz zaman $p->getbytoken(0) ile html dosyasını okuyoruz. Ardından basmaya başlamak için bir bayrak ($printnow) atıyoruz ve ne zaman ki </title> bulduk, basmayı durduyoruz.
Programı şu şekilde kullanıyoruz:

htmltitle file.html somedir/index.html
file.html:4: the cool perl page
somedir/index.html:9: joe's homepage

Elbette tr_tagcontentgrep 'i aşağıdan HTML::TagReader ile uygulamak mümkün. Yazmak için biraz daha kısa ve basit olarak:

#!/usr/bin/perl -w
use HTML::TagReader;
die "USAGE: taggrep.pl searchexpr file.html\n" unless ($ARGV[1]);
my $expression = shift;
my @tag;
for my $file (@ARGV){
  my $p=new HTML::TagReader "$file";
  while(@tag = $p->gettag(0)){
    # $tag[0] is the tag (e.g <a href=...>)
    # $tag[1]=linenumber $tag[2]=column
    if ($tag[0]=~/$expression/io){
      print "$file:$tag[1]:$tag[2]: $tag[0]\n";
    }
  }
}
Betik kısadır ve fazla hata kaldırmaz ancak öte yandan tamamen işlevseldir. "gif" değişkenini yakalamak için yazılması gereken:

taggrep.pl gif file.html
file.html:135:15: <img src="images/2doc.gif" width=34 height=22>
file.html:140:1: <img src="images/tst.gif" height="164" width="173">

Bir örnek daha? İşte tüm <font...> ve </font> Etiket'lerini html kodundan ayıklayacak bir program. Bu font Etiket'leri bazı zayıf grafik tabanlı tarayıcılar tarafından yoğun olarak kullanılmakta ve farklı tarayıcılar ve ekran boyutları ile görüntülenmeye çalışıldıklarında sorun yaratmaktadırlar. Bu basit sürüm tüm font Etiket'leri ayıklamakta. Sadece font yüzü ve boyutunu ayarlamak ve rengi değişmeden bırakmak için kullanabilirsiniz.

#!/usr/bin/perl -w
use strict;
use HTML::TagReader;
# strip all font tags from html code but leave the rest of the
# code un-changed.
die "USAGE: delfont file.html > newfile.html\n" unless ($ARGV[0]);
my $file = $ARGV[0];
my ($tagOrText,$tagtype,$linenumber,$column);
#
my $p=new HTML::TagReader "$file";
# read the file with getbytoken:
while(($tagOrText,$tagtype,$linenumber,$column) = $p->getbytoken(0)){
  if ($tagtype eq "font" || $tagtype eq "/font"){
    print STDERR "${file}:${linenumber}:${column}: deleting $tagtype\n";
    next;
  }
  print $tagOrText;
}
# vim: set sw=4 ts=4 si et:
Gördüğünüz gibi sadece birkaç satırla kolayca kullanışlı programlar yazılabiliyor.
HTML::TagReader (örneklere bkz) paket kaynak kodu bazı HTML::TagReader uygulamalarını zaten içermektedir: tr_xlnk ve tr_staticssi bir sanal yöreden CDRom yapmak istediğinizde çok kullanışlıdır. Bir sanal yöre sunucusu http://www.linuxfocus.org yazdığınızda (index.html olmaksızın) size http://www.linuxfocus.org/index.html'yi verecektir. Eğer ki tüm dosyaları ve dizinleri CD ye yazmış ve tarayıcınız aracılığı ile doğrudan CD ye erişiyorsanız (dosya:/mnt/cdrom) bu durumda index.html yerine dizin listesi göreceksiniz ve bu işlem bir dizini gösteren her linki seçtiğinizde tekrarlanacaktır. İlk LinuxFocusCD yi yapan şirket bu hatayı yaptı ve CD yi kullanım açısında bir felaket oldu. Şimdi veriyi tr_xlnk ile alıyorlar ve CD ler çalışıyor.

Eminim ki HTML::TagReader 'ı kullanışlı bulacaksınız. Mutlu programlamalar!  

References

 

Bu yazı için görüş bildiriminde bulunabilirsiniz

Her yazı kendi görüş bildirim sayfasına sahiptir. Bu sayfaya yorumlarınızı yazabilir ve diğer okuyucuların yorumlarına bakabilirsiniz.
 talkback page 

<--, Bu sayının ana sayfasına gider

Görselyöre sayfalarının bakımı, LinuxFocus Editörleri tarafından yapılmaktadır
© Guido Socher, FDL
LinuxFocus.org
Çeviri bilgisi:
en --> -- : Guido Socher (homepage)
en --> tr: İnanç Özçubukçu <inanco(at)atlas.net.tr>

2003-10-10, generated by lfparser version 2.43