从SimpleXML访问@attribute

151

我无法访问SimpleXML对象中的@attribute部分。当我使用var_dump查看整个对象时,输出是正确的;当我var_dump其他对象(嵌套标记)时,输出也是正确的。但是,当我按照文档中的方法使用var_dump $xml->OFFICE->{'@attributes'}时,输出为空对象,尽管第一个var_dump明确显示有属性可输出。

请问有人知道我这里做错了什么吗?或者有什么办法可以解决这个问题吗?


5
var_dump()在SimpleXML中容易产生误导,不要直接按照它的输出结果来理解。同时,你也可以使用数组访问语法来获取属性值,例如 $xml->OFFICE['MyAttribute']。 - Frank Farmer
如果想使用 ['@attributes'],你需要先将 SimpleXMLElement 转换为数组。 - Enrique
10个回答

161

试试这个

$xml->attributes()->Token

3
这个问题已经被 @Artefacto 回答过了。 - hakre
2
是的,这是最优雅的解决方案。 - Christian
我已经尝试过这个,但是我认为页面崩溃了。下面的Bora似乎认为这是错误的格式,而我此时也同意他的看法。然而,我已经多次看到这种(你的)格式被提及。我是否错过了一些微妙之处? - Gerard ONeill
2
@GerardONeill,我不明白为什么Bora说这是访问属性的错误方式,它运行得非常完美。你可能忽略了需要在XML中对应正确标签的对象上调用attributes()。例如,如果你有<root><tag attr="a">b</tag></root>,那么你需要使用$xml->tag->attributes()->attr来访问它。 - zysoft
这对我来说返回了null,可能不是因为答案错误,而是因为答案缺乏足够的解释让我正确使用它。 - Goose
显示剩余2条评论

96

您可以在XML节点上调用attributes()函数来获取XML元素的属性。然后,您可以使用var_dump函数打印该函数的返回值。

更多信息请参考php.net http://php.net/simplexmlelement.attributes

该页面提供了示例代码:

$xml = simplexml_load_string($string);
foreach($xml->foo[0]->attributes() as $a => $b) {
    echo $a,'="',$b,"\"\n";
}

9
有趣的是,$b将会成为一个SimpleXMLElement对象,所以print_rvar_dump将会输出奇怪的结果。你可以将其强制转换为字符串(或者其他任何你想要的类型)来避免这种情况发生。 - jxmallett
使用 "".$b 将其保留为字符串。 - dr_rk

72

我以前经常这样获取@attributes,但是代码会更长一些。

$att = $xml->attributes();
echo $att['field'];

这样做会更加容易,你只需一次遵循以下格式即可获取属性:

标准方式 - 数组访问属性(AAA)

$xml['field'];

其他替代品包括:

正确且快速的格式化

$xml->attributes()->{'field'};

错误的格式

$xml->attributes()->field;
$xml->{"@attributes"}->field;
$xml->attributes('field');
$xml->attributes()['field'];
$xml->attributes->['field'];

1
我同意你关于错误格式的第一个观点,因为我也遇到了页面崩溃 -- 然而很多人声称这个方法有效。你有什么解释或者细微差别吗? - Gerard ONeill
1
“Wrong formats”工作。我总是使用第一个例子。为什么它是错误的? - Grzegorz
3
从技术上讲,$xml->attributes()->{'field'}, $xml->attributes()->field, 和 $f='field'; $xml->attributes()->$f; 是相同的。我看不出为什么其中一个是正确的格式,而另一个是错误的。 - zysoft
3
$xml->attributes()->{'field'} 是正确的,因为它可以安全地用于带有特殊字符(例如"data-attr")的属性名。$xml->attributes()->field 仅适用于单个字母数字单词的属性。 - vzr
1
在使用正确选项时获取SimpleXMLElement。 - Darius.V
必须显式地将其转换为 string,以便获得 string 而不是 SimpleXMLElement(string) $xml->attributes()['attr'] - Z. Zlatev

44
$xml = <<<XML
<root>
<elem attrib="value" />
</root>
XML;

$sxml = simplexml_load_string($xml);
$attrs = $sxml->elem->attributes();
echo $attrs["attrib"]; //or just $sxml->elem["attrib"]

使用SimpleXMLElement::attributes

事实上,get_properties处理程序会严重误导 SimpleXMLElement。没有属性名为“@attributes”,因此您无法执行$sxml->elem->{"@attributes"}["attrib"]


感谢您解释 SimpleXML 为什么会以这种奇怪的方式(即 get_properties 处理程序)运行。非常有趣。 - andrewtweber
在执行此操作时获取SimpleXMLElement而不是值 - Darius.V

16

你可以直接这样做:

echo $xml['token'];

9
如果你正在寻找这些属性的列表,XPath会是你的好帮手。
print_r($xml->xpath('@token'));

4

它帮助我将simplexml_load_file($file)的结果转换为JSON结构,并解码回来:

$xml = simplexml_load_file("$token.xml");
$json = json_encode($xml);
$xml_fixed = json_decode($json);

$try1 = $xml->structure->{"@attributes"}['value'];
print_r($try1);

>> result: SimpleXMLElement Object
(
)

$try2 = $xml_fixed->structure->{"@attributes"}['value'];
print_r($try2);

>> result: stdClass Object
(
    [key] => value
)

4

不幸的是,我使用的是独特的 PHP 5.5 版本(目前只能使用 Gentoo),我发现

 $xml->tagName['attribute']

这是唯一有效的解决方案。我试过Bora提供的所有方法,包括“正确快速”格式,但它们都失败了。

虽然这是最简单的格式之一,但我不喜欢想着自己为什么要尝试其他人说可以的格式,感觉自己像疯了一样。

享受所值得的(我提到过独特的构建吗?)。


我通常建议对于与其属于同一命名空间的元素属性,使用数组符号来表示。我认为这是最简单的格式(就像你所说的那样),也是有原因的。使用具有命名键的数组访问可以表示成一个 SimpleXML 元素的属性。 - hakre

0
我想从外部 xml 文件中提取字符串(仅歌曲标题和歌手姓名):https://nostalgicfm.ro/NowOnAir.xml 这是 xml 的形式:
 <Schedule System="Jazler">
     <Event status="happening" startTime="20:31:20" eventType="song">
        <Announcement Display=""/>
      <Song title="Let It Be ">
       <Artist name="Beatles">
        <Media runTime="265.186"/>
        <Expire Time="20:35:45"/>
       </Artist>
      </Song>
     </Event>
    </Schedule>

我尝试了这段 PHP 代码,但是我不知道如何提取名称和标题...比如 "Beatles - Let It Be"

  <?php
    $url = "https://nostalgicfm.ro/NowOnAir.xml";
    $xml = simplexml_load_file($url);
    print_r($xml);
    ?>

结果是一个对象:

 SimpleXMLElement Object ( [@attributes] => Array ( [System] => Jazler ) [Event] => SimpleXMLElement Object ( [@attributes] => Array ( [status] => happening [startTime] => 20:51:21 [eventType] => song ) [Announcement] => SimpleXMLElement Object ( [@attributes] => Array ( [Display] => ) ) [Song] => SimpleXMLElement Object ( [@attributes] => Array ( [title] => If You Were A Sailboat ) [Artist] => SimpleXMLElement Object ( [@attributes] => Array ( [name] => Katie Melua ) [Media] => SimpleXMLElement Object ( [@attributes] => Array ( [runTime] => 228.732 ) ) [Expire] => SimpleXMLElement Object ( [@attributes] => Array ( [Time] => 20:55:09 ) ) ) ) ) ) 

0

问题已经解决:

<?php 
$url = 'https://nostalgicfm.ro/NowOnAir.xml'; 
$xml = simplexml_load_file($url); 
foreach ( $xml->Event->Song->Artist->attributes() as $tag => $value ); 
foreach ( $xml->Event->Song->attributes() as $tag => $value1 ) { 
echo $value." - ".$value1.PHP_EOL; } 
?>

解释你的答案 - ash
1
解释是我解决了这个问题,脚本就是上面提到的那个。显示的答案是期望的:"艺术家 - 标题"。 - petro
太好了,petro。 - ash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接