使用 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 );

参考