Search code examples
javascriptjqueryxmlcheerioqueryselector

cheeriojs iterate over xml response


Say I have an xml response from a request that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/xsl/someExcelSheet.xsl"?>
<events>
  <event onair="true">
    <type>Live</type>
    <title>Nyhederne - 1/1</title>
    <airtime>09:30:02.13</airtime>
    <id>58529</id>
  </event>
  <event onair="false">
    <type>PrimaryVideo</type>
    <title>MTV1</title>
    <airtime>09:35:02.13</airtime>
    <id>58532</id>
  </event>
  ...

How do I use cheeriojs to extract data from it?

Was doing

  request(url, (error, response, xml) => {
    if (!error && response.statusCode == 200) {
      const $ = cheerio.load(xml, {
        xmlMode: true,
        decodeEntities: true,
        withStartIndices: false,
        withEndIndices: false,
      })

and trying

> $('events')
LoadedCheerio(1) [Element, options: {…}, _root: LoadedCheerio(1), prevObject: LoadedCheerio(1)]
> $('event')
LoadedCheerio(468) [Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, Element, …]

but could not figure out how to work with it. Wanted to grab all event in the events and iterate over it and read the text in the <type>, <title> etc tags.

what I ended up doing was

const rows: string[][] = $('event')
  .text()
  .split(/\n/)
  .map((str) => str.trim())
  .join('\n')
  .split(/\n{2,}/g)
  .reduce((acc, str) => [...acc, str.split(/\n/)], [])

But there must be a better way and I'm hoping somebody would like to explain that to me?


Solution

  • Something like this should get you started:

    $('event').get().map(event => {
      return {
        type: $(event).find('type').text(),
        title: $(event).find('title').text(),
        // more props
      }
    })