Skip to content

Formatunabhängige IR

DocumentIR ist die strukturelle Brücke von Office Oxide zwischen den Formaten. Öffne eine .docx, eine .xlsx oder ein Legacy-.ppt — du bekommst immer dieselbe Form zurück: eine Liste von Abschnitten, jeder mit einer Sequenz typisierter Elemente (Überschriften, Absätze, Tabellen, Listen, Bilder).

Die IR trägt to_html, save_as und die Legacy→OOXML-Konvertierung. Sie ist auch die richtige Schnittstelle für Downstream-Pipelines — Suchindizes, RAG-Chunker, eigene Renderer —, weil du ein Schema verarbeitest statt sechs formatspezifischer.

IR lesen

Rust

use office_oxide::Document;

let doc = Document::open("report.docx")?;
let ir = doc.to_ir();

for section in &ir.sections {
    println!("{:?}", section.title);
    for el in &section.elements {
        // el ist ein Element-Enum — Heading, Paragraph, Table, List, Image, ...
    }
}

Python

from office_oxide import Document

with Document.open("report.docx") as doc:
    ir = doc.to_ir()

for section in ir["sections"]:
    print(section.get("title"))
    for el in section["elements"]:
        kind = el["kind"]   # "Heading" | "Paragraph" | "Table" | "List" | "Image"

JavaScript

using doc = Document.open('report.docx');
const ir = doc.toIr();

for (const section of ir.sections) {
  for (const el of section.elements) {
    // el.kind: "Heading" | "Paragraph" | "Table" | "List" | "Image"
  }
}

Go

import "encoding/json"

irJSON, _ := doc.ToIRJSON()

var ir struct {
    Sections []struct {
        Title    *string           `json:"title"`
        Elements []json.RawMessage `json:"elements"`
    } `json:"sections"`
}
_ = json.Unmarshal([]byte(irJSON), &ir)

C#

using System.Text.Json;

using var doc = Document.Open("report.docx");
using var ir = JsonDocument.Parse(doc.ToIrJson());

foreach (var section in ir.RootElement.GetProperty("sections").EnumerateArray())
{
    // ...
}

C

int err = 0;
OfficeDocumentHandle *doc = office_document_open("report.docx", &err);
char *ir_json = office_document_to_ir_json(doc, &err);   /* DocumentIR as JSON */
if (ir_json) {
    /* parse with your JSON lib — sections[].elements[].kind: "Heading" | ... */
    office_oxide_free_string(ir_json);
}
office_document_free(doc);

WASM

import { WasmDocument } from 'office-oxide-wasm';

const data = new Uint8Array(await (await fetch('/report.docx')).arrayBuffer());
const doc = new WasmDocument(data, 'docx');
try {
  const ir = doc.toIr();                 // JS object, schema == Rust DocumentIR
  for (const section of ir.sections) {
    for (const el of section.elements) {
      // el.kind: "Heading" | "Paragraph" | "Table" | "List" | "Image"
    }
  }
} finally {
  doc.free();
}

Schema

Die Form ist bewusst schlank und stabil gehalten.

{
  "sections": [
    {
      "title": "Optional section title",     // string | null
      "elements": [
        { "kind": "Heading", "level": 1, "text": "..." },
        { "kind": "Paragraph", "runs": [
            { "text": "Hello ", "bold": false, "italic": false },
            { "text": "world", "bold": true,  "italic": false }
        ] },
        { "kind": "List", "ordered": true, "items": ["one", "two"] },
        { "kind": "Table", "rows": [
            ["A1", "B1"],
            ["A2", "B2"]
        ] },
        { "kind": "Image", "filename": "image1.png", "data": "<base64>" }
      ]
    }
  ]
}

Mapping nach Format:

Format Abschnittsgrenze Anmerkungen
DOCX Ein Abschnitt pro <w:sectPr> (oder der gesamte Body, wenn keiner vorhanden) Überschriften per w:pStyle zugeordnet
XLSX Ein Abschnitt pro Tabellenblatt title = Blattname; ein Table-Element pro genutztem Bereich
PPTX Ein Abschnitt pro Folie title = Folientitel-Platzhalter; Notizen als letzter Absatz angehängt
DOC / XLS / PPT Gleiche Form wie die OOXML-Entsprechungen Wird über die Legacy-CFB-Pipeline geparst

Warum die IR nutzen

  • Einmal aufbauen, vielfach rendern. Konvertiere DOCX, XLSX und PPTX in dieselbe Form und betreibe eine einzige Such-/Chunk-Pipeline.
  • LLM-Kontext, der Formatwechsel überlebt. Das Schema driftet nicht, wenn Dokumente von .doc zu .docx wandern.
  • Round-Trip mit save_as. Bearbeite die IR und schreibe ein neues Dokument in jedem unterstützten Format.

Rust

use office_oxide::create::create_from_ir;
use office_oxide::DocumentFormat;

create_from_ir(&ir, DocumentFormat::Docx, "out.docx")?;

Serialisierung

Die Rust-DocumentIR leitet Serialize / Deserialize ab (via serde). Pythons to_ir() gibt ein gewöhnliches dict zurück (bereits JSON-serialisierbar). Die Node-, Go-, C#- und C-Bindings stellen JSON-Strings über to_ir_json() / ToIRJSON() / ToIrJson() bereit.

Siehe auch