我注意到,在下面的示例中,以及我在这个网站上看到的用于在html中查看xml的所有示例中,自闭合标签(如<br />)的外观并没有保留。解析器无法区分<tag />和<tag></tag>,如果你的开始和结束元素函数像这些示例一样,则这两个实例都将输出单独的开始和结束标签。我需要保留自闭合标签,并且花了我一段时间才找到这个解决方法。希望这对某些人有所帮助……
开始标签保持打开状态,然后由其第一个子节点、下一个开始标签或其结束标签完成。结束标签将以“ />”或</tag>结尾,具体取决于解析数据中开始和结束标签之间的字节数。
<?php
$data=<<<DATA
<normal_tag>
<self_close_tag />
data
<normal_tag>data
<self_close_tag attr="value" />
</normal_tag>
data
<normal_tag></normal_tag>
</normal_tag>
DATA;
function startElement($parser, $name, $attrs)
{
xml_set_character_data_handler($parser, "characterData");
global $first_child, $start_byte;
if($first_child) echo "><br />";
$first_child=true;
$start_byte=xml_get_current_byte_index ($parser);
if(count($attrs)>=1){
foreach($attrs as $x=>$y){
$attr_string .= " $x=\"$y\"";
}
}
echo htmlentities("<{$name}{$attr_string}"); }
function endElement($parser, $name)
{
global $first_child, $start_byte;
$byte=xml_get_current_byte_index ($parser);
if($byte-$start_byte>2){ if($first_child) echo "><br />";
echo htmlentities("</{$name}>")."<br />"; }else
echo " /><br />"; $first_child=false;
}
function characterData($parser, $data)
{
global $first_child;
if($first_child) echo "><br />";
if($data=trim($data))
echo "<font color='blue'>$data</font><br />";
$first_child=false;
}
function ParseData($data)
{
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
if(is_file($data))
{
if (!($fp = fopen($file, "r"))) {
die("无法打开XML输入");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
$error=xml_error_string(xml_get_error_code($xml_parser));
$line=xml_get_current_line_number($xml_parser);
die(sprintf("XML错误: %s 在第 %d 行",$error,$line));
}
}
}else{
if (!xml_parse($xml_parser, $data, 1)) {
$error=xml_error_string(xml_get_error_code($xml_parser));
$line=xml_get_current_line_number($xml_parser);
die(sprintf("XML错误: %s 在第 %d 行",$error,$line));
}
}
xml_parser_free($xml_parser);
}
ParseData($data);
?>