Using PHP to get xml selector attributes - php

I am trying to access the xml attributes using php. I can access the actual text of any field, but
For example, a line from the xml file looks like this:
<Competitor CODE1="MIN" CODE3="MIN" CODE4="l.mlb.com-t.10" ID="69" LineOrderOverride="" NAME="Minnesota Twins" NUM="1" ROT="927" SCORE="5">Game 1</Competitor>
The code I am using will show me "Game 1" but I want to be able to access the NAME and SCORE values
#$doc->load($feedURL);
$arrFeeds = array();
foreach ($doc->getElementsByTagName('Event') as $node) {
$itemRSS = array (
echo strip_tags(str_replace("'","",$node->getElementsByTagName('Competitor')->item(0)->nodeValue));
};
Does anyone know a way to access the meta variables using PHP?

Inside your foreach(), add
echo $node->getElementsByTagName('Competitor')->item(0)->getAttribute("NAME"); // For NAME
echo $node->getElementsByTagName('Competitor')->item(0)->getAttribute("SCORE"); // For SCORE

Related

Loading a Search and Retrieve via URL (SRU) in php with simplexml_load_string returns an empty object

Im trying to load search result from an library api using Search and Retrieve via URL (SRU) at : https://data.norge.no/data/bibsys/bibsys-bibliotekbase-bibliografiske-data-sru
If you see the search result links there, its looks pretty much like XML but when i try like i have before with xml using the code below, it just returns a empty object,
SimpleXMLElement {#546}
whats going on here?
My php function in my laravel project:
public function bokId($bokid) {
$apiUrl = "http://sru.bibsys.no/search/biblio?version=1.2&operation=searchRetrieve&startRecord=1&maximumRecords=10&query=ibsen&recordSchema=marcxchange";
$filename = "bok.xml";
$xmlfile = file_get_contents($apiUrl);
file_put_contents($filename, $xmlfile); // xml file is saved.
$fileXml = simplexml_load_string($xmlfile);
dd($fileXml);
}
If i do:
dd($xmlfile);
instead, it echoes out like this:
Making me very confused that i cannot get an object to work with. Code i present have worked fine before.
It may be that the data your being provided ha changed format, but the data is still there and you can still use it. The main problem with using something like dd() is that it doesn't work well with SimpleXMLElements, it tends to have it's own idea of what you want to see of what data there is.
In this case the namespaces are the usual problem. But if you look at the following code you can see a quick way of getting the data from a specific namespace, which you can then easily access as normal. In this code I use ->children("srw", true) to say fetch all child elements that are in the namespace srw (the second argument indicates that this is the prefix and not the URL)...
$apiUrl = "http://sru.bibsys.no/search/biblio?version=1.2&operation=searchRetrieve&startRecord=1&maximumRecords=10&query=ibsen&recordSchema=marcxchange";
$filename = "bok.xml";
$xmlfile = file_get_contents($apiUrl);
file_put_contents($filename, $xmlfile); // xml file is saved.
$fileXml = simplexml_load_string($xmlfile);
foreach ( $fileXml->children("srw", true)->records->record as $record) {
echo "recordIdentifier=".$record->recordIdentifier.PHP_EOL;
}
This outputs...
recordIdentifier=792012771
recordIdentifier=941956423
recordIdentifier=941956466
recordIdentifier=950546232
recordIdentifier=802109055
recordIdentifier=910941041
recordIdentifier=940589451
recordIdentifier=951721941
recordIdentifier=080703852
recordIdentifier=011800283
As I'm not sure which data you want to retrieve as the title, I just wanted to show the idea of how to fetch data when you have a list of possibilities. In this example I'm using XPath to look in each <srw:record> element and find the <marc:datafield tag="100"...> element and in that the <marc:subfield code="a"> element. This is done using //marc:datafield[#tag='100']/marc:subfield[#code='a']. You may need to adjust the #tag= bit to the datafield your after and the #code= to point to the subfield your after.
$fileXml = simplexml_load_string($xmlfile);
$fileXml->registerXPathNamespace("marc","info:lc/xmlns/marcxchange-v1");
foreach ( $fileXml->children("srw", true)->records->record as $record) {
echo "recordIdentifier=".$record->recordIdentifier.PHP_EOL;
$data = $record->xpath("//marc:datafield[#tag='100']/marc:subfield[#code='a']");
$subData=$data[0]->children("marc", true);
echo "Data=".(string)$data[0].PHP_EOL;
}

Separating XML products by Category in PHP

I read an XML file in PHP by
$xml=simplexml_load_file("./files/downloaded.xml");
This file is having many products with different categories.
I want to separate them with respect to their categories.
Here is the look of the read file view by the following code.
print "<pre>";
print_r($xml);
print "</pre>";
I separated the products by the following code
$baby = array();
for($x=0;$x < count($xml->product); $x++)
{
if( preg_match("#Groceries > ([ a-zA-Z0-9]+) >#i",$xml->product[$x]->category,$match) )
{
$match[1] = str_replace(" ", "" , strtolower($match[1]) );
if($match[1] == "baby"){
$baby[] = $xml->product[$x];
}
}
}
and it has been separated in an array named as $baby and here is the view of the baby array by the following code
print "<pre>";
print_r($baby);
print "</pre>";
Now I want to save this as baby.xml and baby.json file but I don't know how to save this.
I tried this code to save these files
$baby_json = simplexml_load_string($baby);
$json = json_encode($baby_json);
file_put_contents("./files/foodcupobard.json",$json);
file_put_contents("./files/foodcupobard.xml",$baby);
But it is not working after separation.
Here is the code which works before separation
$xml=simplexml_load_file("./files/downloaded.xml");
$xml_json = simplexml_load_string($xml);
$json = json_encode($xml_json);
file_put_contents("./files/baby.json",$json);
file_put_contents("./files/baby.xml",$xml);
The reason it is not working after separation is that after separation {$baby} becomes an array instead of SimpleXMLElement Object. Can anyone help me to save these separated products into an baby.xml and baby.json files ? or any other way to separate these products with php code ?
Any Help would be much appreciated!
Thanks :)
Manipulate the original SimpleXml object instead of creating an array.
Then save as XML with $xml->asXML($filename);
Use xpath to select <product> nodes with a certain <category>. xpath is like SQL for XML:
/products/product[starts-with(category, 'Foo > Bar >')]
Comments:
expression will return all <product> having a <category> starting with "Foo > Bar >"
[] enclose a condition.
you could use the contains function instead of start-with
code example:
$products = $xml->xpath("/products/product[starts-with(category, 'Foo > Bar >')]");
BUT $products is an array of SimpleXml elements, but no SimpleXml object, so asXML() won't work here.
Solution 1:
select all <product> that are NOT in the desired category
delete those from $xml
save with asXML()
code example:
$products = $xml->xpath("/products/product[not(starts-with(category, 'Foo > Bar >'))]");
foreach ($products as $product)
unset($product[0]);
This is the self-reference-technique to delete a node with unset.
show the manipulated XML:
echo $xml->asXML();
see it working: https://eval.in/512140
Solution 2
Go with the original $products and build a new XML string from it.
foreach ($products as $product)
$newxmlstr = $newxmlstr . $product->asXML();
$newxmlstr = "<products>" . $newxmlstr . "</products>";
see it working: https://eval.in/512153
I prefer solution 1. XML manipulation by string functions carry the risk of error. If the original XML is really large, solution 2 might be faster.

Php xml parsing for element value

i have the following xml returned from a jsp call
<assumption name="test" id="34" description="vector description" is_shared="no" vector_type="Prepay">
<userVector>
<vectorType>"Prepay"</vectorType>
<ppydefTypeCode>"CDR"</ppydefTypeCode>
<ppydefVector>
<vectorName>"test"</vectorName>
<vectorSeasoning>No</vectorSeasoning>
<vectorPeriod>"6 12"</vectorPeriod>
<vectorData>"7 4"</vectorData>
</ppydefVector>
</userVector>
</assumption>
What is the best way to retrieve the vectorType information and vectorName using php .
I tried something similar but was not sure how to grab the node value in php
foreach ($xmlDoc->getElementsByTagName('userVector') as $vectorRow)
{
$vectorType = $xmlDoc->getElementsByTagName('vectorType');
}
getElementsByTagName('vectorType') will return a DOMNodeList that you'll additionally have to iterate through. You can save each element's value to a variable by accessing their nodeValue fields.
foreach ($xmlDoc->getElementsByTagName('userVector') as $vectorRow){
$vectorTypes = $vectorRow->getElementsByTagName('vectorType');
foreach ($vectorTypes as $vectorTypeElement){
$vectorType = $vectorTypeElement->nodeValue;
}
}
Try this:
$sx = new SimpleXMLElement($XMLData);
echo $sx->xpath('/assumption/userVector/vectorType')[0];
echo $sx->xpath('/assumption/userVector/ppydefVector/vectorName')[0];
Outputs:
"Prepay"
"test"

how to display SimpleXMLElement with php

Hi I have never used xml but need to now, so I am trying to quickly learn but struggling with the structure I think. This is just to display the weather at the top of someones website.
I want to display Melbourne weather using this xml link ftp://ftp2.bom.gov.au/anon/gen/fwo/IDV10753.xml
Basically I am trying get Melbourne forecast for 3 days (what ever just something that works) there is a forecast-period array [0] to [6]
I used this print_r to view the structure:
$url = "linkhere";
$xml = simplexml_load_file($url);
echo "<pre>";
print_r($xml);
and tried this just to get something:
$url = "linkhere";
$xml = simplexml_load_file($url);
$data = (string) $xml->forecast->area[52]->description;
echo $data;
Which gave me nothing (expected 'Melbourne'), obviously I need to learn and I am but if someone could help that would be great.
Because description is an attribute of <area>, you need to use
$data = (string) $xml->forecast->area[52]['description'];
I also wouldn't rely on Melbourne being the 52nd area node (though this is really up to the data maintainers). I'd go by its aac attribute as this appears to be unique, eg
$search = $xml->xpath('forecast/area[#aac="VIC_PT042"]');
if (count($search)) {
$melbourne = $search[0];
echo $melbourne['description'];
}
This is a working example for you:
<?php
$forecastdata = simplexml_load_file('ftp://ftp2.bom.gov.au/anon/gen/fwo/IDV10753.xml','SimpleXMLElement',LIBXML_NOCDATA);
foreach($forecastdata->forecast->area as $singleregion) {
$area = $singleregion['description'];
$weather = $singleregion->{'forecast-period'}->text;
echo $area.': '.$weather.'<hr />';
}
?>
You can edit the aforementioned example to extract the tags and attributes you want.
Always remember that a good practice to understand the structure of your XML object is printing out its content using, for instance, print_r
In the specific case of the XML you proposed, cities are specified through attributes (description). For this reason you have to read also those attributes using ['attribute name'] (see here for more information).
Notice also that the tag {'forecast-period'} is wrapped in curly brackets cause it contains a hyphen, and otherwise it wouldn generate an error.

xpath search for a php variable

I am trying to search for a php variable in an xml file using xpath, but failing miserably. It works with a hard coded value, so I am nearly there..
<visitors>
<detail>
<id>876867</id>
<name>Bob McHaggis</name>
<email>bob#gmail.com</email>
</detail>
<detail>
<id>897987</id>
<name>Mark McBob</name>
<email>mark#gmail.com</email>
</detail>
</visitors>
<?php $sxe = simplexml_load_file("/CaptivePortal/visitors.xml");
foreach($sxe->xpath('//visitors/detail') as $item){
$row = simplexml_load_string($item->asXML());
$v = $row->xpath('//id[. ="'.$_COOKIE["judsons"].'"]');
} echo $v[0]; ?>
This works great checks for an id against the id stored in the cookie. But based on that value being found how do I access the name and email for the key matched?
Found & matched: 897987
I want to echo the name and email to, so based on that is Mark McBob & mark#gmail.com
My initial advice would be to take a good few minutes to (re-)read through the SimpleXML Basic Usage page in the PHP manual.
For selecting a single item within the XML file, there is no need at all to loop over anything. The example code below, and why it is different from yours, should become clear after familiarising yourself with the page mentioned above.
<?php
$search_id = (int) $_COOKIE["judsons"];
$visitors = simplexml_load_file("/CaptivePortal/visitors.xml");
$details = $visitors->xpath("detail[id='$search_id']");
if (empty($details)) {
echo "No details found for '$search_id'.";
} else {
$detail = $details[0];
$name = (string) $detail->name;
$email = (string) $detail->email;
echo "$name's email is $email";
}
The idea above is that $details will be an array containing hopefully just one <detail> element. It could be an empty array if no <detail> was found with the specified <id>, which is what the if(empty(…)) checks for. If the $details array is not empty, we're really only interested in the first one ($details[0]).
To access the information available within the <detail>, as explained on the "basic usage" page, the elements can be accessed with normal object property syntax ($detail->name). Doing so returns an object for that item (e.g. the <name>), so to get at the value as a string the object is type cast using (string).
You're actually doing quite a bit you don't need to there. For one thing, you don't need the loop. For another, inside your loop, you convert the context XML into a string (::asXML()), then convert it back into XML (simplexml_load_string()).
All you need is:
$xml = "<visitors><detail><id>876867</id><name>Bob McHaggis</name><email>bob#gmail.com</email></detail><detail><id>897987</id><name>Mark McBob</name><email>mark#gmail.com</email></detail></visitors>";
$sxe = simplexml_load_string($xml);
$row = $sxe->xpath('detail[id = '.$_COOKIE["judsons"].']');
That gets you the row. To extract part of it:
$name = $row[0]->xpath('name');
echo $name[0]; //Mark McBob

Categories