readFeatureElementInternal(node, objectStack, asFeature) {
    let geometryName;
    const values = {};
    for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
      let value;
      const localName = n.localName;
      // first, check if it is simple attribute
      if (
        n.childNodes.length === 0 ||
        (n.childNodes.length === 1 &&
          (n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))
      ) {
        value = getAllTextContent(n, false);
        if (ONLY_WHITESPACE_RE.test(value)) {
          value = undefined;
        }
      } else {
        if (asFeature) {
          //if feature, try it as a geometry or extent
          value =
            localName === 'boundedBy'
              ? this.readExtentElement(n, objectStack)
              : this.readGeometryElement(n, objectStack);
        }
        if (!value) {
          //if not a geometry or not a feature, treat it as a complex attribute
          value = this.readFeatureElementInternal(n, objectStack, false);
        } else if (localName !== 'boundedBy') {
          // boundedBy is an extent and must not be considered as a geometry
          geometryName = localName;
        }
      }

      const len = n.attributes.length;
      if (len > 0 && !(value instanceof Geometry)) {
        value = {_content_: value};
        for (let i = 0; i < len; i++) {
          const attName = n.attributes[i].name;
          value[attName] = n.attributes[i].value;
        }
      }

      if (values[localName]) {
        if (!(values[localName] instanceof Array)) {
          values[localName] = [values[localName]];
        }
        values[localName].push(value);
      } else {
        values[localName] = value;
      }
    }
    if (!asFeature) {
      return values;
    }
    const feature = new Feature(values);
    if (geometryName) {
      feature.setGeometryName(geometryName);
    }
    const fid =
      node.getAttribute('fid') || getAttributeNS(node, this.namespace, 'id');
    if (fid) {
      feature.setId(fid);
    }
    return feature;
  }
@param {Element} node Node.
@param {Array<*>} objectStack Object stack.
@param {boolean} asFeature whether result should be wrapped as a feature.
@return {Feature|Object} Feature