How to delete a specific element from xml file - php

I want to delete:
<newWord>
<Heb>צהוב</Heb>
<Eng>yellow</Eng>
</newWord>
from:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<newWord>
<Heb>מילה ראשונה</Heb>
<Eng>first word</Eng>
</newWord>
<newWord>
<Heb>צהוב</Heb>
<Eng>yellow</Eng>
</newWord>
</xml>
so the output will be:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<newWord>
<Heb>מילה ראשונה</Heb>
<Eng>first word</Eng>
</newWord>
</xml>
I try to find the tag <newWord> and after this to go to child of it <Eng>yellow</Eng>
and if i found it by $searchString = 'yellow'; I should need to go to parrent of it and delete the element <newWord>.
I try to do it by the following code but I do not know ho to go to child of the <newWord>. many thx for helping.
this my code:
<?php
$del=true;
if ($del==TRUE){
$searchString = 'yellow';
header('Content-type: text/xml; charset=utf-8');
$xml = simplexml_load_file('./Dictionary_user.xml');
foreach($xml->children() as $child){
if($child->getName() == "newWord") {
if($searchString == $child['Eng']) {
$dom->parentNode->removeChild($xml);
} else {
echo('no match found resualt');
}
}
}
$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->formatOutput = true;
$dom->load('Dictionary_user.xml');
$dom->save("Dictionary_user.xml");
$dom->saveXML();
header('Location: http://127.0.0.1/www/www1/ajax/ajax4/workwell/popus1.html');
}
?>

Try this:
$searchString = 'yellow';
$xml = simplexml_load_file('./Dictionary_user.xml');
foreach($xml->children() as $child){
if($child->getName() == "newWord") {
if($child->Eng == $searchString){
$dom = dom_import_simplexml($child);
$dom->parentNode->removeChild($dom);
}
}
}
echo $xml->asXML();

On this line
if($searchString == $child['Eng']) {
You're trying to compare the body of the child node, but it doesn't convert to a string automatically. It's still a SimpleXMLElement object, so the comparison fails.
Try explicitly casting it to a string to get the body of the tag.
if($searchString == (string)$child['Eng']) {

Related

Replace HTML tags with DOMdocument while keeping nested tags [duplicate]

I'm trying to figure out how to rename a node in XML using PHP?
I Have come this far:
$dom = new DOMDocument( '1.0' );
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
// load the xml file
$dom->loadXML( '<?xml version="1.0" encoding="ISO-8859-1"?>
<library>
<data>
<invite>
<username>jmansa</username>
<userid>1</userid>
</invite>
<update>1</update>
</data>
</library>', LIBXML_NOBLANKS );
$xpath = new DOMXPath($dom);
//find all 'data' nodes.
$node = $xpath->query("//data");
// if found
if( $node->length ) {
foreach ($node as $n) {
// RENAME HERE? //
}
}
echo "<xmp>". $dom->saveXML() ."</xmp>";
Now, I want to rename <data> to <invites>. Can this be done and if yes, how?
A Node's name ("data" or "invites" respectively) cannot be renamed via the DOM because the Node::nodeName property is read-only.
You can create a new node named "invites", append it before the "data" node, move the children of "data" to the new "invites" node, remove the "data" node, and then output the tree to get your result.
Example:
<?php
// Create a test document.
$dom = new DOMDocument( '1.0' );
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
// Load the xml file.
$dom->loadXML('<?xml version="1.0" encoding="ISO-8859-1"?'.'>
<library>
<data attr1="1" attr2="2">
<invite>
<username>jmansa</username>
<userid>1</userid>
</invite>
<update>1</update>
</data>
</library>', LIBXML_NOBLANKS );
$xpath = new DOMXPath($dom);
// Convert <data> to <invites>.
if ($dataNode = $xpath->query("/library/data")->item(0))
{
// Create the <invites> node.
$invitesNode = $dom->createElement('invites');
$dataAttrs = $dataNode->attributes;
foreach ($dataAttrs as $dataAttr)
{ $invitesNode->setAttributeNodeNS($dataAttr->cloneNode()); }
$dom->documentElement->appendChild($invitesNode);
// Move the <data> children over.
if ($childNodes = $xpath->query("/library/data/*"))
{
foreach ($childNodes as $childNode)
{ $invitesNode->appendChild($childNode); }
}
// Remove <data>.
$dataNode->parentNode->removeChild($dataNode);
}
// Test the result.
echo $dom->saveXML();
?>
My solution, with extended test case:
// Changes the name of element $element to $newName.
function renameElement($element, $newName) {
$newElement = $element->ownerDocument->createElement($newName);
$parentElement = $element->parentNode;
$parentElement->insertBefore($newElement, $element);
$childNodes = $element->childNodes;
while ($childNodes->length > 0) {
$newElement->appendChild($childNodes->item(0));
}
$attributes = $element->attributes;
while ($attributes->length > 0) {
$attribute = $attributes->item(0);
if (!is_null($attribute->namespaceURI)) {
$newElement->setAttributeNS('http://www.w3.org/2000/xmlns/',
'xmlns:'.$attribute->prefix,
$attribute->namespaceURI);
}
$newElement->setAttributeNode($attribute);
}
$parentElement->removeChild($element);
}
function prettyPrint($d) {
$d->formatOutput = true;
echo '<pre>'.htmlspecialchars($d->saveXML()).'</pre>';
}
$d = new DOMDocument( '1.0' );
$d->loadXML('<?xml version="1.0"?>
<library>
<data a:foo="1" x="bar" xmlns:a="http://example.com/a">
<invite>
<username>jmansa</username>
<userid>1</userid>
</invite>
<update>1</update>
</data>
</library>');
$xpath = new DOMXPath($d);
$elements = $xpath->query('/library/data');
if ($elements->length == 1) {
$element = $elements->item(0);
renameElement($element, 'invites');
}
prettyPrint($d);
By the way, I added this solution as a comment to the PHP documentation for DOMElement.

How to replace a special xml tag by using php

I have a xml file such as this:
<?xml version="1.0"?>
<datas>
<books>
<book>
<id>1</id>
<title>PHP Undercover</title>
<author>Wiwit Siswoutomo</author>
</book>`enter code here`
<book>
<id>2</id>
<title>PHP Enterprise</title>
<author>Wiwit Siswoutomo</author>
</book>
</books>
</datas>
and now i wana to replace a special tag in this way:
search in xml file and if it has a PHP Enterprise ,find it and replace it by 'new title'.
What should i do?
TNX
You can parse the document with SimpleXML:
$datas = new SimpleXMLElement("my.xml");
foreach ($datas->books->book as $book) {
if (preg_match('/PHP Enterprise/', $book->title) {
$book->title = "new title";
}
}
$datas->asXML("my.xml");
This script will help you!! Try this :)
<?php
function replace_Special_Str($mystring)
{
//Load file
$filename="./myfile.xml";
if (!file_exists($filename)) { echo "There is not a myfile.xml file in the directory."; exit;}
$xml = simplexml_load_file($filename);
//search and replace particular node by book title
$node = $xml->xpath('/datas/books[title="' . $mystring. '"]');
if(sizeof($node) > 0)
{
$node[0]->title = 'My Title';
}
$xml->asXML('./aucstatus.xml');
}
?>
OR Try This,
<users>
<name>John</name>
<address>My Address</address>
<zipcode>12345</zipcode>
<city>My City</city>
<phone>555 1234-4321</phone>
</users>
PHP FILE
fopen('users.xml');
while ($users->read()) {
switch ($users->nodeType) {
case (XMLReader::ELEMENT):
if ($users->localName == "users") {
$node = $reader->expand();
$dom = new DomDocument();
$n = $dom->importNode($node,true);
$dom->appendChild($n);
$simple_xml = simplexml_import_dom($n);
$id = $simple_xml['id'];
$name = $simple_xml->name;
$address = $simple_xml->address;
// Custom code insert, update, whatever...
}
}
}

Rename an XML node using PHP

I'm trying to figure out how to rename a node in XML using PHP?
I Have come this far:
$dom = new DOMDocument( '1.0' );
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
// load the xml file
$dom->loadXML( '<?xml version="1.0" encoding="ISO-8859-1"?>
<library>
<data>
<invite>
<username>jmansa</username>
<userid>1</userid>
</invite>
<update>1</update>
</data>
</library>', LIBXML_NOBLANKS );
$xpath = new DOMXPath($dom);
//find all 'data' nodes.
$node = $xpath->query("//data");
// if found
if( $node->length ) {
foreach ($node as $n) {
// RENAME HERE? //
}
}
echo "<xmp>". $dom->saveXML() ."</xmp>";
Now, I want to rename <data> to <invites>. Can this be done and if yes, how?
A Node's name ("data" or "invites" respectively) cannot be renamed via the DOM because the Node::nodeName property is read-only.
You can create a new node named "invites", append it before the "data" node, move the children of "data" to the new "invites" node, remove the "data" node, and then output the tree to get your result.
Example:
<?php
// Create a test document.
$dom = new DOMDocument( '1.0' );
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
// Load the xml file.
$dom->loadXML('<?xml version="1.0" encoding="ISO-8859-1"?'.'>
<library>
<data attr1="1" attr2="2">
<invite>
<username>jmansa</username>
<userid>1</userid>
</invite>
<update>1</update>
</data>
</library>', LIBXML_NOBLANKS );
$xpath = new DOMXPath($dom);
// Convert <data> to <invites>.
if ($dataNode = $xpath->query("/library/data")->item(0))
{
// Create the <invites> node.
$invitesNode = $dom->createElement('invites');
$dataAttrs = $dataNode->attributes;
foreach ($dataAttrs as $dataAttr)
{ $invitesNode->setAttributeNodeNS($dataAttr->cloneNode()); }
$dom->documentElement->appendChild($invitesNode);
// Move the <data> children over.
if ($childNodes = $xpath->query("/library/data/*"))
{
foreach ($childNodes as $childNode)
{ $invitesNode->appendChild($childNode); }
}
// Remove <data>.
$dataNode->parentNode->removeChild($dataNode);
}
// Test the result.
echo $dom->saveXML();
?>
My solution, with extended test case:
// Changes the name of element $element to $newName.
function renameElement($element, $newName) {
$newElement = $element->ownerDocument->createElement($newName);
$parentElement = $element->parentNode;
$parentElement->insertBefore($newElement, $element);
$childNodes = $element->childNodes;
while ($childNodes->length > 0) {
$newElement->appendChild($childNodes->item(0));
}
$attributes = $element->attributes;
while ($attributes->length > 0) {
$attribute = $attributes->item(0);
if (!is_null($attribute->namespaceURI)) {
$newElement->setAttributeNS('http://www.w3.org/2000/xmlns/',
'xmlns:'.$attribute->prefix,
$attribute->namespaceURI);
}
$newElement->setAttributeNode($attribute);
}
$parentElement->removeChild($element);
}
function prettyPrint($d) {
$d->formatOutput = true;
echo '<pre>'.htmlspecialchars($d->saveXML()).'</pre>';
}
$d = new DOMDocument( '1.0' );
$d->loadXML('<?xml version="1.0"?>
<library>
<data a:foo="1" x="bar" xmlns:a="http://example.com/a">
<invite>
<username>jmansa</username>
<userid>1</userid>
</invite>
<update>1</update>
</data>
</library>');
$xpath = new DOMXPath($d);
$elements = $xpath->query('/library/data');
if ($elements->length == 1) {
$element = $elements->item(0);
renameElement($element, 'invites');
}
prettyPrint($d);
By the way, I added this solution as a comment to the PHP documentation for DOMElement.

Wrap an element for each set of elements with SimpleXML/DOMDocument

I have the code below to create a XML file
<?php
try
{
$dom = new domDocument;
$dom->formatOutput = true;
$root = $dom->appendChild($dom->createElement( "items" ));
$sxe = simplexml_import_dom( $dom );
$sxe->addChild("model", "HTC Desire");
$sxe->addChild("model", "Motorola Atrix");
echo $sxe->asXML();
}
catch( Exception $e )
{
echo $e->getMessage();
}
?>
While execute this code, it will generate the content likes:
<?xml version="1.0"?>
<items>
<model>HTC Desire</model>
<model>Motorola Atrix</model>
</items>
But, I would like to wrap an element called item for each model, the result should be:
<?xml version="1.0"?>
<items>
<item><model>HTC Desire</model></item>
<item><model>Motorola Atrix</model></item>
</items>
Anyone could suggest how to do this?
The addChild method returns a SimpleXMLElement object representing the child added to the XML node. This allows for method chaining like so:
try
{
$dom = new domDocument;
$dom->formatOutput = true;
$root = $dom->appendChild($dom->createElement( "items" ));
$sxe = simplexml_import_dom($dom);
$sxe->addChild("item")->addChild("model", "HTC Desire");
$sxe->addChild("item")->addChild("model", "Motorola Atrix");
echo $sxe->asXML();
}
catch( Exception $e )
{
echo $e->getMessage();
}

How do extract child element in XML using DOM in PHP 5.0?

I am having the XML like this
<?xml version="1.0" encoding="utf-8"?>
<root>
<mynode catid="10" catname="Animals" label="Animals" catdesc="" parent_id="2">
<mynode catid="11" catname="Lions" label="Lions" catdesc="" parent_id="10">
<mynode catid="12" catname="lion" label="lion" catdesc="" parent_id="11"/>
<mynode catid="13" catname="lioness" label="lioness" catdesc="" parent_id="11"/>
</mynode>
</mynode>
</root>
From this I want to remove
<?xml version="1.0" encoding="utf-8"?>
<root>
and
</root>
So expected result is
<mynode catid="10" catname="Animals" label="Animals" catdesc="" parent_id="2">
<mynode catid="11" catname="Lions" label="Lions" catdesc="" parent_id="10">
<mynode catid="12" catname="lion" label="lion" catdesc="" parent_id="11"/>
<mynode catid="13" catname="lioness" label="lioness" catdesc="" parent_id="11"/>
</mynode>
</mynode>
How can I do this?
Edit 1:TO Phil
$dom = new DomDocument();
//$dom->preserveWhitespace = false;
$dom->load('treewithchild.xml');
function DOMinnerHTML($element)
{
$innerHTML = "";
$children = $element->childNodes;
foreach ($children as $child)
{
$tmp_dom = new DOMDocument();
$tmp_dom->appendChild($tmp_dom->importNode($child, true));
$innerHTML.=trim($tmp_dom->saveXML());
echo $tmp_dom->saveXML();
}
return $innerHTML;
}
$dom->preserveWhiteSpace = false;
$domTable = $dom->getElementsByTagName("mynode");
foreach ($domTable as $tables)
{
//echo $tables;
DOMinnerHTML($tables);
}
As you want the inner markup of the <root> node, that is the element who's child nodes you'll want to iterate. You can access this element using the DOMDocument::documentElement property.
Try this (tested and working)
$doc = new DOMDocument;
$doc->load('treewithchild.xml');
$inner = '';
foreach ($doc->documentElement->childNodes as $child) {
$inner .= $doc->saveXML($child);
}
echo $inner;
I expect that the root element is returned also, you have to know that for each xml file an is added impliicitly, even if it exists in your file. so try to do this
$children = $element->childNodes->childNodes;
i think that would help you.

Categories