Teknik Makale

Delphi'de PDFium Bileşeni ile XFDF Dışa ve İçe Aktarma

Delphi ve Lazarus için PDFium Bileşeni, form verilerini ve açıklamaları ISO 19444-1 tarafından tanımlanan XML değişim biçimi olan XFDF aracılığıyla aktarır. TPdf.ExportXFDF yüklü belgedeki her form alanı değerini ve desteklenen her açıklamayı bir XFDF dosyasına veya TStream'e serileştirir; TPdf.ImportXFDF bir XFDF belgesini geri okur, sayfalarında açıklamaları yeniden oluşturur ve alan değerlerini uygular. Bu tek gidiş-dönüş, her belge uygulamasının eninde sonunda ihtiyaç duyduğu iki iş akışını kapsar: Bir incelemeci Acrobat'ta bir PDF'i işaretler ve birleştirmeniz için size yorumları postalar veya bir uyumluluk kuralı, form verilerinin PDF'in kendisine pişirilmesi yerine ayrı, karşılaştırılabilir, denetlenebilir bir dosyada yaşaması gerektiğini söyler

PDFium, XFDF içe ve dışa aktarımını destekler mi?

PDFium kütüphanesinin kendisi bunu yapmaz. Yerel C API'sinin hiçbir XFDF veya FDF işlevi yoktur — genel başlıklarında hiçbir formatı okuyan veya yazan bir şey yoktur, bu nedenle sarmalamanın hiçbir miktarı sizi oraya ulaştırmaz. PDFium Bileşeni bu nedenle XFDF motorunun tamamını Pascal'da, doğrudan mevcut TPdf açıklama ve form alanı veri modeli üzerinde XML'i oluşturan ve ayrıştıran özel bir ünitede uygular. Yazar XML'i elle çıkarır ve okuyucu elle yazılmış bir durum makinesi (state-machine) ayrıştırıcısıdır; dolayısıyla bu özellik Delphi XMLDoc veya FPC DOM ünitelerine hiçbir bağımlılık eklemez ve Delphi ile Lazarus'ta tamamen aynı şekilde davranır

Alternatifleri değerlendirdiğinizde bu tasarım seçimi önem kazanır. Pascal'dan ham FPDF_* işlevlerini çağırıyorsanız XFDF bir duvardır: Bu yetenek DLL'de mevcut değildir. Bileşen, XFDF'i saf bir serileştirme problemi olarak ele alarak bu duvarı aşar — sarmalayıcının zaten nasıl okuyacağını bildiği alan değerlerini ve açıklama kayıtlarını toplayın, bunları standart XML olarak yazın ve içe aktarma sırasında işlemi tersine çevirin

Bir XFDF dosyası ne içerir?

ISO 19444-1, XFDF'i FDF'in XML temsili olarak tanımlar ve yükü iki üst düzey bloğa ayrılır. <fields> öğesi hiyerarşik form alanı adlarını ve değerlerini — kullanıcının bir AcroForm'da yazdığı, seçtiği veya işaretlediği her şeyi — taşır. <annots> öğesi açıklamaları taşır: TPdf.ExportXFDF; metin, vurgulama, altı çizili, üstü çizili, dalgalı, çizgi, daire, kare, şapka işareti (caret), çokgen, çoklu çizgi, damga, mürekkep, serbest metin, dosya eki, ses, bağlantı ve karartma olmak üzere 18 alt tür yayar. Widget açıklamaları <annots> içinde kasıtlı olarak bulunmaz çünkü verileri <fields> içinde seyahat eder ve açılır pencere (Popup) gibi görüntüleyiciye özel alt türler XFDF kelime hazinesinin parçası değildir

Gidiş-dönüşü sadık kılmak için TPdfAnnotation kaydı, XFDF'in beklediği meta verilerle genişletildi: Name (NM benzersiz tanımlayıcısı), Subject, ModificationDate, CreationDate, Icon, Opacity, çizgi uç noktaları, çokgen ve çoklu çizgi köşeleri ve mürekkep hareketi (gesture) yolları. Her yeni alan bir Has* boolean nöbetçisi ile eşleşir, böylece önceki sürümlere karşı açıklamalar oluşturan kodlar derlenmeye ve aynı sözlükleri üretmeye devam eder — ayarlanmamış bir alan asla yazılmaz. İşaretlemeyi zaten programlı olarak oluşturuyorsanız, dört noktalı (quad points) metin işaretleme açıklamaları için kullandığınız aynı kayıt artık XFDF'in ihtiyaç duyduğu her şeyi taşır

Form verilerini ve açıklamaları XFDF'e nasıl dışa aktarırsınız?

Tek bir çağrı tüm belgeyi yapar. PDF'i form doldurma etkinleştirilmiş olarak yükleyin, ExportXFDF'i çağırın; bileşen her sayfayı yürür, alan değerlerini ve açıklamaları toplar ve XML'i yazar. Döndürülen değer, yazılan UTF-8 bayt sayısıdır, bu da günlüklerde ucuz bir sağlamlık kontrolü sağlar

var
  Pdf: TPdf;
  Bytes: Integer;
begin
  Pdf := TPdf.Create(Self);
  Pdf.FormFill := True;            // alan değerlerinin canlı olması için gereklidir
  Pdf.FileName := 'expense-report.pdf';
  Pdf.Active := True;
  Bytes := Pdf.ExportXFDF('expense-report.xfdf');
  ShowMessage(Format('%d bayt XFDF yazıldı', [Bytes]));
end;

Her iki yönün de bir TStream aşırı yüklemesi (overload) vardır, bu nedenle hiçbir şey diskte geçici bir dosya zorlamaz. XFDF bir HTTP yanıtına, bir veritabanı bloğuna veya imzalı bir arşiv girişine yöneldiğinde, bir TMemoryStream içine dışa aktarmak en doğal şekildir

var
  Buffer: TMemoryStream;
begin
  Buffer := TMemoryStream.Create;
  try
    Pdf.ExportXFDF(Buffer);        // aynı XML, dosya içermez
    Buffer.Position := 0;
    // akışı bir web yanıtına, blob sütununa veya zip girişine teslim edin
  finally
    Buffer.Free;
  end;
end;

ImportXFDF yorumları belgeye nasıl geri birleştirir?

İçe aktarma tarafı, incelemeci iş akışının kapandığı yerdir. Bir meslektaşınız Acrobat'ta sözleşmeyi açıklar, yorumları XFDF olarak dışa aktarır ve PDF'in ikinci bir kopyası yerine size birkaç kilobaytlık XML gönderir. TPdf.ImportXFDF bu dosyayı ayrıştırır, page özniteliğinin adlandırdığı sayfada her açıklamayı oluşturur ve alan değerlerini eşleşen widget açıklamalarına yazar. İşlev, uygulanan alanlar artı açıklamaların birleşik sayısını döndürür, böylece kullanıcı arayüzü tam olarak ne kadar ulaştığını doğrulayabilir

var
  Applied: Integer;
begin
  Applied := Pdf.ImportXFDF('review-comments.xfdf');
  StatusBar.SimpleText :=
    Format('%d alan ve açıklama birleştirildi', [Applied]);
end;

Ayrıştırıcı, katılık yerine tolerans için oluşturulmuş elle yazılmış bir etiket tarayıcısıdır: Bilinmeyen öğeler atlanır; işleme talimatları, DOCTYPE bildirimleri ve yorumlar yoksayılır, tanınmayan bayrak adları bırakılır ve öznitelik değerleri, UTF-16 surrogate çiftleri de dahil olmak üzere XML varlık ve sayısal karakter referanslarının tam seti üzerinden kaçıştan çıkarılır (unescape). Acrobat, bir web görüntüleyici veya başka bir araç tarafından üretilen XFDF merasim olmaksızın birleşir. Açıklamalar belgeye girdikten sonra, inceleme döngüsü, PDFium Bileşeni ile bir açıklama inceleme iş akışı oluşturma hakkındaki makalede açıklanan yanıt ve durum mekanizmasıyla devam eder ve içe aktarılan alan değerleri, form alanı navigasyonu altında ele alınan normal sekme sırası (tab-order) mantığına katılır

XFDF için ondalık ayırıcılar neden önemlidir?

XFDF'teki her açıklama koordinat dizeleri — rect="70.5,540,200,560" ve benzerleri — ile konumlandırılır ve ISO 19444-1, ondalık ayırıcı olarak nokta gerektirir. Delphi varsayılan ondalık formatı Windows yerel ayarlarını takip eder; bu nedenle bir Alman veya Fransız sisteminde basit bir FloatToStr, 70.5'i 70,5 haline getirir; bu da virgülle ayrılmış bir koordinat listesini diğer işlemcilerin reddettiği veya yanlış okuduğu bir çöpe dönüştürür. PDFium Bileşeni yazdığı her sayyı normalleştirir: Yerel ondalık ayırıcı bir noktaya dönüştürülür ve sondaki sıfırlar kırpılır; böylece dışa aktarılan dosya ister en-US ister de-DE makinesinde üretilmiş olsun bayt bazında özdeştir. Ofiste çalışıp Avrupalı bir müşterinin sitesinde başarısız olan bir PDF aracını ayıkladıysanız, bu tam hata sınıfıyla karşılaşmışsınızdır — bileşenin bunu sizin için hallettiğini bilmek faydalıdır

Gidiş-dönüşün sınırları nelerdir?

İki sınırı açıkça belirtmekte fayda var. İlk olarak, XFDF görünüm akışlarını (appearance streams) değil, açıklama verilerini taşır — görünüm akışları biçimin bir parçası değildir, some zaman alıcı görüntüleyici her açıklama görünümünü kendi özelliklerinden yeniden oluşturur. Bir vurgu veya kare her yerde doğru şekilde işlenir; özel bir görünüme sahip bir damga (stamp), hedef görüntüleyicinin o damga adı için çizdiğine geri döner. İkinci olarak, alttaki PDFium API'sinin dizeler için ayarlayıcıları (setters) vardır ancak açıklama numaraları veya yol geometrisi için yoktur; bu nedenle Opacity, çizgi uç noktaları, köşeler ve mürekkep hareketleri yalnızca dışa aktarılabilir: Bileşen bunları XFDF yazarken sadık bir şekilde korur, ancak içe aktarırken bir PDF'e geri yazamaz. Alan değerleri, içerikler, renkler, dikdörtgenler (rects), dört noktalar (quad points), tarihler ve kimlik meta verilerinin tümü her iki yönde de gidiş-dönüş yapar

Pratik bir başlangıç için, Delphi, C++Builder ve Lazarus demo setlerinde gönderilen XfdfLab örneği, açtığınız herhangi bir PDF üzerinde her iki çağrıyı düğmelere bağlar. XFDF desteği, üzerine inşa edildiği açıklama ve form API'lerinin yanı sıra, PDFium Bileşeni'nin güncel sürümünde yer almaktadır