0

この関数で取得した名前の UTF8 バージョンを取得するために行ったことがありますが、何らかの理由で正しい文字で出力されません。

出力例:

ѕqÃ…ιÑÂтℓє

期待される出力:

ѕqυιятℓє 

ファイル、file_get_contents から取得された文字列、関数の出力、およびソース XML ファイルに対して文字セット チェックを実行しました。MySQL も正しいバージョンを取得しません。

また、SimpleXML は UTF-8 をサポートしています。

sudo ファイル -i debug.txt

debug.txt: txt/plain; charset=utf-8

MySQL照合

utf8_general_ci

ソース XML ファイルのヘッダー:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

これは(コードに2回あります)-

  $enc = mb_detect_encoding($xml, 'UTF-8', true);
  echo 'Detected encoding '.$enc;

出力:

Detected encoding UTF-8
Detected encoding UTF-8

他にどこで UTF-8 文字セットを確認すればよいのか、それが最初に必要なのかどうかはわかりません。ここの誰かが、期待されるバージョンの名前を取得する方法を知っていることを願っています。ありがとうございます。

TextFile (ログ) 出力関数:

function log_output($message){
  $file = 'debug.txt';
  $current = file_get_contents($file);
  $current .= $message."\n"; 
  file_put_contents($file, $current);  
}

ソースコード:

// Converts SteamID(64) to the users current name on Steam.
        function steamid64_to_name($steamid64) {
          // Get User Profile Data
          $xml = file_get_contents('http://steamcommunity.com/profiles/'.$steamid64.'/?xml=1');
          $enc = mb_detect_encoding($xml, 'UTF-8', true);
          echo 'Detected encoding '.$enc;
          $xml = simplexml_load_string($xml, null, LIBXML_NOCDATA);
          if(!empty($xml)) {
            if(isset($xml->steamID)) {
               $username = $xml->steamID;// Example: steamcommunity.com/profiles/76561198077095013/?xml=1
            } else { 
              $username = "Username Not Found";
            } 
          } else {
            $username = "User XML Not Found"; // Example: steamcommunity.com/profiles/0/?xml=1
          }
          $enc = mb_detect_encoding($xml, 'UTF-8', true);
          echo 'Detected encoding '.$enc;
          return $username;
        }
4

1 に答える 1

0

あなたが尋ねるのは、SimpleXML についてではなく、出力エンコーディングについてです。出力エンコーディングは、ブラウザに送信するデータと、そのデータで使用されるエンコーディングに関する情報 (データ + メタ) です。

また、Apache HTTPD を使用することについてコメントしました。

AddDefaultCharset utf-8

問題を修正しました。つまり、ブラウザに送信するデータが UTF-8 でエンコードされていることをブラウザに伝えます。以前は、ブラウザにラテン語の何かになると伝えていたため、これらの間違った文字が表示されました。手紙を受け取った人がどの言語で手紙を読むべきかを理解できるように、手紙の横に言語に名前を付ける必要があることを考慮してください.

それとは別に、問題をより迅速に発見し、コードを書きすぎないようにするために考慮すべき一般的な経験則がいくつかあります。

  • から文字列を読み取ると、SimpleXMLElementUTF-8 でエンコードされたデータが得られます。作成した元のファイルのエンコーディングが何であったかに関係なく。
  • SimpleXML はほとんどの再エンコーディングを独自に処理します。必要なのは、通常は適切な iconv をインストールすることだけです (それ以外の場合は推奨されます)。
  • 自分自身に厳密になり、ここでmb_detect_encoding. 技術的には不可能であり、代わりに、エンコーディングが不明な場合は、データからではなく、ソースからその情報を取得します (データから取得することは技術的に不可能であり、これは常に推測のままです)。
  • 最後になりましたが、これはリモート サービスに関するものであるため、常に間接的なレイヤーをここに追加する必要があります。ここで紹介したい最も小さなことは、私が推測するリモート リクエストのキャッシュです。したがって、それをクラスにラップすることが最初のステップです。

Steam API アクセスの例:

<?php
/**
 * PHP SimpleXML - Unable to correctly convert SteamID64 to Steam
 * Name with UTF8
 *
 * @link http://stackoverflow.com/q/19507614/367456
 */

$profile = new SteamProfile('76561198027590831');
echo $profile->getUsername(), "\n";
var_dump((string)$profile);

/**
 * Class SteamProfile
 *
 * Converts SteamID(64) to the users current name on Steam.
 */
class SteamProfile
{
    const STEAMAPI_URL_MASK = 'http://steamcommunity.com/profiles/%s/?xml=1';
    const UNKONWN_NAME_MASK = 'User #%s (Username Not Found)';

    private $steamId;
    private $xml;

    public function __construct($steamId)
    {
        $this->steamId = $steamId;
    }

    public function getUsername()
    {
        $xml = $this->getXml($this->steamId);

        return $xml->steamID
            ? (string)$xml->steamID
            : sprintf(self::UNKONWN_NAME_MASK, $this->steamId)
            ;
    }

    private function getXml($steamId)
    {
        if ($this->xml) {
            return $this->xml;
        }

        $url = sprintf(self::STEAMAPI_URL_MASK, $steamId);

        if (!$xml = simplexml_load_file($url)) {
            throw new UnexpectedValueException(sprintf('Unable to load XML from "%s"', $url));
        }

        return $this->xml = $xml;
    }

    public function __toString()
    {
        return sprintf("%s (SteamID: %s)", $this->getUsername(), $this->steamId);
    }
}

出力例 (UTF-8 エンコード):

ѕqυιятℓє | [A]
string(51) "ѕqυιятℓє | [A] (SteamID: 76561198027590831)"

例と出力が示すように、Steam が有効な XML を提供し、Simplexml が有効な XML に対して作成されている限り、エンコーディングについてあまり気にする必要はありません。Web サイトでエンコードとして UTF-8 を使用する、最初にデータを UTF-8 からターゲット エンコードに再エンコードする必要があります。

また、SteamProfileオブジェクトを使用することで、後で別の実装に置き換えることができます。たとえば、リモートリクエストを別のレイヤーに委任するものを使用します。

于 2013-10-30T09:27:04.270 に答える