"""
Functions to process content of lxml nodes.
"""
from StringIO import StringIO
import lxml.html

from text import normalize_space as normalize_space_func, find_number

def get_node_text(node, smart=False, normalize_space=True):
    """
    Extract text content of the `node` and all its descendants.

    In smart mode `get_node_text` insert spaces between <tag><another tag>
    and also ignores content of the script and style tags.

    In non-smart mode this func just return text_content() of node
    with normalized spaces
    """

    if smart:
        value = ' '.join(node.xpath(
            './descendant-or-self::*[name() != "script" and '\
            'name() != "style"]/text()[normalize-space()]'))
    else:
        value = node.text_content()
    if normalize_space:
        value = normalize_space_func(value)
    return value

def find_node_number(node, ignore_spaces=False):
    """
    Find number in text content of the `node`.
    """

    return find_number(get_node_text(node), ignore_spaces=ignore_spaces)


def truncate_tail(node, xpath):
    """
    Find sub-node by its xpath and remove it and all adjacent nodes following
    after found node.
    """

    subnode = node.xpath(xpath)[0]
    for item in subnode.xpath('following-sibling::*'):
        item.getparent().remove(item)
    subnode.getparent().remove(subnode)


def drop_node(node, xpath):
    """
    Find sub-node by its xpath and remove it.
    """

    for item in node.xpath(xpath):
        item.getparent().remove(item)


def parse_html(html):
    """
    Parse html into ElementTree node.
    """

    return lxml.html.parse(StringIO(html),
                           lxml.html.HTMLParser(encoding='utf-8'))


def render_html(node, encoding='utf-8'):
    return lxml.html.tostring(node, encoding=encoding)


def truncate_html(html, limit, encoding='utf-8'):
    """
    Truncate html data to specified length and then fix broken tags.
    """

    if isinstance(html, basestring):
        html = html.decode('utf-8')
    truncated_html = html[:limit]
    elem = parse_html(truncated_html)
    fixed_html = render_html(elem, encoding=encoding)
    return fixed_html

@@ -1534,16 +1534,34 @@
 tml(html
+, encoding='utf-8'
 ):%0A    %22
@@ -1610,30 +1610,32 @@
    %22%22%22%0A%0A    
-return
+parser =
  lxml.html.p
@@ -1637,95 +1637,98 @@
 tml.
-parse(StringIO(html),%0A                           lxml.html.HTMLParser(encoding='utf-8')
+HTMLParser(encoding=encoding)%0A    return lxml.html.fragment_fromstring(html, parser=parser
 )%0A%0A%0A
@@ -1968,16 +1968,20 @@
 %0A    if 
+not 
 isinstan
@@ -1993,18 +1993,15 @@
 ml, 
-basestring
+unicode
 ):%0A 
@@ -2026,23 +2026,24 @@
 .decode(
-'utf-8'
+encoding
 )%0A    tr
@@ -2106,16 +2106,35 @@
 ted_html
+, encoding=encoding
 )%0A    fi

Refactor html serialization methods in lxml_tools module