SimpleXMLElement::children

(PHP 5, PHP 7, PHP 8)

SimpleXMLElement::children查找给定节点的子节点

说明

public SimpleXMLElement::children(?string $namespaceOrPrefix = null, bool $isPrefix = false): ?SimpleXMLElement

此方法查找元素的子节点。结果遵循正常的迭代规则。

注意: SimpleXML 规则是在大多数方法中添加迭代属性。它们无法使用 var_dump() 或其他任何可以检查对象的函数查看。

参数

namespaceOrPrefix

一个 XML 命名空间。

isPrefix

如果 isPrefixtrue,则 namespaceOrPrefix 将被视为前缀。如果为 false,则 namespaceOrPrefix 将被视为命名空间 URL

返回值

返回一个 SimpleXMLElement 元素,无论节点是否有子节点,除非节点代表一个属性,在这种情况下将返回 null

示例

示例 #1 遍历 children() 伪数组

<?php
$xml
= new SimpleXMLElement(
'<person>
<child role="son">
<child role="daughter"/>
</child>
<child role="daughter">
<child role="son">
<child role="son"/>
</child>
</child>
</person>'
);

foreach (
$xml->children() as $second_gen) {
echo
' The person begot a ' . $second_gen['role'];

foreach (
$second_gen->children() as $third_gen) {
echo
' who begot a ' . $third_gen['role'] . ';';

foreach (
$third_gen->children() as $fourth_gen) {
echo
' and that ' . $third_gen['role'] .
' begot a ' . $fourth_gen['role'];
}
}
}
?>

上面的示例将输出

The person begot a son who begot a daughter; The person
begot a daughter who begot a son; and that son begot a son

示例 #2 使用命名空间

<?php
$xml
= '<example xmlns:foo="my.foo.urn">
<foo:a>Apple</foo:a>
<foo:b>Banana</foo:b>
<c>Cherry</c>
</example>'
;

$sxe = new SimpleXMLElement($xml);

$kids = $sxe->children('foo');
var_dump(count($kids));

$kids = $sxe->children('foo', TRUE);
var_dump(count($kids));

$kids = $sxe->children('my.foo.urn');
var_dump(count($kids));

$kids = $sxe->children('my.foo.urn', TRUE);
var_dump(count($kids));

$kids = $sxe->children();
var_dump(count($kids));
?>
int(0)
int(2)
int(2)
int(0)
int(1)

参见

添加注释

用户贡献的注释 15 个注释

aero
17 年前
这是一个简单、递归的函数,用于将 XML 数据转换为伪 E4X 语法,即 root.child.value = foobar

<?php
error_reporting
(E_ALL);

$xml = new SimpleXMLElement(
'<Patriarch>
<name>Bill</name>
<wife>
<name>Vi</name>
</wife>
<son>
<name>Bill</name>
</son>
<daughter>
<name>Jeri</name>
<husband>
<name>Mark</name>
</husband>
<son>
<name>Greg</name>
</son>
<son>
<name>Tim</name>
</son>
<son>
<name>Mark</name>
</son>
<son>
<name>Josh</name>
<wife>
<name>Kristine</name>
</wife>
<son>
<name>Blake</name>
</son>
<daughter>
<name>Liah</name>
</daughter>
</son>
</daughter>
</Patriarch>'
);

RecurseXML($xml);

function
RecurseXML($xml,$parent="")
{
$child_count = 0;
foreach(
$xml as $key=>$value)
{
$child_count++;
if(
RecurseXML($value,$parent.".".$key) == 0) // no childern, aka "leaf node"
{
print(
$parent . "." . (string)$key . " = " . (string)$value . "<BR>\n");
}
}
return
$child_count;
}

?>

输出结果....

.name = Bill
.wife.name = Vi
.son.name = Bill
.daughter.name = Jeri
.daughter.husband.name = Mark
.daughter.son.name = Greg
.daughter.son.name = Tim
.daughter.son.name = Mark
.daughter.son.name = Josh
.daughter.son.wife.name = Kristine
.daughter.son.son.name = Blake
.daughter.son.daughter.name = Liah
Sebastian
18年前
一个小小的补充

如果你需要访问包含连字符的子节点,你需要用 {""} 将其括起来。

例如
<?php
foreach ($domain->domain-listing as $product) {
}
?>

上面的例子因为连字符而无法工作。 但你需要使用
<?php
foreach ($domain->{"domain-listing"} as $product) {
}
?>

至少对我来说,第二个例子完美地工作了。
transglobe at gmx dot de
16年前
我对 RecurseXML 函数做了稍微不同的处理。 因为我当时很饿,所以代码出了问题,它只是覆盖了两个 <maincourse>。 所以我做了以下操作

<?php

$xml
= new SimpleXMLElement(
'<meal>
<type>Lunch</type>
<time>12:30</time>
<menu>
<entree>salad</entree>
<maincourse>
<part>ships</part>
<part>steak</part>
</maincourse>
<maincourse>
<part>fisch</part>
<part>rice</part>
</maincourse>
<maincourse>
<part>wine</part>
<part>cheese</part>
</maincourse>
</menu>
</meal>'
);

$vals = array();
RecurseXML($xml,$vals);

foreach(
$vals as $key=>$value)
print(
"{$key} = {$value}<BR>\n");

function
RecurseXML($xml,&$vals,$parent="") {

$childs=0;
$child_count=-1; # Not realy needed.
$arr=array();
foreach (
$xml->children() as $key=>$value) {
if (
in_array($key,$arr)) {
$child_count++;
} else {
$child_count=0;
}
$arr[]=$key;
$k=($parent == "") ? "$key.$child_count" : "$parent.$key.$child_count";
$childs=RecurseXML($value,$vals,$k);
if (
$childs==0) {
$vals[$k]= (string)$value;
}
}

return
$childs;
}

?>
输出结果如下
type.0 = Lunch
time.0 = 12:30
menu.0.entree.0 = salad
menu.0.maincourse.0.part.0 = ships
menu.0.maincourse.0.part.1 = steak
menu.0.maincourse.0 =
menu.0.maincourse.1.part.0 = fisch
menu.0.maincourse.1.part.1 = rice
menu.0.maincourse.1 =
menu.0.maincourse.2.part.0 = wine
menu.0.maincourse.2.part.1 = cheese
menu.0.maincourse.2 =
menu.0 =

(虽然不美观,但它解决了我的问题...)
boan dot web at outlook dot com
5年前
SimpleXMLElement::children 在这种情况下可能返回 null

<?php
$xml
= '
<root attr="Hello"/>
'
;

$sxe = new SimpleXMLElement($xml);

$sxe_xpath = $sxe->xpath('/root/@attr')[0];

$children = $sxe_xpath->children();

var_export($children); // Is null
?>
Anonymous
13年前
这是我的 xml-to-array 例程。 与这里其他许多评论不同,这个例程考虑到了命名空间。

<?php

class XmlArray {

public function
load_dom ($xml) {
$node=simplexml_import_dom($xml);
return
$this->add_node($node);
}

public function
load_string ($s) {
$node=simplexml_load_string($s);
return
$this->add_node($node);
}

private function
add_node ($node, &$parent=null, $namespace='', $recursive=false) {

$namespaces = $node->getNameSpaces(true);
$content="$node";

$r['name']=$node->getName();
if (!
$recursive) {
$tmp=array_keys($node->getNameSpaces(false));
$r['namespace']=$tmp[0];
$r['namespaces']=$namespaces;
}
if (
$namespace) $r['namespace']=$namespace;
if (
$content) $r['content']=$content;

foreach (
$namespaces as $pre=>$ns) {
foreach (
$node->children($ns) as $k=>$v) {
$this->add_node($v, $r['children'], $pre, true);
}
foreach (
$node->attributes($ns) as $k=>$v) {
$r['attributes'][$k]="$pre:$v";
}
}
foreach (
$node->children() as $k=>$v) {
$this->add_node($v, $r['children'], '', true);
}
foreach (
$node->attributes() as $k=>$v) {
$r['attributes'][$k]="$v";
}

$parent[]=&$r;
return
$parent[0];

}

}

?>
Andrew Rose (rose dot andrew at gmail dot com)
19 年前
以下示例展示了使用深度优先递归遍历 XML 树的基本方法。

此代码适用于命令行,它会打印出上面的原始句子,然后打印它自己创建的模仿句子,以便进行比较,正如你将看到的,这个示例与我的预期略有不同,我将把这个问题留给你来解决。

总的来说,我个人认为 XML 和递归是相辅相成的,因此,如果你不理解递归,但了解 XML 并且想使用 PHP 来操作 XML,那么你迟早都需要学习递归。

<?php
$xml
= simplexml_load_string(
'<person>
<child role="son">
<child role="daughter"/>
</child>
<child role="daughter">
<child role="son">
<child role="son"/>
</child>
</child>
</person>'
);

function
recurse($child)
{
foreach(
$child->children() as $children) {
echo
' who begot a '.$children['role'];
recurse($children);
}
return;
}

foreach(
$xml->children() as $children) {
echo
'The person begot a '.$children['role'];
recurse($children, 0);
echo
'; ';
}

echo
"\n";
echo
'The person begot a son who begot a daughter; The person begot a daughter who begot a son; and that son begot a son'."\n";

?>
mrdaniellee at live dot com
14 年前
如果你想查看 HTML 以及数据,请使用此代码。

正常的转储会显示 HTML 的解析版本。
此代码会将 HTML 作为文本显示在文本区域中,并同时显示所有其他数据作为数组。

非常适合调试(包含 HTML 的 XML)。

尝试以下代码

<?php
$xml
= simplexml_load_file($url);

function
xml2array_parse($xml){
foreach (
$xml->children() as $parent => $child){
$return["$parent"] = xml2array_parse($child)?xml2array_parse($child):"$child";
}
return
$return;
}

print
"<pre><textarea style=\"width:200%;height:100%;\">";
print_r(xml2array_parse($xml));
print
"</textarea></pre>";
?>
Anonymous
15 年前
对于 RSS 订阅中出现的 <dc:creator> 之类的 XML 命名空间,请使用以下代码

<?php
$xml
= new SimpleXMLElement($string);
$item = $xml->channel[0]->item[0];
$dc = $item->children("http://purl.org/dc/elements/1.1/");
echo
$dc->creator;
?>
coldshine1 at rambler dot ru
13年前
这是我用来解析带属性的 XML 的递归简单函数。

<?php
function ParseXML($node, &$parent=array(), $only_child=true) {

//当前节点名称
$node_name = $node->getName();

//统计子节点数量
$only_child = true;
if(
$node->count() > 1 ) $only_child = false;

//如果没有子节点,则可能存在文本数据
if($only_child){
$content="$node";
if (
strlen($content)>0) $parent['content']=$content;
}

//获取当前节点的属性
foreach ($node->attributes() as $k=>$v) {
$parent['@attributes'][$k]="$v";
}

//获取子节点
$count = 0;
foreach (
$node->children() as $child_name=>$child_node) {
if(!
$only_child) //如果有兄弟节点,则将节点添加到数组末尾
LGServerPVR::ParseXML($child_node, $parent[$node_name][$child_name][$count], $only_child);
else
LGServerPVR::ParseXML($child_node, $parent[$node_name][$child_name], $only_child);
$count++;
}

return
$parent;
//(c) c01d[s]h!nE 10.12.2010
}

?>
thetazzbot at gmail dot com
12 年前
假设你拥有以下 XML 文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE nitf
PUBLIC "-//IPTC-NAA//DTD NITF 3.1//EN"
"http://www.nitf.org/site/nitf-documentation/nitf-3-1.dtd">
<nitf>
<head>
<docdata management-status="embargoed">
<!--data/2011/08/23/parties/doc4e53aa5783cca930694817.txt-->
<doc-id id-string="doc4e53aa5783cca930694817"/>
<date.release norm="20110823T000000"/>
<key-list/>
</docdata>
<pubdata type="web" position.section="parties" position.sequence="0"/>
</head>

-- snip --

如果你需要访问名为 "like.this" 的节点,例如上面的 date.release,可以使用以下方法:

$xml = new SimpleXMLElement($xhtml);
echo (string)$xml->head->docdata->{"date.release"}["norm"];

我花了一段时间才弄明白这个方法 ;)
no-one
19 年前
对于任何还没有阅读 Sterling Hughe 文章的人 (http://www.zend.com/php5/articles/php5-simplexml.php)

<?php
$xml_document
=<<<EOT
<?xml version="1.0"?>
<root xmlns:foo="http://example.com">
<foo:bar>baz</foo:bar>
</root>
EOT;

$xml_document = simplexml_load_xml($xml_document);

$foo_ns_bar = $xml_document->children('http://example.com');

echo
$foo_ns_bar->bar[0]; // 输出 'baz'
?>
rodmen at gmail dot com
15 年前
将 XML 转换为 PHP 数组

<?php
function xml2phpArray($xml,$arr){
$iter = 0;
foreach(
$xml->children() as $b){
$a = $b->getName();
if(!
$b->children()){
$arr[$a] = trim($b[0]);
}
else{
$arr[$a][$iter] = array();
$arr[$a][$iter] = xml2phpArray($b,$arr[$a][$iter]);
}
$iter++;
}
return
$arr;
}

$Array = simplexml_load_string(file_get_contents('myfile.xml'));
print_r(xml2phpArray($Array,array()));
?>
taylorbarstow at that google mail thingy
18年前
有时你实际上想要一个数组,而不是一个伪数组。当你不处理属性时,尤其如此(即,你只想要子节点的数组)。

可以这样做:

<?php
$children
= $sxml->xpath('child::node()');
?>

你可能想要这样做是为了能够使用像 array_shift、array_pop 这样的数组函数。当编写递归函数时,这一点尤其重要。Simplexml 在迭代编程中非常有效,但如果你尝试实现递归,就会变得很丑。
crescentfreshpot at yahoo dot com
16年前
只需注意,从 children() 返回的可迭代对象包含 '@attributes' 键,它在 foreach 中是“不可见”的,但如果使用其他结构,例如 list()=each() 或在使用 foreach 迭代之前将其强制转换为数组,则可以查看它。
zyxwvu at users dot sourceforge dot net
20 年前
文件

<category>
<item>text</item>
<bold>text</bold>
<item>text</item>
<item>text</item>
<mark>text</mark>
<bold>text</bold>
</category>

如果你想要获取标签名称,可以使用以下循环布局:

<?php
foreach($category -> children() as $name => $node){
echo
$name.'<br/>';
}
?>
To Top