5

Inside a React Native method I'm fetching a xml encoded in ISO-8859-1.

As long as the fetching is completed I'm trying to convert it to UTF-8.

Here the code:

const iconv = require('iconv-lite');

fetch('http://www.band.uol.com.br/rss/colunista_64.xml', {
      headers: {
        "Content-type": "text/xml; charset=ISO-8859-1"
      }
})
.then(res=>res.text()})
.then(text => {
   const decodedText = iconv.decode(Buffer.from(text, 'latin1'), 'latin1')
  , output = iconv.encode(decodedText, 'utf8')
   console.log(output.toString())
})

The problem is: all especial characters of the body is being replaced by "¿½"

For the conversion, I'm using the package iconv-lite

What is the better workaround for this problem?

4 Answers4

4

The best workaround is to use res.arrayBuffer() instead res.text(), as long the Buffer constructor accepts ArrayBuffer

The code:

fetch('http://www.band.uol.com.br/rss/colunista_64.xml')
      .then(res => res.arrayBuffer())
      .then(arrayBuffer => iconv.decode(new Buffer(arrayBuffer), 'iso-8859-1').toString())
      .then(converted => console.log(converted))
  • 1
    have you tested this? i got an error message saying that arrayBuffer() is not implement in react-native – andri Mar 24 '18 at 16:52
  • Very true; that won't work on react-native; you could make `iconv` work on React.js by importing the `buffer`, `stream` and `iconv-lite` packages, but `arrayBuffer()` still wouldn't work. – Haroldo_OK Aug 06 '19 at 17:25
  • 1
    This is an ugly problem, with an even uglier workaround: you will need to install `iconv-lite`, plus its dependencies, then do the [monkey punch listed this issue](https://github.com/facebook/react-native/issues/21209#issuecomment-495294672), because, for whatever reason, React Native does not support `arrayBuffer()`, then instantiate an `Uint8Array` passing the `ArrayBuffer` as an argument, because `iconv-lite` won't be able to use it directly. – Haroldo_OK Aug 06 '19 at 19:00
3

As pointed out by Hellon Canella Machado you can't use res.text() and must use an ArrayBuffer as a workaround.

Since res.arrayBuffer() doesn't work with fetch in React Native you can use the XMLHttpRequest API.

import iconv from 'iconv-lite';
import { Buffer } from 'buffer';

function fetchXML() {
  return new Promise((resolve, reject) => {
    const request = new XMLHttpRequest();

    request.onload = () => {
      if (request.status === 200) {
        resolve(iconv.decode(Buffer.from(request.response), 'iso-8859-1'));
      } else {
        reject(new Error(request.statusText));
      }
    };
    request.onerror = () => reject(new Error(request.statusText));
    request.responseType = 'arraybuffer';

    request.open('GET', 'http://www.band.uol.com.br/rss/colunista_64.xml');
    request.setRequestHeader('Content-type', 'text/xml; charset=ISO-8859-1');
    request.send();
  });
}

fetchXML().then(response => 
    console.log(response)
);

Also make sure that you have the packages buffer and stream installed.

Nico0302
  • 41
  • 1
  • 4
0
let axiosConfig = {
    responseType: 'arraybuffer',
    responseEncoding: 'binary',
  }

const htmlPage = await axios.get(`http://www.band.uol.com.br/rss/colunista_64.xml`, axiosConfig);
const decoder = new TextDecoder('iso-8859-1');
decoder.decode(pageHtml.data)
General Grievance
  • 4,555
  • 31
  • 31
  • 45
  • 2
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 20 '21 at 15:17
  • 1
    Welcome to Stack Overflow, and thank you for contributing an answer. Would you kindly edit your answer to to include an explanation of your code? That will help future readers better understand what is going on, and especially those members of the community who are new to the language and struggling to understand the concepts. That's especially important when there's already an accepted answer from a few years ago that's been validated by the community. Under what conditions might your approach be preferred? Are you taking advantage of new capabilities? – Jeremy Caney Sep 21 '21 at 00:12
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 21 '21 at 00:37
0

The solution is actually rather simple. Just use axios instead of fetch. Axios works out of the box in react native, without any special dependencies. It converts the encoding of a response to UTF-8 automatically for each request by default without any configuration.

npm install axios

Example:

import axios from 'axios';

let response = await axios.get(url);
console.log(response);

Thats it! The response.data is auto converted to UTF-8 from whichever encoding the archaic site uses.

ropman
  • 1
  • 2