Hoe te werken met PDF-gegevens in Python
Aspose.PDF FOSS voor Python vertegenwoordigt de XMP-metadata van een PDF-document als een in-memory datamodel opgebouwd uit XmpPacket, XmpField, XmpArray, XmpStruct en XmpProperty objecten, waarbij NamespaceProvider namespace-prefixen naar URI’s resolveert. Hierdoor kun je gestructureerde metadata lezen, opbouwen en herschrijven — titels, data, trefwoordenlijsten, aangepaste velden — zonder handmatig RDF/XML te schrijven. De bibliotheek is pure Python en wordt geïnstalleerd met het onderstaande commando.
Stapsgewijze handleiding
Stap 1: Installeer het pakket
Installeer het Aspose.PDF FOSS-pakket:
git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .Controleer de installatie door XmpPacket te importeren en een bevestigingsbericht af te drukken:
from aspose_pdf import XmpPacket
print("aspose-pdf-foss-for-python is ready.")Stap 2: Vereiste klassen importeren
Importeer de XMP-datamodelklassen en de namespace-resolver:
from aspose_pdf import (
NamespaceProvider,
XmpArray,
XmpField,
XmpPacket,
XmpProperty,
XmpStruct,
)Stap 3: Maak een pakket aan en stel eenvoudige eigenschappen in
XmpPacket() begint met een lege veldlijst. set_value(prefix, name, value, uri=...) stelt een eenvoudige eigenschap in of vervangt deze, en get(prefix_or_uri, name) leest deze terug als een XmpField; get accepteert zowel het geregistreerde prefix als de volledige namespace-URI:
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"Stap 4: Getypte waarden opslaan
XmpPacket biedt getypte gemaktoegangsmethoden die converteren van en naar de platte-tekstvorm die XMP intern opslaat: set_date/get_date, set_int/get_int, set_real/get_real, en set_bool/get_bool. Elke getter retourneert None wanneer de eigenschap afwezig is in plaats van een uitzondering te werpen:
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"))Stap 5: Gelokaliseerde tekst en geordende arrays opslaan
set_localized_text schrijft een taal-alternatief (rdf:Alt) eigenschap zoals dc:title in een specifieke taal, standaard "x-default". set_array schrijft een geordende (Seq), ongeordende (Bag), of alternatieve (Alt) array vanuit een eenvoudige lijst van waarden, en get_array leest deze terug als een lijst van strings:
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"))Stap 6: Gestructureerde waarden bouwen met XmpStruct
Sommige XMP-eigenschappen (dimensie-records, geschiedenis-items) zijn gestructureerde waarden in plaats van eenvoudige tekst. Bouw er één met XmpStruct, voeg lid XmpField objecten toe met add, en lees een lid terug op naam met get, waarna je de struct aan het pakket koppelt met 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))Stap 7: Aangepaste XMP-naamruimtes registreren
NamespaceProvider wordt vooraf geladen met de standaard XMP-naamruimtes (Dublin Core, Adobe XMP, PDF en andere). Roep register(prefix, uri) aan om een aangepaste mapping toe te voegen — het retourneert de provider zelf zodat aanroepen kunnen worden gekoppeld — en koppel vervolgens de provider aan een pakket zodat serialisatie de aangepaste prefix kan omzetten naar de URI:
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")Stap 8: Een pakket parseren en serialiseren
XmpPacket.parse(data, provider=...) leest ruwe XMP-pakketbytes of tekst in een XmpPacket. serialize() en to_bytes() renderen beide het pakket terug naar XMP-pakketbytes:
xmp_bytes = packet.to_bytes()
restored = XmpPacket.parse(xmp_bytes)
print(restored.get("dc", "title").value)Veelvoorkomende problemen en oplossingen
get() of een getypte getter retourneert None ondanks dat ik net de property heb ingesteld
Bevestig dat het prefix (of URI) argument voor get/get_int/get_date/etc. exact overeenkomt met wat werd doorgegeven aan de overeenkomstige set_*-aanroep — get controleert zowel het voorvoegsel van het veld als de namespace-URI, maar een niet-overeenkomend aangepast voorvoegsel in de ene aanroep en een URI in de andere zal mislukken.
Aangepast namespace-voorvoegsel produceert onvolledige output bij serialisatie
Een voorvoegsel dat niet tot de standaard XMP-namespaces behoort (dc, xmp, pdf en soortgelijke) vereist ofwel een expliciet uri= argument bij elke set_*-aanroep, of een NamespaceProvider waarbij dat voorvoegsel is geregistreerd en aan het pakket is gekoppeld via XmpPacket(namespace_provider=provider) voordat serialize()/to_bytes() wordt aangeroepen.
get_bool, get_int, of get_real returns None voor een waarde waarvan ik weet dat die is ingesteld
Deze getypte getters retourneren None wanneer de opgeslagen tekst niet kan worden geparseerd als het verwachte type — bijvoorbeeld get_int op een eigenschap waarvan de waarde is ingesteld met set_value als vrije-tekst in plaats van set_int. Gebruik de bijbehorende getypte setter (set_int, set_real, set_bool) zodat de parse-logica van de getter overeenkomt met het schrijfpad.
XmpPacket.parse raises ValueError op een packet van een niet-vertrouwde bron
parse wijst elke <!DOCTYPE of <!ENTITY declaratie af als een hostiele-invoergarde tegen XXE- en billion-laughs-aanvallen. Een legitiem XMP-pakket heeft nooit een DTD nodig; beschouw de uitzondering als een signaal dat de bronstroom malformed of onveilig is in plaats van de garde te omzeilen.
get_array returns None in plaats van een lijst
get_array retourneert None wanneer de benoemde eigenschap niet bestaat of niet is opgeslagen als een XmpArray (bijvoorbeeld, als deze is ingesteld met set_value in plaats van set_array). Gebruik set_array bij het schrijven van de eigenschap zodat de opgeslagen waarde overeenkomt met de vorm die get_array verwacht.
Veelgestelde vragen
Wat is het verschil tussen set_value en de getypte setters zoals set_int?
set_value slaat alles wat value je doorgeeft onveranderd op. De getypte setters (set_date, set_int, set_real, set_bool) zetten hun invoer om naar de platte-tekst vorm die XMP intern gebruikt en gaan gepaard met een overeenkomstige getypte getter die het weer parseert, dus gebruik ze wanneer je round-trip type-veiligheid nodig hebt in plaats van ruwe strings.
Hoe verschillen de XmpArray soorten (Bag, Seq, Alt)?
Bag is een ongeordende verzameling waarden, Seq is een geordende lijst, en Alt bevat alternatieve waarden (meestal taalvarianten, zoals gebruikt door set_localized_text). Geef het gewenste type door aan set_array(..., kind="Bag") of bouw direct een XmpArray(kind=...).
Kan ik de ruwe lijst van eigenschappen op een packet lezen zonder hun namen van tevoren te kennen?
Ja — doorloop packet.fields, die elke XmpField, XmpArray en XmpProperty bevat die in de volgorde van invoeging aan het pakket zijn toegevoegd.
Heb ik een NamespaceProvider nodig voor de standaard XMP-namespaces?
Nee. dc, xmp, pdf en de andere standaardprefixen worden automatisch opgelost. Een NamespaceProvider is alleen nodig voor aangepaste prefixen die je zelf bedenkt.
Hoe verschillen XmpProperty kwalificaties van een gewone XmpField?
XmpProperty wikkelt een basis XmpField samen met een lijst van kwalificatievelden (toegevoegd met add_qualifier), gebruikt voor het minder voorkomende geval waarin een eigenschap zelf extra RDF-metadata nodig heeft die aan de waarde wordt gekoppeld, naast de xml:lang kwalificatie die XmpField.language al dekt.