How to properly add new child with children in xml - php

An API returns the following, and I want to add another data record for testing purposes:
<?xml version="1.0" encoding="UTF-8" ?>
<API>
<code>0000</code>
<time>1549959757</time>
<data cnt="1">
<record>
<record>
<approval_idx>224833</approval_idx>
<reg_date>2019-02-12</reg_date>
<user_id>test</user_id>
<state1>10</state1>
<state2>03</state2>
<name>tester</name>
<e_id>3743</e_id>
<cname>test cname</cname>
<cId>3089</cId>
<loc>oh</loc>
</record>
</record>
</data>
</API>
I tried doing this
$utilApi = new libUtilApi($apiRequest);
$utilApi->request();
$resultAPI = $utilApi->response;
$resultAPI = simplexml_load_string($resultAPI);
$record = $resultAPI->addChild("record");
$record->addChild("approval_idx", "7546");
but the output look like this
<?xml version="1.0" encoding="UTF-8" ?>
<API>
<code>0000</code>
<time>1549959757</time>
<data cnt="1">
<record>
<record>
<approval_idx>224833</approval_idx>
<reg_date>2019-02-12</reg_date>
<user_id>test</user_id>
<state1>10</state1>
<state2>03</state2>
<name>tester</name>
<e_id>3743</e_id>
<cname>test cname</cname>
<cId>3089</cId>
<branch>oh</branch>
</record>
</record>
<record>
<approval_idx>7546</approval_idx>
<reg_date>2019-02-13</reg_date>
<user_id>test3</user_id>
<state1>75</state1>
<state2>09</state2>
<name>new test</name>
<e_id>7546</e_id>
<cname>Q1</cname>
<cId>325</cId>
<branch>oh</branch>
</record>
</data>
</API>
The added child is not going in right position, I tried
$record = $resultAPI->record[0]->addChild("record");
but it falls to an error like:
Call to a member function addChild() on null
-I just updated the code, yes the api is returning the proper format and data, its just that I can't make the addition of children on the right place

Related

php xml schema formatting

I have a php page what post's a xml to Heartinternet API and after a long time I have got it to work but now I cant find away to only pull only one part out of the replyed XML
$some_xml = '<?xml version="1.0"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:package="http://www.heartinternet.co.uk/whapi/package-2.2">
<command>
<info>
<package:info>
<package:id>171371a16973b1bf</package:id>
</package:info>
</info>
<extension>
<ext-package:preAuthenticate xmlns:ext-package="http://www.heartinternet.co.uk/whapi/ext-package-2.2"/>
</extension>
<clTRID>fac89208bea460fa3fef11b22a519cce</clTRID>
</command>
</epp>';
This is the code what is posted to the API. Full code can been seen here.
This is what I get back and can't figure out how to pull one line from the reply.
<?xml version='1.0'?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:ext-package="http://www.heartinternet.co.uk/whapi/ext-package-2.2">
<response>
<result code='1000'>
<msg>Command completed successfully</msg>
</result>
<resData>
<ext-package:redirectURL>http://bobcp.example.org/sso.cgi?session=LUB9UNbw6jTW</ext-package:redirectURL>
</resData>
<trID>
<clTRID>fac89208bea460fa3fef11b22a519cce</clTRID>
<svTRID>test-19272326601ef4c3bf6b64730d09c6cf</svTRID>
</trID>
</response>
</epp>
The one line I need to show is ext-package:redirectURL.
If anyone could help me or point me in the right direction to find how to sort this I would be grateful!
You can get the redirect url by registering the namespace urn:ietf:params:xml:ns:epp-1.0 and then you could use an xpath expression for example. In this case, I have chosen u as the prefix.
/u:epp/u:response/u:resData/ext-package:redirectURL
Using SimpleXML with your returned xml:
The response xml from the comments is slightly different. This is the updated code:
$returned_xml->registerXPathNamespace('u', 'urn:ietf:params:xml:ns:epp-1.0');
$returned_xml->registerXPathNamespace('ext-package', 'http://www.heartinternet.co.uk/whapi/ext-package-2.2');
$redirectUrl = $returned_xml->xpath('/u:epp/u:response/u:resData/ext-package:redirectURL');
echo $redirectUrl[0];
Or with DOMDocument:
$doc = new DOMDocument();
$doc->loadXML(file_get_contents("https://custom-hosting.co.uk/source/test.php"));
$xpath = new DOMXpath($doc);
$xpath->registerNamespace('u', 'urn:ietf:params:xml:ns:epp-1.0');
$xpath->registerNamespace('ext-package', 'http://www.heartinternet.co.uk/whapi/ext-package-2.2');
$redirectUrl = $xpath->query('/u:epp/u:response/u:resData/ext-package:redirectURL')->item(0)->nodeValue;
echo $redirectUrl;
That will give you for example:
http://bobcp.example.org/sso.cgi?session=LUB9UNbw6jTW
<?xml version='1.0'?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:ext-package="http://www.heartinternet.co.uk/whapi/ext-package-2.2">
<response>
<result code='1000'>
<msg>Command completed successfully</msg>
</result>
<resData>
<ext-package:redirectURL>http://bobcp.example.org/sso.cgi?session=LUB9UNbw6jTW</ext-package:redirectURL>
</resData>
<trID>
<clTRID>fac89208bea460fa3fef11b22a519cce</clTRID>
<svTRID>test-19272326601ef4c3bf6b64730d09c6cf</svTRID>
</trID>
</response>
</epp>
that is what i get sent back from the API its not in my test page at all
Full page source
if i add
$xml = simplexml_load_string($returned_xml);
$xml->registerXPathNamespace('u', 'urn:ietf:params:xml:ns:epp-1.0');
$redirectUrl = $xml->xpath('/u:epp/u:response/u:resData/ext-package:redirectURL');
echo $redirectUrl[0];
to the page i just get
XML Parsing Error: no element found
Location: https://custom-hosting.co.uk/
Line Number 1, Column 1:

How to parse XML-file to array and retrieve all children of an child with specific attribute in PHP?

my XML-file is as follows: agents.xml
<?xml version="1.0" encoding="UTF-8"?>
<agents>
<agent id="1">
<aname>pi1</aname>
<alive>0</alive>
<scenarios>1,2,3</scenarios>
</agent>
<agent id="2">
<aname>pi2</aname>
<alive>1</alive>
<scenarios>4,5,6</scenarios>
</agent>
</agents>
I want to retrieve all child elements of an agent, selected by attribute value "id". I tried the following, passing a the variable "id" to the script:
$agents_xml = simplexml_load_file("/<path_to>/agents.xml");
$json = json_encode($agents_xml);
$array = json_decode($json,TRUE);
//decrement id for correct index
$id=$id-1;
//I want to return in JSON format
$testarr=json_encode($array['agent'][$id]);
echo $testarr;
When "id" has value 1, i got this:
{"#attributes":{"id":"1"},"aname":"pi1","alive":"0","scenarios":"1,2,3"}
But i know, if the XML is disordered like:
<?xml version="1.0" encoding="UTF-8"?>
<agents>
<agent id="2">
<aname>pi2</aname>
<alive>1</alive>
<scenarios>4,5,6</scenarios>
</agent>
<agent id="1">
<aname>pi1</aname>
<alive>0</alive>
<scenarios>1,2,3</scenarios>
</agent>
</agents>
This is not very reliable.
Thanks for any idea!
Try
$str = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<agents>
<agent id="1">
<aname>pi1</aname>
<alive>0</alive>
<scenarios>1,2,3</scenarios>
</agent>
<agent id="2">
<aname>pi2</aname>
<alive>1</alive>
<scenarios>4,5,6</scenarios>
</agent>
</agents>
XML;
$xml = new SimpleXMLElement($str);
foreach($xml->agent as $agent)
{
var_dump($agent);
echo "<hr>";
}

How Can I combine a list from XML in PHP

I Have a Parts List Coming from an XML File, It goes something like what is below. I Want to be able to generate using PHP a Combined List. For Example the "Part 1" Is recorded twice. I want the Qty to Show 13 Under Part 1 when Generated either in a JSON output or another XML Output. What would be the best way of doing that? I looked at the php function array_combine but wasn't able to figure out if the values could be combined mathematically instead of showing one of the results. I am loading the XML from a url in simplexml_load_file() function. Thank You for your help
My XML from URL:
<db>
<record>
<part>Part 1</part>
<qty>4</qty
</record>
<record>
<part>Part 2</part>
<qty>5</qty
</record>
<record>
<part>Part 1</part>
<qty>9</qty
</record>
</db>
Want to Display:
<db>
<record>
<part>Part 1</part>
<qty>13</qty>
</record>
<record>
<part>Part 2</part>
<qty>5</qty
</record>
</db>
Iterate over the XML document, accumulating part quantities as you go:
$simpleXmlElement = new SimpleXMLElement(<<<XML
<db>
<record>
<part>Part 1</part>
<qty>4</qty>
</record>
<record>
<part>Part 2</part>
<qty>5</qty>
</record>
<record>
<part>Part 1</part>
<qty>9</qty>
</record>
</db>
XML
);
$quantities = array();
foreach ($simpleXmlElement as $child) {
if ($child->part && $child->qty) {
$part = (string)$child->part;
if (!isset($quantities[$part])) {
$quantities[$part] = 0;
}
$quantities[$part] += (int)$child->qty;
}
}
echo json_encode($quantities);
simplexml_load_string() will parse the xml and build an array of all the records as 'record' => array(...)
you can then iterate the record array and group them by type
$parts = array();
foreach ($document['record'] as $item) {
if (isset($parts[$item['part']]) $parts[$item['part']] += $item['qty'];
else $parts[$item['part']] = $item['qty'];
}
after the above loop, $parts will contain a hash mapping the part name to qty

How to concatenate similar tags in a XML file

There can be one or many similar XML tags inside a single XML record set. If there are many, I need them to be in a one tag, comma separated.
This is the XML I have now.
<?xml version="1.0"?>
<Results>
<Recordset setCount="3">
<Record setEntry="0">
<AU>One</AU>
<AU>Two</AU>
<AU>three</AU>
</Record>
<Record setEntry="1">
<AU>One</AU>
<AU>Two</AU>
<AU>Three</AU>
<AU>Four</AU>
<AU>Five</AU>
<AU>Six</AU>
<AU>Seven</AU>
</Record>
<Record setEntry="2">
<AU>One</AU>
</Record>
</Recordset>
</Results>
I need it to be like this. Please help with a code.
<?xml version="1.0"?>
<Results>
<Recordset setCount="3">
<Record setEntry="0">
<AU>One, Two, Three</AU>
</Record>
<Record setEntry="1">
<AU>One, Two, Three, Four, Five, Six, Seven</AU>
</Record>
<Record setEntry="2">
<AU>One</AU>
</Record>
</Recordset>
</Results>
This can be done with xpath. Here is an example with Simplexml:
You can first find all the first leafs:
foreach ($xml->xpath('//*[not(*) and not(preceding-sibling::*)]') as $firstLeaf) {
...
}
and then you concat the text together with all the following leafs:
$followingWithSameName = 'following-sibling::*[name(.) = name(preceding-sibling::*[last()])]';
// change the text of the first leaf
$firstLeaf[0] = implode(', ', $firstLeaf->xpath(".|$followingWithSameName"));
and then you remove all the following leafs:
// remove all following leafs with the same name
foreach ($firstLeaf->xpath($followingWithSameName) as $leaf) {
unset($leaf[0]);
}
Demo

PHP SimpleXML add child to each parent repeatedly

I have this kind of XML:
<?xml version="1.0" encoding="utf-8"?>
<data>
<stats>
</stats>
<params>
</params>
<results>
<record id='SJDGH'>
<item>abc</item>
<item>def</item>
<item>ghi</item>
</record>
<record id='OIIO'>
<item>abc</item>
<item>def</item>
<item>ghi</item>
</record>
</results>
</data>
I'm generating a new <item> for every <record> in <results> in a loop:
// $data is SimpleXml objec from XML above
foreach ($data->results->record as $record)
{
$newitem = 'New item!'.time().$record->attributes()->id;
}
Somehow in this loop i need to change the SimpleXML object ($data) to contain new items in every <record>.
is it possible?
I needed a little guessing, but this might what you're looking for:
$records = $data->results->record;
foreach($records as $record)
{
$value = sprintf('New Item! %s / id:%s', time(), $record['id']);
$record->item[] = $value;
}
$data->asXML('php://output');
See it in action.
I think you might want to use addChild.
Check it out here: http://php.net/manual/en/simplexmlelement.addchild.php

Categories