<?xml version="1.0"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<article xmlns="http://docbook.org/ns/docbook">
  <section ID="ez_components_-_document">
    <sectioninfo/>
    <title>eZ Components - Document</title>
    <section ID="introduction">
      <sectioninfo/>
      <title>Introduction</title>
      <para>The document component offers transformations between different semantic markup languages, like:</para>
      <itemizedlist>
        <listitem>
          <para>
            <ulink url="http://docutils.sourceforge.net/rst.html">ReStructured text</ulink>
          </para>
        </listitem>
        <listitem>
          <para>
            <ulink url="http://www.w3.org/TR/xhtml1/">XHTML</ulink>
          </para>
        </listitem>
        <listitem>
          <para>
            <ulink url="http://www.docbook.org/">Docbook</ulink>
          </para>
        </listitem>
        <listitem>
          <para>
            <ulink url="Document_conversion.html">eZ Publish XML markup</ulink>
          </para>
        </listitem>
        <listitem>
          <para>Wiki markup languages, like: <ulink url="ezxml">Creole</ulink>, <ulink url="creole">Dokuwiki</ulink> and <ulink url="dokuwiki">Confluence</ulink></para>
        </listitem>
      </itemizedlist>
      <para>Where each format support conversions from and to docbook as a central intermediate format and may implement additional shortcuts for conversions from and to other formats. Not each format can express the same semantics, so there may be some information lost, which is <ulink url="confluence">documented in a dedicated document</ulink>.</para>
      <para>There are central handler classes for each markup language, which follow a common conversion interface ezcDocument and all implement the methods getAsDocbook() and createFromDocbook().</para>
    </section>
    <section ID="markup_languages">
      <sectioninfo/>
      <title>Markup languages</title>
      <para>The following markup languages are currently handled by the document component.</para>
      <section ID="restructured_text">
        <sectioninfo/>
        <title>ReStructured text</title>
        <section ID="error_handling">
          <sectioninfo/>
          <title>Error handling</title>
          <para>By default each parsing or compiling error will be transformed into an exception, so that you are noticed about those errors. The error reporting settings can be modified like for all other document handlers:</para>
          <literallayout>&lt;?php
$document = new ezcDocumentRst();
$document-&gt;options-&gt;errorReporting = E_PARSE | E_ERROR | E_WARNING;
$document-&gt;loadFile( '../tutorial.txt' );

$docbook = $document-&gt;getAsDocbook();
echo $docbook-&gt;save();
?&gt;

</literallayout>
          <para>Where the setting in line 3 causes, that only warnings, errors and fatal errors are transformed to exceptions now, while the notices are only collected, but ignored. This setting affects both, the parsing of the source document and the compiling into the destination language.</para>
        </section>
        <section ID="directives">
          <sectioninfo/>
          <title>Directives</title>
          <section ID="directive_example">
            <sectioninfo/>
            <title>Directive example</title>
            <para>A full example for a custom directive, where we want to embed real world addresses into our RST document and maintain the semantics in the resulting docbook, could look like:</para>
            <literallayout>Address example
===============

.. address:: John Doe
    :street: Some Lane 42

</literallayout>
            <para>We would possibly add more information, like the ZIP code, city and state, but skip this to keep the code short. The implemented directive then would just need to take these information and transform it into valid docbook XML using the DOM extension.</para>
            <literallayout>&lt;?php
class myAddressDirective extends ezcDocumentRstDirective
{
    public function toDocbook( DOMDocument $document, DOMElement $root )
    {
        $address = $document-&gt;createElement( 'address' );
        $root-&gt;appendChild( $address );

        if ( !empty( $this-&gt;node-&gt;parameters ) )
        {
            $name = $document-&gt;createElement( 'personname', htmlspecialchars( $this-&gt;node-&gt;parameters ) );
            $address-&gt;appendChild( $name );
        }

        if ( isset( $this-&gt;node-&gt;options['street'] ) )
        {
            $street = $document-&gt;createElement( 'street', htmlspecialchars( $this-&gt;node-&gt;options['street'] ) );
            $address-&gt;appendChild( $street );
        }
    }
}
?&gt;
</literallayout>
            <para>The AST node, which should be rendered, is passed to the constructor of the custom directive visitor and available in the class property $node. The complete DOMDocument and the current DOMNode are passed to the method. In this case we just create a <ulink url="http://docbook.org/tdg/en/html/address.html">address node</ulink> with the optional child nodes street and personname, depending on the existence of the respective values.</para>
            <para>You can now render the RST document after you registered you custom directive handler as shown above:</para>
            <literallayout>&lt;?php

require 'tutorial_autoload.php';

// Load custom directive
require 'address_directive.php';

$document = new ezcDocumentRst();
$document-&gt;registerDirective( 'address', 'myAddressDirective' );
$document-&gt;loadString( &lt;&lt;&lt;EORST
Address example
===============

.. address:: John Doe
    :street: Some Lane 42
EORST
);

$docbook = $document-&gt;getAsDocbook();
echo $docbook-&gt;save();
?&gt;
</literallayout>
            <para>The output will then look like:</para>
            <literallayout>&lt;?xml version="1.0"?&gt;
&lt;article xmlns="http://docbook.org/ns/docbook"&gt;
  &lt;section ID="address_example"&gt;
    &lt;sectioninfo/&gt;
    &lt;title&gt;Address example&lt;/title&gt;
    &lt;address&gt;
      &lt;personname&gt; John Doe&lt;/personname&gt;
      &lt;street&gt; Some Lane 42&lt;/street&gt;
    &lt;/address&gt;
  &lt;/section&gt;
&lt;/article&gt;

</literallayout>
          </section>
        </section>
        <section ID="xhtml_rendering">
          <sectioninfo/>
          <title>XHTML rendering</title>
          <section ID="modification_of_xhtml_rendering">
            <sectioninfo/>
            <title>Modification of XHTML rendering</title>
            <para>You can modify the generated output of the XHTML visitor by creating a custom visitor for the RST AST. The easiest way probably is to extend from one of the existing XHTML visitors and reusing it. For example you may want to fill the type attribute in bullet lists, like known from HTML, which isn't valid XHTML, though:</para>
            <literallayout>class myDocumentRstXhtmlVisitor extends ezcDocumentRstXhtmlVisitor
{
    protected function visitBulletList( DOMNode $root, ezcDocumentRstNode $node )
    {
        $list = $this-&gt;document-&gt;createElement( 'ul' );
        $root-&gt;appendChild( $list );

        $listTypes = array(
            '*'            =&gt; 'circle',
            '+'            =&gt; 'disc',
            '-'            =&gt; 'square',
            "\xe2\x80\xa2" =&gt; 'disc',
            "\xe2\x80\xa3" =&gt; 'circle',
            "\xe2\x81\x83" =&gt; 'square',
        );
        // Not allowed in XHTML strict
        $list-&gt;setAttribute( 'type', $listTypes[$node-&gt;token-&gt;content] );

        // Decoratre blockquote contents
        foreach ( $node-&gt;nodes as $child )
        {
            $this-&gt;visitNode( $list, $child );
        }
    }
}

</literallayout>
            <para>The structure, which is not enforced for visitors, but used in the docbook and XHTML visitors, is to call special methods for each node type in the AST to decorate the AST recursively. This method will be called for all bullet list nodes in the AST which contain the actual list items. As the first parameter the current position in the XHTML DOM tree is also provided to the method.</para>
            <para>To create the XHTML we can now just create a new list node (&lt;ul&gt;) in the current DOMNode, set the new attribute, and recursively decorate all descendants using the general visitor dispatching method visitNode() for all children in the AST. For the AST childs being also rendered as children in the XML tree, we pass the just created DOMNode (&lt;ul&gt;) as the new root node to the visitNode() method.</para>
            <para>After defining such a class, you could use the custom visitor like shown above:</para>
            <literallayout>&lt;?php
$document = new ezcDocumentRst();
$document-&gt;options-&gt;xhtmlVisitor = 'myDocumentRstXhtmlVisitor';
$document-&gt;loadFile( $from );

$xhtml = $document-&gt;getAsXhtml();
$xml = $xhtml-&gt;save();
?&gt;

</literallayout>
            <para>Now the lists in the generated XHTML will also the type attribute set.</para>
          </section>
        </section>
      </section>
    </section>
  </section>
</article>
