I'm writing a custom plugin for use in my website using Jw player adtonomy plugin which loads adverts from XML files. However I do not know how to update the nodes in the files. I have tried using simple xml but I don't know how to update. Any implementation is highly regarded. Thanks. Here is the xml file.
<xml>
<plugins>adtimage</plugins>
<adtimage.graphic>http://mysite/default.png</adtimage.graphic>
<adtimage.link>http://targetsite.com</adtimage.link>
<adtimage.positions>pre,post</adtimage.positions>
<adtimage.onpause>true</adtimage.onpause>
<adtimage.txt>Advertisement</adtimage.txt>
<adtimage.btntxt>Click to continue with video</adtimage.btntxt>
</xml>
my code is here.
<?php
$xml = simplexml_load_file("test.xml");
echo $xml->getName() . "<br />";
foreach($xml->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
/*
TO DO
change the node value of
<adtimage.graphic>http://mysite/default.png</adtimage.graphic>
to
<adtimage.graphic>http://stackoverflow.com</adtimage.graphic>
*/
}
?>
You can use this
//Load XML
$xml = simplexml_load_file("test.xml");
// Modify a node
$xml->{"adtimage.graphic"} = 'http://stackoverflow.com/adtimage.graphic';
// Saving the whole modified XML to a new filename
$xml->asXml('updated.xml');
Example Output 'updated.xml'
<?xml version="1.0"?>
<xml>
<plugins>adtimage</plugins>
<adtimage.graphic>http://stackoverflow.com/adtimage.graphic</adtimage.graphic>
<adtimage.link>http://targetsite.com</adtimage.link>
<adtimage.positions>pre,post</adtimage.positions>
<adtimage.onpause>true</adtimage.onpause>
<adtimage.txt>Advertisement</adtimage.txt>
<adtimage.btntxt>Click to continue with video</adtimage.btntxt>
</xml>
Related
There's a few threads about this, but I couldn't find a solution to this issue in them. I hope it doesn't violate duplicate rules.
I've tested the following code with static XML and it works great, but said XML did not contain any headers.
I'm trying to remove headers through code after making a POST request so I can continue to process the resulting XML, but I'm not having any luck with it.
This is the XML:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><AUTOS_Cotizar_PHPResponse xmlns="http://tempuri.org/"><AUTOS_Cotizar_PHPResult><auto xmlns=""><operacion>1555843</operacion><statusSuccess>TRUE</statusSuccess><statusText></statusText><cotizacion><cobertura><codigo>A0</codigo><descripcion>RESPONSABILIDAD CIVIL SOLAMENTE</descripcion><premio>928,45</premio><cuotas>01</cuotas><impcuotas>928,45</impcuotas></cobertura></cotizacion><datos_cotiz><suma>477250</suma><uso>901</uso></datos_cotiz></auto></AUTOS_Cotizar_PHPResult></AUTOS_Cotizar_PHPResponse></soap:Body></soap:Envelope>
this is the code:
//converting raw cURL response to XML
$temp1 = htmlspecialchars ($reply);
//replacing top headers
$temp2 = str_replace('<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><AUTOS_Cotizar_PHPResponse xmlns="http://tempuri.org/"><AUTOS_Cotizar_PHPResult>', "<<<'EOD'", $temp1);
//replacing closing header tags
$temp3 = str_replace('</AUTOS_Cotizar_PHPResult></AUTOS_Cotizar_PHPResponse></soap:Body></soap:Envelope>', "EOD;", $temp2);
//this returns the original $temp1 without having anything replaced
echo $temp3;
//simplexml conversion
$xml = simplexml_load_string($temp3);
//running through the array and printing all values
if ($xml !== false) {
foreach ($xml->cotizacion as $cotizacion) {
foreach ($cotizacion->cobertura as $cobertura) {
echo $cobertura->codigo;
echo '<br>';
echo $cobertura->descripcion;
echo '<br>';
echo $cobertura->premio;
echo '<br>';
echo $cobertura->cuotas;
echo '<br>';
echo $cobertura->impcuotas;
echo '<br>';
}
}
}
There are probably more efficient ways to do this, or maybe I'm not doing this correctly. I'm just about learning right now, so feel free to correct me in any way if you want, I'd appreciate it!
The way you are processing the response string is a bad idea, you should stick to processing the content as XML and work with it. This uses XPath to find a start point to process the data (which I can't test with the current sample), but should help with what you need to do...
// Load the original reply
$xml = simplexml_load_string($reply);
//running through the array and printing all values
if ($xml !== false) {
// Find the <auto> element (use [0] as you want the first one)
$auto = $xml->xpath("//auto")[0];
// Loop through the cotizacion elements in the auto element
foreach ($auto->cotizacion as $cotizacion) {
foreach ($cotizacion->cobertura as $cobertura) {
echo $cobertura->codigo;
echo '<br>';
echo $cobertura->descripcion;
echo '<br>';
echo $cobertura->premio;
echo '<br>';
echo $cobertura->cuotas;
echo '<br>';
echo $cobertura->impcuotas;
echo '<br>';
}
}
}
The SOAP response is still an XML document, so work with it instead of fighting it. Treating it as a string is definitely not great.
As far as I can tell you're trying to work with all the <cotizaction> elements. It's simple to find elements inside an XML document. Read up on XPath.
$xml = simplexml_load_string(htmlspecialchars($reply));
if ($xml) {
foreach ($xml->xpath('//cotizacion') as $cotizacion) {
// do your thing
}
}
I have an xml file like this
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Job>
<JobInfo>
<User>abc</User>
<Computer>acb</Computer>
<Started>2018/04/21-21:58:30:0182-06</Started>
<Ended>2018/04/21-23:10:10:0093-06</Ended>
</JobInfo>
<JobFlags>
<Active>Yes</Active>
<Complete>Yes</Complete>
</JobFlags>
</Job>
I use simplexml_load_file to load file and print out User, Computer and Complete attribute.
$xml=simplexml_load_file("abc.xml") or die("Error: Cannot create object");
foreach($xml->children() as $xm) {
echo $xm->User . "<br>";
echo $xm->Computer . "<br>";
echo $xm->Complete . "<br>";
But it only print out User and Computer. The result for Complete is empty.
Please help me with this, thank you!
The main issue is that you are trying to mix the fields from different elements. You can see from the original XML that <User> and <Computer> are in the <JobInfo> element and <Complete> is in the <JobFlags> element. This isn't a problem, but when you use your foreach loop, you go through each child element of <Job> and output all of the values for each element. If you change your loop to...
foreach($xml->children() as $tag => $xm) {
echo "element=".$tag . "<br>";
echo $xm->User . "<br>";
echo $xm->Computer . "<br>";
echo $xm->Complete . "<br>";
}
You get (please excuse wrong markup, I wanted the layout)...
element=JobInfoabcacbelement=JobFlagsYes
If instead you just need those three pieces of information from the document, you could access them using the full path and so just pick out the details your after without using a foreach...
echo $xml->JobInfo->User . "<br>";
echo $xml->JobInfo->Computer . "<br>";
echo $xml->JobFlags->Complete . "<br>";
Gives you.
abcacbYes
simplexml is a bit outdated. Not sure that a <complete> tag is valid, xml, it may be the issue.
If you can, try to use php-dom instead.
https://php.net/manual/en/book.dom.php
Example to retrieve all the tags texts.
#!/usr/bin/php
<?php
$remote =<<<'EOF'
<JobInfo>
<User>abc</User>
<Computer>acb</Computer>
<Started>2018/04/21-21:58:30:0182-06</Started>
<Ended>2018/04/21-23:10:10:0093-06</Ended>
</JobInfo>
<JobFlags>
<Active>Yes</Active>
<Complete>Yes</Complete>
</JobFlags>
EOF;
$i = 0;
$doc = new DOMDocument();
$doc->loadHTML($remote);
foreach($doc->getElementsByTagName('*') as $elem) {
echo $i++.": ".$elem->textContent;
}
The package bellong to php-xml:
Package php-dom is a virtual package provided by: php7.2-xml
Alternatives: https://php.net/manual/en/refs.xml.php
Try to wrap all elements into a parent tag:
<?xml version="1.0"?>
<test>
<JobInfo>
<User>abc</User>
<Computer>acb</Computer>
<Started>2018/04/21-21:58:30:0182-06</Started>
<Ended>2018/04/21-23:10:10:0093-06</Ended>
</JobInfo>
<JobFlags>
<Active>Yes</Active>
<Complete>Yes</Complete>
</JobFlags>
</test>
and then reference in your php:
<?php
$xml=simplexml_load_file("abc.xml") or die("Error: Cannot create object");
echo $xml->JobInfo->User . "<br>";
echo $xml->JobInfo->Computer . "<br>";
echo $xml->JobFlags->Complete . "<br>";
?>
It worked here.
I think it's just a matter of making a correct reference to the entire hierarchical structure of the tags.
See this example taken from http://php.net/manual/en/function.simplexml-load-file.php:
<?php
$xml = '<?xml version="1.0" encoding="UTF-8" ?>
<rss>
<channel>
<item>
<title><![CDATA[Tom & Jerry]]></title>
</item>
</channel>
</rss>';
$xml = simplexml_load_string($xml);
// echo does the casting for you
echo $xml->channel->item->title;
// but vardump (or print_r) not!
var_dump($xml->channel->item->title);
// so cast the SimpleXML Element to 'string' solve this issue
var_dump((string) $xml->channel->item->title);
?>
Above will output:
Tom & Jerry
object(SimpleXMLElement)#4 (0) {}
string(11) "Tom & Jerry"
Reference:
https://stackoverflow.com/a/16972780/5074998
http://php.net/manual/en/function.simplexml-load-file.php
It works just fine for me:
abc
acb
Yes
You might be confused because you are expecting it all on three consecutive lines. Try outputting it like this instead and it may help you visualize that it is echoing all three of your requested elements (whether they exist or not) for two loops (since the XML has two children):
foreach($xml->children() as $xm) {
echo "Current Element: " . $xm->getName() . "<br />";
echo "User: " . $xm->User . "<br />";
echo "Computer: " . $xm->Computer . "<br />";
echo "Complete: " . $xm->Complete . "<br />";
}
which will output:
Current Element: JobInfo
User: abc
Computer: acb
Complete:
Current Element: JobFlags
User:
Computer:
Complete: Yes
As Nick suggested in his comment, if you don't want the <br /> breaks to print when the element doesn't exist, you can use isset like:
foreach($xml->children() as $xm) {
echo isset($xm->User) ? "{$xm->User}<br />" : '';
echo isset($xm->Computer) ? "{$xm->Computer}<br />" : '';
echo isset($xm->Complete) ? "{$xm->Complete}<br />" : '';
}
Or, as NigelRen recommended in their answer, you could skip using children() if you know the full path to the elements you need, and just use those paths instead, like:
echo $xml->JobInfo->User . "<br />";
echo $xml->JobInfo->Computer . "<br />";
echo $xml->JobFlags->Complete . "<br />";
The underlying issue being that when you were echoing out $xm->Complete while traversing the JobInfo element, it was outputting just the <br /> because $xml->JobInfo->Complete does't exist.
In this web page, I have a php script to recreate divs on the page based on XML data. The script is called directly from the HTML page inside <body> </body>.
<body>
<div id="page" class="demo">
</div>
<?php
// script for recreating divs calls SimpleXMLElement or DOMXPath
?>
</body>
When I get the XML nodes with SimpleXMLElement, there are no errors, the nodes are returned. When instead I try DOMXPath, there are errors.
This returns the nodes.
$nodes = new SimpleXMLElement('communities.xml', null, true);
foreach($nodes as $node) // loop through
{
//restore divs from node information
}
This doesn't return the nodes and gives errors.
$dom = new DOMDocument();
$dom->load('communities.xml');
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('COMMUNITY');
foreach($nodes as $node) // loop through
{
//restore divs from node information
}
To extend the script to get more information from the nodes I thought of using xpath. The additional information I want to show is: NAME: text to show for each url contained in the div (Google.com), URLC: url corresponding to the text (http://google.com). The XML file has nodes like this.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<COMMUNITIES>
<COMMUNITY ID="c000010">
<NAME>New000010</NAME>
<TOP>50</TOP>
<LEFT>50</LEFT>
<WIDTH>150</WIDTH>
<HEIGHT>150</HEIGHT>
<URLS>
<URL ID="u000038">
<NAME>Google.com</NAME>
<URLC>http://google.com</URLC>
</URL>
</URLS>
</COMMUNITY>
</COMMUNITIES>
The strange problem is that elsewhere, in ajax calls from javascript functions I get information from the XML file with xpath without any problems. Why doesn't the DOMXPath method work in that situation?
EDITS * NEW INFORMATION
Here is the php file called through ajax from the html page. This is where SimpleXMLElement works. But if I try to create a new DOMdocument() then call xpath. The new DOM document isn't created.
<?php
function get_nodes() {
// load SimpleXML
/* $nodes = new SimpleXMLElement('communities.xml', null, true); */
$dom = new DOMDocument();
$dom->load('communities.xml');
// get document element
$xpath = new DOMXPath($dom);
$nodes = $xpath->query("//COMMUNITY");
foreach($nodes as $node) // loop through
{
echo "<div id = '".$node['ID']."' class= 'comdiv ui-widget-content' style = 'top: ".$node->TOP."; left: ".$node->LEFT."; width: ".$node->WIDTH.";
height: ".$node->HEIGHT.";'> \n"; echo " <p class = 'comhdr editableText ui-widget-header'>".$node->NAME."</p>\n";
echo " Delete \n";
echo " Add URL \n";
echo "</div> \n";
echo "<script type='text/javascript'>\n";
echo " $('#".$node['ID']."').resizable();\n";
echo " $('#".$node['ID']."').draggable();\n";
echo " $('#".$node['ID']."').draggable('option', 'handle', '.comhdr');\n";
echo "</script>\n";
}
echo "<script type='text/javascript'>\n";
echo " $('.comhdr').editableText();\n";
echo "</script>\n";
return;
}
echo get_nodes();
?>
Community is not the root of the xml. Try $nodes = $xpath->query('//COMMUNITY');
This should select any COMMUNITY nodes in your xml document. If you only want to select them when they're children of the root element, then try:
$nodes = $xpath->query('/COMMUNITIES/COMMUNITY');
Had folder permission issues. The folder containing the XML did not have permission set for the script to write the updated XML.
Input is a URL like this http://ws.geonames.org/children?geonameId=6255148 and I would like to receive the XML file in a SimpleXMLElement for example?
Try this as your base point:
<?php
$xml = simplexml_load_file("http://ws.geonames.org/children?geonameId=6255148");
//print_r($xml);
foreach($xml->geoname as $geo)
{
echo $geo->toponymName . "<br />";
}
?>
I have XML file like this :
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
And i code in my php page:
<? php
$xmlDoc = new DOMDocument();
$xmlDoc->load("note.xml");
$x = $xmlDoc->documentElement;
foreach ($x->childNodes AS $item)
{
print $item->nodeName . " = " . $item->nodeValue . "<br />";
}
?>
The output of the code above is:
#text =
to = Tove
#text =
from = Jani
#text =
heading = Reminder
#text =
body = Don't forget me this weekend!
#text =
I known that when XML generates, it often contains white-spaces between the nodes. But Anybody can help me loop through all elements of the element of XML bypass white-spaces between the nodes. I mean loop through only all real elements of the element. Pls help me.
Try this
$xmlDoc = new DOMDocument();
$xmlDoc->preserveWhiteSpace = false;
$xmlDoc->load("note.xml");
If you simply want to iterate over the elements (and do no fancy stuff like reordering elements and so on) I'd go for the simplexml-extension, which make dealing with XML much more simple:
$xml = simplexml_load_file('note.xml');
foreach ($xml as $node) {
echo $node->getName() . ' = ' . (string)$node . '<br />';
}
Whatever you do, it will just be symptomatic treatment. The XML file should not contain those newline characters in the first place,as anything between the closing > and opening < is considered a text element.