kumandur
Eğer ilgilenirseniz, Chatgpt (O3 Pro) ile Cevaplanmıştır.
Aşağıdaki yol haritası, e-Arşiv fatura PDF’sinden (PDF 🔗 XML ekli biçim)¹ bilgileri C# ile çekip bir DataGridView’de göstermenizi adım adım gösterir.
1 | e-Arşiv PDF’sinde sizi bekleyen veri
- Gelir İdaresi Başkanlığı’nın teknik kılavuzları ve pek çok entegratör (QNB eFinans vb.) e-Arşiv faturayı “PDF (UBL Ekli)” veya “PDF (Özel XML Ekli)” biçiminde üretir. Yani PDF içinde dosya eki olarak UBL-TR 1.2 ya da özelleştirilmiş XML mutlaka gömülüdür.(qnbefinans.com)
- Bu XML, PDF’teki görsel düzenle bire bir eşleşir; dolayısıyla metni OCR’la tanımaya çalışmak yerine XML’i çıkarmak en temiz yoldur.
2 | Genel akış
| Adım | Ne yapıyoruz? | Kullanılabilecek NuGet paketi |
| ---- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- |
| 1 | PDF’i aç, ekli dosyaları tara | iText 7 (AGPL → ticari projede lisans gerek) veya UglyToad.PdfPig (MIT) |
| 2 | .xml
ya da .ubl
uzantılı eki belleğe al | PdfDocument.GetCatalog().GetNameTree(PdfName.EmbeddedFiles)
|
| 3 | XML’i LINQ to XML ile parse et | System.Xml.Linq
|
| 4 | Alanları (Tarih, Senaryo, VKN/TCKN, Matrah, KDV, Genel Toplam…) model sınıfına aktar | class InvoiceInfo { … }
|
| 5 | Listeyi DataGridView.DataSource
’a bağla | BindingList<InvoiceInfo>
|
3 | Çalışan örnek kod
Not: iText 7 Community kullanıldı; AGPL lisansı gerektirir. Ticari/kapalı kaynakta IronPDF, Aspose, PdfPig gibi alternatifler düşünün.
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Navigation;
using iText.Kernel.Pdf.Filespec;
using System.Xml.Linq;
using System.ComponentModel;
using System.Windows.Forms;
// -----------------------------------------------------
// 0) Basit POCO — DataGridView bunun kolonlarını kullanır
// -----------------------------------------------------
public class InvoiceInfo
{
public string FaturaNo { get; set; }
public DateTime Tarih { get; set; }
public string Unvan { get; set; }
public decimal GenelToplam { get; set; }
}
// -----------------------------------------------------
// 1) PDF’ten XML’i çıkaran metod
// -----------------------------------------------------
static byte[] ExtractEmbeddedXml(string pdfPath)
{
using var pdf = new PdfDocument(new PdfReader(pdfPath));
var names = PdfNameTree.GetNames(pdf.GetCatalog(), PdfName.EmbeddedFiles);
foreach (var kvp in names)
{
if (kvp.Key.EndsWith(".xml", StringComparison.OrdinalIgnoreCase) ||
kvp.Key.EndsWith(".ubl", StringComparison.OrdinalIgnoreCase))
{
var fs = PdfFileSpec.Wrap((PdfDictionary)kvp.Value);
return fs.GetEmbeddedFile().GetBytes();
}
}
throw new InvalidOperationException("XML eki bulunamadı.");
}
// -----------------------------------------------------
// 2) XML’i parse edip ekrana bağlama
// -----------------------------------------------------
void LoadInvoice(string pdfPath, DataGridView dgv)
{
var xmlBytes = ExtractEmbeddedXml(pdfPath);
var doc = XDocument.Parse(System.Text.Encoding.UTF8.GetString(xmlBytes));
XNamespace cbc = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2";
XNamespace cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2";
var info = new InvoiceInfo
{
FaturaNo = doc.Root.Element(cbc + "ID")?.Value,
Tarih = DateTime.Parse(doc.Root.Element(cbc + "IssueDate")?.Value ?? DateTime.MinValue.ToString()),
Unvan = doc.Root.Element(cac + "AccountingSupplierParty")
?.Element(cac + "Party")
?.Element(cac + "PartyName")
?.Element(cbc + "Name")?.Value,
GenelToplam = decimal.Parse(doc.Root
.Element(cac + "LegalMonetaryTotal")
?.Element(cbc + "PayableAmount")?.Value ?? "0",
System.Globalization.CultureInfo.InvariantCulture)
};
dgv.DataSource = new BindingList<InvoiceInfo> { info };
}
Kullanım
private void btnYükle_Click(object sender, EventArgs e)
{
using var ofd = new OpenFileDialog { Filter = "e-Arşiv PDF|*.pdf" };
if (ofd.ShowDialog() == DialogResult.OK)
LoadInvoice(ofd.FileName, dataGridView1);
}
4 | Karşılaşabileceğiniz “sürprizler”
| Durum | Çözüm |
| ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Entegratör XML’i zip’lemiş olabilir (.zip
) | .zip
ekini çıkarıp içindeki XML’i açın (System.IO.Compression
) |
| Bazı PDF’ler imzalı (PAdES) olabilir; iText okurken “signature invalid” uyarısı verir | PDF’i kopya olarak açıp PdfReader
’ı new ReaderProperties().SetIgnoreXfa(true)
ile başlatın |
| XML ad alanı farklı (cac-cbc prefix’leri yok
) | LINQ to XML’de XName.Get("ID", doc.Root.GetDefaultNamespace().NamespaceName)
kullanın |
| AGPL lisans sıkıntı | PdfPig ile PdfDocument.GetEmbeddedFiles()
veya ücretli IronPDF kullanın |
5 | Alternatif – “Koordinat” yaklaşımı (zorunlu kalırsanız)
XML hiç gömülmemişse (nadir):
- PdfPig ile tüm metni, istemiyorsanız da sayfadaki
WordLocation
koleksiyonlarını çekin.
- “FATURA NO”, “TARİH” metinlerinin x-y koordinatlarını referans alıp yan/alt metni okuyun.
- Düzen entegratörden entegratöre değiştiği için kod bakımı zordur; bu nedenle XML içermeyen PDF’leri entegratörünüzden talep edin.
6 | Özet
- En pratik yol: PDF içindeki UBL-TR XML ekini çıkarmak.
- iText 7 + LINQ to XML birkaç satırlık kodla tarih, unvan, tutar gibi bilgileri rahatça DataGridView’e bağlar.
- XML yoksa metin koordinatları ya da entegratör web-servisinden çekme opsiyonlarını düşünün.
Deneyip takıldığınız noktayı (hata mesajı, sample PDF) paylaşırsanız doğrudan o parçayı birlikte debug edebiliriz. Kolay gelsin!
¹ “Yüklenen Dosya Formatı: ‘UBL / CSXML / Özel XML / PDF (UBL Ekli) / …” (GİB — QNB eFinans e-Arşiv Kullanım Kılavuzu).(qnbefinans.com)
² iText 7’de ek dosya çıkarmaya dair temel örnek (Stack Overflow).(stackoverflow.com)