我需要有关 SimpleXML 调用递归函数(列出元素名称和属性)的帮助。创建 XML 配置文件系统,但每个脚本都有自己的配置文件以及新的命名约定。所以我需要的是一种简单的方法来映射所有具有属性的元素,所以就像示例 1 中一样,我需要一种简单的方法来调用所有进程,但我不知道如何在不硬编码元素名称的情况下做到这一点函数调用。有没有办法递归调用函数来匹配子元素名称?我确实看到了 xpath 功能,但我不知道如何将其用于属性。
示例中的 XML 看起来是否正确?我可以像这样构造我的 XML 吗?
示例1:
<application>
<processes>
<process id="123" name="run batch A" />
<process id="122" name="run batch B" />
<process id="129" name="run batch C" />
</processes>
<connections>
<databases>
<database usr="test" pss="test" hst="test" dbn="test" />
</databases>
<shells>
<ssh usr="test" pss="test" hst="test-2" />
<ssh usr="test" pss="test" hst="test-1" />
</shells>
</connections>
</application>
示例2:
<config>
<queues>
<queue id="1" name="test" />
<queue id="2" name="production" />
<queue id="3" name="error" />
</queues>
</config>
伪代码:
// Would return matching process id
getProcess($process_id) {
return the process attributes as array that are in the XML
}
// Would return matching DBN (database name)
getDatabase($database_name) {
return the database attributes as array that are in the XML
}
// Would return matching SSH Host
getSSHHost($ssh_host) {
return the ssh attributes as array that are in the XML
}
// Would return matching SSH User
getSSHUser($ssh_user) {
return the ssh attributes as array that are in the XML
}
// Would return matching Queue
getQueue($queue_id) {
return the queue attributes as array that are in the XML
}
编辑:
我可以传递两个参数吗?关于您建议的第一种方法@Gordon
我刚刚得到它,谢谢,见下文
public function findProcessById($id, $name)
{
$attr = false;
$el = $this->xml->xpath("//process[@id='$id'][@name='$name']"); // How do I also filter by the name?
if($el && count($el) === 1) {
$attr = (array) $el[0]->attributes();
$attr = $attr['@attributes'];
}
return $attr;
}
最佳答案
XML 对我来说看起来不错。我唯一不会做的就是将 name 设为 process 中的一个属性,因为它包含空格并且应该是一个文本节点(在我看来)。但由于 SimpleXml 没有提示它,我想这可以归结为个人喜好。
我可能会使用 DataFinder 类来解决这个问题,封装 XPath 查询,例如
class XmlFinder
{
protected $xml;
public function __construct($xml)
{
$this->xml = new SimpleXMLElement($xml);
}
public function findProcessById($id)
{
$attr = false;
$el = $this->xml->xpath("//process[@id='$id']");
if($el && count($el) === 1) {
$attr = (array) $el[0]->attributes();
$attr = $attr['@attributes'];
}
return $attr;
}
// ... other methods ...
}
然后使用它
$finder = new XmlFinder($xml);
print_r( $finder->findProcessById(122) );
输出:
Array
(
[id] => 122
[name] => run batch B
)
XPath 教程:
另一种方法是使用 SimpleXmlIterator迭代元素。 Iterators可以是decorated与其他迭代器一起使用,所以你可以这样做:
class XmlFilterIterator extends FilterIterator
{
protected $filterElement;
public function setFilterElement($name)
{
$this->filterElement = $name;
}
public function accept()
{
return ($this->current()->getName() === $this->filterElement);
}
}
$sxi = new XmlFilterIterator(
new RecursiveIteratorIterator(
new SimpleXmlIterator($xml)));
$sxi->setFilterElement('process');
foreach($sxi as $el) {
var_dump( $el ); // will only give process elements
}
您必须添加更多方法才能使过滤器适用于属性,但这是一项相当简单的任务。
SplIterator 简介:
关于PHP SimpleXML 递归函数列出子项和属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2380755/