code: def extract_file(root, xmlpath):
      # Workaround an incompatibility between sphinx's XML generation and ElementTree's XML parsing.
      #
      # The issue is references contain xml tags with colons in them:
      #
      #    <literal_strong py:class="True" py:module="determined.experimental.client" ...>
      #
      # Is that legal XML?  Who knows, who cares.  We don't need that information so we do the
      # simplest thing to make our ElementTree not puke, and that's remove those colons.
      #
      # But ElementTree doesn't have a parsestring() method, so we wrap the fixed text in BytesIO.
      with open(os.path.join(root, xmlpath), "rb") as f:
          raw = f.read()
          fixed = re.sub(b"py:([a-zA-Z_]*)=", b"py\\1=", raw)
          bytes_io = io.BytesIO(fixed)
  
      tree = ElementTree.parse(bytes_io)
      root = tree.getroot()
      # Extract page title.
      title_node = root.find("section").find("title")
      title = xml2str(title_node)
      assert title, xmldumps(title_node)
  
      htmlpath = xmlpath.replace(".xml", ".html")
  
      order = 1
  
      def _extract_section(node, hier_in, idx):
          nonlocal order
          name = None
          try:
              records = []
              words = []
              # Extract the anchor, the first of the "ids" attribute.
              anchor = node.attrib["ids"].split()[0]
              children = iter(node)
              # The first node must be the <title>.
              title_node = next(children)
              assert (
                  title_node.tag == "title"
              ), f"first node's tag was {title_node.tag}, not title"
              name = xml2str(title_node)
              assert name, xmldumps(title_node)
              hier = (*hier_in, name)
              # Find words for this section (whatever comes before the child sections).
              for child in children:
                  if child.tag == "section":
                      have_subsections = True
                      break
                  # Smush all the text together like we just don't care.
                  words += xml2str(child).split()
              else:
                  have_subsections = False
  
              # Make a header record with no content.
              path = f"{htmlpath}#{anchor}"
              records.append(
                  mkrecord(hier, None, path, f"lvl{len(hier)-1}", order)
              )
              order += 1
              if words:
                  # Make a content-type record
                  records.append(
                      mkrecord(hier, words, path, "content", order)
                  )
                  order += 1
  
              if have_subsections:
                  records += _extract_section(child, hier, 0)
                  for i, subsection in enumerate(children):
                      records += _extract_section(
                          subsection, hier, i + 1
                      )
  
              return records
  
          except Exception as e:
              if isinstance(e, ExtractionError):
                  raise
              raise ExtractionError(
                  f"extraction failed, hier_in={hier_in}, idx={idx}, name={name}, "
                  f"node={xmldumps(node)[:512]}"
              ) from e
  
      return _extract_section(root.find("section"), [title], 0)
  
file_path: determined/docs/deploy/scrape.py
imports: import argparse
  import html
  import io
  import json
  import os
  import pathlib
  import re
  import sys
  import time
  import traceback
  from xml.etree import ElementTree
  from algoliasearch import search_client
label_desc: Use image node_id 4 for calling a global function with example usage: extract_file(root, xmlpath) and returns: _extract_section, records