Create a new CatalogElement.




CatalogElement(Atom atom, IndirectObject host)
CatalogElement(IndirectObject obj)
CatalogElement(Element relation, CreationOptions options)

[Visual Basic]
CatalogElement(atom As Atom, host As IndirectObject)
CatalogElement(obj As IndirectObject)
CatalogElement(relation As Element, options As CreationOptions)



Name Description
atom The Atom to be assigned to this Element.
host An IndirectObject. This can be any IndirectObject from the Soup but ideally should be one closely associated with the Atom.
obj The IndirectObject to be assigned to this Element.
relation An Element. This can be any Element in the Soup but ideally should be one closely associated with this Element.
options Options related to creation. For example this allows you to determine whether the Element should be created using an IndirectObject rather than just an Atom. If not provided a default set of options is used.




Create a new CatalogElement.

The different constructors allow different ways of creating an Element. Some are used for wrapping existing Atoms or IndirectObjects and others are for creating new ones.

The constructor taking a relation Element creates a new object in the document - it is typically the constructor you will want to use. Do not specify creation options unless you have very specific needs.

However for your first Element - one you can use as a relation for the others - you will need to wrap an existing IndirectObject inside an Element. For this you might use code of the following form "CatalogElement root = new CatalogElement(doc.ObjectSoup.Catalog)".

The parameterless constructor allows you to create an empty Element. By empty we mean it has no contents - no Atom within it. So before use an Atom must be Assigned or Created. In practice it is easiest to do this using one of the other constructors.

The atom and host constructor is used to wrap an existing Atom. It creates an Element and then Assigns the Atom to it. The result is a specialized Element which can be used to examine or modify the contents of the Atom.

The CreationOptions enumeration may take the following values:

  • Default - Default creation options for this particular type of Element.
  • Indirect - Create Element containing an IndirectObject.
  • Direct - Create Element containing an Atom.




This code snippet is taken from Annotations.cs line 325 in the Annotations example project.

FieldElement.EntryT = fieldName;
CatalogElement cat = new CatalogElement(Form.Doc.ObjectSoup[Form.Doc.Root]);

FieldElement.EntryT = fieldName
Dim cat As New CatalogElement(Form.Doc.ObjectSoup(Form.Doc.Root))

This code snippet is taken from Annotations.cs line 987 in the Annotations example project.

bool duplicatesFound = false;
CatalogElement cat = new CatalogElement(Doc.ObjectSoup[Doc.Root]);
FieldElement parent = field.FieldElement.EntryParent;
InteractiveFormElement acroForm = cat.EntryAcroForm;
ArrayElement<FieldElement> kids = parent != null ? parent.EntryKids : acroForm.EntryFields;
Dictionary<string, List<FieldElement>> items = new Dictionary<string, List<FieldElement>>();
foreach (var kid in kids) {
  if (kid == null)
    continue; // shouldn't really happen
  string name = kid.EntryT;
  if (!items.ContainsKey(name))
    items[name] = new List<FieldElement>();
foreach (KeyValuePair<string, List<FieldElement>> pair in items) {
  if (pair.Value.Count > 1) {
    duplicatesFound = true;
    // shift field down to be a child of a new field node
    FieldElement newField = new FieldElement(cat);
    newField.EntryKids = new ArrayElement<FieldElement>(acroForm);
    if (parent != null) {
      newField.EntryParent = parent;
    else {
    foreach (FieldElement twin in pair.Value) {
      if (!string.IsNullOrEmpty(twin.EntryFT)) {
        newField.EntryFT = twin.EntryFT;
        twin.EntryFT = null;
      if (!string.IsNullOrEmpty(twin.EntryT)) {
        newField.EntryT = twin.EntryT;
        twin.EntryT = null;
      if (!string.IsNullOrEmpty(twin.EntryTU)) {
        newField.EntryTU = twin.EntryTU;
        twin.EntryTU = null;
      if (twin.EntryFf.HasValue) {
        newField.EntryFf = twin.EntryFf;
        twin.EntryFf = null;
      if (twin.EntryV != null) {
        newField.EntryV = twin.EntryV;
        twin.EntryV = null;
      if (twin.EntryDV != null) {
        newField.EntryDV = twin.EntryDV;
        twin.EntryDV = null;
      twin.EntryParent = newField;
if ((refreshForm) && (duplicatesFound))
return duplicatesFound;

Dim duplicatesFound As Boolean = False
Dim cat As New CatalogElement(Doc.ObjectSoup(Doc.Root))
Dim parent As FieldElement = field.FieldElement.EntryParent
Dim acroForm As InteractiveFormElement = cat.EntryAcroForm
Dim kids As ArrayElement(Of FieldElement) = If(parent IsNot Nothing, parent.EntryKids, acroForm.EntryFields)
Dim items As New Dictionary(Of String, List(Of FieldElement))()
For Each kid In kids
  If kid Is Nothing Then
    Continue For ' shouldn't really happen
  End If
  Dim name As String = kid.EntryT
  If Not items.ContainsKey(name) Then
    items(name) = New List(Of FieldElement)()
  End If
Next kid
For Each pair As KeyValuePair(Of String, List(Of FieldElement)) In items
  If pair.Value.Count > 1 Then
    duplicatesFound = True
    ' shift field down to be a child of a new field node
    Dim newField As New FieldElement(cat)
    newField.EntryKids = New ArrayElement(Of FieldElement)(acroForm)
    If parent IsNot Nothing Then
      newField.EntryParent = parent
    End If
    For Each twin As FieldElement In pair.Value
      If Not String.IsNullOrEmpty(twin.EntryFT) Then
        newField.EntryFT = twin.EntryFT
        twin.EntryFT = Nothing
      End If
      If Not String.IsNullOrEmpty(twin.EntryT) Then
        newField.EntryT = twin.EntryT
        twin.EntryT = Nothing
      End If
      If Not String.IsNullOrEmpty(twin.EntryTU) Then
        newField.EntryTU = twin.EntryTU
        twin.EntryTU = Nothing
      End If
      If twin.EntryFf.HasValue Then
        newField.EntryFf = twin.EntryFf
        twin.EntryFf = Nothing
      End If
      If twin.EntryV IsNot Nothing Then
        newField.EntryV = twin.EntryV
        twin.EntryV = Nothing
      End If
      If twin.EntryDV IsNot Nothing Then
        newField.EntryDV = twin.EntryDV
        twin.EntryDV = Nothing
      End If
      twin.EntryParent = newField
    Next twin
  End If
Next pair
If (refreshForm) AndAlso (duplicatesFound) Then
End If
Return duplicatesFound

This code snippet is taken from ValidationUtilities.cs line 83 in the ValidatePDF example project.

ValidationLog validation = new ValidationLog();
validation.Coverage = coverage;
validation.Stack = new Stack<ValidationStackNode>();
CatalogElement cat = new CatalogElement(doc.ObjectSoup.Catalog);
StreamObject trail = doc.ObjectSoup.Trailer;
bool isCrossRef = Atom.GetItem(trail.Atom, "W") != null;
CrossReferenceStreamElement crossRef = isCrossRef ? new CrossReferenceStreamElement(trail) : null;
FileTrailerElement fileTrailer = !isCrossRef ? new FileTrailerElement(trail) : null;
Element trailer = isCrossRef ? (Element)crossRef : (Element)fileTrailer;
if (doc.Encryption.Type != 0) {
  EncryptionElement encryption = crossRef != null ? crossRef.EntryEncrypt : fileTrailer.EntryEncrypt;
  validation.ReportEntryVersion("Encryption.V", encryption.GetEntryVersion("V"));

StringBuilder sb = validation.Log;
HashSet<int> done = validation.Done;
List<IndirectObject> missed = new List<IndirectObject>();
foreach (IndirectObject io in doc.ObjectSoup) {
  if ((io != null) && (io.ID != 0) && (!done.Contains(io.ID))) {
    Element e = ElementFactories.AutodetectFactory(new RefAtom(io), io, null);
    if ((e is ObjectStreamElement) || (e is CrossReferenceStreamElement) || (e is LinearizationParameterElement)) {
      done = validation.Done;
if (reportOrphans) {
  foreach (IndirectObject io in doc.ObjectSoup) {
    if ((io != null) && (io.ID != 0) && (!done.Contains(io.ID)))
  if (missed.Count > 0) {
    HashSet<int> refOnlyObjects = new HashSet<int>();
    Dictionary<int, HashSet<int>> references = new Dictionary<int, HashSet<int>>();
    foreach (IndirectObject io in doc.ObjectSoup) {
      if (io != null) {
        bool hasContent = false;
        FindAllReferences(io.ID, io.Atom, references, ref hasContent);
        if (!hasContent)
    foreach (IndirectObject io in missed) {
      HashSet<int> set = null;
      references.TryGetValue(io.ID, out set);
      if (set == null)
        continue; // object not referenced by anything - ignore
      if (refOnlyObjects.Contains(io.ID))
        continue; // only reference atoms - simply a stop en route to other items
      sb.AppendLine("Missed ID: " + io.ID.ToString() + ": " + IndirectObjectDescription(io));
      foreach (var id in set)
        sb.AppendLine(" Referenced by ID: " + id.ToString() + ": " + IndirectObjectDescription(doc.ObjectSoup[id]));
string header = "PDF Version: " + GetVersion(validation.Version) + "\r\n";
if (validation.Version.HasFlag(PDFVersion.AdobeUndocumented))
  header += "PDF Uses Undocumented Extensions\r\n";
if (validation.Version.HasFlag(PDFVersion.PDF20Deprecated)) {
  header += "PDF Uses PDF 2.0 Deprecated Features\r\n";
  foreach (string feature in validation.Deprecated)
    header += " - " + feature + "\r\n";
header += "\r\n";
return header + sb.ToString();

Dim validation As New ValidationLog()
validation.Coverage = coverage
validation.Stack = New Stack(Of ValidationStackNode)()
Dim cat As New CatalogElement(doc.ObjectSoup.Catalog)
Dim trail As StreamObject = doc.ObjectSoup.Trailer
Dim isCrossRef As Boolean = Atom.GetItem(trail.Atom, "W") IsNot Nothing
Dim crossRef As CrossReferenceStreamElement = If(isCrossRef, New CrossReferenceStreamElement(trail), Nothing)
Dim fileTrailer As FileTrailerElement = If(Not isCrossRef, New FileTrailerElement(trail), Nothing)
Dim trailer As Element = If(isCrossRef, CType(crossRef, Element), CType(fileTrailer, Element))
If doc.Encryption.Type <> 0 Then
  Dim encryption As EncryptionElement = If(crossRef IsNot Nothing, crossRef.EntryEncrypt, fileTrailer.EntryEncrypt)
  validation.ReportEntryVersion("Encryption.V", encryption.GetEntryVersion("V"))
End If

Dim sb As StringBuilder = validation.Log
Dim done As HashSet(Of Integer) = validation.Done
Dim missed As New List(Of IndirectObject)()
For Each io As IndirectObject In doc.ObjectSoup
  If (io IsNot Nothing) AndAlso (io.ID <> 0) AndAlso (Not done.Contains(io.ID)) Then
    Dim e As Element = ElementFactories.AutodetectFactory(New RefAtom(io), io, Nothing)
    If (TypeOf e Is ObjectStreamElement) OrElse (TypeOf e Is CrossReferenceStreamElement) OrElse (TypeOf e Is LinearizationParameterElement) Then
      done = validation.Done
    End If
  End If
Next io
If reportOrphans Then
  For Each io As IndirectObject In doc.ObjectSoup
    If (io IsNot Nothing) AndAlso (io.ID <> 0) AndAlso (Not done.Contains(io.ID)) Then
    End If
  Next io
  If missed.Count > 0 Then
    Dim refOnlyObjects As New HashSet(Of Integer)()
    Dim references As New Dictionary(Of Integer, HashSet(Of Integer))()
    For Each io As IndirectObject In doc.ObjectSoup
      If io IsNot Nothing Then
        Dim hasContent As Boolean = False
        FindAllReferences(io.ID, io.Atom, references, hasContent)
        If Not hasContent Then
        End If
      End If
    Next io
    For Each io As IndirectObject In missed
      Dim set As HashSet(Of Integer) = Nothing
      references.TryGetValue(io.ID, set)
      If set Is Nothing Then
        Continue For ' object not referenced by anything - ignore
      End If
      If refOnlyObjects.Contains(io.ID) Then
        Continue For ' only reference atoms - simply a stop en route to other items
      End If
      sb.AppendLine("Missed ID: " & io.ID.ToString() & ": " & IndirectObjectDescription(io))
      For Each id In set
        sb.AppendLine(" Referenced by ID: " & id.ToString() & ": " & IndirectObjectDescription(doc.ObjectSoup(id)))
      Next id
    Next io
  End If
End If
Dim header As String = "PDF Version: " & GetVersion(validation.Version) & vbCrLf
If validation.Version.HasFlag(PDFVersion.AdobeUndocumented) Then
  header &= "PDF Uses Undocumented Extensions" & vbCrLf
End If
If validation.Version.HasFlag(PDFVersion.PDF20Deprecated) Then
  header &= "PDF Uses PDF 2.0 Deprecated Features" & vbCrLf
  For Each feature As String In validation.Deprecated
    header &= " - " & feature & vbCrLf
  Next feature
End If
header &= vbCrLf
Return header + sb.ToString()