Expat current line/column number

N

Nicolas Fleury

Hi,
Is it possible with xml.parsers.expat to get the current line and
column number if an exception is raised by one of the callbacks (not
necessary an xml.parsers.expat.ExpatError)?

Thx and Regards,

Nicolas Fleury
 
A

Alan Kennedy

[Nicolas Fleury]
Is it possible with xml.parsers.expat to get the current line and
column number if an exception is raised by one of the callbacks (not
necessary an xml.parsers.expat.ExpatError)?

Is this the type of thing you mean?

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
import StringIO
import xml.sax
import xml.sax.xmlreader
import xml.sax.expatreader

class ApplicationException(Exception): pass

class HandlerThatRaisesExceptions(xml.sax.ContentHandler):

def endDocument(self):
raise ApplicationException('End-of-document Exception')

inputfile = StringIO.StringIO("""
<well>
<formed/>
</well>
""")

parser = xml.sax.make_parser('xml.sax.expatreader')
parser.setContentHandler(HandlerThatRaisesExceptions())
try:
parser.parse(inputfile)
except ApplicationException, ax:
print "App exception:%s: Line %d, Column %d" % (str(ax), \
parser.getLineNumber(), parser.getColumnNumber())

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
N

Nicolas Fleury

Alan said:
[Nicolas Fleury]
Is it possible with xml.parsers.expat to get the current line and
column number if an exception is raised by one of the callbacks (not
necessary an xml.parsers.expat.ExpatError)?


Is this the type of thing you mean?

This is exactly what I mean. Unfortunately, I've use the parser in
xml.parsers.expat and not xml.sax, and it seems that parser only
provides line and column numbers for its own exceptions. I will
investigate to convert to xml.sax. Thx for your help.

Regards,

Nicolas Fleury
 
N

Nicolas Fleury

Alan said:
[Nicolas Fleury]
Is it possible with xml.parsers.expat to get the current line and
column number if an exception is raised by one of the callbacks (not
necessary an xml.parsers.expat.ExpatError)?


Is this the type of thing you mean?

It doesn't work on my side or I'm missing something.

Here's your example slightly modified:

import StringIO
import xml.sax
import xml.sax.xmlreader
import xml.sax.expatreader

class ApplicationException(Exception): pass

class HandlerThatRaisesExceptions(xml.sax.ContentHandler):
def startElement(self, name, attrs):
if name == 'hello':
raise Exception('wrong')

inputfile = StringIO.StringIO("""
<well>
<formed/>
<xyz>
<hello/>
</xyz>
</well>
""")

parser = xml.sax.make_parser(['xml.sax.expatreader'])
parser.setContentHandler(HandlerThatRaisesExceptions())
try:
parser.parse(inputfile)
except Exception, ax:
print "App exception:%s: Line %d, Column %d" % (str(ax), \
parser.getLineNumber(), parser.getColumnNumber())


My output is:
App exception:wrong: Line 15, Column 0

I don't understand these numbers; there's not even 15 lines... Anyone
have an idea what I'm missing?

Thx and Regards,

Nicolas Fleury
 
A

Alan Kennedy

[Nicolas Fleury]
[Alan Kennedy]
[Code elided]

[Nicolas Fleury]
This is exactly what I mean. Unfortunately, I've use the parser in
xml.parsers.expat and not xml.sax, and it seems that parser only
provides line and column numbers for its own exceptions.

Ah. I think this solves the problem.

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
import StringIO
import xml.parsers.expat

class AppExc(Exception):

def __init__(self, elem, line, col):
self.elem, self.line, self.col = elem, line, col

def __str__(self):
return "Yucky %s :p Line %d, Col %d" % \
(self.elem, self.line, self.col)

def endElementHandler(elemname):
global parser
if elemname == 'bluveny':
raise AppExc(elemname, parser.ErrorLineNumber, \
parser.ErrorColumnNumber)

inputfile = StringIO.StringIO("""
<cheeses>
<limburger/>
<stilton/>
<gruyere/>
<jarlsburg/>
<dorset><bluveny/></dorset>
</cheeses>
""")

parser = xml.parsers.expat.ParserCreate()
parser.EndElementHandler = endElementHandler
try:
parser.ParseFile(inputfile)
except AppExc, ax:
print str(ax)
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Not quite as clean though, because of the requirement to declare
'parser' as a global. To get rid of the 'global' declaration, you
could always wrap up your handlers in a class, and set the parser as
an attribute of each instance.
 
N

Nicolas Fleury

Nicolas said:
Alan said:
[Nicolas Fleury]
Is it possible with xml.parsers.expat to get the current line and
column number if an exception is raised by one of the callbacks (not
necessary an xml.parsers.expat.ExpatError)?



Is this the type of thing you mean?


It doesn't work on my side or I'm missing something.

ok the solution is get the line and column number during parsing.
Here's a working example:

import StringIO
import xml.sax
import xml.sax.xmlreader
import xml.sax.expatreader

class ApplicationException(Exception): pass

class HandlerThatRaisesExceptions(xml.sax.ContentHandler):
def startElement(self, name, attrs):
if name == 'hello':
raise Exception('wrong at line ' +
str(parser.getLineNumber()) +
' and column ' + str(parser.getColumnNumber()))

inputfile = StringIO.StringIO("""
<well>
<formed/>
<xyz>
<hello/>
</xyz>
</well>
""")

parser = xml.sax.make_parser(['xml.sax.expatreader'])
parser.setContentHandler(HandlerThatRaisesExceptions())
parser.parse(inputfile)
 
N

Nicolas Fleury

Alan said:
[Nicolas Fleury]
This is exactly what I mean. Unfortunately, I've use the parser in
xml.parsers.expat and not xml.sax, and it seems that parser only
provides line and column numbers for its own exceptions.


Ah. I think this solves the problem.
(...)

Not quite as clean though, because of the requirement to declare
'parser' as a global. To get rid of the 'global' declaration, you
could always wrap up your handlers in a class, and set the parser as
an attribute of each instance.

Yes, it seems expat reset line and column numbers when leaving parsing
function. It is a little bit limiting, since like you said, the handler
must know the parser. In my case it's not that bad; since I only use
startElement and endElement, I will only need to add try blocks in these
two functions. Thx for your help.

Regards,

Nicolas Fleury
 

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

Forum statistics

Threads
474,167
Messages
2,570,910
Members
47,453
Latest member
MadelinePh

Latest Threads

Top