Php simpleXMLElement的属性中包含什么? 问题1:以字符串形式访问innerXHTML

Php simpleXMLElement的属性中包含什么? 问题1:以字符串形式访问innerXHTML,php,xml,simplexml,Php,Xml,Simplexml,想象一下以下XML: <?xml version="1.0" encoding="utf-8" ?> <feed> <title type="text">This is my title</title> <id>123456</id> <content>Hello World</content> </feed> 但这不对,我们将只打印一个新的SimpleXMLElement,

想象一下以下XML:

<?xml version="1.0" encoding="utf-8" ?>
<feed>
  <title type="text">This is my title</title>
  <id>123456</id>
  <content>Hello World</content>
</feed>
但这不对,我们将只打印一个新的SimpleXMLElement,如下所示:

SimpleXMLElement Object
(
   [0] => 123456
)
所以我们得到一个新的对象,我猜0是它的一个属性?有两种方法看起来很自然,但都不起作用:

//throws an error
$xml = simplexml_load_file('file.xml');
print_r($xml->id->0);

//prints "SimpleXMLElement Object ( [0] => 123456 )"
$xml = simplexml_load_file('file.xml');
print_r($xml->id[0]);
这就引出了问题A:
$xml->id
的内部是什么?它有点像对象,但也有点像数组。最终,有两种方法可以访问此值:

//prints '123456'
$xml = simplexml_load_file('file.xml');
$id = (array) $xml->id;
print_r($id[0]);

//prints '123456'
$xml = simplexml_load_file('file.xml');
print_r($xml->id->__toString());
其中,第二个对我来说更“正确”,但我想知道这里到底发生了什么问题B:为什么
$xml->id
$xml->id[0]
相同?
就这一点而言,为什么
$xml->id[0]
$xml->id[0][0][0][0]
也相同

问题2:处理相同类型的多个节点 想象一下下面的XML

<?xml version="1.0" encoding="utf-8" ?>
<feed>
  <title type="text">This is my title</title>
  <tag>news</tag>
  <tag>sports</tag>
  <content>Hello World</content>
</feed>
结果如下:

SimpleXMLElement Object
(
    [0] => news
) 
这很合理,但这是我不明白的部分。我们也可以这样做:

$xml = simplexml_load_file('file.xml');
print_r($xml->tag[1]);
打印出这个:

SimpleXMLElement Object
(
    [0] => sports
) 
怎么回事?如果两个标记都在
$xml->tag
中可用,那么,问题C:为什么
不打印($xml->tag)
以下内容

SimpleXMLElement Object
(
  [0] => news  
  [1] => sports
) 
我猜
$xml->tag
意味着
$xml->tag[0]
?最终,访问所有
列表的唯一方法是使用xpath:

$xml = simplexml_load_file('file.xml');
$tags = $xml->xpath('//tag');

//$tags is now an array of objects.  We want an array of strings.
foreach ($tags as &$tag) {
  $tag = (string) $tag;
}
print_r($tags);
哪些产出:

Array
(
    [0] => news
    [1] => sports
)
但老实说,这似乎是很多代码来做一些非常简单和常见的事情。因此问题D:有没有更好的方法在PHP中从XML本机获取值列表?

问题1:以字符串形式访问innerXHTML 通过将内部XML转换为字符串,可以将其作为任何SimpleXMLElement的字符串进行访问:

print_r((string) $xml->id); # gives 123456
那么,这是如何工作的呢?这是因为在PHP中,您可以对任何对象进行编程,通过使用SimpleXMLElement是执行相同操作的内部对象

为什么
打印($xml->id)
看起来很奇怪?这是因为simplexmlement\s上的
print\r
var\u dump
都是骗子。所以不要太依赖他们SimpleXMLElement可以位于此处,因为它是一个内部对象。当我们在PHP用户空间中编写自己的对象时,它可以否认我们无法做到的规则

问题A:$xml->id的内部是什么

这只是一个simplexmlement。它的行为就像一个已经实现的对象。因此,您可以编写可以像数组一样访问的对象SimpleXMLElement也可以这样做

它还替代了对阵列的标准转换。当转换到数组时,SimpleXMLElement将遵循的确切规则有些不直观(到目前为止,我做的最好的列表是使用JSON编码,只有当您感兴趣时,因为您通常不需要那个级别的细节)

问题B:$xml->id和$xml->id[0]为什么相同

这是因为
$xml->id
是第一个
元素的别名,它的数字索引也可以访问:
$xml->id[0]
。顺便说一句,允许您访问元素本身,即使它位于单个变量中:

$id = $xml->id;

# change inner text
$id[0] = 'hello';   // $id = 'hello'; would have turned $id into a string

# remove the node from the tree
unset($id[0]);      // unset($id); would have unset the $id variable only
$id[0]
$id->{0}
符号有时也称为simplexml自引用。关于它的较长答案和更多参考是:

顺便说一句,这是不一样的。只有两种方法可以访问文档中的同一个XML节点

在这方面:
$xml->id->{0}
也可以。就像
$xml->id[0]->{0}
一样,甚至
$xml->id->{0}[0][0]->{0}[0]->{0}[0][0]->{0}[0]->{0}[0]
等等

问题2:处理相同类型的多个节点 问题C:为什么不打印($xml->tag)以下内容:

这是因为由于SimpleXML所做的简化,它不能同时做这两件事,所以它需要做一个决定。通常使用
$xml->tag
时,您希望访问名为
的第一个元素,而不是所有标记。但是,通过强制转换,您可以给SimpleXML一个您想要的提示:

通过将其转换为字符串,您基本上会说:给我第一个元素的值

(string) $xml->tag; # news
通过对数组进行强制转换,您可以说:给我所有元素的值:

(array) $xml->tag # Array([0] => news, [1] => sports)
这可能已经是你在这方面的要求了

问题D:有没有更好的方法在PHP中从XML本机获取值列表

这在很大程度上取决于你的需要。正如您所意识到的,SimpleXML中的“简单”具有很多魔力,并不总是可以直接理解。它是一个用于某种典型XML解析需求的压缩接口,但它不能区分所有情况


DOM姐妹库允许您使用基于DOMDocument的API访问更详细的信息,如果需要,通常允许更细粒度的控制。

谢谢,回答得很好。
(string) $xml->tag; # news
(array) $xml->tag # Array([0] => news, [1] => sports)