Tengo un archivo xml de terceros como este. Es una aplicación de películas que organiza qué escena se filma y qué día de rodaje.

<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 /> 

Como puede ver, hay un nuevo día, luego se filma la escena 81, luego viene otro día, donde se filman la escena 82 y la escena 85.

(Si me preguntas, no estructuraría el xml de esta manera, pero eso es lo que obtuve de los otros chicos).

Ahora, si analizo este archivo xml usando simplexml de PHP, obtengo estas matrices:

                [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
                    (
                    )

Como puede ver, ya no puedo analizar qué escena se filma y qué día mientras se resume la matriz.

¿Qué debo hacer?

Gracias Matt

0
Kinesias 16 feb. 2015 a las 22:39

2 respuestas

La mejor respuesta

Una forma sería recorrer los nodos secundarios schedule de arriba a abajo, arreglando el XML a lo largo del camino. Cuando te topes con un nodo DayBreak, crea un nuevo nodo contenedor Day en ese lugar y coloca el DayBreak en ese nodo Day. Los nodos Scene que siguen también entrarán en ese nodo.

De esta forma tendrás una mejor estructura para trabajar.

<?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()));

Salida:

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
"
      }
    }
  }
}

Editar

Luego puede recorrer los días y las escenas usando DOMDocument:

foreach ($dom->getElementsByTagName('Day') as $day) {
    echo "Day:";
    foreach ($day->getElementsByTagName('Scene') as $scene) {
        echo ' ' . trim($scene->nodeValue);
    }
    echo PHP_EOL;
}

O un objeto SimpleXMLElement, si está más familiarizado con eso:

$xml = new SimpleXMLElement($dom->saveXML());

foreach ($xml->Day as $day) {
    echo "Day:";
    foreach ($day->Scene as $scene) {
        echo ' ' . trim($scene);
    }
    echo PHP_EOL;
}

Salida (para los ejemplos de DOMDocument y SimpleXMLElement):

Day: 81
Day: 82 85
1
mhall 20 feb. 2015 a las 21:26

Has probado:

$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";
}
0
Alex 16 feb. 2015 a las 19:52