nutools/lib/pyulib/src/uapps/uxpath.py

140 lines
4.0 KiB
Python
Executable File

#!/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 == ATTRIBUTE_NODE:
print rs.value.encode("utf-8")
elif nodeType == TEXT_NODE or nodeType == 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 == ATTRIBUTE_NODE:
rs.value = value
elif nodeType == TEXT_NODE or nodeType == 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()