I'm trying to write some XML as a byte string (to wit, a response from the Zillow API) to an XML file using the ElementTree.write
method. Here is an example of what I'm trying to do:
from xml.etree import ElementTree
content = b'<?xml version="1.0" encoding="utf-8"?><Comps:comps xsi:schemaLocation="http://www.zillow.com/static/xsd/Comps.xsd https://www.zillowstatic.com/vstatic/b20c067/static/xsd/Comps.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:Comps="http://www.zillow.com/static/xsd/Comps.xsd"><request><zpid>48789177</zpid><count>1</count></request><message><text>Request successfully processed</text><code>0</code></message><response><properties><principal><zpid>48789177</zpid><links><homedetails>https://www.zillow.com/homedetails/1614-E-Columbia-St-Seattle-WA-98122/48789177_zpid/</homedetails><graphsanddata>http://www.zillow.com/homedetails/1614-E-Columbia-St-Seattle-WA-98122/48789177_zpid/#charts-and-data</graphsanddata><mapthishome>http://www.zillow.com/homes/48789177_zpid/</mapthishome><comparables>http://www.zillow.com/homes/comps/48789177_zpid/</comparables></links><address><street>1614 E Columbia St</street><zipcode>98122</zipcode><city>SEATTLE</city><state>WA</state><latitude>47.609388</latitude><longitude>-122.310834</longitude></address><taxAssessmentYear>2016</taxAssessmentYear><taxAssessment>528000.0</taxAssessment><yearBuilt>1907</yearBuilt><lotSizeSqFt>2613</lotSizeSqFt><finishedSqFt>2430</finishedSqFt><bathrooms>2.0</bathrooms><bedrooms>4</bedrooms><zestimate><amount currency="USD">900186</amount><last-updated>04/13/2018</last-updated><oneWeekChange deprecated="true"></oneWeekChange><valueChange duration="30" currency="USD">112285</valueChange><valuationRange><low currency="USD">783162</low><high currency="USD">1053218</high></valuationRange><percentile>90</percentile></zestimate><localRealEstate><region name="Minor" id="271921" type="neighborhood"><zindexValue>588,800</zindexValue><links><overview>http://www.zillow.com/local-info/WA-Seattle/Minor/r_271921/</overview><forSaleByOwner>http://www.zillow.com/minor-seattle-wa/fsbo/</forSaleByOwner><forSale>http://www.zillow.com/minor-seattle-wa/</forSale></links></region></localRealEstate></principal><comparables><comp score="7.0"><zpid>89822967</zpid><links><homedetails>https://www.zillow.com/homedetails/1711-E-Fir-St-Seattle-WA-98122/89822967_zpid/</homedetails><graphsanddata>http://www.zillow.com/homedetails/1711-E-Fir-St-Seattle-WA-98122/89822967_zpid/#charts-and-data</graphsanddata><mapthishome>http://www.zillow.com/homes/89822967_zpid/</mapthishome><comparables>http://www.zillow.com/homes/comps/89822967_zpid/</comparables></links><address><street>1711 E Fir St</street><zipcode>98122</zipcode><city>SEATTLE</city><state>WA</state><latitude>47.602463</latitude><longitude>-122.309743</longitude></address><taxAssessmentYear>2016</taxAssessmentYear><taxAssessment>513000.0</taxAssessment><yearBuilt>2008</yearBuilt><lotSizeSqFt>1306</lotSizeSqFt><finishedSqFt>1490</finishedSqFt><bathrooms>3.0</bathrooms><bedrooms>3</bedrooms><lastSoldDate>03/15/2018</lastSoldDate><lastSoldPrice currency="USD">783000</lastSoldPrice><zestimate><amount currency="USD">791686</amount><last-updated>04/13/2018</last-updated><oneWeekChange deprecated="true"></oneWeekChange><valueChange duration="30" currency="USD">-8370</valueChange><valuationRange><low currency="USD">752102</low><high currency="USD">831270</high></valuationRange><percentile>87</percentile></zestimate><localRealEstate><region name="Minor" id="271921" type="neighborhood"><zindexValue>588,800</zindexValue><links><overview>http://www.zillow.com/local-info/WA-Seattle/Minor/r_271921/</overview><forSaleByOwner>http://www.zillow.com/minor-seattle-wa/fsbo/</forSaleByOwner><forSale>http://www.zillow.com/minor-seattle-wa/</forSale></links></region></localRealEstate></comp></comparables></properties></response></Comps:comps><!-- H:042 T:99ms S:2011 R:Sun Apr 15 09:01:05 PDT 2018 B:5.0.53029.1-hotfix_ADAT-2519.69881bc~hotfix-platform-for-2018-04-11.319b04e -->'
root = ElementTree.fromstring(content)
tree = ElementTree.ElementTree(root)
with open(f"comparables.xml", 'w+') as fp:
tree.write(fp)
However, if I run this (in iPython) I get a TypeError
:
In [3]: exec(open('zillow_api.py').read())
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-23b53830497c> in <module>()
----> 1 exec(open('zillow_api.py').read())
<string> in <module>()
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/xml/etree/ElementTree.py in write(self, file_or_filename, encoding, xml_declaration, default_namespace, method, short_empty_elements)
774 serialize = _serialize[method]
775 serialize(write, self._root, qnames, namespaces,
--> 776 short_empty_elements=short_empty_elements)
777
778 def write_c14n(self, file):
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/contextlib.py in __exit__(self, type, value, traceback)
86 if type is None:
87 try:
---> 88 next(self.gen)
89 except StopIteration:
90 return False
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/xml/etree/ElementTree.py in _get_writer(file_or_filename, encoding)
833 # destroyed
834 stack.callback(file.detach)
--> 835 yield file.write
836
837 def _namespaces(elem, default_namespace=None):
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/contextlib.py in __exit__(self, *exc_details)
378 # set-up context
379 fixed_ctx = exc_details[1].__context__
--> 380 raise exc_details[1]
381 except BaseException:
382 exc_details[1].__context__ = fixed_ctx
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/contextlib.py in __exit__(self, *exc_details)
363 cb = self._exit_callbacks.pop()
364 try:
--> 365 if cb(*exc_details):
366 suppressed_exc = True
367 pending_raise = False
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/contextlib.py in _exit_wrapper(exc_type, exc, tb)
312 """
313 def _exit_wrapper(exc_type, exc, tb):
--> 314 callback(*args, **kwds)
315 # We changed the signature, so using @wraps is not appropriate, but
316 # setting __wrapped__ may still help with introspection
TypeError: write() argument must be str, not bytes
Is what I'm passing in not a "file object opened for writing" as specified in the docs?
I've tried following the solution in ElementTree TypeError "write() argument must be str, not bytes" in Python3, but the tostring
method appears to no longer be contained in the xml.etree
module.
It turns out that the argument to tree.write()
should just be the name of the file you want to create:
tree.write("comparables.xml")
which creates comparables.xml
in my current directory.