У меня есть некоторые нестандартные XML от Avendor с повторяющимися элементами.
SimpleXML и DOM объединяют мои теги XML. Как я могу предотвратить это?
Есть ли способ получить их в массив без их слияния?
<quiz>
<settings>
<user name="joe" email="[email protected]" />
</settings>
<questions>
<multiplechoice id="1">
<directions>What is 1+1?</directions>
<answer correct="true" selected="false">2</answer>
<answer correct="false" selected="false">4</answer>
<answer correct="false" selected="true">1</answer>
<answer correct="false" selected="false">0</answer>
</multiplechoice>
<truefalse id="2">
<directions>0 > 1?</directions>
<answer correct="true" selected="false">True</answer>
<answer correct="false" selected="true">False</answer>
</truefalse>
<multiplechoice id="3">
<directions>What is 2+1?</directions>
<answer correct="true" selected="false">3</answer>
<answer correct="false" selected="false">4</answer>
<answer correct="false" selected="true">1</answer>
<answer correct="false" selected="false">0</answer>
</multiplechoice>
</questions>
</quiz>
$xml = new SimpleXMLElement($xmldata);
Независимо от того, как я это пробую, SimpleXML объединяет <multiplechoice>
элементы в единый array()
как это:
[questions] => Array
(
[multiplechoice] => Array
(
[0] => Array
(
[@attributes] => Array
(
[id] => 1}
)
[directions] => What is 1+1?
[answers] => Array
(
[answer] => Array
(
[0] => 2
[1] => 4
[2] => 1
[3] => 0
)
)
)
[1] => Array
(
[@attributes] => Array
(
[id] => 3
)
[directions] => What is 2+1?
[answers] => Array
(
[answer] => Array
(
[0] => 3
[1] => 4
[2] => 1
[3] => 0
)
)
)
)
[truefalse] => Array
(
[0] => Array
(
[@attributes] => Array
(
[id] => 2}
)
[directions] => 0 > 1?
[answers] => Array
(
[answer] => Array
(
[0] => True
[1] => False
)
)
)
)
)
<multiplechoice>
элементы должны быть отдельными и в начальном порядке:
[questions] => Array
(
[multiplechoice] => Array
(
[0] => Array
(
[@attributes] => Array
(
[id] => 1}
)
[directions] => What is 1+1?
[answers] => Array
(
[answer] => Array
(
[0] => 2
[1] => 4
[2] => 1
[3] => 0
)
)
)
)
[truefalse] => Array
(
[0] => Array
(
[@attributes] => Array
(
[id] => 2}
)
[directions] => 0 > 1?
[answers] => Array
(
[answer] => Array
(
[0] => True
[1] => False
)
)
)
)
[multiplechoice] => Array
(
[0] => Array
(
[@attributes] => Array
(
[id] => 3
)
[directions] => What is 2+1?
[answers] => Array
(
[answer] => Array
(
[0] => 3
[1] => 4
[2] => 1
[3] => 0
)
)
)
)
)
Я не знаю какие ты делаешь с DOM
, но он поддерживает порядок «из коробки» здесь:
$dom = new DOMDocument();
$dom->loadXML($xml);
$questions = $dom->getElementsByTagName('questions')->item(0);
if($questions instanceof DOMElement){
foreach($questions->childNodes as $child){
if($child instanceof DOMElement){
var_dump($child->tagName, simplexml_import_dom($child));
}
}
}
Прекрасно по порядку:
string(14) "multiplechoice"class SimpleXMLElement#4 (3) {
public $@attributes =>
array(1) {
'id' =>
string(1) "1"}
public $directions =>
string(12) "What is 1+1?"public $answer =>
array(4) {
[0] =>
string(1) "2"[1] =>
string(1) "4"[2] =>
string(1) "1"[3] =>
string(1) "0"}
}
string(9) "truefalse"class SimpleXMLElement#4 (3) {
public $@attributes =>
array(1) {
'id' =>
string(1) "2"}
public $directions =>
string(6) "0 > 1?"public $answer =>
array(2) {
[0] =>
string(4) "True"[1] =>
string(5) "False"}
}
string(14) "multiplechoice"class SimpleXMLElement#4 (3) {
public $@attributes =>
array(1) {
'id' =>
string(1) "3"}
public $directions =>
string(12) "What is 2+1?"public $answer =>
array(4) {
[0] =>
string(1) "3"[1] =>
string(1) "4"[2] =>
string(1) "1"[3] =>
string(1) "0"}
как и другие Сам я обрисовал в общих чертах, невозможно поместить древовидную структуру в массив так, как вы просите в своем вопросе.
XML — это древовидная структура, и несколько элементов с одинаковым именем могут существовать на одном уровне. то, что невозможно с массивами.
так что лучше сохранить SimpleXMLElementкак они есть. С ними гораздо удобнее работать с данными, чем с массивом.
Как бы то ни было, все же возможно создать массив из этих данных, аналогичный тому, который вы запрашиваете, но он требует особого подхода к структуре в нем. Нет общего способа справиться с этим.
Например: все дочерние элементы из вопросов на их позиции, затем набираются их имена:
$result = $xml->xpath('//questions/*');
foreach ($result as &$rebuild) {
$rebuild = [$rebuild->getName() => $rebuild];
}
unset($rebuild);
$result = ['questions' => $result];
$array = json_decode(json_encode($result), true);
В результате получается массив в таком формате, с которым, я думаю, не очень удобно иметь дело:
Array
(
[questions] => Array
(
[0] => Array
(
[multiplechoice] => Array
(
[@attributes] => Array
(
[id] => 1
)
[directions] => What is 1+1?
[answer] => Array
(
[0] => 2
[1] => 4
[2] => 1
[3] => 0
)
)
)
[1] => Array
(
[truefalse] => Array
(
[@attributes] => Array
(
[id] => 2
)
[directions] => 0 > 1?
[answer] => Array
(
[0] => True
[1] => False
)
)
)
[2] => Array
(
[multiplechoice] => Array
(
[@attributes] => Array
(
[id] => 3
)
[directions] => What is 2+1?
[answer] => Array
(
[0] => 3
[1] => 4
[2] => 1
[3] => 0
)
)
)
)
)