Неперехваченное исключение PHP XML DOM ‘DOMException’ с сообщением ‘Ошибка неправильного документа’

#php #xml #dom #xmldom

#php #xml #dom #xmldom

Вопрос:

Я пытаюсь изучить XML, и я знаю, что это проблема с неправильным импортом узлов. Но я не могу в этом разобраться. Я осмотрелся, и у большинства людей нет нескольких дочерних элементов, как у меня с departments.

Вот моя структура XML:

 <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>
  

Я понимаю, что SOT является моим корневым элементом и что отделы являются «дочерними элементами» SOT, и в каждом отделе есть несколько «дочерних элементов» сотрудников. Проблема, с которой я сталкиваюсь, заключается в том, что я пытаюсь добавить нового сотрудника в определенный отдел. При попытке $departmentArray->item($i)->appendChild($employee); я получаю ошибку неправильного документа.

Я использую этот PHP-код, чтобы попытаться добавить дочерний элемент в 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");


?>
  

Была бы высоко оценена любая помощь, объясняющая, как правильно импортировать все узлы отдела, чтобы иметь возможность добавлять к ним. Я пробовал использовать массивы.

Ответ №1:

Вам нужно импортировать любой узел, чтобы добавить его в другой документ:

 $departmentArray->item($i)->appendChild( $doc->importNode( $employee, true ) );
  

Комментарии:

1. Это потому, что departmentArray в настоящее время находится внутри исходного $ doc, а не $ newDoc? Спасибо за помощь!

2. Важен второй параметр importNode. По умолчанию имеет значение false и не импортирует дочерние элементы.

Ответ №2:

Я почти уверен, что это происходит из-за того, что вы пытаетесь добавить элемент из другого документа в свой выходной документ.

Я нашел этот код в комментарии на сайте php для DOMNode::cloneNode , который может быть тем, что вам нужно.

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

В качестве альтернативы, вы могли бы посмотреть на экспорт XML узла и повторно импортировать его в DOMDocumentFragment , но мне пришлось бы поэкспериментировать, чтобы узнать наверняка.