static parseXpath(exprString) {
    const StringUtils = shaka.util.StringUtils;
    const returnPaths = [];
    // Split string by paths but ignore '/' in quotes
    const paths = StringUtils.htmlUnescape(exprString)
        .split(/\/+(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/);
    for (const path of paths) {
      const nodeName = path.match(/^([\w]+)/);

      if (nodeName) {
        // We only want the id attribute in which case
        // /'(.*?)'/ will suffice to get it.
        const idAttr = path.match(/(@id='(.*?)')/);
        const tAttr = path.match(/(@t='(\d+)')/);
        const numberIndex = path.match(/(@n='(\d+)')/);
        const position = path.match(/\[(\d+)\]/);
        returnPaths.push({
          name: nodeName[0],
          id: idAttr ?
            idAttr[0].match(/'(.*?)'/)[0].replace(/'/gm, '') : null,
          t: tAttr ?
            Number(tAttr[0].match(/'(.*?)'/)[0].replace(/'/gm, '')) : null,
          n: numberIndex ?
            Number(numberIndex[0].match(/'(.*?)'/)[0].replace(/'/gm, '')):
            null,
          // position is counted from 1, so make it readable for devs
          position: position ? Number(position[1]) - 1 : null,
          attribute: path.split('/@')[1] || null,
        });
      } else if (path.startsWith('@') && returnPaths.length) {
        returnPaths[returnPaths.length - 1].attribute = path.slice(1);
      }
    }
    return returnPaths;
  }
Parse xPath strings for segments and id targets.
@param {string} exprString
@return {!Array<!shaka.util.TXml.PathNode>}