Skip to content

Metadatos y XMP

PDF Oxide lee los metadatos a nivel de documento desde múltiples fuentes: la cabecera del PDF (versión), los diccionarios trailer y catalog, los flujos de metadatos XMP (ISO 16684) y las definiciones de etiquetas de página. El XmpExtractor analiza los namespaces de Dublin Core, XMP Core, PDF y XMP Rights, además de cualquier propiedad personalizada.

Usa version() y catalog() para las propiedades básicas del documento, XmpExtractor::extract() para los metadatos enriquecidos y PageLabelExtractor para los esquemas de numeración de páginas.

Ejemplo rápido

Python

from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")
major, minor = doc.version()
print(f"PDF {major}.{minor}, {doc.page_count()} pages")

Node.js

const { PdfDocument } = require("pdf-oxide");

const doc = new PdfDocument("report.pdf");
const { major, minor } = doc.getVersion();
console.log(`PDF ${major}.${minor}, ${doc.pageCount()} pages`);
doc.close();

Go

import pdfoxide "github.com/yfedoseev/pdf_oxide/go"

doc, _ := pdfoxide.Open("report.pdf")
defer doc.Close()
major, minor, _ := doc.Version()
pages, _ := doc.PageCount()
fmt.Printf("PDF %d.%d, %d pages\n", major, minor, pages)

C#

using PdfOxide.Core;

using var doc = PdfDocument.Open("report.pdf");
var (major, minor) = doc.Version;
Console.WriteLine($"PDF {major}.{minor}, {doc.PageCount} pages");

WASM

const doc = new WasmPdfDocument(bytes);
const version = doc.version();
console.log(`PDF ${version}, ${doc.pageCount()} pages`);

Rust

use pdf_oxide::PdfDocument;

let mut doc = PdfDocument::open("report.pdf")?;
let (major, minor) = doc.version();
println!("PDF {}.{}", major, minor);
println!("Pages: {}", doc.page_count()?);

Referencia de API

version() -> (u8, u8)

Obtiene la versión del PDF a partir de la cabecera del archivo.

Devuelve: Una tupla de (major, minor), p. ej., (1, 7) para PDF 1.7 o (2, 0) para PDF 2.0.


catalog() -> Result<Object>

Obtiene el diccionario catalog del documento. El catalog es la raíz de la jerarquía de objetos del PDF y contiene referencias al árbol de páginas, los marcadores (outlines), los nombres y otras estructuras a nivel de documento.

Rust

let mut doc = PdfDocument::open("report.pdf")?;
let catalog = doc.catalog()?;
if let Some(dict) = catalog.as_dict() {
    for (key, _) in dict {
        println!("Catalog key: {}", key);
    }
}

trailer() -> &Object

Obtiene el diccionario trailer del documento. El trailer contiene la ubicación de la tabla de referencias cruzadas, el ID del documento, la referencia al diccionario de cifrado y la referencia al diccionario info.

Rust

let doc = PdfDocument::open("report.pdf")?;
let trailer = doc.trailer();
println!("Trailer: {:?}", trailer);

XmpExtractor::extract(doc) -> Result<Option<XmpMetadata>>

Extrae los metadatos XMP (Extensible Metadata Platform) del flujo de metadatos del documento. XMP proporciona metadatos más ricos que el diccionario Info tradicional, usando namespaces XML estándar.

Parámetro Tipo Descripción
doc &mut PdfDocument El documento PDF

Devuelve: Some(XmpMetadata) si hay datos XMP presentes, None en caso contrario.

Campos de XmpMetadata

Namespace Dublin Core (dc:)

Campo Tipo Descripción
dc_title Option<String> Título del documento
dc_creator Vec<String> Lista de autores/creadores
dc_description Option<String> Descripción del documento
dc_subject Vec<String> Palabras clave del tema
dc_language Option<String> Idioma del documento (p. ej., "en-US")
dc_rights Option<String> Declaración de copyright
dc_format Option<String> Formato MIME (p. ej., "application/pdf")

Namespace XMP Core (xmp:)

Campo Tipo Descripción
xmp_creator_tool Option<String> Herramienta usada para crear el documento
xmp_create_date Option<String> Fecha de creación (ISO 8601)
xmp_modify_date Option<String> Fecha de última modificación
xmp_metadata_date Option<String> Fecha de modificación de los metadatos

Namespace PDF (pdf:)

Campo Tipo Descripción
pdf_producer Option<String> Aplicación productora del PDF
pdf_keywords Option<String> Cadena de palabras clave
pdf_version Option<String> Versión del PDF según XMP (puede diferir de la cabecera)
pdf_trapped Option<String> Estado de trapping

Namespace XMP Rights (xmpRights:)

Campo Tipo Descripción
xmp_rights_usage_terms Option<String> Términos de uso
xmp_rights_marked Option<bool> Si está marcado con derechos
xmp_rights_web_statement Option<String> URL de la declaración web

Otros

Campo Tipo Descripción
custom HashMap<String, String> Propiedades personalizadas (namespace:propiedad a valor)
raw_xml Option<String> El paquete XML XMP original

Rust

use pdf_oxide::extractors::xmp::XmpExtractor;

let mut doc = PdfDocument::open("report.pdf")?;
if let Some(xmp) = XmpExtractor::extract(&mut doc)? {
    if let Some(title) = &xmp.dc_title {
        println!("Title: {}", title);
    }
    for creator in &xmp.dc_creator {
        println!("Author: {}", creator);
    }
    if let Some(tool) = &xmp.xmp_creator_tool {
        println!("Created with: {}", tool);
    }
    if let Some(date) = &xmp.xmp_create_date {
        println!("Created: {}", date);
    }
    if let Some(producer) = &xmp.pdf_producer {
        println!("Producer: {}", producer);
    }
}

WASM

const doc = new WasmPdfDocument(bytes);
const xmp = doc.xmpMetadata();

if (xmp) {
  console.log(`Title: ${xmp.dc_title}`);
  console.log(`Authors: ${xmp.dc_creator}`);
  console.log(`Created with: ${xmp.xmp_creator_tool}`);
  console.log(`Created: ${xmp.xmp_create_date}`);
  console.log(`Producer: ${xmp.pdf_producer}`);
}
doc.free();

Python

doc = PdfDocument("report.pdf")
xmp = doc.xmp_metadata()

if xmp:
    print(f"Title: {xmp.get('dc_title')}")
    print(f"Authors: {xmp.get('dc_creator')}")
    print(f"Created with: {xmp.get('xmp_creator_tool')}")
    print(f"Created: {xmp.get('xmp_create_date')}")
    print(f"Producer: {xmp.get('pdf_producer')}")

<!-- Node.js: no equivalent on PdfDocumentImpl — xmp metadata not exposed in js/src/index.ts -->

Go

doc, _ := pdfoxide.Open("report.pdf")
defer doc.Close()
xmp, _ := doc.XmpMetadata() // returns JSON string
fmt.Println(xmp)

C#

using var doc = PdfDocument.Open("report.pdf");
var xmp = doc.GetXmpMetadata(); // returns JSON string
Console.WriteLine(xmp);

Métodos de conveniencia de Pdf

La API de alto nivel Pdf proporciona métodos abreviados para las consultas de metadatos más habituales.

xmp_metadata() -> Result<Option<XmpMetadata>>

Obtiene el objeto completo de metadatos XMP.

xmp_title() -> Result<Option<String>>

Obtiene solo el título del documento desde XMP.

xmp_creators() -> Result<Vec<String>>

Obtiene la lista de creadores/autores desde XMP.

Rust

use pdf_oxide::api::Pdf;

let mut pdf = Pdf::open("report.pdf")?;

if let Some(title) = pdf.xmp_title()? {
    println!("Title: {}", title);
}

let creators = pdf.xmp_creators()?;
for creator in &creators {
    println!("Author: {}", creator);
}

PageLabelExtractor::extract(doc) -> Result<Vec<PageLabelRange>>

Extrae las definiciones de etiquetas de página del documento. Las etiquetas de página definen cómo se muestran los números de página (p. ej., números romanos para las páginas preliminares, números arábigos para el cuerpo).

Parámetro Tipo Descripción
doc &mut PdfDocument El documento PDF

Devuelve: Un vector de definiciones PageLabelRange.

Campos de PageLabelRange

Campo Tipo Descripción
start_page usize Primer índice de página al que se aplica este rango
style PageLabelStyle Estilo de numeración
prefix Option<String> Cadena de prefijo de la etiqueta
start_number u32 Número inicial de este rango

Variantes de PageLabelStyle

Variante Descripción Ejemplo
DecimalArabic Números arábigos 1, 2, 3
UppercaseRoman Romanos en mayúscula I, II, III
LowercaseRoman Romanos en minúscula i, ii, iii
UppercaseLetters Letras mayúsculas A, B, C
LowercaseLetters Letras minúsculas a, b, c
None Sin numeración (solo prefijo)

Métodos de conveniencia de etiquetas de página de Pdf

page_labels() -> Result<Vec<PageLabelRange>>

Obtiene todas las definiciones de rangos de etiquetas de página.

page_label(page) -> Result<String>

Obtiene la etiqueta visible para un índice de página específico.

Rust

use pdf_oxide::api::Pdf;

let mut pdf = Pdf::open("book.pdf")?;

// Get all label ranges
let ranges = pdf.page_labels()?;
for range in &ranges {
    println!(
        "Pages from {}: {:?} style, prefix={:?}, start={}",
        range.start_page, range.style, range.prefix, range.start_number
    );
}

// Get label for a specific page
let label = pdf.page_label(0)?;
println!("Page 0 label: {}", label); // e.g., "i" or "Cover"

WASM

const doc = new WasmPdfDocument(bytes);
const labels = doc.pageLabels();

for (const range of labels) {
  console.log(`Pages from ${range.start_page}: style=${range.style}, prefix=${range.prefix}`);
}
doc.free();

Python

doc = PdfDocument("book.pdf")
labels = doc.page_labels()

for range in labels:
    print(f"Pages from {range['start_page']}: style={range['style']}, prefix={range['prefix']}")

<!-- Node.js: no equivalent on PdfDocumentImpl — pageLabels not exposed on class, only via properties mixin -->

Go

doc, _ := pdfoxide.Open("book.pdf")
defer doc.Close()
labels, _ := doc.PageLabels() // returns JSON string
fmt.Println(labels)

C#

using var doc = PdfDocument.Open("book.pdf");
var labels = doc.GetPageLabels(); // returns JSON string
Console.WriteLine(labels);

Ejemplos avanzados

Mostrar los metadatos completos del documento

use pdf_oxide::PdfDocument;
use pdf_oxide::extractors::xmp::XmpExtractor;

let mut doc = PdfDocument::open("report.pdf")?;

// Basic info
let (major, minor) = doc.version();
println!("PDF Version: {}.{}", major, minor);
println!("Pages: {}", doc.page_count()?);

// XMP metadata
if let Some(xmp) = XmpExtractor::extract(&mut doc)? {
    println!("\nXMP Metadata:");
    println!("  Title:       {:?}", xmp.dc_title);
    println!("  Authors:     {:?}", xmp.dc_creator);
    println!("  Description: {:?}", xmp.dc_description);
    println!("  Keywords:    {:?}", xmp.pdf_keywords);
    println!("  Creator:     {:?}", xmp.xmp_creator_tool);
    println!("  Producer:    {:?}", xmp.pdf_producer);
    println!("  Created:     {:?}", xmp.xmp_create_date);
    println!("  Modified:    {:?}", xmp.xmp_modify_date);
    println!("  Language:    {:?}", xmp.dc_language);
    println!("  Rights:      {:?}", xmp.dc_rights);

    if !xmp.custom.is_empty() {
        println!("\n  Custom properties:");
        for (key, value) in &xmp.custom {
            println!("    {}: {}", key, value);
        }
    }
}

Acceder al XML XMP sin procesar

use pdf_oxide::extractors::xmp::XmpExtractor;

let mut doc = PdfDocument::open("report.pdf")?;
if let Some(xmp) = XmpExtractor::extract(&mut doc)? {
    if let Some(xml) = &xmp.raw_xml {
        std::fs::write("metadata.xml", xml)?;
        println!("Raw XMP saved ({} bytes)", xml.len());
    }
}

Generar las cadenas visibles de numeración de páginas

use pdf_oxide::api::Pdf;

let mut pdf = Pdf::open("thesis.pdf")?;
let page_count = pdf.page_count()?;

for i in 0..page_count {
    let label = pdf.page_label(i)?;
    println!("Physical page {} -> display label '{}'", i + 1, label);
}
// Example output:
//   Physical page 1 -> display label 'i'
//   Physical page 2 -> display label 'ii'
//   Physical page 3 -> display label 'iii'
//   Physical page 4 -> display label '1'
//   Physical page 5 -> display label '2'

Páginas relacionadas