Is NSXMLParser really a streaming parser?

  • I am working on a project that requires parsing of XML data that
    comes from a socket stream.  I want to feed an NSXMLParser object xml
    data from my socket connection 1 byte at a time.  Is this possible?

    So far I have been receiving the socket stream data from a
    NSFileHandle.  I subscribe an object to receive the
    NSFileHandleReadCompletionNotification and get the NSData item from
    the notification.  Then I initialize the XMLParser with the NSData.
    Will the NSXMLParser be able to parse correctly if I give it xml data
    1 byte at a time?  This might mean that the  data I feed the
    XMLParser is cut in the middle of a tag or the contents.

    - (void)xmlStream:(NSNotification *)notification
    {
    NSData *messageData = [[notification userInfo]
    objectForKey:NSFileHandleNotificationDataItem];

        if ( [messageData length] == 0 ) {
            [xmlFileHandle readInBackgroundAndNotify];
            return;
        }

        if(!xmlController)
        {
            xmlController = [[XMLcontroller alloc] init];
        }

        [xmlController initXMLparser: messageData];
        [xmlController startParse];

        [xmlFileHandle readInBackgroundAndNotify];
    }

    Inside my xml controller object

    - (void) initXMLparser:(NSData *) xmlData
    {
    if(!parser)
    {
      parser = [[NSXMLParser alloc] initWithData: xmlData];
      [parser setDelegate: self];
      [parser setShouldResolveExternalEntities:YES];
    }

    [parser initWithData: xmlData];

    nc = [NSNotificationCenter defaultCenter];
    }

    - (void) startParse
    {
    [parser parse];
    }

    Any insights will be greatly appreciated.

    Chris Woodruff

    Jet Propulsion Laboratory
    M/S: 138-206
    4800 Oak Grove Dr.
    Pasadena, CA 91109
    818-354-2412
  • Hi Christopher,

    I think you're misunderstanding the use of the word "streaming" in the
    API description. NSXMLParser is a "streaming" parser in the sense that
    it produces a stream of events w.r.t. the XML document rather than a
    fully-cooked document/DOM tree.

    We have an enhancement request for NSXMLParser to accept an
    NSInputStream, which would do the kind of thing you're trying to do
    here. Unfortunately as of Leopard there is still no "take bytes in
    chunks and parse them" API on NSXMLParser.

    BTW, your code below is re-initializing the same parser instance over
    and over again - you should only be sending any "-init*" method to an
    object instance once. The behavior you'd be getting here is completely
    undefined.

    .chris

    --
    Chris Parker
    Cocoa Frameworks
    Apple Inc.

    On Nov 1, 2007, at 11:29 AM, Christopher Woodruff wrote:

    > I am working on a project that requires parsing of XML data that
    > comes from a socket stream.  I want to feed an NSXMLParser object
    > xml data from my socket connection 1 byte at a time.  Is this
    > possible?
    >
    > So far I have been receiving the socket stream data from a
    > NSFileHandle.  I subscribe an object to receive the
    > NSFileHandleReadCompletionNotification and get the NSData item from
    > the notification.  Then I initialize the XMLParser with the NSData.
    > Will the NSXMLParser be able to parse correctly if I give it xml
    > data 1 byte at a time?  This might mean that the  data I feed the
    > XMLParser is cut in the middle of a tag or the contents.
    >
    > - (void)xmlStream:(NSNotification *)notification
    > {
    > NSData *messageData = [[notification userInfo]
    > objectForKey:NSFileHandleNotificationDataItem];
    >
    > if ( [messageData length] == 0 ) {
    > [xmlFileHandle readInBackgroundAndNotify];
    > return;
    > }
    >
    > if(!xmlController)
    > {
    > xmlController = [[XMLcontroller alloc] init];
    > }
    >
    > [xmlController initXMLparser: messageData];
    > [xmlController startParse];
    >
    > [xmlFileHandle readInBackgroundAndNotify];
    > }
    >
    >
    > Inside my xml controller object
    >
    > - (void) initXMLparser:(NSData *) xmlData
    > {
    > if(!parser)
    > {
    > parser = [[NSXMLParser alloc] initWithData: xmlData];
    > [parser setDelegate: self];
    > [parser setShouldResolveExternalEntities:YES];
    > }
    >
    > [parser initWithData: xmlData];
    >
    > nc = [NSNotificationCenter defaultCenter];
    > }
    >
    > - (void) startParse
    > {
    > [parser parse];
    > }
    >
    > Any insights will be greatly appreciated.
    >
    > Chris Woodruff
    >
    > Jet Propulsion Laboratory
    > M/S: 138-206
    > 4800 Oak Grove Dr.
    > Pasadena, CA 91109
    > 818-354-2412
  • Thanks for the help.  Do you know of any third party xml parsers that
    might work in this fashion?  I've found a number of people that talk
    about expat with the objective-c wrapper.  Is this a possible
    solution, or is it limited in the same way?

    Chris Woodruff

    Jet Propulsion Laboratory
    M/S: 138-206
    4800 Oak Grove Dr.
    Pasadena, CA 91109
    818-354-2412

    On Nov 1, 2007, at 1:28 PM, Chris Parker wrote:

    > Hi Christopher,
    >
    > I think you're misunderstanding the use of the word "streaming" in
    > the API description. NSXMLParser is a "streaming" parser in the
    > sense that it produces a stream of events w.r.t. the XML document
    > rather than a fully-cooked document/DOM tree.
    >
    > We have an enhancement request for NSXMLParser to accept an
    > NSInputStream, which would do the kind of thing you're trying to do
    > here. Unfortunately as of Leopard there is still no "take bytes in
    > chunks and parse them" API on NSXMLParser.
    >
    > BTW, your code below is re-initializing the same parser instance
    > over and over again - you should only be sending any "-init*"
    > method to an object instance once. The behavior you'd be getting
    > here is completely undefined.
    >
    > .chris
    >
    > --
    > Chris Parker
    > Cocoa Frameworks
    > Apple Inc.
    >
    > On Nov 1, 2007, at 11:29 AM, Christopher Woodruff wrote:
    >
    >> I am working on a project that requires parsing of XML data that
    >> comes from a socket stream.  I want to feed an NSXMLParser object
    >> xml data from my socket connection 1 byte at a time.  Is this
    >> possible?
    >>
    >> So far I have been receiving the socket stream data from a
    >> NSFileHandle.  I subscribe an object to receive the
    >> NSFileHandleReadCompletionNotification and get the NSData item
    >> from the notification.  Then I initialize the XMLParser with the
    >> NSData.  Will the NSXMLParser be able to parse correctly if I give
    >> it xml data 1 byte at a time?  This might mean that the  data I
    >> feed the XMLParser is cut in the middle of a tag or the contents.
    >>
    >> - (void)xmlStream:(NSNotification *)notification
    >> {
    >> NSData *messageData = [[notification userInfo]
    >> objectForKey:NSFileHandleNotificationDataItem];
    >>
    >> if ( [messageData length] == 0 ) {
    >> [xmlFileHandle readInBackgroundAndNotify];
    >> return;
    >> }
    >>
    >> if(!xmlController)
    >> {
    >> xmlController = [[XMLcontroller alloc] init];
    >> }
    >>
    >> [xmlController initXMLparser: messageData];
    >> [xmlController startParse];
    >>
    >> [xmlFileHandle readInBackgroundAndNotify];
    >> }
    >>
    >>
    >> Inside my xml controller object
    >>
    >> - (void) initXMLparser:(NSData *) xmlData
    >> {
    >> if(!parser)
    >> {
    >> parser = [[NSXMLParser alloc] initWithData: xmlData];
    >> [parser setDelegate: self];
    >> [parser setShouldResolveExternalEntities:YES];
    >> }
    >>
    >> [parser initWithData: xmlData];
    >>
    >> nc = [NSNotificationCenter defaultCenter];
    >> }
    >>
    >> - (void) startParse
    >> {
    >> [parser parse];
    >> }
    >>
    >> Any insights will be greatly appreciated.
    >>
    >> Chris Woodruff
    >>
    >> Jet Propulsion Laboratory
    >> M/S: 138-206
    >> 4800 Oak Grove Dr.
    >> Pasadena, CA 91109
    >> 818-354-2412
    >
  • Hi Chris, I'm not 100% sure what you're trying to do, but when you
    mention XML and sockets, the first thing that pops to my mind is BEEP
    (http://www.beepcore.org/).  From its FAQ:

    "...BEEP is a framework for building application protocols. It's not a
    replacement for any existing protocol. Instead, it's kind of a "best
    hits" album of the tricks used by experienced application protocol
    designers since the early 80's.

    If you attend many working groups in the IETF, you'll notice that
    whenever they get together to define a new application protocol, most of
    the time is spent arguing the same issues, over and over and over again.
    Although the goals and needs of application protocols may differ quite a
    bit, there's a lot of application protocols that pretty much have the
    same set of design requirements.

    This is what BEEP is for. Someone sat down, did an inventory of what
    techniques got used a lot, what the tradeoffs were, made some choices,
    and then integrated it all together.

    Although some might make passionate arguments for a particular approach,
    at the end of the day you just have to pick something and make it work.
    Hopefully with BEEP, the people designing application protocols will
    start arguing about other things. If we're lucky, those things will be a
    lot more important.

    ..."

    Basically, it is an XML based application layer protocol that allows
    formation of channels on the same socket.  You can decide what each
    channel means, allowing you to multiplex your data over the transport
    protocol.  The multiplexing part is designed to allow synchronized data
    transfer, so you can put video on one channel and audio on another, or
    multiple synchronized video channels.  IIRC, one of the libraries has
    automatic compression to reduce network bandwidth consumption.  It is
    also an RFC, so if standards compliance is important to you, you've got
    that covered.

    Good luck,
    Cem Karan

    ------------------------------

    Message: 5
    Date: Thu, 1 Nov 2007 13:49:22 -0700
    From: Christopher Woodruff <Christopher.S.Woodruff...>
    Subject: Re: Is NSXMLParser really a streaming parser?
    To: Chris Parker <ctp...>
    Cc: <cocoa-dev...>
    Message-ID: <33EAFFC2-14F4-4335-ADBF-592C29695EF5...>
    Content-Type: text/plain;    charset=US-ASCII;    delsp=yes;
    format=flowed

    Thanks for the help.  Do you know of any third party xml parsers that
    might work in this fashion?  I've found a number of people that talk
    about expat with the objective-c wrapper.  Is this a possible solution,
    or is it limited in the same way?

    Chris Woodruff

    Jet Propulsion Laboratory
    M/S: 138-206
    4800 Oak Grove Dr.
    Pasadena, CA 91109
    818-354-2412

    On Nov 1, 2007, at 1:28 PM, Chris Parker wrote:

    > Hi Christopher,
    >
    > I think you're misunderstanding the use of the word "streaming" in the

    > API description. NSXMLParser is a "streaming" parser in the sense that

    > it produces a stream of events w.r.t. the XML document rather than a
    > fully-cooked document/DOM tree.
    >
    > We have an enhancement request for NSXMLParser to accept an
    > NSInputStream, which would do the kind of thing you're trying to do
    > here. Unfortunately as of Leopard there is still no "take bytes in
    > chunks and parse them" API on NSXMLParser.
    >
    > BTW, your code below is re-initializing the same parser instance over
    > and over again - you should only be sending any "-init*"
    > method to an object instance once. The behavior you'd be getting here
    > is completely undefined.
    >
    > .chris
    >
    > --
    > Chris Parker
    > Cocoa Frameworks
    > Apple Inc.
    >
    > On Nov 1, 2007, at 11:29 AM, Christopher Woodruff wrote:
    >
    >> I am working on a project that requires parsing of XML data that
    >> comes from a socket stream.  I want to feed an NSXMLParser object xml

    >> data from my socket connection 1 byte at a time.  Is this possible?
    >>
    >> So far I have been receiving the socket stream data from a
    >> NSFileHandle.  I subscribe an object to receive the
    >> NSFileHandleReadCompletionNotification and get the NSData item from
    >> the notification.  Then I initialize the XMLParser with the NSData.
    >> Will the NSXMLParser be able to parse correctly if I give it xml data

    >> 1 byte at a time?  This might mean that the  data I feed the
    >> XMLParser is cut in the middle of a tag or the contents.
    >>
    >> - (void)xmlStream:(NSNotification *)notification {
    >> NSData *messageData = [[notification userInfo]
    >> objectForKey:NSFileHandleNotificationDataItem];
    >>
    >> if ( [messageData length] == 0 ) {
    >> [xmlFileHandle readInBackgroundAndNotify];
    >> return;
    >> }
    >>
    >> if(!xmlController)
    >> {
    >> xmlController = [[XMLcontroller alloc] init];
    >> }
    >>
    >> [xmlController initXMLparser: messageData];
    >> [xmlController startParse];
    >>
    >> [xmlFileHandle readInBackgroundAndNotify]; }
    >>
    >>
    >> Inside my xml controller object
    >>
    >> - (void) initXMLparser:(NSData *) xmlData
    >> {
    >> if(!parser)
    >> {
    >> parser = [[NSXMLParser alloc] initWithData: xmlData];
    >> [parser setDelegate: self];
    >> [parser setShouldResolveExternalEntities:YES];
    >> }
    >>
    >> [parser initWithData: xmlData];
    >>
    >> nc = [NSNotificationCenter defaultCenter];
    >> }
    >>
    >> - (void) startParse
    >> {
    >> [parser parse];
    >> }
    >>
    >> Any insights will be greatly appreciated.
    >>
    >> Chris Woodruff
    >>
    >> Jet Propulsion Laboratory
    >> M/S: 138-206
    >> 4800 Oak Grove Dr.
    >> Pasadena, CA 91109
    >> 818-354-2412
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today