0

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;  
  }
6
  • Give examples of output from the print statements - i.e. response.body, pet_data and doc Commented Jul 30, 2022 at 20:48
  • it gives an error of XmlParserException (XmlParserException: "<" expected at 1:1) on the ` final doc = XmlDocument.parse(pet_data);` line, and print(pet_data) gives a one letter output like q or B ... Commented Jul 30, 2022 at 20:58
  • In which case, what makes you think you can parse pet_data as XML?? a single letter cannot possible be XML. What does response.body look like? Commented Jul 30, 2022 at 21:17
  • response.body is a XML like <ArrayList><item><id>1</id><category><id>101</id><name>Bunny</name></category><name>Bundor Bunny</name><photoUrls><photoUrl>data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAD/4gxYSUNDX1BST0ZJTEUAAQEAAAxITGlubwIQAAB... Commented Jul 30, 2022 at 21:27
  • I have some data about pets, and sometimes with multiple photoUrls for one pet, I think it would be easier to parse them into XML, to handle that multiple photos @RichardHeap Commented Jul 30, 2022 at 21:28

1 Answer 1

1

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);
}
Sign up to request clarification or add additional context in comments.

7 Comments

doesn't work for me, is there anything else that I need to consider?
What doesn't work? What bits do? What happens if you print doc? What happens if you do doc.findAllElements('photoURL').forEach(print); ?
printing doc gives me only q and doc.findAllElements('photoURL') gives XmlParserException (XmlParserException: "<" expected at 1:1) Error
Update your question showing your XML processing code.
Thank you I am going to test it soon, really appreciate your time
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.