getElementsWhere method

List<XmlElement>? getElementsWhere(
  1. {String? name,
  2. String? id,
  3. List<String>? attributeNames,
  4. List<XmlAttribute>? attributes,
  5. bool matchAllAttributes = false,
  6. bool attributesMustBeIdentical = false,
  7. List<XmlNode>? children,
  8. bool matchAllChildren = false,
  9. bool childrenMustBeIdentical = false,
  10. bool ignoreNestedMatches = true,
  11. int start = 0,
  12. int? stop,
  13. bool global = true,
  14. bool reversed = false}
)

Recursively checks all elements within the node tree and returns any elements found with properties matching those specified.

name and id must not be empty if they are provided.

If attributeNames is not null, only elements posessing an attribute with a name contained in attributeNames will be returned. If matchAllAttributes is true, an element must possess every attribute contained in attributeNames to be returned, if false, the element only needs to posess a single attribute contained in attributeNames.

If attributes isn't null, only elements possessing attributes with an identical name and value as those contained in attributes will be returned. If matchAllAttributes is true, an element must possess every attribute contained in attributes, if false, the element only needs to possess a single attribute contained in attributes.

If children isn't null, only elements possessing children matching those in children will be returned. If matchAllChildren is true, an element must posess every child found in children, if false, the element only needs to posess a single child found in children. If childrenMustBeIdentical is true, the element's children must be in the same order and possess the same number of children as those in children, children will also be compared with the == operator, rather than the compareValues method.

If ignoreNestedMatches is true, matching elements that are nested within matching elements will not be returned, only the highest level matching elements will be returned. If false, all matching elements will be returned.

start and stop refer to the indexes of the identified elements. Only matches found between start and stop will be returned. start must not be null and must be >= 0. stop may be null, but must be >= start if provided.

Returns null if no element can be found.

Implementation

List<XmlElement>? getElementsWhere({
  String? name,
  String? id,
  List<String>? attributeNames,
  List<XmlAttribute>? attributes,
  bool matchAllAttributes = false,
  bool attributesMustBeIdentical = false,
  List<XmlNode>? children,
  bool matchAllChildren = false,
  bool childrenMustBeIdentical = false,
  bool ignoreNestedMatches = true,
  int start = 0,
  int? stop,
  bool global = true,
  bool reversed = false,
}) {
  assert(name == null || name.isNotEmpty);
  assert(id == null || id.isNotEmpty);
  assert(start >= 0);
  assert(stop == null || stop >= start);

  if (this.children == null || start >= this.children!.length) return null;

  name = name?.toLowerCase();

  final elements = <XmlElement>[];
  var elementCount = 0;

  for (var child in reversed ? this.children!.reversed : this.children!) {
    if (child is XmlElement) {
      if (compareValues(
        child,
        name: name,
        id: id,
        attributes: attributes,
        attributeNames: attributeNames,
        matchAllAttributes: matchAllAttributes,
        attributesMustBeIdentical: attributesMustBeIdentical,
        children: children,
        matchAllChildren: matchAllChildren,
        childrenMustBeIdentical: childrenMustBeIdentical,
      )) {
        if (elementCount >= start) elements.add(child);

        elementCount++;

        if (stop != null && elementCount > stop) break;

        if (ignoreNestedMatches) continue;
      }

      if (!global) continue;

      if (child.children?.isNotEmpty == true) {
        final nestedChildren = child.getElementsWhere(
          name: name,
          id: id,
          attributeNames: attributeNames,
          attributes: attributes,
          matchAllAttributes: matchAllAttributes,
          attributesMustBeIdentical: attributesMustBeIdentical,
          children: children,
          matchAllChildren: matchAllChildren,
          childrenMustBeIdentical: childrenMustBeIdentical,
          ignoreNestedMatches: ignoreNestedMatches,
          start: 0,
          stop: (stop != null) ? stop - elementCount : null,
        );

        if (nestedChildren != null) {
          for (var nestedChild in nestedChildren) {
            if (elementCount >= start) elements.add(nestedChild);

            elementCount++;

            if (stop != null && elementCount > stop) break;
          }
        }
      }

      if (stop != null && elementCount > stop) break;
    }
  }

  if (elements.isEmpty) return null;

  return elements;
}