I'm creating XML response for the one of our clients with the namespace URLs in that using PHP. I'm expecting the output as follows,
<?xml version="1.0" encoding="UTF-8"?>
<ns3:userResponse xmlns:ns3="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://www.w3.org/2001/XMLSchema">
<Content>
<field1>fieldvalue1</field1>
</Content>
</ns3:userResponse>
But by using the following code,
<?php
// create a new XML document
$doc = new DomDocument('1.0', 'UTF-8');
// create root node
$root = $doc->createElementNS('http://www.w3.org/2001/XMLSchema-instance', 'ns3:userResponse');
$root = $doc->appendChild($root);
$root->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'ns1:schemaLocation','');
$root->setAttributeNS('http://www.w3.org/2001/XMLSchema', 'ns2:schemaLocation','');
// add node for each row
$occ = $doc->createElement('Content');
$occ = $root->appendChild($occ);
$child = $doc->createElement("field1");
$child = $occ->appendChild($child);
$value = $doc->createTextNode('fieldvalue1');
$value = $child->appendChild($value);
// get completed xml document
$xml_string = $doc->saveXML();
echo $xml_string;
DEMO:
The demo is here, http://codepad.org/11W9dLU9
Here the problem is, the third attribute is mandatory attribute for the setAttributeNS PHP function. So, i'm getting the output as,
<?xml version="1.0" encoding="UTF-8"?>
<ns3:userResponse xmlns:ns3="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://www.w3.org/2001/XMLSchema" ns3:schemaLocation="" ns2:schemaLocation="">
<Content>
<field1>fieldvalue1</field1>
</Content>
</ns3:userResponse>
So, is there anyway to remove that ns3:schemaLocation and ns2:schemaLocation which is coming with empty value? I googled a lot but couldn't able to find any useful answers.
Any idea on this would be so great. Please help.
You create this attributes:
$root->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'ns1:schemaLocation','');
$root->setAttributeNS('http://www.w3.org/2001/XMLSchema', 'ns2:schemaLocation','');
remove this lines and they will be removed.
If you want to add some xmlns without using it in code is:
$attr_ns = $doc->createAttributeNS( 'http://www.w3.org/2001/XMLSchema', 'ns2:attr' );
Read this comment: http://php.net/manual/pl/domdocument.createattributens.php#98210
Related
I'm creating an xml file with PHP.
The file I need to create is this one I show you:
<p:FatturaElettronica versione="FPA12" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="FPA12" >
<FatturaElettronicaHeader>
<DatiTrasmissione>
<IdTrasmittente>
<IdPaese>IT</IdPaese>
<IdCodice>01234567890</IdCodice>
</IdTrasmittente>
<ProgressivoInvio>00001</ProgressivoInvio>
<FormatoTrasmissione>FPA12</FormatoTrasmissione>
<CodiceDestinatario>AAAAAA</CodiceDestinatario>
</DatiTrasmissione>
</FatturaElettronicaHeader>
<p:FatturaElettronica>
This is my code:
$xml = new SimpleXMLElement('<p:FatturazioneElettronica xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://microsoft.com/wsdl/types/" />');
$xml->addAttribute("versione","FPA12");
$xml->addAttribute("xmlns:xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
$FatturaElettronicaHeader = $xml->addChild('FatturaElettronicaHeader');
$DatiTrasmissione=$FatturaElettronicaHeader->addChild('DatiTrasmissione');
$IdTrasmittente=$DatiTrasmissione->addChild('IdTrasmittente');
$IdTrasmittente->addChild('IdPaese', 'IT');
$IdTrasmittente->addChild('IdCodice','01234567890');
$ProgressivoInvio=$DatiTrasmissione->addChild('ProgressivoInvio', '00001');
$FormatoTrasmissione=$DatiTrasmissione->addChild('DatiTrasmissione', 'FPA12');
$CodiceDestinatario=$DatiTrasmissione->addChild('CodiceDestinatario', 'AAAAAA');
Because in my created file I initially had the prefix p: in each tag, as shown below
<p:FatturazioneElettronica xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="FPA12">
<p:FatturaElettronicaHeader>
<p:DatiTrasmissione>
<p:IdTrasmittente>
<p:IdPaese>IT</p:IdPaese>
<p:IdCodice>01234567890</p:IdCodice>
</p:IdTrasmittente>
<p:ProgressivoInvio>00001</p:ProgressivoInvio>
<p:DatiTrasmissione>FPA12</p:DatiTrasmissione>
<p:CodiceDestinatario>AAAAAA</p:CodiceDestinatario>
</p:DatiTrasmissione>
while this prefix p: must be only in the root node (p:FatturaElettronica) I added xmlns="http://dummy.com"
<p:FatturazioneElettronica xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="FPA12" xmlns="http://dummy.com">
and
$fatturaelettronicaheader = $xml->addChild('FatturaElettronicaHeader', '', 'http://dummy.com');
as it was suggested in this question
Only this 'http://dummy.com' is not present in the original xml file.
How can I solve this problem or possibly eliminate it before actually generating the file?
SimpleXML abstracts nodes and has some automatic logic for namespaces. That works fine for basic/simple XML structures.
For more complex XML structures you want to be explicit - so use DOM. It has specific methods for different node types with and without namespaces.
// define a list with the used namespaces
$namespaces = [
'xmlns' => 'http://www.w3.org/2000/xmlns/',
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'signature' => 'http://www.w3.org/2000/09/xmldsig#',
'wsdl-types' => 'http://microsoft.com/wsdl/types/'
];
$document = new DOMDocument('1.0', 'UTF-8');
// create and append an element with a namespace
// this will add the namespace definition for the prefix "p" also
$document->appendChild(
$root = $document->createElementNS($namespaces['wsdl-types'], 'p:FatturazioneElettronica')
);
// set an attribute without a namespace
$root->setAttribute('versione', 'FPA12');
// add namespace definitions using the reserved "xmlns" namespace
$root->setAttributeNS($namespaces['xmlns'], 'xmlns:xsi', $namespaces['xsi']);
$root->setAttributeNS($namespaces['xmlns'], 'xmlns:ds', $namespaces['signature']);
// create and append the an element - keep in variable for manipulation
// the element does not have a namespace
$root->appendChild(
$header = $document->createElement('FatturaElettronicaHeader')
);
$header->appendChild(
$dati = $document->createElement('DatiTrasmissione')
);
$dati->appendChild(
$id = $document->createElement('IdTrasmittente')
);
// create and append element, set text content using a chained call
$id
->appendChild($document->createElement('IdPaese'))
->textContent = 'IT';
$id
->appendChild($document->createElement('IdCodice'))
->textContent = '01234567890';
$dati
->appendChild($document->createElement('ProgressivoInvio'))
->textContent = '00001';
$dati
->appendChild($document->createElement('FormatoTrasmissione'))
->textContent = 'FPA12';
$dati
->appendChild($document->createElement('CodiceDestinatario'))
->textContent = 'AAAAAA';
$document->formatOutput = TRUE;
echo $document->saveXML();
Output:
<?xml version="1.0" encoding="UTF-8"?>
<p:FatturazioneElettronica xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" versione="FPA12">
<FatturaElettronicaHeader>
<DatiTrasmissione>
<IdTrasmittente>
<IdPaese>IT</IdPaese>
<IdCodice>01234567890</IdCodice>
</IdTrasmittente>
<ProgressivoInvio>00001</ProgressivoInvio>
<FormatoTrasmissione>FPA12</FormatoTrasmissione>
<CodiceDestinatario>AAAAAA</CodiceDestinatario>
</DatiTrasmissione>
</FatturaElettronicaHeader>
</p:FatturazioneElettronica>
Be aware that in your XML p:FatturazioneElettronica has a namespace. It resolves to {http://microsoft.com/wsdl/types/}FatturazioneElettronica. However I don't think that FatturazioneElettronica is a valid element in the WSDL types namespace.
FatturaElettronicaHeader (and the descandant nodes) do not have a namespace.
First, your desired xml (as well as the one in the question you link to) is not well formed for several reasons.
Second, even after that's fixed (see below), it's not clear to me why you're going about it the way you do.
How about this way:
$string = '<?xml version="1.0" encoding="UTF-8"?>
<root>
<p:FatturaElettronica xmlns:p="http://microsoft.com/wsdl/types/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="FPA12">
<FatturaElettronicaHeader>
<DatiTrasmissione>
<IdTrasmittente>
<IdPaese>IT</IdPaese>
<IdCodice>01234567890</IdCodice>
</IdTrasmittente>
<ProgressivoInvio>00001</ProgressivoInvio>
<FormatoTrasmissione>FPA12</FormatoTrasmissione>
<CodiceDestinatario>AAAAAA</CodiceDestinatario>
</DatiTrasmissione>
</FatturaElettronicaHeader>
</p:FatturaElettronica>
</root>';
$xml = simplexml_load_string($string);
echo $xml->asXML() ."\r\n";
That should echo your well-formed xml.
Let's say I have the following .xml file:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<name>Foo</name>
</item>
<item>
<name>Bar</name>
</item>
</root>
In this sample file, I'm trying to append new nodes <item> to node <root> after the last node <item>.
I'm trying to append newly created <item> nodes after the last <item> node in the <root> node in the .xml file.
<?php
$file = new DOMDocument;
$file->load("xml.xml");
$file->loadXML($file->saveXML());
$root = $file->getElementsByTagName('root')->item(0);
foreach (["Foo_1", "Bar_2", "Foo_3", "Bar_4"] as $val) {
$item = new DOMElement('item');
$item->appendChild(new DOMElement('name', $val));
$root->appendChild(item);
}
?>
But I'm getting an error:
Fatal error: Uncaught Error: Call to a member function appendChild() on null in C:\Users\pfort\Desktop\p.php:12
Stack trace:
#0 {main}
thrown in C:\Users\user_acer\Desktop\p.php on line 12
What am I doing wrong?
There's multiple issues with your example code. I will address the error you received first:
There is no element <terminy> in your example XML, so
$root = $file->getElementsByTagName('terminy')->item(0);
will return null. That's why you are receiving the
Call to a member function appendChild() on null
error at
$root->appendChild(item);
Also, item is a typo, because it's not a valid variable name (but a name for a non-existent constant); you meant $item.
I'm assuming "terminy" means something similar to "root" in your native language and that you actually meant to write
$root = $file->getElementsByTagName('root')->item(0);
By the way: if you want a reference to the root node of an XML document, you can also use $file->docomentElement.
However, there are other issues with your example code:
$file->load("xml.xml");
$file->loadXML($file->saveXML()); // why are you reloading it in this way?
The last line is unnecessary. You are reloading the same XML again. Is it for formatting purposes? If so, there's a better option available:
$file->preserveWhiteSpace = false;
$file->formatOutput = true;
$file->load("xml.xml");
Lastly: you cannot append children to a node that has not been associated with a document yet. So, to create a new item and associate it with the document, you either do (recommended):
// automatically associate new nodes with document
$item = $file->createElement('item');
$item->appendChild($file->createElement('name', $val));
or (more cumbersome):
// import nodes to associate them with document
$item = $file->importNode(new DOMElement('item'));
$item->appendChild($file->importNode(new DOMElement('name', $val)));
So, putting it all together it becomes:
<?php
$xml = <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<name>Foo</name>
</item>
<item>
<name>Bar</name>
</item>
</root>
XML;
$file = new DOMDocument;
$file->preserveWhiteSpace = false;
$file->formatOutput = true;
$file->loadXML($xml); // (for demo purpose loading above XML) replace this with $file->load("xml.xml"); in your actual code
$root = $file->documentElement;
foreach (["Foo_1", "Bar_2", "Foo_3", "Bar_4"] as $val) {
$item = $file->createElement('item');
$item->appendChild($file->createElement('name', $val));
$root->appendChild($item);
}
echo $file->saveXML();
**PROBLEM SOLVED**
I lost too much time on this problem. The good news is, I already know how to get what I need. Here I offer a solution - for everyone who will need to solve the same problem.
Perhaps this solution will be useful for anyone who needs it.
<?php
// snippet of xml temple
$xml = <<<XML
<item date="%s" status="%s">
<name>%s</name>
</item>
XML;
// prepare snippet
$xmlSnippet = sprintf($xml, "2022-11-21", 0, "Foo Bar");
// new DOMDocument
$dom = new DOMDocument;
$dom->preserveWhiteSpace = 0;
$dom->formatOutput = 1;
// load of .xml file content and load to DOMDocument object
$file = simplexml_load_file("xml.xml");
$dom->loadXML($file->asXML());
// creating of fragment from snippet
$fragment = $dom->createDocumentFragment();
$fragment->appendXML($xmlSnippet);
//append the snippet to the DOMDocument
// and save it to the xml.xml file
$dom->documentElement->appendChild($fragment);
$dom->save("xml.xml");
?>
Result:
I have the xml below
<?xml version="1.0" encoding="UTF-8"?>
<!--Sample XML file generated by XMLSpy v2013 (http://www.altova.com)-->
<ftc:FATCA_OECD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ftc="urn:oecd:ties:fatca:v2" xmlns:sfa="urn:oecd:ties:stffatcatypes:v2" version="2.0" xsi:schemaLocation="urn:oecd:ties:fatca:v2 FatcaXML_v2.0.xsd">
<ftc:MessageSpec>
<sfa:SendingCompanyIN>S519K4.99999.SL.392</sfa:SendingCompanyIN>
<sfa:TransmittingCountry>JP</sfa:TransmittingCountry>
<sfa:ReceivingCountry>US</sfa:ReceivingCountry>
<sfa:MessageType>FATCA</sfa:MessageType>
<sfa:MessageRefId>DBA6455E-8454-47D9-914B-FEE48E4EF3AA</sfa:MessageRefId>
<sfa:ReportingPeriod>2016-12-31</sfa:ReportingPeriod>
<sfa:Timestamp>2017-01-17T09:30:47Z</sfa:Timestamp>
<ftc:SendingCompanyIN>testing</ftc:SendingCompanyIN></ftc:MessageSpec>
<ftc:FATCA>
<ftc:ReportingFI>
<sfa:ResCountryCode>JP</sfa:ResCountryCode>
<sfa:TIN>S519K4.99999.SL.392</sfa:TIN>
<sfa:Name>Bank of NN</sfa:Name>
<sfa:Address>
<sfa:CountryCode>JP</sfa:CountryCode>
<sfa:AddressFree>123 Main Street</sfa:AddressFree>
</sfa:Address>
<ftc:DocSpec>
<ftc:DocTypeIndic>FATCA1</ftc:DocTypeIndic>
<ftc:DocRefId>S519K4.99999.SL.392.50B80D2D-79DA-4AFD-8148-F06480FFDEB5</ftc:DocRefId>
</ftc:DocSpec>
</ftc:ReportingFI>
<ftc:ReportingGroup>
<ftc:NilReport>
<ftc:DocSpec>
<ftc:DocTypeIndic>FATCA1</ftc:DocTypeIndic>
<ftc:DocRefId>S519K4.99999.SL.392.CE54CA78-7C31-4EC2-B73C-E387C314F426</ftc:DocRefId>
</ftc:DocSpec>
<ftc:NoAccountToReport>yes</ftc:NoAccountToReport>
</ftc:NilReport>
</ftc:ReportingGroup>
</ftc:FATCA>
</ftc:FATCA_OECD>
I want to change node value, sfa:TIN and save the xml in a new file. How can this be accomplished in PHP? I got examples but none used namespaces.
One way you could do this is using DOMDocument and DOMXPath and find your elements using for example an xpath expression which will find the 'TIN' elements in the sfa namespace.
/ftc:FATCA_OECD/ftc:FATCA/ftc:ReportingFI/sfa:TIN
To update the value of the first found elemement you could take the first item from the DOMNodeList which is returned by query.
$doc = new DOMDocument();
$doc->loadXML($data);
$xpath = new DOMXPath($doc);
$res = $xpath->query("/ftc:FATCA_OECD/ftc:FATCA/ftc:ReportingFI/sfa:TIN");
if ($res->length > 0) {
$res[0]->nodeValue = "test";
}
$doc->save("yourfilename.xml");
Demo
You can use the following solution, using DOMDocument::getElementsByTagNameNS:
<?php
$dom = new DOMDocument();
$dom->load('old-file.xml');
//get all TIN nodes.
$nodesTIN = $dom->getElementsByTagNameNS('urn:oecd:ties:stffatcatypes:v2', 'TIN');
//check for existing TIN node.
if (count($nodesTIN) === 1) {
//update the first TIN node.
$nodesTIN->item(0)->nodeValue = 'NEWVALUE_OF_TIN';
}
//save the file to a new one.
$dom->save('new-file.xml');
I'm in the process of writing an XML file:
<?php
$xml2 = "currenttest";
$xml = new DOMDocument("1.0");
$root = $xml->createElement ('tv');
$xml->appendChild($root);
$root->appendChild($xml->createTextNode("\n"));
$root->appendChild($xml->createTextNode($xml2));
$root->appendChild($xml->createTextNode("\n"));
$xml->save('epg.xml');
XML:
<?xml version="1.0"?>
<tv>
test
</tv>
If i change the text and again runs the code, the old content is deleted.
And I want the old text to stay.
Let's say this:
<?xml version="1.0"?>
<tv>
currenttest...
newtest...
</tv>
My previous way was to write the XML with:
file_put_contents($file, $xml2, FILE_APPEND | LOCK_EX);
FILE_APPEND | LOCK_EX, its helped me that the previous text would not be erased
I found a solution in another post:
$doc->loadXML(file_get_contents('epg.xml'));
foreach($doc->getElementsByTagName('***') as $node)
{
}
But how can it fit into my code?
You have nothing particular to do, just to reload your xml string and to append a new text node to your root element:
// your previous code (I only changed the variable names and added a default encoding)
$text = "currenttest";
$dom = new DOMDocument("1.0", "UTF-8");
$root = $dom->createElement('tv');
$dom->appendChild($root);
$root->appendChild($dom->createTextNode("\n"));
$root->appendChild($dom->createTextNode($text));
$root->appendChild($dom->createTextNode("\n"));
$xml = $dom->saveXML();
// let's add a new element
$newtext = 'newtext';
$dom = new DOMDocument;
$dom->loadXML($xml);
$root = $dom->documentElement; // conveniant way to target the root element
// but you can also write:
//$root = $dom->getElementsByTagName('tv')->item(0);
$root->appendChild($dom->createTextNode($newtext));
$newxml = $dom->saveXML();
echo $newxml;
demo
About $doc->loadXML(file_get_contents('epg.xml'));, note that you don't need to use file_get_contents since DOMDocument has already two methods:
DOMDocument::loadXML that loads the xml content from a string.
DOMDocument::load that loads the xml content directly from a file.
In addition to DOMNode::appendChild that adds a node to an element after all the children nodes of this element, you have also DOMNode::insertBefore to add a node to an element before the child node of your choice.
I tryed the code on top, 'cause i was overwriting my data, but when I coded in my application, it didn't worked cause I was trying to add the new node data in the loaded xml, you have to create a root to add data inside.
$xml = new DOMDocument("1.0", "UTF-8");
//an tag root must be first thing to add
$root = $xml->createElement('root');
$xml->appendChild($root);
Then, just add the data when you need
$xml = new DOMDocument("1.0", "UTF-8");
$xml->load($sFilepath);
$root = $xml->getElementsByTagName('root')->item(0);
your structure must looks like this:
<xml version="1.0" encoding="UTF-8">
<root>
</root>
The answer on top is totally correct. This answer is only to help if somebody is having trouble to understand.
I have code which add item like below to xml file:
<newWord>
<Heb>rer</Heb>
<Eng>twew</Eng>
</newWord>
the problem is when I add element it will be not in the right place, it is out from xml tag like below.
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<newWord>
<Heb>hebword</Heb>
<Eng>banna</Eng>
</newWord>
</xml>
<newWord>
<Heb>rer</Heb>
<Eng>twew</Eng>
</newWord>
How can I add the new element to correct place? thx
my code:
<?php
$wordH=$_GET['varHeb'];
$wordE=$_GET['varEng'];
$domtree='';
if(!$domtree)
{
$domtree = new DOMDocument('1.0', 'UTF-8');
$domtree->formatOutput = true;
$domtree->load('Dictionary_user.xml');
}
$Dictionary_user = $domtree->documentElement;
$currentitem = $domtree->createElement("newWord");
$currentitem = $domtree->appendChild($currentitem);
$currentitem->appendChild($domtree->createElement('Heb', $wordH));
$currentitem->appendChild($domtree->createElement('Eng',$wordE));
$Dictionary_user->childNodes->item(0)->parentNode->insertBefore($currentitem,$Dictionary_user->childNodes->item(0));
header("Content-type: text/xml");
$domtree->save("Dictionary_user.xml");
/* get the xml printed */
echo $domtree->saveXML();
?>
Perhaps you want something like:
<?php
if(!empty($_GET['varHeb']) && !empty($_GET['varEng'])){
//Dont forget utf-8 if using Hebrew letters
header('Content-type: text/xml; charset=utf-8');
//Load It
$xml = simplexml_load_file('./Dictionary_user.xml');
//Add a new node & add the children
$node = $xml->addChild('newWord');
$node->addChild('Heb', trim($_GET['varHeb']));
$node->addChild('Eng', trim($_GET['varEng']));
//DOMDocument to format code output
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($xml->asXML());
echo $dom->saveXML();
}else{
//params not set for $_GET
}
/**
* Result
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<newWord>
<Heb>hebword</Heb>
<Eng>banna</Eng>
</newWord>
<newWord>
<Heb>אנחנו אוהבים גלישת מחסנית</Heb>
<Eng>We Love Stack overflow</Eng>
</newWord>
</xml>
*/
The issue is you doing:
$currentitem = $domtree->createElement("newWord");
$currentitem = $domtree->appendChild($currentitem);
Change it to
$currentitem = $domtree->createElement("newWord");
$currentitem = $domtree->documentElement->appendChild($currentitem);
This will them append to the root node.
There is also few other things to be improved in your code:
$wordH=$_GET['varHeb'];
$wordE=$_GET['varEng'];
Make sure you sanitize/filter this content. DOM is quite good at making sure no malicious content will be inserted, but anything coming from the outside world should be sanity checked.
$domtree='';
if(!$domtree)
{
This is rather pointless to do. You made $domtree an empty string, so the if block will always get triggered. Remove that part and simply load the XML.
$domtree = new DOMDocument('1.0', 'UTF-8');
$domtree->formatOutput = true;
$domtree->load('Dictionary_user.xml');
}
When you load a string or file with DOM, it will discard any arguments you put into the constructor and use the arguments found in the xml prolog of the string or file instead. So you do not need to supply them when newing the DOMDocument.
$Dictionary_user = $domtree->documentElement;
This is the root node (<xml>) you want to append to.
$currentitem = $domtree->createElement("newWord");
$currentitem = $domtree->appendChild($currentitem);
This is where the error is happening. You create a new element and then append it to the $domtree, which is the document as a whole. In an XPath query, $domtree is / while you want to append to /xml, e.g. the root element.
$currentitem->appendChild($domtree->createElement('Heb', $wordH));
$currentitem->appendChild($domtree->createElement('Eng',$wordE));
This works as expected. You are adding to <newWord>
$Dictionary_user
->childNodes
->item(0)
->parentNode
->insertBefore($currentitem, $Dictionary_user->childNodes->item(0));
You are traversing from the root element (<xml>) to the first child element and then back up to the parent, which is the root element again obviously. So the entire traversal is not necessary. In fact, unless you want to move the appended <newWord> above the first child of the root element, the entire block is not necessary at all.