XML file/data handling with PHP - php

I have a XML file as a master file (master.xml) and its content is blank.
<?xml version="1.0" encoding="UTF-8"?>
<master/>
I have a loop in which i get some data and turn them into xml files (item.xml) and their content is like
<?xml version="1.0" encoding="UTF-8"?>
<master>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
</master>
All i want, is to be able to get the Item from the item.xml and insert it on master.xml under the master tag so the final result would look something like
<?xml version="1.0" encoding="UTF-8"?>
<master>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
</master>
I don't know if it helps but the code right now is like this.
$targetDom = new DOMDocument();
$targetDom->load('master.xml');
while($row = $sql->fetch(PDO::FETCH_ASSOC)) {
// Data beeing processed and stored as item.xml
$sourceDom = new DOMDocument();
$sourceDom->load('item.xml');
foreach ($sourceDom->documentElement->childNodes as $child) {
$targetDom->appendChild(
$targetDom->importNode($child, TRUE)
);
}
}
The code above has a result of this
<?xml version="1.0" encoding="UTF-8"?>
<master/>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
What am i missing?

You need to append the items to the first element of the $targetDom
Use:
$targetDom->documentElement->appendChild(
$targetDom->importNode($child, TRUE)
);

Related

How to get all nodes with xpath and return as resposeXML to js?

How to retrieve xml using xpath and send back to client js as responseXML?
I have php as the server, js as the client, need the specified data and display as html table.
here's my xml
// goods.xml
<items>
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>2</id>
<itemname>Apple iPhone 7</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>3</id>
<itemname>Apple iPhone 8</itemname>
<itemqty>2</itemqty>
</item>
</items>
I want those item with over 10 quantities, I was only able to get only one of them with my php file
// handle.php
$xmlFile = "../../data/goods.xml";
$doc->load($xmlFile);
$xpath = new DOMXPath($doc);
$xml = new SimpleXMLElement($xmlFile, NULL, TRUE);
$nodes = $xml->xpath("/items/item[itemqty>10]");
echo $doc->saveXML($xpathresultset->item(0)); // send the xml response back to the client
Then I only got the first result, I couldn't get both result (id 1 & id 2)
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
But I want
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>2</id>
<itemname>Apple iPhone 7</itemname>
<itemqty>20</itemqty>
</item>
Any help would be appreciated!!
This is probably more easily done using DOMDocument than SimpleXML, as you can then use xpath to search for nodes with itemqty <= 10 and remove them from the document:
$xml = '<items>
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>2</id>
<itemname>Apple iPhone 7</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>3</id>
<itemname>Apple iPhone 8</itemname>
<itemqty>2</itemqty>
</item>
</items>';
$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
foreach ($xpath->query('/items/item[itemqty<=10]') as $node) {
$node->parentNode->removeChild($node);
}
echo $doc->C14N();
Output:
<items>
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>2</id>
<itemname>Apple iPhone 7</itemname>
<itemqty>20</itemqty>
</item>
</items>

phpClient returning nesting XML

I have returning data from webservice with soap like this :
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header/>
<soap-env:Body>
<n0:ZFIFM_VIRTUAL_ACCOUNTResponse xmlns:n0="urn:sap-com:document:sap:rfc:functions">
<BILLDETAILS>
<item>
<BILLCODE>?</BILLCODE>
<BILLNAME>?</BILLNAME>
<BILLSHORTNAME>?</BILLSHORTNAME>
<BILLAMOUNT>?</BILLAMOUNT>
</item>
<item>
<BILLCODE>01</BILLCODE>
<BILLNAME>BIL</BILLNAME>
<BILLSHORTNAME>Billing</BILLSHORTNAME>
<BILLAMOUNT>114509000</BILLAMOUNT>
</item>
<item>
<BILLCODE>02</BILLCODE>
<BILLNAME>TAX</BILLNAME>
<BILLSHORTNAME>PPN 10%</BILLSHORTNAME>
<BILLAMOUNT>11450900</BILLAMOUNT>
</item>
<item>
<BILLCODE>03</BILLCODE>
<BILLNAME>TAX</BILLNAME>
<BILLSHORTNAME>PPL WAPU</BILLSHORTNAME>
<BILLAMOUNT>11450900</BILLAMOUNT>
</item>
<item>
<BILLCODE>04</BILLCODE>
<BILLNAME>TAX</BILLNAME>
<BILLSHORTNAME>PPK 4.2</BILLSHORTNAME>
<BILLAMOUNT>6758400</BILLAMOUNT>
</item>
<item>
<BILLCODE>05</BILLCODE>
<BILLNAME>TAX</BILLNAME>
<BILLSHORTNAME>PPJ 23 - 2%</BILLSHORTNAME>
<BILLAMOUNT>193500</BILLAMOUNT>
</item>
<item>
<BILLCODE>06</BILLCODE>
<BILLNAME>TAX</BILLNAME>
<BILLSHORTNAME>PPO 23 - 15%</BILLSHORTNAME>
<BILLAMOUNT>5587500</BILLAMOUNT>
</item>
</BILLDETAILS>
<BILLINFO1>1000000014</BILLINFO1>
<BILLINFO2>YOU MEAN IT</BILLINFO2>
<BILLINFO3>1140000000</BILLINFO3>
<BILLINFO4>JOJO Heart</BILLINFO4>
<CURRENCY>360</CURRENCY>
<STATUS>
<item>
<ISERROR>?</ISERROR>
<ERRORCODE>?</ERRORCODE>
<STATUSDESCRIPTION>?</STATUSDESCRIPTION>
</item>
<item>
<ISERROR>false</ISERROR>
<ERRORCODE>00</ERRORCODE>
<STATUSDESCRIPTION>Success</STATUSDESCRIPTION>
</item>
</STATUS>
</n0:ZFIFM_VIRTUAL_ACCOUNTResponse>
</soap-env:Body>
</soap-env:Envelope>
the problem is how can I get array of BILLDETAILS while I'm using this method to call soapCLient :
$x = $client->ZFIFM_VIRTUAL_ACCOUNT(array("BILLKEY1"=>"8871711140100014"));
I already try with count($x->BILlDETAILS) but it's only return 1 values, and when I echo with : echo $x->BILLDETAILS[0];
it print blank..
please i need an advice..
thanks..
Try it like this:
foreach ($x->BILLDETAILS->item as $key => $item) {
var_dump($item);
}

Foreach loop through XML tags named tag-1, tag-2, tag-3

How can one loop through XML structure with tags named like
<response>
<tag-1>
<item>
<id>106</id>
<title>DG</title>
</item>
<item>
<id>105</id>
<title>AC</title>
</item>
</tag-1>
<tag-2>
<item>
<id>1</id>
<title>DjG</title>
</item>
<item>
<id>15</id>
<title>AoC</title>
</item>
</tag-2>
</response>
So I load xml with simplexml_load_file, then I tried with xml->children().
$xml = simplexml_load_file("data.xml");
foreach($xml->children() as $kat);
{
var_dump($kat);
}
This has only returned the last element. So I can not loop through all of the tag-* elements.
Any help how to loop through all tags named tag-* will be very appreciated

Remove one tag and all of it's child nodes of a xml using php

i'm trying to remove one item from a xml with all of it's child nodes but when i excecute following php only the child nodes will be removed.
following is my php
<?php
header('Content-Type: text/xml');
$doc = new DOMDocument('1.0');
$url = '../../data/auction.xml';
$itemNo ="0";
$xml=simplexml_load_file($url);
foreach($xml->xpath('/items/item[itemNumber="'.$itemNo.'"]')as $child)
{
unset($child[0]);
//$child->parentNode->removeChild($node);
}
print $xml->asXML();
?>
the original XML
<?xml version="1.0"?>
<items>
<item>
<itemNumber>0</itemNumber>
<itemName>item1</itemName>
<category>Phones</category>
</item>
<item>
<itemNumber>2</itemNumber>
<itemName>item3</itemName>
<category>laptops</category>
</item>
</items>
Actual output
<items>
<item>
</item>
<item>
<itemNumber>2</itemNumber>
<itemName>item3</itemName>
<category>laptops</category>
</item>
</items>
Desired output
<items>
<item>
<itemNumber>2</itemNumber>
<itemName>item3</itemName>
<category>laptops</category>
</item>
</items>
Please tell me what i'm doing wrong

Replacing innertext of XML node using PHP DOMDocument

I want to replace innertext of a XML node my XML file named test.xml is
<?xml version="1.0" encoding="utf-8"?>
<ads>
<loop>no</loop>
<item>
<description>Description 1</description>
</item>
<item>
<description>Text in item2</description>
</item>
<item>
<description>Let play with this XML</description>
</item>
</ads>
I want to change the value of loop and description tag both,
and it should be saved in test.xml like:
<?xml version="1.0" encoding="utf-8"?>
<ads>
<loop>yes</loop>
<item>
<description>Description Changing Here</description>
</item>
<item>
<description>Changing text in item2</description>
</item>
<item>
<description>We will play later</description>
</item>
</ads>
I tried code in PHP:
<?
$file = "test.xml";
$fp = fopen($file, "rb") or die("cannot open file");
$str = fread($fp, filesize($file));
$dom=new DOMDocument();
$dom->formatOutput = true;
$dom->preserveWhiteSpace = false;
$dom->loadXML($str) or die("Error");
//$dom->load("items.xml");
$root=$dom->documentElement; // This can differ (I am not sure, it can be only documentElement or documentElement->firstChild or only firstChild)
$loop=$root->getElementsByTagName('loop')->item(0);//->textContent;
//echo $loop;
if(trim($loop->textContent)=='no')
{
echo 'ok';
$root->getElementsByTagName('loop')->item(0)->nodeValue ='yes';
}
echo "<xmp>NEW:\n". $dom->saveXML() ."</xmp>";
?>
I tried only for loop tag.I don't know how to replace nodevalue in description tag.
When I run this page it shows output like:
ok
NEW:
<?xml version="1.0" encoding="utf-8"?>
<ads>
<loop>yes</loop>
<item>
<description>Description 1</description>
</item>
<item>
<description>Changing text in item2</description>
</item>
<item>
<description>Let play with this XML</description>
</item>
</ads>
It gives the value yes in browser but don't save it in test.xml any reason?
So, since you have created DOMDocument you can use DOMXpath. Or keep using getElementsByTagName()
You could do this (but only in that context):
$descriptions = $root->getElementsByTagName('description');
foreach($descriptions as $nodeDesciption)
{
$nodeDesciption->nodeValue ='Your custom value';
}

Categories