ODFDOM for Java:简化文档及其数据的程序控制,第 3 部分
2010-06-23 00:00:00 来源:WEB开发网使用 ODFDOM 来创建文本、电子表格和演示图形文档
首先,我们简要描述一下 ODF 文档结构。ODF 文档保存在一个 ZIP 压缩包中,它包含 content.xml、style.xml 及其他若干文档。
Content.xml 用来保存文档内容,style.xml 用来保存文档样式信息。content.xml 文件也含有一些样式信息,可以用来自动创建一些默认值,如字体和颜色。
一般来说,操作一个 ODF 文档分四步:
加载已有 ODF 文档或创建 ODF 文档。
向 ODF 文档插入内容。
为信息的不同部分设置样式。
保存文档。
ODFDOM 现在提供一些 API,借助它们,可以轻松完成这四步主要操作。
创建文本文件
在本小节中,我们将演示一个简单用例:读取一个 XML 文件并输出到 ODF 文档。
作为文本文件,content.xml 层级如下(见清单 1):
第一个元素是 <office:body>,它是文档根目录的子元素。
下一级是 <office:text> 元素,它表示所有要保存在输出文档中的文档元素。
在 <office:body> 之前的 <office:automatic-styles> 是文档根目录的另一个子元素,用于保存元素的各种样式信息。
清单 1. 文本文件 content.xml 级的结构
<office:document-content>
<office:automatic-style/>
<office:body>
<office:text/>
</office:body>
</ office:document-content>
此处,<office:style> 和 <office:automatic-styles> 都定义了一些样式,但有些区别。<office:style> 通常用来定义常用样式。一般通过设置样式名称来应用 <office:style> 中定义的样式。从 ODF 编辑器的角度来看,<office:style> 中定义的样式是由用户定义的一组特征值。
另一方面,<office:automatic-styles> 中定义的样式包含一些特别的样式属性。从 ODF 编辑器的角度看,它用于编辑对象的某些属性。
ODFDOM 提供对象来表示各种文档的 ODF 包:
OdfTextDocument textDocument:对应于一个文本文件(odt)对象。
OdfFileDom contentDom:对应于 content.xml 的 XML 文档对象。
OdfFileDom stylesDom:对应于 styles.xml 的 XML 文档对象。
文本文件对象可以使用 API 来获取内容对象(content.xml)和样式对象(styles.xml):
OdfFileDom contentDom = textDocument.getContentDom()
OdfFileDom stylesDom = textDocument.getStylesDom()
ODFDOM 还提供多个对象来表示各种内容和样式元素:
OdfOfficeAutomaticStyles contentAutoStyles:对应 content.xml 中 <office:automatic-styles>。
OdfOfficeStyles stylesOfficeStyles:对应 styles.xml 中 <office:styles>。
OdfOfficeText officeText:对应 content.xml 中 <office:text>。
用 ODFDOM API 获取内容元素对象和文本元素对象也很容易:
OdfOfficeAutomaticStyles autoStyles = textDocument.getContentDom (). GetAutomaticStyles ()
OdfOfficeStyles styles = textDocument.getDocumentStyles ();
OdfOfficeText text = (OfficeText) textDocument.getContentRoot ();
ODFDOM 还提供一个 API 来对 ODF 文档进行文件级操作,例如,可以用来创建文本文件、加载已有文件以及保存文件:
OdfTextDocument odtDoc = OdfTextDocument.newTextDocument (); / / 创建文本文件
OdfTextDocument odtDoc = (OdfTextDocument) OdfDocument.loadDocument ( "text.odt"); / / 加载已有文本文件
odtDoc.save ( "text.odt") / / 保存文件
当然,文本文件没有丰富的样式属性也不行,如文本字体、段落布局、项目符号。因此,ODFDOM 也有处理这些样式属性的方法:
OdfStyle style = odtDoc.getDocumentStyles (). getStyle ( "myStyle",
OdfStyleFamily.Paragraph);
/ / 从文本文件获取用户定义的样式(style)对象
style.setProperty (OdfStyleTextProperties.FontWeight, "bold");
/ / 将样式设置为特定属性值
设置文本样式属性的代码如清单 2 所示。
清单 2. 设置文本样式属性的代码
OdfTextParagraph para;
para.setProperty (OdfStyleTextProperties.FontSize, "17pt");
para.setProperty (OdfStyleParagraphProperties.TextAlign, "left");
para.setProperty (OdfStyleChartProperties.DataLabelNumber, "value");
使用特征值的代码可以应用到特定文档元素,这种方式产生的样式是 <office:automatic-style>。
我们介绍了文本文件及 API 的重要用法。在下面的例子中,我们将看一个 ODFDOM 应用程序,它从 XML 文件中读出数据,然后通过 ODFDOM API 操作,数据以特定格式保存到 ODF 文本文档中(见清单 3-7)。
清单 3. XML 数据文件 book.xml
<book>
<title> The ODFDOM tutorial </ title>
<author> IBM ODF team </ author>
<content> introduce ODFDOM usage </ content>
</ book>
清单 4. 使用 Java DOM API 来解析要读取的 XML 文档
DocumentBuilder builder = null;
inputDocument = null;
try (
inputXPath = XPathFactory.newInstance (). newXPath ();
builder = DocumentBuilderFactory.newInstance (). newDocumentBuilder ();
inputDocument = builder.parse ( "book.xml");
) catch (IOException e) (
System.err.println ( "Unable to read input file.");
System.err.println (e.getMessage ());
) catch (Exception e) (
System.err.println ( "Unable to parse input file.");
System.err.println (e.getMessage ());
)
清单 5. 创建文本 ODF 对象
try (
OdfTextDocument odtDocument = OdfTextDocument.newTextDocument ();
OdfFileDom contentDom = outputDocument.getContentDom ();
OdfFileDom stylesDom = outputDocument.getStylesDom ();
contentAutoStyles = contentDom.getOrCreateAutomaticStyles ();
OdfOfficeStyles stylesOfficeStyles = odtDocument.getOrCreateDocumentStyles ();
officeText = outputDocument.getContentRoot ();
) catch (Exception e) (
System.err.println ( "Unable to create output file.");
System.err.println (e.getMessage ());
odtDocument = null;
)
由于内容和样式需要额外信息来补充完整,必须向这个新文本文件的内容 DOM 树插入内容元素,并向内容和样式 DOM 树插入自动样式元素(见清单 6 和 7)。
清单 6. 将 XML 内容读到 ODF 文本文件中
NodeList booklist = inputDocument.getElementsByTagName ( "book");
Node book = booklist [0];
String title = inputXPath.evaluate ( "book / title", book);
String author = inputXPath.evaluate ( "book / author", book);
String content = inputXPath.evaluate ( "book / content", book);
OdfTextHeading heading = (OdfHeading) officeText.newTextHElement (title);
(OdfTextParagraph) para = (OdfTextParagraph) newTextPElement ();
para. addContent (content);
清单 7. 样式应用到文本内容
OdfStyle style1 = odtDocument.getOrCreateDocumentStyles ().
NewStyle ( "hStyle", OdfStyleFamily.Text);
style.setProperty (OdfTextProperties.FontWeight, "bold");
style.setProperty (OdfTextProperties.FontStyle, "italic");
style.setProperty (OdfTextProperties.FontSize, "16");
heading.setStyleName ( "hStyle");
OdfStyle style2 = odtDocument.getOrCreateDocumentStyles ().
NewStyle ( "pStyle", OdfStyleFamily.Text);
style.setProperty (OdfTextProperties.FontStyle, "italic");
style.setProperty (OdfTextProperties.FontSize, "10");
para.setStyleName ( "pStyle");
最后,保存 ODT 文本文件:
odtDocument.save ( "text.odt")
可以使用 OpenOffice 或 IBM® Lotus® Symphony™ 来打开新文件,并看到 ODFDOM 如何通过直接访问 API 产生结果。
创建电子表格文件
首先,我们看一下电子表格文档的 content.xml 的主要结构(见清单 8)。
清单 8. 电子表格 content.xml 的结构
<office:document-content>
<office :automatic-style/>
<office :body>
<office:spreadsheet>
<table:table/>
</ Office: spreadsheet>
</ office: body>
</ Office: document-content>
电子表格文档中,主要元素有:
<table:table> 是表的根元素,表内容的所有元素都是它的子元素
<table:column> 指定电子表格的宽度,是默认的样式定义
<table:row> 表示表格行,由多个 <table:cell> 元素组成
对于 <table:cell> 元素,两个属性 office:value-type 和 office: value,通常必须用子元素 <text:p> 指定。
ODFDOM 有很多与文件相关的对象:
OdfSpreadsheetDocument | content.xml |
OdfTable | <table:table> |
OdfTableColumn | <table:table-column> |
OdfTableRow | <table:table-row> |
OdfTableCell | <table:table-cell> |
其中:
OdfTable 对象表示电子表格的表。
OdfTableColumn 用来指定电子表格的列,列数通过 TableNumberColumnsRepeatedAttribute 属性值设置。
OdfTableRow 用来表示表格行。一行由一个或多个 OdfTableCell 对象组成。
OdfTableCell 是组成表格元素的单元,每个单元格对象可以用来放值、段落和其他文本内容;通常需要设置三个属性值:
OfficeValueAttribute
OfficeValueTypeAttribute
TextContent
OfficeValueTypeAttribute 用来指定保存数据的类型(字符、数字、日期、时间、公式等);OfficeValueAttribute 用来保存值;TextContent 用来保存用户看到的值。
现在创建一个三行四列的表格来演示如何对表特性使用 ODFDOM API 操作(见清单 9):
创建 OdfSpreadsheetDocument 电子表格对象。
得到 OdfOfficeSpreadsheet 根。
创建 OdfTable 对象。
创建 <table:column> 元素,设置 table:number-columns-repeated 属性为表中列数。
使用循环为每一行创建 <table:row> 元素。
使用循环为每行中的单元格创建 <table:cell> 元素,并填入值。
保存电子表格。
清单 9. 构造电子表格
int data [][]= ((1,2,3,4), (5,6,7,8), (9,10,11,12));
OdfSpreadsheetDocument odfdoc = OdfSpreadsheetDocument.newSpreadsheetDocument ();
OdfOfficeSpreadsheet spreadsheet = odfdoc.getContentRoot ();
OdfTable table = (OdfTable) spreadsheet.newTableTableElement ();
OdfTableColumn column = (OdfTableColumn) table.newTableTableColumnElement ();
column.setTableNumberColumnsRepeatedAttribute (new Integer (4));
for (int i = 0; i <3; i) (
OdfTableRow row = (OdfTableRow) table.newTableTableRowElement ();
/ / row.setStyleName ( "ro1");
for (int j = 0; j <4; j) (
OdfTableCell cell = (OdfTableCell) row.newTableTableCellElement ();
cell.setOfficeValueAttribute (new Double (data [i] [j]));
cell.setOfficeValueTypeAttribute ( "float");
cell.setTextContent ((new Double (data [i] [j]). toString ()));
)
) Odfdoc.save (ResourceUtilities.createTestResource ( "table3R4C.ods"));
表特性经常包含日期和时间值,这些值的表示在各国家和地区会不一样。ODFDOM 不仅提供合适的方法来设置日期和时间格式,还有一些特别的类用于这种格式。
例如,OdfNumberDateStyle 用于处理日期格式,OdfNumberTimeStyle 用来处理时间格式,OdfNumberStyle 用来处理数字格式。
这些样式元素可以放在 <office:automatic-styles> 元素下(见清单 10),如下所示:
用 getStylesDom () 取得 OdfAutomaticStyles 对象。
创建对应类的对象。
设置样式对象的具体格式。
清单 10. 设置数字样式
OdfOfficeAutomaticStyles autoStyles = odfdoc.getStylesDom (). GetAutomaticStyles ();
OdfNumberDateStyle dataStyle = (OdfNumberDateStyle)
autoStyles.newNumberDateStyleElement ( "numberDateStyle");
dataStyle.buildFromFormat ( "yyyy-MM-dd");
OdfNumberTimeStyle timeStyle = (OdfNumberTimeStyle)
autoStyles.newNumberTimeStyleElement ( "numberTimeStyle");
timeStyle.buildFromFormat ( "hh: mm: ss");
OdfNumberStyle numberStyle = (OdfNumberStyle)
autoStyles.newNumberNumberStyleElement ( "numberStyle");
numberStyle.buildFromFormat ( "# 0.00");
然后指定单元格样式,然后将其和数字样式对象关联到单元格样式对象(见清单 11):
创建 OdfStyle 对象,它的层次是表单元格。
用 getStyleNameAttribute () 取得日期和数字样式名。
用 setStyleDataStyleNameAttribute() 设置日期和数字样式名为单元格样式对象的 style:data-stylename 属性。
将单元格样式应用到具体的单元格。
清单 11. 应用单元格样式
Cell style for date cells:
OdfStyle style;
style = autoStyles.newStyle (OdfStyleFamily.TableCell);
String dataCellStyleName = style.getStyleNameAttribute ();
style.setStyleDataStyleNameAttribute ( "numberDateStyle");
cell.setStyleName (dataCellStyleName);
And for time cells:
style = autoStyles.newStyle (OdfStyleFamily.TableCell);
String timeCellStyleName = style.getStyleNameAttribute ();
style.setStyleDataStyleNameAttribute ( "numberTimeStyle");
cell.setStyleName (timeCellStyleName);
And for the temperatures:
style = autoStyles.newStyle (OdfStyleFamily.TableCell);
String numberCellStyleName = style.getStyleNameAttribute ();
style.setStyleDataStyleNameAttribute ( "numberStyle");
cell.setStyleName (numberCellStyleNam);
本例中,创建了一个简单的电子表格,但实际上,电子表格可能会相当复杂。例如,可能有跨行和跨列的单元格,以及大量样式和嵌入对象和媒体的应用程序。
这些复杂的特性可以通过 ODFDOM API 实现,尽管代码会很复杂。但随着 ODFDOM 发展,这些复杂的电子表格的创建会变得越来越简单。
创建演示文件
让我们从定义演示 content.xml 中的相关术语开始(见清单 12):
<office:presentation> 电子演示文档的根元素。
<draw:page> 是 <office:presentation> 的子元素,表示一张幻灯片。只有图像元素才能保存在 <draw:page> 中,因此文本元素,如 <text:title>,必须先放在 <draw:frame> 下,然后才能放到幻灯片中。
<style:master-page> 是一个通用模板页,是 <style:master-style>. Styles 的子元素,例如背景,在母版页中设置,每张幻灯片都可关联到一个母版页;从而,可对其应用对应的模板。
清单 12. 演示文件 content.xml 的结构
<office:document-content>
<office :automatic-style/>
<office :body>
<office:presentation>
<draw:page/>
</ office: presentation>
</ office: body>
</ Office: document-content>
在本小节中,我们将展示如何创建演示文件、插入幻灯片、列出标题、应用母版页模板,还有保存新幻灯片。
表 1 列举出代码中用到的 ODF 类。
表 1. ODF 类和用途
ODF 类 | 用途 |
OdfPresentationDocument | 演示文件 |
OdfStyleDom | Style DOM |
OdfOfficePresentation | <office:presentation> 元素 |
OdfOfficeStyles | <office:styles> 文档样式元素 |
OdfOfficeAutomaticStyle | <style:automatic-styles> 放在自动样式中 |
OdfStylePageLayout | <style:page-layout> 定义页面布局 |
OdfOfficeMasterStyles | <office:master-styles> 定义页面的母版样式 |
OdfStyleMasterPage | <style:master-page> 是 <office:master-styles> 子元素,用于定义主样式母版页 |
OdfDrawPage | <draw:page> 元素用于表示一个演示页面或一张幻灯片 |
OdfDrawFrame | <draw:frame> 是一个容器元素,其他元素放置其中 |
步骤如下(见清单 13):
创建 OdfPresentationDocument 对象。
获取 OdfOfficePresentation 对象。
获取 OdfOfficeStyles 对象,它表示文档样式元素;如果该元素不存在,就创建一个。
创建 <style:page-layout> 元素;该元素在 OdfOfficeAutomaticStyle 元素下,因此可以使用 getAutomaticStyles () 得到。
使用 OdfPresentationDocument 类的 getOfficeMasterStyles() 方法获取 OdfOfficeMasterStyles 对象。
创建 OdfStyleMasterPage 对象,其中我们必须指定母版页名称和布局样式名称。(可以使用第 4 步中的布局样式名称。)
演示文档由多个幻灯片组成,所以下一步是用 newDrawPageElement 方法(MasterPageStyleName)创建 OdfDrawPage 对象,这里我们可以指定母版页。调用该方法后,母版页就应用到新幻灯片。
由于只有图形元素能保存到 <draw:page> 中,因此我们需要创建 OdfDrawFrame 对象来添加内容。
我们创建两个 OdfDrawFrame 对象。一个用来保存标题; 另一个用来保存图片。
至此,演示文档已创建完成,现在可以保存为 ODP 文档,并使用 OpenOffice 或 IBM Lotus Symphony 打开。
清单 13. 创建演示文件
OdfPresentationDocument presentationDoc =
OdfPresentationDocument.newPresentationDocument ();
OdfOfficePresentation presentation1 = presentationDoc.getContentRoot ();
presentationDoc.getOrCreateDocumentStyles ();
presentationDoc.getStylesDom (). getAutomaticStyles ().
newStylePageLayoutElement ( "PM01");
OdfOfficeMasterStyles officeMasterStyles = presentationDoc.getOfficeMasterStyles ();
OdfStyleMasterPage masterPage = (OdfStyleMasterPage) officeMasterStyles.
newStyleMasterPageElement ( "master-name-1", "PM01");
OdfDrawPage page4 = (OdfDrawPage) presentation1.newDrawPageElement
( "master-name-1");
OdfDrawFrame frame1 = (OdfDrawFrame) page4.newDrawFrameElement ();
frame1.newDrawTextBoxElement (). setTextContent ( "title");
OdfDrawFrame frame2 = (OdfDrawFrame) page4.newDrawFrameElement ();
frame2.newDrawImageElement (). setXlinkHrefAttribute ( "http://impage");
presentationDoc.save ( "presentation.odp");
结束语
在对本文中三个例子的详细讲解中,我们演示了如何使用 ODFDOM API 来创建文本、电子表格、演示 ODF 文档的内容、样式、以及其他特性。
本文示例源代码或素材下载
更多精彩
赞助商链接