3

I need help parsing a nested XML file in Dart/Flutter.

I have a Dart class

class Genre {
String id;
String title;
String token;
String type;
// For children objets I want to get list of IDs
// as String
List<String> subGenres;
}

The XML file looks as follow:

<genres>
  <genre id="5003" title="Бизнес-книги" type="root">
    <genre id="5049" title="Банковское дело" token="bankovskoe_delo" type="genre"/>
    <genre id="5047" title="Кадровый менеджмент" token="kadrovyj_menedzhment" type="container">
      <genre id="5334" title="Аттестация персонала" token="attestaciya_personala" type="genre"/>
      <genre id="5330" title="Гендерные различия" token="gendernyye_razlichiya" type="genre"/>
      <genre id="5332" title="Конфликты" token="konflikty" type="genre"/>
    </genre>
  </genre>
  <genre id="5013" title="Юмористическая литература" type="root">
    <genre id="5201" title="Анекдоты" token="anekdoty" type="genre"/>
    <genre id="5202" title="Зарубежный юмор" token="zarubezhnyy" type="genre"/>
  </genre>
</genres>

So I have maybe unlimited levels of sub-genres. If a type of object is 'root' or 'container' it contains sub-genres, type 'genre' is a single record (like folders and files).

How can I get the list of all of my objects and parse it to class objects ?

1 Answer 1

4

Use the xml package. I like to use a factory constructor that takes an XmlElement. There's no reason to limit yourself to a List<String> for the children; you could have a List<Genre> to build a tree that mirrors your XML. (You could, of course, do that instead if you prefer.)

Notice how the factory constructor iterates through any child XML elements, recursively calling itself. The normal constructor is private, so that only the factory constructor uses it. If a genre has no sub-genres, the subGenres list isEmpty.

import 'package:xml/xml.dart';

var sample = '''<?xml version="1.0" encoding="UTF-8"?>
<genres>
  <genre id="5003" title="Бизнес-книги" type="root">
    <genre id="5049" title="Банковское дело" token="bankovskoe_delo" type="genre"/>
    <genre id="5047" title="Кадровый менеджмент" token="kadrovyj_menedzhment" type="container">
      <genre id="5334" title="Аттестация персонала" token="attestaciya_personala" type="genre"/>
      <genre id="5330" title="Гендерные различия" token="gendernyye_razlichiya" type="genre"/>
      <genre id="5332" title="Конфликты" token="konflikty" type="genre"/>
    </genre>
  </genre>
  <genre id="5013" title="Юмористическая литература" type="root">
    <genre id="5201" title="Анекдоты" token="anekdoty" type="genre"/>
    <genre id="5202" title="Зарубежный юмор" token="zarubezhnyy" type="genre"/>
  </genre>
</genres>
''';

class Genre {
  Genre._(this.id, this.title, this.token, this.type, this.subGenres);

  factory Genre.fromElement(XmlElement genreElement) {
    return Genre._(
      genreElement.getAttribute('id'),
      genreElement.getAttribute('title'),
      genreElement.getAttribute('token'),
      genreElement.getAttribute('type'),
      genreElement
          .findElements('genre')
          .map<Genre>((e) => Genre.fromElement(e))
          .toList(),
    );
  }

  String id;
  String title;
  String token;
  String type;
  List<Genre> subGenres;
}

void main() {
  var root = XmlDocument.parse(sample).getElement('genres');
  var rootGenres = root
      .findElements('genre')
      .map<Genre>((e) => Genre.fromElement(e))
      .toList();

  print(rootGenres);
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you man, you saved my day. Now I need to realize how to put this stuff to firebase an to show it in ListViews )). I think I'll put all the genres to the top level and address the children genres by ids list in parent genre.
Thank you again. I've almost completely finished my production code w/ your help. How can I accept the answer in stack ? And I have another question on flutter xml package, if you can help it'll be cool - stackoverflow.com/questions/63431246/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.