# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # """ Useful transforms for dom objects. """ from __future__ import absolute_import from . import dom try: from io import StringIO except ImportError: from cStringIO import StringIO class Visitor: def descend(self, node): for child in node.children: child.dispatch(self) def node(self, node): self.descend(node) def leaf(self, leaf): pass class Identity: def descend(self, node): result = [] for child in node.children: result.append(child.dispatch(self)) return result def default(self, tag): result = dom.Tag(tag.name, *tag.attrs) result.extend(self.descend(tag)) return result def tree(self, tree): result = dom.Tree() result.extend(self.descend(tree)) return result def tag(self, tag): return self.default(tag) def leaf(self, leaf): return leaf.__class__(leaf.data) class Sexp(Identity): def __init__(self): self.stack = [] self.level = 0 self.out = "" def open(self, s): self.out += "(%s" % s self.level += len(s) + 1 self.stack.append(s) def line(self, s=""): self.out = self.out.rstrip() self.out += "\n" + " " * self.level + s def close(self): s = self.stack.pop() self.level -= len(s) + 1 self.out = self.out.rstrip() self.out += ")" def tree(self, tree): self.open("+ ") for child in tree.children: self.line() child.dispatch(self) self.close() def tag(self, tag): self.open("Node(%s) " % tag.name) for child in tag.children: self.line() child.dispatch(self) self.close() def leaf(self, leaf): self.line("%s(%s)" % (leaf.__class__.__name__, leaf.data)) class Output: def descend(self, node): out = StringIO() for child in node.children: out.write(child.dispatch(self)) return out.getvalue() def default(self, tag): out = StringIO() out.write("<%s" % tag.name) for k, v in tag.attrs: out.write(' %s="%s"' % (k, v)) out.write(">") out.write(self.descend(tag)) if not tag.singleton: out.write("" % tag.name) return out.getvalue() def tree(self, tree): return self.descend(tree) def tag(self, tag): return self.default(tag) def data(self, leaf): return leaf.data def entity(self, leaf): return "&%s;" % leaf.data def character(self, leaf): raise Exception("TODO") def comment(self, leaf): return "" % leaf.data class Empty(Output): def tag(self, tag): return self.descend(tag) def data(self, leaf): return "" def entity(self, leaf): return "" def character(self, leaf): return "" def comment(self, leaf): return "" class Text(Empty): def data(self, leaf): return leaf.data def entity(self, leaf): return "&%s;" % leaf.data def character(self, leaf): # XXX: is this right? return "&#%s;" % leaf.data