获取汇总节点而不是单独的嵌套节点
getting summarized nodes instead of separate nested nodes
我有这样的第三方 xml 文件。这是一个电影应用程序,可以组织在哪个拍摄日拍摄哪个场景。
<schedule>
<DayBreak>
<AutoText>true</AutoText>
<Text></Text>
</DayBreak>
<Scene>
81
</Scene>
<DayBreak>
<AutoText>false</AutoText>
<Text>myday</Text>
</DayBreak>
<Scene>
82
</Scene>
<Scene>
85
</Scene>
<schedule />
如你所见,新的一天,拍摄了第81场景,然后又到了,拍摄了第82场景和第85场景。
(如果你问我,我不会像这样构建 xml,但那是我从其他人那里得到的。)
现在,如果我使用 PHP 的简单 xml 解析这个 xml 文件,我会得到这些数组:
[DayBreak] => Array
(
[0] => SimpleXMLElement Object
(
[AutoText] => true
[Text] => SimpleXMLElement Object
(
)
)
[1] => SimpleXMLElement Object
(
[AutoText] => false
[Text] => myday
)
)
[Scene] => Array
(
[0] => 81
[1] => 82
[2] => 85
)
[EndShooting] => SimpleXMLElement Object
(
)
如你所见,随着数组的汇总,我无法再解析哪一天拍摄的场景。
我该怎么办?
谢谢,马特
你试过了吗:
$xml = <<<xml
<schedule>
<DayBreak>
<AutoText>true</AutoText>
<Text></Text>
</DayBreak>
<Scene>
81
</Scene>
<DayBreak>
<AutoText>false</AutoText>
<Text>myday</Text>
</DayBreak>
<Scene>
82
</Scene>
<Scene>
85
</Scene>
</schedule>
xml;
$simpleXML = simplexml_load_string ($xml);
foreach ($simpleXML->children() as $node) {
echo $node->getName().' = '.$node."\n";
}
一种方法是从上到下遍历 schedule
个子节点,沿途修复 XML。当您偶然发现 DayBreak
节点时,在该位置创建一个新的 Day
容器节点并将 DayBreak
放入该 Day
节点。 Scene
后面的节点也将进入该节点。
这样您将拥有更好的工作结构。
<?php
$xml = <<<END
<schedule>
<DayBreak>
<AutoText>true</AutoText>
<Text></Text>
</DayBreak>
<Scene>
81
</Scene>
<DayBreak>
<AutoText>false</AutoText>
<Text>myday</Text>
</DayBreak>
<Scene>
82
</Scene>
<Scene>
85
</Scene>
</schedule>
END;
// Note: Last line in XML edited (used to be "<schedule />")
// Load
$dom = new DOMDocument();
$dom->loadXml($xml);
// Grab schedule node
$schedule = $dom->getElementsByTagName('schedule')->item(0);
// Loop through the child nodes of schedule
$i = 0;
while ($i < $schedule->childNodes->length) {
$childNode = $schedule->childNodes->item($i);
switch ($childNode->nodeName) {
case 'DayBreak':
$dayBreak = $childNode;
// Brand new day. Wrap DayBreak node in Day node, into which the
// following scene nodes will be moved
$day = $dom->createElement('Day');
$schedule->insertBefore($day, $dayBreak);
$day->appendChild($dayBreak);
break;
case 'Scene':
$sceneNode = $childNode;
// A scene shot the current day. Move the node into the day node.
$day->appendChild($childNode);
continue 2; // Don't increase $i as node was moved out of 'schedule'
}
$i++;
}
// echo $dom->saveXML(); // Uncomment to view XML
var_dump(new SimpleXMLElement($dom->saveXML()));
输出:
object(SimpleXMLElement)#5 (1) {
["Day"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#6 (2) {
["DayBreak"]=>
object(SimpleXMLElement)#9 (2) {
["AutoText"]=>
string(4) "true"
["Text"]=>
object(SimpleXMLElement)#10 (0) {
}
}
["Scene"]=>
string(8) "
81
"
}
[1]=>
object(SimpleXMLElement)#8 (2) {
["DayBreak"]=>
object(SimpleXMLElement)#9 (2) {
["AutoText"]=>
string(5) "false"
["Text"]=>
string(5) "myday"
}
["Scene"]=>
array(2) {
[0]=>
string(8) "
82
"
[1]=>
string(8) "
85
"
}
}
}
}
编辑
然后您可以使用 DOMDocument 遍历日期和场景:
foreach ($dom->getElementsByTagName('Day') as $day) {
echo "Day:";
foreach ($day->getElementsByTagName('Scene') as $scene) {
echo ' ' . trim($scene->nodeValue);
}
echo PHP_EOL;
}
或简单XML元素对象,如果您更熟悉它:
$xml = new SimpleXMLElement($dom->saveXML());
foreach ($xml->Day as $day) {
echo "Day:";
foreach ($day->Scene as $scene) {
echo ' ' . trim($scene);
}
echo PHP_EOL;
}
输出(对于 DOMDocument 和 SimpleXMLElement 示例):
Day: 81
Day: 82 85
我有这样的第三方 xml 文件。这是一个电影应用程序,可以组织在哪个拍摄日拍摄哪个场景。
<schedule>
<DayBreak>
<AutoText>true</AutoText>
<Text></Text>
</DayBreak>
<Scene>
81
</Scene>
<DayBreak>
<AutoText>false</AutoText>
<Text>myday</Text>
</DayBreak>
<Scene>
82
</Scene>
<Scene>
85
</Scene>
<schedule />
如你所见,新的一天,拍摄了第81场景,然后又到了,拍摄了第82场景和第85场景。
(如果你问我,我不会像这样构建 xml,但那是我从其他人那里得到的。)
现在,如果我使用 PHP 的简单 xml 解析这个 xml 文件,我会得到这些数组:
[DayBreak] => Array
(
[0] => SimpleXMLElement Object
(
[AutoText] => true
[Text] => SimpleXMLElement Object
(
)
)
[1] => SimpleXMLElement Object
(
[AutoText] => false
[Text] => myday
)
)
[Scene] => Array
(
[0] => 81
[1] => 82
[2] => 85
)
[EndShooting] => SimpleXMLElement Object
(
)
如你所见,随着数组的汇总,我无法再解析哪一天拍摄的场景。
我该怎么办?
谢谢,马特
你试过了吗:
$xml = <<<xml
<schedule>
<DayBreak>
<AutoText>true</AutoText>
<Text></Text>
</DayBreak>
<Scene>
81
</Scene>
<DayBreak>
<AutoText>false</AutoText>
<Text>myday</Text>
</DayBreak>
<Scene>
82
</Scene>
<Scene>
85
</Scene>
</schedule>
xml;
$simpleXML = simplexml_load_string ($xml);
foreach ($simpleXML->children() as $node) {
echo $node->getName().' = '.$node."\n";
}
一种方法是从上到下遍历 schedule
个子节点,沿途修复 XML。当您偶然发现 DayBreak
节点时,在该位置创建一个新的 Day
容器节点并将 DayBreak
放入该 Day
节点。 Scene
后面的节点也将进入该节点。
这样您将拥有更好的工作结构。
<?php
$xml = <<<END
<schedule>
<DayBreak>
<AutoText>true</AutoText>
<Text></Text>
</DayBreak>
<Scene>
81
</Scene>
<DayBreak>
<AutoText>false</AutoText>
<Text>myday</Text>
</DayBreak>
<Scene>
82
</Scene>
<Scene>
85
</Scene>
</schedule>
END;
// Note: Last line in XML edited (used to be "<schedule />")
// Load
$dom = new DOMDocument();
$dom->loadXml($xml);
// Grab schedule node
$schedule = $dom->getElementsByTagName('schedule')->item(0);
// Loop through the child nodes of schedule
$i = 0;
while ($i < $schedule->childNodes->length) {
$childNode = $schedule->childNodes->item($i);
switch ($childNode->nodeName) {
case 'DayBreak':
$dayBreak = $childNode;
// Brand new day. Wrap DayBreak node in Day node, into which the
// following scene nodes will be moved
$day = $dom->createElement('Day');
$schedule->insertBefore($day, $dayBreak);
$day->appendChild($dayBreak);
break;
case 'Scene':
$sceneNode = $childNode;
// A scene shot the current day. Move the node into the day node.
$day->appendChild($childNode);
continue 2; // Don't increase $i as node was moved out of 'schedule'
}
$i++;
}
// echo $dom->saveXML(); // Uncomment to view XML
var_dump(new SimpleXMLElement($dom->saveXML()));
输出:
object(SimpleXMLElement)#5 (1) {
["Day"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#6 (2) {
["DayBreak"]=>
object(SimpleXMLElement)#9 (2) {
["AutoText"]=>
string(4) "true"
["Text"]=>
object(SimpleXMLElement)#10 (0) {
}
}
["Scene"]=>
string(8) "
81
"
}
[1]=>
object(SimpleXMLElement)#8 (2) {
["DayBreak"]=>
object(SimpleXMLElement)#9 (2) {
["AutoText"]=>
string(5) "false"
["Text"]=>
string(5) "myday"
}
["Scene"]=>
array(2) {
[0]=>
string(8) "
82
"
[1]=>
string(8) "
85
"
}
}
}
}
编辑
然后您可以使用 DOMDocument 遍历日期和场景:
foreach ($dom->getElementsByTagName('Day') as $day) {
echo "Day:";
foreach ($day->getElementsByTagName('Scene') as $scene) {
echo ' ' . trim($scene->nodeValue);
}
echo PHP_EOL;
}
或简单XML元素对象,如果您更熟悉它:
$xml = new SimpleXMLElement($dom->saveXML());
foreach ($xml->Day as $day) {
echo "Day:";
foreach ($day->Scene as $scene) {
echo ' ' . trim($scene);
}
echo PHP_EOL;
}
输出(对于 DOMDocument 和 SimpleXMLElement 示例):
Day: 81
Day: 82 85