PHP SimpleXML递归函数列出孩子和属性 [英] PHP SimpleXML recursive function to list children and attibutes
问题描述
我需要一些帮助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. Any ideas?
示例中的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
}
$ b b
编辑:
我可以传递两个parms吗?第一种方法你建议@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看起来不错。我唯一不会做的是在进程中创建属性,因为它包含空格,应该是一个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
}
SplIterators简介:
Introduction to SplIterators:
- http://www.phpro.org/tutorials/Introduction-to-SPL.html
这篇关于PHP SimpleXML递归函数列出孩子和属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!