【问题标题】:How to get an element from simplexml [duplicate]如何从simplexml中获取元素[重复]
【发布时间】:2026-01-11 10:25:02
【问题描述】:
SimpleXMLElement Object
(
    [SMSMessage] => SimpleXMLElement Object
        (
            [Sid] => xyz
            [DateUpdated] => 2013-05-02 18:43:19
            [DateCreated] => 2013-05-02 18:43:19
            [DateSent] => 1970-01-01 05:30:00
            [AccountSid] => xx
            [To] => 09011148771
            [From] => xx
            [Body] => Hello
            [BodyIndex] => SimpleXMLElement Object
                (
                )

            [Status] => sending
            [Direction] => outbound-api
            [Price] => SimpleXMLElement Object
                (
                )

            [ApiVersion] => SimpleXMLElement Object
                (
                )

            [Uri] => /v1/Accounts/xx/Sms/Messages/xyz
        )

)

我试过了:

$xml->Sid;

但它返回SimpleXMLElement Object ( )

我也尝试了$xml->title,它也返回了相同的SimpleXMLElement Object ( )

如何从上述XMl获取Sid

【问题讨论】:

  • 试试 $xml->SMSMessage->Attributes('Sid');
  • @Archie.bpgc:不,请参阅simplexml basic usage in the PHP Manual。它很好地解释了这一点,请参见示例 #1 和 #2。
  • @aleation:是的,有很多魔法。这意味着,更好地阅读基本用法示例once。然后在这里搜索关于 SO 的问题。我们在较早的答案中有一些更好的答案,而在较新的答案中则很少(并不是说它们通常不好,但通常会快速输入)。如果我认为合适,我什至会编辑旧答案并为它们添加新方法,以便让这里变得更好。
  • 这篇文章可能也很有趣:SimpleXML - echo / print_r return different values - 只是因为print_rSimpleXML 并不总是因为魔法而直接相互工作.
  • 我同意@hakre 关于阅读手册和以前的问题所说的一切,并会为我的调试功能添加我常用的插件,这些插件试图比print_r 做得更好,代表了SimpleXML:github.com/IMSoP/simplexml_debug

标签: php xml simplexml


【解决方案1】:

我一直在摆弄并重新创建了一个类似于你的结构:

$string='<?xml version="1.0"?>
<xml>
    <SMSMessage>
        <Sid>xyz</Sid>
        <DateUpdated>2013-05-02 18:43:19</DateUpdated>
    </SMSMessage>
</xml>';

$xml = new SimpleXMLElement($string);

print_r($xml);

这个输出:

SimpleXMLElement Object
(
    [SMSMessage] => SimpleXMLElement Object
    ( 
        [Sid] => xyz
        [DateUpdated] => 2013-05-02 18:43:19
    )
)

这和你的一样。我可以打印 xyz :

echo $xml->SMSMessage->Sid;

试试看,你可能缺少一些父节点或其他东西。

【讨论】:

    【解决方案2】:

    您的方法:要按照您想要的方式进行操作,我认为您的调用必须更进一步,因为 SimpleXMLObject 是另一个 SimpleXMLObject 的父级。例如。 $xml-&gt;SMSMessage-&gt;Sid;。我一般推荐使用带有 XML 的 xpath,因为在大多数情况下,您希望直接跳转到特定节点而不是遍历整个 XML 树。例如:$xml-&gt;xpath('//[node]')$xml-&gt;tier1-&gt;tier2-&gt;tier3-&gt;etc 快。

    首选方法:假设 $xml 代表您发布的 SimpleXMLObject,您可以像这样访问 Sid:$xml-&gt;xpath('//Sid');。这应该直接跳到树中的“Sid”节点。

    【讨论】:

    • 显然,这是一个见仁见智的问题,但我完全不同意 XPath。大多数时候你绝对想知道文档的结构,因为在其他地方可能有另一个同名的节点,你可以放心地忽略。
    • 这不是见仁见智的问题。这个:$xml-&gt;xpath('//[node]') 比这个:$xml-&gt;tier1-&gt;tier2-&gt;tier3 更容易和更干净的节点访问。总有一个 API 可能具有更简单的结构,但在大多数情况下,尤其是付费 API 服务,有很多不必要的 XML 样板。欢迎您尝试提供更好的替代方案,并说明为什么 xpath 不优于手动访问方法。
    • @cwscribner:是的,xpath 很舒服,但我认为这不是@IMSoP 的问题所在。恕我直言,我认为您应该了解这两种方法。如果您需要它在示例中未显示的不同,“正确”示例也将是 -$xml-&gt;xpath('tier1/tier2/tier3/etc')。所以在这里比较两种不同的东西是不公平的。只是说,xpath 很好。我经常使用它。
    • XPath 不比使用 SimpleXML 之类的 API 遍历更“手动”;您的示例中的不同之处在于它是搜索,而不是遍历。两者都有自己的位置,但它们不等价,使用搜索当然并不总是“更干净”。考虑$doc-&gt;xpath('//Title'); - 如果文档有一个Title 节点,这很好,但如果稍后在每个部分添加Title,它就会变得模棱两可。 $doc-&gt;CoverPage-&gt;Title,OTOH,准确显示正在访问的内容,并且更能抵抗文档其他地方的意外更改。
    • @IMSoP 从经验上讲,与键入每个单独的节点相比,在键入和代码格式方面的手动操作更少。这不是你可以争论的。就歧义而言,这更多是 SimpleXMLElement Object 默认行为的错误。如果多个标题节点嵌套在同一级别,它们将组合成一个标题数组。对于同一级别的任何节点名称都是如此。因此,使用 xpath 不会加剧歧义。 xpath 实际上将目标节点分解为单个对象,然后可以对其进行操作。这就是为什么 xpath 更可取的原因。
    【解决方案3】:

    simplexml 中,你总是需要转换你的价值观——所以你必须这样做:

    echo $xml->Sid;
    

    (回声自动投射)。或明确:

    $string = (string) $xml->id;
    

    【讨论】:

    • 请注意,echo 不是函数,因此您不需要这些括号。 (不必要地添加它们会导致人们误解代码,因为 PHP 不会按照您的想法对待它们。)
    • 哦,echo 也是需要将值转换为字符串的最糟糕示例,因为它明确具有字符串上下文,因此会自动为您转换任何值。
    【解决方案4】:

    如果你有:

    $string='<?xml version="1.0"?>
    <xml>
        <SMSMessage>
            <Sid>xyz</Sid>
            <DateUpdated>2013-05-02 18:43:19</DateUpdated>
        </SMSMessage>
    </xml>';
    
    $xml = new SimpleXMLElement($string);
    
    print_r('<pre>');
    $Sid = (array)($xml->SMSMessage->Sid);
    print_r($Sid[0]);
    print_r($xml);
    

    您可以像这样访问 Sid $Sid = (array)(xml-&gt;SMSMessage-&gt;Sid); echo $Sid[0]; 但如果你更喜欢使用数组,你可以这样做:

    $string='<?xml version="1.0"?>
    <xml>
        <SMSMessage>
            <Sid>xyz</Sid>
            <DateUpdated>2013-05-02 18:43:19</DateUpdated>
        </SMSMessage>
    </xml>';
    
    $array= json_decode(json_encode(new SimpleXMLElement($string)), true);
    
    print_r('<pre>');
    print_r($array['SMSMessage']['Sid']);
    print_r($array);
    

    【讨论】:

    • 不知道为什么你会纠结于将所有内容都转换为数组。 SimpleXML 被设计成一种非常有效和自然的遍历 XML 文档的方式;将整个事物转换为其他结构在某种程度上违背了这一点。