2016-12-13 4 views
0

Мне нужно преобразовать XML-файл в массив, используя какое-то очень простое и быстрое решение. Это один был хорошо выглядеть для меня:Несогласованный разбор XML

json_decode(json_encode(simplexml_load_string($xmlContent, "SimpleXMLElement", LIBXML_NOCDATA)), true); 

Проблема с этим состоит в том, что он рассматривает несколько детей как индексированный массив, состоящий из ассоциативного массива для каждого ребенка, но если это только один ребенок в родительском теге, это Безразлично Создайте индексированный массив с одним элементом и поместите соответствующий массив непосредственно в элемент родительского тега. Мне нужно, чтобы результат этих сценариев был последовательным. То есть индексированный массив сначала не зависит от количества детей. Моя цель - последовательная схема после разбора.

Пример нескольких детей:

Вход:

<PICK_NOTE_LINES> 
      <LINE> 
      <PICK_LINE_NUM>1</PICK_LINE_NUM> 
      <PRODUCT_CODE>3342</PRODUCT_CODE> 
      <BATCH_CODE></BATCH_CODE> 
      <QUANTITY>1</QUANTITY> 
      </LINE> 
      <LINE> 
      <PICK_LINE_NUM>2</PICK_LINE_NUM> 
      <PRODUCT_CODE>5285</PRODUCT_CODE> 
      <BATCH_CODE></BATCH_CODE> 
      <QUANTITY>1</QUANTITY> 
      </LINE> 
</PICK_NOTE_LINES> 

выход (я индексированный массив в линии родительского элемента):

['PICK_NOTE_LINES'=>['LINE'=>[['PICK_LINE_NUM'=>1, ...],['PICK_LINE_NUM'=>2, ...]]] 

Пример одного ребенка:

<PICK_NOTE_LINES> 
     <LINE> 
     <PICK_LINE_NUM>1</PICK_LINE_NUM> 
     <PRODUCT_CODE>3342</PRODUCT_CODE> 
     <BATCH_CODE></BATCH_CODE> 
     <QUANTITY>1</QUANTITY> 
     </LINE> 
    </PICK_NOTE_LINES> 

вывода (ассоциативный массив в строке родительского элемента):

['PICK_NOTE_LINES'=> ['LINE'=>['PICK_LINE_NUM'=>1, ...]]] 

Можно ли получить его всегда помещая детей в индексный массив, даже если это только один ребенок? Если это невозможно, что я могу использовать для получения последовательного вывода?

+0

Очевидно, что это невозможно с вашим текущим кодом.Измените его, чтобы делать то, что вам нужно –

+0

@u_mulder Я подумал, что, возможно, есть некоторые варианты парсера, которые позволят это. – Sergey

ответ

0

Фактически синтаксический анализ довольно последователен - но преобразование ограничено, поскольку JSON не имеет таких же функций формата, как XML.

Ваш запрос не может работать, потому что здесь нет никакого способа, чтобы универсальный конвертер знал, может ли здесь «потенциально» быть несколько детей (с тем же именем). Если бы он все равно создал массив, это сделало бы это для ЛЮБОГО элемента (даже для таких родительских узлов, как PICK_NOTE_LINES). Некоторые JSON-форматы, такие как JsonML, действительно делают что-то подобное.

Сам SimpleXML позволяет обрабатывать каждый элемент как отдельный узел или список. Вы знаете, как получить доступ к данным, чтобы избежать этой проблемы.

Если вам нравится создавать определенный вывод JSON, вам нужно будет написать свою собственную логику преобразования, прочитав XML и создав структуру объекта/массива.

Я настоятельно рекомендую избегать общего преобразования. Если вы читаете XML, храните SimpleXMLElement, конверсия означает, что вы потеряете данные и функции API.

Если вам нужен конкретный выход JSON, сгенерируйте его, используя свою собственную логику. Таким образом, вы можете быть уверены, что структура нужна вам.

1

Я закончил с использованием библиотеки сабля/xml. Несколько строк кода, и это дает мне структуру мне нужно:

$this->service->elementMap = [ 
      '{}DOCUMENT' => $assocParser, 
      '{}DATA' => $assocParser, 
      '{}CONSIGNMENTS' => $indexParser, 
      '{}PICK_NOTE_LINES' => function ($reader) use ($makeArray) { 
       $lines = []; 
       $children = $reader->parseInnerTree(); 
       foreach ($children as $child) { 
        $lines[] = $makeArray($child['value']); 
       } 
       return $lines; 
      }, 
     ]; 

где $this->service является Sabre\Xml\Service, $ assocParser и $ indexParser создать структуру массива Мне нужно от стандартного выхода Lib с помощью $makeArray закрытия.