我解析一个大型XML文档,在解析子节点时遇到了很多麻烦。下面是我试图解析的一个示例。
<link rel="http://xxxxx/people.employees" title="employees">
<people>
<link href="/154" rel="http://catalog/person" title="Guy Nom" />
<link href="/385" rel="http://catalog/person" title="Carrie Jin" />
<link href="/162" rel="http://catalog/person" title="Joe Zee" />
<link href="/2125" rel="http://catalog/person" title="Mark Polin" />
<link href="/9293" rel="http://catalog/person" title="Stephen Castor" />
<link href="/21822" rel="http://catalog/person" title="Callum Tinge" />
<link href="/2022" rel="http://catalog/person" title="Brian Lennon" />
<link href="/2040" rel="http://catalog/person" title="Jorja Fox" />
<link href="/2046" rel="http://catalog/person" title="Harry Harris" />
<link href="/2399" rel="http://catalog/person" title="Sam Muellerleile" />
</people>
</link>
<link rel="http://xxxxx/people/others" title="others">
<people>
<link href="/7143" rel="http://catalog/person" title="James Smith" />
</people>
</link>
我需要区分"员工"answers"其他人",并将它们存储在单独的字段中。我想做如下的事情:
if($xmlReader->localName == 'link') {
if ($xmlReader->getAttribute('title') == "employees"){
//GO TO NEXT LINK TAG AND GET NAME
$myObject->employees[$myObject->employees_count]['name'] = $xmlReader->getAttribute('title');
$myObject->employees_count++;
} else if ($xmlReader->getAttribute('title') == "others"){
//GO TO NEXT LINK TAG AND GET NAME
$myObject->others[$myObject->others_count]['name'] = $xmlReader->getAttribute('title');
$myObject->others_count++;
}
}
显然,上面评论的部分对我来说是个问题。我不知道如何阅读这些子元素,而且在我看来,关于这方面的PHP文档一点也不好。如果有任何帮助,我将不胜感激。
对于XmlReader,可以使用$depth
属性。<link>
元素会有1
(一),所以当你继续阅读时,你可以检查当前元素是否仍然是它的子元素,因为你会看到一个END_ELEMENT
和相同的$depth
,然后你知道子元素都被消耗掉了。
在昨天的回答中,我展示了如何通过从XML_Reader
:扩展来封装该逻辑
- 为什么这个xmlreader代码不起作用
它允许将父元素的深度传递给一个名为readToNextChildElement($depth)
的新方法,该方法将允许您仅遍历子元素。
用法示例:
$depth = $reader->depth; # parent elements depth
while ($reader->readToNextChildElement($depth)) {
# only children
}
实现是:
class MyXMLReader extends XMLReader
{
...
public function readToNextChildElement($depth)
{
// if the current element is the parent and
// empty there are no children to go into
if ($this->depth == $depth && $this->isEmptyElement) {
return false;
}
while ($result = $this->read()) {
if ($this->depth <= $depth) return false;
if ($this->nodeType === self::ELEMENT) break;
}
return $result;
}
...
你可以在链接的答案中找到其余的代码。根据您的需要,如果您想要基于XML_Reader
的,这可能会有所帮助。否则,如果您可以将整个文档加载到内存中,那么Xpath更容易用于查询元素。
$employees_names = array_map(
'strval',
$sxml->xpath('//link[@title="employees"]//link/@title')
);
这就是SimpleXML。
使用XMLReader::readInnerXML()
<?php
$reader = new XMLReader();
$reader->open("filename.xml");
while ($reader->read()) {
if($reader->name=='Foo' && $reader->nodeType == XMLReader::ELEMENT) {
$reader->moveToElement();
$Foo = new SimpleXMLElement($reader->readOuterXml());
//$Foo->bar
}
}
$reader->close();
?>
就我个人而言,我会使用SimpleXML
来实现这一点,因为XMLReader根本没有很好的文档记录,而且(根据您的需要)如果您没有XMLReader来正确解析文档的其他部分,它应该可以很好地工作。话虽如此,这是我使用的代码以及输入。
test.xml
<?xml version="1.0" encoding="UTF-8" ?>
<result>
<link rel="http://xxxxx/people.employees" title="employees">
<people>
<link href="/154" rel="http://catalog/person" title="Guy Nom" />
<link href="/385" rel="http://catalog/person" title="Carrie Jin" />
<link href="/162" rel="http://catalog/person" title="Joe Zee" />
<link href="/2125" rel="http://catalog/person" title="Mark Polin" />
<link href="/9293" rel="http://catalog/person" title="Stephen Castor" />
<link href="/21822" rel="http://catalog/person" title="Callum Tinge" />
<link href="/2022" rel="http://catalog/person" title="Brian Lennon" />
<link href="/2040" rel="http://catalog/person" title="Jorja Fox" />
<link href="/2046" rel="http://catalog/person" title="Harry Harris" />
<link href="/2399" rel="http://catalog/person" title="Sam Muellerleile" />
</people>
</link>
<link rel="http://xxxxx/people/others" title="others">
<people>
<link href="/7143" rel="http://catalog/person" title="James Smith" />
</people>
</link>
</result>
然后用PHP解析该示例(注意,这里没有包含您的变量,但您应该能够从中导出您需要的内容。此外,最后是对已填充内容的验证,即显示。)
<?php
$xml = simplexml_load_file('test.xml','SimpleXMLElement', LIBXML_NOCDATA);
//Place holder variables as I don't have access to the object.
$emp=array();$emp_count=0;$other=array();$other_count=0;
foreach($xml->link as $links) {
$at = $links->attributes();
if($at['title'] == 'employees') {
foreach($links->people->link as $person) {
$emp_count++;
$employee = $person->attributes();
$emp[] = (string)$employee['title'];
}
} elseif($at['title'] == 'others') {
foreach($links->people->link as $person) {
$other_count++;
$others = $person->attributes();
$other[] = (string)$others['title'];
}
}
}
echo "<pre>";
echo "Employees: $emp_count'n";
print_r($emp);
echo "Others: $other_count'n";
print_r($other);
echo "</pre>";
?>
这就是输出(所以你不必自己运行^^)
Employees: 10
Array
(
[0] => Guy Nom
[1] => Carrie Jin
[2] => Joe Zee
[3] => Mark Polin
[4] => Stephen Castor
[5] => Callum Tinge
[6] => Brian Lennon
[7] => Jorja Fox
[8] => Harry Harris
[9] => Sam Muellerleile
)
Others: 1
Array
(
[0] => James Smith
)
我希望这能有所帮助!