💡 Volledig werkend voorbeeld beschikbaar op GitHub:
extract-annotations-from-pdf-using-groupdocs-parser-dotnet
Introductie
Een PDF die een review heeft ondergaan bevat meestal meer dan alleen de zichtbare tekst – plaknotities, gemarkeerde opmerkingen en inline‑commentaren van reviewers. Door elke pagina te scrollen om ze te vinden, schaalt niet meer zodra een document meerdere feedbackrondes heeft doorlopen. GroupDocs.Parser is een .NET‑bibliotheek die de ingebedde annotaties van een document programmatisch uitleest, waardoor verspreide reviewer‑commentaren worden omgezet in gestructureerde gegevens waar je code mee kan werken. Deze tutorial laat zien hoe je annotaties uit een volledige PDF kunt extraheren, ze pagina voor pagina kunt opsplitsen, ze samen met de tekst van het document kunt ophalen en de resultaten naar CSV of JSON kunt exporteren.
Ik kwam dit probleem tegen toen ik een review‑tracker bouwde voor een documentatieteam: een 40‑pagina’s tellende release‑note had drie reviewers doorlopen, en het handmatig openen van het bestand om elke opmerking te vinden duurde langer dan het daadwerkelijk oplossen van de gemarkeerde problemen. Het extraheren van de annotaties in een paar regels code maakte er een taak van twee minuten van.
In de volgende secties leer je hoe je:
- Elke annotatie uit een PDF in één keer kunt extraheren.
- Elke annotatie kunt taggen met de pagina waartoe hij behoort.
- Document‑tekst en annotatietekst samen kunt ophalen in één leesactie.
- De resultaten kunt serialiseren naar CSV of JSON voor downstream‑tools.
Waarom het extraheren van PDF‑annotaties belangrijk is
Het programmatisch lezen van PDF‑annotaties is nuttig voor:
- Review‑workflows: Verzamel elke reviewer‑opmerking zonder het bestand in een PDF‑viewer te openen.
- Samenwerking: Breng gemarkeerde of genoteerde secties direct in je eigen tools naar voren.
- Auditing: Houd een overzicht bij van markup die op een document is achtergelaten, zelfs nadat het is geflatteerd of afgerond.
GroupDocs.Parser voegde native annotatie‑extractie voor PDF‑documenten toe in versie 26.7 via de GetAnnotations‑methode, naast een nieuwe IncludeAnnotations‑optie op TextOptions om annotatietekst in een reguliere tekst‑read op te nemen.
Vereisten
- .NET 6.0 of hoger
- GroupDocs.Parser for .NET 26.7+ (temporary license)
- Een PDF‑bestand met bestaande annotaties (bijv.
document-with-annotations.pdf)
Installeren via NuGet:
dotnet add package GroupDocs.Parser
Hoe extraheer ik annotaties uit een PDF‑document?
Antwoord: Laad het bestand met Parser en roep vervolgens GetAnnotations() aan voor het hele document of GetAnnotations(pageIndex) voor een enkele pagina. Elk resultaat is een collectie van AnnotationItem‑objecten waarvan de Value‑eigenschap de commentaartekst bevat. Als je de opmerkingen liever inline ziet met de reguliere inhoud van het document, stel dan IncludeAnnotations in op TextOptions en roep GetText aan.
Extractie van het volledige document
De volgende code haalt elke annotatie uit het bestand in één enkele oproep, wat de snelste manier is om te controleren of een document überhaupt openstaande opmerkingen bevat.
// Extract every annotation from the whole document
var result = new List<string>();
using (var parser = new Parser(path))
{
IEnumerable<AnnotationItem> annotations = parser.GetAnnotations();
if (annotations == null)
{
return result; // format doesn't support annotations
}
foreach (var item in annotations)
{
result.Add(item.Value); // annotation text
}
}
return result;
Belangrijke punten:
GetAnnotations()retourneertnullwanneer annotatie‑extractie niet wordt ondersteund voor het document, en een lege collectie wanneer het document simpelweg geen annotaties heeft.- Elke
AnnotationItemgeeft zijn tekst weer via deValue‑eigenschap – dat is het enige datapunt dat de SDK momenteel rapporteert. - Er wordt hier geen paginatoewijzing meegegeven; gebruik de per‑pagina‑overload hieronder als je die nodig hebt.
Extractie per pagina
Wanneer de locatie van een opmerking van belang is, loop je over de pagina’s van het document en roep je GetAnnotations(pageIndex) aan voor elke pagina.
// Tag each annotation with its zero-based page index
var result = new List<AnnotationRecord>();
using (var parser = new Parser(path))
{
if (!parser.Features.Annotations)
{
return result;
}
var info = parser.GetDocumentInfo();
if (info == null || info.PageCount == 0)
{
return result;
}
for (int pageIndex = 0; pageIndex < info.PageCount; pageIndex++)
{
IEnumerable<AnnotationItem> pageAnnotations = parser.GetAnnotations(pageIndex);
if (pageAnnotations == null)
{
continue;
}
foreach (var item in pageAnnotations)
{
result.Add(new AnnotationRecord { PageIndex = pageIndex, Value = item.Value });
}
}
}
return result;
Belangrijke punten:
GetDocumentInfo().PageCountbepaalt de loop; er is geen aparte “annotation page count”.GetAnnotations(pageIndex)gebruikt een nul‑gebaseerde index, net als elke andere paginaniveau‑methode in de API.- De resulterende
AnnotationRecord‑lijst heeft precies de vorm die een CSV‑ of JSON‑export nodig heeft.
Tekst extraheren samen met annotaties
In plaats van twee passes over het document kun je annotatietekst direct in de reguliere tekst‑extractie opnemen.
// Read document text with annotation text included
using (var parser = new Parser(path))
{
var options = new TextOptions
{
IncludeAnnotations = true
};
using (TextReader reader = parser.GetText(options))
{
return reader?.ReadToEnd() ?? string.Empty;
}
}
Belangrijke punten:
IncludeAnnotationsis een eigenschap vanTextOptions, dus dit werkt met dezelfdeGetText‑aanroep die je al gebruikt voor gewone tekst‑extractie.- Handig wanneer je één transcript‑stijl output wilt in plaats van een aparte commentaarslijst.
- Combineer het met
GetText(pageIndex, options)als je dit alleen voor één pagina nodig hebt.
Eerst controleren of annotaties worden ondersteund
Niet elk formaat ondersteunt annotaties, dus het is de moeite waard om dit eerst te controleren voordat je logica rond GetAnnotations bouwt.
// Returns true if the loaded document format supports annotation extraction
using (var parser = new Parser(path))
{
return parser.Features.Annotations;
}
Belangrijke punten:
Features.Annotationsis een eenvoudige boolean‑vlag op deParser‑instantie.- Vooraf controleren maakt de intentie expliciet, ook al faalt
GetAnnotationsal netjes doornullte retourneren.
De annotaties exporteren naar CSV
Een CSV‑export stelt reviewers in staat de commentaarslijst direct in Excel te openen. De onderstaande methode schrijft een twee‑koloms bestand (page,value) vanuit de eerder gebouwde paginagetagde records.
var sb = new StringBuilder();
sb.AppendLine("page,value");
foreach (var record in records)
{
sb.AppendLine($"{record.PageIndex},{CsvEscape(record.Value)}");
}
File.WriteAllText(outputPath, sb.ToString());
Belangrijke punten:
CsvEscapezet velden met komma’s, aanhalingstekens of regeleinden veilig tussen aanhalingstekens.- Het resulterende bestand opent direct in Excel of kan worden doorgevoerd naar een ticket‑systeem.
Helper: CsvEscape
if (string.IsNullOrEmpty(s)) return string.Empty;
if (s.Contains(",") || s.Contains("\"") || s.Contains("\n"))
{
return "\"" + s.Replace("\"", "\"\"") + "\"";
}
return s;
De annotaties exporteren naar JSON
Voor pipelines die commentaren programmatisch consumeren, is een JSON‑array meestal beter geschikt dan een platte CSV.
var sb = new StringBuilder();
sb.AppendLine("[");
for (int i = 0; i < records.Count; i++)
{
var comma = i < records.Count - 1 ? "," : string.Empty;
sb.AppendLine($" {{ \"page\": {records[i].PageIndex}, \"value\": \"{Escape(records[i].Value)}\" }}{comma}");
}
sb.AppendLine("]");
File.WriteAllText(outputPath, sb.ToString());
Belangrijke punten:
- De output is een platte array van
{ page, value }‑objecten – eenvoudig voor elke downstream‑service om te deserialiseren. Escapehoudt de payload geldige JSON zonder een serialisatie‑bibliotheek te gebruiken.
Helper: Escape
return s?.Replace("\\", "\\\\").Replace("\"", "\\\"") ?? string.Empty;
Vergelijking van methoden: wanneer welke te gebruiken
| Methode | Beste voor | Belangrijkste voordelen | Beperkingen |
|---|---|---|---|
| Whole‑Document Extraction | Snelle controle “zijn er opmerkingen?” | Eén oproep, eenvoudigste code | Geen paginatoewijzing |
| Per‑Page Extraction | Feedback naar de juiste sectie routeren | Pagina‑gemarkeerde resultaten, klaar voor export | Eén extra oproep per pagina |
| Combined Text + Annotations | Eén leesbare transcript | Geen tweede pass over het document | Opmerkingen zijn niet gescheiden van de hoofdtekst |
| CSV Export | Spreadsheet‑gebaseerde review‑tracking | Makkelijk te openen in Excel, mens‑leesbaar | Beperkt tot platte structuur |
| JSON Export | Geautomatiseerde pipelines, ticket‑systemen | Gestructureerd, machine‑leesbaar | Iets grotere payload |
Begin met whole‑document extraction om te bevestigen dat een bestand commentaren bevat die actie vereisen, en schakel vervolgens over op per‑page extraction zodra je feedback naar een specifieke sectie moet routeren.
Best practices en tips
- Dispose
Parserdirect: wikkel het in eenusing‑blok om native resources vrij te geven. - Maak onderscheid tussen
nullen leeg:GetAnnotationsdienullretourneert betekent dat het formaat niet wordt ondersteund; een lege collectie betekent dat het document geen commentaren heeft. - Controleer
Features.Annotationsin batch‑jobs: sla niet‑ondersteunde bestanden vroegtijdig over in plaats van te vertrouwen op eennull‑check diep in je loop. - Herbruik de paginagetagde lijst: bouw deze één keer met
ExtractAnnotationsByPageen gebruik dezelfde data voor zowel de CSV‑ als JSON‑export, zodat de twee outputs nooit uit de pas lopen. - Beveiliging: annotatietekst is vrije invoer van reviewers – behandel het net als elke andere onbetrouwbare string voordat je het weergeeft in een UI of rapport.
Conclusie
GroupDocs.Parser biedt een directe, programmatische manier om reviewer‑commentaren uit een PDF te halen in plaats van ze handmatig te zoeken. Door annotaties voor het volledige document te extraheren, ze per pagina te taggen of ze in de reguliere tekststroom te integreren, kun je review‑workflows bouwen die feedback direct zichtbaar maken zodra een document jouw pipeline binnenkomt. Exporteer de resultaten naar CSV of JSON en koppel ze rechtstreeks aan de tools die je team al gebruikt.
Volgende stappen:
- Verken de GetAnnotations API‑referentie voor de volledige methodesignature en overloads.
- Leer hoe je tekst uit PDF‑documenten kunt extraheren naast annotaties voor een volledige content‑pipeline.
- Bekijk extra voorbeeldprojecten op GitHub voor batch‑verwerkingsscenario’s (Examples Repo).