Cum să lucrați cu date PDF în Python
Aspose.PDF FOSS pentru Python reprezintă metadatele XMP ale unui document PDF ca un model de date în memorie construit din obiecte XmpPacket, XmpField, XmpArray, XmpStruct și XmpProperty, cu NamespaceProvider care rezolvă prefixele de spațiu de nume la URI-uri. Acest lucru vă permite să citiți, să construiți și să rescrieți metadatele structurate — titluri, date, liste de cuvinte cheie, câmpuri personalizate — fără a scrie manual RDF/XML. Biblioteca este pur Python și se instalează cu comanda de mai jos.
Ghid pas cu pas
Pasul 1: Instalați pachetul
Instalați pachetul Aspose.PDF FOSS:
git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .Verificați instalarea importând XmpPacket și afișând un mesaj de confirmare:
from aspose_pdf import XmpPacket
print("aspose-pdf-foss-for-python is ready.")Pasul 2: Importă clasele necesare
Importă clasele modelului de date XMP și rezolvatorul de spațiu de nume:
from aspose_pdf import (
NamespaceProvider,
XmpArray,
XmpField,
XmpPacket,
XmpProperty,
XmpStruct,
)Pasul 3: Creează un pachet și setează proprietăți simple
XmpPacket() începe cu o listă de câmpuri goală. set_value(prefix, name, value, uri=...) setează sau înlocuiește o proprietate simplă, iar get(prefix_or_uri, name) o citește înapoi ca un XmpField; get acceptă fie prefixul înregistrat, fie URI-ul complet al spațiului de nume:
from aspose_pdf import XmpPacket
packet = XmpPacket()
packet.set_value("dc", "title", "Quarterly Report")
packet.set_value(
"dc", "creator", "Automation Pipeline",
uri="http://purl.org/dc/elements/1.1/",
)
title_field = packet.get("dc", "title")
print(title_field.value) # "Quarterly Report"Pasul 4: Stochează valori tipizate
XmpPacket furnizează accesori convenabili tipizați care convertesc către și din forma text simplu pe care XMP o stochează intern: set_date/get_date, set_int/get_int, set_real/get_real și set_bool/get_bool. Fiecare getter returnează None când proprietatea este absentă în loc să arunce:
from datetime import datetime
packet.set_date("xmp", "CreateDate", datetime(2026, 7, 29, 9, 30))
packet.set_int("pdf", "PageCount", 42)
packet.set_real("custom", "ConfidenceScore", 0.97, uri="https://example.com/ns/custom/1.0/")
packet.set_bool("custom", "IsFinal", True, uri="https://example.com/ns/custom/1.0/")
print(packet.get_date("xmp", "CreateDate"))
print(packet.get_int("pdf", "PageCount"))
print(packet.get_real("custom", "ConfidenceScore"))
print(packet.get_bool("custom", "IsFinal"))Pasul 5: Stochează text localizat și tablouri ordonate
set_localized_text scrie o proprietate alternativă pe limbă (rdf:Alt) cum ar fi dc:title într-o limbă specifică, implicit "x-default". set_array scrie un tablou ordonat (Seq), neordonat (Bag) sau alternativ (Alt) dintr-o listă simplă de valori, iar get_array îl citește înapoi ca o listă de șiruri:
packet.set_localized_text("dc", "description", "Quarterly summary", lang="en")
packet.set_localized_text(
"dc", "description", "Resumen trimestral",
uri="http://purl.org/dc/elements/1.1/", lang="es",
)
print(packet.get_localized_text("dc", "description", lang="es"))
packet.set_array("dc", "subject", ["finance", "quarterly", "internal"], kind="Bag")
print(packet.get_array("dc", "subject"))Pasul 6: Construiește valori structurate cu XmpStruct
Unele proprietăți XMP (înregistrări de dimensiune, intrări de istoric) sunt valori structurate în loc de text simplu. Construiește una cu XmpStruct, adaugă obiecte membru XmpField cu add, și citește un membru înapoi după nume cu get, apoi atașează structura la pachet cu add:
dimensions = XmpStruct()
dimensions.add(XmpField(prefix="stDim", name="w", value="612"))
dimensions.add(XmpField(prefix="stDim", name="h", value="792"))
dimensions.add(XmpField(prefix="stDim", name="unit", value="pt"))
print(dimensions.get("w").value) # "612"
packet.add(XmpField(prefix="xmpTPg", name="MaxPageSize", value=dimensions))Pasul 7: Înregistrează spații de nume XMP personalizate
NamespaceProvider este preîncărcat cu spațiile de nume XMP standard (Dublin Core, Adobe XMP, PDF și altele). Apelează register(prefix, uri) pentru a adăuga o mapare personalizată — returnează furnizorul însuși, astfel încât apelurile să poată fi înlănțuite — apoi atașează furnizorul la un pachet pentru ca serializarea să poată rezolva prefixul personalizat la URI-ul său:
from aspose_pdf import NamespaceProvider, XmpPacket
provider = NamespaceProvider()
provider.register("custom", "https://example.com/ns/custom/1.0/")
packet = XmpPacket(namespace_provider=provider)
packet.set_value("custom", "batch_id", "run-2026-07-29")Pasul 8: Analizează și serializează un pachet
XmpPacket.parse(data, provider=...) citește octeți brut de pachet XMP sau text într-un XmpPacket. serialize() și to_bytes() ambele redau pachetul înapoi în octeți de pachet XMP:
xmp_bytes = packet.to_bytes()
restored = XmpPacket.parse(xmp_bytes)
print(restored.get("dc", "title").value)Probleme comune și soluții
get() sau un getter tipizat returnează None chiar dacă tocmai am setat proprietatea
Confirmați că argumentul prefix (sau URI) pentru get/get_int/get_date/etc. se potrivește exact cu ceea ce a fost transmis apelului set_* corespunzător — get se potrivește atât cu prefixul câmpului, cât și cu URI-ul spațiului de nume, dar un prefix personalizat necorespunzător într-un apel și un URI în celălalt vor duce la nepotrivire.
Prefixul de spațiu de nume personalizat produce ieșire incompletă la serializare
Un prefix care nu este unul dintre spațiile de nume XMP standard (dc, xmp, pdf și altele) necesită fie un argument uri= explicit la fiecare apel set_*, fie un NamespaceProvider cu acel prefix înregistrat și atașat pachetului prin XmpPacket(namespace_provider=provider) înainte de a apela serialize()/to_bytes().
get_bool, get_int, sau get_real returns None pentru o valoare pe care știu că este setată
Acești getteri tipați returnează None când textul stocat nu se poate analiza ca tipul așteptat — de exemplu, get_int pe o proprietate al cărei valoare a fost setată cu set_value ca text liber în loc de set_int. Folosiți setterul tipat corespunzător (set_int, set_real, set_bool) astfel încât logica de analiză a getterului să corespundă căii de scriere.
XmpPacket.parse raises ValueError pe un pachet provenit dintr-o sursă neîncrezătoare
parse respinge orice declarație <!DOCTYPE sau <!ENTITY ca o protecție împotriva intrărilor ostile împotriva atacurilor XXE și billion-laughs. Un pachet XMP legitim nu are niciodată nevoie de un DTD; tratați excepția ca un semnal că fluxul sursă este defect sau nesigur, în loc să ocoliți protecția.
get_array returns None în loc de o listă
get_array returnează None când proprietatea numită fie nu există, fie nu a fost stocată ca un XmpArray (de exemplu, dacă a fost setată cu set_value în loc de set_array). Folosește set_array când scrii proprietatea astfel încât valoarea stocată să corespundă formei pe care get_array o așteaptă.
Întrebări frecvente
Care este diferența dintre set_value și setter-ele tipizate precum set_int?
set_value stochează orice value îi transmiți așa cum este. Setter-ele tipizate (set_date, set_int, set_real, set_bool) își convertesc intrarea în forma de text simplu pe care XMP o folosește intern și se asociază cu un getter tipizat corespunzător care o parsează înapoi, așa că folosește-le când ai nevoie de siguranță tipică pe parcursul întregului ciclu în loc de șiruri brute.
Cum diferă tipurile de XmpArray (Bag, Seq, Alt)?
Bag este un set neordonat de valori, Seq este o listă ordonată, iar Alt conține valori alternative (cel mai adesea alternative de limbă, așa cum este utilizat de set_localized_text). Transmite tipul dorit către set_array(..., kind="Bag") sau construiește un XmpArray(kind=...) direct.
Pot să citesc lista brută de proprietăți dintr-un pachet fără să cunosc în prealabil numele lor?
Da — iterează packet.fields, care conține fiecare XmpField, XmpArray și XmpProperty adăugat la pachet în ordinea inserării.
Am nevoie de un NamespaceProvider pentru spațiile de nume XMP standard?
Nu. dc, xmp, pdf și celelalte prefixe standard se rezolvă automat. Un NamespaceProvider este necesar doar pentru prefixele personalizate pe care le inventezi tu.
Cum diferă calificativele XmpProperty de un simplu XmpField?
XmpProperty înfășoară un XmpField de bază împreună cu o listă de câmpuri calificative (adăugate cu add_qualifier), utilizată pentru cazul mai rar în care o proprietate are nevoie de metadate RDF suplimentare atașate valorii sale, dincolo de calificativul xml:lang pe care XmpField.language îl acoperă deja.