START = StreamEventKind('START') #: a start tag END = StreamEventKind('END') #: an end tag TEXT = StreamEventKind('TEXT') #: literal text class QName(unicode):
    """A qualified element or attribute name.
    
    The unicode value of instances of this class contains the qualified name of
    the element or attribute, in the form ``{namespace-uri}local-name``. The
    namespace URI can be obtained through the additional `namespace` attribute,
    while the local name can be accessed through the `localname` attribute.
    
    >>> qname = QName('foo')
    >>> qname
    QName('foo')
    >>> qname.localname
    u'foo'
    >>> qname.namespace
    
    >>> qname = QName('http://www.w3.org/1999/xhtml}body')
    >>> qname
    QName('http://www.w3.org/1999/xhtml}body')
    >>> qname.localname
    u'body'
    >>> qname.namespace
    u'http://www.w3.org/1999/xhtml'
    """
    __slots__ = ['namespace', 'localname']

    def __new__(cls, qname):
        """Create the `QName` instance.
        
        :param qname: the qualified name as a string of the form
                      ``{namespace-uri}local-name``, where the leading curly
                      brace is optional
        """
        if type(qname) is cls:
            return qname

        parts = qname.lstrip('{').split('}', 1)
        if len(parts) > 1:
            self = unicode.__new__(cls, '{%s' % qname)
            self.namespace, self.localname = map(unicode, parts)
        else:
            self = unicode.__new__(cls, qname)
            self.namespace, self.localname = None, unicode(qname)
        return self

    def __getnewargs__(self):
        return (self.lstrip('{'),)

    def __repr__(self):
        return '%s(%s)' % (type(self).__name__, stringrepr(self.lstrip('{'))) class Attrs(tuple):
    """Immutable sequence type that stores the attributes of an element.
    
    Ordering of the attributes is preserved, while access by name is also
    supported.
    
    >>> attrs = Attrs([('href', '#'), ('title', 'Foo')])
    >>> attrs
    Attrs([('href', '#'), ('title', 'Foo')])
    
    >>> 'href' in attrs
    True
    >>> 'tabindex' in attrs
    False
    >>> attrs.get('title')
    'Foo'
    
    Instances may not be manipulated directly. Instead, the operators ``|`` and
    ``-`` can be used to produce new instances that have specific attributes
    added, replaced or removed.
    
    To remove an attribute, use the ``-`` operator. The right hand side can be
    either a string or a set/sequence of strings, identifying the name(s) of
    the attribute(s) to remove:
    
    >>> attrs - 'title'
    Attrs([('href', '#')])
    >>> attrs - ('title', 'href')
    Attrs()
    
    The original instance is not modified, but the operator can of course be
    used with an assignment:

    >>> attrs
    Attrs([('href', '#'), ('title', 'Foo')])
    >>> attrs -= 'title'
    >>> attrs
    Attrs([('href', '#')])
    
    To add a new attribute, use the ``|`` operator, where the right hand value
    is a sequence of ``(name, value)`` tuples (which includes `Attrs`
    instances):
    
    >>> attrs | [('title', 'Bar')]
    Attrs([('href', '#'), ('title', 'Bar')])
    
    If the attributes already contain an attribute with a given name, the value
    of that attribute is replaced:
    
    >>> attrs | [('href', 'http://example.org/')]
    Attrs([('href', 'http://example.org/')])
    """
    __slots__ = []

    def __contains__(self, name):
        """Return whether the list includes an attribute with the specified
        name.
        
        :return: `True` if the list includes the attribute
        :rtype: `bool`
        """
        for attr, _ in self:
            if attr == name:
                return True

    def __getitem__(self, i):
        """Return an item or slice of the attributes list.
        
        >>> attrs = Attrs([('href', '#'), ('title', 'Foo')])
        >>> attrs[1]
        ('title', 'Foo')
        >>> attrs[1:]
        Attrs([('title', 'Foo')])
        """
        items = tuple.__getitem__(self, i)
        if type(i) is slice:
            return Attrs(items)
        return items

    def __getslice__(self, i, j):
        """Return a slice of the attributes list.
        
        >>> attrs = Attrs([('href', '#'), ('title', 'Foo')])
        >>> attrs[1:]
        Attrs([('title', 'Foo')])
        """
        return Attrs(tuple.__getslice__(self, i, j))

    def __or__(self, attrs):
        """Return a new instance that contains the attributes in `attrs` in
        addition to any already existing attributes. Any attributes in the new
        set that have a value of `None` are removed.
        
        :return: a new instance with the merged attributes
        :rtype: `Attrs`
        """
        remove = set([an for an, av in attrs if av is None])
        replace = dict([(an, av) for an, av in attrs
                        if an in self and av is not None])
        return Attrs([(sn, replace.get(sn, sv)) for sn, sv in self
                      if sn not in remove] +
                     [(an, av) for an, av in attrs
                      if an not in self and an not in remove])

    def __repr__(self):
        if not self:
            return 'Attrs()'
        return 'Attrs([%s])' % ', '.join([repr(item) for item in self])

    def __sub__(self, names):
        """Return a new instance with all attributes with a name in `names` are
        removed.
        
        :param names: the names of the attributes to remove
        :return: a new instance with the attribute removed
        :rtype: `Attrs`
        """
        if isinstance(names, basestring):
            names = (names,)
        return Attrs([(name, val) for name, val in self if name not in names])

    def get(self, name, default=None):
        """Return the value of the attribute with the specified name, or the
        value of the `default` parameter if no such attribute is found.
        
        :param name: the name of the attribute
        :param default: the value to return when the attribute does not exist
        :return: the attribute value, or the `default` value if that attribute
                 does not exist
        :rtype: `object`
        """
        for attr, value in self:
            if attr == name:
                return value
        return default

    def totuple(self):
        """Return the attributes as a markup event.
        
        The returned event is a `TEXT` event, the data is the value of all
        attributes joined together.
        
        >>> Attrs([('href', '#'), ('title', 'Foo')]).totuple()
        ('TEXT', '#Foo', (None, -1, -1))
        
        :return: a `TEXT` event
        :rtype: `tuple`
        """
        return TEXT, ''.join([x[1] for x in self]), (None, -1, -1) class Transformer(object):
    """Stream filter that can apply a variety of different transformations to
    a stream.

    This is achieved by selecting the events to be transformed using XPath,
    then applying the transformations to the events matched by the path
    expression. Each marked event is in the form (mark, (kind, data, pos)),
    where mark can be any of `ENTER`, `INSIDE`, `EXIT`, `OUTSIDE`, or `None`.

    The first three marks match `START` and `END` events, and any events
    contained `INSIDE` any selected XML/HTML element. A non-element match
    outside a `START`/`END` container (e.g. ``text()``) will yield an `OUTSIDE`
    mark.

    >>> html = HTML('<html><head><title>Some Title</title></head>'
    ...             '<body>Some <em>body</em> text.</body></html>')

    Transformations act on selected stream events matching an XPath expression.
    Here's an example of removing some markup (the title, in this case)
    selected by an expression:

    >>> print(html | Transformer('head/title').remove())
    <html><head/><body>Some <em>body</em> text.</body></html>

    Inserted content can be passed in the form of a string, or a markup event
    stream, which includes streams generated programmatically via the
    `builder` module:

    >>> from genshi.builder import tag
    >>> print(html | Transformer('body').prepend(tag.h1('Document Title')))
    <html><head><title>Some Title</title></head><body><h1>Document
    Title</h1>Some <em>body</em> text.</body></html>

    Each XPath expression determines the set of tags that will be acted upon by
    subsequent transformations. In this example we select the ``<title>`` text,
    copy it into a buffer, then select the ``<body>`` element and paste the
    copied text into the body as ``<h1>`` enclosed text:

    >>> buffer = StreamBuffer()
    >>> print(html | Transformer('head/title/text()').copy(buffer)
    ...     .end().select('body').prepend(tag.h1(buffer)))
    <html><head><title>Some Title</title></head><body><h1>Some Title</h1>Some
    <em>body</em> text.</body></html>

    Transformations can also be assigned and reused, although care must be
    taken when using buffers, to ensure that buffers are cleared between
    transforms:

    >>> emphasis = Transformer('body//em').attr('class', 'emphasis')
    >>> print(html | emphasis)
    <html><head><title>Some Title</title></head><body>Some <em
    class="emphasis">body</em> text.</body></html>
    """

    __slots__ = ['transforms']

    def __init__(self, path='.'):
        """Construct a new transformation filter.

        :param path: an XPath expression (as string) or a `Path` instance
        """
        self.transforms = [SelectTransformation(path)]

    def __call__(self, stream, keep_marks=False):
        """Apply the transform filter to the marked stream.

        :param stream: the marked event stream to filter
        :param keep_marks: Do not strip transformer selection marks from the
                           stream. Useful for testing.
        :return: the transformed stream
        :rtype: `Stream`
        """
        transforms = self._mark(stream)
        for link in self.transforms:
            transforms = link(transforms)
        if not keep_marks:
            transforms = self._unmark(transforms)
        return Stream(transforms,
                      serializer=getattr(stream, 'serializer', None))

    def apply(self, function):
        """Apply a transformation to the stream.

        Transformations can be chained, similar to stream filters. Any callable
        accepting a marked stream can be used as a transform.

        As an example, here is a simple `TEXT` event upper-casing transform:

        >>> def upper(stream):
        ...     for mark, (kind, data, pos) in stream:
        ...         if mark and kind is TEXT:
        ...             yield mark, (kind, data.upper(), pos)
        ...         else:
        ...             yield mark, (kind, data, pos)
        >>> short_stream = HTML('<body>Some <em>test</em> text</body>')
        >>> print(short_stream | Transformer('.//em/text()').apply(upper))
        <body>Some <em>TEST</em> text</body>
        """
        transformer = Transformer()
        transformer.transforms = self.transforms[:]
        if isinstance(function, Transformer):
            transformer.transforms.extend(function.transforms)
        else:
            transformer.transforms.append(function)
        return transformer

    #{ Selection operations

    def select(self, path):
        """Mark events matching the given XPath expression, within the current
        selection.

        >>> html = HTML('<body>Some <em>test</em> text</body>')
        >>> print(html | Transformer().select('.//em').trace())
        (None, ('START', (QName('body'), Attrs()), (None, 1, 0)))
        (None, ('TEXT', u'Some ', (None, 1, 6)))
        ('ENTER', ('START', (QName('em'), Attrs()), (None, 1, 11)))
        ('INSIDE', ('TEXT', u'test', (None, 1, 15)))
        ('EXIT', ('END', QName('em'), (None, 1, 19)))
        (None, ('TEXT', u' text', (None, 1, 24)))
        (None, ('END', QName('body'), (None, 1, 29)))
        <body>Some <em>test</em> text</body>

        :param path: an XPath expression (as string) or a `Path` instance
        :return: the stream augmented by transformation marks
        :rtype: `Transformer`
        """
        return self.apply(SelectTransformation(path))

    def invert(self):
        """Invert selection so that marked events become unmarked, and vice
        versa.

        Specificaly, all marks are converted to null marks, and all null marks
        are converted to OUTSIDE marks.

        >>> html = HTML('<body>Some <em>test</em> text</body>')
        >>> print(html | Transformer('//em').invert().trace())
        ('OUTSIDE', ('START', (QName('body'), Attrs()), (None, 1, 0)))
        ('OUTSIDE', ('TEXT', u'Some ', (None, 1, 6)))
        (None, ('START', (QName('em'), Attrs()), (None, 1, 11)))
        (None, ('TEXT', u'test', (None, 1, 15)))
        (None, ('END', QName('em'), (None, 1, 19)))
        ('OUTSIDE', ('TEXT', u' text', (None, 1, 24)))
        ('OUTSIDE', ('END', QName('body'), (None, 1, 29)))
        <body>Some <em>test</em> text</body>

        :rtype: `Transformer`
        """
        return self.apply(InvertTransformation())

    def end(self):
        """End current selection, allowing all events to be selected.

        Example:

        >>> html = HTML('<body>Some <em>test</em> text</body>')
        >>> print(html | Transformer('//em').end().trace())
        ('OUTSIDE', ('START', (QName('body'), Attrs()), (None, 1, 0)))
        ('OUTSIDE', ('TEXT', u'Some ', (None, 1, 6)))
        ('OUTSIDE', ('START', (QName('em'), Attrs()), (None, 1, 11)))
        ('OUTSIDE', ('TEXT', u'test', (None, 1, 15)))
        ('OUTSIDE', ('END', QName('em'), (None, 1, 19)))
        ('OUTSIDE', ('TEXT', u' text', (None, 1, 24)))
        ('OUTSIDE', ('END', QName('body'), (None, 1, 29)))
        <body>Some <em>test</em> text</body>

        :return: the stream augmented by transformation marks
        :rtype: `Transformer`
        """
        return self.apply(EndTransformation())

    #{ Deletion operations

    def empty(self):
        """Empty selected elements of all content.

        Example:

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//em').empty())
        <html><head><title>Some Title</title></head><body>Some <em/>
        text.</body></html>

        :rtype: `Transformer`
        """
        return self.apply(EmptyTransformation())

    def remove(self):
        """Remove selection from the stream.

        Example:

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//em').remove())
        <html><head><title>Some Title</title></head><body>Some
        text.</body></html>

        :rtype: `Transformer`
        """
        return self.apply(RemoveTransformation())

    #{ Direct element operations

    def unwrap(self):
        """Remove outermost enclosing elements from selection.

        Example:

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//em').unwrap())
        <html><head><title>Some Title</title></head><body>Some body
        text.</body></html>

        :rtype: `Transformer`
        """
        return self.apply(UnwrapTransformation())

    def wrap(self, element):
        """Wrap selection in an element.

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//em').wrap('strong'))
        <html><head><title>Some Title</title></head><body>Some
        <strong><em>body</em></strong> text.</body></html>

        :param element: either a tag name (as string) or an `Element` object
        :rtype: `Transformer`
        """
        return self.apply(WrapTransformation(element))

    #{ Content insertion operations

    def replace(self, content):
        """Replace selection with content.

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//title/text()').replace('New Title'))
        <html><head><title>New Title</title></head><body>Some <em>body</em>
        text.</body></html>

        :param content: Either a callable, an iterable of events, or a string
                        to insert.
        :rtype: `Transformer`
        """
        return self.apply(ReplaceTransformation(content))

    def before(self, content):
        """Insert content before selection.

        In this example we insert the word 'emphasised' before the <em> opening
        tag:

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//em').before('emphasised '))
        <html><head><title>Some Title</title></head><body>Some emphasised
        <em>body</em> text.</body></html>

        :param content: Either a callable, an iterable of events, or a string
                        to insert.
        :rtype: `Transformer`
        """
        return self.apply(BeforeTransformation(content))

    def after(self, content):
        """Insert content after selection.

        Here, we insert some text after the </em> closing tag:

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//em').after(' rock'))
        <html><head><title>Some Title</title></head><body>Some <em>body</em>
        rock text.</body></html>

        :param content: Either a callable, an iterable of events, or a string
                        to insert.
        :rtype: `Transformer`
        """
        return self.apply(AfterTransformation(content))

    def prepend(self, content):
        """Insert content after the ENTER event of the selection.

        Inserting some new text at the start of the <body>:

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//body').prepend('Some new body text. '))
        <html><head><title>Some Title</title></head><body>Some new body text.
        Some <em>body</em> text.</body></html>

        :param content: Either a callable, an iterable of events, or a string
                        to insert.
        :rtype: `Transformer`
        """
        return self.apply(PrependTransformation(content))

    def append(self, content):
        """Insert content before the END event of the selection.

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//body').append(' Some new body text.'))
        <html><head><title>Some Title</title></head><body>Some <em>body</em>
        text. Some new body text.</body></html>

        :param content: Either a callable, an iterable of events, or a string
                        to insert.
        :rtype: `Transformer`
        """
        return self.apply(AppendTransformation(content))

    #{ Attribute manipulation

    def attr(self, name, value):
        """Add, replace or delete an attribute on selected elements.

        If `value` evaulates to `None` the attribute will be deleted from the
        element:

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em class="before">body</em> <em>text</em>.</body>'
        ...             '</html>')
        >>> print(html | Transformer('body/em').attr('class', None))
        <html><head><title>Some Title</title></head><body>Some <em>body</em>
        <em>text</em>.</body></html>

        Otherwise the attribute will be set to `value`:

        >>> print(html | Transformer('body/em').attr('class', 'emphasis'))
        <html><head><title>Some Title</title></head><body>Some <em
        class="emphasis">body</em> <em class="emphasis">text</em>.</body></html>

        If `value` is a callable it will be called with the attribute name and
        the `START` event for the matching element. Its return value will then
        be used to set the attribute:

        >>> def print_attr(name, event):
        ...     attrs = event[1][1]
        ...     print(attrs)
        ...     return attrs.get(name)
        >>> print(html | Transformer('body/em').attr('class', print_attr))
        Attrs([(QName('class'), u'before')])
        Attrs()
        <html><head><title>Some Title</title></head><body>Some <em
        class="before">body</em> <em>text</em>.</body></html>

        :param name: the name of the attribute
        :param value: the value that should be set for the attribute.
        :rtype: `Transformer`
        """
        return self.apply(AttrTransformation(name, value))

    #{ Buffer operations

    def copy(self, buffer, accumulate=False):
        """Copy selection into buffer.

        The buffer is replaced by each *contiguous* selection before being passed
        to the next transformation. If accumulate=True, further selections will
        be appended to the buffer rather than replacing it.

        >>> from genshi.builder import tag
        >>> buffer = StreamBuffer()
        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('head/title/text()').copy(buffer)
        ...     .end().select('body').prepend(tag.h1(buffer)))
        <html><head><title>Some Title</title></head><body><h1>Some
        Title</h1>Some <em>body</em> text.</body></html>

        This example illustrates that only a single contiguous selection will
        be buffered:

        >>> print(html | Transformer('head/title/text()').copy(buffer)
        ...     .end().select('body/em').copy(buffer).end().select('body')
        ...     .prepend(tag.h1(buffer)))
        <html><head><title>Some Title</title></head><body><h1>Some
        Title</h1>Some <em>body</em> text.</body></html>
        >>> print(buffer)
        <em>body</em>

        Element attributes can also be copied for later use:

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body><em>Some</em> <em class="before">body</em>'
        ...             '<em>text</em>.</body></html>')
        >>> buffer = StreamBuffer()
        >>> def apply_attr(name, entry):
        ...     return list(buffer)[0][1][1].get('class')
        >>> print(html | Transformer('body/em[@class]/@class').copy(buffer)
        ...     .end().buffer().select('body/em[not(@class)]')
        ...     .attr('class', apply_attr))
        <html><head><title>Some Title</title></head><body><em
        class="before">Some</em> <em class="before">body</em><em
        class="before">text</em>.</body></html>


        :param buffer: the `StreamBuffer` in which the selection should be
                       stored
        :rtype: `Transformer`
        :note: Copy (and cut) copy each individual selected object into the
               buffer before passing to the next transform. For example, the
               XPath ``*|text()`` will select all elements and text, each
               instance of which will be copied to the buffer individually
               before passing to the next transform. This has implications for
               how ``StreamBuffer`` objects can be used, so some
               experimentation may be required.

        """
        return self.apply(CopyTransformation(buffer, accumulate))

    def cut(self, buffer, accumulate=False):
        """Copy selection into buffer and remove the selection from the stream.

        >>> from genshi.builder import tag
        >>> buffer = StreamBuffer()
        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...             '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('.//em/text()').cut(buffer)
        ...     .end().select('.//em').after(tag.h1(buffer)))
        <html><head><title>Some Title</title></head><body>Some
        <em/><h1>body</h1> text.</body></html>

        Specifying accumulate=True, appends all selected intervals onto the
        buffer. Combining this with the .buffer() operation allows us operate
        on all copied events rather than per-segment. See the documentation on
        buffer() for more information.

        :param buffer: the `StreamBuffer` in which the selection should be
                       stored
        :rtype: `Transformer`
        :note: this transformation will buffer the entire input stream
        """
        return self.apply(CutTransformation(buffer, accumulate))

    def buffer(self):
        """Buffer the entire stream (can consume a considerable amount of
        memory).

        Useful in conjunction with copy(accumulate=True) and
        cut(accumulate=True) to ensure that all marked events in the entire
        stream are copied to the buffer before further transformations are
        applied.

        For example, to move all <note> elements inside a <notes> tag at the
        top of the document:

        >>> doc = HTML('<doc><notes></notes><body>Some <note>one</note> '
        ...            'text <note>two</note>.</body></doc>')
        >>> buffer = StreamBuffer()
        >>> print(doc | Transformer('body/note').cut(buffer, accumulate=True)
        ...     .end().buffer().select('notes').prepend(buffer))
        <doc><notes><note>one</note><note>two</note></notes><body>Some  text
        .</body></doc>

        """
        return self.apply(list)

    #{ Miscellaneous operations

    def filter(self, filter):
        """Apply a normal stream filter to the selection. The filter is called
        once for each contiguous block of marked events.

        >>> from genshi.filters.html import HTMLSanitizer
        >>> html = HTML('<html><body>Some text<script>alert(document.cookie)'
        ...             '</script> and some more text</body></html>')
        >>> print(html | Transformer('body/*').filter(HTMLSanitizer()))
        <html><body>Some text and some more text</body></html>

        :param filter: The stream filter to apply.
        :rtype: `Transformer`
        """
        return self.apply(FilterTransformation(filter))

    def map(self, function, kind):
        """Applies a function to the ``data`` element of events of ``kind`` in
        the selection.

        >>> html = HTML('<html><head><title>Some Title</title></head>'
        ...               '<body>Some <em>body</em> text.</body></html>')
        >>> print(html | Transformer('head/title').map(unicode.upper, TEXT))
        <html><head><title>SOME TITLE</title></head><body>Some <em>body</em>
        text.</body></html>

        :param function: the function to apply
        :param kind: the kind of event the function should be applied to
        :rtype: `Transformer`
        """
        return self.apply(MapTransformation(function, kind))

    def substitute(self, pattern, replace, count=1):
        """Replace text matching a regular expression.

        Refer to the documentation for ``re.sub()`` for details.

        >>> html = HTML('<html><body>Some text, some more text and '
        ...             '<b>some bold text</b>\\n'
        ...             '<i>some italicised text</i></body></html>')
        >>> print(html | Transformer('body/b').substitute('(?i)some', 'SOME'))
        <html><body>Some text, some more text and <b>SOME bold text</b>
        <i>some italicised text</i></body></html>
        >>> tags = tag.html(tag.body('Some text, some more text and\\n',
        ...      Markup('<b>some bold text</b>')))
        >>> print(tags.generate() | Transformer('body').substitute(
        ...     '(?i)some', 'SOME'))
        <html><body>SOME text, some more text and
        <b>SOME bold text</b></body></html>

        :param pattern: A regular expression object or string.
        :param replace: Replacement pattern.
        :param count: Number of replacements to make in each text fragment.
        :rtype: `Transformer`
        """
        return self.apply(SubstituteTransformation(pattern, replace, count))

    def rename(self, name):
        """Rename matching elements.

        >>> html = HTML('<html><body>Some text, some more text and '
        ...             '<b>some bold text</b></body></html>')
        >>> print(html | Transformer('body/b').rename('strong'))
        <html><body>Some text, some more text and <strong>some bold text</strong></body></html>
        """
        return self.apply(RenameTransformation(name))

    def trace(self, prefix='', fileobj=None):
        """Print events as they pass through the transform.

        >>> html = HTML('<body>Some <em>test</em> text</body>')
        >>> print(html | Transformer('em').trace())
        (None, ('START', (QName('body'), Attrs()), (None, 1, 0)))
        (None, ('TEXT', u'Some ', (None, 1, 6)))
        ('ENTER', ('START', (QName('em'), Attrs()), (None, 1, 11)))
        ('INSIDE', ('TEXT', u'test', (None, 1, 15)))
        ('EXIT', ('END', QName('em'), (None, 1, 19)))
        (None, ('TEXT', u' text', (None, 1, 24)))
        (None, ('END', QName('body'), (None, 1, 29)))
        <body>Some <em>test</em> text</body>

        :param prefix: a string to prefix each event with in the output
        :param fileobj: the writable file-like object to write to; defaults to
                        the standard output stream
        :rtype: `Transformer`
        """
        return self.apply(TraceTransformation(prefix, fileobj=fileobj))

    # Internal methods

    def _mark(self, stream):
        for event in stream:
            yield OUTSIDE, event

    def _unmark(self, stream):
        for mark, event in stream:
            kind = event[0]
            if not (kind is None or kind is ATTR or kind is BREAK):
                yield event class StreamBuffer(Stream):
    """Stream event buffer used for cut and copy transformations."""

    def __init__(self):
        """Create the buffer."""
        Stream.__init__(self, [])

    def append(self, event):
        """Add an event to the buffer.

        :param event: the markup event to add
        """
        self.events.append(event)

    def reset(self):
        """Empty the buffer of events."""
        del self.events[:] ENTER = TransformMark('ENTER') EXIT = TransformMark('EXIT') OUTSIDE = TransformMark('OUTSIDE') INSIDE = TransformMark('INSIDE') ATTR = TransformMark('ATTR') BREAK = TransformMark('BREAK')
import doctest
import unittest
import genshi.filters.transform
from pprint import pprint
from genshi import HTML
from genshi.builder import Element
from genshi.core import START, END, TEXT, QName, Attrs
from genshi.filters.transform import Transformer, StreamBuffer, ENTER, EXIT, \
                                     OUTSIDE, INSIDE, ATTR, BREAK
    from genshi.input import HTML
    from genshi.core import Markup
    from genshi.builder import tag
# -*- coding: utf-8 -*-
#
# Copyright (C) 2007 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://genshi.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://genshi.edgewall.org/log/.




FOO = '<root>ROOT<foo name="foo">FOO</foo></root>'
FOOBAR = '<root>ROOT<foo name="foo" size="100">FOO</foo><bar name="bar">BAR</bar></root>'


def _simplify(stream, with_attrs=False):
    """Simplify a marked stream."""
    def _generate():
        for mark, (kind, data, pos) in stream:
            if kind is START:
                if with_attrs:
                    data = (unicode(data[0]), dict((unicode(k), v)
                                                   for k, v in data[1]))
                else:
                    data = unicode(data[0])
            elif kind is END:
                data = unicode(data)
            elif kind is ATTR:
                kind = ATTR
                data = dict((unicode(k), v) for k, v in data[1])
            yield mark, kind, data
    return list(_generate())


def _transform(html, transformer, with_attrs=False):
    """Apply transformation returning simplified marked stream."""
    if isinstance(html, basestring):
        html = HTML(html)
    stream = transformer(html, keep_marks=True)
    return _simplify(stream, with_attrs)


class SelectTest(unittest.TestCase):
    """Test .select()"""
    def _select(self, select):
        html = HTML(FOOBAR)
        if isinstance(select, basestring):
            select = [select]
        transformer = Transformer(select[0])
        for sel in select[1:]:
            transformer = transformer.select(sel)
        return _transform(html, transformer)

    def test_select_single_element(self):
        self.assertEqual(
            self._select('foo'),
            [(None, START, u'root'),
             (None, TEXT, u'ROOT'),
             (ENTER, START, u'foo'),
             (INSIDE, TEXT, u'FOO'),
             (EXIT, END, u'foo'),
             (None, START, u'bar'),
             (None, TEXT, u'BAR'),
             (None, END, u'bar'),
             (None, END, u'root')],
            )

    def test_select_context(self):
        self.assertEqual(
            self._select('.'),
            [(ENTER, START, u'root'),
             (INSIDE, TEXT, u'ROOT'),
             (INSIDE, START, u'foo'),
             (INSIDE, TEXT, u'FOO'),
             (INSIDE, END, u'foo'),
             (INSIDE, START, u'bar'),
             (INSIDE, TEXT, u'BAR'),
             (INSIDE, END, u'bar'),
             (EXIT, END, u'root')]
            )

    def test_select_inside_select(self):
        self.assertEqual(
            self._select(['.', 'foo']),
            [(None, START, u'root'),
             (None, TEXT, u'ROOT'),
             (ENTER, START, u'foo'),
             (INSIDE, TEXT, u'FOO'),
             (EXIT, END, u'foo'),
             (None, START, u'bar'),
             (None, TEXT, u'BAR'),
             (None, END, u'bar'),
             (None, END, u'root')],
            )

    def test_select_text(self):
        self.assertEqual(
            self._select('*/text()'),
            [(None, START, u'root'),
             (None, TEXT, u'ROOT'),
             (None, START, u'foo'),

             (OUTSIDE, TEXT, u'FOO'),