Skip to content

Формат-незалежний IR

DocumentIR — структурний міст Office Oxide між форматами. Відкрийте .docx, .xlsx або legacy .ppt — отримаєте ту саму форму: список секцій, у кожній — послідовність типізованих елементів (заголовки, абзаци, таблиці, списки, зображення).

IR рухає to_html, save_as та legacy → OOXML конвертацію. Це і правильна поверхня для downstream-пайплайнів — пошукових індексів, RAG-чанкерів, власних рендерерів — бо ви обробляєте одну схему замість шести форматних.

Прочитати IR

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 — це enum Element: 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())
{
    // ...
}

Схема

Форма навмисно компактна й стабільна.

{
  "sections": [
    {
      "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>" }
      ]
    }
  ]
}

Маппінг за форматами:

Формат Межа секції Примітки
DOCX По одній секції на <w:sectPr> (або весь body, якщо немає) Заголовки — за w:pStyle
XLSX По одній секції на лист title = ім’я листа; по одному Table на використовуваний діапазон
PPTX По одній секції на слайд title = плейсхолдер заголовка слайду; нотатки додаються останнім абзацом
DOC / XLS / PPT Та сама форма, що в OOXML-аналогів Парсяться через legacy CFB-пайплайн

Чому варто використовувати IR

  • Зроби раз — рендер по-різному. Конвертуйте DOCX, XLSX і PPTX в одну форму, ганяйте єдиний пайплайн пошуку/чанкінгу.
  • LLM-контекст, що переживає зміни формату. Схема не дрейфує, коли документи мігрують з .doc на .docx.
  • Round-trip з save_as. Поправте IR — запишіть новий документ у будь-якому підтримуваному форматі.
use office_oxide::create::create_from_ir;
use office_oxide::DocumentFormat;

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

Серіалізація

Rust-DocumentIR має Serialize / Deserialize (через serde). Python-to_ir() повертає звичайний dict (вже JSON-серіалізований). Node-, Go-, C#- та C-прив’язки виставляють JSON-рядки через to_ir_json() / ToIRJSON() / ToIrJson().

Дивіться також