PHP XML Parser xml_set_default_handler разделяет специальный символ

Синтаксический анализатор XML в PHP дважды вызывает функцию-обработчик по умолчанию, когда встречает специальный символ в строке, и поэтому разбивает строку. Я пытался решить эту проблему, используя разные кодировки в заголовке XML, а также в коде PHP, но он все равно разбивает строку:

$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 />';
}                                                                                                                        

Пример XML:

<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]

Я бы не хотел, чтобы линия была разделена, так что есть идеи, каково решение?


person Postie    schedule 02.01.2012    source источник


Ответы (1)


xml_parser действительно создает несколько событий здесь по причине, которую я окончательно не понял, я думаю, это из-за автоматического определения кодировки.

Вы можете справиться с этим, создав свой собственный класс парсера. Это вообще полезно в любом случае, не только в этом случае. Но в этом случае это особенно важно, чтобы вы могли составить текст метки, который распределяется по нескольким событиям.

Основная работа заключается в том, чтобы сделать функции обратного вызова общедоступными функциями класса и затем зарегистрировать эти функции.

Затем каждый раз, когда открывается тег label, временное хранилище сбрасывается. Когда текст появляется, он добавляется в это временное хранилище. Если тег 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;
        }
    }
}
person hakre    schedule 02.01.2012
comment
Я хотел бы извлечь каждый тег label XML в строку и вставить его в базу данных. Я также пробовал это с xml_set_character_data_handler, но это дает тот же результат. Это большой файл XML, содержащий тысячи тегов variable и label. - person Postie; 03.01.2012
comment
Вероятный вариант: установите целевую кодировку в UTF-8 - она ​​имеет все символы и не требует сущностей - и после того, как вы получили текст в виде UTF-8, перекодируйте его в ISO-8859-1, возможно, с транслитерацией, как вы хотите. не иметь возможности вставлять каждый символ текста в базу данных как Latin-1. Звучит практично? - person hakre; 03.01.2012
comment
Я пробовал несколько кодировок для цели и источника. Изменил кодировку XML на UTF, но все равно не работает. Странно, что ломается только на первом спецсимволе. Не знал о классе XMLReader в PHP, изменил код, чтобы использовать этот класс, это не вызывает проблем. - person Postie; 03.01.2012
comment
В какой кодировке находится исходный файл/строка XML? XML Reader в порядке, я скомпилировал пример кода для пошагового чтения с ним в каком-то (разном) ответе (просто для справки, можете на мгновение не обращать на это внимания). - Если вы говорите исходную кодировку, было бы неплохо знать, чтобы скомпилировать пример. Кроме того, если бы вы могли добавить код, в который вы загружаете этот файл, в свой вопрос, он также был бы более конкретным, чтобы дать лучшие предложения. - person hakre; 03.01.2012
comment
XML находится в кодировке ISO-8859-1, и это экспорт из приложения, поэтому я не могу его контролировать. Я использую код while(!feof($fp)) { $data = fread($fp, 4096); xml_parse($parser, $data, feof($fp)); } - person Postie; 03.01.2012
comment
Я тоже подумал об этом ответе, соедините строку, но потом я столкнулся с классом XmlReader в PHP, и он работает как шарм. Поэтому я переписал класс, чтобы использовать его вместо синтаксического анализатора xml. Это также немного быстрее. - person Postie; 05.01.2012
comment
Хорошо, я связал XMLReader выше;) При компиляции кода примера я сначала хотел использовать его, но подумал, что вам нужен xml_parser. Вот как жизнь играет ;) - person hakre; 05.01.2012