Работа с открытыми форматами документов: Часть 2.Средства проекта ODF Toolkit


Введение

В предыдущей части серии мы открыли тему открытых форматов документов: рассмотрели их идеологию, а также краткую историю борьбы с проприетарными форматами за место под солнцем, т.е. на компьютерах пользователей. В статье речь также шла и о способах задания формата в различных файловых системах. Кроме того, были перечислены основные открытые форматы текстовых документов, графических и медиафайлов и, разумеется, популярные «офисные» форматы. Среди последних основным на сегодня является ODF (open document format).

Проект ODF Toolkit, начатый в ноябре 2008 года по инициативе корпораций IBM и Sun Microsystems, был призван стимулировать создание инструментов для эффективной работы с документами в формате ODF. За год его существования были разработаны такие средства, как ODFDOM, AODL, ODF Validator, ODF XSLT Runner, ODF XSLT Ant Task. Краткому обзору некоторых из них посвящена настоящая статья.

1. Структура пакета ODF

Прежде чем приступать к изучению средств работы с документами в формате Open Document, рассмотрим структуру ODF-файла.

Он представляет собой zip-архив, содержащий несколько директорий и файлов, четыре из которых предназначены для содержимого документа, стилей, метаданных и настроек приложения. Данные хранятся в формате xml, что позволяет использовать для работы с ними соответствующие стандартные приемы.

2. ODF Validator

Начнем с продукта, который называется ODF Validator. Как понятно из названия, это средство создано для проверки соответствия обрабатываемых документов спецификации формата Open Document.

В операционной системе ODF Validator работает как утилита командной строки. Кроме того, существует ее онлайн-версия, доступная по адресу http://tools.odftoolkit.org/odfvalidator/ (EN).

Инсталляция программы требует наличия нескольких jar-библиотек, а также загрузки схем ODF 1.0, 1.1, 1.2, MathML 1.01 DTD, MathML 2.0. Для работы утилиты в операционной системе должна быть установлена java-машина.

Чтобы проверить файл file1 с использованием JRE 1.5, программа запускается из командной строки следующим образом:

Code
#java -jar "<path>/odfvalidator.jar" file1


Если версия JRE 1.6, синтаксис вызова усложняется:

# java -Djavax.xml.validation.SchemaFactory:http://relaxng.org/
ns/structure/1.0=org.iso_relax.verifier.jaxp.validation.RELAXNGSchemaFactoryImpl
-Dorg.iso_relax.verifier.VerifierFactoryLoader=com.sun.msv.
verifier.jarv.FactoryLoaderImpl -jar "<path>/odfvalidator.jar" file1



Здесь – это полный путь к директории, в которой находится odfvalidator.jar.

При таком упрощенном вызове файл проверяется на соответствие той схеме, которая совпадает с форматом, заявленным в самом файле. Если необходимо указать нужную версию ODF, ее номер передается в качестве параметра: -1.0, -1.1 или -1.2. Указать любую другую конкретную схему (точнее, имя файла, содержащего схему) можно через параметр –S.

Программе можно передать для проверки сразу несколько файлов или каталогов. При указании директории проверке подвергаются все файлы, имеющие формат ODF – odt, ods и т.д. Для исключения из проверки каких-либо файлов и директорий используйте опцию –x. Полные пути к исключаемым из проверки файлам и каталогам указываются через регулярные выражения. Поскольку опция –x может использоваться при вызове утилиты только один раз, несколько шаблонов имен файлов нужно разделять вертикальной чертой.

Параметр –d указывает на необходимость использования схемы MathML 1.01 DTD для проверки файла content.xml для документов, содержащих формулы. По умолчанию используется MathML 2.0.

Вместо того чтобы всякий раз указывать необходимые параметры непосредственно в командной строке, нужный режим проверки можно задать через конфигурационный файл – стандартный файл формата Java XML properties. Поддерживаются следующие свойства:

* strict-schema: указывает используемую схему;
* manifest-schema: указывает manifest-схему;
* mathml-schema: указывает схему MathML 1.01;
* mathml2-schema: указывает схему MathML 2;
* path*: в этих тегах (path1, path2 и т.д.) содержатся имена подлежащих валидации файлов и директорий;
* recursive: логическое свойство определяет, необходимо ли сканировать директории рекурсивно, принимает значения true или false;
* exclude: здесь в виде регулярных выражений перечисляются исключаемые из проверки файлы и каталоги;
* filter: путь к файлу фильтра.

Приведем пример файла конфигурации:

Code
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="strict-schema">
 /home/odf11-cd2/msv/OpenDocument-strict-schema-v1.1-cd2.rng
</entry>
<entry key="manifest-schema">
 /home/odf11-cd2/msv/OpenDocument-manifest-schema-v1.1-cd2.rng
</entry>
<entry key="mathml-schema">/home/odf11-cd2/msv/mathml2.xsd</entry>
<entry key="path1">/home/testdocs</entry>
<entry key="path2">/home/temp</entry>
</properties>


Что такое упоминавшийся файл фильтра? Это XML-файл, при помощи которого можно пропускать известные ошибки проверки. Сообщения о них добавляются в файл фильтра, составленный в соответствии со следующей схемой (формат Relax-NG Compact):

Code
start = filter
filter = element filter { filter-attlist, filter-entry+ }
filter-attlist &= empty
filter-entry = element filter-entry { filter-entry-attlist, text }
filter-entry-attlist &=
 attribute task-id {
   xsd:string { pattern = '[a-z]?[0-9]+"' }
 }
filter-entry-attlist &= attribute resolved-in { xsd:integer }?


А вот пример самого файла фильтра:

Code
<filter>
 <filter-entry task-id="i38753" resolved-in="8864">
  attribute "presentation:display-header" has a bad value.
Possible values are: false,true
 </filter-entry>
</filter>



Каждый элемент содержит одно игнорируемое сообщение об ошибке. Обязательный атрибут task-id включает идентификатор модуля, который исправляет данную ошибку (или будет исправлять, если она еще не исправлена).

Необязательный атрибут resolved-in содержит версию сборки программного средства (например, OpenOffice), в которой ошибка исправлена. Сообщения об ошибках пропускаются только в том случае, если указан атрибут resolved-in и если идентификатор сборки ниже, чем указанный в теге самого проверяемого документа. Таким образом, ошибка не будет пропущена, если она встретилась в документе, созданном в программе, версия сборки которой предполагает, что эта ошибка уже исправлена.

Когда ошибка игнорируется, генерируется предупреждение (warning), в котором содержится task-id из файла фильтра. Обратите внимание, что увидеть предупреждения можно только в том случае, если указан параметр вызова ODF Validator –w или –v.

При использовании ODF Validator с прямым указанием параметров в командной строке путь к файлу фильтра задается через параметр –f.

Онлайн-версия программы представляет собой форму, содержащую поле для ввода имени файла на вашем компьютере, и несколько параметров проверки. Среди них:

* версия спецификации, на соответствие которой будет осуществляться проверка (можно установить автоопределение);
* строгость проверки;
* уровень фиксации ошибок и предупреждений в отчете.

Файл загружается на сервер, после чего проверяется в соответствии с заданными параметрами. Отчет о проверке выдается пользователю в виде Web-страницы с перечнем обнаруженных нарушений:

Code
ODF Validator Result Page
Result for regulations_v13.odt
This file is NOT valid
Result details:
upload:///regulations_v13.odt/content.xml[1,29250]:Error:element
"text:h" is missing "outline-level" attribute
upload:///regulations_v13.odt/content.xml[1,34140]:Error:element
"text:h" is missing "outline-level" attribute
upload:///regulations_v13.odt/content.xml[1,38492]:Error:element
"text:h" is missing "outline-level" attribute
upload:///regulations_v13.odt/content.xml[1,43274]:Error:element
"text:h" is missing "outline-level" attribute
upload:///regulations_v13.odt/content.xml[1,47630]:Error:element
"text:h" is missing "outline-level" attribute
upload:///regulations_v13.odt/content.xml[1,50101]:Error:element
"text:h" is missing "outline-level" attribute
upload:///regulations_v13.odt/content.xml[1,51984]:Error:element
"text:h" is missing "outline-level" attribute
upload:///regulations_v13.odt/content.xml[1,53702]:Error:element
"text:h" is missing "outline-level" attribute
upload:///regulations_v13.odt/content.xml[1,54701]:Error:element
"text:h" is missing "outline-level" attribute
upload:///regulations_v13.odt:Info:validation errors found
upload:///regulations_v13.odt:Info:Generator: Aspose.Words



На этом мы завершим обзор инструмента ODF Validator. Полный перечень параметров вызова, а также требования к программной среде можно найти на сайте проекта ODF Toolkit.

3. ODFXSLTRunner

ODFXSLTRunner – это небольшое Java-приложение для применения таблиц стилей XSLT к XML документам, в том числе и ODF, без извлечения их из пакета. Как и ODF Validator, этот инструмент работает через командную строку.

ODFXSLTRunner создан в NetBeans, поэтому для его сборки и установки требуется открыть проект в этой среде.

Чтобы использовать odfxsltrunner.jar, необходимо наличие некоторых дополнительных библиотек классов, перечень которых можно найти на сайте проекта ODF Toolkit (EN).

Вызвать ODFXSLTRunner можно из командной строки одним из следующих способов:

Code
# java -jar odfxsltrunner.jar <style sheet> [-v]
[-p <path in package>] [-l log file]
  <input package> [<output package> [name=value ...]]
# java -jar odfxsltrunner.jar <style sheet> [-v]
[-p <path in package>] [-l log file] -t
  <input package> <output package> [name=value ...]
# java -jar odfxsltrunner.jar <style sheet> [-v]
[-p <path in package>] [-l log file] -r
  <package> [name=value ...]
# java -jar odfxsltrunner.jar <style sheet> [-v]
[-p <path in package>] [-l log file] -o
  <input package> <output file> [name=value ...]
# java -jar odfxsltrunner.jar <style sheet> [-v]
[-p <path in package>] [-l log file] -i
  <input file> <output package> [name=value ...]



Самый простой пример вызова – применение страницы стилей XSLT к потоку content.xml ODF-файла . Результат преобразования попадет в стандартный вывод либо в выходной пакет, указанный в параметре . Во втором случае копируется в , после чего content.xml замещается результатом преобразования.

Если необходимо использовать не content.xml, а другой источник преобразования, он указывается через параметр –p.

Через параметр –t задается шаблон выходного пакета. В этом случае результат преобразования сохраняется в content.xml (или другом потоке, указанном через параметр –p) пакета , а остальные потоки не преобразуются.

Использование опции –i позволяет указывать в качестве источника преобразования простой xml-файл .

Таким образом, чтобы создать ODF-документ из простого xml-документа, необходимо вызвать ODFXSLTRunner с параметрами –p и –i.

Множество применений может найти возможность использования в качестве выходного потока простого файл, а не ODF-пакета. Для указания такого файла используется параметр –o. Таким способом можно, например, получить результат преобразования в виде HTML.

В процессе преобразования изменениям можно подвергнуть и сам исходный файл, используя параметр –r. Он преобразует поток content.xml (или другой поток, указанный через параметр –p) исходного документа. Будьте очень осторожны с этой опцией!

Пары [name=value] содержат стандартные параметры XSLT в соответствии со спецификацией W3C. Они перечисляются после всех остальных параметров.

4. ODFXSLTRunnerTask

ODFXSLTRunnerTask – это определение задания (Task) для java-утилиты автоматизации сборки программного кода Ant, независимого от используемой платформы аналога UNIX-утилиты make. В результате включения этого задания в сценарий Ant (им является файл build.xml) к документу ODF применяются таблицы стилей XSLT.

Для сборки пакета, как и в предыдущем случае, необходимо открыть проект в NetBeans. Для работы инструмента требуются дополнительные библиотеки, список которых указан в соответствующем разделе сайта ODF Toolkit.

Чтобы использовать odfxsltrunner.jar совместно с Ant, необходимо включить в файл build.xml следующее определение задания:

Code
<taskdef name="odfxslt" classname="odfxsltrunnertask.ODFXSLTRunnerTask"
        classpath="<path>/odfxsltrunnertak.jar:<path>/odfxsltrunner.jar"/>



Здесь – это путь к файлам odfxsltrunnertask.jar и odfxsltrunner.jar.

Определение можно включать в сценарий Ant как на верхнем уровне в качестве дочернего элемента для , так и внутри отдельных элементов.

Задание во многом аналогично стандартному заданию ANT . Так, внутри можно использовать те же параметры, что и в , задавая их в элементах . Эти параметры приведены в таблице 1.

Таблица 1. Параметры и

Code
Параметр Описание Обязательность
in Определяет документ ODF, к которому применяется таблица стилей. Да, если не задан infile.
infile Определяет документ XML, к которому применяется таблица стилей. Да, если не задан in.
out Документ ODF, в котором сохраняется результат преобразования. Входной пакет копируется в выходной, после чего поток, указанный через параметр path, замещается результатом преобразования. Да, если не задан outfile.
outfile Определяет документ XML, в котором сохраняется результат преобразования. Да, если не задан out.
path Указывает поток внутри пакета ODF, который является источником преобразования или местом для сохранения результата. Нет.
template Если указан этот параметр, выбранный поток в выходном ODF-пакете (который должен существовать на момент применения данного параметра) замещается результатом преобразования, при этом предварительного копирования входного пакета в выходной не происходит. Нет.
По умолчанию content.xml.
force Если указан этот параметр, целевой файл будет создан заново, даже если он более поздний, чем файл источника или таблица стилей. Нет.
По умолчанию false.


5. OpenDocument for Java – odf4j

Odf4j – это библиотека java-классов, которая предназначена для поддержки работы с документами ODF в Java-приложениях. API, создаваемый в рамках этой разработки, предназначен для применения операций записи и чтения к документам в формате ODF, а также для управления документами прямо из java-приложений.

Существуют два уровня доступа:

* уровень пакета (Package Layer) предоставляет прямой доступ к ресурсам, хранящимся в ODF пакете: XML-схемам, изображениям и другим встроенным объектам;
* уровень документа предоставляет структурированный интерфейс к самому документу, здесь программист работает с разделами текста, параграфами, стилями и т.д.

Уровень пакета

На уровне пакета документ представляется как набор именованных ресурсов, к каждому из которых доступ организуется как к потоку. Ресурсы в формате xml, кроме того, могут быть представлены как документы DOM. Все изменения, вносимые в ресурсы в таком режиме, сохраняются в пакете автоматически.

Пример обращения к документу на уровне пакета:

Code
import org.openoffice.odf.OdfPackage;
import org.openoffice.odf.xml.OdfPackageStream;
import org.w3c.dom.Document;
import java.io.FileInputStream;
[...]

// открываем пакет
OdfPackage odfPackage = OpenDocumentFactory.load("testdocument1.odt");

// получаем content.xml как документ DOM
Document doc = odfPackage.getDocument(OdfPackage.STREAMNAME_CONTENT);

// работаем с DOM-документом
[...]

// добавляем картинку
FileInputStream fin=new FileInputStream("/tmp/mypicture.gif");
odfPackage.store("Pictures/mypicture.gif",fin,"image/gif");

// сохраняем документ
odfPackage.save("tesdocument1_processed.odt");

// освобождаем ресурс
odfPackage.close();



Уровень документа

На уровне документа мы работаем с иерархической структурой объектов, содержащих контент. Приложение может получать доступ к таким мелким объектам документа, как параграфы, секции, фреймы, гиперссылки и т.д. На этом уровне пользователь может редактировать документ, манипулируя его объектами. Возможно также добавление в существующий документ новых объектов и создание нового документа.

Пример доступа на уровне документа:

Code
import org.openoffice.odf.text.TextDocument;
import org.openoffice.odf.text.Body;
import org.openoffice.odf.text.Element;
import org.openoffice.odf.text.Paragraph;
import org.openoffice.odf.text.Portion;
[...]

TextDocument td = (TextDocument) OpenDocumentFactory.load("test/testdocument1.odt");
System.out.println("top level body structure:");
Body body = td.getBody();
// проходим по телу документа
for (Element element : body) {
   // обработчик разделов
   if (element instanceof Section) {
       Section section = (Section) element;
       for (Element se : section) {
           // обработчик абзацев
           if (se instanceof Paragraph) {
        Paragraph paragraph = (Paragraph)se;
               for (Element pe : paragraph) {
                   // обработка частей
                   if (pe instanceof Portion) {
                       Portion portion = (Portion)pe;
                       System.out.println("    portion: {" + portion.toString() +"}");
                   }
               }
           }
       }
   }
}
import org.openoffice.odf.OdfPackage;
import org.openoffice.odf.xml.OdfPackageStream;
import org.w3c.dom.Document;
import java.io.FileInputStream;
[...]


В следующем фрагменте кода создается новый документ:

Code
import org.openoffice.odf.text.TextDocument;
import org.openoffice.odf.text.Body;
import org.openoffice.odf.text.Element;
import org.openoffice.odf.text.Paragraph;
import org.openoffice.odf.text.Portion;
import org.openoffice.odf.text.List;
import org.openoffice.odf.text.ListItem;
[...]

// создаем новый текстовый документ
TextDocument textdoc = new TextDocument();
Body body = textdoc.getBody();

// добавляем абзац
body.add(new Paragraph(textdoc, "Hello World!"));

// еще один абзац
Paragraph p2 = new Paragraph(textdoc);
// вставляем текст в начало параграфа
p2.addText("Bar!");    
// добавляем абзац в конец документа        
body.add(p2);
// вставляем текст в начало второго абзаца
p2.insertText(0, "Foo, ");
         
//создаем список с элементами
List l1 = new List(textdoc,
   new ListItem(textdoc, "list item 1"),
   new ListItem(textdoc, "list item 2"),
   new ListItem(textdoc, "list item 3"));

// вставляем список в конец документа          
body.add(l1);

// сохраняем документ в файл new_document.odt
textdoc.save("new_document.odt");


Очевидно, что odf4j – полезный инструмент, но в настоящий момент работа над ним еще не завершена. В частности, не реализована возможность управления стилями текста и таблицами.

Заключение

Мы рассмотрели инструментальные средства, созданные для работы с ODF-документами в рамках проекта ODF Toolkit. Однако программные инструменты – это лишь «вспомогательная» часть в составе проекта.

Задачу упрощения разработки приложений, работающих с документами в формате ODF, решают два прикладных программных интерфейса. В следующей статье речь пойдет об основных разработках проекта – SDK для платформы Java ODFDOM (the OpenDocument API) и SDK для платформы .Net AODL (An Open Document Library).

Взято с: www.ibm.com