如何在使用PHP的文件夹中的多个XML文件中获取元素计数?

huangapple go评论61阅读模式
英文:

How to get element count in multiple xml files in a folder using PHP?

问题

以下是翻译好的代码部分:

<?php
$doc = new DOMDocument;
$xml = simplexml_load_file("uploads/test.xml");
//file to SimpleXMLElement 
$xml = simplexml_import_dom($xml);
print("Number of elements: ".$xml->count());    
?>
英文:

The following php script gives count of elements in a single xml file in the folder uploads. But I have number of xml files in the folder. What to modify in the following script so that I get result in tabular format with the file name and element count for all the xml files in the folder.

&lt;?php
$doc = new DOMDocument;
$xml = simplexml_load_file(&quot;uploads/test.xml&quot;);
//file to SimpleXMLElement 
$xml = simplexml_import_dom($xml);
print(&quot;Number of elements: &quot;.$xml-&gt;count());	
?&gt;

答案1

得分: 2

首先,创建一个带有你所拥有的逻辑的function

function getXML($path) {
    $doc = new DOMDocument;
    $xml = simplexml_load_file($path);
    //将文件加载为SimpleXMLElement
    $xml = simplexml_import_dom($xml);
    return $xml;
}

请注意,我:

  • 将路径转换为参数,这样你可以重复使用相同的逻辑来处理不同的文件
  • 将XML的解析与显示分开
  • 返回XML本身,这样你可以获取其计数或执行其他你可能想要的操作

这是如何获取给定路径的文件的方法:

$files = array_diff(scandir('uploads'), array('.', '..'));

我们获取了除了'.''..'之外的所有文件,这些文件肯定不会在这里感兴趣。了解更多关于scandir的信息,请参考:https://www.php.net/manual/en/function.scandir.php

成功时,你会获得一个文件名的数组,因此,让我们循环它并执行你需要的逻辑:

$xmls = [];
foreach ($files as $file) {
    if (str_ends_with($file, '.xml')) {
        $xmls[] = $file . "\t" . getXML('uploads/' . $file)->count();
    }
}
echo implode("\n", $xmls);

编辑

正如@Juan在评论部分友好地解释的那样,你可以使用以下代码:

$files = glob("./uploads/*.xml");

而不是使用scandir,这将确保我们不再需要调用array_diff,并且稍后可以避免在循环中使用if

$xmls = [];
foreach ($files as $file) {
    $xmls[] = $file . "\t" . getXML('uploads/' . $file)->count();
}
echo implode("\n", $xmls);
英文:

First, create a function with the logic you have:

function getXML($path) {
    $doc = new DOMDocument;
    $xml = simplexml_load_file($path);
    //file to SimpleXMLElement 
    $xml = simplexml_import_dom($xml);
    return $xml;
}

Note that I:

  • have converted the path into a parameter, so you can reuse the same logic for your files
  • separated the parsing of XML from showing it
  • returned the XML itself, so you can get the count or you can do whatever else you may want with it

This is how you can get the files of a given path:

$files = array_diff(scandir(&#39;uploads&#39;), array(&#39;.&#39;, &#39;..&#39;));

we get all files except for . and .., which are surely not of interest here. Read more about scandir here: https://www.php.net/manual/en/function.scandir.php

You received an array of filenames on success, so, let's loop it and perform the logic you need:

$xmls = [];
foreach ($files as $file) {
    if (str_ends_with($file, &#39;.xml&#39;)) {
        $xmls[] = $file . &quot;\t&quot; . getXML(&#39;uploads/&#39; . $file)-&gt;count();
    }
}
echo implode(&quot;\n&quot;, $xmls);

EDIT

As @Juan kindly explained in the comment section, one can use

$files = glob(&quot;./uploads/*.xml&quot;);

instead of scandir and that would ensure that we no longer need a call for array_diff and later we can avoid the if inside the loop:

$xmls = [];
foreach ($files as $file) {
    $xmls[] = $file . &quot;\t&quot; . getXML(&#39;uploads/&#39; . $file)-&gt;count();
}
echo implode(&quot;\n&quot;, $xmls);

答案2

得分: 2

你首先将XML文件加载到一个SimpleXMLElement中,然后导入到DOMElement并调用其count()方法。但是DOMElement上并没有这个方法,只有SimpleXMLElement上有。所以导入操作是不必要的。

你可以使用GlobIterator来遍历文件:

$directory = __DIR__.'/uploads';

// 获取XML文件的迭代器
$files = new GlobIterator(
  $directory.'/*.xml', FilesystemIterator::CURRENT_AS_FILEINFO
);

$results = [];
foreach ($files as $file) {
  // 使用绝对文件路径加载文件
  // 返回的SimpleXMLElement包装了文档元素节点
  $documentElement = simplexml_load_file($file->getRealPath());
  $results[] = [
    // 文件名(不包含路径)
    'file' => $file->getFilename(),
    // "SimpleXMLElement::count()" 返回元素的子元素数量
    'item-count' => $documentElement->count(),
  ];
}

var_dump($results);

使用DOM,你可以使用XPath从XML中提取特定的值:

$directory = __DIR__.'/uploads';

// 获取XML文件的迭代器
$files = new GlobIterator(
  $directory.'/*.xml', FilesystemIterator::CURRENT_AS_FILEINFO
);

// 只需要一个文档实例
$document = new DOMDocument();

$results = [];
foreach ($files as $file) {
  // 将文件加载到DOM文档中
  $document->load($file->getRealPath());
  // 为加载的文档创建XPath处理器
  $xpath = new DOMXpath($document);
  $results[] = [
    'file' => $file->getFilename(),
    // 使用XPath表达式来提取值
    'item-count' => $xpath->evaluate('count(/*/*)'),
  ];
}

var_dump($results);

XPath表达式

  • 获取文档元素 /*
  • 获取文档元素的子元素 /*/*
  • 计算它们的数量 count(/*/*)

* 是一个通用选择器,匹配任何元素节点。如果可能的话,应该更具体地使用实际的元素名称(例如 /list/item)。

英文:

You're first loading the XML file into a SimpleXMLElement then import it into a DOMElement and call the method count() on it. This method does not exists on DOMElement - only on SimpleXMLElement. So the import would not be necessary.

You can use a GlobIterator to iterate the files:

$directory = __DIR__.&#39;/uploads&#39;;

// get an iterator for the XML files
$files = new GlobIterator(
  $directory.&#39;/*.xml&#39;, FilesystemIterator::CURRENT_AS_FILEINFO
);

$results = [];
foreach ($files as $file) {
  // load file using absolute file path 
  // the returned SimpleXMLElement wraps the document element node
  $documentElement = simplexml_load_file($file-&gt;getRealPath());
  $results[] = [
    // file name without path
    &#39;file&#39; =&gt; $file-&gt;getFilename(),
    // &quot;SimpleXMLElement::count()&quot; returns the number of children of an element
    &#39;item-count&#39; =&gt; $documentElement-&gt;count(),
  ];
}

var_dump($results);

With DOM you can use Xpath to fetch specific values from the XML.

$directory = __DIR__.&#39;/uploads&#39;;

// get an iterator for the XML files
$files = new GlobIterator(
  $directory.&#39;/*.xml&#39;, FilesystemIterator::CURRENT_AS_FILEINFO
);

// only one document instance is needed
$document = new DOMDocument();

$results = [];
foreach ($files as $file) {
  // load the file into the DOM document
  $document-&gt;load($file-&gt;getRealPath());
  // create an Xpath processor for the loaded document
  $xpath = new DOMXpath($document);
  $results[] = [
    &#39;file&#39; =&gt; $file-&gt;getFilename(),
    // use an Xpath expression to fetch the value
    &#39;item-count&#39; =&gt; $xpath-&gt;evaluate(&#39;count(/*/*)&#39;),
  ];
}

var_dump($results);

The Xpath Expression

  • Get the document element /*
  • Get the child elements of the document element /*/*
  • Count them count(/*/*)

* is an universal selector for any element node. If you can you should be more specific and use the actual element names (e.g. /list/item).

huangapple
  • 本文由 发表于 2023年2月8日 19:22:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75385059.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定