Mysql
 sql >> Base de données >  >> RDS >> Mysql

Erreur d'encodage PHP lors de la production de XML à partir de la base de données

Votre question est vraiment large, la meilleure réponse que je puisse donner est que vous devriez utiliser une bibliothèque existante pour encoder le XML au lieu d'écrire la vôtre (car vous échouez évidemment avec le travail d'où l'erreur d'encodage XML signalée par le consommateur XML).

L'utilisation d'une bibliothèque existante vous permettrait également de signaler les problèmes plus tôt. Par exemple. pour le code suivant, assurez-vous que tout ce que vous récupérez de votre base de données sont des chaînes encodées en UTF-8.

L'utilisation d'une classe de client de base de données plus moderne vous aidera également à écrire simplement le code. Voici un exemple avec PDO et DOMDocument :

### configuration values

$config = array(
    'Database'     => array(
        'dsn'  => 'mysql:dbname=test;host=localhost;charset=utf8',
        'user' => 'testuser',
        'pass' => 'test',
    ),
    'table_name'   => 'config',
    'table_fields' => '*',
);

### implement database access

class Database extends PDO
{
    public function __construct(array $config = null)
    {
        $config = $config ? : $GLOBALS['config'][__CLASS__];
        parent::__construct($config['dsn'], $config['user'], $config['pass']);
        $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
        $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    }
}

### setup the datasource ($rows)

$db   = new Database();
$rows = $db->query("SELECT $config[table_fields] FROM $config[table_name]");

### setup the XML encoder ($doc)

$doc               = new DOMDocument();
$doc->formatOutput = true;
$doc->loadXML("<$config[table_name]s/>");
$doc->encoding = 'utf-8';

### fetch data from the datasource and encode the XML

foreach ($rows as $row) {
    $child = $doc->createElement($config['table_name']);
    $child = $doc->documentElement->appendChild($child);
    foreach ($row as $key => $value) {
        $child->appendChild($doc->createElement($key, $value));
    }
}

### output XML

header("Content-Type:text/xml");
echo $doc->saveXML();

Voir ce DomDocument s'occupe ici d'encoder correctement les chaînes UTF-8 renvoyées par la base de données. Il n'y a (normalement) pas besoin de <![CDATA[...]]> plus ici. Comme vous pouvez l'imaginer, vous avez probablement mis quelque chose là-dedans qui a cassé votre encodage XML.

De plus, pour l'interaction avec la base de données, la plupart de votre code n'est pas nécessaire non plus, vous pouvez simplement itérer sur les lignes, s'il n'y a pas de lignes, il n'y aurait pas d'itération. Ceci est normalement mieux exprimé avec un Iterator le foreach la construction de langage peut fonctionner sur laquelle est fournie par les interfaces de base de données modernes. Techniquement, vous pouvez remplacer $rows ici avec beaucoup d'autres choses, comme un itérateur qui parcourt plusieurs tables les unes après les autres.

De plus, l'utilisation du mode d'erreur d'exception vous évite de placer des chèques et de die s partout dans votre base de code.

Un exemple de sortie est :

<?xml version="1.0" encoding="utf-8"?>
<configs>
  <config>
    <id>1</id>
    <option>value for option with ID1</option>
  </config>
  <config>
    <id>2</id>
    <option>value for option with ID2</option>
  </config>
  ...
</configs>

Si vous avez encore besoin de créer des éléments CDATA, cela fonctionne de la même manière (je ne montre qu'une partie du script ici, qui ne contient qu'une légère modification en ajoutant des sections CDATA au lieu d'une valeur enfant) :

### fetch data from the datasource and encode the XML

foreach ($rows as $row) {
    $child = $doc->createElement($config['table_name']);
    $child = $doc->documentElement->appendChild($child);
    foreach ($row as $key => $value) {
        $child->appendChild($doc->createElement($key))
              ->appendChild($doc->createCDATASection($value))
        ;
    }
}

Ici aussi, DOMDocument s'occupe d'encoder correctement la section CDATA. Quelque chose que vous n'avez probablement pas fait.

Les problèmes potentiels que vous pourriez encore rencontrer sont avec des noms de table ou de ligne qui sont noms XML invalides . Mais alors DOMDocument vous le dira en fait pour que vous le sachiez lors de la génération du XML, pas seulement après avec une erreur d'encodage.