Преобразование XML-файла с одним узлом с помощью simplexml_load_string()

#php #xml #simplexml

#php #xml #симплексml

Вопрос:

У меня есть простой xml-файл с одним или несколькими узлами, например:

 lt;?xml version='1.0' standalone='yes'?gt; lt;nodesgt;  lt;nodegt;  lt;valuegt;Val1lt;/valuegt;  lt;/nodegt;  lt;/nodesgt;  

Можно ли, используя simplexml_load_string() функцию, для файла с одним узлом (как указано выше) получить:

 SimpleXMLElement Object (  [node] =gt; Array  (  [0] =gt; SimpleXMLElement Object  (  [value] =gt; Val1  )  ) )  

с ключом [0], как для xml-файла с большим количеством узлов, а не:

 SimpleXMLElement Object (  [node] =gt; SimpleXMLElement Object  (  [value] =gt; Val1  ) )  

Потому что затем мне нужно преобразовать его в массив с той же глубиной, будь то из файла с одним или несколькими узлами

Ответ №1:

SimpleXML уже делает то , что вы хотите — разница между ними заключается только в выводе print_r , который показывает наиболее краткий способ доступа к элементам, а не единственный способ.

В частности, $xml-gt;node-gt;value и $xml-gt;node[0]-gt;value[0] всегда может использоваться для ссылки на один и тот же узел, и foreach ( $xml-gt;node as $node ) всегда работает, даже если есть только один соответствующий узел.

Вот почему, как правило, плохая идея «вслепую» конвертировать XML — структуру в массив PHP-вместо этого используйте foreach циклы и доступ к свойствам для извлечения любой необходимой вам информации.

Вы можете попробовать это сами с помощью этого кода:

 // Single node $xml1 = lt;lt;lt;XML lt;?xml version='1.0' standalone='yes'?gt; lt;nodesgt;  lt;nodegt;  lt;valuegt;Val1lt;/valuegt;  lt;/nodegt;  lt;/nodesgt; XML;  $sx1 = simplexml_load_string($xml1); print_r($sx1); // misleading! echo $sx1-gt;node-gt;value, PHP_EOL; echo $sx1-gt;node-gt;value[0], PHP_EOL; echo $sx1-gt;node[0]-gt;value[0], PHP_EOL; echo $sx1-gt;node[0]-gt;value, PHP_EOL; foreach ( $sx1-gt;node as $node ) {  echo $node-gt;value, PHP_EOL; }  // Two nodes with same name $xml2 = lt;lt;lt;XML lt;?xml version='1.0' standalone='yes'?gt; lt;nodesgt;  lt;nodegt;  lt;valuegt;Val1lt;/valuegt;  lt;/nodegt;   lt;nodegt;  lt;valuegt;Val2lt;/valuegt;  lt;/nodegt;  lt;/nodesgt; XML;  $sx2 = simplexml_load_string($xml2); print_r($sx2); // misleading! echo $sx2-gt;node-gt;value, PHP_EOL; echo $sx2-gt;node[0]-gt;value, PHP_EOL; echo $sx2-gt;node[0]-gt;value[0], PHP_EOL; echo $sx2-gt;node-gt;value[0], PHP_EOL; foreach ( $sx2-gt;node as $node ) {  echo $node-gt;value, PHP_EOL; }  

Комментарии:

1. Спасибо, я все понимаю. Проблема начинается как раз тогда, когда я пытаюсь преобразовать ее в массивы… У меня есть другие данные в массивах, и мне нужно сравнить/сопоставить их с этими данными из xml-файла. Оптимально ли использовать массивы, с одной стороны, и объект, с другой, или лучше преобразовать его в один и тот же тип?

2. Я думал о массивах, потому что функции array_intersect_key (), array_change_key_case() и т. Д. были мне очень полезны.

3. Использование массивов-это нормально, но не ожидайте, что вы напишете функцию, которая может преобразовать любой XML-документ в полезный массив, потому что существует так много способов структурирования XML и так много деталей, которые вас, вероятно, не волнуют. Вместо этого посмотрите на конкретный документ, который у вас есть, и просмотрите его фрагменты, которые вас интересуют, выстраивая их в свою собственную структуру массива. Например, в этом примере вы можете пройти по узлам и создать что-то вроде ['Val1', 'Val2] или [ ['Value' =gt; 'Val1'], ['Value' =gt; 'Val2'] ] .