1

i have "problems" validating external xml. What i want is to fetch data from an external rss site, validate if all fields are present and save it to the database then.

The problem i am having is that i am not sure how can i send the xml data to my validator. I tried in different ways but it was not working.

https://api.foxsports.com/v1/rss?partnerKey=zBaFxRyGKCfxBagJG9b8pqLyndmvo7UU&tag=nba

This is an example of the rss i am trying to parse.

Here is my code:

    import json
import requests
import xml.etree.ElementTree as ET

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, generics

class Test(APIView):

    def get(self, request, format=None):


                response = requests.get(
                    channel.url
                )

                print(response.status_code)

                if response.status_code == 200:
                    xml = response.text.encode("utf-8")

                    tree = ET.fromstring(xml)

                    for child in tree.iter("item"):


                        serializer = RssSerializer(data=child)
                        if serializer.is_valid():
                            serializer.save(parsed_xml)

The problem here is that my serializer is always not valid, no matter what i do. I kind of got around this problem when i wrote a small helper function that is manually extracting fields from the request.

It looks like this:

def parse_xml(self, node):

    parsed_json = {
        "title": node.find("title").text,
        "description": node.find("description").text,
        "link": node.find("link").text,
        "pub_date": node.find("pubDate").text,
        "guid": node.find("guid").text,
    }

    return parsed_json

Basically i just added this line parsed_xml = self.parse_xml(child) and i am sending the parsed_xml to my serializer. That works fine but it seems like a hackhish way to me, but i am not able to process the data in any other way.

 class RssSerializer(serializers.Serializer):
    title = serializers.CharField(min_length=2)
    link = serializers.CharField(min_length=2)
    description = serializers.CharField(min_length=2)
    pub_date = serializers.CharField(min_length=2)
    guid = serializers.CharField(min_length=2)


    def save(self, data):
        new_feed = RssFeed()

        new_feed.title = data["title"]
        new_feed.description = data["description"]
        new_feed.pub_date = data["pub_date"]
        new_feed.link = data["link"]
        new_feed.guid = data["guid"]

        new_feed.save()

What i want to know is there any way i can fetch the xml from an external source and directly pass it to my validator? Thanks in advance for your help

Proxy
  • 1,118
  • 2
  • 10
  • 27

1 Answers1

3

Serializers do not expect xml nodes as data, so the short answer is no, unfortunately there is no direct way to pass it to validator. However, you could reuse one of the existing methods to either change whole xml to dictionary, and then feed the items to the serializer, or to change single nodes to dictionaries.

For inspiration, I would look into available solution (no need to reinvent the wheel):

E.g. your code could look like this:

xml = response.text.encode("utf-8")
xml_dict = xmltodict.parse(xml)
for item in xml_dict["rss"]["channel"]["item"]:
    serializer = RssSerializer(data=item)
mfrackowiak
  • 1,294
  • 8
  • 11