7

Ok, so I am pretty stuck on this. I have a semi-complex XML file which looks a bit like this:

<?xml version="1.0" encoding="UTF-8"?>

<community ID="1234" POSTDATE="20180329" xmlns="" COMPANY="SAMPLE CO">
   <data1>
      <datatype ID="0001">
         <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
      <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
      <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
      <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
</data1>
          <datatype ID="0002">
             <utpricing LT="2" STARTDATE="20160102" ENDDATE="20170102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
          <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
          <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
          <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
    </datatype>
</data1>
  <data2>
      <data2 ID="141" NAME="IAM | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
      <data2 ID="142" NAME="ASA | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
      <data2 ID="143" NAME="MPL | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
      <data2 ID="144" NAME="EBI | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
      <data2 ID="145" NAME="TOF | 2 | 2.00" SQFTMIN="111" SQFTMAX="222"/>
   </data2>

   <samples>
      <sample ID="001" AVAILDATE="20152901" STATUS="Unavailable" data1TYPE="001" UNITCAT="1X1" SOMEVALUE="50.00" data2ID="141">
         <item1 ID="59" item2="50.00" DESCRIPTION="Sample Description"/>
         <offeredterm LT="2" BASEAMOUNT="1120.00" TOTALCONCESSION="0.00" EFFECTIVESAMPLE="1120.00" CONTYPE="T" CONVALUE="0.00"/>
      </sample>
    <sample ID="002" AVAILDATE="20152901" STATUS="Unavailable" data1TYPE="001" UNITCAT="1X1" SOMEVALUE="50.00" data2ID="141">
         <item1 ID="59" item2="50.00" DESCRIPTION="Sample Description"/>
         <offeredterm LT="2" BASEAMOUNT="1120.00" TOTALCONCESSION="0.00" EFFECTIVESAMPLE="1120.00" CONTYPE="T" CONVALUE="0.00"/>
      </sample>

So I have tried to parse this a few ways, but what I want to end up with is a structured collection that I can then run operations on like selecting all items from data1 which have the same data1TYPE as the datatype ID etc.

Currently my code looks like this:

$XML = Storage::disk('local')->get('data\XML.xml');
$random = collect(json_decode(json_encode((array) simplexml_load_string($XML)), true));

I have been able to retrieve an object like this and then loop through by the indexes and build a separate collection for each xml tag. This doesn't feel that efficient though and I'm not sure how I would best run the comparison operations later on.

Any ideas?

1
  • Is there a way you can give us the actual xml? The example you provided is malformed xml. Commented Nov 5, 2018 at 15:23

2 Answers 2

27

Welcome to the world of xml! The way you are doing it is the best way that I am currently aware of. A basic example of xml to json is the way you are doing it:

$xml = simplexml_load_string($xml_string);

$json = json_encode($xml);

$array = json_decode($json,TRUE);

I do see that you are type-hinting array before your simplexml_load_string call. Is there a reason for that?

Also when you state that you are not sure how to run the comparison, what exactly do you mean by that? Is your xml static, meaning never changing, or does it change in size and/or scope?

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

1 Comment

or use: php <?php $doc = new \DOMDocument('1.0', 'UTF-8'); $doc->loadXML($xml); $xml = $doc->saveXML($doc->firstElementChild);
1

I created a package that works very well with Laravel to help you convert XML into an array.

https://github.com/mtownsend5512/xml-to-array

Install it, and you can make use of the global helper function for Laravel xml_to_array.

Because your XML is malformed, I tried my best to fix it so I could provide an example:

    $xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<community ID="1234" POSTDATE="20180329"
    xmlns="" COMPANY="SAMPLE CO">
    <data1>
        <datatype ID="0001">
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
        </datatype>
        <datatype ID="0002">
            <utpricing LT="2" STARTDATE="20160102" ENDDATE="20170102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
        </datatype>
    </data1>
    <data2>
        <data2 ID="141" NAME="IAM | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
        <data2 ID="142" NAME="ASA | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
        <data2 ID="143" NAME="MPL | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
        <data2 ID="144" NAME="EBI | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
        <data2 ID="145" NAME="TOF | 2 | 2.00" SQFTMIN="111" SQFTMAX="222"/>
    </data2>
    <samples>
        <sample ID="001" AVAILDATE="20152901" STATUS="Unavailable" data1TYPE="001" UNITCAT="1X1" SOMEVALUE="50.00" data2ID="141">
            <item1 ID="59" item2="50.00" DESCRIPTION="Sample Description"/>
            <offeredterm LT="2" BASEAMOUNT="1120.00" TOTALCONCESSION="0.00" EFFECTIVESAMPLE="1120.00" CONTYPE="T" CONVALUE="0.00"/>
        </sample>
        <sample ID="002" AVAILDATE="20152901" STATUS="Unavailable" data1TYPE="001" UNITCAT="1X1" SOMEVALUE="50.00" data2ID="141">
            <item1 ID="59" item2="50.00" DESCRIPTION="Sample Description"/>
            <offeredterm LT="2" BASEAMOUNT="1120.00" TOTALCONCESSION="0.00" EFFECTIVESAMPLE="1120.00" CONTYPE="T" CONVALUE="0.00"/>
        </sample>
    </samples>
</community>
XML;

dd(xml_to_array($xml));

Now your XML will be a valid array which can be manipulated. Because of your extensive use of attributes you will have a lot of data clean up to do. I recommend wrapping it in a Laravel Collection by doing collect($xml), then checking Laravel's Collection documentation to figure out the best way to transform the data in the way you want it.

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.