#!/usr/bin/env python
# -*- coding: utf-8 mode: python -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8

u"""%(scriptname)s: Faire une requête xpath

USAGE
    %(scriptname)s -f input expr

OPTIONS
    -f, --input INPUT
        Spécifier un fichier en entrée
    -r, --replace VALUE
        Remplacer le contenu des noeuds trouvés par la valeur spécifiée.
    -w, --rewrite
        Re-écrire l'arbre modifié dans le fichier d'origine."""

import i_need_py25

import os, sys, mimetypes, types, shutil
from os import path
from xml.dom import Node, minidom

from ulib.all import *
from ulib.ext import xpath

def display_help():
    uprint(__doc__ % globals())

def dumprs(rs):
    tr = type(rs)
    unsupported = False
    if tr is types.BooleanType:
        print rs and "true" or "false"
    elif tr is types.FloatType:
        print rs
    elif tr is types.UnicodeType:
        print rs.encode("utf-8")
    elif tr is types.ListType:
        for r in rs: dumprs(r)
    elif isinstance(rs, Node):
        nodeType = rs.nodeType
        if nodeType == Node.ELEMENT_NODE:
            print rs.toxml("utf-8")
        elif nodeType == Node.ATTRIBUTE_NODE:
            print rs.value.encode("utf-8")
        elif nodeType == Node.TEXT_NODE or nodeType == Node.CDATA_SECTION_NODE:
            print rs.data.encode("utf-8")
        else:
            unsupported = True
    else:
        unsupported = True
    if unsupported:
        die("type non géré pour l'affichage: %s (%s)" % (str(rs), tr))

def updaters(rs, value, doc):
    tr = type(rs)
    unsupported = False
    if tr is types.ListType:
        for r in rs: updaters(r, value, doc)
    elif isinstance(rs, Node):
        nodeType = rs.nodeType
        if nodeType == Node.ELEMENT_NODE:
            firstChild = rs.firstChild
            textNode = doc.createTextNode(value)
            if firstChild is None:
                rs.appendChild(textNode)
            elif firstChild.nodeType == Node.TEXT_NODE or \
            firstChild.nodeType == Node.CDATA_SECTION_NODE:
                rs.replaceChild(textNode, firstChild)
            else:
                rs.insertBefore(textNode, firstChild)
        elif nodeType == Node.ATTRIBUTE_NODE:
            rs.value = value
        elif nodeType == Node.TEXT_NODE or nodeType == Node.CDATA_SECTION_NODE:
            rs.data = value
        else:
            unsupported = True
    else:
        unsupported = True
    if unsupported:
        die("type non géré pour la mise à jour: %s (%s)" % (str(rs), tr))

def run_xpath():
    options, longoptions = build_options([
        ('h', 'help', "Afficher l'aide"),
        ('f:', 'input=', "Spécifier un fichier en entrée"),
        ('r:', 'replace=', "Remplacer la valeur des noeuds par celle spécifiée"),
        ('w', 'rewrite', "Reécrire le résultat dans le fichier original"),
        ])
    options, args = get_args(None, options, longoptions)

    file = None
    replace = None
    rewrite = False
    for option, value in options:
        if option in ('-h', '--help'):
            display_help()
            sys.exit(0)
        elif option in ('-f', '--input'):
            file = value
        elif option in ('-r', '--replace'):
            replace = value
        elif option in ('-w', '--rewrite'):
            rewrite = True

    if len(args) == 0:
        die("Vous devez spécifier l'expression XPATH")

    if file is None or file == "-":
        inf = sys.stdin
        close = False
        rewrite = False
    else:
        inf = open(file, 'rb')
        close = True

    doc = minidom.parse(inf)
    if close: inf.close()

    for expr in args:
        rs = xpath.find(expr, doc)
        if replace is None: dumprs(rs)
        else: updaters(rs, replace, doc)

    if replace is not None:
        if rewrite:
            outf, tempf = mktemp()
            close = True
        else:
            outf = sys.stdout
            close = False
        doc.writexml(outf, encoding='utf-8')
        if close:
            outf.close()
            shutil.copyfile(tempf, file)
            cltemp()

if __name__ == '__main__':
    run_xpath()
