1
2
3
4
5
6
7
8
9 import sys
10 import codecs
11
13 """
14 Doctest:
15
16 >>>from xmlwriter import XMLWriter
17 >>>writer = XMLWriter()
18 >>>writer.doctype(
19 ... u"xsa", u"-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML",
20 ... u"http://www.garshol.priv.no/download/xsa/xsa.dtd")
21 >>>#Notice: there is no error checking to ensure that the root element
22 >>>#specified in the doctype matches the top-level element generated
23 >>>writer.push(u"xsa")
24 >>>#Another element with child elements
25 >>>writer.push(u"vendor")
26 >>>#Element with simple text (#PCDATA) content
27 >>>writer.elem(u"name", u"Centigrade systems")
28 >>>writer.elem(u"email", u"info@centigrade.bogus")
29 >>>writer.elem(u"vendor", u"Centigrade systems")
30 >>>#Close currently open element ("vendor)
31 >>>writer.pop()
32 >>>#Element with an attribute
33 >>>writer.push(u"product", {u"id": u"100\u00B0"})
34 >>>writer.elem(u"name", u"100\u00B0 Server")
35 >>>writer.elem(u"version", u"1.0")
36 >>>writer.elem(u"last-release", u"20030401")
37 >>>#Empty element
38 >>>writer.empty(u"changes")
39 >>>writer.pop()
40 >>>writer.pop()
41
42 startElement
43 endElement
44 emptyElement
45 text, data
46 endDocument
47 attribute
48 indentation
49 close
50 flush
51 """
52
53 - def __init__(self, out=sys.stdout, encoding="utf-8", indent=u" "):
54 """
55 out - a stream for the output
56 encoding - an encoding used to wrap the output for unicode
57 indent - white space used for indentation
58 """
59 wrapper = codecs.lookup(encoding)[3]
60 self.out = wrapper(out)
61 self.stack = []
62 self.indent = indent
63 self.out.write(u'<?xml version="1.0" encoding="%s"?>\n' % encoding)
64
65 - def doctype(self, root, pubid, sysid):
66 """
67 Create a document type declaration (no internal subset)
68 """
69 if pubid == None:
70 self.out.write(
71 u"<!DOCTYPE %s SYSTEM '%s'>\n" % (root, sysid))
72 else:
73 self.out.write(
74 u"<!DOCTYPE %s PUBLIC '%s' '%s'>\n" \
75 % (root, pubid, sysid))
76
77 - def push(self, elem, attrs={}):
78 """
79 Create an element which will have child elements
80 """
81 self._indent()
82 self.out.write("<" + elem)
83 for (a, v) in attrs.items():
84 self.out.write(u" %s='%s'" % (a, self._escape_attr(v)))
85 self.out.write(u">\n")
86 self.stack.append(elem)
87
88 - def elem(self, elem, content, attrs={}):
89 """
90 Create an element with text content only
91 """
92 self._indent()
93 self.out.write(u"<" + elem)
94 for (a, v) in attrs.items():
95 self.out.write(u" %s='%s'" % (a, self._escape_attr(v)))
96 self.out.write(u">%s</%s>\n" \
97 % (self._escape_cont(content), elem))
98
99 - def empty(self, elem, attrs={}):
100 """
101 Create an empty element
102 """
103 self._indent()
104 self.out.write(u"<"+elem)
105 for a in attrs.items():
106 self.out.write(u" %s='%s'" % a)
107 self.out.write(u"/>\n")
108
110 """
111 Close an element started with the push() method
112 """
113 if len(self.stack) > 0:
114 elem=self.stack[-1]
115 del self.stack[-1]
116 self._indent()
117 self.out.write(u"</%s>\n" % elem)
118
120 return len(self.stack)
121
123 self.out.write(self.indent * (len(self.stack) * 2))
124
126 if text is None:
127 return None
128 return text.replace(u"&", u"&")\
129 .replace(u"<", u"<").replace(u">", u">")
130
132 if text is None:
133 return None
134 return text.replace(u"&", u"&") \
135 .replace(u"'", u"'").replace(u"<", u"<")\
136 .replace(u">", u">")
137