Skip to content

Commit

Permalink
Improved printing of namespaces.
Browse files Browse the repository at this point in the history
  • Loading branch information
peteradrichem committed Jan 12, 2025
1 parent 40b44d9 commit 228acc3
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 58 deletions.
7 changes: 4 additions & 3 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ Changelog

This document records all notable changes to `Xul <https://xul.readthedocs.io/>`_.

`Unreleased <https://github.com/peteradrichem/Xul/compare/2.5.1...py3k>`_ (2025-01-11)
`Unreleased <https://github.com/peteradrichem/Xul/compare/2.5.1...py3k>`_ (2025-01-12)
--------------------------------------------------------------------------------------
* Drop support for Python <= 3.8.
* Code checks: ruff, black, isort, mypy.
* Updated Sphinx configuration.
* Test script for local testing with Docker Compose.
* GitHub Action: code checks.
* Output formatting (f-strings).
* :doc:`xp <xp>`: fix boolean result (Python >= 3.12)
* :doc:`xp <xp>`: fix string result representation (Python 3)
* :doc:`xp <xp>`: fix boolean result (Python >= 3.12).
* :doc:`xp <xp>`: fix string result representation (Python 3).
* :doc:`xp <xp>`: improved printing of namespaces.

`2.5.1 <https://github.com/peteradrichem/Xul/compare/2.5.0...2.5.1>`_ (2024-12-26)
----------------------------------------------------------------------------------
Expand Down
42 changes: 19 additions & 23 deletions docs/xp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,33 +40,29 @@ Options
$ xp --help
usage: xp [-h] [-V] [-e] [-d DEFAULT_NS_PREFIX] [-r] [-p] [-m] [-f | -F] [-q]
xpath_expr [xml_source [xml_source ...]]
usage: xp [-h] [-V] [-e] [-d DEFAULT_NS_PREFIX] [-q] [-p] [-r] [-f | -F] [-m] xpath_expr [xml_source ...]
Select nodes in an XML source with an XPath expression.
positional arguments:
xpath_expr XPath expression
xml_source XML source (file, <stdin>, http://...)
optional arguments:
-h, --help show this help message and exit
-V, --version show program's version number and exit
-e, --exslt add EXSLT XML namespace prefixes
-d DEFAULT_NS_PREFIX, --default-prefix DEFAULT_NS_PREFIX
set the prefix for the default namespace in XPath
[default: 'd']
-r, --result-xpath print the XPath expression of the result element (or
its parent)
-p, --pretty-element pretty print the result element
-m, --method use ElementTree.xpath method instead of XPath class
-f, -l, --files-with-hits
only the names of files with a non-false and non-NaN
result are written to standard output
-F, -L, --files-without-hits
only the names of files with a false or NaN result, or
without any results are written to standard output
-q, --quiet don't print the XML namespace list
xpath_expr XPath expression
xml_source XML source (file, <stdin>, http://...)
options:
-h, --help show this help message and exit
-V, --version show program's version number and exit
-e, --exslt add EXSLT XML namespaces
-d DEFAULT_NS_PREFIX, --default-prefix DEFAULT_NS_PREFIX
set the prefix for the default namespace in XPath [default: 'd']
-q, --quiet don't print XML source namespaces
-p, --pretty-element pretty print the result element
-r, --result-xpath print the XPath expression of the result element (or its parent)
-f, -l, --files-with-hits
only the names of files with a non-false and non-NaN result are written to standard output
-F, -L, --files-without-hits
only the names of files with a false or NaN result, or without any results are written to
standard output
-m, --method use ElementTree.xpath method instead of XPath class
.. index::
Expand Down
66 changes: 34 additions & 32 deletions src/xul/cmd/xp.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def parse_cl() -> argparse.Namespace:
action="store_true",
default=False,
dest="exslt",
help="add EXSLT XML namespace prefixes",
help="add EXSLT XML namespaces",
)
parser.add_argument(
"-d",
Expand All @@ -41,12 +41,12 @@ def parse_cl() -> argparse.Namespace:
help="set the prefix for the default namespace in XPath [default: '%(default)s']",
)
parser.add_argument(
"-r",
"--result-xpath",
action="store_true",
default=False,
dest="result_xpath",
help="print the XPath expression of the result element (or its parent)",
"-q",
"--quiet",
action="store_false",
default=True,
dest="verbose",
help="don't print XML source namespaces",
)
parser.add_argument(
"-p",
Expand All @@ -57,12 +57,12 @@ def parse_cl() -> argparse.Namespace:
help="pretty print the result element",
)
parser.add_argument(
"-m",
"--method",
"-r",
"--result-xpath",
action="store_true",
default=False,
dest="lxml_method",
help="use ElementTree.xpath method instead of XPath class",
dest="result_xpath",
help="print the XPath expression of the result element (or its parent)",
)
file_group = parser.add_mutually_exclusive_group(required=False)
file_group.add_argument(
Expand All @@ -86,12 +86,12 @@ def parse_cl() -> argparse.Namespace:
+ "or without any results are written to standard output",
)
parser.add_argument(
"-q",
"--quiet",
action="store_false",
default=True,
dest="verbose",
help="don't print the XML namespace list",
"-m",
"--method",
action="store_true",
default=False,
dest="lxml_method",
help="use ElementTree.xpath method instead of XPath class",
)

return parser.parse_args()
Expand Down Expand Up @@ -151,18 +151,20 @@ def xp_prepare(


def print_xmlns(ns_map: dict[str, str], root: etree._Element) -> None:
"""Print XML namespaces.
"""Print XML source namespaces (prefix: namespace URI).
:param ns_map: XML namespaces (xmlns) 'prefix': 'URI' dict
:param root: root (document) element
"""
if None in root.nsmap:
print(f"Default XML namespace URI: {root.nsmap[None]}")
if ns_map:
# Print all XML namespaces -- prefix: namespace URI.
print("XML namespaces:")
print("XML namespaces (prefix: URI):")
for key in ns_map:
print(f"{key:>9}: {ns_map[key]}")
if None in root.nsmap and ns_map[key] == root.nsmap[None]:
print(f"{key:>9}: {ns_map[key]} (default namespace)")
else:
print(f"{key:>9}: {ns_map[key]}")
elif None in root.nsmap:
print(f"Default XML namespace URI: {root.nsmap[None]}")


def element_repr(node) -> str:
Expand Down Expand Up @@ -315,7 +317,10 @@ def print_result_list(result_list, el_tree: etree._ElementTree, args: argparse.N
elif isinstance(node, tuple):
prefix, uri = node
# No line number.
print(f"prefix: {str(prefix):<8} URI: {uri}")
if prefix is None:
print(f"prefix: {args.default_ns_prefix:<8} URI: {uri}")
else:
print(f"prefix: {prefix:<8} URI: {uri}")

# ?
else:
Expand Down Expand Up @@ -355,14 +360,11 @@ def print_result_header(source_name: str, xp_result) -> None:
print(f"{xp_r_len} results.")


def print_xp_result(
xp_result, el_tree: etree._ElementTree, ns_map: dict[str, str], args: argparse.Namespace
) -> None:
def print_xp_result(xp_result, el_tree: etree._ElementTree, args: argparse.Namespace) -> None:
"""Print XPath results.
:param xp_result: XPath result
:param el_tree: lxml ElementTree
:param ns_map: XML namespaces (xmlns) 'prefix': 'URI' dict
:param args: command-line arguments
Prints:
Expand All @@ -372,9 +374,6 @@ def print_xp_result(
XPath return values:
https://lxml.de/xpathxslt.html#xpath-return-values
"""
if args.verbose:
print_xmlns(ns_map, el_tree.getroot())

# STRING - string - smart string | Namespace URI.
if isinstance(xp_result, etree._ElementUnicodeResult):
print_smart_string(xp_result, el_tree, args)
Expand Down Expand Up @@ -453,10 +452,13 @@ def xpath_on_xml(
print(source_name)
return True

# XML namespaces.
if args.verbose:
print_xmlns(ns_map, el_tree.getroot())
# Result header.
print_result_header(source_name, xp_result)
# XPath results.
print_xp_result(xp_result, el_tree, ns_map, args)
print_xp_result(xp_result, el_tree, args)
return True


Expand Down

0 comments on commit 228acc3

Please sign in to comment.