使用 Ruby 语言来解析开放文档格式 OOXML 文件

在这篇文章中,我们将了解一个开发团队如何解决他们在应用程序中解析数据时遇到的问题。

为了测试 ONLYOFFICE 文档编辑器,我们用Ruby语言开发编写了个docx、xlsx、pptx文件解析器程序,它是免费开源的,被我们放在GitHubRubyGems.org上面了,采用AGPL V3开源协议。

本文我们将告诉你这是如何开发的以及这是如何工作的。

没有现成的工具集

我们本可以从很多已有的工具中选择一个来用,但是有不少原因阻止了我们采用现有的工具集:

  • 他们大多数都被自己的开发者抛弃了。
  • 他们被分为三个独立的库来提供,也就是文档、表格、幻灯片演示这三大类办公文件,三个库的界面接口不同,这使得它们使用起来非常不方便。
  • 他们只支持基本的功能。

译者注:很多软件如果被废弃就会因为久不升级而逐渐不支持不断更新升级的工作对象文件,过两三年就会彻底无用,GitHub上各个项目我最关注的就是the latest release的时间,死了好几年的项目一大把,每每看见都会扼腕叹息

给ONLYOFFICE质保QA团队开发的解析器

我们需要一个更强大的工具,测试我们的ONLYOFFICE编辑器,因为ONLYOFFICE编辑器:

  • 一直处于活跃开发的状态中
  • 允许文档、表格、幻灯片文件使用各种复杂的格式、风格、等功能
  • 尽可能的最大化的支持开放文档格式OOXML,即docx、xlsx、pptx文件

解析复杂的功能

ONLYOFFICE编辑器对微软Office格式有最大的支持力度,所以这个测试用解析器也要有同样的支持力度。我们按照ECMA-376 standard标准来开发,该标准实际上分为上下四大册书,总共七千多页。

所以,你可能会理解,我们实际上无法实现该标准所有的细节,但为了测试ONLYOFFICE编辑器高级功能,我们必须涵盖这些功能点。

因此,除了解析基本的功能特征,比如段落、表格、形状等,我们的解析器还要支持:

  • 配色主题
  • 段落和表格的风格
  • 图表
  • 分列
  • 自动图形的属性
  • 列表

为什么我们需要一个解析器

开始启动对ONLYOFFICE的自动测试之后,我们采取了一个功能测试的简单概念。

比如:

  1. 创建一个新文档
  2. 随意输入文字并加粗它
  3. 检查文字是否被加粗

ONLYOFFICE编辑器是由HTML5 Canvas来开发实现的,因此文档里面的文字被作为图像显示出来。从图像里面确认文字的字体是否加粗了,这种事并不容易。比如下图所示,Arial Black字体,你能辨识出这个字体是否加粗了呢?

 

这就是在这个软件测试的场景下,为什么我们要添加一套额外的确认步骤的原因了:

4. 下载为docx文件,检查确认这个文字就是被赋予了Bold加粗的属性配置。

细节上有数百个类似的属性参数,然而现有的解析器工具没有一个能够支持所有这些参数,有的不过是解析文字、表格以及其它一些简单内容,这就是为什么我们开发自己的测试库的原因了。

这个解析器是如何工作的

如果你曾经把.docx作为zip文件来解压缩,你就会注意到压缩率非常高,那是因为一个OOXML开放文档格式文件实际上就是一套压缩的XML文件。

例如,我们在ONLYOFFICE编辑器中创建一个文件简单输入一些自负然后保存下载为docx文件:

现在我们把它当作一个zip文件来解压缩,就会看到类似如下的文件夹结构:

#tree
.       
├── [Content_Types].xml     
├── docProps                
│   ├── app.xml            
│   └── core.xml            
├── _rels                   
└── word├── document.xml        ├── fontTable.xml       ├── _rels               │   └── document.xml.rels                  ├── settings.xml        ├── styles.xml          ├── theme               │   ├── _rels           │   │   └── theme1.xml.rels                │   └── theme1.xml      └── webSettings.xml 

仔细看看这些文件:

[Content_Types].xml —— 文档的MIME类型列表

app.xml —— 文档元数据、应用程序元数据以及统计数据

core.xml  —— 最新修改的元数据

document.xml  —— 这就是我们要重点查看的文档内容的文件

fontTable.xml   —— 文档的字体列表,可能有用

document.xml.rels  —— 压缩包中的所有文件的列表,对于复杂文档例如包含有插图、绘图的来说会有用

settings.xml  —— 顾名思义,包含文档各种设置,例如默认缩放、数字的分隔符等等

styles.xmltheme1.xmltheme1.xml.rels  —— 非常详细的文件,设置风格和主题等信息,识别这些设置的能力就是Office类软件的关键优势之一了

webSettings.xml   —— 文档的web版式版本设置,对于docx类文件并不常用的功能 |

译者注:docx类文件在文档编辑器软件中切换为web版式显示画面,可以让文档编辑器软件不去自动计算分页,这对于长达数百页上千页的超大docx文档来说,是在编写过程和只读阅览过程中防止死机提高效率的非常实用的技巧,当然,在排版过程中还是需要切换回常用的页面视图,这个时候就需要办公电脑拥有具备顶级游戏电脑的硬件配置。

所以,如果我们处理上面这个举例的非常简单的文档,我们只需要解析document.xml文件。

这是非常简单的一个XML。幸运的是,这可以用Ruby来轻松解析,我们使用了Nokogiri这个工具,获取DOM树,然后查看OOXML标准,或者是反向工程技术,来看我们所需的参数在哪里。

这个解析器是如何编写出来的

我们开始开发这个工具的时候遇上了两个错误,好在后来我们发现了并改正了。希望我们的经验能够对后来的你们有用,避免发生同样的问题。

大文件

所以,我们需要测试三种不同的编辑器,编辑文档、表格和幻灯片文件,我们如何为此目的而组织代码呢?这就很有趣了,但是,最初我们有四个文件,第四个是为了测试三种编辑器共有的那些通用特性而准备的,这四个文件每个都长达4000多行。调试这些文件花费了很多时间,我们就精心地重新架构了这些代码,结果是分解成为200多个文件,代替先前的四个大文件,这样,现在就很容易定位bug解决bug了。

没有测试

我们:对这个解析器没有测试!因为我们编写这个解析器是用来测试编辑器的,而不是再多开发一个东西来测试这个解析器。

所有事情:我们纠正一处拼写错误来解决一个bug,结果却全部崩溃

所以,我们不得不创建一个特别的文件夹,把这两百多个文件放进来,检查一堆参数,确保知道我们下班之前所做的commit不会crash第三层菜单中某个选项的确认操作,开发团队没有人会详细记得所写代码的所有细节。

我们也有些好主意,例如

使用RuboCop

RuboCop是一个Ruby静态代码分析器和格式化工具,基于Ruby社区风格指南的。我们喜欢这个工具,它帮助我们避免了很多错误,让代码保持干净,确保我们最后的提交没有让代码变坏,感谢经过overcommit进行集成。

例如,如果,在经历了艰难的一天开发滞后,你不小心忘记了Ruby中的变量是小写的,然后就尝试提交类似如下这样的代码:

— path_to_zip_file = copy_file_and_rename_to_zip(path_to_file)
+ ZIP_file = copy_file_and_rename_to_zip(path_to_file)

就会报错:

Analyze with RuboCop........................................[RuboCop] FAILEDErrors on modified lines:ooxml_parser/lib/ooxml_parser/common_parser/parser.rb:8:7: E: dynamic constant assignment

如果没有额外的操作,您将无法提交代码。 这是一个极好措施来预防傻瓜式错误的出现。

使用我们的文档库

实际上到我们开发出来这个解析器的时候,我们就已经收集了很多的,实际上,各种奇奇怪怪的docx、xlsx、pptx文件了。我们在ONLYOFFICE编辑器开发的早期阶段,收集了这些文件,用它们来检查复杂文档的渲染功能,几年之后,我们用它们来测试我们的解析器。我们检测到了不少的错误,然后花费了数周的时间来修复它们,但这些工作物有所值。

现在我们就有了解析OOXML文件的强大的工具OOXML Parser,我们用它来测试:

  • ONLYOFFICE文档社区版:开源版本由开源社区维护支持;
  • ONLYOFFICE文档企业版:2B面向企业端用户的商业销售版本;
  • ONLYOFFICE文档开发者版:面向开发商的可以进行开发的版本。

希望这一篇文章可以对你的项目有所帮助,就如ONLYOFFICE一样。

另:解析器怎么用

按照OOXML Parser的说明,安装后,编写测试脚本:

#!/usr/bin/env rubyrequire 'ooxml_parser'docx = OoxmlParser::Parser.parse('/home/WangXiaoShen/Documents/HelloWorld.docx')p docx.document_properties.pagesp docx.file_path

执行,可以看到解析结果:


英文原文:Parsing OOXML Files With Ruby - DZone

译者:天哥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/146553.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【一】初步认识数据库

数据库概览数据库 缘起表(Table)的理解用表来定义数据库数据库系统的理解概念层次的理解实例层次的理解 数据库管理系统的理解从用户角度看从系统实现角度看典型的数据库管理系统 数据库语言数据库定义、操纵、控制语言数据库语言 VS 高级语言 内容回顾练习 数据库概览 走马观…

安卓玩机-----给app加注册码 app加弹窗 云注入弹窗

在对接很多工作室业务中有些客户需要在他们自带的有些app中加注册码或者验证码的需求。其实操作起来也很简单。很多反编译软件有自带的注入功能。例如注入弹窗。这个是需要对应的注册码来启动应用。而且是随机id。重新安装app后需要重新注册才可以继续使用,原则上可…

深入学习git

1、git原理及整体架构图 一些常用的命令 git add . 或 git add src/com/ygl/hello/hello.java 指定文件 git commit . 或 git commit src/com/ygl/hello/hello.java 指定文件 git push origin 分支名称 2、git stash的应用场景 场景一:你正在当前分支A开发&…

localStorage实现历史记录搜索功能

📝个人主页:爱吃炫迈 💌系列专栏:JavaScript 🧑‍💻座右铭:道阻且长,行则将至💗 文章目录 为什么使用localStorage如何使用localStorage实现历史记录搜索功能&#xff08…

代码随想录算法训练营第五十二天 | 300. 最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

1. 最长递增子序列 300. 最长递增子序列 - 力扣(LeetCode) dp[i] 取决于 i 之前所有的dp class Solution {public int lengthOfLIS(int[] nums) {// dp[i] 第 0 - i 位的递增子序列长度int length nums.length;int[] dp new int[length];Arrays.fil…

基于SSM的微博系统网站的设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用Vue技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

如何用ChatGPT学或教英文?5个使用ChatGPT的应用场景!

原文:百度安全验证 AI工具ChatGPT的出现大幅改变许多领域的运作方式,就连「学英文」也不例外!我发现ChatGPT应用在英语的学习与教学上非常有意思。 究竟ChatGPT如何改变英文学习者(学生)与教学者(老师)呢? 有5个应用场景我感到…

2023-09-28 monetdb-databae的概念和作用-分析

摘要: 每个数据库对于db,schema以及user,role都有一套自己的设计, 不同数据库间对于相同名字的东西例如database和schema可以说南辕北辙, 例如mysql中schema其实是database的同义词. 本文分析monetdb的database的概念和作用 database的概念和作用: 和mysql的database完全不同…

Linux开发工具之文本编译器vim

目录 Linux编辑器-vim使用 1. vim的基本概念 ● 正常/普通/命令模式(Normal mode) ● 插入模式(Insert mode) ● 末行模式(last line mode) 2. vim的基本操作 ● [正常模式]切换至[插入模式] ● [插入模式]切换至[正常模式] ● [正常模式]切换至[末行模式] ● 退出vi…

步力宝科技爆款产品定位,开创智能物联网新商业

数据显示,中国处于 “亚健康”状态人口数量约占总人口的70%,亚健康是一种临界状态,指介于健康和疾病之间的状态。亚健康是一个动态演变的过程,既有向慢病发展的趋势,也能通过合理的干预使人体重返健康状态,…

网络运营和电子商务有什么区别

大家好,我是网络工程师成长日记实验室的郑老师,您现在正在查看的是网络工程师成长日记专栏,记录网络工程师日常生活的点点滴滴 一个同学他问我,他说学网络运营的话,它是不是电子商务里面的这个东西?像电子大…

南京大学【软件分析】08 Pointer Analysis

文章目录 1. Motivation2. Introduction to Pointer Analysis3. Key Factors of Pointer Analysis3.1 Heap Abstraction3.2 Context Sensitivity3.3 Flow sensitivity3.4 Analysis scope 4. Concerned Statements 1. Motivation 指针分析存在不精确的问题。对于下面的例子&…

快排三种递归及其优化,非递归和三路划分

个人主页:Lei宝啊 愿所有美好如期而遇 目录 快排简介: 快排的三种递归实现: Hoare: 挖坑: 双指针: 小区间优化: 三数取中优化: 快排非递归实现: 快排的三路划…

Ubuntu配置深度学习环境(TensorFlow和pyTorch)

文章目录 一、CUDA安装1.1 安装显卡驱动1.2 CUDA安装1.3 安装cuDNN 二、Anaconda安装三、安装TensorFlow和pyTorch3.1 安装pyTorch3.2 安装TensorFlow2 四、安装pyCharm4.1 pyCharm的安装4.2 关联anaconda的Python解释器 五、VScode配置anaconda的Python虚拟环境 前言&#xff…

一维数组和二维数组的使用(char类型)

目录 导读1. 字符数组1.1 字符数组的创建1.2 字符数组的初始化1.3 不同初始化在内存中的不同1.3.1 strlen测试1.3.2 sizeof测试1.3.3 差异原因 1.4 字符数组的使用 2. 数组越界3. 数组作为函数参数博主有话说 导读 我们在前面讲到了 int 类型的数组的创建和使用: 一…

焕新古文化传承之路,AI为古彝文识别赋能

目录 1 古彝文与古典保护 2 古文识别的挑战 2.1 西文与汉文OCR 2.2 古彝文识别难点 3 合合信息:古彝文保护新思路 3.1 图像矫正 3.2 图像增强 3.3 语义理解 3.4 工程技巧 4 总结 1 古彝文与古典保护 彝文指的是云南、贵州、四川等地的彝族人使用的文字&am…

行为型设计模式——责任链模式

摘要 责任链模式(Chain of responsibility pattern): 通过责任链模式, 你可以为某个请求创建一个对象链. 每个对象依序检查此请求并对其进行处理或者将它传给链中的下一个对象。 一、责任链模式意图 职责链模式(Chain Of Responsibility) 是一种行为设…

MAC手动修复『已损坏』问题 终端运行命令报错处理

安装一些第三方软件会出现已损坏的报错提醒,需要用命令sudo xattr -rd com.apple.quarantine进行修复,但是终端提示命令错误,怎么版 错误有几种: No module named ‘pkg_resources’ 这是mac电脑上python2,python3并…

mfc140u.dll是什么文件?mfc140u放在哪个文件夹?详细修复教程

今天我想和大家分享一个非常常见的问题——mfc140u.dll丢失的困扰以及解决方法。 首先,让我们来了解一下什么是mfc140u.dll。这是一个非常重要的动态链接库文件,它是Microsoft Foundation Class Library的一个组件。许多软件和游戏都需要这个文件的支持才…

Appium 全新 2.0 全新跨平台生态,版本特性抢鲜体验!

关于Appium V2 Appium V2 beta版本在2021年发布,从2022年1月1号开始,Appium核心团队不会再维护Appium 1.x版本了,所有近期官方发布的平台驱动(如Android平台的UIAutomator,IOS平台的XCUITest)不再兼容Appi…