2012-01-02 7 views
1

PHPのXMLパーサーは、文字列内に特殊文字が見つかると、その文字列を分割してデフォルトハンドラ関数を2回呼び出します。私は、PHPのコードに同様のXMLヘッダーで異なるエンコーディングを使用してそれを解決しようとしたが、それはまだ文字列を分割:XMLのPHP XMLパーサーxml_set_default_handlerは特殊文字を分割します

$parser = xml_parser_create(); 
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1"); 
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 

xml_set_element_handler($parser, "startTag", "endTag"); 
xml_set_default_handler($parser, 'defaultHandler'); 


function startTag($p, $name, $attributes) 
{ 

} 

function endTag($p, $name) 
{ 

} 

function defaultHandler($parser, $data) 
{ 
    if(strlen(trim($data)) > 0) 
     echo '[' . $data . ']' . '<br />'; 
}                               

例:

<variable name="GZH29" type="integer"> 
    <label>This is a small test with a special ë character. Let's try an ë character too</label> 
</variable> 

一つが期待します:

[This is a small test with a special ë character. Let's try an ë character too] 

しかし、結果は

[This is a small test with a special ] 
[ë character. Let's try an ë character too] 
です

私はラインを分割したくないので、解決策は何ですか?

答えて

0

xml_parserここで私が最後に完全に理解していなかった理由で複数のイベントが作成されますが、これはエンコードの自動検出のためだと思います。

独自のパーサークラスを作成することで対応できます。これは、とにかく、この場合だけでなく、一般に有用です。しかし、この場合は特に、複数のイベントで配布されるラベルのテキストをまとめることができます。

基本的な作業は、コールバック関数をクラスの公開関数にして、これらの関数を登録することです。

次に、labelタグが開くたびに、一時ストアがリセットされます。テキストが表示されると、そのテンポラリストアに追加されます。

$variableParser = new VariableParser($parser); 

$file = 'data://,'.$xml; 
$fp = fopen($file, 'r'); 
while(!feof($fp)) { $data = fread($fp, 4096); xml_parse($parser, $data, feof($fp)); } 


class VariableParser 
{ 
    private $label = ''; # place for the label text 
    public function doLabel($text) 
    { 
     printf("[%s]<br />\n", $text); 
    } 
    public function __construct($parser = NULL) 
    { 
     if ($parser) $this->register($parser); 
    } 
    public function register($parser) 
    { 
     xml_set_element_handler($parser, array($this, "startTag"), array($this, "endTag")); 
     xml_set_default_handler($parser, array($this, 'defaultHandler')); 
    } 

    public function startTag($parser, $name, $attributes) 
    { 
     if ($name === 'label') $this->label = ''; 
    } 

    function endTag($parser, $name) 
    { 
     if ($name === 'label') 
     { 
      $this->doLabel($this->label); 
      $this->label = ''; 
     } 
    } 

    function defaultHandler($parser, $data) 
    { 
     if(strlen(trim($data)) > 0) 
     { 
      $this->label .= $data; 
     } 
    } 
} 
+0

私はXMLの各 'label'タグを抽出したいと思います:labelタグは、その後閉じた場合は、新しい「イベント」この時にあなたはそれがテキストだと探している機能を、このテキストを渡すことができます文字列に変換してデータベースに挿入します。私は 'xml_set_character_data_handler'でも試しましたが、同じ結果が得られます。これは1000個の 'variable'タグと' label'タグを含む大きなXMLファイルです。 – Postie

+0

おそらくオプション:ターゲットのエンコーディングをUTF-8に設定します。すべての文字を持ち、エンティティは必要ありません。また、UTF-8としてテキストを取得した後は、ISO-8859-1に再エンコードします。テキストのすべての文字をLatin-1としてデータベースに挿入することはできません。実用的に聞こえる? – hakre

+0

私はターゲットとソースのエンコーディングをいくつか試しました。 XMLエンコーディングをUTFに変更しましたが、それでも機能しませんでした。最初の特殊文字だけが壊れるのは不思議です。 PHPのXMLReaderクラスを認識できませんでした。このクラスを使用するコードが変更されましたが、これは問題ありません。 – Postie

関連する問題