使用XML解析,但元素的名称是动态(XML parsing using but Element Na

2019-07-03 13:15发布

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

我有上述格式的SimpleXMLElment并在运行时生成此XML和它的节点值等ti_pid_20642是部分dnymaic,例如ti_pid_3232ti-pid_2323ti_pid_anyumber

我的问题是如何获得这些节点的值,它的使用PHP的孩子吗?

Answer 1:

要获得在用SimpleXML可以使用的XML 字符串中使用的所有节点名称SimpleXMLIterator

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

print_r($tagnames);

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

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

如果您有问题需要提供包含有效的XML字符串,把你现有的SimpleXMLElement并创建一个XML字符串出来的 :

$string = $simpleXML->asXML();

不过,如果你想获得从SimpleXML对象的所有标记名,但你不希望将其转换为字符串,您可以创建一个递归迭代SimpleXMLElement还有:

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());
    }
}

它的用法是类似( 演示 ):

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

这只是取决于你所需要的。

这个问题就不那么简单的,与命名空间的元素。 根据如果你想获得仅在本地名称或namspace名称或与标记名甚至命名空间的URI。

给定SimpleXMLElementIterator可以改变以支持跨命名空间的元素迭代,默认情况下只的SimpleXML在默认命名空间的元素提供遍历:

/**
 * 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文档利用命名空间:

<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下面的示例代码上面演示了新的行为:

$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 parsing using but Element Names are Dynamic