Created a new library directory called "FreeLib". All OpenSource RFMKII components will reside there, fontTools being the flagship.
git-svn-id: svn://svn.code.sf.net/p/fonttools/code/trunk@2 4cde692c-a291-49d1-8350-778aa11640f8
diff --git a/Lib/xmlWriter.py b/Lib/xmlWriter.py
new file mode 100644
index 0000000..b078959
--- /dev/null
+++ b/Lib/xmlWriter.py
@@ -0,0 +1,172 @@
+"""xmlWriter.py -- Simple XML authoring class"""
+
+__author__ = "jvr"
+__version__ = "0.9"
+
+import string
+import struct
+
+INDENT = " "
+
+class XMLWriter:
+
+ def __init__(self, file, dtd=None, indentwhite=INDENT):
+ if type(file) == type(""):
+ self.file = open(file, "w")
+ else:
+ # assume writable file object
+ self.file = file
+ self.dtd = dtd
+ self.indentwhite = indentwhite
+ self.indentlevel = 0
+ self.stack = []
+ self.needindent = 1
+ self.writeraw("<?xml version='1.0'?>")
+ self.newline()
+ if self.dtd:
+ # DOCTYPE???
+ self.newline()
+
+ def close(self):
+ self.file.close()
+
+ def write(self, data):
+ self.writeraw(escape(data))
+
+ def write_noindent(self, data):
+ self.file.write(escape(data))
+
+ def write8bit(self, data):
+ self.writeraw(escape8bit(data))
+
+ def write16bit(self, data):
+ self.writeraw(escape16bit(data))
+
+ def writeraw(self, data):
+ if self.needindent:
+ self.file.write(self.indentlevel * self.indentwhite)
+ self.needindent = 0
+ self.file.write(data)
+
+ def newline(self):
+ self.file.write("\n")
+ self.needindent = 1
+
+ def comment(self, data):
+ data = escape(data)
+ lines = string.split(data, "\n")
+ self.writeraw("<!-- " + lines[0])
+ for line in lines[1:]:
+ self.newline()
+ self.writeraw(" " + line)
+ self.writeraw(" -->")
+
+ def simpletag(self, _TAG_, *args, **kwargs):
+ attrdata = apply(self.stringifyattrs, args, kwargs)
+ data = "<%s%s/>" % (_TAG_, attrdata)
+ self.writeraw(data)
+
+ def begintag(self, _TAG_, *args, **kwargs):
+ attrdata = apply(self.stringifyattrs, args, kwargs)
+ data = "<%s%s>" % (_TAG_, attrdata)
+ self.writeraw(data)
+ self.stack.append(_TAG_)
+ self.indent()
+
+ def endtag(self, _TAG_):
+ assert self.stack and self.stack[-1] == _TAG_, "nonmatching endtag"
+ del self.stack[-1]
+ self.dedent()
+ data = "</%s>" % _TAG_
+ self.writeraw(data)
+
+ def dumphex(self, data):
+ linelength = 16
+ hexlinelength = linelength * 2
+ chunksize = 8
+ for i in range(0, len(data), linelength):
+ hexline = hexStr(data[i:i+linelength])
+ line = ""
+ white = ""
+ for j in range(0, hexlinelength, chunksize):
+ line = line + white + hexline[j:j+chunksize]
+ white = " "
+ self.writeraw(line)
+ self.newline()
+
+ def indent(self):
+ self.indentlevel = self.indentlevel + 1
+
+ def dedent(self):
+ assert self.indentlevel > 0
+ self.indentlevel = self.indentlevel - 1
+
+ def stringifyattrs(self, *args, **kwargs):
+ if kwargs:
+ assert not args
+ attributes = kwargs.items()
+ attributes.sort()
+ elif args:
+ assert len(args) == 1
+ attributes = args[0]
+ else:
+ return ""
+ data = ""
+ for attr, value in attributes:
+ data = data + ' %s="%s"' % (attr, escapeattr(str(value)))
+ return data
+
+
+def escape(data):
+ data = string.replace(data, "&", "&")
+ data = string.replace(data, "<", "<")
+ return data
+
+def escapeattr(data):
+ data = string.replace(data, "&", "&")
+ data = string.replace(data, "<", "<")
+ data = string.replace(data, '"', """)
+ return data
+
+def escape8bit(data):
+ def escapechar(c):
+ n = ord(c)
+ if c in "<&":
+ if c == "&":
+ return "&"
+ else:
+ return "<"
+ elif 32 <= n <= 127:
+ return c
+ else:
+ return "&#" + `n` + ";"
+ return string.join(map(escapechar, data), "")
+
+needswap = struct.pack("h", 1) == "\001\000"
+
+def escape16bit(data):
+ import array
+ a = array.array("H")
+ a.fromstring(data)
+ if needswap:
+ a.byteswap()
+ def escapenum(n, amp=ord("&"), lt=ord("<")):
+ if n == amp:
+ return "&"
+ elif n == lt:
+ return "<"
+ elif 32 <= n <= 127:
+ return chr(n)
+ else:
+ return "&#" + `n` + ";"
+ return string.join(map(escapenum, a), "")
+
+
+def hexStr(s):
+ h = string.hexdigits
+ r = ''
+ for c in s:
+ i = ord(c)
+ r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
+ return r
+