1

Please, looking for little push over my problem. Having this script which append data to my existing JSON. What I am looking is: when I append new data it is create new $key (category) and set it all to JSON. Better to show on example. This is my code:

function parseTag($content1,$tg)
{
    $dom = new DOMDocument;
    libxml_use_internal_errors(true);
    $dom->loadHTML($content1);
    libxml_clear_errors();
    $attr = array();
    foreach ($dom->getElementsByTagName($tg) as $tag) {
        foreach ($tag->attributes as $attribName => $attribNodeVal)
        {
            $attr[$attribName]=$tag->getAttribute($attribName);
        }
    }
    return $attr;
}
for ($i = 0; $i < count($split); $i++) 
{
    $attrib_arr = parseTag($split[$i],'path');
    if (empty($attrib_arr)) {break;}
    $data_results = file_get_contents('newfile.json');
    $tempArray = json_decode($data_results, true);
    $a = "a".$i; 
    $tempArray[]=array($a => $attrib_arr);
    $jsonData = json_encode($tempArray, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    file_put_contents('newfile.json', $jsonData); 
}

It output this:

[
{
    "a0": {
        "d": "m34.511 143.4v3.0302l54.101-0.63086v-2.078z",
        "points": "34.510773,146.42924 88.611514,145.79838 88.611514,143.72037 34.510773,143.39908 ",
        "fill": "#353564"
    }
},
{
    "a1": {
        "d": "m34.511 146.43 78.119 2.1017 56.193-2.4552-80.211-0.27738z",
        "points": "112.6299,148.53093 168.82266,146.07576 88.611514,145.79838 34.510773,146.42924 ",
        "fill": "#afafde"
    }
},
{
    "a2": {
        "d": "m88.612 143.72 80.211-1.5957v3.9511l-80.211-0.27738z",
        "points": "168.82266,142.1247 168.82266,146.07576 88.611514,145.79838 88.611514,143.72037 ",
        "fill": "#e9e9ff"
    }
}
]

What I am looking for is this:

[
{
"x": {
        "a0": {
            "d": "m34.511 143.4v3.0302l54.101-0.63086v-2.078z",
            "points": "34.510773,146.42924 88.611514,145.79838 88.611514,143.72037 34.510773,143.39908 ",
            "fill": "#353564"
        },

        "a1": {
            "d": "m34.511 146.43 78.119 2.1017 56.193-2.4552-80.211-0.27738z",
            "points": "112.6299,148.53093 168.82266,146.07576 88.611514,145.79838 34.510773,146.42924 ",
            "fill": "#afafde"
        },
        "a2": {
            "d": "m88.612 143.72 80.211-1.5957v3.9511l-80.211-0.27738z",
            "points": "168.82266,142.1247 168.82266,146.07576 88.611514,145.79838 88.611514,143.72037 ",
            "fill": "#e9e9ff"
        }
    }
}
]

I know that is something to do within the function but I am failing to set the code to do that. Thank you all who can suggest the correct code for it.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
x-magix
  • 2,623
  • 15
  • 19
  • As an aside, I'll recommend a `foreach` versus a `for` loop so that you aren't calling `count()` on each iteration. – mickmackusa Aug 14 '18 at 04:05
  • I don't see where `x` comes from. Do you want something like `$jsonData = json_encode(["x" => $tempArray], ...` ? Do you mean to `put` in an iterated fashion? I think I would perform all of my data generation then just save to file once. – mickmackusa Aug 14 '18 at 04:10
  • hi actually you sugested nice try but it created many "x" categories `{ "x": { "x": { "x": {` – x-magix Aug 14 '18 at 04:37
  • I just need one so aha you also sugested for each .. ok will go take a look over that – x-magix Aug 14 '18 at 04:38
  • 1
    You shouldn't call `json_encode()` and `file_put_contents()` inside the loop. Do that after the loop is done, when you've finished filling in `$tempArray`. – Barmar Aug 14 '18 at 04:42
  • "x" is just new parent for all new data in JSON.. When I append new data is will be named "x".. When again new "x" category will join the json file.. so than I can read the moves in my SVG with "x" is a one move. next "x" next move and so on.. dont know if all will understand, my english is little bit broken in terms of explaining something, sorry – x-magix Aug 14 '18 at 05:04

3 Answers3

1

I'm not sure if I completely understand your requirements (and I am coding from my phone), but I recommend generating the complete file contents before writing to the file (only once).

Do away with unnecessary levels and prefixed counters...

$tempArray = [];
foreach ($split as $item) {
    $attrib_arr = parseTag($item, 'path');
    if (!empty($attrib_arr)) {
        $tempArray[] = $attrib_arr;
    }
}
if (!empty($tempArray)) {
    $data_array = json_decode(file_get_contents('newfile.json'), true);
    $data_array["x"][] = $tempArray;
    $jsonData = json_encode($data_array, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    file_put_contents('newfile.json', $jsonData);
}

In this snippet, the foreach loop creates the "current batch" of data. If it is not empty, it will store it in its own group under the x parent key. This way you can always differentiate the data from one batch to another.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • yes it dos what I am looking for BUT still is not all in place. Because when I add new data again its add the new category "x" INSIDE old "x". What I want is that new "x" will be add after old "x" category... But otherwise it was correct.. just to solve the end :) – x-magix Aug 14 '18 at 04:58
  • To be clear, I am not breaking the loop when an empty array is returned. We don't know what `x`is for. You can't have multiple `x` keys on the same level. – mickmackusa Aug 14 '18 at 04:58
  • Do you actually need to prefix the counter with `a`? It just makes more difficulty while coding. – mickmackusa Aug 14 '18 at 05:04
  • actually yes I would like to have the category "x" as sign for one move in SVG.. If I append new data it will read from it as the next "x" is new move – x-magix Aug 14 '18 at 05:15
  • Will you have data that is not associate with `x` in this file too? – mickmackusa Aug 14 '18 at 05:18
  • so it is no possible to have multiple x on the same level?.. Ok but is any possibility to sign new set of "x" as for exaple "x1" ? – x-magix Aug 14 '18 at 05:19
  • I recommend using numeric keys so that you don't need to go to any extra trouble. See barmar's answer to realize the extra toil. – mickmackusa Aug 14 '18 at 05:21
  • its will be very nice if you find something which helps me in the future to get my data settled.. marmar suggestion was nice.. just its will be nice for example when new data will append "x" will change to "x1" and append to the document – x-magix Aug 14 '18 at 05:42
  • Barmar is a smart man. We both urge you to omit the letter from your keys which exist below `x`. – mickmackusa Aug 14 '18 at 05:43
  • so the suggestion .. I know I am bit slow to understand.. sorry for that – x-magix Aug 14 '18 at 05:46
  • yes this is nice suggestion ,, fantastic, thank you very much and have a nice all day – x-magix Aug 14 '18 at 05:56
0

It's unclear what that x even means but, I suppose this is what you are looking for:

$json = json_decode(file_get_contents('newfile.json'), true);

foreach ($split as $i => $item)
    if ($item = parseTag($item, 'path'))
       $json['x']["a$i"] = $item;
    else
       break; // for some reason break loop if no result in that particular slice...

file_put_contents('newfile.json', json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));

Mind JSON_UNESCAPED_UNICODE and JSON_UNESCAPED_SLASHES may imply in creating invalid JSON that cannot be parsed back.

Edit: Hold on, for that exact output:

$json = json_decode(file_get_contents('newfile.json'), true);

foreach ($split as $i => $item)
    if ($item = parseTag($item, 'path'))
       $json[0]['x']["a$i"] = $item;
    else
       break; // for some reason break loop if no result in that particular slice...

file_put_contents('newfile.json', json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
Havenard
  • 27,022
  • 5
  • 36
  • 62
  • hi. yes it does the trick but I cant run it multiple times. I would like that when I run it again its exactly like this but join other data in JSON. Meaning next "x" with new data will append old data in the file – x-magix Aug 14 '18 at 05:13
0

You shouldn't read and write the file each time through the loop. And to get the structure you want, you need to access nested array elements.

Also, when you're updating the JSON, you need to start the aN keys from where the existing array ended. Your code starts from a0 each time, which overwrites the existing elements instead of adding to them.

And you shouldn't use [] to add to the array, you need to use $a as the index for the new array element.

$data_results = file_get_contents('newfile.json');
$tempArray = json_decode($data_results, true);

if (empty($tempArray[0]['x'])) {
    $i = 0;
} else {
    end($tempArray[0]['x']);
    $lastkey = key($tempArray[0]['x']);
    $i = substr($lastkey, 1) + 1;
}

foreach ($split as $el) 
{
    $attrib_arr = parseTag($el, 'path');
    if (empty($attrib_arr)) {
        break;
    }
    $a = "a".$i;
    $i++;
    $tempArray[0]['x'][$a]=$attrib_arr;
}

$jsonData = json_encode($tempArray, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
file_put_contents('newfile.json', $jsonData); 

Note that each time you run this, the new elements being added to the file will start with a0,

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • sorry I tried but it not help me .. this is actually brake my coding.. What I am looking for: I would like to have the category "x" as sign for one move in SVG.. If I append new data it will read from it as the next "x" is new move – x-magix Aug 14 '18 at 05:17
  • This code assumes that the JSON in the file already has `[{"x": {...}}]`. You can't use it with your existing file. – Barmar Aug 14 '18 at 05:19
  • I just fixed it to assign to `[$a]` rather than `[]`. You were adding an extra level of nesting there. – Barmar Aug 14 '18 at 05:21
  • ok this is much better it helps a lot.. it is anyhow possible that either will add next numeric will add next numeric to "x".. for example next append data is "x1", next "x2" and so one? – x-magix Aug 14 '18 at 05:30
  • Yes, you can use the same technique I used to change `a0` to start after the old ending value. – Barmar Aug 14 '18 at 05:31
  • It seems like you're making things really hard on yourself by using these named keys instead of just using ordinary arrays that you push onto. – Barmar Aug 14 '18 at 05:32
  • Is it really necessary to use objects instead of arrays? – Barmar Aug 14 '18 at 05:32
  • I do dont know this :).. I suggested this is will be the easiest but maybe I was wrong.. – x-magix Aug 14 '18 at 05:36