PHP » Quellcode betrachten

Download

<?php
/* xml class
 * (C) 2006 Julian von Mendel (http://derjulian.net)
 * License: LGPL
 */

class InvalidXMLException extends Exception {}

interface 
xml_widget
{
                  function 
__construct($node$xml);
    public static function 
dtd        ();
    public        function 
output     ($returntype "xhtml");
}

interface 
form_widget extends xml_widget
{
    public        function 
validate   ($get$post$files = array());
}

class 
xml
{
    protected 
$xml             "";
    public    
$beforeparsexml  False;
    public    
$data            = array();
    public    
$freeid          0;
    public    
$protocols       = array();
    private   
$forcechildnodes = array("textarea""script");
    private   
$a_inside        = array("p""li""td""th""dt""dd""div""span""h1""h2""h3""h4""h5""h6""strong""sub""sup""em");
    private   
$a_outside       = array("img");
    public    
$workafterwards  = array();
    protected 
$tags            = array();
    protected 
$replacements    = array();
    protected 
$replacementnr   0;
    public    
$doctypes        = array
    (
        
"xhtml1-strict"        => "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">",
        
"xhtml1-transitional"  => "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
    
);

    public function 
setDataItem($key$val)
    {
        
$this->data[$key] = $val;
    }

    public function 
getDataItem($key)
    {
        if (!isset(
$this->data[$key])) return False;
        return 
$this->data[$key];
    }

    public function 
getFreeID()
    {
        return 
$this->freeid++;
    }

    public function 
setBeforeParseCallback($callback)
    {
        if (!
is_callable($callback))
            return 
False;
        
$this->beforeparsexml $callback;
    }

    public function 
addReplacement($callback$key False)
    {
        if (!
is_callable($callback))
            return 
False;
        if (!
$key)
        {
            
$key "<rEpLaCeThIs".($this->replacementnr++)." />";
        }
        
$this->replacements[$key] = $callback;
        return 
$key;
    }

    public function 
addFunction($callback)
    {
        if (!
is_callable($callback))
            return 
False;
        
$this->workafterwards[] = $callback;
    }

    public function 
setProtocol($key$val)
    { 
// i. e. "callback:db://" => array($dbclass, "getvalue")
        
if (substr($key09) == "callback:" && !is_callable($val))
            return 
False;
        
$this->protocols[$key] = $val;
    }

    public function 
output($xml$returntype "xhtml"$doctype "xhtml1-strict")
    {
        foreach(
get_declared_classes() as $class)
        {
            if (
substr($class,0,4) == "xml_")
            {
                
$this->tags[] = substr($class4);
            }
        }

        
$this->returntype $returntype;
        
$this->xml        $xml;
        
$output           xml::parse($this->xml);
        
$this->xml        $output["content_string"];

        if (isset(
$this->doctypes[$doctype]))
        {
            
$doctype $this->doctypes[$doctype];
        }
        if (
$doctype != "")
        {
            
$this->xml  "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n".$doctype."\n".$this->xml;
        }

        foreach(
$this->workafterwards as $function)
        {
            
$this->xml call_user_func($function$this->xml);
        }

        foreach(
$this->replacements as $key => $val)
        {
            
$val call_user_func($val$this->xml);
            
$this->xml str_replace($key$val$this->xml);
        }

        
$this->xml str_replace(" clear=\"none\""""$this->xml);
        
$this->xml str_replace(" rowspan=\"1\" colspan=\"1\""""$this->xml);

        return 
$this->xml;
    }

    public function 
url($url)
    {
        foreach(
$this->protocols as $protocol => $replace)
        {
            if (
substr($protocol09) == "callback:")
            {
                
$callback True;
                
$protocol substr($protocol9);
            }
            else
            {
                
$callback False;
            }
            if (
substr($url0strlen($protocol)) == $protocol)
            {
                
$url substr($urlstrlen($protocol));
                if (
$callback)
                {
                    
$protocol call_user_func($replace$url);
                }
                else
                {
                    
$protocol str_replace("%s"$url$replace);
                    
$protocol str_replace("%u"urlencode($url), $protocol);
                }
                return 
$protocol;
            }
        }
        return 
$url;
    }

    public static function 
mask_xml($xml)
    {
        return 
xml::mask(utf8_encode($xml));
    }

    public static function 
mask($xml)
    {
        
$xml htmlspecialchars($xmlENT_QUOTES);
        return 
preg_replace("/&#0*39;/""&apos;"$xml);
    }

    public function 
parse($xml$onlychilds False)
    {
        
$xml call_user_func($this->beforeparsexml$xml);

        if (
substr(trim($xml), 01) != "<")
        {
            
$xml "<section toc=\"no\">".$xml."</section>";
            
$onlychilds True;
        }
        if (
substr(trim($xml), 06) != "<?xml ")
        {
            
$xml "<?xml version=\"1.0\" encoding=\"iso8859-1\" ?>\n".$xml;
        }

        
$dom = new DomDocument();
        
$dom->resolveExternals True;
        if (!
$dom->loadXML($xml))
        {
            
$xml explode("\n"self::mask($xml));
            echo 
"<pre>\n";
            
$i 1;
            foreach(
$xml as $line)
            {
                echo 
$i.": ".$line."\n";
                
$i++;
            }
            echo 
"</pre>";
            throw 
InvalidXMLException("Invalid XML.");
        }
        
$xml $this->parseNode($dom->documentElement$onlychilds);
        return 
$xml;
    }

    public function 
parseNode
    
(
        
$node                   ,
        
$onlychilds    False  ,
        
$returncontent True   ,
        
$xmlfuncs      True   ,
        
$attributes    = array(),
        
$tags          = array(),
        
$level         0
    
)
    {
        
$workthroughchilds False;
        
$content_string    ""   ;
        
$attributes_string ""     ;
        
$attributes_array  = array();
        
$tags_array        = array();
        
$childnodes        $node->childNodes;

        if (
$node->nodeType == XML_TEXT_NODE)
            
$content_string xml::mask($node->nodeValue);
        elseif (
$node->nodeType == XML_COMMENT_NODE)
            
$content_string "<!--".$node->nodeValue."-->";
        elseif (
$node->nodeType == XML_CDATA_SECTION_NODE)
            
$content_string "<![CDATA[".$node->nodeValue."]]>";
        else if (
$node->nodeType == XML_ENTITY_REF_NODE)
            
$content_string $node->textContent;
        else
            
$workthroughchilds True;

        if (!
$workthroughchilds)
        {
            return array
            (
                
"content_string"    => $content_string   ,
                
"attributes_string" => $attributes_string,
                
"attributes_array"  => $attributes_array ,
                
"tags_array"        => $tags_array
            
);                                                      
        }

        foreach(
$childnodes as $child)
        {
            if (
$child->nodeName == "parentattr")
            {
                
$content self::parseNode
                
(
                    
$child       ,
                    
True         ,
                    
True         ,
                    
$xmlfuncs
                
);
                
$attributes_array[$child->getAttribute("name")] = $this->url($content["content_string"]);
            }
            else if (
$tags == "*" || in_array($child->nodeName$tags))
            {
                if (
$child->nodeName[0] == "#") continue;
                if (
$level == 0)
                {
                    
$data $this->parseNode
                    
(
                        
$child       ,
                        
True         ,
                        
True         ,
                        
$xmlfuncs
                    
);
                }
                else
                {
                    
$data $this->parseNode
                    
(
                        
$child       ,
                        
True         ,
                        
True         ,
                        
$xmlfuncs    ,
                        array()      ,
                        
"*"          ,
                        
$level 1
                    
);
                    
$data["content_string"] = $data["tags_array"];
                }
                if (!isset(
$tags_array[$child->nodeName]))
                    
$tags_array[$child->nodeName] = array();
                
$tags_array[$child->nodeName][] = array("content" => $data["content_string"], "attributes" => $data["attributes_array"], "node" => $child);
            }
            else if (
$returncontent && $xmlfuncs && in_array($child->nodeName$this->tags))
            {
                
$class   "xml_".$child->nodeName;
                
$class   = new $class($child$this);
                
$output  $class->output($this->returntype);
                if (
is_array($output) && isset($output["reparse"]))
                {
                    
$output  $this->parse("<test>".$output["output"]."</test>"True);
                    
$output  $output["content_string"];
                }
                
$content_string .= $output;
            }
            elseif (
$returncontent)
            {
                
$data $this->parseNode
                
(
                    
$child       ,
                    
False        ,
                    
True         ,
                    
$xmlfuncs    ,
                    
$attributes
                
);
                
$content_string .= $data["content_string"];
            }
        }
        if (
is_object($node->attributes))
        {
            for(
$i=0$attribute $node->attributes->item($i); $i++)
            {
                if (!
$attribute)
                {
                    break;
                }
                
$attributes_array[$attribute->nodeName] = $this->url($attribute->nodeValue);
            }
        }

        
$inside  in_array($node->nodeName$this->a_inside );
        
$outside in_array($node->nodeName$this->a_outside);

        if (
is_array($attributes))
        {
            foreach(
$attributes_array as $key => $val)
            {
                if (
in_array($key$attributes) || (($inside || $outside) && $key == "href"))
                {
                    continue;
                }
                
$attributes_string .= " ".$key."=\"".self::mask($val)."\"";
                unset(
$attributes_array[$key]);
            }
            foreach(
$attributes as $key)
            {
                if (!isset(
$attributes_array[$key]))
                {
                    
$attributes_array[$key] = "";
                }
            }
        }
        if (!
$onlychilds)
        {
            if (
$content_string == "" && !in_array($node->nodeName$this->forcechildnodes))
            {
                
$content_string $this->href("<".$node->nodeName.$attributes_string." />"""$attributes_array);
            }
            else
            {
                if (
$inside || $outside)
                {
                    
$xml_string "<".$node->nodeName.$attributes_string.">%s</".$node->nodeName.">";
                    
$content_string $this->href($xml_string$content_string$attributes_array$inside);
                }
                else
                {
                    
$content_string "<".$node->nodeName.$attributes_string.">".$content_string."</".$node->nodeName.">";
                }
            }
        }

        return array
        (
            
"content_string"    => $content_string   ,
            
"attributes_string" => $attributes_string,
            
"attributes_array"  => $attributes_array ,
            
"tags_array"        => $tags_array
        
);
    }

    public function 
attributes($node$attributes = array())
    {
        return 
$this->parseNode($nodeTrueFalseTrue$attributes);
    }

    public function 
href($xml$content$attributes$child False)
    {
        if (!isset(
$attributes["href"]) || $attributes["href"] == "")
        {
            
$xml str_replace("%s"$content$xml);
            return 
$xml;
        }
        
$rule "<a href=\"".self::mask($this->url($attributes["href"]))."\">%s</a>";
        if (!
$child)
        {
            
$xml str_replace("%s"$content$xml );
            
$xml str_replace("%s"$xml    $rule);
            return 
$xml;
        }
        
$xml str_replace("%s"$rule   $xml);
        
$xml str_replace("%s"$content$xml);
        return 
$xml;
    }
}
?>

© 2009 Julian von Mendel (http://derjulian.net) | Datum: 19.04.2024