[XML-SIG] question about behaviour of __poptag in xml.sax.writer.XmlWriter

Tim Hoffman timh at zute.net
Wed Nov 10 07:32:37 CET 2004


Hi

I have been using PyXML sax based XmlWriter (xml.sax.writer.XmlWriter) 
to produce valid xml.
One of my objectives was to ensure that even if a process was 
interrupted (though not catastrophically)
that the my close method could successfully close all tags and I end up 
with a wellformed XML file.

No given that XmLWriter  keeps track of  state I thought I could
just have a stack of try blocks that could close each tag rather than me 
tracking state as well, i.e.

       try:
            self._logger.endElement( u'items')
        except RuntimeError,e:
            pass
        try:
            self._logger.endElement( u'page')
        except RuntimeError,e:
            pass
       
        try:
            self._logger.endElement( u'pages')
        except RuntimeError,e:
            pass
        try:
            self._logger.endElement( u'template')
        except RuntimeError,e:
            pass
   

As there didn't seem to be any point in my keeping track of something 
that was already managed.
However __poptag

def __poptag(self, tag):
        state = self.__stack.pop()
        self._flowing, self.__lang, expected_tag, \
                       self._packing, self._dtdflowing = state
        if tag != expected_tag:
            raise RuntimeError, \
                  "expected </%s>, got </%s>" % (expected_tag, tag)
        self._prefix = self._prefix[:-self.indentation]

which manages the state doesn't restore the stack state after a 
RuntimeError is raised. So it is destructive even on error.

For what I am doing a simple fix that I used was to restore the stack in 
the event of a RuntimeError
as in

def __poptag(self, tag):
        state = self.__stack.pop()
        self._flowing, self.__lang, expected_tag, \
                       self._packing, self._dtdflowing = state
        if tag != expected_tag:
            self.__stack.append(state)  # restore state
            raise RuntimeError, \
                  "expected </%s>, got </%s>" % (expected_tag, tag)
        self._prefix = self._prefix[:-self.indentation]

It would seem to me, that not restoring the stack is probably wrong  
when a runtime error has been raised.
You may not want to bail out completely when this occurs and take 
corrective action, but  then you have  try and pick
apart the error string to work out what went wrong. you have no way of 
winding back and recovering and outputting the
correct tag because you have  none of the other details that are stored 
in the stack with the tag (state).

At least in my case this approach/fix works very well, but there may be 
other cases that
I haven't thought about where this approach breaks down.

What are other peoples thoughts on this ?  Is the existing behaviour 
mandated as part of the standard API ?

Rgds

Tim Hoffman


More information about the XML-SIG mailing list