PHP的XML解析器在遇到字符串中的特殊字符时会调用默认处理函数两次,因此会拆分字符串。我试图在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]
我不想分割线,所以不知道解决方案是什么?
答案 0 :(得分:0)
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;
}
}
}