views:

353

answers:

1

Hi, everyone.

About a year ago I wrote a jQuery-inspired library which allowed you to manipulate the DOM using PHP's XPath and DOMDocument. I recently wanted to clean it up and post it as an open source project. I've been spending the past few days making improvements and implementing some more of PHP's native OO features.

Anyhow, I thought I'd add a new method which allows you to merge a separate XML document with the current one. The catch here is that this method asks for 2 XPath expressions. The first one fetches the elements you want to merge into the existing document. The second specifies the destination path of these merged elements.

The method works well in fetching matching elements from both paths, but I'm having issues with importing the foreign elements into the current DOM. I keep getting the dreaded 'Wrong Document Error' message.

I thought I knew what I was doing, but I suppose I was wrong. If you look at the following code, you can see that I'm first iteration through the current documents matching elements, then through the foreign document's matching elements.

Within the second nested loop is where I am attempting to merge each foreign element into the destination path in the current document.

Not sure what I'm doing wrong here as I'm clearly importing the foreign node into the current document before appending it.

public function merge($source, $path_origin, $path_destination)
{
    $Dom = new self;

    if(false == $Dom->loadXml($source))
    {
        throw new DOMException('XML source could not be loaded into the DOM.');
    }

    $XPath = new DOMXPath($Dom);

    foreach($this->path($path_destination, true) as $Destination)
    {
        if(false == in_array($Destination->nodeName, array('#text', '#document')))
        {
            foreach($XPath->query($path_origin) as $Origin)
            {
                if(false == in_array($Destination->nodeName, array('#text', '#document')))
                {
                    $this->importNode($Origin, true);

                    $Destination->appendChild($Origin->cloneNode(true));
                }
            }
        }
    }

    return $this;
}

You can find the library in its entirety in the following Github repo:

http://github.com/wilhelm-murdoch/DomQuery

Halps!!!

+2  A: 

importNode doesn't "change" the node so it belongs to another document. It creates a new node belonging to the new document and returns it. So you should be getting its return value and using that in appendChild.

$Destination->appendChild($this->importNode($Origin, true));
Nicolás
Damnit, I think you're right. Lemme test this mofo.
Wilhelm Murdoch
Yep. Confirmed. You are correct! For some odd reason I thought it would update by reference and returned only TRUE or FALSE. Thanks! :D
Wilhelm Murdoch
AFAIK, in theory (DOM spec, not PHP impl), the two documents could even be from different DOM implementations, such that the two nodes are instances of different classes. In that case it would be impossible to update by reference.
Nicolás