You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

66 lines
2.0 KiB

#!/usr/bin/env python3
# Based on jeffbr's xq
# a1ba: added unicode output
import argparse
import sys
from typing import Union
from lxml import etree
from lxml.builder import E
from pygments import highlight
from pygments.formatters.other import NullFormatter
from pygments.formatters.terminal import TerminalFormatter
from pygments.lexers.html import XmlLexer
# from . import NAME, DESCRIPTION, VERSION
NAME = 'xq'
VERSION = '0.0.4'
DESCRIPTION = 'like jq but for XML and XPath'
def wrap_in_results(elements: [Union[etree._Element, etree._ElementUnicodeResult]]) -> etree._Element:
results = E.results()
for el in elements:
results.append(E.result(el))
return results
def apply_xpath(infile, xpath_query=None, colorize=False):
try:
parsed = etree.parse(infile, etree.XMLParser(remove_blank_text=True))
except etree.XMLSyntaxError:
parsed = etree.parse(infile, etree.HTMLParser(remove_blank_text=True))
if xpath_query:
matches = parsed.xpath(xpath_query)
results = wrap_in_results(matches)
output = etree.tostring(results, pretty_print=True, encoding='unicode')
else:
output = etree.tostring(parsed, pretty_print=True, encoding='unicode')
formatter = TerminalFormatter() if colorize else NullFormatter()
return highlight(output, XmlLexer(), formatter)
def main():
parser = argparse.ArgumentParser(
prog=NAME,
description=DESCRIPTION,
)
parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + VERSION)
parser.add_argument(
'xpath_query', nargs='?', type=str,
help='XPath query to apply to XML document.'
)
parser.add_argument(
'file', nargs='?', type=argparse.FileType('r'), default=sys.stdin,
help='XML file to process. Defaults to STDIN.',
)
args = parser.parse_args()
sys.stdout.write(apply_xpath(args.file, args.xpath_query, sys.stdout.isatty()))
if __name__ == '__main__':
main()