☰
Xberg Ruby 元素级提取实战:element_based 结果格式与 DOCX 元素类型断言
2026/10/9 5:11:56 网站建设 项目流程
  • 后端
  • AI 应用
  • NLP

【免费下载链接】xberg

Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.

项目地址:https://gitcode.com/gh_mirrors/kr/xberg
点击查看免费下载

本文以 xberg 仓库 Ruby 绑定中的config_element_types契约测试为骨架,讲解如何在 Ruby 中启用 element_based(元素级)结果格式,对 DOCX 等文档执行结构化元素提取,并对element_type进行断言与遍历。读完本文,你将掌握result_format: 'element_based'的配置方式、Element/ElementType数据模型、元素元数据(页码、坐标)的读取方法,以及如何在测试中验证元素类型分类的正确性。

一、从契约测试理解 element_based 结果格式

仓库中docs-site/src/snippets-generated/ruby/contract/config_element_types.md是 alef 自动生成的 Ruby 契约测试片段,其元数据声明了测试性质:

  • id: fixture_ruby_config_element_types,language: ruby,target: ruby
  • level: typecheck:该片段用于类型层面的校验
  • side_effect: server:测试需要外部文档服务器(mock server)提供 DOCX 样本

测试目的(原文)是 "Tests element-based result format with element type assertions on DOCX"——即在 DOCX 文档上验证元素级结果格式,并对每个元素的类型做断言。它演示了 xberg Ruby API 的完整调用链路:

require "xberg" result = Xberg.extract(Xberg::ExtractInput.new(kind: 'uri', uri: 'https://example.com/docx/unit_test_headers.docx'), { 'result_format' => 'element_based' }) (result.results[0].elements || []).each do |element| puts element.element_type.inspect puts element.text.inspect end

这段代码虽然简短,却包含了 element_based 用法的全部关键要素:URI 输入构造、结果格式配置、元素集合遍历与类型打印。下文将逐一拆解。

二、element_based 与 unified 结果格式的区别

在开始写代码前,先明确两种结果"形状"的区别。xberg 的 Rust 核心在 types/extraction.rs 中定义了ResultFormat枚举:

pub enum ResultFormat { /// Unified format with all content in `content` field #[default] Unified, /// Element-based format with semantic element extraction ElementBased, }

源码注释清楚地说明了二者差异:Unified把所有内容放入单一content字段(一个扁平文本/标记块),而ElementBased输出语义元素分解——每个逻辑单元(标题、段落、表格、图片等)被单独分类、带唯一标识与元数据。这与OutputFormat(控制 Plain / Markdown / HTML 等渲染方式)是正交的维度:ResultFormat决定结果"形状",OutputFormat决定渲染"样式"。

在关联文档的示例中,ExtractedDocument.elements是一个可空字段(Option<Vec<Element>>,见 types/extraction.rs),仅在启用 element_based 时填充——这正是代码里写(result.results[0].elements || [])的原因:当结果不是元素级格式时,elements为nil,用|| []兜底避免遍历报错。这一细节在实战中非常关键。

三、核心示例逐行拆解

3.1 构造 URI 输入

Xberg::ExtractInput.new(kind: 'uri', uri: 'https://example.com/docx/unit_test_headers.docx')

ExtractInput支持两种输入方式(见 packages/ruby/README.md):

  • kind: 'uri':本地路径、file://或 HTTP(S) URI
  • kind: 'bytes':内存字节流,需配合bytes:与mime_type:

示例中的 URL 是契约测试的占位地址;实际运行测试时,e2e/ruby的契约测试会通过环境变量MOCK_SERVER_CONFIG_ELEMENT_TYPES(缺省为MOCK_SERVER_URL/fixtures/config_element_types)将占位 URL 替换为本地 mock server 的真实地址,供测试文件unit_test_headers.docx使用。

3.2 启用 element_based 结果格式

{ 'result_format' => 'element_based' }

关联文档直接向Xberg.extract传入配置哈希。在仓库的契约测试 e2e/ruby/spec/contract_spec.rb 中,同一条测试使用了等价的强类型写法:

Xberg.extract( Xberg::ExtractInput.new(kind: 'uri', uri: '$mock_url/docx/unit_test_headers.docx'.gsub('$mock_url', input_mock_base_url)), Xberg::ExtractionConfig.new(result_format: 'element_based') )

两种写法的字段名一致(result_format),对应 Rust 核心ResultFormat::ElementBased的 snake_case 序列化名。此外,文档站示例 element_based_output.md 中还出现了Xberg::ExtractionConfig.new(output_format: 'element_based')的写法,用于同一目标。在实际项目中,建议优先使用result_format:关键字写法,以获得 IDE 补全与类型检查支持。

3.3 遍历元素并断言类型

(result.results[0].elements || []).each do |element| puts element.element_type.inspect puts element.text.inspect end
  • result.results[0]:返回ExtractedDocument,包含content、metadata、tables、chunks、elements等字段
  • element.element_type:元素的语义类型,如:title、:narrative_text
  • element.text:该元素承载的文本内容

puts ... .inspect会在输出中带上符号与引号标记(如:title、"Introduction"),便于测试日志区分类型与内容,这也呼应了"元素类型断言"的测试目的。

四、Element 数据模型与完整 ElementType 清单

Element结构定义在 types/extraction.rs:

pub struct Element { /// Deterministic element identifier pub element_id: String, /// Semantic type of this element pub element_type: ElementType, /// Text content of the element pub text: String, /// Metadata about the element pub metadata: ElementMetadata, }

element_id是确定性标识符,可追踪元素来源;element_type则是核心的语义分类。ElementType枚举共 12 种取值(types/extraction.rs),序列化为 snake_case:

Ruby 符号Rust 变体含义
:titleTitle文档标题
:narrative_textNarrativeText正文叙述文本
:headingHeading章节标题
:list_itemListItem列表项(项目符号、编号等)
:tableTable表格元素
:imageImage图片元素
:page_breakPageBreak分页标记
:code_blockCodeBlock代码块
:formulaFormula数学公式(text中为 LaTeX 源码)
:block_quoteBlockQuote引用块
:footerFooter页脚文本
:headerHeader页眉文本

源码注释指出该分类"Supports the element types commonly found in Unstructured documents"——即对齐业界通用的文档语义单元划分。对unit_test_headers.docx这类带标题结构的 DOCX,预期可断言到:title、:heading、:narrative_text等类型。

五、元素元数据:页码、坐标与自定义信息

遍历元素时,除了类型与文本,还可读取element.metadata。ElementMetadata定义见 types/extraction.rs:

  • page_number:页码(从 1 开始)
  • filename:来源文件名
  • coordinates:BoundingBox边界框,包含x0(左)、y0(下)、x1(右)、y1(上)四个浮点坐标
  • element_index:元素在序列中的位置索引
  • additional:HashMap<String, String>,扩展的自定义元数据

文档站示例 element_based_output.md 展示了完整读取姿势:

result.results.first.elements.each do |element| puts "Type: #{element.element_type}" puts "Text: #{element.text[0...100]}" puts "Page: #{element.metadata.page_number}" if element.metadata.page_number if element.metadata.coordinates coords = element.metadata.coordinates puts "Coords: (#{coords.left}, #{coords.top}) - (#{coords.right}, #{coords.bottom})" end puts "---" end # 按类型过滤:提取所有标题,并读取层级 titles = result.results.first.elements.select { |e| e.element_type == 'title' } titles.each do |title| level = title.metadata.additional['level'] || 'unknown' puts "[#{level}] #{title.text}" end

注意两点:

  1. page_number、coordinates均为可空字段,访问前需判空(示例中用if守卫)
  2. 标题的层级信息(如level)存放在metadata.additional哈希中——这是"类型 + 附加属性"模式的典型用法,非常适合对 DOCX 标题结构做递归目录还原

六、底层实现:pipeline 中的 result_format 分支

从源码结构可以推断,element_based 不只是结果序列化层面的开关,而是贯穿核心提取流水线的模式。在 core/pipeline/mod.rs 等处,多次出现如下判断:

if config.result_format == crate::types::ResultFormat::ElementBased { // ... 构造元素级文档,保留 InternalElement 的语义分类 }

这说明 pipeline 在渲染(render_plain / render_markdown 等)之前,会依据result_format决定保留"元素分解"路径还是扁平内容路径。也就是说,启用 element_based 后,elements数组中的分类并非事后拼凑,而是由内部元素模型(InternalElement与ElementKind)直接映射而来——这也是element_type分类稳定、可被契约测试断言的根本原因。

七、测试验证:mock server 与契约断言

契约测试片段并非孤例。仓库中的 Ruby e2e 测试 contract_spec.rb 完整复现了同一场景:

it 'config_element_types: Tests element-based result format with element type assertions on DOCX' do input_mock_base_url = ENV.fetch('MOCK_SERVER_CONFIG_ELEMENT_TYPES', nil) || "#{ENV.fetch('MOCK_SERVER_URL')}/fixtures/config_element_types" result = Xberg.extract( Xberg::ExtractInput.new(kind: 'uri', uri: '$mock_url/docx/unit_test_headers.docx'.gsub('$mock_url', input_mock_base_url)), Xberg::ExtractionConfig.new(result_format: 'element_based') ) # ... 随后对 elements 做类型断言 end

配套的 mock 响应数据位于 fixtures/contract/config_element_types.json。整个测试体系说明:element_based 输出已在 CI 中被持续验证,包括契约格式、元素分类与跨语言绑定一致性——Ruby 绑定的行为与 Rust 核心、其他语言绑定保持一致(这也是 alef 生成器保证的跨绑定 parity)。

八、实战要点小结

  1. 启用方式:Xberg::ExtractionConfig.new(result_format: 'element_based')或等价配置哈希{ 'result_format' => 'element_based' };元素集合在ExtractedDocument#elements上
  2. 空安全:elements为可空字段,非 element_based 模式下为nil,遍历前务必|| []兜底
  3. 类型清单:12 种ElementType(title / narrative_text / heading / list_item / table / image / page_break / code_block / formula / block_quote / footer / header),可用于select过滤
  4. 元数据:page_number(1 起始)、coordinates(BoundingBox:x0/y0/x1/y1)、additional(自定义键值,如标题层级level)需判空后访问
  5. 测试思路:对带标题结构的 DOCX(如unit_test_headers.docx)断言:title、:heading等类型的出现与顺序,即可低成本回归验证文档结构解析质量

至此,你已掌握 xberg Ruby 绑定中 element_based 结果格式的配置、遍历、元数据读取与测试断言全流程。需要继续深入时,可参考 packages/ruby/README.md 的 API 概览,或直接阅读 Rust 核心的类型定义 types/extraction.rs。

  • 后端
  • AI 应用
  • NLP

【免费下载链接】xberg

Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.

项目地址:https://gitcode.com/gh_mirrors/kr/xberg
点击查看免费下载

相关推荐

上一篇:3步构建专业级GB28181国标视频监控平台:wvp-GB28181-pro快速部署指南
下一篇:如何在Android手机上免root运行完整Linux系统:AnLinux-App完全指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询