XML 解析使用但元素名称是动态的 [英] XML parsing using but Element Names are Dynamic

查看:20
本文介绍了XML 解析使用但元素名称是动态的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Simple XMLElement Object
(    
         [IpStatus] => 1    
         [ti_pid_20642] => SimpleXmlElement Object    
               (

我有一个上述格式的 SimpleXMLElment,这个 XML 是在运行时生成的,它的节点值如 ti_pid_20642 部分是动态的,例如 ti_pid_3232ti-pid_2323, ti_pid_anyumber.

I have a SimpleXMLElment in above format and this XML is generated at run time and it's node values like ti_pid_20642 are partly dnymaic, for example ti_pid_3232, ti-pid_2323, ti_pid_anyumber.

我的问题是如何使用 PHP 获取这些节点值及其子节点?

My question is how can I get these nodes values and it's children using PHP?

推荐答案

要使用 SimpleXML 获取 XML string 中使用的所有节点名称,您可以使用 SimpleXMLIterator:

To get all node names that are used in an XML string with SimpleXML you can use the SimpleXMLIterator:

$tagnames = array_keys(iterator_to_array(
    new RecursiveIteratorIterator(
        new SimpleXMLIterator($string)
        , RecursiveIteratorIterator::SELF_FIRST
    )
));

print_r($tagnames);

这可以给你示范(你没有在你的问题中给出任何 XML,Demo):

Which could give you exemplary (you did not give any XML in your question, Demo):

Array
(
    [0] => IpStatus
    [1] => ti_pid_20642
    [2] => dependend
    [3] => ti-pid_2323
    [4] => ti_pid_anyumber
    [5] => more
)

如果您在提供包含有效 XML 的字符串时遇到问题,请使用现有的 SimpleXMLelement 并创建一个 XML 字符串.它:

If you have problems to provide a string that contains valid XML, take your existing SimpleXMLelement and create an XML string out of it:

$string = $simpleXML->asXML();

但是,如果您想从 SimpleXML 对象中获取所有标记名,但又不想将其转换为字符串,您也可以为 SimpleXMLElement 创建一个递归迭代器:

However, if you like to get all tagnames from a SimpleXML object but you don't want to convert it to a string, you can create a recursive iterator for SimpleXMLElement as well:

class SimpleXMLElementIterator extends IteratorIterator implements RecursiveIterator
{
    private $element;

    public function __construct(SimpleXMLElement $element) {
        parent::__construct($element);
    }

    public function hasChildren() {
        return (bool)$this->current()->children();
    }

    public function getChildren() {
        return new self($this->current()->children());
    }
}

它的用法是类似的(Demo):

The usage of it would be similar (Demo):

$it      = new RecursiveIteratorIterator(
    new SimpleXMLElementIterator($xml), RecursiveIteratorIterator::SELF_FIRST
);
$tagnames = array_keys(iterator_to_array($it));

这取决于你需要什么.

这变得不那么直接了,带有命名空间的元素.取决于您是只想获取本地名称还是 namspace 名称,甚至是带有标记名的命名空间 URI.

This becomes less straight forward, with namespaced elements. Depending if you want to get the local names only or the namspace names or even the namespace URIs with the tagnames.

可以更改给定的 SimpleXMLElementIterator 以支持跨命名空间的元素迭代,默认情况下 simplexml 仅提供对默认命名空间中元素的遍历:

The given SimpleXMLElementIterator could be changed to support the iteration over elements across namespaces, by default simplexml only offers traversal over elements in the default namespace:

/**
 * SimpleXMLElementIterator over all child elements across namespaces 
 */
class SimpleXMLElementIterator extends IteratorIterator implements RecursiveIterator
{
    private $element;

    public function __construct(SimpleXMLElement $element) {
        parent::__construct(new ArrayIterator($element->xpath('./*')));
    }

    public function key() {
        return $this->current()->getName();
    }

    public function hasChildren() {
        return (bool)$this->current()->xpath('./*');
    }

    public function getChildren() {
        return new self($this->current());
    }
}

然后您需要检查每个元素的命名空间 - 例如,使用命名空间的修改后的 XML 文档:

You would then need to check for the namespace per each element- As an example a modified XML document making use of namespaces:

<root xmlns="namspace:default" xmlns:ns1="namespace.numbered.1">
    <ns1:IpStatus>1</ns1:IpStatus>
    <ti_pid_20642>
        <dependend xmlns="namspace:depending">
            <ti-pid_2323>ti-pid_2323</ti-pid_2323>
            <ti_pid_anyumber>ti_pid_anyumber</ti_pid_anyumber>
            <more xmlns:ns2="namspace.numbered.2">
                <ti_pid_20642 ns2:attribute="test">ti_pid_20642</ti_pid_20642>
                <ns2:ti_pid_20642>ti_pid_20642</ns2:ti_pid_20642>
            </more>
        </dependend>
    </ti_pid_20642>
</root>

结合上面的更新SimpleXMLIterator,下面的示例代码演示了新的行为:

Combined with the update SimpleXMLIterator above the following example-code demonstrates the new behavior:

$xml = new SimpleXMLElement($string);
$it  = new RecursiveIteratorIterator(
    new SimpleXMLElementIterator($xml), RecursiveIteratorIterator::SELF_FIRST
);

$count = 0;
foreach ($it as $name => $element) {
    $nsList = $element->getNamespaces();
    list($ns, $nsUri) = each($nsList);
    printf("#%d:  %' -20s  %' -4s  %s\n", ++$count, $name, $ns, $nsUri);
}

输出(演示):

#1:  IpStatus              ns1   namespace.numbered.1
#2:  ti_pid_20642                namspace:default
#3:  dependend                   namspace:depending
#4:  ti-pid_2323                 namspace:depending
#5:  ti_pid_anyumber             namspace:depending
#6:  more                        namspace:depending
#7:  ti_pid_20642                namspace:depending
#8:  ti_pid_20642          ns2   namspace.numbered.2

玩得开心.

这篇关于XML 解析使用但元素名称是动态的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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