XML ATOM to SimpleXML Object losing data - php

Hi, i have a simple problem. When i try to convert an atom XML string to simplexml object or using simplexml_load_data function, it seems to drop many attributes data..
like in my original string i have
<?xml version="1.0" encoding="UTF-8"?>
<feed gd:kind="customsearch#search" xmlns="http://www.w3.org/2005/Atom" xmlns:cse="http://schemas.google.com/cseapi/2010" xmlns:gd="http://schemas.google.com/g/2005" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
<title>Google Custom Search - flower</title>
<id>tag:www.googleapis.com,2010-09-29:/customsearch/v1?q=flower&&num=10&start=1&safe=off</id>
<author>
<name>- Google Custom Search</name>
</author>
<updated>1970-01-16T10:55:22.093Z</updated>
<opensearch:Url type="application/atom+xml" template="https://www.googleapis.com/customsearch/v1?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&safe={cse:safe?}&cx={cse:cx?}&cref={cse:cref?}&sort={cse:sort?}&filter={cse:filter?}&gl={cse:gl?}&cr={cse:cr?}}&googlehost={cse:googleHost?}&c2coff={?cse:disableCnTwTranslation}&hq={cse:hq?}&hl={cse:hl?}&siteSearch={cse:siteSearch?}&siteSearchFilter={cse:siteSearchFilter?}&exactTerms={cse:exactTerms?}&excludeTerms={cse:excludeTerms?}&linkSite={cse:linkSite?}&orTerms={cse:orTerms?}&relatedSite={cse:relatedSite?}&dateRestrict={cse:dateRestrict?}&lowRange={cse:lowRange?}&highRange={cse:highRange?}&searchType={cse:searchType?}&fileType={cse:fileType?}&rights={cse:rights?}&imgsz={cse:imgsz?}&imgtype={cse:imgtype?}&imgc={cse:imgc?}&imgcolor={cse:imgcolor?}&alt=atom"/>
<opensearch:Query role="request" title="Google Custom Search - flower" totalResults="98800000" searchTerms="flower" count="10" startIndex="1" inputEncoding="utf8" outputEncoding="utf8" cse:safe="off" cse:cx="g"/>
<opensearch:Query role="cse:nextPage" title="Google Custom Search - flower" totalResults="98800000" searchTerms="flower" count="10" startIndex="11" inputEncoding="utf8" outputEncoding="utf8" cse:safe="off" cse:cx="0vv1rbg"/>
<opensearch:totalResults>98800000</opensearch:totalResults>
<opensearch:startIndex>1</opensearch:startIndex>
but when i convert it to xml using
$xml = simplexml_load_string($rs);
print_r($xml);
my output is like below. All the key information like number of searches, total results set is gone..
SimpleXMLElement Object
(
[title] => Google Custom Search - flower
[id] => tag:www.googleapis.com,2010-09-29:/customsearch/v1?q=flower&cx=&num=10&start=1&safe=off
[author] => SimpleXMLElement Object
(
[name] => Search Engine - Google Custom Search
)
[updated] => 1970-01-16T10:55:22.093Z
[entry] => Array
(
[0] => SimpleXMLElement Object
(
[id] => http://en.wikipedia.org/wiki/Flower
[updated] => 1970-01-16T10:55:22.093Z
[title] => <b>Flower</b> - Wikipedia, the free encyclopedia
[link] => SimpleXMLElement Object
(
[#attributes] => Array
(
[href] => http://en.wikipedia.org/wiki/Flower
[title] => en.wikipedia.org
)
)
[summary] => A <b>flower</b>, sometimes known as a bloom or blossom, is the reproductive structure <br> found in <b>flowering</b> plants (plants of the division Magnoliophyta, also called <b>...</b>
)

Those elements are not gone, you just can't "see" them in a standard dump, because they are in a different namespace. You can still iterate over them like this:
foreach ($xml->children('opensearch', TRUE) as $element) {
echo $element->getName(), "\n";
}
Where 'opensearch' indicates the namespace prefix and TRUE means that you used the document specific prefix instead of the full namespace url.

Related

How to get attribute value from element with several attributes

I have this xml file (part of it):
<exchangerates xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="Valutakurser" author="Danmarks Nationalbank" refcur="DKK" refamt="1">
<dailyrates id="2020-10-23">
<currency code="AUD" desc="Australske dollar" rate="448,83"/>
<currency code="BGN" desc="Bulgarske lev" rate="380,44"/>
I want to get the rate from AUD, Australian dollar.
My xpath query looks like this:
$result = $xml->xpath("/exchangerates/dailyrates/currency[#code = 'AUD']");
It works and deliver this output:
Array ( [0] => SimpleXMLElement Object ( [#attributes] => Array ( [code] => AUD [desc] => Australske
dollar [rate] => 448,83 ) ) )
And now I am stuck. I want the [rate] value. But how? I have solved this in c# using a navigator.
But now I am using php. I could use javascript if necessary.
From the xpath point of view, you just need to add /#attributeName to your xpath.
/exchangerates/dailyrates/currency[#code = 'AUD']/#rate

SimpleXML to Array

I load some XML which produces a SimpleXML Object like so (only displaying one Object)
SimpleXMLElement Object
(
[Jobs] => SimpleXMLElement Object
(
[Job] => Array
(
[0] => SimpleXMLElement Object
(
[ID] => J000001
[Name] => Internal Time
[Description] => Use this job to record your internal and non-billable time for activities such as annual leave, sick leave, professional development, staff meetings etc
[Client] => SimpleXMLElement Object
(
[ID] => 8430219
[Name] => Fake Client
)
[ClientOrderNumber] => SimpleXMLElement Object
(
)
[State] => Planned
[StartDate] => 2016-03-21T00:00:00
[DueDate] => 2017-03-21T00:00:00
[InternalID] => 11442733
[Assigned] => SimpleXMLElement Object
(
[Staff] => SimpleXMLElement Object
(
[ID] => 344460
[Name] => Som Name
)
)
)
)
)
)
What I would like to do is create an array of the client Name and client ID. So I am aiming for something like so
[data] => array (
8430219 => Fake Client,
8430343 => Another Client,
etc
)
At the moment, I can get the name in place, but struggling with the id because it says it is an illegal offset type. This is what I have
foreach($oXML->Jobs as $oEntry) {
foreach ($oEntry->Job as $data) {
$jobsArray = array(
$data->Client->ID => $data->Client->Name
);
}
}
How can I create the array based on the SimpleXML Object I have?
Thanks
First of all, to obtain your desired array you can not use this syntax:
$jobsArray = array( $key => $val );
You have to use something like this:
$jobsArray[$key] = $val;
Otherwise, at each repeating loop, your syntax will override precedent array values.
Then, I suggest you to use XPath to simplify entire process. With XPath queries, you can retrieve a set of nodes with only one search.
Assuming you have this XML:
<?xml version="1.0"?>
<Jobs>
<Job>
<Client>
<ID>8430219</ID>
<Name>Fake Client</Name>
</Client>
<Client>
<ID>8430220</ID>
<Name>Fake Client 2</Name>
</Client>
</Job>
<Job>
<Client>
<ID>8430221</ID>
<Name>Fake Client 3</Name>
</Client>
</Job>
</Jobs>
With this xpath query:
$clients = $oXML->xpath( '/Jobs/Job/Client' );
you obtain in $clients all <Client> nodes. Then you can create your array in this way:
$result = array();
foreach( $clients as $client )
{
$result[$client->ID->__toString()] = $client->Name->__toString();
}
This is $result after foreach loop:
Array
(
[8430219] => Fake Client
[8430220] => Fake Client 2
[8430221] => Fake Client 3
)
Note that we have to cast as string single nodes (that are SimpleXML objects): this is absolutely necessary creating keys, otherwise the array assignment fails. You can obtain same result using (string) $client->ID instead of $client->ID->__toString()
Read more about SimpleXMLElement::xpath
Read more about XPath

PHP simplexml_load_string() elements within elements

I'm trying to parse some XML data using the php function simplexml_load_string() however it doesn't seem to work on elements where there is text and then further elements. Here is a sample data:
<?xml version="1.0"?>
<KPPRINT>
<CURRENTDATE>31/01/2015</CURRENTDATE>
<CURRENTTIME>21:43</CURRENTTIME>
<HEADER>
<ORDERNUMBER>CHECK NO: 69</ORDERNUMBER>
<CHECKNUMBER>ORDER NO: 16</CHECKNUMBER>
<REFTEXT>Party table</REFTEXT>
<REFTEXT>LOCATION 4</REFTEXT>
</HEADER>
<ITEM>VK Ice<QTY>1</QTY><PRICE>£0.03</PRICE><RECORD>57</RECORD><DEPT number="1" name="Wet Sales"/><GROUP number="5" name="FABs"/><CAT number="1" name="CATEGORY 1"/></ITEM>
<ITEM>Bramble<QTY>1</QTY><PRICE>£0.45</PRICE><RECORD>241</RECORD><DEPT number="1" name="Wet Sales"/><GROUP number="10" name="Cocktails"/><CAT number="1" name="CATEGORY 1"/></ITEM>
<ITEM>Gran Seleccion Rioja<QTY>1</QTY><PRICE>£19.95</PRICE><RECORD>225</RECORD><DEPT number="1" name="Wet Sales"/><GROUP number="9" name="Wines & Champagnes"/><CAT number="1" name="CATEGORY 1"/></ITEM>
<TRAILER>
<CLERK>Tom</CLERK>
<MACHINE>S000-T1</MACHINE>
<TIME>21:43</TIME>
<CONSEC>000023</CONSEC>
</TRAILER>
</KPPRINT>
This is the output I get:
Array
(
[CURRENTDATE] => 31/01/2015
[CURRENTTIME] => 21:43
[HEADER] => Array
(
[ORDERNUMBER] => CHECK NO: 69
[CHECKNUMBER] => ORDER NO: 16
[REFTEXT] => Array
(
[0] => Party table
[1] => LOCATION 4
)
)
[ITEM] => Array
(
[0] => Product 1
[1] => Product 2
[2] => Product 3
)
[TRAILER] => Array
(
[CLERK] => Tom
[MACHINE] => S000-T1
[TIME] => 21:43
[CONSEC] => 000023
)
)
The element text is there but the other elements within are not. Is there a simple option to the function or do I need to parse the whole string manually?
If it doesn't work with simplexml_load_string() you should try work with the data as recursive objects with DOMDocument because it allows to work with children nodes and I think it is not limited.
Please consider reading the following pages:
http://php.net/manual/en/class.domdocument.php
http://www.w3schools.com/php/php_xml_dom.asp

PHP XML xlink:href Attributes [duplicate]

This question already has answers here:
Simple XML - Dealing With Colons In Nodes
(4 answers)
Closed 8 years ago.
I'm having trouble reading attributes from the Spreadshirt API with SimpleXML. I can't grab the xlink:href attribute from resources, which is what I need as it's not displays in the data received. Seem to be able to grab everything else, though.
This is the XML I'm reading in:
<articles xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://api.spreadshirt.net" xlink:href="http://api.spreadshirt.net/api/v1/shops/800323/articles?fullData=true" offset="0" limit="50" count="16" sortField="default" sortOrder="default">
<article isDuplicate="false" xlink:href="http://api.spreadshirt.net/api/v1/shops/800323/articles/100402428" id="100402428">
<name>Hammer T-Shirt</name>
<price>
<vatExcluded>13.33</vatExcluded>
<vatIncluded>16.00</vatIncluded>
<vat>20.00</vat>
<currency xlink:href="http://api.spreadshirt.net/api/v1/currencies/2" id="2"/>
</price>
<resources>
<resource mediaType="png" type="preview" xlink:href="http://image.spreadshirt.net/image-server/v1/products/125642560/views/1"/>
</resources>
</article>
</atricles>
This is the data coming back from SimpleXML:
SimpleXMLElement Object
(
[#attributes] => Array
(
[isDuplicate] => false
[id] => 27368595
)
[name] => Hammer Boxers
[price] => SimpleXMLElement Object
(
[vatExcluded] => 10.00
[vatIncluded] => 12.00
[vat] => 20.00
[currency] => SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => 2
)
)
)
[resources] => SimpleXMLElement Object
(
[resource] => SimpleXMLElement Object
(
[#attributes] => Array
(
[mediaType] => png
[type] => preview
)
)
)
)
Does anyone have any ideas? I'm stumped.
The isDuplicate and id attributes are in the same namespace as the element.
The href element is in the http://www.w3.org/1999/xlink namespace, as indicated by the xlink prefix that is registered on the <articles> root element.
To access all the elements for the namespace, call $element->attributes('http://www.w3.org/1999/xlink').
The idea is that the root element could instead say xmlns:foobar="http://www.w3.org/1999/xlink", and each <article> would have foobar:href="..." attributes, and the code above would still work, because the bound prefix is just a way of improving readability. What counts is the namespace URL, not its prefix.

access data attributes using simpleXML

I am using an API to get a Block FIPS number but I have not been able to target that specific number within the XML file.
I did a print_r() on the xml output and here is what I get
SimpleXMLElement Object ( [#attributes] => Array ( [status] => OK [executionTime] => 6 ) [Block] => SimpleXMLElement Object ( [#attributes] => Array ( [FIPS] => 060730200252015 ) ) [County] => SimpleXMLElement Object ( [#attributes] => Array ( [FIPS] => 06073 [name] => San Diego ) ) [State] => SimpleXMLElement Object ( [#attributes] => Array ( [FIPS] => 06 [code] => CA [name] => California ) ) )
Here is the XML that is being generated
<Response xmlns="http://data.fcc.gov/api" status="OK" executionTime="10">
<Block FIPS="060730200252015"/>
<County FIPS="06073" name="San Diego"/>
<State FIPS="06" code="CA" name="California"/>
</Response>
I have been trying to get the Block FIPS Number like this:
$fccAPI = "http://data.fcc.gov/api/block/2010/find?latitude=$lat&longitude=$lng";
//echo $fccAPI;
$fccXML= simplexml_load_file($fccAPI);
print_r($fccXML);
//Echo FIPS Number
echo $fccXML->FIPS;
Please help me target the Block FIPS number.
You need to use the following:
echo $fccXML->Block[0]['FIPS'];
$fccXML is the root node, the <Response> element. ->Block[0] selects the first Block element, and to access an attribute, use the square brackets notation with the attribute name, i.e. ['FIPS'].
The SimpleXML documentation has numerous examples if you're having trouble with the syntax.

Categories