【问题标题】:Incorporate XMLReader with DOMXPath in PHP在 PHP 中将 XMLReader 与 DOMXPath 结合起来
【发布时间】:2021-06-16 07:58:21
【问题描述】:

我习惯于使用DOMDocumentDOMXPath 来解析/遍历我的XML。

现在我有 2.5 MB 的 XML 文件,并且刚刚意识到 DOMDocument 在“处理”该文件时非常慢。

我用谷歌搜索了一些关于 XMLReader 的内容,他们说这是更好的方法,并且可能具有处理大型 XML 文件的最快性能

问题是我不知道如何将DOMXPathXMLReader 合并

如何将以下代码转换为XMLReader

$dom = new DOMDocument;
        $dom->load('myxml.xml');
        
        $xp = new DOMXPath($dom);
        $xp->registerNamespace('f', 'my-name-space:namespace');
        
        $expression = "//f:my-person/@name";
        $col = $xp->query($expression);

我已经这样做了,但还是很慢:

注意:这是取自该线程的假设代码:XML DOMDocument optimization。不过重点是一样的

$xmlReader = new XMLReader();
        $xmlReader->open('myxml.xml');

while ($reader->read()) {
    switch ($reader->nodeType) {
        case (XMLREADER::ELEMENT):
        if ($reader->localName == "game") {
             $node = $reader->expand();
             $dom = new DomDocument();
             $n = $dom->importNode($node,true);
             $dom->appendChild($n);
             $xp = new DOMXPath($dom);
             $xp->registerNamespace('f', 'my-name-space:namespace');
        
             $expression = "//f:my-person/@name";
             $col = $xp->query($expression);
        }
    }
}

随意建议任何 PHP 库来解决这个问题

【问题讨论】:

  • 如果您查找my-person 元素而不是game 元素,它可能会更快(无法给出任何数字)。然后,您只需要获取属性,而不必加载 XML 并使用 XPath。

标签: php xml


【解决方案1】:

XMLReader 没有针对性能进行优化 - 它是针对内存消耗的。它只允许将 XML 文件的一部分加载到内存中。

您可以扩展为准备好的文档实例。这是一个经典的书籍示例:

$xmlString = <<<'XML'
<books xmlns="urn:example-books">
  <book>
    <title isbn="978-0596100087">XSLT 1.0 Pocket Reference</title>
  </book>
  <book>
    <title isbn="978-0596100506">XML Pocket Reference</title>
  </book>
</books>
XML;

$reader = new XMLReader();
$reader->open('data:text/xml;base64,'.base64_encode($xmlString));

// prepare a document instance
$document = new DOMDocument();
$xpath = new DOMXpath($document);
// register a namespace prefix
$xpath->registerNamespace('b', 'urn:example-books');

// look for the first "book" element in the defined namespace 
while (
  $reader->read() &&
  (
    $reader->localName !== 'book' ||
    $reader->namespaceURI !== 'urn:example-books'
  )
) {
  continue;
}

// as long there is a "book" element ...
while ($reader->localName === 'book') {
  // ... in the defined namespace
  if ($reader->namespaceURI === 'urn:example-books') {
    // expand into the prepared document instance
    $book = $reader->expand($document);
    // use xpath with the context argument
    var_dump(
      $xpath->evaluate('string(b:title/@isbn)', $book),
      $xpath->evaluate('string(b:title)', $book)
    );
  }
  // go to the next book sibling element
  $reader->next('book');
}
$reader->close();

输出:

string(14) "978-0596100087"
string(25) "XSLT 1.0 Pocket Reference"
string(14) "978-0596100506"
string(20) "XML Pocket Reference"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多