comparison venv/lib/python2.7/site-packages/docutils/writers/docutils_xml.py @ 0:d67268158946 draft

planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author bcclaywell
date Mon, 12 Oct 2015 17:43:33 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d67268158946
1 # $Id: docutils_xml.py 7497 2012-08-16 15:17:29Z milde $
2 # Author: David Goodger, Paul Tremblay, Guenter Milde
3 # Maintainer: docutils-develop@lists.sourceforge.net
4 # Copyright: This module has been placed in the public domain.
5
6 """
7 Simple document tree Writer, writes Docutils XML according to
8 http://docutils.sourceforge.net/docs/ref/docutils.dtd.
9 """
10
11 __docformat__ = 'reStructuredText'
12
13 import sys
14
15 # Work around broken PyXML and obsolete python stdlib behaviour. (The stdlib
16 # replaces its own xml module with PyXML if the latter is installed. However,
17 # PyXML is no longer maintained and partially incompatible/buggy.) Reverse
18 # the order in which xml module and submodules are searched to import stdlib
19 # modules if they exist and PyXML modules if they do not exist in the stdlib.
20 #
21 # See http://sourceforge.net/tracker/index.php?func=detail&aid=3552403&group_id=38414&atid=422030
22 # and http://lists.fedoraproject.org/pipermail/python-devel/2012-July/000406.html
23 import xml
24 if "_xmlplus" in xml.__path__[0]: # PyXML sub-module
25 xml.__path__.reverse() # If both are available, prefer stdlib over PyXML
26
27 import xml.sax.saxutils
28 from StringIO import StringIO
29
30 import docutils
31 from docutils import frontend, writers, nodes
32
33
34 class RawXmlError(docutils.ApplicationError): pass
35
36
37 class Writer(writers.Writer):
38
39 supported = ('xml',)
40 """Formats this writer supports."""
41
42 settings_spec = (
43 '"Docutils XML" Writer Options',
44 None,
45 (('Generate XML with newlines before and after tags.',
46 ['--newlines'],
47 {'action': 'store_true', 'validator': frontend.validate_boolean}),
48 ('Generate XML with indents and newlines.',
49 ['--indents'],
50 {'action': 'store_true', 'validator': frontend.validate_boolean}),
51 ('Omit the XML declaration. Use with caution.',
52 ['--no-xml-declaration'],
53 {'dest': 'xml_declaration', 'default': 1, 'action': 'store_false',
54 'validator': frontend.validate_boolean}),
55 ('Omit the DOCTYPE declaration.',
56 ['--no-doctype'],
57 {'dest': 'doctype_declaration', 'default': 1,
58 'action': 'store_false', 'validator': frontend.validate_boolean}),))
59
60 settings_defaults = {'output_encoding_error_handler': 'xmlcharrefreplace'}
61
62 config_section = 'docutils_xml writer'
63 config_section_dependencies = ('writers',)
64
65 output = None
66 """Final translated form of `document`."""
67
68 def __init__(self):
69 writers.Writer.__init__(self)
70 self.translator_class = XMLTranslator
71
72 def translate(self):
73 self.visitor = visitor = self.translator_class(self.document)
74 self.document.walkabout(visitor)
75 self.output = ''.join(visitor.output)
76
77
78 class XMLTranslator(nodes.GenericNodeVisitor):
79
80 xml_declaration = '<?xml version="1.0" encoding="%s"?>\n'
81 # TODO: add stylesheet options similar to HTML and LaTeX writers?
82 #xml_stylesheet = '<?xml-stylesheet type="text/xsl" href="%s"?>\n'
83 doctype = (
84 '<!DOCTYPE document PUBLIC'
85 ' "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML"'
86 ' "http://docutils.sourceforge.net/docs/ref/docutils.dtd">\n')
87 generator = '<!-- Generated by Docutils %s -->\n'
88
89 xmlparser = xml.sax.make_parser()
90 """SAX parser instance to check/exctract raw XML."""
91 xmlparser.setFeature(
92 "http://xml.org/sax/features/external-general-entities", True)
93
94 def __init__(self, document):
95 nodes.NodeVisitor.__init__(self, document)
96
97 # Reporter
98 self.warn = self.document.reporter.warning
99 self.error = self.document.reporter.error
100
101 # Settings
102 self.settings = settings = document.settings
103 self.indent = self.newline = ''
104 if settings.newlines:
105 self.newline = '\n'
106 if settings.indents:
107 self.newline = '\n'
108 self.indent = ' '
109 self.level = 0 # indentation level
110 self.in_simple = 0 # level of nesting inside mixed-content elements
111
112 # Output
113 self.output = []
114 if settings.xml_declaration:
115 self.output.append(
116 self.xml_declaration % settings.output_encoding)
117 if settings.doctype_declaration:
118 self.output.append(self.doctype)
119 self.output.append(self.generator % docutils.__version__)
120
121 # initialize XML parser
122 self.the_handle=TestXml()
123 self.xmlparser.setContentHandler(self.the_handle)
124
125 # generic visit and depart methods
126 # --------------------------------
127
128 def default_visit(self, node):
129 """Default node visit method."""
130 if not self.in_simple:
131 self.output.append(self.indent*self.level)
132 self.output.append(node.starttag(xml.sax.saxutils.quoteattr))
133 self.level += 1
134 if isinstance(node, nodes.TextElement):
135 self.in_simple += 1
136 if not self.in_simple:
137 self.output.append(self.newline)
138
139 def default_departure(self, node):
140 """Default node depart method."""
141 self.level -= 1
142 if not self.in_simple:
143 self.output.append(self.indent*self.level)
144 self.output.append(node.endtag())
145 if isinstance(node, nodes.TextElement):
146 self.in_simple -= 1
147 if not self.in_simple:
148 self.output.append(self.newline)
149
150
151 # specific visit and depart methods
152 # ---------------------------------
153
154 def visit_Text(self, node):
155 text = xml.sax.saxutils.escape(node.astext())
156 self.output.append(text)
157
158 def depart_Text(self, node):
159 pass
160
161 def visit_raw(self, node):
162 if 'xml' not in node.get('format', '').split():
163 # skip other raw content?
164 # raise nodes.SkipNode
165 self.default_visit(node)
166 return
167 # wrap in <raw> element
168 self.default_visit(node) # or not?
169 xml_string = node.astext()
170 self.output.append(xml_string)
171 self.default_departure(node) # or not?
172 # Check validity of raw XML:
173 if isinstance(xml_string, unicode) and sys.version_info < (3,):
174 xml_string = xml_string.encode('utf8')
175 try:
176 self.xmlparser.parse(StringIO(xml_string))
177 except xml.sax._exceptions.SAXParseException, error:
178 col_num = self.the_handle.locator.getColumnNumber()
179 line_num = self.the_handle.locator.getLineNumber()
180 srcline = node.line
181 if not isinstance(node.parent, nodes.TextElement):
182 srcline += 2 # directive content start line
183 msg = 'Invalid raw XML in column %d, line offset %d:\n%s' % (
184 col_num, line_num, node.astext())
185 self.warn(msg, source=node.source, line=srcline+line_num-1)
186 raise nodes.SkipNode # content already processed
187
188
189 class TestXml(xml.sax.ContentHandler):
190
191 def setDocumentLocator(self, locator):
192 self.locator = locator