【问题标题】:XML parsing using but Element Names are DynamicXML 解析使用但元素名称是动态的
【发布时间】:2012-11-04 17:44:48
【问题描述】:
Simple XMLElement Object
(    
         [IpStatus] => 1    
         [ti_pid_20642] => SimpleXmlElement Object    
               (

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

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

【问题讨论】:

  • 你得到它就像使用 simplexml 的任何其他节点一样。如果你不知道这是怎么做的,搜索这个网站应该会对你有所帮助。我这样写是因为从你的问题来看,目前还不清楚你做了什么,所以很清楚你的 programming 问题是什么。你在哪里遇到障碍?我还编辑了你的问题,检查格式化工具。
  • 我被搜索但我没有找到任何解决方案,我得到像 $xml->ti_pid_20642 这样的节点值,但我的问题是“ti_pid_20642”这个值在运行时生成,我不知道节点名称,那么我如何获得节点值?
  • 我想你不明白我的问题,我的简单问题是我不知道节点名称,所以我如何获得它的价值?
  • 如果你也不知道,为什么给我-1?
  • 可能是因为不清楚您对代码做了什么。由于这是一个关于编程问题的网站,因此通常会看到一些问题所涉及的代码。在您的情况下:XML 的一个简短示例,到目前为止您使用的 3-7 行代码(对您不起作用)和类似的东西(我没有对您投反对票,仅供参考)。

标签: php xml simplexml


【解决方案1】:

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

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

print_r($tagnames);

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

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

如果您在提供包含有效 XML 的字符串时遇到问题,请使用您现有的 SimpleXMLelement 和 create an XML string out of it

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

用法类似(Demo):

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

这取决于你需要什么。

这变得不那么直接了,带有命名空间的元素。取决于您是否只想获取本地名称或命名空间名称,甚至是带有标记名的命名空间 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);
}

输出(Demo):

#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 --- FAtAl ERROR
  • 提供一个有效的 XML 字符串。否则这将永远失败。如果你有一个SimpleXMLElement object,你需要先得到它的XML。
  • 谢谢,您的这条消息 [提供一个有效的 XML 字符串。否则这将永远失败。如果你有一个 SimpleXMLElement 对象,你需要先得到它的 XML。] 对我很有帮助。
  • @AdomsAdoms:我现在添加了一个 SimpleXMLElementIterator,它能够直接迭代 SimpleXML 对象。它有两个变体,第一个遵循 SimpleXML 的标准遍历,第二个允许遍历所有 xml 元素而不管命名空间。我把这个留作以后参考,我不知道你是否理解它。但也许它会有所帮助。
猜你喜欢
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多