XML文件到RTF和PDF的转换


Author: Holyfair
E-Mail: [email protected]


一. 序

在一些运用中,我们通常会把一些文本和配置信息转换成XML文件进行传输,修改,保存.特别是具有一定模板性质的文档用XML文件来实现其管理就显得相当的方便了.提供对于XML文件的操作的java API很多,诸于DOM,JDOM,Castor,SAX,XMLReader,XPath,XSLT等等. 具体的这些API的用法这里就不多提了. 当使用这些接口实现XML的操作后,对于有些文档而言最终必须呈现给用户看的还是我们通常所熟悉的WORD和PDF文档.我们这里就来看一下从一个XML文件到RTF和PDF文件转换的实现.


二. 从XML到PDF

对于一个具有一定模板性质的XML文件,我们可以用FOP API来实现其到PDF的转换.

FOP需要fop.jar. 我们可以到 http://xml.apache.org/fop/ 上获取和了解其用法.

以一个一般复杂的XML文件为例:

要转换XML文档 test.xml 如下:

 1<featuresrs title="SRS">
 2<introduction>
 3<objective>objective here</objective>
 4<scope>scope here</scope>
 5<responsibilities>responsibilities here</responsibilities>
 6<references>reference here</references>
 7<daa>
 8<term>   
 9term here   
10</term>
11<definition>   
12definition here   
13</definition>
14</daa>
15</introduction>
16<generaldescription>
17<featurename>
18<summary>summary here</summary>
19<breakdown>breakdown here</breakdown>
20</featurename>
21<requirement>
22<content>   
23content here.   
24</content>
25</requirement>
26<requirement>
27<content>   
28content2 here.   
29</content>
30</requirement>
31<featureinteractions>featureInteractions here</featureinteractions>
32</generaldescription>
33<strresources>
34<strresource>
35<estring>   
36estring here   
37</estring>
38<resourceid>   
39resourceid here   
40</resourceid>
41<rqmt>   
42rqmt here.   
43</rqmt>
44</strresource>
45</strresources>
46</featuresrs>

对于这样一个XML文档,我们要将其转化成PDF格式必须建立一个XSL-FO文件,来定义对各element和value格

式的转换.

我们建立XSL-FO文件 test.xsl 如下:

  1<xsl:stylesheet exclude-result-prefixes="fo" version="1.1" xmlns:fo=" http://www.w3.org/1999/XSL/Format " xmlns:xsl=" http://www.w3.org/1999/XSL/Transform ">
  2<xsl:output indent="yes" method="xml" omit-xml-declaration="no" version="1.0"></xsl:output>
  3<!-- ========================= -->
  4<!-- root element: projectteam -->
  5<!-- ========================= -->
  6<xsl:template match="FeatureSRS">
  7<fo:root xmlns:fo=" http://www.w3.org/1999/XSL/Format ">
  8<fo:layout-master-set>
  9<fo:simple-page-master margin-bottom="2cm" margin-left="2cm" margin-right="2cm" margin-top="2cm" master-name="simpleA4" page-height="29.7cm" page-width="21cm">
 10<fo:region-body></fo:region-body>
 11</fo:simple-page-master>
 12</fo:layout-master-set>
 13<fo:page-sequence master-reference="simpleA4">
 14<fo:flow flow-name="xsl-region-body">
 15<fo:block font-size="20pt" font-weight="bold" space-after="5mm" text-align="center">Cardiac Feature SRS   
 16</fo:block>
 17<fo:block font-size="10pt">
 18<xsl:apply-templates></xsl:apply-templates>
 19</fo:block>
 20</fo:flow>
 21</fo:page-sequence>
 22</fo:root>
 23</xsl:template>
 24<!-- ========================= -->
 25<!-- child element: member -->
 26<!-- ========================= -->
 27<xsl:template match="introduction" name="introduction">
 28<fo:block font-size="18pt" font-weight="bold" space-after="5mm">1\. Intruction</fo:block>
 29<fo:block font-size="14pt" font-weight="bold" margin-left="5mm" space-after="5mm">1.1 Objective</fo:block>
 30<fo:block font-size="10pt" font-weight="normal" margin-left="7mm" space-after="5mm">
 31<xsl:value-of select="objective"></xsl:value-of>
 32</fo:block>
 33<fo:block font-size="14pt" font-weight="bold" margin-left="5mm" space-after="5mm">1.2 Scope</fo:block>
 34<fo:block font-size="10pt" font-weight="normal" margin-left="7mm" space-after="5mm">
 35<xsl:value-of select="scope"></xsl:value-of>
 36</fo:block>
 37<fo:block font-size="14pt" font-weight="bold" margin-left="5mm" space-after="5mm">1.3. Responsibilities</fo:block>
 38<fo:block font-size="10pt" font-weight="normal" margin-left="7mm" space-after="5mm">
 39<xsl:value-of select="responsibilities"></xsl:value-of>
 40</fo:block>
 41<fo:block font-size="14pt" font-weight="bold" margin-left="5mm" space-after="5mm">1.4. References</fo:block>
 42<fo:block font-size="10pt" font-weight="normal" margin-left="7mm" space-after="5mm">
 43<xsl:value-of select="references"></xsl:value-of>
 44</fo:block>
 45<fo:block font-size="14pt" font-weight="bold" margin-left="5mm" space-after="5mm">1.5. Definitions, Acronyms, and Abbreviations</fo:block>
 46<fo:block font-size="10pt" font-weight="bold" margin-left="5mm" space-after="5mm">
 47<fo:table background-color="#fff2d9" border="2cm" table-layout="fixed">
 48<fo:table-column column-width="4cm"></fo:table-column>
 49<fo:table-column column-width="6cm"></fo:table-column>
 50<fo:table-body>
 51<fo:table-row border="2">
 52<fo:table-cell>
 53<fo:block>
 54<xsl:text>Term</xsl:text>
 55</fo:block>
 56</fo:table-cell>
 57<fo:table-cell>
 58<fo:block>
 59<xsl:text>Definition</xsl:text>
 60</fo:block>
 61</fo:table-cell>
 62</fo:table-row>
 63<xsl:for-each select="DAA">
 64<fo:table-row border="2">
 65<fo:table-cell>
 66<fo:block>
 67<xsl:value-of select="term"></xsl:value-of>
 68</fo:block>
 69</fo:table-cell>
 70<fo:table-cell>
 71<fo:block>
 72<xsl:value-of select="definition"></xsl:value-of>
 73</fo:block>
 74</fo:table-cell>
 75</fo:table-row>
 76</xsl:for-each>
 77</fo:table-body>
 78</fo:table>
 79</fo:block>
 80</xsl:template>
 81<xsl:template match="generalDescription" name="generalDescription">
 82<fo:block font-size="18pt" font-weight="bold" space-after="5mm">2\. General Description</fo:block>
 83<fo:block font-size="14pt" font-weight="bold" margin-left="5mm" space-after="5mm">2.1. Feature Name</fo:block>
 84<fo:block font-size="14pt" font-weight="bold" margin-left="7mm" space-after="5mm">2.1.1. Feature Summary</fo:block>
 85<fo:block font-size="10pt" font-weight="normal" margin-left="9mm" space-after="5mm">
 86<xsl:value-of select="featureName/summary"></xsl:value-of>
 87</fo:block>
 88<fo:block font-size="14pt" font-weight="bold" margin-left="7mm" space-after="5mm">2.1.2. Feature Breakdown</fo:block>
 89<fo:block font-size="10pt" font-weight="normal" margin-left="9mm" space-after="5mm">
 90<xsl:value-of select="featureName/breakdown"></xsl:value-of>
 91</fo:block>
 92<fo:block font-size="14pt" font-weight="bold" margin-left="5mm" space-after="5mm">2.2. Feature Requirements</fo:block>
 93<fo:block font-size="10pt" font-weight="normal" margin-left="7mm" space-after="5mm">
 94<xsl:for-each select="requirement">
 95<xsl:value-of select="content"></xsl:value-of>
 96</xsl:for-each>
 97</fo:block>
 98<fo:block font-size="14pt" font-weight="bold" margin-left="5mm" space-after="5mm">2.3. Feature Interactions</fo:block>
 99<fo:block font-size="10pt" font-weight="normal" margin-left="7mm" space-after="5mm">
100<xsl:value-of select="featureInteractions"></xsl:value-of>
101</fo:block>
102</xsl:template>
103<xsl:template match="strResources" name="strResources">
104<fo:block font-size="18pt" font-weight="bold" space-after="5mm">3\. String Resources </fo:block>
105<fo:block font-size="10pt" font-weight="bold" margin-left="5mm" space-after="5mm">
106<fo:table background-color="#fff2d9" border="2cm" table-layout="fixed">
107<fo:table-column column-width="4cm"></fo:table-column>
108<fo:table-column column-width="10cm"></fo:table-column>
109<fo:table-column column-width="4cm"></fo:table-column>
110<fo:table-body>
111<fo:table-row border="2">
112<fo:table-cell>
113<fo:block>
114<xsl:text>English String</xsl:text>
115</fo:block>
116</fo:table-cell>
117<fo:table-cell>
118<fo:block>
119<xsl:text>Resource ID</xsl:text>
120</fo:block>
121</fo:table-cell>
122<fo:table-cell>
123<fo:block>
124<xsl:text>Rqmt</xsl:text>
125</fo:block>
126</fo:table-cell>
127</fo:table-row>
128<xsl:for-each select="strResource">
129<fo:table-row border="2">
130<fo:table-cell>
131<fo:block>
132<xsl:value-of select="estring"></xsl:value-of>
133</fo:block>
134</fo:table-cell>
135<fo:table-cell>
136<fo:block>
137<xsl:value-of select="resourceid"></xsl:value-of>
138</fo:block>
139</fo:table-cell>
140<fo:table-cell>
141<fo:block>
142<xsl:value-of select="rqmt"></xsl:value-of>
143</fo:block>
144</fo:table-cell>
145</fo:table-row>
146</xsl:for-each>
147</fo:table-body>
148</fo:table>
149</fo:block>
150</xsl:template>
151</xsl:stylesheet>

其具体的XSL-FO文件格式的语法可以参照一些其他资料.

建立好了此文件之后,我们就可以用FOP提供的一些接口方便的进行转换了.

FOP提供了XML->FO,XML->PDF,FO-PDF,OBJ->FO,OBJ->PDF的转换接口.

我们这里以XML->PDF的为例,其余的可以参照FOP包里相应的DEMO.

public class ExampleXML2PDF {

public void convertXML2PDF(File xml, File xslt, File pdf)
throws IOException, FOPException, TransformerException {
Driver driver = new Driver();
Logger logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
driver.setLogger(logger);
MessageHandler.setScreenLogger(logger);

//Setup Renderer (output format)
driver.setRenderer(Driver.RENDER_PDF);

//Setup output
OutputStream out = new java.io.FileOutputStream(pdf);
try {
driver.setOutputStream(out);

//Setup XSLT
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(xslt));

//Setup input for XSLT transformation
Source src = new StreamSource(xml);

//Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(driver.getContentHandler());

//Start XSLT transformation and FOP processing
transformer.transform(src, res);
} finally {
out.close();
}
}

public static void main(String[] args) {
try {
System.out.println("FOP ExampleXML2PDF\n");
System.out.println("Preparing...");

//Setup directories
File baseDir = new File(".");
File outDir = new File(baseDir, "out");
outDir.mkdirs();

//Setup input and output files
File xmlfile = new File(baseDir, "test.xml");
File xsltfile = new File(baseDir, "test.xsl");
File pdffile = new File(outDir, "test.pdf");

System.out.println("Input: XML (" + xmlfile + ")");
System.out.println("Stylesheet: " + xsltfile);
System.out.println("Output: PDF (" + pdffile + ")");
System.out.println();
System.out.println("Transforming...");

ExampleXML2PDF app = new ExampleXML2PDF();
app.convertXML2PDF(xmlfile, xsltfile, pdffile);

System.out.println("Success!");
} catch (Exception e) {
System.err.println(ExceptionUtil.printStackTrace(e));
System.exit(-1);
}
}
}


这样我们就很轻易地实现了XML文档到PDF文档的转换.

如果这些用在webservice的servlet中,想从xml文件直接生成pdf传输给浏览者而并不生成的pdf文件,我们可以如

下实现:

public class FOPServlet extends HttpServlet {
public static final String FO_REQUEST_PARAM = "fo";
public static final String XML_REQUEST_PARAM = "xml";
public static final String XSL_REQUEST_PARAM = "xsl";

public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException {
try {
String xmlParam =getServletContext().getRealPath("WEB-INF/doc/xml/test.xml");
String xslParam =getServletContext().getRealPath("WEB-INF/doc/xsl/test.xsl");

if ((xmlParam != null) && (xslParam != null)) {
XSLTInputHandler input =
new XSLTInputHandler(new File(xmlParam),
new File(xslParam));
renderXML(input, response);
} else {
PrintWriter out = response.getWriter();
out.println("

1<html><head><title>Error</title></head>\n"+   
2"<body><h1>FopServlet Error</h1><h3>No 'fo' "+   
3"request param given.</h3></body></html>

");
}
} catch (ServletException ex) {
throw ex;
}
catch (Exception ex) {
throw new ServletException(ex);
}
}
public void renderXML(XSLTInputHandler input,
HttpServletResponse response) throws ServletException {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();

response.setContentType("application/pdf");

Driver driver = new Driver();
driver.setRenderer(Driver.RENDER_PDF);
driver.setOutputStream(out);
driver.render(input.getParser(), input.getInputSource());

byte[] content = out.toByteArray();
response.setContentLength(content.length);
response.getOutputStream().write(content);
response.getOutputStream().flush();
} catch (Exception ex) {
throw new ServletException(ex);
}
}

}



三. XML to RTF

xml到rtf的转换稍微有一些麻烦,我们没有直接从XML到RTF的API, 我们将要用的JFor API还没有整合到FOP

中去. JFor API可以实现 从 FO文件到RTF文件的转换, 它也提供了consle接口.

我们可以从 www.jfor.org 上获取jfor相关信息.

我们从XML文件到RTF文件的转换可以分为两步:

1. 用FOP将 xml 转换成 fo

2. 用JFor将 fo 转换成RTF

**3.1 用FOP将 xml 转换成 fo
**
这一步我们可以很轻易的沿用上面所述的方法,如下实现xml到fo 的转换,依然会用到上面所用的xml文件

和xsl-fo文件.

OutputStream foOut = new FileOutputStream(fofile);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(
xsltfile));
Source src = new StreamSource(xmlfile);
Result res = new StreamResult(foOut);
transformer.transform(src, res);
foOut.close();

**3.2 用JFor将 fo 转换成RTF
**
仅以Serlvet需求的实现为例:

InputStream foInput = new FileInputStream(fofile);
InputSource inputSource = new InputSource(foInput);

ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer output = new OutputStreamWriter(out);

response.setContentType("application/msword");

new Converter(inputSource,output,Converter.createConverterOption ());
output.flush();

byte[] content = out.toByteArray();

System.out.println(out.toString());

response.setContentLength(content.length);
response.getOutputStream().write(content);
response.getOutputStream().flush();

foInput.close();
output.close();
out.close();


这样我们就成功地将xml转化成了RTF格式的文件.

本文仅简述了大体的实现过程,具体的细节可参照各技术点的详细自述.

Published At
Categories with Web编程
Tagged with
comments powered by Disqus