I'm trying to load a foreach into a string formatted as XML.
I've tried as follows
<?php
$data = '<?xml version="1.0" encoding="utf-8" ?><markers>';
foreach ($entries as $entry => $marker ) {
'<marker name="' . $marker->getName() . '"'.'lat="' . $marker->getLatitude() . '"'.'lng="' . $marker->getLongitude() . '"'.'address="' . $marker->getAddressLineOne() . '"'.'address2="' . $marker->getAddressLineTwo() . '"'.'city="' . $marker->getCitySuburb() . '"'.'state="' . $marker->getState('fieldName') . '"'.'postal="' . $marker->getPostCode() . '"'.'country="' . $marker->getCountry('fieldName') . '"'.'phone="' . $marker->getPhone() . '"'.'email="' . $marker->getEmail() . '"'.'web="' . $marker->getWebSite() . '"'.'/>';
}
'</markers>';
?>
But what I end up getting is:
nothing in the $data variable
for some reason each item is nesting in the previous item
Basically I would like to achieve the following result:
<?php
$data = '<?xml version="1.0" encoding="utf-8"?>
<markers>
<marker name="Chipotle Minneapolis" lat="44.947464" lng="-93.320826" category="Restaurant" address="3040 Excelsior Blvd" address2="" city="Minneapolis" state="MN" postal="55416" country="US" phone="612-922-6662" email="info#chipotle.com" web="http://www.chipotle.com" />
<marker name="Chipotle St. Louis Park" lat="44.930810" lng="-93.347877" category="Restaurant" address="5480 Excelsior Blvd." address2="" city="St. Louis Park" state="MN" postal="55416" country="US" phone="952-922-1970" email="info#chipotle.com" web="http://www.chipotle.com" />
<marker name="Chipotle Minneapolis" lat="44.9553438" lng="-93.29719699999998" category="Restaurant, Bar" address="2600 Hennepin Ave." address2="" city="Minneapolis" state="MN" postal="55404" country="US" phone="612-377-6035" email="info#chipotle.com" web="http://www.chipotle.com" />
</markers>';
?>
Thanks
Said
Revised code
<?php
$data = simplexml_load_string("<markers />");
foreach ($entries as $entry => $marker ) {
$newMarker = $data->addChild("marker");
$newMarker->addAttribute("name", $marker->getName());
$newMarker->addAttribute("lat", $marker->getLatitude());
$newMarker->addAttribute("lng", $marker->getLongitude());
$newMarker->addAttribute("state", $marker->getPostCode());
}
echo $data->asXML();
?>
<?php
echo var_dump($data);
?>
After the first line where you use
$data = '<?xml version="1.0" encoding="utf-8" ?><markers>';
you don't add any of the further text onto the variable. You need to use something like
$data .='<marker name="' . $marker->getName() .`
(with the dot before the = to add the value), you also need to be careful with the spacing and the quotes.
I would also recommend using something like SimpleXML to build the XML rather than using put text, it is longer code but safer. Something like...
$xml = simplexml_load_string("<markers />");
foreach ($entries as $entry => $marker ) {
$newMarker = $xml->addChild("marker");
$newMarker->addAttribute("name", $marker->getName());
$newMarker->addAttribute("lat", $marker->getLatitude());
$newMarker->addAttribute("lng", $marker->getLongitude());
// Repeat for all attributes
}
echo $xml->asXML();
Since it's not clear to me how $entries are generated, I'll make up some data in couple of arrays and create a simplified version of your expected output, with the help of a function borrowed from here. Obviously, you'll need to modify it to fit your actual code.
$data = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<markers>
</markers>
XML;
$xml = simplexml_load_string($data);
function sxml_append(SimpleXMLElement $to, SimpleXMLElement $from) {
$toDom = dom_import_simplexml($to);
$fromDom = dom_import_simplexml($from);
$toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
}
$stores = ["Chipotle Chicago","Chipotle St. Louis Park","Chipotle Minneapolis"];
$locations = ["Chicago","St. Louis Park","Minneapolis"];
$destination = $xml->xpath('//markers');
foreach(array_combine($stores, $locations) as $store => $location) {
$tm = simplexml_load_string('<marker name="xxx" city="yyy"/>');
$tmxml = $tm->xpath('//marker')[0];
$tmxml['name'] = $store;
$tmxml['city'] = $location;
sxml_append($destination[0], $tmxml);
}
echo $xml->asXML();
Output:
<?xml version="1.0" encoding="UTF-8"?>
<markers>
<marker name="Chipotle Chicago" city="Chicago" />
<marker name="Chipotle St. Louis Park" city="St. Louis Park" />
<marker name="Chipotle Minneapolis" city="Minneapolis" />
</markers>
Related
Hi I have been struggling with this puzzle for some time now how to get data out of this embedded namespaces here is the xml feed I have cut it down to make easier to read
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:atom="http://www.w3.org/2005/Atom" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns="http://www.w3.org/2005/Atom" xmlns:sc="http://schemas.sage.com/sc/2009" xmlns:crm="http://schemas.sage.com/crmErp/2008" xmlns:sdatasync="http://schemas.sage.com/sdata/sync/2008/1" xmlns:sdata="http://schemas.sage.com/sdata/2008/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:sme="http://schemas.sage.com/sdata/sme/2007" xmlns:http="http://schemas.sage.com/sdata/http/2008/1">
<author />
<category term="tradingAccount" />
<generator />
<subtitle>Provides a feed containing tradingAccount details</subtitle>
<title>Sage Accounts 50 | tradingAccount - Practice Accounts </title>
<entry>
<author />
<content type="html"><![CDATA[<html>
</html>]]></content>
<id>http://computer_1:5493/sdata/accounts50/GCRM/{FF476636-D4AF-4191-BDE4-891EDA349A68}/tradingAccountCustomer(58b10585-63d4-4bb8-adb3-7096d9b055d9)?format=atomentry</id>
<link href="http://computer_1:5493/sdata/accounts50/GCRM/-/tradingAccountCustomer" rel="via" type="application/atom+xml" />
<published>2015-03-13T21:28:59.000+00:00</published>
<updated>2015-07-01T21:33:13.000+01:00</updated>
<http:httpStatus>200</http:httpStatus>
<sdata:payload>
<crm:tradingAccount sdata:url="http://computer_1:5493/sdata/accounts50/GCRM/{FF476636-D4AF-4191-BDE4-891EDA349A68}/tradingAccountCustomer(58b10585-63d4-4bb8-adb3-7096d9b055d9)?format=atomentry" sdata:uuid="58b10585-63d4-4bb8-adb3-7096d9b055d9">
<crm:active>true</crm:active>
<crm:customerSupplierFlag>Customer</crm:customerSupplierFlag>
<crm:companyPersonFlag>Company</crm:companyPersonFlag>
<crm:invoiceTradingAccount xsi:nil="true" />
<crm:openedDate>2013-04-22</crm:openedDate>
<crm:reference>AAA</crm:reference>
<crm:name>BBB</crm:name>
</crm:tradingAccount>
</sdata:payload>
</entry>
<opensearch:totalResults>118</opensearch:totalResults>
<opensearch:startIndex>1</opensearch:startIndex>
<opensearch:itemsPerPage>118</opensearch:itemsPerPage>
</feed>
I am trying to access the <crm:reference><crm:name><crm:openedDate> namespace but failing I have looked at similar projects but I think its a namespace within a namespace
here is my attempt at parsing the data
<?php
$xml = simplexml_load_file("sage.xml");
$xml->registerXPathNamespace('sdata', 'http://schemas.sage.com/sdata/sync/2008/1');
foreach($xml->xpath("//sdata:payload") as $entry) {
$entry->registerXPathNamespace('sdata', 'http://schemas.sage.com/sdata/sync/2008/1');
$entry->registerXPathNamespace('crm', 'http://schemas.sage.com/crmErp/2008');
$content = $entry->xpath("/sdata:payload/crm:tradingAccount/crm:active");
//$article = feed->xpath("/sdata:payload/crm:tradingAccount/crm:active");
foreach($content as $c) {
// echo $c->reference . " | " . $c->name . "/" . $c->accountOpenedDate . "<br />\n";
}
}
var_dump($content);
var_dump($c);
any pointers to my problem would help
foreach($xml->xpath("//sdata:payload") as $entry) {
// xpath here must be from payload to tradingAccount
$content = $entry->xpath("./crm:tradingAccount");
foreach($content as $c) {
// Make set of children with prefix crm
$nodes = $c->children('crm', true);
echo $nodes->reference . " | " . $nodes->name . " / " . $nodes->openedDate . "<br />\n";
}
}
It could be as simple as:
$xml = simplexml_load_file("sage.xml");
$reference = $xml->xpath("//crm:reference");
$name = $xml->xpath("//crm:name");
$openedDate = $xml->xpath("//crm:openedDate");
echo "reference: ". $reference[0] . "<br>";
echo "name: ". $name[0] . "<br>";
echo "openedDate: ". $openedDate[0] . "<br>";
If you would like to use a foreach loop to get all children of 'crm' you can do the following. You need atleast 5.2.0 if you want to set children to prefix (true)
$xml = simplexml_load_file("sage.xml");
foreach($xml->xpath("//crm:tradingAccount") as $entry) {
$child = $entry->children('crm', true);
}
echo "reference: ". $child->reference . "<br>";
echo "name: ". $child->name . "<br>";
echo "openedDate: ". $child->openedDate . "<br>";
How to read ALL atribute xml:lang values?
Sometimes I do not know how many languages are defined in XMLs data.
<?xml version="1.0" encoding="UTF-8"?>
<offer>
<products>
<product>
<description>
<name xml:lang="eng">English translation</name>
<name xml:lang="lat">Latvian translation</name>
</description>
</product>
<product>
<description>
<name xml:lang="eng">The same English</name>
<name xml:lang="pol">And Polish language</name>
</description>
</product>
</products>
</offer>
I can xml:lang parse in PHP by adding exact language code in xpath
print_r($xml->xpath('products/product/description/name[#xml:lang = "eng"]'));
But I need to add all xml:lang atributes values to parsed array.
Can it be done with PHP SimpleXML?
what about this:
$nodes = $xml->xpath('products/product/description/name[#xml:lang]');
Will return an array of <name>-nodes.
If this is not it, please clarify exactly your desired result.
EDIT
try this to get the xml:lang attributes only:
$langs = $xml->xpath("products/product/description/name[#xml:lang]/#xml:lang");
// $lang is an array of simplexml-elements, transform the values to string like this:
$langs = array_map("strval", $langs);
I'm not 100% on SimpleXML sorry, but I know DomDocument can do what you are after. Hopefully this can be of use to you:
$xmlstring = '<?xml version="1.0" encoding="UTF-8"?>
<offer>
<products>
<product>
<description>
<name xml:lang="eng">English translation</name>
<name xml:lang="lat">Latvian translation</name>
</description>
</product>
<product>
<description>
<name xml:lang="eng">The same English</name>
<name xml:lang="pol">And Polish language</name>
</description>
</product>
</products>
</offer>';
$dom = new DOMDocument();
$dom->loadXML($xmlstring); //or $dom->load('filename.xml');
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//products/product/description/name');
foreach ($nodes as $node) {
echo 'Language: ' . $node->getAttribute('xml:lang') . '<br />';
echo 'Value: ' . $node->nodeValue . '<br /><br />';
}
You can assign $node->getAttribute('xml:lang') to a variable and run some checks to see if it matches 'eng' or whatever you need.
I used xpath as you had in your original post, but you can also use $dom->getElementsByTagName('name') and access values and attributes in much the same way.
I found easier way to access namespaced attributes. You could use $name->attributes("xml", true) function.
Here is working example:
<?php
$xmlString = '
<products>
<product>
<name xml:lang="eng">
Apples
</name>
<name xml:lang="fr">
Pommes
</name>
</product>
<product>
<name xml:lang="eng">
Strawberries
</name>
<name xml:lang="fr">
Fraises
</name>
</product>
</products>
';
$xml = new \SimpleXMLElement($xmlString);
foreach($xml->product as $product)
{
foreach ($product->name as $name)
{
$attributes = $name->attributes("xml", true);
// print_r($attributes);
foreach ($attributes as $attributeName => $attributeValue)
{
// echo $attributeName . PHP_EOL;
// echo $attributeValue . PHP_EOL;
if ($attributeValue == "eng" && $attributeName == "lang") {
echo "English: " . trim(((string) $name)) . PHP_EOL;
}
if ($attributeValue == "fr" && $attributeName == "lang") {
echo "French: " . trim(((string) $name)) . PHP_EOL;
}
}
}
}
Online demo: https://repl.it/repls/LovingFineDaemon
I have an XML file that looks like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
<product sku="CATDJ" type="CAT" vendor="DJ" active="1" on_sale="0" discountable="0">
<name>CATALOGS</name>
<short_description><![CDATA[The DJ catalog features 182 pages]]></short_description>
<long_description><![CDATA[The DJ catalog features 182 pages.]]></long_description>
<price>1.5</price>
<stock_quantity>65</stock_quantity>
<release_date>2003-05-06T00:00:00-04:00</release_date>
<barcode>782421791315</barcode>
</product>
....
I can get the price, stock_quatity, and barcode, but not the sku, active or discountable data.
This is what my code looks like this:
$myinv = simplexml_load_file('http://www.*******.com/products.xml');
foreach ($myinv as $invinfo):
$sku = $invinfo->products->product->sku;
$active = $invinfo->products->product->active;
$deductible = $invinfo->products->product->discountable;
$qty=$invinfo->stock_quantity;
$price=$invinfo->price;
$upc=$invinfo->barcode;
What Am I doing wrong? BTW, I'm new to php.
Thank you for your help.
I always typecast everything I get from SimpleXML, because it always returns a SimpleXMLElement. var_dump your variables to see for yourself.
<?php
$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
<product sku="CATDJ" type="CAT" vendor="DJ" active="1" on_sale="0" discountable="0">
<name>CATALOGS</name>
<short_description><![CDATA[The DJ catalog features 182 pages]]></short_description>
<long_description><![CDATA[The DJ catalog features 182 pages.]]></long_description>
<price>1.5</price>
<stock_quantity>65</stock_quantity>
<release_date>2003-05-06T00:00:00-04:00</release_date>
<barcode>782421791315</barcode>
</product>
</products>';
$myinv = new SimpleXMLElement($xml);
$products = $myinv->product;
foreach ($products as $product){
$attrs = $product->attributes();
$sku = $attrs->sku;
$active = $attrs->active;
$discountable = $attrs->discountable;
$qty = $product->stock_quantity;
$price = $product->price;
$upc = $product->barcode;
echo (string)$sku . "<br>\n";
echo (string)$active . "<br>\n";
echo (string)$discountable . "<br>\n";
echo (string)$qty . "<br>\n";
echo (string)$price . "<br>\n";
echo (string)$upc . "<br>\n";
}
?>
XPath can do the job of getting the value of an attribute with $xpath->query("//product[#name='sku']/#value");.
How do you retrieve the value in atom:id from a XML document?
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
<atom:id>http://www.google.com/m8/feeds/profiles/domain/mydomain.com/full/test</atom:id>
</atom:entry>
You can use SimpleXML and XPath for that:
$xml = <<<XML
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
<atom:id>http://www.google.com/m8/feeds/profiles/domain/mydomain.com/full/test</atom:id>
</atom:entry>
XML;
$xml = new SimpleXMLElement($xml);
$result = $xml->xpath('/atom:entry/atom:id');
foreach ($result as $curResult)
{
echo __FILE__ . ':' . __LINE__ . '<pre>' . print_r($curResult, 1) . '</pre>';
}
You could use simple_xml and an xpath query. Like so:
$xml = <<<EOF
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
<atom:id>http://www.google.com/m8/feeds/profiles/domain/mydomain.com/full/test</atom:id>
</atom:entry>
EOF;
$doc = simplexml_load_string($xml);
$el = $doc->xpath('//atom:id');
echo (string)$el[0];
(obviously that's without error checking and all)
I am trying to edit some XML with PHP. Currently the XML looking something like:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Main Title</title>
<link>http://exmaple.com</link>
<description> blahblahblah </description>
<language>en</language>
<item>
<title>Tite1</title>
<link>http://www.example.com (THIS IS WHAT I WANT)</link>
<description>blah blah blah</description>
</item>
.
.
.
</channel>
</rss>
I've tried to access the 2nd level link but my code only changes the first Link node value. Here is the code:
$xml->load('http://www.google.com/doodles/doodles.xml');
$element = $xml->getElementsByTagName('channel')->item(0);
$secondlvl = $element->getElementsByTagName('item')->item(0);
$2ndlevellinknode = $element->getElementsByTagName('link')->item(0);
$2ndlevellinknode->nodeValue = $newvalue;
Any suggestions? Also is it possible to use this line of code in a for loop like this
for ($i = 0; $i <= 20; $i++) {
$element = $xml->getElementsByTagName('channel')->item(0);
$secondlvl = $element->getElementsByTagName('item')->item(0);
$2ndlevellinknode = $element->getElementsByTagName('link')->item($i);
$2ndlevellinknode->nodeValue = $newvalue;
}
this should give you an idea.
$f = simplexml_load_file('test.xml');
print $f->channel->title . "\n";
print $f->channel->link . "\n";
print $f->channel->description . "\n";
foreach($f->channel->item as $item) {
print $item->title . "\n";
}