以下是我正在使用的示例xml:
<contact id="43956">
<personal>
<name>
<first>J</first>
<middle>J</middle>
<last>J</last>
Some text...
</name>
<title>Manager</title>
<employer>National</employer>
<dob>1971-12-22</dob>
</personal>
</contact>
我得到了Some text...
,但现在我需要我的代码来阅读整个xml文档。它也没有读取xml中的值...因为你可以说我以前从未使用过XMLReader
。
这就是我得到的:
Array ( [contact] => Array ( [id] => 43956 [value] => some sample value ) [first] => [middle] => [last] => [#text] => Some text... [name] => [title] => [employer] => [dob] => [personal] => )
以下是我现在的代码:
function xml2array($file, array $result = array()) {
$lastElementNodeType = '';
$xml = new XMLReader();
if(!$xml->open($file)) {
die("Failed to open input file");
}
while($xml->read()) {
switch ($xml->nodeType) {
case $xml::END_ELEMENT:
$lastElementNodeType = $xml->nodeType;
case $xml::TEXT:
$tag = $xml->name;
if($lastElementNodeType == 15) {
$result[$tag] = $xml->readString();
}
case $xml::ELEMENT:
$lastElementNodeType = $xml->nodeType;
$tag = $xml->name;
if($xml->hasAttributes) {
while($xml->moveToNextAttribute()) {
$result[$tag][$xml->name] = $xml->value;
}
}
}
}
print_r($result);
}
我想过让这个函数递归,但是当我尝试它时,它让数组变得非常混乱。
我有一个版本,但它仍然没有输出J
中的first
等等:
function xml2assoc($xml) {
$tree = null;
while($xml->read())
switch ($xml->nodeType) {
case XMLReader::END_ELEMENT: return $tree;
case XMLReader::ELEMENT:
$node = array('tag' => $xml->name, 'value' => $xml->isEmptyElement ? '' : xml2assoc($xml));
if($xml->hasAttributes)
while($xml->moveToNextAttribute())
$node['attributes'][$xml->name] = $xml->value;
$tree[] = $node;
break;
case XMLReader::TEXT:
case XMLReader::CDATA:
$tree .= $xml->value;
}
return $tree;
}
答案 0 :(得分:0)
我认为您需要做的是保存最近节点的类型,或者至少保存最后一个节点,以便进行测试。简而言之,至少在您的示例XML中展示它时,您将遇到ELEMENT_END
节点类型,TEXT
节点类型,其中包含您正在查找的文本,然后是另一个ELEMENT_END
节点类型{1}}节点类型。
所以你需要一个case $xml::TEXT
,你还需要保存上一个节点类型,以便你的解析器知道,在正常情况下它应该是期待一个新的{{ 1}}事件或ELEMENT
事件,但已收到TEXT。这将是您使用END_ELEMENT
将文本捕获到临时变量所需的信号,并将其保存以用于您的目的,或等待查看下一个节点是否也是readString()
此时您可以保存并清除临时变量。
现在我们知道了你希望最终得到的更多信息(即,因为你想要捕获整棵树而不仅仅是捕获整个树的特定信息),我建议你坚持使用递归版本功能。我稍微修改了你的那个(请参阅TEXT和CDATA案例进行主要的实质性修改)。
ELEMENT_END
这种情况下的输出看起来像:
function xml2assoc($xml)
{
$tree = null;
while($xml->read())
{
switch ($xml->nodeType)
{
case XMLReader::END_ELEMENT:
return $tree;
case XMLReader::ELEMENT:
$node = array('tag' => $xml->name, 'value' => $xml->isEmptyElement ? '' : xml2assoc($xml));
if($xml->hasAttributes)
while($xml->moveToNextAttribute())
$node['attributes'][$xml->name] = $xml->value;
$tree[] = $node;
break;
case XMLReader::TEXT:
$tree["text"] = $xml->value;
break;
case XMLReader::CDATA:
$tree["cdata"] = $xml->value;
break;
}
}
return $tree;
}
我认为这是你想要的小编辑,但我们真的只是在这里重新发明轮子。我希望你需要解析的XML不是特别大。