@@ -126,35 +126,48 @@ def internal_to_elem(pfsh, factory=ET.Element):
126126 sublist = []
127127 tags = list (pfsh .keys ())
128128
129- # Allow deeply nested structures
130- for tag in tags :
131- value = pfsh [tag ]
132- # we santize values automatically
133- # $ref -> _ref
134- if tag .startswith ('$' ):
135- tag = '_' + tag [1 :]
136-
137- if isinstance (value , dict ):
138- for k , v in value .items ():
139- if k [:1 ] == "@" :
140- attribs [k [1 :]] = v
141- elif k == "#text" :
142- text = v
143- elif k == "#tail" :
144- tail = v
145- elif isinstance (v , list ):
146- for v2 in v :
147- sublist .append (internal_to_elem ({k : v2 }, factory = factory ))
148- else :
149- sublist .append (internal_to_elem ({k : v }, factory = factory ))
150- else :
151- text = value
152- e = factory (tag , attribs )
129+ if len (tags ) > 1 :
130+ raise ValueError ("Illegal structure with multiple tags: %s" % tag )
131+
132+ tag = tags [0 ]
133+ value = pfsh [tag ]
134+
135+ def sani_value (v ):
136+ if v is None :
137+ return v
138+ return unicode (v )
139+
140+ # we santize values automatically
141+ # $ref -> _ref
142+ if tag .startswith ('$' ):
143+ tag = '_' + tag [1 :]
144+ if ':' in tag :
145+ assert isinstance (value , dict ), "hardcoded requirement: value must be dict for us to sanitize tag"
146+ tk = 'value'
147+ assert tk not in value
148+ value [tk ] = tag
149+ tag = 'item'
150+ if isinstance (value , dict ):
151+ for k , v in value .items ():
152+ if k [:1 ] == "@" :
153+ attribs [k [1 :]] = v
154+ elif k == "#text" :
155+ text = v
156+ elif k == "#tail" :
157+ tail = v
158+ elif isinstance (v , list ):
159+ for v2 in v :
160+ sublist .append (internal_to_elem ({k : v2 }, factory = factory ))
161+ else :
162+ sublist .append (internal_to_elem ({k : v }, factory = factory ))
163+ else :
164+ text = value
165+ e = factory (tag , attribs )
153166
154167 for sub in sublist :
155168 e .append (sub )
156- e .text = unicode (text )
157- e .tail = unicode (tail )
169+ e .text = sani_value (text )
170+ e .tail = sani_value (tail )
158171 return e
159172
160173
@@ -191,7 +204,7 @@ def xml2json(xmlstring, options, strip_ns=1, strip=1):
191204 return elem2json (elem , options , strip_ns = strip_ns , strip = strip )
192205
193206
194- def json2xml (json_data , factory = ET .Element ):
207+ def json2xml (json_data , options , factory = ET .Element ):
195208
196209 """Convert a JSON string into an XML string.
197210
@@ -202,8 +215,16 @@ def json2xml(json_data, factory=ET.Element):
202215 if not isinstance (json_data , dict ):
203216 json_data = json .loads (json_data )
204217
218+ if len (json_data .keys ()) > 1 :
219+ json_data = dict (root = json_data )
220+
205221 elem = internal_to_elem (json_data , factory )
206- return minidom .parseString (ET .tostring (elem )).toprettyxml (indent = '\t ' )
222+
223+ xml_str = ET .tostring (elem )
224+
225+ if options .pretty :
226+ xml_str = minidom .parseString (xml_str ).toprettyxml (indent = '\t ' )
227+ return xml_str
207228
208229
209230def main ():
@@ -219,7 +240,7 @@ def main():
219240 dest = "strip_text" , help = "Strip text for xml2json" )
220241 p .add_option (
221242 '--pretty' , action = "store_true" ,
222- dest = "pretty" , help = "Format JSON output so it is easier to read" )
243+ dest = "pretty" , help = "Format JSON/HTML output so it is easier to read" )
223244 p .add_option (
224245 '--strip_namespace' , action = "store_true" ,
225246 dest = "strip_ns" , help = "Strip namespace for xml2json" )
@@ -250,14 +271,14 @@ def main():
250271 if (options .type == "xml2json" ):
251272 out = xml2json (input , options , strip_ns , strip )
252273 else :
253- out = json2xml (input )
274+ out = json2xml (input , options )
254275
255276 if (options .out ):
256- file = open (options .out , 'w ' )
277+ file = open (options .out , 'wb ' )
257278 file .write (out )
258279 file .close ()
259280 else :
260- print (out )
281+ print (out . encode ( 'utf-8' ) )
261282
262283if __name__ == "__main__" :
263284 main ()
0 commit comments