How to delete xml Dom document in php - php

I'd search for this problem and find some questions but they didn't mention to my error...
I'm trying to remove a child of my DOM document and when I type the $x->removeChild($key); function, nothing happend...
$xmlreq = new DOMDocument;
$xmlreq->loadXML($xmlStr);
$x = $xmlreq->getElementsByTagName('*');
foreach($x as $key)
{
if (substr($key->nodeValue,0,3)=="{{{" and substr($key->nodeValue,-3)=="}}}")
{
$field = explode("|",substr($key->nodeValue,3,strlen($key->nodeValue)-6));
if((int)$field[3]==0)
{
if(trim($_POST[$field[2]])=="")
{
$x->removeChild($key);
}else{
$key->nodeValue = trim($_POST[$field[2]]);
}
}elseif((int)$field[3]==1)
{
if(trim($_POST[$field[2]])=="")
{
$errors.="";
}else{
$key->nodeValue = trim($_POST[$field[2]]);
}
}else{
}
}
}
header("content-type: application/xml");
print $xmlreq->saveXml();
and this is my xml:
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<contact:check xmlns:contact="http://epp.nic.ir/ns/contact-1.0">
<contact:id>ghhg-ghgh</contact:id>
<contact:id>45</contact:id>
<contact:id>45</contact:id>
<contact:id>45</contact:id>
<contact:authInfo>
<contact:pw>1561651321321</contact:pw>
</contact:authInfo>
</contact:check>
</check>
<clTRID>TEST-12345</clTRID>
</command>
</epp>
and I want to delete one of <contact:id>45</contact:id>

Your loop does nothing since the outer conditional is looking for a node where nodeValue starts with {{{ and ends with }}}:
foreach($x as $key)
{
if (substr($key->nodeValue,0,3)=="{{{" and substr($key->nodeValue,-3)=="}}}")
Additionally, there's no removeChild() method in DOMNodeList. You probably want to fetch the node's parent first and call its removeChild() method instead.
A possible alternative:
$x = $xmlreq->getElementsByTagName('*');
$remove = TRUE;
foreach($x as $key)
{
if( $key->nodeName=='contact:id' && $key->nodeValue=='45' ){
if($remove){
$key->parentNode->removeChild($key);
$remove = FALSE;
}
}
}

Related

How to loop through two XML files and print result

I've been trying unsuccessfully with PHP to loop through two XML files and print the result to the screen. The aim is to take a country's name and output its regions/states/provinces as the case may be.
The first block of code successfully prints all the countries but the loop through both files gives me a blank screen.
The countries file is in the format:
<row>
<id>6</id>
<name>Andorra</name>
<iso2>AD</iso2>
<phone_code>376</phone_code>
</row>
And the states.xml:
<row>
<id>488</id>
<name>Andorra la Vella</name>
<country_id>6</country_id>
<country_code>AD</country_code>
<state_code>07</state_code>
</row>
so that country_id = id.
This gives a perfect list of countries:
$xml = simplexml_load_file("countries.xml");
$xml1 = simplexml_load_file("states.xml");
foreach($xml->children() as $key => $children) {
print((string)$children->name); echo "<br>";
}
This gives me a blank screen except for the HTML stuff on the page:
$xml = simplexml_load_file("countries.xml");
$xml1 = simplexml_load_file("states.xml");
$s = "Jamaica";
foreach($xml->children() as $child) {
foreach($xml1->children() as $child2){
if ($child->id == $child2->country_id && $child->name == $s) {
print((string)$child2->name);
echo "<br>";
}
}
}
Where have I gone wrong?
Thanks.
I suspect your problem is not casting the name to a string before doing your comparison. But why are you starting the second loop before checking if it's needed? You're looping through every single item in states.xml needlessly.
$countries = simplexml_load_file("countries.xml");
$states = simplexml_load_file("states.xml");
$search = "Jamaica";
foreach($countries->children() as $country) {
if ((string)$country->name !== $search) {
continue;
}
foreach($states->children() as $state) {
if ((string)$country->id === (string)$state->country_id) {
echo (string)$state->name . "<br/>";
}
}
}
Also, note that naming your variables in a descriptive manner makes it much easier to figure out what's going on with code.
You could probably get rid of the loops altogether using an XPath query to match the sibling value. I don't use SimpleXML, but here's what it would look like with DomDocument:
$search = "Jamaica";
$countries = new DomDocument();
$countries->load("countries.xml");
$xpath = new DomXPath($countries);
$country = $xpath->query("//row[name/text() = '$search']/id/text()");
$country_id = $country[0]->nodeValue;
$states = new DomDocument();
$states->load("states.xml");
$xpath = new DomXPath($states);
$states = $xpath->query("//row[country_id/text() = '$country_id']/name/text()");
foreach ($states as $state) {
echo $state->nodeValue . "<br/>";
}

How to update an xml file on filesystem conditionally - PHP

I have the xml file called fonts.xml located on my filesystem.
Goal:
I want to update the attribute <status> where name is "Aclonica" but I don't know how to do it conditionally.
XML:
<fonts>
<font>
<name>Aclonica</name>
<category>Aclonica</category>
<variants>100,bold</variants>
<status>active</status>
</font>
<font>
<name>Azeebe</name>
<category>Sans-serif</category>
<variants>100,bold,italic</variants>
<status>active</status>
</font>
</fonts>
You need to use DOMDocument class. This way you select data using normal if condition:
solution:
$a = $_POST['font']; // here value 'Aclonica' is assigned to $a
$dom = new DOMDocument();
$dom->load('c:/xampp/htdocs/cms/public/fonts/font.xml');
foreach ($dom->documentElement->childNodes as $node) {
// print_r($node); // >> uncomment for debug purposes
if($node->nodeType == 1) {
$name = $node->getElementsByTagName('name')->Item(0);
if($name->nodeValue == $a) { // >> IMPORTANT: here is the condition you need
$OldJobId = $node->getElementsByTagName('status')->Item(0);
if($OldJobId->nodeValue == 'active') {
$newelement = $dom->createElement('status','inactive');
$OldJobId->parentNode->replaceChild($newelement, $OldJobId);
}else{
$newelement = $dom->createElement('status','active');
$OldJobId->parentNode->replaceChild($newelement, $OldJobId);
}
}
}
}
$dom->save("c:/xampp/htdocs/cms/public/fonts/font.xml");

simplexml doesn't read CDATA

I want to grab data from a xml file from a remote location which contains CDATA information in all nodes as listed below.
I use the following PHP function to grab such information but it doesn't work and seems not to be able to catch CDATA tags from xml file.
the question is whether my piece of code is correct or not ? and if it's wrong can you suggest any php code to get requested information?
<Items>
<Item ID="1">
<Name>Mountain</Name>
<Properties>
<Property Code="feature"><![CDATA[<ul><li>sample text</li></ul>]]></Property>
<Property Code="SystemRequirements"><![CDATA[Windows XP/Windows Vista]]></Property>
<Property Code="Description" Type="plain"><![CDATA[sample text2]]></Property>
</Properties>
</Item>
<Items>
and this is my php code :
<?
function xmlParse($file, $wrapperName, $callback, $limit = NULL) {
$xml = new XMLReader();
if (!$xml->open($file)) {
die("Failed to open input file.");
}
$n = 0;
$x = 0;
while ($xml->read()) {
if ($xml->nodeType == XMLReader::ELEMENT && $xml->name == $wrapperName) {
while ($xml->read() && $xml->name != $wrapperName) {
if ($xml->nodeType == XMLReader::ELEMENT) {
//$subarray[]=$xml->expand();
$doc = new DOMDocument('1.0', 'UTF-8');
$simplexml = simplexml_import_dom($doc->importNode($xml->expand(), true));
$subarray[]=$simplexml;
}
}
if ($limit == NULL || $x < $limit) {
if ($callback($subarray)) {
$x++;
}
unset($subarray);
}
$n++;
}
}
$xml->close();
}
echo '<pre>';
function func1($s) {
print_r($s);
}
xmlParse('myfile.xml', 'Item', 'func1', 100);
When I print this object by print_r($s); I can't see CDATA in result !.
do you have any idea in order to retrieve CDATA context ?
Treat it like a string
$file = "1.xml";
$xml = simplexml_load_file($file);
foreach($xml->Item->Properties->children() as $properties) {
printf("%s", $properties);
}
Output
<ul><li>sample text</li></ul>
Windows XP/Windows Vista
sample text2
There is allways way to use DOMDocument to open xml files, for example:
$xmlFile = new DOMDocument();
$xmlFile->load(myfile.xml);
echo $xmlFile->getElementsByTagName('Property')->item(0)->nodeValue;

Getting nodes by attribute value in DomXML and PHP

I am trying to select a specific node to edit its content and attributes later on, but I am not able to select a notice node (see the PHP code below).
XML document
<?xml version="1.0" encoding="UTF-8"?>
<notices lastID="0001">
<!--
<notice id="0000" endDate="31-12-2025">
Content of the notice.
</notice>
-->
<notice id="0001" endDate="13-01-2013" active="1">
One amazing notice.
</notice>
</notices>
The $id value is "0001" (string).
PHP
$document = new DOMDocument;
$document = dom_import_simplexml($this->xml);
$notices= $document->getElementsByTagName('notice');
#var_dump($notices);
foreach($notices as $element)
{
if($element->getAttribute('id') == $id)
{
$notice = $element;
var_dump($notice); //Returns absolutely nothing (I guess the if returns false).
}
}
$notice->removeAttribute("endDate");
$notice->setAttribute("endDate",$endDate);
Everytime I fall into the if statement, my $notice returns no value.
I tried with xpath query ( //notice[#id="{$id}"]) without any success.
To clarify, my problem would be $element->getAttribute('id') does not seem to work.
I also tried with SimpleXML:
PHP
$document = new DOMDocument;
$document = simplexml_import_dom($this->xml);
$notice = "";
foreach($document->notices->children() as $element)
{
$attributes = $element->attributes();
if($attributes['id'] == $id)
{
$notice= $element;
var_dump($notice);
}
}
$avis->removeAttribute("endDate");
$avis->setAttribute("endDate",$endDate);
SimpleXML gives me the following message: Node no longer exists on the following line:
foreach($document->notices->children() as $element)
I finally got it.
PHP
$document = simplexml_import_dom($this->xml);
$notice = "";
$xpathResults = $document->xpath('//notice');
foreach($xpathResults as $element)
{
$elementID = $element->id[0];
$domXML = dom_import_simplexml($element);
if((string) $noticeID == $id)
{
$notice = $domXML;
}
}

PHP DOM remove child

I am trying to remove the parent node of <wcccanumber> from my xml, if it's content matches a certain criterion, but it keeps just removing the one node <wcccanumber>. How do I remove the whole parent node?
Heres my code:
$xml = new SimpleXMLElement('<xml/>');
if (file_exists("xml/units/E01.xml")) {
$xml = simplexml_load_file("xml/units/E01.xml");
echo "File exists";
echo "</br>";
$wcccanumber = "121202482";
foreach ($xml->call->wcccanumber as $call) {
if ($call == $wcccanumber) {
$dom = dom_import_simplexml($call);
$dom->parentNode->removeChild($dom);
$fp = fopen("xml/units/E01.xml","wb");
fwrite($fp,$xml->asXML());
fclose($fp);
}
}
}
Here is the xml:
<xml>
<call>
<wcccanumber>121202482</wcccanumber>
<currentcall>FALL</currentcall>
<county>W</county>
<id>82</id>
<location>234 E MAIN ST</location>
<callcreated>12:26:09</callcreated>
<station>HBM</station>
<units>E01</units>
<calltype>M</calltype>
<lat>45.5225067888299</lat>
<lng>-122.987112718574</lng>
<inputtime>12/18/2012 12:27:01 pm</inputtime>
</call>
</xml>
Iterate through call and compare $call->wcccanumber with $wcccanumber. Convert $call to dom and remove it (parentNode->removeChild).
foreach ($xml->call as $call) {
if ($call->wcccanumber == $wcccanumber) {
$dom = dom_import_simplexml($call);
$dom->parentNode->removeChild($dom);
$fp = fopen("xml/units/E01.xml","wb");
fwrite($fp,$xml->asXML());
fclose($fp);
}
}
If there are multiple deletions it makes sense to save only once after all deletions have been done.
$deletionCount = 0;
foreach ($xml->call as $call) {
if ($call->wcccanumber != $wcccanumber) {
continue;
}
$dom = dom_import_simplexml($call);
$dom->parentNode->removeChild($dom);
$deletionCount++;
}
if ($deletionCount) {
file_put_contents("xml/units/E01.xml", $xml->asXML());
}

Categories