PHP SimpleXML递归函数列出子代和属性 [英] PHP SimpleXML recursive function to list children and attributes

查看:90
本文介绍了PHP SimpleXML递归函数列出子代和属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在SimpleXML调用上需要一些帮助,该调用列出了元素名称和属性的递归函数。创建一个XML配置文件系统,但每个脚本都将拥有自己的配置文件以及新的命名约定。因此,我需要一种简单的方法来映射具有属性的所有元素,因此像示例1中一样,我需要一种简单的方法来调用所有过程,但是如果不对元素名称进行硬编码,我不知道如何做到这一点。函数调用。有没有一种方法可以递归调用函数以匹配子元素名称?我确实看到了xpath功能,但没有看到如何将其用于属性。

I need some help on the SimpleXML calls for a recursive function that lists the elements name and attributes. Making a XML config file system but each script will have it's own config file as well as a new naming convention. So what I need is an easy way to map out all the elements that have attributes, so like in example 1 I need a simple way to call all the processes but I don't know how to do this without hard coding the elements name is the function call. Is there a way to recursively call a function to match a child element name? I did see the xpath functionality but I don't see how to use this for attributes.

示例中的XML看起来也正确吗?我可以这样构造XML吗?

Also does the XML in the examples look correct? can I structure my XML like this?

示例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

Can I pass two parms? on the first method you have suggested @Gordon

我刚得到它,thnx,请参见下文

I just got it, thnx, see below

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 中的一个属性,因为它包含空格并且应该是一个textnode(我认为)。但是由于SimpleXml没有抱怨,所以我认为它归结为个人喜好。

The XML looks good to me. The only thing I wouldn't do is making name an attribute in process, because it contains spaces and should be a textnode then (in my opinion). But since SimpleXml does not complain about it, I guess it boils down to personal preference.

我可能会用DataFinder类来实现这一点,封装XPath查询,例如

I'd likely approach this with a DataFinder class, encapsulating XPath queries, e.g.

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教程:

  • http://www.w3schools.com/XPath/default.asp

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

An alternative would be to use SimpleXmlIterator to iterate over the elements. Iterators can be decorated with other Iterators, so you can do:

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
}

您将不得不添加更多方法具有属性的过滤器工作,但这是一个相当琐碎的任务。

You would have to add some more methods to have the filter work for attributes, but this is a rather trivial task.

SplIterators简介:

Introduction to SplIterators:

  • http://www.phpro.org/tutorials/Introduction-to-SPL.html

这篇关于PHP SimpleXML递归函数列出子代和属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆