使用 Doxia Sink API
转换文件
Doxia 可用于将任意输入文档转换为任何支持的输出格式。以下片段展示了如何使用 Doxia Parser将 apt 文件转换为 html:
File userDir = new File( System.getProperty ( "user.dir" ) ); File inputFile = new File( userDir, "test.apt" ); File outputFile = new File( userDir, "test.html" ); SinkFactory sinkFactory = (SinkFactory) lookup( SinkFactory.ROLE, "html" ); // Plexus lookup Sink sink = sinkFactory.createSink( outputFile.getParentFile(), outputFile.getName() ) ); Parser parser = (AptParser) lookup( Parser.ROLE, "apt" ); // Plexus lookup Reader reader = ReaderFactory.newReader( inputFile, "UTF-8" ); parser.parse( reader, sink );
建议您使用Plexus来查找解析器。原则上,您可以直接实例化解析器(Parser parser = new AptParser();
),但某些特殊功能(如宏)将不可用。
您还可以使用Doxia 转换器工具将给定的文件/目录解析为另一个文件/目录。
生成文档
下面的代码片段给出了一个如何使用 Doxia Sink API 生成文档的简单示例。
/** * Generate a simple document and emit it * into the specified sink. The sink is flushed but not closed. * * @param sink The sink to receive the events. */ public static void generate( Sink sink ) { sink.head(); sink.title(); sink.text( "Title" ); sink.title_(); sink.author(); sink.text( "Author" ); sink.author_(); sink.date(); sink.text( "Date" ); sink.date_(); sink.head_(); sink.body(); sink.paragraph(); sink.text( "A paragraph of text." ); sink.paragraph_(); sink.section1(); sink.sectionTitle1(); sink.text( "Section title" ); sink.sectionTitle1_(); sink.paragraph(); sink.text( "Paragraph in section." ); sink.paragraph_(); sink.section1_(); sink.body_(); sink.flush(); }
可以在 Doxia SinkTestDocument类中找到更完整的示例,该示例还显示了生成文档时使用的“规范”事件顺序。
将属性传递给 Sink 事件
Sink API 中的许多方法允许将一组属性传递给许多 sink 事件。一个典型的用例是:
SinkEventAttributeSet atts = new SinkEventAttributeSet(); atts.addAttribute( SinkEventAttributes.ALIGN, "center" ); sink.paragraph( atts );
支持的属性类型取决于事件和接收器实现。接收器 API 指定接收器应该识别的建议属性名称列表,并且解析器在发出事件时应该使用这些属性名称。
避免 sink.rawText!
在Doxia 1.0中,使用 sink.rawText() 生成 Sink API 不支持的元素是一种常见的做法。例如,以下代码段可用于生成样式化的 HTML <div> 块:
sink.RawText( "<div style=\"cool\">" ); sink.text( "A text with a cool style." ); sink.rawText( "</div>" );
然而,这有一个主要缺点:它仅在接收 Sink 是 HTML Sink 时才有效。换句话说,上述方法不适用于 HTML 以外的任何其他格式的目标文档(想想 FO Sink 生成 pdf,或 LaTeX sink,...)。
在Doxia 1.1中,Sink API 中添加了一个新方法 unknown(),可用于发出任意事件,而无需对接收 Sink 进行特殊假设。根据参数,Sink 可以决定是否处理事件、将其作为原始文本、作为评论发送、记录等。
现在生成上述 <div> 块的正确方法是:
SinkEventAttributeSet atts = new SinkEventAttributeSet(); atts.addAttribute( SinkEventAttributes.STYLE, "cool" ); sink.unknown( "div", new Object[]{new Integer( HtmlMarkup.TAG_TYPE_START )}, atts ); sink.text( "A text with a cool style." ); sink.unknown( "div", new Object[]{new Integer( HtmlMarkup.TAG_TYPE_END )}, null );
阅读Sink接口中 unknown() 方法的 javadocs 和XhtmlbaseSink以获取有关方法参数的信息。请注意,任意接收器可能会完全忽略未知事件!
通常,在将事件发送到任意 Sink 时,应完全避免使用 rawText 方法。
如何将javascript代码注入HTML
与上述相关,这是将 javascript 片段注入 Sink 的正确方法:
// the javascript code is emitted within a commented CDATA section // so we have to start with a newline and comment the CDATA closing in the end // note that the sink will replace the newline by the system EOL String javascriptCode = "\n function javascriptFunction() {...} \n //"; SinkEventAttributeSet atts = new SinkEventAttributeSet(); atts.addAttribute( SinkEventAttributes.TYPE, "text/javascript" ); sink.unknown( "script", new Object[]{new Integer( HtmlMarkup.TAG_TYPE_START )}, atts ); sink.unknown( "cdata", new Object[]{new Integer( HtmlMarkup.CDATA_TYPE ), javascriptCode }, null ); sink.unknown( "script", new Object[]{new Integer( HtmlMarkup.TAG_TYPE_END )}, null );