vue.jsaxiosnuxt.jsrss-reader

How to get an url attribute from a namespaced XML source with Vue?


I am trying to show a Rss feed in Nuxt with Axios.

I can get:

It is working but for the images which are in:

<media:content url="https://uploads-ssl.webflow.com/60f1911b212fd90baa99ee92/00e5cfa7_mv2.jpg" medium="image >

I can't find the way to access it.

Here is my axios:

<script>
  asyncData ({params}, callback) {
    axios.get("https://yaniimodels.webflow.io/categories/rss.xml" )
      .then((res) => {
        var parseString = require('xml2js').parseString
        var xml = res.data
        parseString(xml, (message, xmlres) => {
          callback(null,{ data: xmlres.rss.channel[0].item})
        })
      })
      .catch((e) => {
        callback({ statusCode: 404, message: 'error' })
      })
  },
</script>

and in my template:

<template>
  <ul>
    <li v-for="item in data" :key="item.id">
      <a :href="item.link">
        {{item.title}}
        {{item.description}}
      </a>
    </li>
  </ul>
</template>

My rss.xml is like this :

<item>
    <title>Yanii Models | Ben and Ezra</title>
    <link>https://yaniimodels.webflow.io/categories/ben-and-ezra</link>
    <guid>https://yaniimodels.webflow.io/categories/ben-and-ezra</guid>
    <description>Petit Bâteau</description>
    <pubDate>Fri, 16 Jul 2021 16:27:00 GMT</pubDate>
    <media:content url="https://uploads-ssl.webflow.com/60f1911b212fd90baa99ee92/60f1b23cf09c3f73a4f92a1b_b79a66_8fa332a4dea94558b5f1e97200e5cfa7_mv2.jpg" medium="image"/>
    <media:thumbnail url="https://uploads-ssl.webflow.com/60f1911b212fd90baa99ee92/60f1b23cf09c3f73a4f92a1b_b79a66_8fa332a4dea94558b5f1e97200e5cfa7_mv2.jpg"/>
</item>

Solution

  • To display the RSS feed:

    1. @nuxtjs/axios is commonly used with Nuxt, which provides access to axios via the $axios context property (1st argument for asyncData). There's no need to import it in your component.

    2. The asyncData() callback parameter is deprecated. Use async/await instead.

    3. Use the Promise-based xml2js parser API for more succinct code.

    4. xml2js seems to wrap all propertries in an array, so you'll have to unwrap it (or index into it, which would be inconvenient to me).

    5. There is no item.id property, but there's item.guid. Use that for the v-for item key.

    6. The image URL is stored in media:content.$.url of each item. You could bind that URL to <img>.src.

    <script>
    export default {
      async asyncData ({ $axios 1️⃣, params }, /* callback 2️⃣ */) {
        const res = await $axios.get("https://yaniimodels.webflow.io/categories/rss.xml")
        const xmlres = await parseStringPromise(res.data) 3️⃣
        
        4️⃣
        const data = xmlres.rss.channel[0].item.map(item => {
          const newEntries = Object.entries(item).map(([key,val]) => [key, val[0]])
          return Object.fromEntries(newEntries)
        })
    
        return { data }
      }
    }
    </script>
    
    <template>
      <ul>
        <li v-for="item in data" :key="item.guid"> 5️⃣
          ...
          <img :src="item['media:content'].$.url"> 6️⃣
        </li>
      </ul>
    </template>
    

    demo