static processXlinks(
      element, retryParameters,
      failGracefully, baseUri, networkingEngine,
      linkDepth = 0) {
    const MpdUtils = shaka.dash.MpdUtils;
    const TXml = shaka.util.TXml;
    const NS = MpdUtils.XlinkNamespaceUri_;

    if (TXml.getAttributeNS(element, NS, 'href')) {
      let handled = MpdUtils.handleXlinkInElement_(
          element, retryParameters, failGracefully,
          baseUri, networkingEngine, linkDepth);
      if (failGracefully) {
        // Catch any error and go on.
        handled = handled.chain(undefined, (error) => {
          // handleXlinkInElement_ strips the xlink properties off of the
          // element even if it fails, so calling processXlinks again will
          // handle whatever contents the element natively has.
          return MpdUtils.processXlinks(
              element, retryParameters, failGracefully, baseUri,
              networkingEngine, linkDepth);
        });
      }
      return handled;
    }

    const childOperations = [];
    for (const child of shaka.util.TXml.getChildNodes(element)) {
      const resolveToZeroString = 'urn:mpeg:dash:resolve-to-zero:2013';
      if (TXml.getAttributeNS(child, NS, 'href') == resolveToZeroString) {
        // This is a 'resolve to zero' code; it means the element should
        // be removed, as specified by the mpeg-dash rules for xlink.
        element.children = element.children.filter(
            (elem) => elem !== child);
      } else if (child.tagName != 'SegmentTimeline') {
        // Don't recurse into a SegmentTimeline since xlink attributes
        // aren't valid in there and looking at each segment can take a long
        // time with larger manifests.

        // Replace the child with its processed form.
        childOperations.push(shaka.dash.MpdUtils.processXlinks(
            /** @type {!shaka.extern.xml.Node} */ (child),
            retryParameters, failGracefully,
            baseUri, networkingEngine, linkDepth));
      }
    }

    return shaka.util.AbortableOperation.all(childOperations).chain(() => {
      return element;
    });
  }
Filter the contents of a node recursively, replacing xlink links
with their associated online data.

@param {!shaka.extern.xml.Node} element
@param {!shaka.extern.RetryParameters} retryParameters
@param {boolean} failGracefully
@param {string} baseUri
@param {!shaka.net.NetworkingEngine} networkingEngine
@param {number=} linkDepth default set to 0
@return {!shaka.util.AbortableOperation.<!shaka.extern.xml.Node>}