Tindona
Tindona

Reputation: 450

Parsing a XML list in to a list in flutter

I am getting data from an API that contains an ID, a name, a category, and multiple images and other attributes. My problem is with images, the XML is something like this:

<photoURLs>
   <photoURL> --URL-- </photoURL>
   <photoURL> --URL-- </photoURL>
   <photoURL> --URL-- </photoURL>
</photoURLs>

My object is defined like this:

class Pet {
  int id = 0;
  String name = '';
  String category = '';
  List<dynamic> photoUrls = [];
  List<dynamic> tags = [];
  String status = '';

  Pet(int id, String name, String category, List<dynamic> photoUrls,
      List<dynamic> tags, String status) {
    this.id = id;
    this.name = name;
    this.category = category;
    this.photoUrls = photoUrls;
    this.tags = tags;
    this.status = status;
  }

  Pet.fromJson(Map json)
      : id = json['id'],
        name = json['name'],
        category = json['category']['name'],
        photoUrls = json['photoUrls'],
        tags = json['tags'],
        status = json['status'];

  Map toJson() {
    return {
      'id': id,
      'name': name,
      'category': category,
      'photoUrls': photoUrls,
      'tags': tags,
      'status': status
    };
  }
}

My problem is my code gets the first image and shows it, but I dont know how to implement it for multiple images, I guess I have to parse this XML list into a list first, but I don't know how to do this. The output should be something like this:

List image_urls = [URL1, URL2, URL3]

here is my code so far: could anyone help me with this?

child: 
            FutureBuilder<List<Pet>>(
                    future: API.get_pets(),
                    builder: (context, snapshot) {
                      if (snapshot.hasData) {
                          return Column(
                            children: [
                              Text("Actual Pet: " + category.toString()),   
                              Expanded(
                                child: PageView.builder(
                                  itemCount: number_of_parameters,
                                  itemBuilder: (context, index) {
                                    Pet pet = snapshot.data![index];
                                    category = pet.category.toString();
                                    return Card(
                                      child: Container(
                                        decoration: BoxDecoration(
                                                borderRadius:
                                                    BorderRadius.circular(15),
                                                image: DecorationImage(
                                                    image: image(photoURL).image,
                                                    fit: BoxFit.fitWidth),
                                              ),
                                        child: Column(children: [
                                          Text ("": category)
                                        ]),),);},),),
                            ],
                          );
                      return const CircularProgressIndicator();
                      },},),);

PS: After using xml package:

 FutureBuilder<String>(
                    future: API.get_pets_full(randomly_select_URL()),
                    builder: (context, snapshot) {
                      if (snapshot.hasData) {
                        if (dropDownIsSelected == true) {
                          var number_of_parameters = snapshot.data!.length;
                          var random_pet = random.nextInt(number_of_parameters);
                          return Expanded(
                            child: PageView.builder(
                              scrollDirection: Axis.horizontal,
                              itemCount: number_of_parameters,
                              onPageChanged: (int index) {
                                setState(() {
                                  dropdownvalue = null;
                                  dropDownIsSelected = false;
                                });
                              },
                              itemBuilder: (context, index) {
                                String pet_data = snapshot.data![random_pet]; //[id, name, category, status, imageUrls];
                                print('PET_DATA');
                                print(pet_data);
                                final doc = XmlDocument.parse(pet_data);
                                print("DOC");
                                print(doc);

                                var id = doc.findAllElements('id').first.text;
                                var name = doc.findAllElements('name').first.text;
                                var category = doc.findAllElements('category').first.text;
                                var status = doc.findAllElements('status').first.text;
                                final photoUrls = doc.findAllElements('photoUrl').map((e) => e.text).toList();
                                print(photoUrls);

And The get_pets full function is like this:

  static Future<String> get_pets_full(selectedURL) async {
    selectedURL ??=
        'MY_API';
    final response = await http.get(Uri.parse(selectedURL),headers: {
    'Accept': 'application/xml',
  },);
  print(response.body); 
   return response.body;  
  }

Upvotes: 0

Views: 846

Answers (1)

Richard Heap
Richard Heap

Reputation: 51732

Use the xml package. Parse the document, then find the elements, which will give you an iterator of elements. Extract the text and form a list.

final doc = XmlDocument.parse(input);
final imageUrls = doc.findAllElements('photoURL').map((e) => e.text).toList();

EDIT

It seems based on your other question that your API will supply either JSON or XML. Parsing the list of URLs out of either is pretty simple. Note that there's a typo in your question; you show the tag as photoURL but in fact it's photoUrl.

Here's complete code showing both versions. (You can try the JSON version in Dartpad.)

import 'dart:convert';

import 'package:http/http.dart' as http;
import 'package:xml/xml.dart';

void main() async {
  var uri = Uri.parse(
    'https://yadda.yadda.io/api/v3/pet/findByStatus?status=available',
  );

  // The XML way
  final response = await http.get(
    uri,
    headers: {'Accept': 'application/xml'},
  );

  final doc = XmlDocument.parse(response.body);
  final imageUrls = doc.findAllElements('photoUrl').map((e) => e.text).toList();
  print(imageUrls);

  // The JSON way
  final r2 = await http.get(uri);
  final j = json.decode(r2.body);
  final images = (j[0]['photoUrls'] as List<dynamic>).cast<String>();
  print(images);
}

Upvotes: 1

Related Questions