Jump to content

Merging XML in PHP using SimpleXML and DOM


dbarndt

Recommended Posts

Hi,

 

I'm having trouble trying to merge two SimpleXML objects (user preference settings) in PHP.  It should be simple enough - the objects have the same root element, and I simply want to merge at the top child level.  However, the code I'm providing here, while it executes, does not work.  At the end of the merge() function, the merged preferences are empty.

 

I would very much appreciate if someone could tell me what I'm doing wrong or suggest another approach.  Thanks very much!

 

Example of desired XML result:

Before merge:

Old:
<xml version="1.0"/>
<preferences>
<setting1>value1</setting1>
<setting2 attr21="attr21Value" attr22="attr22Value" attr23="attr23Value"/>
</preferences>

New:
<xml version="1.0"/>
<preferences>
<setting1>value2</setting1>
<setting3 attr31="attrValue31" attr32="attr32Value" attr33="attrValue33"><setting31>value31</setting31><setting32>value32</setting32></setting3>
</preferences>

After merge:
<xml version="1.0"/>
<preferences>
<setting1>value2</setting1>
<setting2 attr21="attr21Value" attr22="attr22Value" attr23="attr23Value"/>
<setting3 attr31="attrValue31" attr32="attr32Value" attr33="attrValue33"><setting31>value31</setting31><setting32>value32</setting32></setting3>
</preferences>

-------------------

class UserPreferences
{
        const DEFAULT_STRING = "<preferences/>";

        $m_preferences = null;

        public function __construct()
        {
                $this->m_preferences = new SimpleXMLElement(self::DEFAULT_STRING);
        }

        // $new is a SimpleXMLElement containing the preferences to be merged
        public function merge($new)
        {
                $mergedDom = DOMDocument::loadXML(self::DEFAULT_STRING);

                $oldDom = DOMDocument::loadXML($this->m_preferences->asXML());

                // Compare existing/old preferences with the new
                // preferences.  If a match is found, delete the
                // old preference.
                foreach ($new->children() as $newChild)
                {
                        $i = 0;

                        foreach ($this->m_preferences->children() as $oldChild)
                        {
                                if ($newChild->asXML() == $oldChild->asXML())
                                {
                                        $oldDom->documentElement->removeChild($oldDom->documentElement->childNodes->item($i));
                                        $i--;
                                }
                                else
                                {
                                        $i++;
                                }
                        }

                        // Add the new preference to the merged list.
                        $newChildDom = DOMDocument::loadXML($newChild->asXML());
                        $mergedDom->documentElement->appendChild($mergedDom->importNode($newChildDom, true));
                }

                // Add the old preferences which did not match any of the new preferences to the merged list.
                $this->m_preferences = simplexml_import_dom($oldDom);

                foreach ($this->m_preferences->children() as $oldChild)
                {
                        $oldChildDom = DOMDocument::loadXML($oldChild->asXML());
                        $mergedDom->documentElement->appendChild($mergedDom->importNode($oldChildDom, true));
                }

                // Save the newly merged preferences.
                $this->m_preferences = simplexml_import_dom($mergedDom);
        }
}

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.