PHP SimpleXML递归函数,用于列出子项和属性

Phi*_*ord 2 php xml recursion configuration simplexml

我需要一些关于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>
Run Code Online (Sandbox Code Playgroud)

例2:

<config>
  <queues>
    <queue id="1" name="test" />
    <queue id="2" name="production" />
    <queue id="3" name="error" />
  </queues>
</config>
Run Code Online (Sandbox Code Playgroud)

伪代码:

// 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
}
Run Code Online (Sandbox Code Playgroud)

编辑:

我可以通过两个参赛吗?关于你建议@Gordon的第一种方法

我得到了它,thnx,见下文

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;
}
Run Code Online (Sandbox Code Playgroud)

Gor*_*don 5

XML对我来说很好看.我不会做正在唯一名称中的一个属性的过程,因为它包含空格,应该是再textnode(在我看来).但由于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 ...
}
Run Code Online (Sandbox Code Playgroud)

然后用它

$finder = new XmlFinder($xml);
print_r( $finder->findProcessById(122) );
Run Code Online (Sandbox Code Playgroud)

输出:

Array
(
    [id] => 122
    [name] => run batch B
)
Run Code Online (Sandbox Code Playgroud)

XPath教程:


另一种方法是使用SimpleXmlIterator迭代元素.迭代器可以使用其他迭代进行修饰,因此您可以执行以下操作:

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
}
Run Code Online (Sandbox Code Playgroud)

您必须添加一些方法才能使过滤器适用于属性,但这是一项相当简单的任务.

SplIterators简介: