new_contents: import os
  import urllib, urllib2
  from functools32 import lru_cache
  import xml.etree.ElementTree as ET
  
  # THIS FILE IS NOT UNDER VERSION CONTROL
  # For more information see http://dev.elsevier.com/
  api_key_file = os.path.dirname(os.path.realpath(__file__)) + '/' + \
                 'elsevier_api_key'
  
  # Read the API key
  try:
      with open(api_key_file, 'rt') as fh:
          api_key = fh.read().strip()
  except IOError:
      print 'Elsevier API key could not be found.'
      print api_key_file
      api_key = None
  
  elsevier_ns = {'dc': 'http://purl.org/dc/elements/1.1/',
                 'article': 'http://www.elsevier.com/xml/svapi/article/dtd',
                 'ja': 'http://www.elsevier.com/xml/ja/dtd',
                 'xocs': 'http://www.elsevier.com/xml/xocs/dtd',
                 'common': 'http://www.elsevier.com/xml/common/dtd'}
  
  @lru_cache(maxsize=100)
  def download_article(doi):
      """Download an article in XML format from Elsevier."""
      url = 'http://api.elsevier.com/content/article/%s' % doi
      if api_key is None:
          print 'Missing API key, could not download article.'
          return None
      params = {'APIKey': api_key, 'httpAccept': 'text/xml'}
      res = urllib2.urlopen(url, data=urllib.urlencode(params))
      xml = res.read()
      return xml
  
  def get_abstract(doi):
      """Get the abstract of an article from Elsevier."""
      xml = download_article(doi)
      et = ET.fromstring(xml)
      coredata = et.find('article:coredata', elsevier_ns)
      abstract = coredata.find('dc:description', elsevier_ns)
      abs_text = abstract.text
      return abs_text
  
  def get_article(doi, output='txt'):
      """Get the full body of an article from Elsevier. There are two output
      modes: 'txt' strips all xml tags and joins the pieces of text in the main
      text, while 'xml' simply takes the tag containing the body of the article
      and returns it as is . In the latter case, downstream code needs to be
      able to interpret Elsever's XML format. """
      xml = download_article(doi)
      et = ET.fromstring(xml)
      full_text = et.find('article:originalText', elsevier_ns)
      if full_text is None:
          print 'Could not find full text for %s.' % doi
          return None
      main_body = full_text.find('xocs:doc/xocs:serial-item/ja:article/ja:body',
                                 elsevier_ns)
      if output == 'xml':
          return main_body
      elif output == 'txt':
          sections = main_body.findall('common:sections/common:section', elsevier_ns)
          full_txt = ''
          for s in sections:
              pars = s.findall('common:para', elsevier_ns)
              for p in pars:
                  # Get the initial string inside the paragraph
                  if p.text is not None:
                      full_txt += p.text
                  # When there are tags inside the paragraph (for instance
                  # references), we need to take those child elements one by one
                  # and get the corresponding tail strings and join these. 
                  full_txt += ''.join([c.tail if c.tail is not None 
                                       else '' for c in p.getchildren()])
                  full_txt += '\n'
      else:
          print 'Unknown output format %s.' % output
          return None
      return full_txt
  
subject: Implement client to download articles from Elsevier