parseString static method

List<XmlText>? parseString(
  1. String string, {
  2. bool parseCharacterEntities = true,
  3. bool trimWhitespace = true,
  4. int start = 0,
  5. int? stop,
})
override

Returns a list of every root level XML text node found in string. string must not be null.

If parseCharacterEntities is true, text values will be parsed and replace all encoded character entities with their corresponding character. parseCharacterEntities must not be null.

If trimWhitespace is true, unnecessary whitespace between nodes will be removed and all remaining whitespace will be replaced with a single space. trimWhitespace must not be null.

start and stop refer to the indexes of the identified text nodes. 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 text nodes are found.

Implementation

static List<XmlText>? parseString(
  String string, {
  bool parseCharacterEntities = true,
  bool trimWhitespace = true,
  int start = 0,
  int? stop,
}) {
  assert(start >= 0);
  assert(stop == null || stop >= start);

  string = string.removeComments();
  if (trimWhitespace) string = string.trimWhitespace();

  if (!string.contains(RegExp(r'<.*>', dotAll: true))) {
    return <XmlText>[XmlText(string)];
  }

  final text = <XmlText>[];
  var textCount = 0;

  // Capture any text found before the first node.
  final firstNode = string.indexOf('<');
  if (firstNode >= 0) {
    var prependedText = string.substring(0, firstNode).trim();
    if (prependedText.isNotEmpty) {
      if (parseCharacterEntities) {
        prependedText = HtmlCharacterEntities.decode(prependedText);
      }

      if (start == 0) text.add(XmlText(prependedText));
      textCount++;

      if (stop != null && textCount > stop) {
        if (text.isEmpty) {
          return null;
        } else {
          return text;
        }
      }
    }
  }

  // Capture any text found in/between nodes.
  final matches = Delimiters.text.allMatches(string);

  for (var match in matches) {
    var matchedText = match.namedGroup('text');

    if (matchedText?.isEmpty == true) continue;

    if (textCount >= start) {
      if (parseCharacterEntities) {
        matchedText = HtmlCharacterEntities.decode(matchedText!);
      }

      text.add(XmlText(matchedText!));
    }

    textCount++;

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

  // Capture any text found after the last node.
  if (stop == null || textCount < stop) {
    final lastNode = string.lastIndexOf('>');

    if (lastNode >= 0) {
      var appendedText = string.substring(lastNode + 1).trim();

      if (appendedText.isNotEmpty) {
        if (parseCharacterEntities) {
          appendedText = HtmlCharacterEntities.decode(appendedText);
        }

        text.add(XmlText(appendedText));
      }
    }
  }

  if (text.isEmpty) return null;

  return text;
}