def extract_message(response)
      # Extract the message element
      # e.g. /Envelope/Body/ReadPublicationResponse/PublicationMessage
      soap_ns = 'http://schemas.xmlsoap.org/soap/envelope/'
      message = response.doc.xpath('s:Envelope/s:Body', s: soap_ns).first.first_element_child.first_element_child

      return nil unless message

      id = message.element_children[0].text
      content = message.element_children[1].first_element_child
      topics = message.element_children[2..-1].map {|e| e.text}

      # Retain any ancestor namespaces in case they are applicable for the element
      # and/or children. This is because content.to_xml does not output ancestor
      # namespaces.
      # There may be unnecessary namespaces carried across (e.g. ISBM, SOAP), but we
      # can't tell if the content uses them without parsing the content itself.
      content.namespaces.each do |key, value|
        # Don't replace default namespace if it already exists
        next if key == 'xmlns' && content['xmlns']
        content[key] = value
      end

      # Wrap content in a separate Nokogiri document. This allows the ability to
      # validate the content against a schema.
      doc = Nokogiri::XML(content.to_xml)

      IsbmAdaptor::Message.new(id, doc, topics)
    end
def extract_message(response)
      # Extract the message element
      # e.g. /Envelope/Body/ReadPublicationResponse/PublicationMessage
      soap_ns = 'http://schemas.xmlsoap.org/soap/envelope/'
      message = response.doc.xpath('s:Envelope/s:Body', s: soap_ns).first.first_element_child.first_element_child

      return nil unless message

      id = message.element_children[0].text
      content = message.element_children[1].first_element_child
      topics = message.element_children[2..-1].map {|e| e.text}

      # Retain any ancestor namespaces in case they are applicable for the element
      # and/or children. This is because content.to_xml does not output ancestor
      # namespaces.
      # There may be unnecessary namespaces carried across (e.g. ISBM, SOAP), but we
      # can't tell if the content uses them without parsing the content itself.
      content.namespaces.each do |key, value|
        # Don't replace default namespace if it already exists
        next if key == 'xmlns' && content['xmlns']
        content[key] = value
      end

      # Wrap content in a separate Nokogiri document. This allows the ability to
      # validate the content against a schema.
      doc = Nokogiri::XML(content.to_xml)

      IsbmAdaptor::Message.new(id, doc, topics)
    end
Creates an IsbmAdaptor::Message from a ISBM response.

 @param response [Savon::Response] the ISBM response
 @return [IsbmAdaptor::Message] the extracted message