文字

XML 外部实体例程

此例程用于加亮 XML 代码。举例说明如何使用外部实体引用来包含和解析其他文档, 及处理指令是如何被处理的,及判断处理指令所包含代码是否“可信任”的一种方法

用于此例程的 XML 文档位于此例程的下方(xmltest.xmlxmltest2.xml)。

Example #1 外部实体例程

<?php
$file 
"xmltest.xml" ;

function 
trustedFile ( $file
{
    
// 仅信任本地文件
    
if (! preg_match ( "@^([a-z]+)\:\/\/@i" $file
        && 
fileowner ( $file ) ==  getmyuid ()) {
            return 
true ;
    }
    return 
false ;
}

function 
startElement ( $parser $name $attribs
{
    echo 
"&lt;<font color=\"#0000cc\"> $name </font>" ;
    if (
count ( $attribs )) {
        foreach (
$attribs  as  $k  =>  $v ) {
            echo 
" <font color=\"#009900\"> $k </font>=\"<font 
                   color=\"#990000\">
$v </font>\"" ;
        }
    }
    echo 
"&gt;" ;
}

function 
endElement ( $parser $name
{
    echo 
"&lt;/<font color=\"#0000cc\"> $name </font>&gt;" ;
}

function 
characterData ( $parser $data
{
    echo 
"<b> $data </b>" ;
}

function 
PIHandler ( $parser $target $data
{
    switch (
strtolower ( $target )) {
        case 
"php" :
            global 
$parser_file ;
            
// 如何要解析的文档是“可信任”的, 则说明可安全
            // 地执行其内部的 PHP 代码。否则,显示代码内容。
            
if ( trustedFile ( $parser_file [ $parser ])) {
                eval(
$data );
            } else {
                
printf ( "Untrusted PHP code: <i>%s</i>"
                        
htmlspecialchars ( $data ));
            }
            break;
    }
}

function 
defaultHandler ( $parser $data
{
    if (
substr ( $data 0 1 ) ==  "&"  &&  substr ( $data , - 1 1 ) ==  ";" ) {
        
printf ( '<font color="#aa00aa">%s</font>'
                
htmlspecialchars ( $data ));
    } else {
        
printf ( '<font size="-1">%s</font>'
                
htmlspecialchars ( $data ));
    }
}

function 
externalEntityRefHandler ( $parser $openEntityNames $base $systemId ,
                                  
$publicId ) {
    if (
$systemId ) {
        if (!list(
$parser $fp ) =  new_xml_parser ( $systemId )) {
            
printf ( "Could not open entity %s at %s\n" $openEntityNames ,
                   
$systemId );
            return 
false ;
        }
        while (
$data  fread ( $fp 4096 )) {
            if (!
xml_parse ( $parser $data feof ( $fp ))) {
                
printf ( "XML error: %s at line %d while parsing entity %s\n" ,
                       
xml_error_string ( xml_get_error_code ( $parser )),
                       
xml_get_current_line_number ( $parser ),  $openEntityNames );
                
xml_parser_free ( $parser );
                return 
false ;
            }
        }
        
xml_parser_free ( $parser );
        return 
true ;
    }
    return 
false ;
}

function 
new_xml_parser ( $file
{
    global 
$parser_file ;

    
$xml_parser  xml_parser_create ();
    
xml_parser_set_option ( $xml_parser XML_OPTION_CASE_FOLDING 1 );
    
xml_set_element_handler ( $xml_parser "startElement" "endElement" );
    
xml_set_character_data_handler ( $xml_parser "characterData" );
    
xml_set_processing_instruction_handler ( $xml_parser "PIHandler" );
    
xml_set_default_handler ( $xml_parser "defaultHandler" );
    
xml_set_external_entity_ref_handler ( $xml_parser "externalEntityRefHandler" );
    
    if (!(
$fp  = @ fopen ( $file "r" ))) {
        return 
false ;
    }
    if (!
is_array ( $parser_file )) {
        
settype ( $parser_file "array" );
    }
    
$parser_file [ $xml_parser ] =  $file ;
    return array(
$xml_parser $fp );
}

if (!(list(
$xml_parser $fp ) =  new_xml_parser ( $file ))) {
    die(
"could not open XML input" );
}

echo 
"<pre>" ;
while (
$data  fread ( $fp 4096 )) {
    if (!
xml_parse ( $xml_parser $data feof ( $fp ))) {
        die(
sprintf ( "XML error: %s at line %d\n" ,
                    
xml_error_string ( xml_get_error_code ( $xml_parser )),
                    
xml_get_current_line_number ( $xml_parser )));
    }
}
echo 
"</pre>" ;
echo 
"parse complete\n" ;
xml_parser_free ( $xml_parser );

?>

Example #2 xmltest.xml

<?xml version='1.0'?>
<!DOCTYPE chapter SYSTEM "/just/a/test.dtd" [
<!ENTITY plainEntity "FOO entity">
<!ENTITY systemEntity SYSTEM "xmltest2.xml">
]>
<chapter>
 <TITLE>Title &plainEntity;</TITLE>
 <para>
  <informaltable>
   <tgroup cols="3">
    <tbody>
     <row><entry>a1</entry><entry morerows="1">b1</entry><entry>c1</entry></row>
     <row><entry>a2</entry><entry>c2</entry></row>
     <row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>
    </tbody>
   </tgroup>
  </informaltable>
 </para>
 &systemEntity;
 <section id="about">
  <title>About this Document</title>
  <para>
   <!-- this is a comment -->
   <?php echo 'Hi!  This is PHP version ' . phpversion(); ?>
  </para>
 </section>
</chapter>

此文件包含在 xmltest.xml 中:

Example #3 xmltest2.xml

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY testEnt "test entity">
]>
<foo>
   <element attrib="value"/>
   &testEnt;
   <?php echo "This is some more PHP code being executed."; ?>
</foo>
上一篇: 下一篇: