Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP XML DOM Uncaught exception 'DOMException' with message 'Wrong Document Error'

Tags:

dom

php

xml

xmldom

I am trying to learn XML and I know this is a problem with not properly importing the Nodes. But I can't quite figure it out. I've been looking around and most people don't have multiple child elements like I do with the departments.

Here is my XML structure:

<SOT>  
    <DEPARTMENT name="Aviation Technology" id="AT">  
        <EMPLOYEE type="Faculty">  
            <LOGIN>jdoe1</LOGIN>  
            <NAME>John Doe</NAME>   
        </EMPLOYEE>

        <EMPLOYEE type="Faculty">  
            <LOGIN>jdoe2</LOGIN>  
            <NAME>Jane Doe</NAME>   
        </EMPLOYEE>

        <EMPLOYEE type="Faculty">  
            <LOGIN>jdoe3</LOGIN>  
            <NAME>Joe Doe</NAME>  
        </EMPLOYEE> 
    </DEPARTMENT>    

    <DEPARTMENT name="Building and Construction Management" id="BCM">  
    </DEPARTMENT>

    <DEPARTMENT name="Computer Graphics Technology" id="CGT">  
    </DEPARTMENT>  
</SOT>

I understand that SOT is my root element and that departments are "children" of SOT and each department has multiple employee "children". The problem I run into is when I am trying to add a new employee to a certain department. When I try $departmentArray->item($i)->appendChild($employee); I get the Wrong Document Error.

I'm using this PHP code to try and append the child to the departmentNode

<?php

    //grab form data
    $username = $_POST['username'];
    $employeeName = $_POST['employeeName'];
    $department = $_POST['department'];

    //create new DOMDocument to hold current XML data
    $doc = new DOMDocument();
    $doc->load("test.xml");
    $xpath = new DOMXpath($doc);

    //create our new DOMDocument for combining the XML data
    $newDoc = new DOMDocument();
    $newDoc->preserveWhiteSpace = false;

    //create School of Tech Node and append to new doc
    $sotElement = $newDoc->createElement("SOT");
    $newDoc->appendChild($sotElement);
    $root = $newDoc->documentElement;

    //grab the department Nodes
    $departmentArray = $doc->getElementsByTagName("DEPARTMENT");

    //create a new employee and set attribute to faculty
    $employee = $newDoc->createElement("EMPLOYEE");
    $employee->setAttribute("type", "Faculty");

    //counters (might use them later for ->item(counter) function
    $indexCounter = 0;
    $i = 0;

    foreach($departmentArray as $departmentNode){
        if(strcmp($departmentNode->getAttribute('name'),$department) == 0){//check if departments match
            //create login element
            $loginNode = $newDoc->createElement("LOGIN");
            $loginNode->appendChild($newDoc->createTextNode($username));
            $employee->appendChild($loginNode);

            //create name node
            $nameNode = $newDoc->createElement("NAME");
            $nameNode->appendChild($newDoc->createTextNode($employeeName));
            $employee->appendChild($nameNode);

            //append employee onto department node
            //$departmentArray->item($i) = $doc->importNode($departmentArray->item($i), true);
            $departmentArray->item($i)->appendChild($employee);

            //set index of department array (possibly used for appending later)
            $indexCounter = $i;
        }
        $i++;
    }

    #######################################
    /*Write out data to XML file         */
    #######################################
    //$departmentArray = $doc->getElementsByTagName("DEPARTMENT");
    foreach($departmentArray as $departmentNode){
        $tempNode = $newDoc->importNode($departmentNode, true);
        /*if(strcmp($departmentNode->getAttribute('name'),$department) == 0){
            $sotElement->appendChild($employee);

        }*/
        $sotElement->appendChild($tempNode);
    }

    $newDoc->formatOutput = true;
    $newDoc->save("test2.xml");


?>

Any help explaining how to properly import all the department nodes to be able to append onto them would be greatly appreciated. I've tried using arrays.

like image 644
Grant Avatar asked Apr 25 '11 21:04

Grant


2 Answers

You need to import any node to append it to another document:

$departmentArray->item($i)->appendChild( $doc->importNode( $employee, true ) );
like image 123
SteAp Avatar answered Oct 18 '22 20:10

SteAp


I'm pretty sure that this is happening because you are trying to append an element from a different document into your output document.

I found this code in a comment on php's site for DOMNode::cloneNode which might be what you want.

<?php 
    $dom1->documentElement->appendChild( 
        $dom1->importNode( $dom2->documentElement, true )
    ); 
?>

Alternatively, you could look at exporting the node's XML and reimporting it into a DOMDocumentFragment, but I'd have to experiment to know for sure.

like image 25
Kevin Peno Avatar answered Oct 18 '22 22:10

Kevin Peno