TypeError coercing to Unicode with field read from XML file

R

Randall Parker

Running Python 2.4.2 on Windows in SPE. I have a very small XML file
(see below) that is in UTF-8 and saved by Windows Notepad as such. I'm
reading it with minidom.

My problem is that once I parse the file with minidom and a field from
it to another variable as shown with this line:
IPAddr = self.SocketSettingsObj.IPAddress

I get this error:

File "<string>", line 1, in connect
TypeError: coercing to Unicode: need string or buffer, instance found

This is the section of code that reads the XML file:

ConfigDom = parse(TestSettingsStore.ConfigFileName)
#ConfigDom
TSSElList =
ConfigDom.getElementsByTagName("TargetSocketSettings")
NumTargSocks = len(TSSElList)
if NumTargSocks > 0:
TargetIPAddrList =
TSSElList[0].getElementsByTagName("TargetIPAddr")
TargetIPPortList =
TSSElList[0].getElementsByTagName("TargetIPPort")
AddrListLen = len(TargetIPAddrList)
PortListLen = len(TargetIPPortList)
if AddrListLen > 0 and PortListLen > 0:
if TargetIPAddrList[0] <> "" and TargetIPPortList[0] <>
0:
StillNeedSettings = False

TestSettingsStore.SettingsDictionary['TargetIPAddr'] =
TargetIPAddrList[0]

TestSettingsStore.SettingsDictionary['TargetIPPort'] =
TargetIPPortList[0]

This I saved as Unicode from Notepad with encoding UTF-16:
<?xml version="1.0" encoding="UTF-16" ?>
<TargetSocketSettings>
<TargetIPAddr>127.0.0.1</TargetIPAddr>
<TargetIPPort>43210</TargetIPPort>
</TargetSocketSettings>

this I saved as UTF-8 from Notepad with encoding UTF-8:
<?xml version="1.0" encoding="UTF-16" ?>
<TargetSocketSettings>
<TargetIPAddr>127.0.0.1</TargetIPAddr>
<TargetIPPort>43210</TargetIPPort>
</TargetSocketSettings>

Both formats create the same error.

I'm probably doing something dumb as I've never done XML in Python
before. Any ideas what?
 
B

Ben Cartwright

Randall said:
My problem is that once I parse the file with minidom and a field from
it to another variable as shown with this line:
IPAddr = self.SocketSettingsObj.IPAddress

I get this error: [...]
if TargetIPAddrList[0] <> "" and TargetIPPortList[0] <>
0:
StillNeedSettings = False

TestSettingsStore.SettingsDictionary['TargetIPAddr'] =
TargetIPAddrList[0]

TestSettingsStore.SettingsDictionary['TargetIPPort'] =
TargetIPPortList[0]


TargetIPAddrList[0] and TargetIPPortList[0] are *not* a string and an
int, respectively. They're both DOM elements. If you want an int, you
have to explicitly cast the variable as an int. Type matters in
Python:
False

Back to your code: try a couple debugging print statements to see
exactly what your variables are. The built-in type() function should
help.

To fix the problem, you need to dig a little deeper in the DOM, e.g.:

addr = TargetIPAddrList[0].firstChild.nodeValue
try:
port = int(TargetIPPortList[0].firstChild.nodeValue)
except ValueError: # safely handle invalid strings for int
port = 0
if addr and port:
StillNeedSettings = False
TestSettingsStore.SettingsDictionary['TargetIPAddr'] = addr
TestSettingsStore.SettingsDictionary['TargetIPPort'] = port

--Ben
 
F

Fredrik Lundh

Randall said:
I'm probably doing something dumb as I've never done XML in Python
before. Any ideas what?

using minidom ? ;-)

if you're not wedded to minidom, there are alternatives that are easier
to use for things like this. here's an ElementTree version of your code:

ConfigTree = ET.parse(TestSettingsStore.ConfigFileName)
# ConfigTree represents the TargetSocketSettings root element

TargetIPAddr = tree.findtext("TargetIPAddr")
TargetIPPort = tree.findtext("TargetIPPort")

if TargetIPAddr and TargetIPPort:
StillNeedSettings = False
TestSettingsStore.SettingsDictionary["TargetIPAddr"] = TargetIPAddr
TestSettingsStore.SettingsDictionary["TargetIPPort"] = TargetIPPort

where ET is set by something like:

try:
import xml.etree.ElementTree as ET # Python 2.5
except ImportError:
# http://effbot.org/zone/element-index.htm
import elementtree.ElementTree as ET

if you don't want to ship the entire ElementTree library with your app,
you can just add the ElementTree.py module somewhere, and do e.g.

import myapp.utils.ElementTree as ET

:::

if you plan to grab more stuff from XML files, you might wish to apply the
DRY principle (google it!), and use a little helper to copy the variables from
the XML file to your dictionary:

def getconfig(settings, elem, keys):
d = {}
for key in keys:
value = elem.findtext(key)
if not value:
return False
d[key] = value
# only update the settings dict if all keys were present
settings.update(d)
return True

if getconfig(
TestSettingsStore.SettingsDictionary,
ConfigTree,
("TargetIPAddr", "TargetIPPortX")):
StillNeedSettings = False

</F>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top