Anastasie Laurent
Anastasie Laurent

Reputation: 915

Laravel loop on model and change to array

I am trying to change my model to xml format.

I did almost everything but I still need this thing:

$data = [
            'domain'=> $xmlDocument->domain,
            'FirstDate' => $xmlDocument->dateAttribute->first_date,
            'LastDate' => $xmlDocument->dateAttribute->last_date,
            'Category' => $xmlDocument->category->name,
            'Action' => $xmlDocument->websiteAction->name,
            'Source' => $xmlDocument->source->name,
            'LogFile' => $xmlDocument->log_file,
            'DateAttribute' => [
                        'Name' => $xmlDocument->dateAttribute->name,
                        'Place' => $xmlDocument->dateAttribute->dateLocation->name,
                        'DateFunction' => $xmlDocument->dateAttribute->dateFunction->name
                    ],
            'MasterPage' => [
                'MasterAttributes' => [

                ],
                'Container'=>[
                    'xpath' => $xmlDocument->masterInformation->xpath
                ],
                'NextPage' =>[],
                'LinkAttribute'=>[]
            ],
        ];

as you see the MasterAttributes is empty.

the model $xmlDocument has a one to many relationship like this:

$xmlDocument->masterInformaton->masterAttributes

the masterAttributes is the many part

My question

how to use that many and transfer it to array, so each element in that array is this:

'masterAttribute' => [
    'name' => ...,
    'xpath' => ...
]

In other words, I will have many arrays and these arrays will be added to the empty MasterAttribute key in the code I showed to u.

I hope I made my point to you, if not, kindly tell me.

Update

What I have tried:

$masterAttributes = [];
        foreach ($xmlDocument->masterInformation->masterAttributes as $attribute){
            $masterAttribute = [
                'Attribute' =>[
                    'defaultValue' => $attribute->defaultValue,
                    'name' => $attribute->attributeName->name,
                    'xpath' => $attribute->xpath
                ]
            ];
            array_push($masterAttributes, $masterAttribute);
        }

and then I put the result like this:

'MasterAttributes' => [
                    $masterAttributes
                ],

but the generated xml is:

<MasterAttributes>
         <item0>
            <item0>
               <Attribute>
                  <defaultValue />
                  <name>bathroom</name>
                  <xpath>this is the xpath</xpath>
               </Attribute>
            </item0>
            <item1>
               <Attribute>
                  <defaultValue />
                  <name>price</name>
                  <xpath>new xpath</xpath>
               </Attribute>
            </item1>
            <item2>
               <Attribute>
                  <defaultValue />
                  <name>bathroom</name>
                  <xpath>new xpath value</xpath>
               </Attribute>
            </item2>
         </item0>
      </MasterAttributes>

look that there is extra Item2 and item0 that I don't want

Update 2

The code to generate the xml is:

$xml = new SimpleXMLElement("<?xml version=\"1.0\"?><websiteInformation></websiteInformation>");
        $this->array_to_xml($data,$xml);
        $xml->asXML("FileName".XmlDocument::find($id)->id.".xml");

where $data is the final array I showed to you and array_to_xml is:

// function defination to convert array to xml
    public  function array_to_xml($student_info, &$xml_student_info) {
        foreach($student_info as $key => $value) {
            if(is_array($value)) {
                if(!is_numeric($key)){
                    $subnode = $xml_student_info->addChild("$key");
                    $this->array_to_xml($value, $subnode);
                }
                else{
                    $subnode = $xml_student_info->addChild("item$key");
                    $this->array_to_xml($value, $subnode);
                }
            }
            else {
                $xml_student_info->addChild("$key",htmlspecialchars("$value"));
            }
        }
    }

Updadte 3

The @watcher gave me an aswer and this is the result of his/her answer

<MasterAttributes>
         <item0>
            <masterAttribute>
               <name />
               <xpath>this is the xpath</xpath>
            </masterAttribute>
         </item0>
         <item1>
            <masterAttribute>
               <name />
               <xpath>new xpath</xpath>
            </masterAttribute>
         </item1>
         <item2>
            <masterAttribute>
               <name />
               <xpath>new xpath value</xpath>
            </masterAttribute>
         </item2>
      </MasterAttributes>

Upvotes: 1

Views: 154

Answers (1)

Jeff Lambert
Jeff Lambert

Reputation: 24661

Try something like this:

$attributes = $xmlDocument->masterInformaton->masterAttributes;
foreach($attributes as $attribute) {
    $data['MasterPage']['MasterAttributes'][] = [
        'masterAttribute' => [
            'name' => $attribute->name,
            'xpath' => $attribute->xpath,
        ]
    ];
}

This is assuming that the attributes on your master attributes are name and xpath.

Update

$subnode = $xml_student_info->addChild("item$key");

This is the line in your xml generation that is adding those item0 nodes. Removing that doesn't help, because you do need to build a subtree based off of these indices, but you don't want to add them directly to the XML document as they are.

I tried coming up with a quick solution, but it turns out its not so quick (I also found I think the original answer where you found your xml generation code here).

Update 2

Try using this for your xml generation, see if it gets you what you need. It's based off of this answer by @drzaus:

function simple_xmlify($arr, SimpleXMLElement $root = null, $el = 'x') {
    // based on, among others https://stackoverflow.com/a/1397164/1037948

    if(!isset($root) || null == $root) $root = new SimpleXMLElement('<' . $el . '/>');

    if(is_array($arr)) {
        foreach($arr as $k => $v) {
            // special: attributes
            if(is_string($k) && $k[0] == '@') $root->addAttribute(substr($k, 1),$v);
            // normal: append
            else {
                if(is_numeric($k) && is_array($v)) {
                    foreach($v as $ik => $iv) {
                        simple_xmlify($iv, $root);
                    }
                } else {
                    simple_xmlify($v, $root->addChild(
                        // fix 'invalid xml name' by prefixing numeric keys
                        is_numeric($k) ? 'n' . $k : $k)
                    );
                }

            }
        }
    } else {
        $root[0] = $arr;
    }

    return $root;
}//--   fn  simple_xmlify

Upvotes: 1

Related Questions