private function _parseAttrString(int &$offset): string
    {
        $idx = $offset;
        $val = "";
        $wsidx = null;
        while ($idx < $this->_len) {
            $c = $this->_dn[$idx];
            // pair (escape sequence)
            if ("\\" == $c) {
                ++$idx;
                $val .= $this->_parsePairAfterSlash($idx);
                $wsidx = null;
                continue;
            } else if ('"' == $c) {
                throw new \UnexpectedValueException("Unexpected quotation.");
            } else if (false !== strpos(self::SPECIAL_CHARS, $c)) {
                break;
            }
            // keep track of the first consecutive whitespace
            if (' ' == $c) {
                if (null === $wsidx) {
                    $wsidx = $idx;
                }
            } else {
                $wsidx = null;
            }
            // stringchar
            $val .= $c;
            ++$idx;
        }
        // if there was non-escaped whitespace in the end of the value
        if (null !== $wsidx) {
            $val = substr($val, 0, -($idx - $wsidx));
        }
        $offset = $idx;
        return $val;
    }