Python and XML Help

Discussion in 'Python' started by ookrin, Apr 12, 2009.

  1. ookrin

    ookrin Guest

    I'm in the process of learning python and PyQt4. I had decided to make
    myself a simple app and soon discovered that I needed to crash into
    xml to use some of the data I was going to be getting off of the
    server.

    I picked up enough xml to use the sax parser to get the data out of
    the xml. I can get as far as printing it to the screen, but there is
    where I get stuck.... I can't seem to send the data to anywhere else,
    into another variable, to another function. The parser stops after the
    first line it finds.

    class offlineLoad():
    def loadXmlFile(self):
    print "Loading from File"
    xf = open('CharacterID.xml','r')
    xml = xmlHandler()
    saxparser = make_parser()
    print "parser created"
    saxparser.setContentHandler(xml)
    print "parser runn"
    try:
    saxparser.parse(xf)
    except:
    print "Error Reading xml"

    class xmlHandler(ContentHandler):
    def startElement(self, name, attrs):
    self.charList = []
    charName = []
    charID = []
    if name == "row":
    charName = attrs.get("name", "")
    charID = attrs.get("characterID", "")
    print charName, '\t', charID
    self.buildlist(self,charName,charID)
    #self.test()

    def test(self):
    print "TeST"
    def buildlist(self,charName,charID):
    print charName, '\t',charID

    so here... test will print, but buildlist makes the parser stop and
    print "Error reading XML" after the first row it finds. Appending
    charName and charID to another variable makes it stop as well. I'm
    confused at this point
    ookrin, Apr 12, 2009
    #1
    1. Advertising

  2. ookrin schrieb:
    > I'm in the process of learning python and PyQt4. I had decided to make
    > myself a simple app and soon discovered that I needed to crash into
    > xml to use some of the data I was going to be getting off of the
    > server.
    >
    > I picked up enough xml to use the sax parser to get the data out of
    > the xml. I can get as far as printing it to the screen, but there is
    > where I get stuck.... I can't seem to send the data to anywhere else,
    > into another variable, to another function. The parser stops after the
    > first line it finds.
    >
    > class offlineLoad():
    > def loadXmlFile(self):
    > print "Loading from File"
    > xf = open('CharacterID.xml','r')
    > xml = xmlHandler()
    > saxparser = make_parser()
    > print "parser created"
    > saxparser.setContentHandler(xml)
    > print "parser runn"
    > try:
    > saxparser.parse(xf)
    > except:
    > print "Error Reading xml"


    This is a very bad thing to do - there are only very few justified cases
    of catch-all for exceptions. This certainly isn't one, as it suppresses
    the real cause for what is happening.

    Which makes it harder for you & for us to diagnose the problem, because
    you don't show (and currently can't) the stacktrace to us.

    > class xmlHandler(ContentHandler):
    > def startElement(self, name, attrs):
    > self.charList = []


    If this shall gather some state over the coures of time, this is the
    wrong place to initialize it, as it will get overwritten with each element.

    > charName = []
    > charID = []


    There is no need to "prefill" variables. And it's confusing you do it
    with a different type than what you assign to them below.

    > if name == "row":
    > charName = attrs.get("name", "")
    > charID = attrs.get("characterID", "")
    > print charName, '\t', charID
    > self.buildlist(self,charName,charID)
    > #self.test()
    >
    > def test(self):
    > print "TeST"
    > def buildlist(self,charName,charID):
    > print charName, '\t',charID
    >
    > so here... test will print, but buildlist makes the parser stop and
    > print "Error reading XML" after the first row it finds. Appending
    > charName and charID to another variable makes it stop as well. I'm
    > confused at this point


    Please show us the stacktrace you suppress. Then help might be possible.

    Diez
    Diez B. Roggisch, Apr 12, 2009
    #2
    1. Advertising

  3. ookrin

    ookrin Guest

    On Apr 12, 12:51 am, "Diez B. Roggisch" <> wrote:
    > ookrin schrieb:
    >
    >
    >
    > > I'm in the process of learning python and PyQt4. I had decided to make
    > > myself a simple app and soon discovered that I needed to crash into
    > > xml to use some of the data I was going to be getting off of the
    > > server.

    >
    > > I picked up enough xml to use the sax parser to get the data out of
    > > the xml. I can get as far as printing it to the screen, but there is
    > > where I get stuck.... I can't seem to send the data to anywhere else,
    > > into another variable, to another function. The parser stops after the
    > > first line it finds.

    >
    > > class offlineLoad():
    > >     def loadXmlFile(self):
    > >         print "Loading from File"
    > >         xf = open('CharacterID.xml','r')
    > >         xml = xmlHandler()
    > >         saxparser = make_parser()
    > >         print "parser created"
    > >         saxparser.setContentHandler(xml)
    > >         print "parser runn"
    > >         try:
    > >             saxparser.parse(xf)
    > >         except:
    > >             print "Error Reading xml"

    >
    > This is a very bad thing to do - there are only very few justified cases
    > of catch-all for exceptions. This certainly isn't one, as it suppresses
    > the real cause for what is happening.
    >
    > Which makes it harder for you & for us to diagnose the problem, because
    > you don't show (and currently can't) the stacktrace to us.
    >
    > > class xmlHandler(ContentHandler):
    > >     def startElement(self, name, attrs):
    > >         self.charList = []

    >
    > If this shall gather some state over the coures of time, this is the
    > wrong place to initialize it, as it will get overwritten with each element.
    >
    > >         charName = []
    > >         charID = []

    >
    > There is no need to "prefill" variables. And it's confusing you do it
    > with a different type than what you assign to them below.
    >
    >
    >
    > >         if name == "row":
    > >             charName = attrs.get("name", "")
    > >             charID = attrs.get("characterID", "")
    > >             print charName, '\t', charID
    > >             self.buildlist(self,charName,charID)
    > >             #self.test()

    >
    > >     def test(self):
    > >         print "TeST"
    > >     def buildlist(self,charName,charID):
    > >         print charName, '\t',charID

    >
    > > so here... test will print, but buildlist makes the parser stop and
    > > print "Error reading XML" after the first row it finds.  Appending
    > > charName and charID to another variable makes it stop as well. I'm
    > > confused at this point

    >
    > Please show us the stacktrace you suppress. Then help might be possible.
    >
    > Diez


    Sorry for the delay, easter weekend:

    I know you don't need to prefill the variables with python, and they
    weren't there originally, I was just getting frustrated and trying
    various things to see if they worked. There is actually no stacktrace
    error. It will just print me the error message that I have when I try
    to send the variables outside of the if loop. (from the try - except
    statement.) I can still run click the button and it'll do it again.

    There are three rows that I have to get out of my xml all the same
    except with different values:
    < row name="CharName" charID="IDNumber" >

    So it prints out the first of the three lines and then just says
    "Error Reading XML" if I'm running the buildlist() and trying to send
    the variables out. As long as I don't try to do anything, it works
    fine.

    I can get these out and print them to the cmd line. But I want to
    collect these in a variable and send it back off to my gui in pyqt4 to
    list them. which is where i'm getting stuck.
    ookrin, Apr 15, 2009
    #3
  4. ookrin

    John Machin Guest

    On Apr 15, 12:29 pm, ookrin <> wrote:
    > On Apr 12, 12:51 am, "Diez B. Roggisch" <> wrote:
    >
    >
    >
    > > ookrin schrieb:

    >
    > > > I'm in the process of learning python and PyQt4. I had decided to make
    > > > myself a simple app and soon discovered that I needed to crash into
    > > > xml to use some of the data I was going to be getting off of the
    > > > server.

    >
    > > > I picked up enough xml to use the sax parser to get the data out of
    > > > the xml. I can get as far as printing it to the screen, but there is
    > > > where I get stuck.... I can't seem to send the data to anywhere else,
    > > > into another variable, to another function. The parser stops after the
    > > > first line it finds.

    >
    > > > class offlineLoad():
    > > >     def loadXmlFile(self):
    > > >         print "Loading from File"
    > > >         xf = open('CharacterID.xml','r')
    > > >         xml = xmlHandler()
    > > >         saxparser = make_parser()
    > > >         print "parser created"
    > > >         saxparser.setContentHandler(xml)
    > > >         print "parser runn"
    > > >         try:
    > > >             saxparser.parse(xf)
    > > >         except:
    > > >             print "Error Reading xml"

    >
    > > This is a very bad thing to do - there are only very few justified cases
    > > of catch-all for exceptions. This certainly isn't one, as it suppresses
    > > the real cause for what is happening.

    >
    > > Which makes it harder for you & for us to diagnose the problem, because
    > > you don't show (and currently can't) the stacktrace to us.

    >
    > > Please show us the stacktrace you suppress. Then help might be possible..

    >
    > There is actually no stacktrace
    > error. It will just print me the error message that I have when I try
    > to send the variables outside of the if loop. (from the try - except
    > statement.)


    That's because (as Diez has already pointed out, and told you to stop
    doing) you are *suppressing* the error message and stack trace that
    will help diagnose what is going wrong in your callback method.

    Instead of this:
    try:
    saxparser.parse(xf)
    except:
    print "Error Reading xml"
    do just this:
    saxparser.parse(xf)
    or if you really want to print something at the time, do this:
    try:
    saxparser.parse(xf)
    except:
    print "something meaningful"
    raise # throw the exception back for normal handling

    And just in case you're not taking the advice of Scott D. D. either,
    let me tell you again: use ElementTree, it's easier (no callbacks to
    complicate things) and the ratio of helpful-user-count to problem-
    likelihood is likely to be much higher than with sax.

    Cheers,
    John
    John Machin, Apr 15, 2009
    #4
  5. ookrin

    ookrin Guest

    On Apr 14, 8:15 pm, John Machin <> wrote:
    > On Apr 15, 12:29 pm, ookrin <> wrote:
    >
    >
    >
    > > On Apr 12, 12:51 am, "Diez B. Roggisch" <> wrote:

    >
    > > > ookrin schrieb:

    >
    > > > > I'm in the process of learning python and PyQt4. I had decided to make
    > > > > myself a simple app and soon discovered that I needed to crash into
    > > > > xml to use some of the data I was going to be getting off of the
    > > > > server.

    >
    > > > > I picked up enough xml to use the sax parser to get the data out of
    > > > > the xml. I can get as far as printing it to the screen, but there is
    > > > > where I get stuck.... I can't seem to send the data to anywhere else,
    > > > > into another variable, to another function. The parser stops after the
    > > > > first line it finds.

    >
    > > > > class offlineLoad():
    > > > >     def loadXmlFile(self):
    > > > >         print "Loading from File"
    > > > >         xf = open('CharacterID.xml','r')
    > > > >         xml = xmlHandler()
    > > > >         saxparser = make_parser()
    > > > >         print "parser created"
    > > > >         saxparser.setContentHandler(xml)
    > > > >         print "parser runn"
    > > > >         try:
    > > > >             saxparser.parse(xf)
    > > > >         except:
    > > > >             print "Error Reading xml"

    >
    > > > This is a very bad thing to do - there are only very few justified cases
    > > > of catch-all for exceptions. This certainly isn't one, as it suppresses
    > > > the real cause for what is happening.

    >
    > > > Which makes it harder for you & for us to diagnose the problem, because
    > > > you don't show (and currently can't) the stacktrace to us.

    >
    > > > Please show us the stacktrace you suppress. Then help might be possible.

    >
    > > There is actually no stacktrace
    > > error. It will just print me the error message that I have when I try
    > > to send the variables outside of the if loop. (from the try - except
    > > statement.)

    >
    > That's because (as Diez has already pointed out, and told you to stop
    > doing) you are *suppressing* the error message and stack trace that
    > will help diagnose what is going wrong in your callback method.
    >
    > Instead of this:
    >         try:
    >             saxparser.parse(xf)
    >         except:
    >             print "Error Reading xml"
    > do just this:
    >         saxparser.parse(xf)
    > or if you really want to print something at the time, do this:
    >         try:
    >             saxparser.parse(xf)
    >         except:
    >             print "something meaningful"
    >             raise # throw the exception back for normal handling
    >
    > And just in case you're not taking the advice of Scott D. D. either,
    > let me tell you again: use ElementTree, it's easier (no callbacks to
    > complicate things) and the ratio of helpful-user-count to problem-
    > likelihood is likely to be much higher than with sax.
    >
    > Cheers,
    > John


    Ok, I didn't know that was what I was actively doing by using the try-
    except. I am still learning. And it's not that I won't take the advice
    for using ElementTree, I just currently don't know anything about it.
    I just didn't want to say, "I have no idea what you're talking about!"
    to Scott cause I figured that would be rude, but I guess so is not
    saying anything, sorry. So I'll need to read up on it before I
    actually try to do anything with that approach.


    Seeing the errors - I changed the two classes to this:

    class offlineLoad():
    def loadXmlFile(self):
    print "Loading from File"
    xf = open('CharacterID.xml','r')
    xml = xmlHandler()
    saxparser = make_parser()
    saxparser.setContentHandler(xml)

    saxparser.parse(xf)

    class xmlHandler(ContentHandler):
    def __init__(self):
    print "---"
    self.idList = []

    def startElement(self, name, attrs):
    if name == "row":
    charName = attrs.get("name", "")
    charID = attrs.get("characterID", "")
    self.buildlist(charName,charID)

    def buildlist(self,charName,charID):
    temp = charName,charID
    self.idList.append(temp)
    print "----"
    print self.idList

    I know calling the self.idList = [] in the init probably isn't
    correct, but I couldn't think of any other way currently so it doesn't
    get rebuilt every time the definition gets called. This works and at
    least I think it puts everything into an array for me. I'm going to
    look at the element tree now, but I probably won't figure it out
    tonight.

    I'm using python 2.6

    Thanks so far,
    Andrew
    ookrin, Apr 15, 2009
    #5
  6. ookrin

    John Machin Guest

    On Apr 15, 2:25 pm, ookrin <> wrote:
    >
    >
    > Seeing the errors - I changed the two classes to this:
    >
    > class offlineLoad():
    >     def loadXmlFile(self):
    >         print "Loading from File"
    >         xf = open('CharacterID.xml','r')
    >         xml = xmlHandler()
    >         saxparser = make_parser()
    >         saxparser.setContentHandler(xml)
    >
    >         saxparser.parse(xf)
    >
    > class xmlHandler(ContentHandler):
    >     def __init__(self):
    >         print "---"
    >         self.idList = []
    >
    >     def startElement(self, name, attrs):
    >         if name == "row":
    >             charName = attrs.get("name", "")
    >             charID = attrs.get("characterID", "")
    >             self.buildlist(charName,charID)
    >
    >     def buildlist(self,charName,charID):
    >         temp = charName,charID
    >         self.idList.append(temp)
    >         print "----"
    >         print self.idList
    >
    > I know calling the self.idList = [] in the init probably isn't
    > correct, but I couldn't think of any other way currently so it doesn't
    > get rebuilt every time the definition gets called. This works and at
    > least I think it puts everything into an array for me.


    AFAICT having self.idList = [] in the __init__ method is the only
    sensible way to do what you want. Non-sensible ways: make it global to
    the module, or local to a class method

    You do have a problem with what you've got so far: you've done the
    heist, you've stuffed the loot into a sack, but where's the getaway
    car? IOW your loadXmlFile method needs a line like

    return xml.idList

    Wouldn't loadXMLFile be better as a stand-alone function? A class
    which is not a subclass of anything more meaty than object and has
    only one method (which isn't __init__) smells strongly of excess
    reliance on paradigms best left behind with the language from which
    you acquired them :)

    Cheers,
    John
    John Machin, Apr 15, 2009
    #6
  7. ookrin

    ookrin Guest

    On Apr 15, 9:43 am, Scott David Daniels <> wrote:
    > ookrin wrote:
    > > .... I am still learning. And it's not that I won't take the advice
    > > for using ElementTree, I just currently don't know anything about it.
    > > I just didn't want to say, "I have no idea what you're talking about!"
    > > to Scott cause I figured that would be rude, but I guess so is not
    > > saying anything, sorry. So I'll need to read up on it before I
    > > actually try to do anything with that approach.

    >
    > > Seeing the errors - I changed the two classes to this:
    > >   ... [some code that actually says a _little_ bit about his target] .....

    >
    > If you had done a better job of asking your question, you'd have found a
    > quick answer.  That is why everyone points people at smartquestions, not
    > to pick on them.
    >
    > Presuming you have an xml structure like:
    >      txt = '''<abc> something <def>
    >             <name name='steve' characterID='sid'> Some contents. </name>
    >             <name name='stevey' characterID='sidy'>Other contents.</name>
    >             </def></abc>'''
    >      import xml.etree.ElementTree as ET
    >      structure = ET.fromstring(xmls)
    >      for node in structure.findall('def/name'):
    >          print '%s: %s / %s: %s' % (node.tag, node.attrib['name'],
    >                                node.attrib['characterID'], node.text)
    >
    > or a file named 'my.xml' with the same contents:
    >      import xml.etree.ElementTree as ET
    >      structure = ET.parse('my.xml')
    >      for node in structure.findall('def/name'):
    >          print '%s: %s / %s: %s' % (node.tag, node.attrib['name'],
    >                                node.attrib['characterID'], node.text)
    >
    > --Scott David Daniels
    >


    Thanks very much for your patience with me and thanks for the help
    everyone.
    This is my end result:

    self.api = apiConnection(self.userID,self.apiKey)
    xmlData = self.api.returnXml()
    if(xmlData != "None"):
    struct = ET.fromstring(xmlData)
    self.charIDs =[]
    i=0
    for node in struct.findall('result/rowset/row'):
    char = node.attrib['name']
    id = node.attrib['characterID']
    temp = char, id
    #append them to the variable for later
    self.charIDs.append(temp)
    i+=1
    #Setup the select window and run it
    #selects which character I want
    self.selectCharUi = selectChar(self,self.charIDs)
    self.selectCharUi.selectWindow.exec_()

    #Get the name that was selected
    self.selectedCharName = self.selectCharUi.returnValue
    ()
    #Set the text widget with the name
    self.lE_charID.setText(self.selectedCharName)
    #enable the Ok button
    self.pbOk.setEnabled(True)

    It collects the names and IDs, sends them to a pyqt4 window with a
    list widget to list the names, a name gets selected and then I get the
    name that was selected. Though now that I think about it, maybe using
    a dictionary would be better. Elsewhere I gather up the userID, apiID,
    characterName and characterID and write it t a file. I hope it doesn't
    look too horrible.

    John - my programming experience was two semesters of c++ about 6
    years ago. Everything else I've learned from the internet. =/

    I'll try to make my questions better next time.

    Andrew
    ookrin, Apr 18, 2009
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page