0

I need to convert an XML file to an array using some really simple and quick solution. This one was looking good to me:

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

The problem with this is that it treats multiple children as an indexed array consisting of an associative array per child, but if it's only one child in a parent tag, it doesn't create an indexed array with one element and put an assoc array directly to the parent tag element. I need the output of these scenarios to be consistent. I.e. an indexed array first not depending on the quantity of the children. My aim is a consistent schema after parsing.

An example of multiple children:

Input:

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

Output (am indexed array in the LINE parent element):

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

An example of one child:

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

output (an associative array in the line parent element):

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

Is it possible to get it always putting children into an indexed array even if it's only one child? If it's not possible, what can I use to get a consistent output?

2
  • Obviously it is not possible with your current code. Modify it to do what you need Commented Dec 13, 2016 at 18:55
  • @u_mulder I thought maybe there are some parser options that would allow that. Commented Dec 13, 2016 at 18:58

2 Answers 2

1

I've ended up with using the sabre/xml library. A few lines of code and it gives me the structure I need:

$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;
            },
        ];

where $this->service is Sabre\Xml\Service, $assocParser and $indexParser create the array structure I need from the standard output of the lib using the $makeArray closure.

Sign up to request clarification or add additional context in comments.

Comments

0

Actually the parsing is quite consistent - but the conversion is limited because JSON does not have the same format features as XML.

Your request can not work, because here is no way for the generic converter to know if here could "potentially" be multiple children (with the same name). If it would create the array anyway it would do this for ANY element (even the parent nodes like PICK_NOTE_LINES). Some JSON based formats like JsonML do something like that actually.

SimpleXML itself allows you to treat each element as a single node or a list. You know how to access the data so the problem is avoided.

If you like to create a specific JSON output, you will need to write your own conversion logic, reading the XML and creating an object/array structure.

I strongly suggest avoiding the generic conversion. If you're reading XML, keep the SimpleXMLElement, the conversion means you will loose data and API features.

If you need a specific JSON output generate it using your own logic. This way you can be sure that the structure is the one you need.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.