# AUTOGENERATED FILE! PLEASE DON'T EDIT
"""All tools related to xml file format. Expected to use behind the "kxml"
module name, like this::
from k1lib.imports import *
cat("abc.xml") | kxml.node() | kxml.display()
"""
from k1lib import cli; from typing import Iterator
import xml.etree.ElementTree as ET; import copy, xml, k1lib
from typing import List
__all__ = ["node", "maxDepth", "tags", "pretty", "display"]
[docs]class node(cli.BaseCli):
"""Turns lines into a single node.
Example::
s = \"\"\"
<html>
<head>
<style></style>
</head>
<body>
<div></div>
</body>
</html>\"\"\"
s | kxml.node() # returns root node"""
[docs] def __ror__(self, it:Iterator[str]) -> ET.Element:
return ET.fromstring("".join(it))
def _maxDepth(node, maxDepth:int, depth:int=0):
if depth >= maxDepth:
while len(node) > 0: del node[0]
for n in node: _maxDepth(n, maxDepth, depth+1)
return node
[docs]class maxDepth(cli.BaseCli):
[docs] def __init__(self, depth:int=None, copy:bool=True):
"""Filters out too deep nodes.
Example::
# returns root node, but prunes children deeper than the specified depth
s | kxml.node() | kxml.maxDepth()
:param depth: max depth to include in
:param copy: whether to limit the nodes itself, or limit a copy"""
self.depth = depth if depth != None else float("inf")
self.copy = copy
[docs] def __ror__(self, node:ET.Element) -> ET.Element:
if self.copy: node = copy.deepcopy(node)
return _maxDepth(node, self.depth)
def _tags(node, tag:str, nested):
if node.tag == tag: yield node
if node.tag != tag or nested:
for n in node: yield from _tags(n, tag, nested)
def _pretty(node, depth:int=0, indents=[]):
attr = "".join([f" {k}=\"{v}\"" for k, v in node.attrib.items()])
text = (node.text or "").strip("\t \n\r")
if len(node) == 0:
if text == "": yield indents[depth] + f"<{node.tag}{attr}/>"
else: yield indents[depth] + f"<{node.tag}{attr}>{text}</{node.tag}>"
else:
yield indents[depth] + f"<{node.tag}{attr}>"
for n in node: yield from _pretty(n, depth+1, indents)
yield indents[depth] + f"</{node.tag}>"
[docs]class pretty(cli.BaseCli):
[docs] def __init__(self, indent:str=None):
"""Converts the element into a list of xml strings, and make them pretty.
Example::
# prints out the element
s | kxml.node() | kxml.pretty() | stdout()"""
self.indent = cli.init.patchDefaultIndent(indent)
[docs] def __ror__(self, it:ET.Element) -> Iterator[str]:
indents = [i*self.indent for i in range(100)]
return _pretty(it, indents=indents) | cli.filt(cli.op().strip() != "")
[docs]class display(cli.BaseCli):
[docs] def __init__(self, depth:int=3, lines:int=20):
"""Convenience method for getting head, make it pretty and print it out.
Example::
# prints out the element
s | kxml.node() | kxml.display()
:param depth: prune tags deeper than the specified depth. Put "None" to not prune at all
:param lines: max number of lines to print out. Put "None" if you want to display everything"""
self.depth = depth; self.lines = lines
[docs] def __ror__(self, it:ET.Element, lines=10):
if self.depth is not None: it = it | maxDepth(self.depth)
it | pretty() | cli.head(self.lines) | cli.stdout()