view MoinMoin/converter/_tests/test_docbook_in.py @ 2956:b8255fed9b4e

fix failing lxml based docbook tests, add tests for trademarks, partially fix #369
author RogerHaase <haaserd@gmail.com>
date Wed, 17 Jun 2015 14:34:46 -0700
parents da84a2c42a92
children
line wrap: on
line source
# -*- coding: utf-8 -*-
# Copyright: 2010 MoinMoin:ValentinJaniaut
# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.

"""
MoinMoin - Tests for MoinMoin.converter.docbook_in
"""


import re
import StringIO

import pytest

etree = pytest.importorskip('lxml.etree')

from emeraldtree.tree import *

from MoinMoin.converter.docbook_in import *

from MoinMoin import log
logging = log.getLogger(__name__)


class Base(object):
    input_namespaces = ns_all = u'xmlns="{0}" xmlns:xlink="{1}"'.format(docbook.namespace, xlink.namespace)
    output_namespaces = {
        moin_page.namespace: u'',
        xlink.namespace: u'xlink',
        xml.namespace: u'xml',
        html.namespace: u'html',
    }

    namespaces_xpath = {'xlink': xlink.namespace,
                        'xml': xml.namespace,
                        'html': html.namespace
                       }

    input_re = re.compile(r'^(<[a-z:]+)')
    output_re = re.compile(r'\s+xmlns="[^"]+"')

    def handle_input(self, input):
        return self.input_re.sub(r'\1 ' + self.input_namespaces, input)

    def handle_output(self, input, **args):
        if 'nonamespace' not in args:
            to_conv = self.handle_input(input)
        elif args['nonamespace']:
            to_conv = input
        out = self.conv(to_conv, 'application/docbook+xml;charset=utf-8')
        f = StringIO.StringIO()
        out.write(f.write, namespaces=self.output_namespaces, )
        return self.output_re.sub(u'', f.getvalue())

    def do(self, input, xpath_query):
        string_to_parse = self.handle_output(input)
        logging.debug(u"After the DOCBOOK_IN conversion : {0}".format(string_to_parse))
        tree = etree.parse(StringIO.StringIO(string_to_parse))
        print 'string_to_parse = %s' % string_to_parse  # provide a clue for failing tests
        assert (tree.xpath(xpath_query, namespaces=self.namespaces_xpath))

    def do_nonamespace(self, input, xpath_query):
        string_to_parse = self.handle_output(input, nonamespace=True)
        logging.debug(u"After the DOCBOOK_IN conversion : {0}".format(string_to_parse))
        tree = etree.parse(StringIO.StringIO(string_to_parse))
        assert (tree.xpath(xpath_query, namespaces=self.namespaces_xpath))


class TestConverter(Base):
    def setup_class(self):
        self.conv = Converter()

    def test_base(self):
        data = [
            ('<article><para>Test</para></article>',
                # <page><body><div html:class="db-article"><p>Test</p></div></body></page>
                '/page/body/div[@html:class="db-article"][p="Test"]'),
            ('<article><simpara>Test</simpara></article>',
                # <page><body><div html:class="article"><p>Test</p></div></body></page>
                '/page/body/div[p="Test"]'),
            ('<article><formalpara><title>Title</title><para>Test</para></formalpara></article>',
                # <page><body><div html:class="article"><p html:title="Title">Test</p></div></body></page>
                '/page/body/div/p[text()="Test"][@html:title="Title"]'),
            ('<article><sect1><title>Heading 1</title> <para>First Paragraph</para></sect1></article>',
                # <page><body><div html:class="article"><h outline-level="1">Heading 1</h><p>First Paragraph</p></div></body></page>
                '/page/body/div[./h[@outline-level="1"][text()="Heading 1"]][./p[text()="First Paragraph"]]'),
            # Test for conversion with unicode char
            (u'<article><para>안녕 유빈</para></article>',
                # <page><body><div html:class="article"><p>안녕 유빈</p></div></body></page>
                u'/page/body/div[p="안녕 유빈"]'),
            # Ignored tags
            ('<article><info><title>Title</title><author>Author</author></info><para>text</para></article>',
                # <page><body><div html:class="article"><p>text</p></div></body></page>
                '/page/body/div[p="text"]'),
            # XML attributes: We support all the xml standard attributes
            ('<article><para xml:base="http://base.tld" xml:id="id" xml:lang="en">Text</para></article>',
                # <page><body><div html:class="article"><p xml:base="http://base.tld" xml:id="id" xml:lang="en">Text</p></div></body></page>
                '/page/body/div/p[@xml:base="http://base.tld"][@xml:id="id"][@xml:lang="en"][text()="Text"]'),
            # ANCHOR --> SPAN
            ('<article><para>bla bla<anchor xml:id="point_1" />bla bla</para></article>',
                # <page><body><div html:class="article"><p>bla bla<span class="db-anchor" xml:id="point_1" />bla bla</p></div></body></page>
                '/page/body/div/p/span[@html:class="db-anchor"][@xml:id="point_1"]'),
            # BOOK Document
            ('<book><para>Test</para></book>',
                # <page><body><div html:class="db-book"><p>Test</p></div></body></page>
                '/page/body/div[@html:class="db-book"][p="Test"]'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_title(self):
        data = [
            # Test simple numbered section conversion into headings.
            ('<article><sect1><title>Heading 1</title> <para>First</para><sect2><title>Heading 2</title><para>Second</para></sect2></sect1></article>',
                # <page><body><table-of-content><div html:class="article"><h outline-level="1">Heading 1</h><p>First</p><h outline-level="2">Heading 2</h><p>Second</p></div></body></page>
                '/page/body[table-of-content]/div[h[1][@outline-level="1"][text()="Heading 1"]][p[1][text()="First"]][h[2][@outline-level="2"][text()="Heading 2"]][p[2][text()="Second"]]'),
            ('<article><section><title>Heading 1</title> <para>First</para><section><title>Heading 2</title><para>Second</para></section></section></article>',
                # <page><body><table-of-content><div html:class="article"><h outline-level="1">Heading 1</h><p>First</p><h outline-level="2">Heading 2</h><p>Second</p></div></body></page>
                '/page/body[table-of-content]/div[h[1][@outline-level="1"][text()="Heading 1"]][p[1][text()="First"]][h[2][@outline-level="2"][text()="Heading 2"]][p[2][text()="Second"]]'),
            # Test complex recursive section conversion into headings.
            ('<article><section><title>Heading 1 A</title><para>First</para><section><title>Heading 2 A</title><para>Second</para><section><title>Heading 3 A</title><para>Third</para></section></section></section><section><title>Heading 1 B</title><para>Fourth</para></section></article>',
                # <page><body><table-of-content /><div html:class="article"><h outline-level="1">Heading 1 A</h><p>First</p><h outline-level="2">Heading 2 A</h><p>Second</p><h outline-level="3">Heading 3 A</h><p>Third</p><h outline-level="1">Heading 1 B</h><p>Fourth</p></div></body></page>
                '/page/body[table-of-content]/div[h[1][@outline-level="1"][text()="Heading 1 A"]][p[1][text()="First"]][h[2][@outline-level="2"][text()="Heading 2 A"]][p[2][text()="Second"]][h[3][@outline-level="3"][text()="Heading 3 A"]][p[3][text()="Third"]][h[4][@outline-level="1"][text()="Heading 1 B"]][p[4][text()="Fourth"]]'),
        ]

        for i in data:
            yield (self.do, ) + i

    def test_list(self):
        data = [
            # ITEMIZED LIST --> unordered list
            ('<article><itemizedlist><listitem>Unordered Item 1</listitem><listitem>Unordered Item 2</listitem></itemizedlist></article>',
                # <page><body><div html:class="article"><list item-label-generate="unordered"><list-item><list-item-body>Unordered Item 1</list-item-body></list-item><list-item><list-item-body>Unordered Item 2</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[@item-label-generate="unordered"][list-item[1]/list-item-body[text()="Unordered Item 1"]][list-item[2]/list-item-body[text()="Unordered Item 2"]]'),
            # ORDERED LIST --> ordered list
            ('<article><orderedlist><listitem>Ordered Item 1</listitem><listitem>Ordered Item 2</listitem></orderedlist></article>',
                # <page><body><div html:class="article"><list item-label-generate="ordered"><list-item><list-item-body>Ordered Item 1</list-item-body></list-item><list-item><list-item-body>Ordered Item 2</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[@item-label-generate="ordered"][list-item[1]/list-item-body[text()="Ordered Item 1"]][list-item[2]/list-item-body[text()="Ordered Item 2"]]'),
            # ORDERED LIST with upperalpha numeration --> ordered list with upper-alpha list-style-type
            ('<article><orderedlist numeration="upperalpha"><listitem>Ordered Item 1</listitem><listitem>Ordered Item 2</listitem></orderedlist></article>',
             # <page><body><div html:class="article"><list item-label-generage="ordered" list-style-type="upper-alpha"><list-item><list-item-body>Ordered Item 1</list-item-body></list-item><list-item><list-item-body>Ordered Item 2</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[@item-label-generate="ordered"][@list-style-type="upper-alpha"][list-item[1]/list-item-body[text()="Ordered Item 1"]][list-item[2]/list-item-body[text()="Ordered Item 2"]]'),
            # ORDERED LIST with loweralpha numeration --> ordered list with lower-alpha list-style-type
            ('<article><orderedlist numeration="loweralpha"><listitem>Ordered Item 1</listitem><listitem>Ordered Item 2</listitem></orderedlist></article>',
                # <page><body><div html:class="article"><list item-label-generage="ordered" list-style-type="lower-alpha"><list-item><list-item-body>Ordered Item 1</list-item-body></list-item><list-item><list-item-body>Ordered Item 2</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[@item-label-generate="ordered"][@list-style-type="lower-alpha"][list-item[1]/list-item-body[text()="Ordered Item 1"]][list-item[2]/list-item-body[text()="Ordered Item 2"]]'),
            # ORDERED LIST with upperroman numeration --> ordered list with upper-roman list-style-type
            ('<article><orderedlist numeration="upperroman"><listitem>Ordered Item 1</listitem><listitem>Ordered Item 2</listitem></orderedlist></article>',
                # <page><body><div html:class="article"><list item-label-generage="ordered" list-style-type="upper-roman"><list-item><list-item-body>Ordered Item 1</list-item-body></list-item><list-item><list-item-body>Ordered Item 2</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[@item-label-generate="ordered"][@list-style-type="upper-roman"][list-item[1]/list-item-body[text()="Ordered Item 1"]][list-item[2]/list-item-body[text()="Ordered Item 2"]]'),
            # ORDERED LIST with lowerroman numeration --> ordered list with lower-roman list-style-type
            ('<article><orderedlist numeration="lowerroman"><listitem>Ordered Item 1</listitem><listitem>Ordered Item 2</listitem></orderedlist></article>',
                # <page><body><div html:class="article"><list item-label-generage="ordered" list-style-type="lower-roman"><list-item><list-item-body>Ordered Item 1</list-item-body></list-item><list-item><list-item-body>Ordered Item 2</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[@item-label-generate="ordered"][@list-style-type="lower-roman"][list-item[1]/list-item-body[text()="Ordered Item 1"]][list-item[2]/list-item-body[text()="Ordered Item 2"]]'),
            # VARIABLE LIST --> list
            ('<article><variablelist><varlistentry><term>Term 1</term><listitem>Definition 1</listitem></varlistentry><varlistentry><term>Term 2</term><listitem>Definition 2</listitem></varlistentry></variablelist></article>',
                # <page><body><div html:class="article"><list><list-item><list-item-label>Termm 1</list-item-label><list-item-body>Definition 1</list-item-body></list-item><list-item><list-item-label>Term 2</list-item-label><list-item-body>Definition 2</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[list-item[1][list-item-label="Term 1"][list-item-body="Definition 1"]][list-item[2][list-item-label="Term 2"][list-item-body="Definition 2"]]'),
            # PROCEDURE --> ordered list (with arabic numeration)
            ('<article><procedure><step>First Step</step><step>Second Step</step></procedure></article>',
                # <page><body><div html:class="article"><list item-label-generate="ordered"><list-item><list-item-body>First Step</list-item-body></list-item><list-item><list-item-body>Second Step</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[@item-label-generate="ordered"][list-item[1]/list-item-body[text()="First Step"]][list-item[2]/list-item-body[text()="Second Step"]]'),
            # PROCEDURE --> ordered list (with arabic numeration) (with stepalternative)
            ('<article><procedure><step>First Step</step><stepalternatives>Second Step</stepalternatives></procedure></article>',
                # <page><body><div html:class="article"><list item-label-generate="ordered"><list-item><list-item-body>First Step</list-item-body></list-item><list-item><list-item-body>Second Step</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[@item-label-generate="ordered"][list-item[1]/list-item-body[text()="First Step"]][list-item[2]/list-item-body[text()="Second Step"]]'),
            # PROCEDURE with SUBSTEPS
            ('<article><procedure><step>First Step</step><substeps><step>Second Step</step></substeps></procedure></article>',
                # <page><body><div html:class="article"><list item-label-generate="ordered"><list-item><list-item-body>First Step</list-item-body></list-item><list-item><list-item-body><list item-label-generate="ordered">Second Step</list-item-body></list-item></list></list></div></body></page>
                '/page/body/div/list[@item-label-generate="ordered"][list-item[1]/list-item-body[text()="First Step"]][list[@item-label-generate="ordered"]/list-item/list-item-body[text()="Second Step"]]'),
            # GLOSS LIST --> Definition list
            ('<article><glosslist><glossentry><glossterm>Term 1</glossterm><glossdef><para>Definition 1</para></glossdef></glossentry><glossentry><glossterm>Term 2</glossterm><glossdef><para>Definition 2</para></glossdef></glossentry></glosslist></article>',
                # <page><body><div html:class="article"><list><list-item><list-item-label>Termm 1</list-item-label><list-item-body>Definition 1</list-item-body></list-item><list-item><list-item-label>Term 2</list-item-label><list-item-body>Definition 2</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[list-item[1][list-item-label="Term 1"][list-item-body[p="Definition 1"]]][list-item[2][list-item-label="Term 2"][list-item-body[p="Definition 2"]]]'),
            # SEGMENTED LIST --> Definition List
            ('<article><segmentedlist><segtitle>Term 1</segtitle><segtitle>Term 2</segtitle><segtitle>Term 3</segtitle><seglistitem><seg>Def 1:1</seg><seg>Def 1:2</seg><seg>Def 1:3</seg></seglistitem><seglistitem><seg>Def 2:1</seg><seg>Def 2:2</seg><seg>Def 2:3</seg></seglistitem></segmentedlist></article>',
                '/page/body/div/list[list-item[1][list-item-label="Term 1"][list-item-body="Def 1:1"]][list-item[2][list-item-label="Term 2"][list-item-body="Def 1:2"]][list-item[3][list-item-label="Term 3"][list-item-body="Def 1:3"]][list-item[4][list-item-label="Term 1"][list-item-body="Def 2:1"]][list-item[5][list-item-label="Term 2"][list-item-body="Def 2:2"]][list-item[6][list-item-label="Term 3"][list-item-body="Def 2:3"]]'),
            # SIMPLE LIST --> unordered list
            ('<article><simplelist><member>Item 1</member><member>Item 2</member></simplelist></article>',
                # <page><body><div html:class="article"><list item-label-generate="unordered"><list-item><list-item-body>Unordered Item 1</list-item-body></list-item><list-item><list-item-body>Unordered Item 2</list-item-body></list-item></list></div></body></page>
                '/page/body/div/list[@item-label-generate="unordered"][list-item[1]/list-item-body[text()="Item 1"]][list-item[2]/list-item-body[text()="Item 2"]]'),
            # Q and A set with defaultlabel = number --> ordered list
            ("<article><qandaset defaultlabel='number'><qandaentry><question><para>Question 1</para></question><answer><para>Answer 1</para></answer></qandaentry><qandaentry><question><para>Question 2</para></question><answer><para>Answer 2</para></answer></qandaentry></qandaset></article> ",
                # <page><body><div html:class="article"><list item-label-generate="ordered"><list-item><list-item-body><p>Question1</p><p>Answer 1</p></list-item-body></list-item><list-item><list-item-body><p>Question 2</p><p>Answer 2</p></list-item-body></list-item></div></body></page>
                '/page/body/div/list[@item-label-generate="ordered"][list-item[1]/list-item-body[p[1][text()="Question 1"]][p[2][text()="Answer 1"]]][list-item[2]/list-item-body[p[1][text()="Question 2"]][p[2][text()="Answer 2"]]]'),
            # Q and A set with defaultlabel = qanda --> definition list, with Q: and A: for the label
            ("<article><qandaset defaultlabel='qanda'><qandaentry><question><para>Question 1</para></question><answer><para>Answer 1</para></answer></qandaentry><qandaentry><question><para>Question 2</para></question><answer><para>Answer 2</para></answer></qandaentry></qandaset></article> ",
                # <page><body><div html:class="article"><list><list-item><list-item-label>Q: </list-item-label><list-item-body>Question 1</list-item-body></list-item><list-item><list-item-label>A: </list-item-label><list-item-body>Answer 1</list-item-body></list-item><list-item><list-item-label>Q: </list-item-label><list-item-body>Question 2</list-item-body></list-item><list-item><list-item-label>A: </list-item-label><list-item-body>Answer 2</list-item-body></list-item>
                '/page/body/div/list[list-item[1][list-item-label="Q:"][list-item-body="Question 1"]][list-item[2][list-item-label="A:"][list-item-body="Answer 1"]][list-item[3][list-item-label="Q:"][list-item-body="Question 2"]][list-item[4][list-item-label="A:"][list-item-body="Answer 2"]]'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_table(self):
        data = [
            ('<article><table><thead><tr><td>Header</td></tr></thead><tfoot><tr><td>Footer</td></tr></tfoot><tbody><tr><td>Cell</td></tr></tbody></table></article>',
                # <page><body><div html:class="article"><table><table-header><table-row><table-cell>Header</table-cell></table-row></table-header><table-footer><table-row><table-cell>Footer</table-cell></table-row></table-footer><table-body><table-row><table-cell>Cell</table-row></table-cell></table></div></body></page>
                '/page/body/div/table[./table-header/table-row[table-cell="Header"]][./table-footer/table-row[table-cell="Footer"]][./table-body/table-row[table-cell="Cell"]]'),
            ('<article><table><tbody><tr><td colspan="2">Cell</td></tr></tbody></table></article>',
                # <page><body><div html:class="article"><table><table-body><table-row><table-cell number-columns-spanned="2">Cell</table-cell></table-row></table-body></table></div></body></page>
                '/page/body/div/table/table-body/table-row/table-cell[text()="Cell"][@number-columns-spanned="2"]'),
            ('<article><table><tbody><tr><td rowspan="2">Cell</td></tr></tbody></table></article>',
                # <page><body><div html:class="article"><table><table-body><table-row><table-cell number-rows-spanned="2">Cell</table-cell></table-row></table-body></table></div></body></page>
                '/page/body/div/table/table-body/table-row/table-cell[text()="Cell"][@number-rows-spanned="2"]'),
            # Simple db.cals.table
            ('<article><table xml:id="ex.calstable"><tgroup cols="2"><thead><row><entry>a1</entry><entry>a2</entry></row></thead><tfoot><row><entry>f1</entry><entry>f2</entry></row></tfoot><tbody><row><entry>b1</entry><entry>b2</entry></row></tbody></tgroup></table></article>',
                # <page><body><div html:class="article"><table><table-header><table-row><table-cell>a1</table-cell><table-cell>a2</table-cell></table-row></table-header><table-footer><table-row><table-cell>f1</table-cell><table-cell>f2</table-cell></table-row></table-footer><table-body><table-row><table-cell>b1</table-row><table-cell>b2</table-row></table-cell></table></div></body></page>
                '/page/body/div/table[./table-header/table-row[table-cell="a1"][table-cell="a2"]][./table-footer/table-row[table-cell="f1"][table-cell="f2"]][./table-body/table-row[table-cell="b1"][table-cell="b2"]]'),
            # db.cals.table with entry table.
            ('<article><table xml:id="ex.calstable"><tgroup cols="1"><thead><row><entry>a1</entry></row></thead><tfoot><row><entry>f1</entry></row></tfoot><tbody><row><entrytbl cols="1"><tbody><row><entry>s1</entry></row></tbody></entrytbl></row></tbody></tgroup></table></article>',
                # <page><body><div html:class="article"><table><table-header><table-row><table-cell>a1</table-cell></table-row></table-header><table-footer><table-row><table-cell>f1</table-cell></table-row></table-footer><table-body><table-row><table-cell><table><table-body><table-row><table-cell>s1</table-cell></table-row></table-body></table></table-row></table-cell></table></div></body></page>
                '/page/body/div/table[./table-header/table-row[table-cell="a1"]][./table-footer/table-row[table-cell="f1"]][./table-body/table-row[table-cell/table/table-body/table-row[table-cell="s1"]]]'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_misc(self):
        data = [
            ('<article><para>Text Para<footnote><para>Text Footnote</para></footnote></para></article>',
                # <page><body><div html:class="article"><p>Text Para<note note-class="footnote"><note-body><p>Text Footnote</p></note-body></note></p></div></body></page>
                '/page/body/div/p[text()="Text Para"]/note[@note-class="footnote"]/note-body/p[text()="Text Footnote"]'),
            ('<article><para><quote>text</quote></para></article>',
                # <page><body><div html:class="article"><p><quote>text</quote></para></article>
                '/page/body/div/p[quote="text"]'),
            # Test span for inline element
            ('<article><para><abbrev>ABBREV</abbrev></para></article>',
                # <page><body><div html:class="article"><p><span class="db-abbrev">ABBREV</span></p></div></body></page>
                '/page/body/div/p/span[@html:class="db-abbrev"][text()="ABBREV"]'),
            # Test div for block element
            ('<article><acknowledgements><para>Text</para></acknowledgements></article>',
                # <page><body><div html:class="article"><div html:class="db-acknowledgements"><p>Text</p></div></div></body></page>
                '/page/body/div/div[@html:class="db-acknowledgements"][p="Text"]'),
            # Test for <informalequation>
            ('<article><informalequation><para>E = mc^2</para></informalequation></article>',
                # <page><body><div html:class="article"><div html:class="db-equation"><p>E = mc^2</p></div></div></body></page>
                '/page/body/div/div[@html:class="db-equation"][p="E = mc^2"]'),
            # Test for <informalexample>
            ('<article><informalexample><para>example</para></informalexample></article>',
                # <page><body><div html:class="article"><div html:class="db-example"><p>example</p></div></div></body></page>
                '/page/body/div/div[@html:class="db-example"][p="example"]'),
            # Test for <sbr />
            ('<article><cmdsynopsis><para>Line 1<sbr />Line 2</para></cmdsynopsis></article>',
                # <page><body><div html:class="article"><div html:class="db-cmdsynopsis"><p>Line 1<line-break />Line 2</p></div></div></body></page>
                '/page/body/div/div[@html:class="db-cmdsynopsis"]/p/line-break'),
            # Test for <tag> element with class and namespace attribute
            ('<article><para><tag class="attribute" namespace="namespace">TAG</tag></para></article>',
                # <page><body><div html:class="article"><p><span class="db-tag-attribute">{namespace}TAG</span></p></div></article>
                '/page/body/div/p/span[@html:class="db-tag-attribute"][text()="{namespace}TAG"]'),
            # Test for <tag> element without class and namespace attribute
            ('<article><para><tag>TAG</tag></para></article>',
                # <page><body><div html:class="article"><p><span class="db-tag">TAG</span></p></div></article>
                '/page/body/div/p/span[@html:class="db-tag"][text()="TAG"]'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_link(self):
        data = [
            # Normal link, with conversion of all the xlink attributes
            ('<article><para><link xlink:href="http:test" xlink:title="title">link</link></para></article>',
                # <page><body><div html:class="article"><p><a xlink:href="http:test" xlink:title="title">link</a></p></div></body></page>
                '/page/body/div/p/a[@xlink:href="http:test"][@xlink:title="title"][text()="link"]'),
            # Old link from DocBook v.4.X for backward compatibility
            ('<article><para><ulink url="http:test">link</ulink></para></article>',
                # <page><body><div html:class="article"><p><a xlink:href="http:test">link</a></p></div></body></page>
                '/page/body/div/p/a[@xlink:href="http:test"][text()="link"]'),
            # Normal link, with linkend attribute
            ('<article><para><link linkend="anchor">link</link></para></article>',
                # <page><body><div html:class="article"><p><a xlink:href="#anchor">link</a></p></div></body></page>
                '/page/body/div/p/a[@xlink:href="#anchor"][text()="link"]'),
            # OLINK
            ('<article><para><olink targetdoc="uri" targetptr="anchor">link</olink></para></article>',
                # <page><body><div html:class="article"><para><a xlink:href="uri#anchor">link</a></para></div></body></page>
                '/page/body/div/p/a[@xlink:href="uri#anchor"][text()="link"]'),
            # Link w/ javascript: scheme
            ('<article><para><ulink url="javascript:alert(\'xss\')">link</ulink></para></article>',
                # the href attribute will default to None because javascript is not an allowed url scheme
                # we don't care how it gets rendered as long as the javascript doesn't show up
                # <page><body><div html:class="article"><p><a xlink:href="None">link</a></p></div></body></page>
                '/page/body/div/p/a[@xlink:href="None"][text()="link"]'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_code(self):
        data = [
            ('<article><screen>Text</screen></article>',
                # <page><body><div html:class="article"><blockcode>Text</blockcode></div></body></page>
                '/page/body/div[blockcode="Text"]'),
            # Test for <screen> with CDATA
            ('<article><screen><![CDATA[Text]]></screen></article>',
                # <page><body><div html:class="article"><blockcode>Text</blockcode></div></body></page>
                '/page/body/div[blockcode="Text"]'),
            # PROGRAMLISTING --> BLOCKCODE
            ('<article><programlisting>Text</programlisting></article>',
                # <page><body><div html:class="article"><blockcode>Text</blockcode></div></body></page>
                '/page/body/div[blockcode="Text"]'),
            # LITERAL --> CODE
            ('<article><para>text<literal>literal</literal></para></article>',
                # <page><body><div html:class="article"><p>text<code>literal</code></p></div></body></page>
                '/page/body/div/p[text()="text"][code="literal"]'),
            ('<article><blockquote><attribution>author</attribution>text</blockquote></article>',
                # <page><body><div html:class="article"><blockquote source="author">text</blockquote></div></body></page>
                '/page/body/div/blockquote[@source="author"][text()="text"]'),
            # CODE --> CODE
            ('<article><para><code>Text</code></para></article>',
                # <page><body><div html:class="article"><p><code>Text</code></p></article>
                '/page/body/div/p[code="Text"]'),
            # COMPUTEROUTPUT --> CODE
            ('<article><para><computeroutput>Text</computeroutput></para></article>',
                # <page><body><div html:class="article"><p><code>Text</code></p></article>
                '/page/body/div/p[code="Text"]'),
            # MARKUP --> CODE
            ('<article><para><markup>Text</markup></para></article>',
                # <page><body><div html:class="article"><p><code>Text</code></p></article>
                '/page/body/div/p[code="Text"]'),
            # LITERALLAYOUT --> BLOCKCODE
            ('<article><literallayout>Text</literallayout></article>',
                # <page><body><div html:class="article"><blockcode html:class="db-literallayout">Text</blockcode></div></body></page>
                '/page/body/div/blockcode[text()="Text"][@html:class="db-literallayout"]'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_object(self):
        data = [
            # Test for image object
            ('<article><para><inlinemediaobject><imageobject><imagedata fileref="test.png"/></imageobject></inlinemediaobject></para></article>',
                # <page><body><div html:class="db-article"><p><span html:class="db-inlinemediaobject"><object type="image/" html:alt="test.png" html:class="moin-transclusion" html:data-href="test.png" xlink:href="+get/test.png" /></span></p></div></body></page>
                '/page/body/div/p/span[@html:class="db-inlinemediaobject"]/object[@xlink:href="+get/test.png"][@type="image/"]'),
            # Test for audio object
            ('<article><para><inlinemediaobject><audioobject><audiodata fileref="test.wav"/></audioobject></inlinemediaobject></para></article>',
                # <page><body><div html:class="db-article"><p><span html:class="db-inlinemediaobject"><object type="audio/" html:alt="test.wav" html:class="moin-transclusion" html:data-href="test.wav" xlink:href="+get/test.wav" /></span></p></div></body></page>
                '/page/body/div/p/span[@html:class="db-inlinemediaobject"]/object[@xlink:href="+get/test.wav"][@type="audio/"]'),
            # Test for video object
            ('<article><para><mediaobject><videoobject><videodata fileref="test.avi"/></videoobject></mediaobject></para></article>',
                # <page><body><div html:class="db-article"><p><div html:class="db-mediaobject"><object type="video/" html:alt="test.avi" html:class="moin-transclusion" html:data-href="test.avi" xlink:href="+get/test.avi" /></div></p></div></body></page>
                '/page/body/div/p/div[@html:class="db-mediaobject"]/object[@xlink:href="+get/test.avi"][@type="video/"]'),
            # Test for image object with different imagedata
            ('<article><mediaobject><imageobject><imagedata fileref="figures/eiffeltower.eps" format="EPS"/></imageobject><imageobject><imagedata fileref="figures/eiffeltower.png" format="PNG"/></imageobject><textobject><phrase>The Eiffel Tower</phrase> </textobject><caption><para>Designed by Gustave Eiffel in 1889, The Eiffel Tower is one of the most widely recognized buildings in the world.</para>  </caption></mediaobject></article>',
                # <page><body><div html:class="db-article"><div html:class="db-mediaobject"><span><object type="image/png" html:alt="figures/eiffeltower.png" html:class="moin-transclusion" html:data-href="figures/eiffeltower.png" xlink:href="+get/figures/eiffeltower.png" /><span class="db-caption"><p>Designed by Gustave Eiffel in 1889, The Eiffel Tower is one of the most widely recognized buildings in the world.</p></span></span></div></div></body></page>
                '/page/body/div/div[@html:class="db-mediaobject"]/span/object[@xlink:href="+get/figures/eiffeltower.png"][@type="image/png"]'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_style_element(self):
        data = [
            # EMPHASIS --> EMPHASIS
            ('<article><para>text<emphasis>emphasis</emphasis></para></article>',
                # <page><body><div html:class="article"><p>text<emphasis>emphasis</emphasis></p></div></body></page>
                '/page/body/div/p[text()="text"][emphasis="emphasis"]'),
            # EMPHASIS role='strong' --> STRONG
            ('<article><para>text<emphasis role="strong">strong</emphasis></para></article>',
                # <page><body><div html:class="db-article"><p>text<emphasis>strong</emphasis></p></div></body></page>
                '/page/body/div/p[text()="text"]/emphasis[text()="strong"]'),
            # SUBSCRIPT --> SPAN baseline-shift = 'sub'
            ('<article><para><subscript>sub</subscript>script</para></article>',
                # <page><body><div html:class="article"><p>script<span baseline-shift="sub">sub</span></p></div></body></page>
                '/page/body/div/p[text()="script"]/span[@baseline-shift="sub"][text()="sub"]'),
            # SUPERSCRIPT --> SPAN baseline-shift = 'super'
            ('<article><para><superscript>super</superscript>script</para></article>',
                # <page><body><div html:class="article"><p>script<span baseline-shift="super">super</span></p></div></body></page>
                '/page/body/div/p[text()="script"]/span[@baseline-shift="super"][text()="super"]'),
            # PHRASE --> SPAN
            ('<article><para><phrase>text</phrase></para></article>',
                # <page><body><div html:class="article"><p><span>text</span></p></div></body></page>
                '/page/body/div/p[span="text"]'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_admonition(self):
        data = [
            # Test for caution admonition
            ('<article><caution><para>text</para></caution></article>',
                # <page><body><div html:class="article"><admonition type='caution'><p>text<p></admonition></div></body></page>
                '/page/body/div/admonition[@type="caution"][p="text"]'),
            # Test for important admonition
            ('<article><important><para>text</para></important></article>',
                # <page><body><div html:class="article"><admonition type='important'><p>text<p></admonition></div></body></page>
                '/page/body/div/admonition[@type="important"][p="text"]'),
            # Test for note admonition
            ('<article><note><para>text</para></note></article>',
                # <page><body><div html:class="article"><admonition type='note'><p>text<p></admonition></div></body></page>
                '/page/body/div/admonition[@type="note"][p="text"]'),
            # Test for tip admonition
            ('<article><tip><para>text</para></tip></article>',
                # <page><body><div html:class="article"><admonition type='tip'><p>text<p></admonition></div></body></page>
                '/page/body/div/admonition[@type="tip"][p="text"]'),
            # Test for warning admonition
            ('<article><warning><para>text</para></warning></article>',
                # <page><body><div html:class="article"><admonition type='warning'><p>text<p></admonition></div></body></page>
                '/page/body/div/admonition[@type="warning"][p="text"]'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_trademark(self):
        data = [
            ('<article><para><trademark class="copyright">MoinMoin</trademark></para></article>',
                # <page><body><div html:class="db-article"><p><span html:class="db-trademark">\xa9  MoinMoin</span></p></div></body></page>
                u'/page/body/div/p/span[@html:class="db-trademark"][text()="\xa9 MoinMoin"]'),
            ('<article><para><trademark class="registered">Nutshell Handbook</trademark></para></article>',
                # <page><body><div html:class="db-article"><p><span html:class="db-trademark">Nutshell Handbook\xae</span></p></div></body></page>
                u'/page/body/div/p/span[@html:class="db-trademark"][text()="Nutshell Handbook\xae"]'),
            ('<article><para><trademark class="trade">Foo Bar</trademark></para></article>',
                # <page><body><div html:class="db-article"><p><span html:class="db-trademark">Foo Bar\u2122</span></p></div></body></page>
                u'/page/body/div/p/span[@html:class="db-trademark"][text()="Foo Bar\u2122"]'),
            ('<article><para><trademark class="service">MoinMoin</trademark></para></article>',
                # <page><body><div html:class="article"><p><span class="db-trademark">MoinMoin<span baseline-shift="super">SM</span></span></p></div></body></page>
                '/page/body/div/p/span[@html:class="db-trademark"][text()="MoinMoin"]/span[@baseline-shift="super"][text()="SM"]'),
            ('<article><para><trademark>MoinMoin</trademark></para></article>',
                # <page><body><div html:class="article"><p><span class="db-trademark">MoinMoin</span></p></div></body></page>
                '/page/body/div/p/span[@html:class="db-trademark"][text()="MoinMoin"]'),
        ]
        for i in data:
            yield(self.do, ) + i

    def test_error(self):
        data = [
            # Error: Xml not correctly formatted
            ('<article><para>Text</para>',
                '/page/body/part/error'),
            # Error: Root Element is not correct
            ('<link xlink:href="uri">link</link>',
                '/page/body/part/error'),
        ]
        for i in data:
            yield (self.do, ) + i

    def test_namespace(self):
        data = [
            # Error: Missing namespace
            ('<article><para>Text</para></article>',
                '/page/body/part/error'),
        ]
        for i in data:
            yield (self.do_nonamespace, ) + i