Наверх

Файлы MS Office "изнутри". Open Packaging Conventions. Базовые принципы. Компоненты и связи

Время чтения: 15 минут
0
Файлы MS Office

Сегодняшним постом я хочу начать серию материалов. В ней я планирую немного поговорить о том, что представляют собой файлы MS Office “изнутри”, а также об инструментах (утилитах и библиотеках) для их создания, изучения, изменения, …

imageСегодняшним постом я хочу начать еще одну серию. В ней я планирую немного поговорить о том, что представляют собой файлы MS Office “изнутри”, а также об инструментах (утилитах и библиотеках) для их создания, изучения, изменения, …

Прежде чем перейти к содержательной части некоторый предваряющий disclaimer (традиционно Улыбка):

●   Я в основном буду касаться современных офисных форматов, тех что появились в редакции Office 2007. Их еще называют XML-based форматами, в противовес старым бинарным (и это закрепилось в расширении файлов: docx, pptx, xlsx, … – в противовес doc, ppt, xls, …), ну или просто Open XML

●   Некоторая часть статей (по крайней мере в самом начале) будет основана на материалах Open XML Developer Workshop (контент и видео), который вел Doug Mahugh. Если вам не хочется ждать моих статей рекомендую обратиться к этим материалам

●   Еще одним хорошим подспорьем для изучающих Open XML будет книга Воутер Ван Вугт. OpenXML. Кратко и доступно. Ранее она в электронном виде была доступна в блоге евангелиста Microsoft Владимира Габриеля, но теперь – увы. Так что, если вам интересно и не хочется тратить время на поиск, можете взять здесь.

Вроде бы все. Можно приступать.

Что такое Open Packaging Conventions?

В двух словах, это формат контейнеров, поддерживающих хранение как структурированных (XML), так и неструктурированных компонентов (картинки, видео, бинарные компоненты, …) в одном файле.

Краткая но довольно информативная статья об OPC есть на wikipedia.

Что можно сказать в общем об этом стандарте/формате? Я бы выделил такие моменты:

●   Формальное описание является частью ECMA-376. Office Open XML File Formats, более конкретно – второй частью Part 2 — Open Packaging Conventions.

●   Сам стандарт описывает только структуру хранения и самые общие метаданные (типа автора, даты,…) поэтому потенциально в таком контейнере можно хранить практически что угодно.

Например, вот несколько форматов, основанных на OPC от самого Microsoft:

o    .docx, pptx, xlsx, .vsdx – форматы Word, Power Point, Excel и Visio

o    .xps (.oxps) – формат “электронной бумаги” или формат c фиксированной разметкой, предназначенный для передачи документов без искажения форматирования (в чем-то аналог PDF).

o    .vsix – формат расширений Visual Studio, начиная с версии 2010

o    .cspkg – формат пакетов для Windows Azure Cloud Services

o    .appx – формат пакетов приложений Windows Store (для Windows 8)

Что представляют собой контейнеры в OPC?

Тут нужно сделать одну существенную оговорку: сам стандарт разбивает описание контейнеров на 2 части: абстрактную модель (которая описывает из каких элементов состоят контейнеры, но ни слова не говорит о том как это должно храниться физически) и физический формат пакета, т.е. конкретную реализацию.

Т.е. в чистой теории, контейнер в OPC может храниться единый файл, а может, например,  как набор отдельных ресурсов на Web-сервере. Но (!) на текущий момент определена только 1 реализация – в виде единого файла ZIP-архива.

Структура контейнеров в OPC

Вообще говоря, концептуальная схема пакетов в Open Packaging Conventions очень проста, она включает в себя всего два элемента:

●   компоненты (parts), которые собственно и содержат хранящийся контент (любой: xml, image, video, …)

●   отношения (relationships), которые определяют

o    предназначение (смысл/семантику) каждой части

o    отношения между частями, а также между частями и пакетом целиком

image

Компоненты

Как уже было сказано выше компонент в OPC это и есть основная единица хранения контента. Каждый компонент характеризуется 2-я составляющими: именем и типом содержимого.

Имя компонента состоит из набора сегментов, начинающихся с прямого слэша (“/”), вот несколько примеров:

●   /hello/world/doc.xml

●   /docProps/app.xml

●   /image4.png

В спецификации приведены более формальные правила построения имен, из которых я укажу только основные (на мой взгляд):

●   все имена должны начинаться с прямого слэша (“/”) и не должны им заканчиваться

●   имя недолжно содержать пустых сегментов (т.е. /images//image1.jpg – неправильное имя)

●   сегменты могут состоять из букв, цифр и знаков «!«, «$«, «&«, «‘«, «(«, «)«, «*«, «+«, «,«, «;«, «=«, «-«, «.«, «_«, «~«, «:«, «@»

●   ни одно имя компонента не должно строиться как имя уже существующего компонента + новый сегмент. Т.е. если есть компонент с именем /abc/abc, то компонент с именем /abc/abc/a существовать не может, зато вполне может существовать компонент с именем /abc/abcde

●   имена могут записываться Unicode-символами или использовать кодирование в виде /a/%D1%86.xml

Тип содержимого компонента задается в соответствии с RFC 2616 (раздел Media Types) т.е. в виде <type>/<subtype>:

●   application/xml

●   image/jpeg

●   application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml

Связи

Любой компонент в пакете (а также сам пакет) может ссылаться на другие компоненты или некоторые ресурсы за пределами пакета. Для представления этих ссылок введен специальный механизм связей. По большому счету, связи позволяют решить 2 задачи:

●   получить список связанных с компонентом ресурсов, без необходимости анализировать его содержимое (которое может быть очень большим, иметь разную структуру, быть зашифрованным или вообще не поддерживать хранение ссылок)

●   поменять набор связей компонента, не меняя его содержимого (которое может быть, например, зашифровано или защищено цифровой подписью)

Создавая свой пакет вы, конечно же, можете не использовать связи. Вместо этого везде в коде использовать фиксированные имена компонент, а где нужны списки связанных ресурсов, ссылаться на них прямо из самих компонент. Однако, рекомендации “лучших собаководов” все же советуют использовать связи везде, где это возможно.

Информация о связях для каждого компонента (а также самого пакета), хранится в специальных компонентах связей (relationships parts) тип содержимого которых application/vnd.openxmlformats-package.relationships+xml

Имена компонентов связи строятся из имени исходных компонент, к которым:

●   добавляется предпоследний сегмент с именем _rels

●   дописывается “расширение” .rels

Связи самого пакета хранятся в специальном компоненте с именем /_rels/.rels

Например, если в пакете у нас есть компонент с именем /document/mainPart.xml и два связанных компонента с картинками (пусть их мена будут /images/image1.png и /images/image2.jpeg), то пакет для них будет иметь следующую структуру:

image

Содержимое компонента связи представляет собой XML следующего формата:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="https://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Id="rId1"
    Type="https://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"
    Target="styles.xml" />
  <Relationship Id="rId2"
    Type="https://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
    Target="theme/theme1.xml" />
  <Relationship Id="rId3"
    Type="https://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"
    Target="fontTable.xml" />
  <Relationship Id="rId4"
    Type="https://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
    Target="file:///C:\Users\Public\Pictures\Sample%20Pictures\Desert.jpg"
    TargetMode="External" />
</Relationships>

Как уже наверняка понятно из приведенного фрагмента, каждый тэг <Relationship> определяет одну связь. Его атрибуты:

Id

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

Type

Тип связи. По сути дела тип указывает семантику связи. Например, две разных связи могут указывать на 2 компонента типа image/jpeg, но одно изображение будет картинкой в тексте документа, а второе – миниатюрой (thumbnail) всей страницы целиком.
В качестве типа может использоваться любой валидный URI

TargetMode

(Необязательный) Принимает одно из возможных значений:

·  Internal (значение по умолчанию) – указывает, что связь ссылается на компонент пакета

·  External – связь указывает на ресурс за пределами пакета

Target

Адрес ресурса или компонента на который ссылается связь

Важный момент: для обращения к компонентам и внешним ресурсам можно использовать как абсолютные адреса (для компонент это будет их полное имя), так и относительные. В последнем случае полное имя компоненты рассматривается как путь в файловой системе, каждый сегмент, кроме последнего – имя “папки”, а последний – имя “файла”. Вот несколько примеров такой адресации:

Имя исходного компонента

Относительный адрес

Результирующий адрес

/mydoc/markup/page.xml

picture.jpg

/mydoc/markup/picture.jpg

/mydoc/markup/page.xml

images/picture.jpg

/mydoc/markup/images/picture.jpg

/mydoc/markup/page.xml

./picture.jpg

/mydoc/markup/picture.jpg

/mydoc/markup/page.xml

../picture.jpg

/mydoc/picture.jpg

/mydoc/markup/page.xml

/images/picture.jpg

/mydoc/images/picture.jpg

/

images/picture.jpg

/images/picture.jpg

Вот, по большому счету и все, что касается модели пакета в OPC. Осталось сказать несколько слов о физической реализации пакетов

Пакеты на основе ZIP-архивов

Как уже было сказано выше, в спецификации OPC определена только одна реализация пакетов – на основе ZIP архивов. Она достаточно проста, поэтому я приведу её обзорно:

●   все компоненты, как обычные, так и компоненты связей, хранятся в виде одного или нескольких файлов внутри архива (при этом логически они все равно адресуются как единое целое)

●   для хранения типа контента каждого компонента в архиве создается специальный файл с именем [Content_Types].xml

Внутри файла [Content_Types].xml хранится XML следующего вида:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="https://schemas.openxmlformats.org/package/2006/content-types">
    <Default Extension="png" ContentType="image/png"/>
    <Default Extension="jpeg" ContentType="image/jpeg"/>
    <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
    <Default Extension="xml" ContentType="application/xml"/>
    <Override PartName="/word/document.xml"
        ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
    <Override PartName="/word/styles.xml"
        ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
</Types>

Собственно, общая схема, я думаю, понятна и так: для описания типов используется два подхода:

●   указание типа по расширению (тэг <Default>)

●   явное указание типа для конкретного компонента (тэг <Override>)

Как заглянуть внутрь OPC-пакета?

Итак, надеюсь вас уже заинтриговало мое объяснение базовых принципов и вы уже жаждите приступить к практическому изучению (т.е. взять и разобрать по косточкам какой-нибудь офисный файл) Улыбка.

Вот несколько способов как это можно сделать:

●   Прямой (“рукопашный”) способ. Т.к. физическая реализация OPC есть ни что иное, как обычный ZIP-архив, то самый простой способ его изучить – распаковать и работать как с обычной папкой (ну или воспользоваться любимым архиватором).

o    Плюс подхода – будете глубже понимать устройство.

o    Минусы:

▪           Сложно отслеживать связи между компонентами (а именно они образуют структуру, а вовсе не “папки” архива)

▪           Довольно муторно редактировать, если захочется экспериментов (нужно добавлять файлы для компонентов, править файлы связей да еще и не забывать про указание типа контента, если он не стандартный)

image

●   Open XML Package Editor Power Tool for Visual Studio 2010. Расширение для Visual Studio. Умеет открывать файлы в формате OPC, показывать и редактировать их логическую структуру (добавлять/удалять/редактировать компоненты и связи). Для редактирования содержимого компонент используется редакторы самой VS, что очень удобно для экспериментов (XML редактор в VS явно не самый плохой, особенно если в наличии есть хорошие XSD-описания).

o    Минусы:

▪           Так и не нашел способа создать пакет с 0 (но это редко нужно, да и обходится созданием пакета вручную).

▪           Требует Visual Studio.

▪           Работает только в 2010 версии VS. Увы, для более новых версий студии пакет так и не обновился, хотя почти наверняка он заработает без доработок в любой последующей. А доработать установщик пакета руками не получается, т.к. это не обычный vsix Печальная рожица

image

●   Standalone приложение от Воутера Ван Вугта Open XML Package Explorer. По возможностям оно близко к предыдущему расширению для VS, но не требует ничего для установки, кроме .Net 3.0. У него даже есть встроенный редактор XML, правда уступающий редактору от VS. К сожалению, приложение давно не обновлялось имеет ряд неприятных ошибок… но пользоваться можно.

image

Пара слов в заключение

Как видите, стандарт OPC в своей основе довольно прост и функционален. Однако остались еще ряд нераскрытых тем. В частности мы не рассмотрели ряд возможностей, заложенных в формат OPC:

●   базовые метаданные пакета (core properties)

●   иконки пакета (thumbnails)

●   цифровые подписи (digital signatures)

Ну и, конечно, мы еще ни слова не проговорили об API для работы с OPC пакетами.

Источник: Блог Михаила Романова.

Чтобы прочитать эту статью до конца,
или зарегистрируйтесь

Комментарии 0

Чтобы прокомментировать, или зарегистрируйтесь