2013-10-04

剖析 OpenDocument Spreadsheet

承接在下上次篇寫的 PHP 輸出 OpenDocument Spreadsheet
在下嘗試慢慢拆解 OpenDocument Spreadsheet 中的 XML

將一個普通的 ods 檔案解壓縮,會得到一組檔案及資料夾,格式大概如下:
Thumbnails/
Thumbnails/thumbnail.png
mimetype
Configurations2/
Configurations2/images/
Configurations2/images/Bitmaps/
Configurations2/statusbar/
Configurations2/menubar/
Configurations2/popupmenu/
Configurations2/toolpanel/
Configurations2/toolbar/
Configurations2/floater/
Configurations2/progressbar/
Configurations2/accelerator/
Configurations2/accelerator/current.xml
settings.xml
meta.xml
styles.xml
content.xml
META-INF/
META-INF/manifest.xml
檔案名最後包含 / 符號表示為 目錄

上次提及 META-INF/manifest.xml 是一個重要檔案
此檔案可以當作 OpenDocument Spreadsheet 中將會使用的 XML 資訊,格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
<!-- declare mime type application/vnd.oasis.opendocument.spreadsheet for OpenDocument Spreadsheet -->
    <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/"/>
    <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
<!-- add more xml files include here
    <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="other.xml"/>
-->
</manifest:manifest>
在 manifest:manifest 中可以載入多個 manifest:file-entry
必須載入 <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/"/>
manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" 宣告文件為 OpenDocument Spreadsheet
manifest:full-path="/" 定義由該結構的 / 位置開始,連接其他文件 (如有)
以 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="other.xml"/> 載入其他文件
manifest:media-type="text/xml" 宣告載入的文件 mine type 為 text/xml
manifest:full-path="other.xml" 載入的文件位置,以 manifest:full-path 為基礎,可以使用絕對路徑

其實 格式化的 XML 資料不一定要指定命名為 content.xml , styles.xml 等名字
只要 格式化的 XML 文件中:
content 的 XML 以 office:document-content 格式編寫
styles 的 XML 以 office:document-styles 格式編寫
定義 XML 在 OpenDocument Spreadsheet 的用途即可,命名為相對名字只是為了方便程式員或分析員查看

OpenDocument Spreadsheet 內容是以 office:document-content 定義,格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2">
    <office:scripts>
<!-- macro scripts here ... -->
    </office:scripts>
    <office:font-face-decls>
<!-- used font faces here ... -->
    </office:font-face-decls>
    <office:automatic-styles>
<!-- table styles here ... -->
    </office:automatic-styles>
    <office:body>
<!-- table contents here ... -->
    </office:body>
</office:document-content>
office:document-content 主要分開 4 部分
office:scripts OpenDocument Spreadsheet 的 Macro 指令碼
office:font-face-decls OpenDocument Spreadsheet 所使用的字型宣告
office:automatic-styles OpenDocument Spreadsheet 所使用的樣式宣告
office:body OpenDocument Spreadsheet 的 表單內容
如果是進行匯出資料 office:scripts 通常都不會有內容,只需要寫上 <office:scripts/> 即可

office:font-face-decls 格式如下:
<office:font-face-decls>
<!-- add more font face here -->
    <style:font-face style:name="font-face-name" svg:font-family="&apos;font-face-name&apos;"/>
</office:font-face-decls>
每增加一個預設字型,便增加一個 style:font-face
需要注意 style:name 及 svg:font-family 雖然是相同,但 svg:font-family 的 字型名稱需要用 &apos; 包著

office:automatic-styles 格式如下:
<office:automatic-styles>
<!-- style:name can be any string of name, style ta-0 is relate to table will apply this table style -->
<!-- style:master-page-name can be any string of name, style page-style-0 is relate to table will apply this page setup style -->
    <style:style style:name="ta-0" style:family="table" style:master-page-name="page-style-0">
        <style:table-properties table:display="true"/>
    </style:style>
<!-- style:name can be any string of name, style ro-0 is relate to table row will apply this row style -->
    <style:style style:name="ro-0" style:family="table-row">
<!-- fo:break-before accepts auto|page|column|before -->
<!-- style:row-height accepts any float value with cm|in -->
<!-- style:use-optimal-row-height accepts true|false -->
        <style:table-row-properties fo:break-before="auto" style:row-height="1in" style:use-optimal-row-height="false"/>
    </style:style>
<!-- style:name can be any string of name, style co-0 is relate to table column will apply this column style -->
    <style:style style:name="co-0" style:family="table-column">
<!-- fo:break-before accepts auto|page|column|before -->
<!-- style:column-width accepts any float value with cm|in -->
        <style:table-column-properties fo:break-before="auto" style:column-width="1in" style:use-optimal-column-width="false"/>
    </style:style>
<!-- style:name can be any string of name, style ce-0-0 is relate to table cell will apply this cell style -->
    <style:style style:name="ce-0-0" style:family="table-cell" style:parent-style-name="Default">
<!-- style:vertical-align accepts top|middle|bottom -->
<!-- fo:border-top, fo:border-left, fo:border-right, fo:border-bottom accept any float value with cm|in|px for border width, solid|dotted|dashed|double for border style, #rrggbb value for border color -->
<!-- if fo:border-top, fo:border-left, fo:border-right, fo:border-bottom set the same values use fo:border to reduce the code -->
<!-- fo:background-color accepts #rrggbb value for border -->
        <style:table-cell-properties style:text-align-source="fix" style:repeat-content="false" style:vertical-align="middle" fo:border-top="2px solid #000000" fo:border-left="2px dotted #ff0000" fo:border-right="2px dashed #00ff00" fo:border-bottom="2px double #0000ff" fo:background-color="#ffffff"/>
<!-- fo:text-align accepts left|center|right -->
        <style:paragraph-properties fo:text-align="center"/>
<!-- fo:font-size, style:font-size-asian, style:font-size-complex accept any float value with pt|px, set as the same for these 3 attributes -->
<!-- fo:color accepts accepts #rrggbb value for border -->
<!-- style:font-name accepts a font face declared in office:font-face-decls -->
        <style:text-properties fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" fo:font-italic="italic" style:font-italic-asian="italic" style:font-italic-complex="italic" fo:color="#000000" style:font-name="font-face-name"/>
    </style:style>
</office:automatic-styles>
office:automatic-styles 是文件的樣式,可以分為
<style:style style:family="table"> OpenDocument Spreadsheet 單行 的樣式
<style:style style:family="table-row"> OpenDocument Spreadsheet 表單行 的樣式
<style:style style:family="table-column"> OpenDocument Spreadsheet 表單欄 的樣式
<style:style style:family="table-cell" style:parent-style-name="Default"> OpenDocument Spreadsheet 表單格 的樣式
style:family 需要宣告 style:name

通常 style:family="table" 時使用 ta- 為前綴
table 會使用 <style:table-properties> 主要使用
style:master-page-name 為使用指定頁面設定的名稱

通常 style:family="table-row" 時使用 ro- 為前綴
table-row 會使用 <style:table-row-properties> 主要使用
fo:break-before="auto" 文字跳行,可選用 auto 為自動分隔, page 以頁分隔, column 以欄分隔, before (不明)
style:row-height="1in" 設定行高,可以使用任何浮點數,而單位可選用 cm 為公分,in 為英寸
style:use-optimal-row-height="false" 使用最佳欄闊,可選用 true 為自動行高,或 false 為使用 style:row-height

通常 style:family="table-column" 時使用 co- 為前綴
table-column 會使用 <style:table-column-properties> 主要使用
fo:break-before="auto" 文字跳行,可選用 auto 為自動分隔, page 以頁分隔, column 以欄分隔, before (不明)
style:column-width="1in" 設定欄闊,可以使用任何浮點數,而單位可選用 cm 為公分,in 為英寸
style:use-optimal-column-width="false" 使用最佳欄闊,可選用 true 為自動欄闊,或 false 為使用 style:column-width

通常 style:family="table-cell" 時使用 ce- 為前綴
table-cell-column 會使用 <style:table-cell-properties> 主要使用
style:vertical-align 為文字垂直放置位置 top, middle, bottom 分別為上、中、下
fo:border-top, fo:border-left, fo:border-right, fo:border-bottom 為表單格的邊界樣式對應位置為上、左、右、下
屬性值為 數值及單位 樣式 顏色 例如 2px solid #000000
如果上、左、右、下都使用相同設定可以簡化使用 fo:border
fo:background-color 為表單格的背景顏色
style:paragraph-properties 的 fo:text-align 為文字水平放置位置 start, center, end 分別為左、中、右
style:text-properties 的
fo:font-size, style:font-size-asian, style:font-size-complex 為字元大小,單位以 pt 為標準
fo:color 為表單格文字顏色
style:font-name 為表單格所使用有字型
<office:body>
    <office:spreadsheet>
<!-- table:name accepts any string of name -->
        <table:table table:name="sheet-name">
<!-- table:style-name retrieves the declared table:style-name and the style:family="table-column" -->
            <table:table-column table:style-name="co-0"/>
<!-- table:style-name retrieves the declared table:style-name and the style:family="table-row" -->
            <table:table-row table:style-name="ro-0">
<!-- table:style-name retrieves the declared table:style-name and the style:family="table-cell" -->
<!-- office:value-type accepts boolean|currency|date|float|percentage|string|time -->
<!-- table:number-rows-spanned accepts an integer which > 0, if not present default 1 -->
<!-- table:number-columns-spanned accepts an integer which > 0, if not present default 1 -->
<!-- <![CDATA[some text]]> some text is any string of text, <![CDATA[]]> can escape any special characters as normal characters in XML -->
                <table:table-cell table:style-name="ce-0-0" office:value-type="string" table:formula="oooc:=SUM([.A1])" table:number-rows-spanned="1" table:number-columns-spanned="1"><text:p><![CDATA[some text]]></text:p></table:table-cell>
            </table:table-row>
        </table:table>
    </office:spreadsheet>
</office:body>
office:body 為文件內文,其 XML 的結構與 HTML 的 table 相似
office:body 包含一個 office:spreadsheet , office:spreadsheet 包含一個或多個 table:table
table:table 需要宣告 table:name 長度必須大於1 ,而且所有 table:table 的 table:name 都不能重覆
值得注意是 table:table-column 在 table:table 中是獨立的 tag

table:table-column 的 table:style-name 可接收 <style:style style:family="table-column"> 的 style:name
table:table-row 的 table:style-name 可接收 <style:style style:family="table-row"> 的 style:name
table:table-cell 的 table:style-name 可接收 <style:style style:family="table-cell"> 的 style:name
table:number-rows-spanned 為跨行數量,必須是正整數,不設定為 1 ,與 HTML td 的 rowspan 相同
table:number-columns-spanned 為跨欄數量,必須是正整數,不設定為 1 ,與 HTML td 的 colspan 相同
office:value-type 可選用 boolean, currency, date, float, percentage, string, time 幾種型態
相對使用 office:boolean-value, office:currency, office:date-value, office:value, office:value, office:string-value, office:time-value
float 及 percentage 都是使用 office:value
而作為 float 或 percentage 型態,可以使用指數寫法,例如 1E+6 代表 1000000 (一百萬)
office:boolean-value 則是 true 或 false

table:formula 是定義表單格中的運算方程式,資料必須輸入 oooc:= 為前綴
若需要存取表單格,便需要用 [.] 包著目標表單格,例如 [.A1] 以存取 A1 表單格
若需要存取表單範圍,可以於 [.] 使用 : 例如 [.A1:B2] 以存取 A1 至 B2 表單範圍
text:p 則是在 表單格中顯示的文字資料,例如 office:value 為 1 可以在 text:p 指定顯示為 1.00
<![CDATA[]]> 這種寫法可以讓 XML 的特殊符號,如 & 符號以普通文字顯示而不需要轉換成 &amp;

OpenDocument Spreadsheet 風格是以 office:document-style 定義,格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<office:document-styles xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2">
    <office:font-face-decls>
<!-- used font face here -->
    </office:font-face-decls>
    <office:automatic-styles>
<!-- sheet style here -->
    </office:automatic-styles>
    <office:master-styles>
<!-- apply the style to table here -->
    </office:master-styles>
</office:document-styles>
office:document-style 主要分開 3 部分
office:font-face-decls OpenDocument Spreadsheet 所使用的字型宣告
office:automatic-styles OpenDocument Spreadsheet 所使用的樣式宣告
office:master-styles OpenDocument Spreadsheet 的表單所應用的樣式

office:automatic-styles 格式如下:
<office:automatic-styles>
<!-- style:name can be any string of name, style page-setup-0 is relate to table will apply this page setup style -->
    <style:page-layout style:name="page-setup-0">
<!-- fo:page-width and fo:page-height accept any float value with cm|in -->
<!-- style:print-orientation accepts portrait|landscape -->
<!-- fo:margin-top, fo:margin-left, fo:margin-right, fo:margin-bottom accept any float value with cm|in -->
<!-- if fo:margin-top, fo:margin-left, fo:margin-right, fo:margin-bottom set the same values use fo:margin to reduce the code -->
<!-- style:table-centering accepts none|horizontal|vertical|both -->
<!-- style:writing-mode accepts lr-tb|tb-lr -->
        <style:page-layout-properties fo:page-width="21cm" fo:page-height="29.7cm" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-left="2cm" fo:margin-right="2cm" fo:margin-bottom="2cm" style:table-centering="none" style:writing-mode="lr-tb"/>
        <style:header-style>
<!-- fo:min-height accepts any float value with cm|in -->
<!-- fo:margin-left accepts any float value with cm|in -->
<!-- fo:margin-right accepts any float value with cm|in -->
<!-- fo:margin-bottom accepts any float value with cm|in -->
            <style:header-footer-properties fo:min-height="0.5cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.25cm"/>
        </style:header-style>
        <style:footer-style>
<!-- fo:min-height accepts any float value with cm|in -->
<!-- fo:margin-left accepts any float value with cm|in -->
<!-- fo:margin-right accepts any float value with cm|in -->
<!-- fo:margin-top accepts any float value with cm|in -->
            <style:header-footer-properties fo:min-height="0.5cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.25cm"/>
        </style:footer-style>
    </style:page-layout>
</office:automatic-styles>
style:page-layout 的 style:name 為讓表單所使用的樣式的名稱
style:page-layout-properties 的
fo:page-width, fo:page-height 分別為表單的闊及高,屬性值為 數值及單位
style:print-orientation 為表單方向,portrait 為直向,landscape 為橫向
不過直向或橫向並沒有必定意思,例如設定 style:print-orientation 為 portrait 但 fo:page-width 設定值比 fo:page-height 大,表格其實是橫向
但會影響列印設定,因此設定 style:print-orientation 時,應配合 fo:page-width 及 fo:page-height
fo:margin-top, fo:margin-left, fo:margin-right, fo:margin-bottom 分別是設定上、左、右、下的頁邊距離,屬性值為 數值及單位
如果上、左、右、下都使用相同設定可以簡化使用 fo:margin
style:table-centering 為表單中心設定,none 為不設定,horizontal 為水平置中,vertical 為垂直置中,both 為水平及垂直置中
style:writing-mode 為控制列印次序 lr-tb 為先由上至下再左至右,tb-lr 為先左至右再上至下

style:header-style 為頁首設定
style:header-footer-properties 的
fo:min-height 為最少高度設定,屬性值為 數值及單位
fo:margin-left, fo:margin-right, fo:margin-top 分別是設定左、右、上的頁邊距離,屬性值為 數值及單位

style:footer-style 為頁首設定
style:header-footer-properties 的
fo:min-height 為最少高度設定,屬性值為 數值及單位
fo:margin-left, fo:margin-right, fo:margin-bottom 分別是設定左、右、下的頁邊距離,屬性值為 數值及單位
留意 header 沒有 fo:margin-bottom 及 footer 沒有 fo:margin-top

office:master-styles 格式如下:
<office:master-styles>
    <style:master-page style:name="page-setup-0"/>
</office:master-styles>
master-page 的
style:name 為讓表單使用的名稱

更多資料有待研究,或閣下參與

沒有留言 :

張貼留言