Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closing the event stream - detect end_document #110

Open
joeppeeters opened this issue Jul 11, 2022 · 0 comments
Open

Closing the event stream - detect end_document #110

joeppeeters opened this issue Jul 11, 2022 · 0 comments

Comments

@joeppeeters
Copy link

joeppeeters commented Jul 11, 2022

I'm trying to use Saxy to convert a streaming XML resource into e SAX event-stream. I'm having a hard time though with closing the document. I wonder if Saxy could help out here.

stream = ["<root>", "<elem>", "text", "</elem>", "</root>"]

{:ok, partial} = Saxy.Partial.new(MyEventHandler, [])

Stream.transform(stream, partial, fn xml_chunk, partial ->
  case Saxy.Partial.parse(partial, xml_chunk) do
    {:cont, partial} ->
      # emit events
      {Enum.reverse(partial.state.user_data), reset_user_data(partial)}
  end
end)
|> Enum.to_list()

# returns something like
[:start_document, :start_element, :start_element, :characters, :end_element,
 :end_element]

As you can see the last emitted event is :end_element (and not :end_document). The stream stops after "</root>", so parsing stops.

My questions:

  • Should Saxy detect the end of the document here?
  • In which situations would Saxy.Partial.parse return a {:halt, _} response?

For now, my alternative solution would be to detect if the stack is empty, and terminate the stream based on that.

Stream.transform(stream, partial, fn
      _, nil ->
        # parsing has been stopped, halt the stream
        {:halt, []}

      xml_chunk, partial ->
        case Saxy.Partial.parse(partial, xml_chunk) do
          {:cont, %{state: %{stack: []}} = partial} ->
            # the stack is empty, so we're done parsing the document: terminate the partial
            {:ok, end_document} = Saxy.Partial.terminate(partial)
            {Enum.reverse(end_document), nil}

          {:cont, partial} ->
            {Enum.reverse(partial.state.user_state), reset_user_state(partial)}

          {:error, error} ->
            raise error
        end
    end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant