Quite las descripciones de las páginas y le quedará una fina capa de estructura que nadie imprime pero de la que dependen todos los lectores, indexadores y sistemas de archivo. Un objeto de página no sabe nada sobre el capítulo al que pertenece, el autor que lo escribió o la nota al pie que vincula a otra parte. Ese conocimiento vive un nivel arriba, en tres estructuras adjuntas al catálogo del documento: los flujos de metadatos, el árbol de esquema y los arreglos de anotaciones por página. Comparten un rasgo que hace que sea fácil equivocarse. Ninguno lleva marcas visibles en la página, por lo que un archivo puede renderizarse perfectamente y seguir sin sus marcadores, contradiciendo su propio campo de autor, o apuntando un enlace a un objeto de página que ya no existe
Esta es la capa que una biblioteca de PDF expone como propiedades de documento, API de marcadores y llamadas de enlaces o anotaciones, y la capa que un rastreador de búsqueda lee para decidir de qué trata su documento. El modelo de objetos debajo de él está cubierto en el recorrido por la estructura del documento PDF. Aquí el enfoque está estrictamente en lo que cuelga del catálogo
Las tres estructuras se adjuntan en el catálogo. Un catálogo completo que las conecta juntas se ve así:
1 0 obj
<< /Type /Catalog
/Pages 2 0 R
/Outlines 3 0 R
/Names << /EmbeddedFiles 4 0 R >>
/Metadata 5 0 R
>>
endobj
Cuatro entradas, cuatro subsistemas independientes. /Pages es el documento visible; /Outlines es el árbol de marcadores; /Metadata apunta al flujo XMP; /Names llega al diccionario de nombres de todo el documento, que entre otras cosas contiene archivos adjuntos incrustados. Cada uno es opcional, y un lector que no encuentra ninguno de ellos aún muestra las páginas. Esa opcionalidad es exactamente el motivo por el cual la capa de navegación es la primera en pudrirse cuando un archivo es editado por herramientas que solo entienden páginas
Dos almacenes de metadatos que discrepan
PDF transporta los metadatos del documento en dos lugares a la vez, y el problema comienza cuando dicen cosas diferentes. El mecanismo original es el diccionario de información del documento, al que se hace referencia mediante /Info en el tráiler: un conjunto plano de pares clave-valor para /Title, /Author, /Subject, /Keywords, /Creator, /Producer y las dos fechas. Es simple y todos los visores lo leen. PDF 2.0 depreca la mayor parte a favor del segundo mecanismo, el flujo de metadatos XMP
XMP es un documento XML autónomo, escrito en RDF, almacenado como un flujo al que el catálogo llega a través de /Metadata y marcado /Type /Metadata /Subtype /XML. A diferencia del diccionario Info enterrado dentro de la estructura de objetos PDF, un paquete XMP está diseñado para ser extraído y analizado por sí solo por herramientas que no saben nada de PDF. Aquí hay un paquete representativo:
5 0 obj
<< /Type /Metadata /Subtype /XML /Length 1235 >>
stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
<dc:title><rdf:Alt><rdf:li xml:lang="x-default">Quarterly Report</rdf:li></rdf:Alt></dc:title>
<dc:creator><rdf:Seq><rdf:li>A. Author</rdf:li></rdf:Seq></dc:creator>
<xmp:CreateDate>2026-06-16T10:46:27+08:00</xmp:CreateDate>
<xmp:CreatorTool>Reporting Service 4.2</xmp:CreatorTool>
<pdf:Producer>losLab PDF Library</pdf:Producer>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
endstream
endobj
Tres detalles en ese bloque deciden si los metadatos sobreviven al contacto con herramientas reales. Las instrucciones de procesamiento de xpacket no son decoración: enmarcan el paquete para que un extractor pueda encontrarlo dentro de un flujo de bytes más grande, y un escritor que omite el <?xpacket end="w"?> final produce un archivo que se abre bien pero hace tropezar a los validadores estrictos. Los tipos de datos de propiedad también importan. dc:title es una alternativa de idioma envuelta en rdf:Alt, mientras que dc:creator es una lista ordenada y toma rdf:Seq; emitir cualquiera de los dos como un nodo de texto simple (bare) es el error XMP más común, tolerado por la mayoría de los visores justo hasta que se encuentra con el que no lo hace. Los prefijos de espacio de nombres son convencionales, pero los URI a los que se vinculan son normativos: un analizador se basa en el URI, no en el prefijo
La regla estricta con dos almacenes es que deben estar de acuerdo. Si /Info dice que el autor es una persona y dc:creator nombra a otra, ha enviado un documento que responde a la misma pregunta de dos maneras, y qué respuesta gana depende de qué campo lee la herramienta que lo consume. Por lo general, una biblioteca escribe ambos por usted, pero en el momento en que edita uno a mano, o combina archivos de diferentes generadores, los dos se separan. Trate el diccionario Info como compatibilidad heredada y XMP como la fuente de la verdad, y regenere ambos a partir de un conjunto de valores en lugar de parchearlos independientemente. Para PDF/A, esto se convierte en un requisito de conformidad: ISO 19005 exige XMP y prohíbe cualquier propiedad Info que contradiga su contraparte XMP
El árbol de esquema detrás del panel de marcadores
Lo que un visor muestra como un panel de marcadores es, en el archivo, un árbol de diccionarios doblemente enlazado llamado el esquema del documento (document outline). El catálogo apunta a un diccionario de esquema raíz a través de /Outlines; la raíz apunta a sus primeros y últimos elementos de nivel superior; y cada elemento está enlazado a sus vecinos y a su elemento padre. No hay un arreglo de marcadores en ninguna parte. Toda la estructura se reconstruye siguiendo referencias, que es precisamente la razón por la que un solo enlace roto puede hacer que toda una rama desaparezca del panel sin ningún error
8 0 obj % the outline root
<< /Type /Outlines /Count 4 /First 9 0 R /Last 9 0 R >>
endobj
9 0 obj % top-level: a chapter
<< /Title (Chapter 1: Results)
/Parent 8 0 R /Count 2
/First 12 0 R /Last 15 0 R >>
endobj
12 0 obj % first child
<< /Title (Introduction)
/Parent 9 0 R /Next 15 0 R
/Dest [3 0 R /XYZ 72 720 0] >>
endobj
15 0 obj % second child, last sibling
<< /Title (Methodology)
/Parent 9 0 R /Prev 12 0 R
/Dest [3 0 R /Fit] >>
endobj
Lea los enlaces y las invariantes se vuelven obvias. Cada elemento apunta de nuevo a su /Parent (padre). Los hermanos forman una cadena a través de /Prev (anterior) y /Next (siguiente), el primer elemento omitiendo /Prev y el último omitiendo /Next. Un padre nombra a sus primer y último hijos a través de /First y /Last, y los hijos intermedios solo son accesibles caminando por la cadena de hermanos. Equivoque uno y la falla es silenciosa: un /Next obsoleto trunca un capítulo, un padre cuyo /Last no termina la cadena deja elementos huérfanos, y el visor renderiza lo que puede alcanzar
El campo /Count contiene un fragmento de estado que sorprende a la gente. En la raíz y en cualquier elemento expandido contiene el número de descendientes actualmente visibles; en un elemento contraído es un número negativo cuya magnitud es cuántos descendientes aparecerían al expandirse. Así que /Count no es un hecho estructural fijo sobre el árbol, es el estado guardado abierto o cerrado del panel, y un generador que lo codifica de forma rígida como un total positivo reabre cada rama que el autor tenía la intención de dejar cerrada
Cada elemento se gana su lugar apuntando a alguna parte. El /Title es lo que muestra el panel; el /Dest (destino) es donde aterriza un clic. Un destino puede estar en línea (inline) en el elemento, como arriba, o un nombre que se resuelve a través del diccionario de nombres del documento, que es la mejor opción cuando muchos marcadores y enlaces apuntan a los mismos lugares, porque usted arregla un objetivo movido en un solo lugar. Una biblioteca generalmente oculta este árbol detrás de un manejador de raíz de esquema y métodos que agregan entradas hijas; en HotPDF, el documento expone un OutlineRoot de tipo THPDFDocOutlineObject y enlaza los vínculos /Prev, /Next, /Parent y /Count por usted a medida que agrega elementos. Vale la pena aprovechar eso, porque mantener manualmente esas invariantes a través de las ediciones es donde se rompen los esquemas
Destinos: la gramática de a dónde va un clic
Tanto los marcadores como las anotaciones de enlace apuntan a destinos, y un destino es más que un número de página. Es un arreglo que nombra un objeto de página y luego especifica, mediante un verbo en la segunda ranura, cómo el visor debería encuadrarlo. El más común y del que más se abusa es /XYZ, de la forma [page /XYZ left top zoom]. Sus tres operandos son independientes, y cualquiera puede ser null para significar "dejar esto como lo tenía el lector". Así que [page /XYZ null null null] salta a la página sin tocar la posición de desplazamiento o el zoom, que es generalmente lo que usted quiere de un enlace de "ir a la página". Los números están en el espacio de usuario predeterminado, medidos desde la parte inferior izquierda con y aumentando hacia arriba, el mismo sistema de coordenadas que usa el contenido de la página. Los autores que llegan del diseño de pantallas miden reflexivamente desde la parte superior y envían al lector al extremo equivocado de la página
La familia /Fit intercambia un posicionamiento preciso por resiliencia. [page /Fit] escala toda la página en la ventana, [page /FitH top] ajusta el ancho de la página con un borde superior dado, y [page /FitR l b r t] hace zoom a un rectángulo para llenar la vista. Debido a que estos calculan la escala a partir de la geometría de la página en lugar de coordenadas fijas, un destino /Fit aún hace lo sensato después de que se cambia el tamaño de la página, mientras que un destino /XYZ con un zoom incorporado puede dejar al lector mirando al margen. Para una tabla de contenido, /FitH con la coordenada superior de la sección envejece mejor que /XYZ con un zoom adivinado
Anotaciones: todo lo interactivo que no es contenido de página
Una anotación es un objeto que se superpone a la página sin ser parte de su flujo de contenido. Enlaces, notas adhesivas, resaltados, widgets de formulario, iconos de archivos adjuntos, sellos: todos son anotaciones, listadas en el arreglo /Annots de la página en la que se encuentran. Eliminar una anotación de ese arreglo la elimina de la página a pesar de que el contenido subyacente está intacto. Ese es el punto principal: las anotaciones son una capa de edición, separada de las marcas sobre las que se asientan
Toda anotación comparte una pequeña columna vertebral. /Subtype nombra el tipo, /Rect da su cuadro delimitador en coordenadas de página y /Contents contiene texto que funciona también como descripción accesible. Vale la pena estudiar la anotación de enlace, porque viene en dos formas: un destino simple (bare) y una acción
12 0 obj % link to a destination
<< /Type /Annot /Subtype /Link
/Rect [100 200 300 250]
/Border [0 0 0]
/Dest [5 0 R /XYZ null null null] >>
endobj
13 0 obj % link that runs an action
<< /Type /Annot /Subtype /Link
/Rect [50 50 200 100]
/Border [0 0 0]
/A << /Type /Action /S /URI /URI (https://www.example.com) >> >>
endobj
El /Rect es un punto de acceso (hotspot); hacer clic dentro de él envía al lector al destino, reutilizando la misma gramática que usa el esquema. El /Border [0 0 0] está haciendo un trabajo real, suprimiendo el feo rectángulo predeterminado que los visores dibujan alrededor de los enlaces. La segunda forma cambia el simple /Dest por una acción /A, cuyo subtipo /S selecciona el comportamiento: /GoTo dentro de este archivo, /GoToR para otro archivo, /URI para una dirección web, /Launch para ejecutar un programa externo. Esa última merece sospecha. Un /Launch que inicia un ejecutable es el comportamiento que hace que los PDF sean un vector de malware, por lo que los visores conformes lo bloquean o preguntan ruidosamente y el enlace falla para la mayoría de los lectores. Recurra a /URI y /GoTo y deje en paz a /Launch
Las anotaciones de marcado, como resaltados y notas adhesivas, y las anotaciones de formas, como /Square, agregan una complicación: su apariencia en pantalla no está implícita en su tipo. Un visor renderiza su propia versión a menos que usted fije la apariencia con un flujo de apariencia, la entrada /AP, que hace referencia a un form XObject que contiene los operadores de dibujo. Omítalo y el mismo resaltado puede verse diferente en dos lectores, o antes y después de un viaje de ida y vuelta a un editor. Para cualquier cosa cuya apariencia exacta sea parte del documento, proporcione el /AP. Los archivos adjuntos, por cierto, reutilizan esta misma maquinaria: un flujo de archivo incrustado y un diccionario de especificación de archivo, expuestos ya sea como una anotación /FileAttachment o a través del árbol de nombres /EmbeddedFiles bajo el /Names del catálogo
Dónde se rompe esta capa y cómo detectarlo
La falla recurrente en todo esto es la referencia colgante (dangling reference). Los marcadores dejan de aparecer cuando el catálogo no tiene una entrada /Outlines o una cadena de hermanos se rompe a mitad del árbol; los metadatos se ignoran cuando el flujo XMP carece de su marca /Type /Metadata /Subtype /XML o la envoltura xpacket está malformada. En cada caso, el contenido de la página está bien, por lo que una apertura casual se ve correcta y el defecto aflora solo en el panel que nadie revisó
Dos hábitos económicos detectan la mayor parte. Abra el archivo terminado en un visor real y haga clic en el panel de marcadores y en una muestra de enlaces, lo cual ejerce el gráfico de referencias de la manera en que lo hará un lector. Luego, lea los metadatos nuevamente con una herramienta separada y confirme que el diccionario Info y el XMP coincidan, el único desacuerdo que ninguna cantidad de clics revela. Genere esta capa a través de una biblioteca que se encargue de la contabilidad de los enlaces y la mayoría de estas trampas nunca se abrirán. El componente HotPDF para Delphi y C++Builder expone las estructuras de esquemas, anotaciones y metadatos a través de API a nivel de documento, de modo que usted describe la jerarquía de marcadores y los enlaces y le permite enlazar las referencias. Para el modelo de objetos al que se adjuntan estas estructuras, la descripción técnica general de la estructura del archivo PDF cubre el catálogo y la tabla de referencias cruzadas de los que dependen