У меня есть сторонний 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, как это, но это то, что я получил от других парней.)
Теперь, если я проанализирую этот xml файл с помощью PHP simplexml, я получаю эти массивы:
[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
(
)
Как вы видите, я больше не могу разобрать, какая сцена снимается в тот день, когда массив суммируется.
Что мне делать?
спасибо, Мэтт
Одним из способов было бы перебрать дочерние узлы 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;
}
или объект SimpleXMLElement, если вы более знакомы с этим:
$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 = <<<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";
}