Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Erro de codificação PHP ao produzir XML do banco de dados


Sua pergunta é muito ampla, a melhor resposta que posso dar é que você deve usar alguma biblioteca existente para codificar o XML em vez de escrever sua própria (como você obviamente falha com o trabalho, portanto, o erro de codificação XML relatado pelo consumidor de XML).

O uso de uma biblioteca existente também permitiria apontar problemas mais cedo. Por exemplo. para o código a seguir, certifique-se de que tudo o que você obtém de seu banco de dados são strings codificadas em UTF-8.

Também usar uma classe de cliente de banco de dados mais moderna também ajudará você a escrever o código. Aqui está um exemplo com PDO e 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();

Veja que DomDocument está cuidando aqui de codificar corretamente as strings UTF-8 que são retornadas do banco de dados. Não há (normalmente) necessidade de <![CDATA[...]]> aqui mais. Como você pode imaginar, você provavelmente colocou algo lá que quebrou sua codificação XML.

Também para a interação com o banco de dados, a maior parte do seu código também não é necessária, você pode apenas iterar sobre as linhas, se não houver linhas, não haverá iteração. Isso normalmente é melhor expresso com um Iterator o foreach construção de linguagem pode operar no que é fornecido por interfaces de banco de dados modernas. Tecnicamente, você pode substituir $rows aqui com muitas outras coisas, como um iterador que percorre várias tabelas uma após a outra.

Além disso, usar o modo de erro de exceção poupa você de fazer cheques e die s em toda a sua base de código.

Uma saída exemplar é:
<?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>

Se você ainda precisar criar elementos CDATA, ele funciona de maneira semelhante (mostro apenas uma parte do script aqui, que contém apenas uma pequena modificação adicionando seções CDATA em vez de um valor filho):
### 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))
        ;
    }
}

Aqui também, DOMDocument cuida da codificação adequada da seção CDATA. Algo que provavelmente você não fez.

Problemas potenciais que você ainda pode encontrar são com nomes de tabelas ou linhas que são nomes XML inválidos . Mas então DOMDocument vai realmente dizer para você saber ao gerar o XML, não apenas depois com um erro de codificação.