DOMXPath的构建有多贵?

时间:2013-02-26 12:33:59

标签: php xml dom xpath domdocument

在编写复杂XML文档的解析器时,我想知道在需要时构造DOMXPath实例是否可以:

function parseData($d) {
    $xpath = new DOMXPath($d);
    // ...
}

function parseMoreData($d) {
    $xpath = new DOMXPath($d);
    // ...
}

$d = new DOMDocument();
$d->loadXML($xml);
parseData($d);
parseMoreData($d);

另一种方法是在开头创建一个DOMXPath实例,然后在解析器中的任何地方重用它:

function parseData($d, $xpath) {
    // ...
}

function parseMoreData($d, $xpath) {
    // ...
}

$d = new DOMDocument();
$d->loadXML($xml);
$xpath = new DOMXPath($d);
parseData($d, $xpath);
parseMoreData($d, $xpath);

2 个答案:

答案 0 :(得分:2)

在需要时创建DOMXpath实例是可以的,PHP中的这些内置类没有太多开销。特别是对于DOMDocument / DOMXpath,它们只包含了libxml的功能。

因此,您打开了多少(不同)文档,而不是您创建了多少DOMXpath个对象。

而不是将DOMDocument传递给解析函数:

function parseData(DOMDocument $doc) 
{
    $xpath = new DOMXPath($doc);

    // ...
}

您可以传递xpath - 它也包含文档:

function parseData(DOMXpath $xpath) 
{
    $doc = $xpath->document;

    // ...
}

因此,在技术上根本不需要具有两个函数参数的替代示例。由于您只关注这个细节,最后一个建议应该解决您的“问题”。

请记住,当您遇到真正的问题时,通常只需要关心性能。这里的代码只是通过注入要操作的对象而不是在函数内创建它来改进。这就是所谓的依赖注入和编写代码的更好方法:函数应该询问(读取:有一个参数)他们需要什么,而不是自己创建它。他们应该专注于工作(这里解析数据)而不是首先实例化DOMXPath


O(1)(Big O表示法)的问题。

new DOMXpath($doc)有多贵?是O(1)吗?在评论中,我基于我从经验和理解中得到的知识回答了这个问题。

现在我也看了一下lxr。当创建新的DOMXPathconstructor in PHP-C-Code)时,它只是libxml中结构的包装器(DOMDocument扩展名的基础C库):xmlXPathContext。< / p>

所有这些代码看起来非常简单,只能读取/设置单个值(而不是misc大小列表等),所以我现在说是的,确实创建DOMXPathO(1)

答案 1 :(得分:0)

您的替代方案当然更有效,因为它不会重建一个domXpath。 但是你要记住的是,你需要的唯一对象是DomXPath。 如您所见,DOMXpath的构造函数仅依赖于您提供给他的DOMDocument实例。因此,如果您的函数仅将DOMXpath作为参数,那么它将是相同的。

您可以使用$xpath->document

访问xpath的文档

然后,就像你想要的那样,你赢得的表现并不那么重要,只有252字节。

关于您将采取的时间,只有在您使用大文件时它才会变得重要,因为解析时间比任何其他处理更重要,并且每次启动DOMXPath时。 解决方案可以是使用工厂模式:

class XPathFactory{
    private static instances=array();
    public static function getXPath($doc,$namespacePrefix){
        if(!isset(self::$instances[spl_object_hash($doc).$namespacePrefix]){
           self::$instances[spl_object_hash($doc).$namespacePrefix] = new DOMXPath($doc);
           self::$instances[spl_object_hash($doc).$namespacePrefix]->registerNamespace($namespacePrefix);
         }
         return self::$instances[spl_object_hash($doc).$namespacePrefix];
    }
 }

然后在你的功能中你只需要打电话:

 XPathFactory::getXPath($doc,$namespace);

你会得到很好的XPAth而不会过多地实现。