I have a problem. My PHP script not working and I dont know why. This is XML file:
http://itoffice.sk/toto.xml
And this is my PHP code for read XML:
$xml = simplexml_load_file("toto.xml") or die("feed sa nepodarilo načítať");
$id = $xml->Zbozi['kod_zbozi'];
echo $id;
This not working. I need show and write into MySQL all attributes of <Zbozi>
<Zbozi> example:
<Zbozi diffgr:id="Zbozi1" msdata:rowOrder="0" kod_zbozi="DL139A" popis="HP DMS-59 to Dual DVI Cable Kit,accessory" part_number="DL139A" zaruka="24" dostupnost="false" dph="20" cena="29.23" cenaEU="35.34" snimek="DL139A/06_s.jpg" kod_vyrobce="093-001453" kod_kategorie="PC STOLNÍ POČÍTAČE" kategorie="Stolné počítače" kod_podkategorie="PŘÍSLUŠENSTVÍ ZN PC" podkategorie="Príslušenstvo značkových PC" typ="0" aut_poplatek="0.000" rema="0.000" sam_neprodejne="0" sn_vydej="false" ean="808736662901" doprodej="false">
Help me please. Thanks.
The reason your script was not working, is because you weren't following the XML tree properly. As you can see, your XML's structure looks like this:
<diffgr:diffgram>
<Cenik>
<Zbozi></Zbozi>
...
<Zbozi></Zbozi>
</Cenik>
</diffgr:diffgram>
Therefore you would have to follow that tree, and then loop for the Zbozi elements in order to get all of their attributes.
Take a look at this code:
$xml = simplexml_load_file('http://itoffice.sk/toto.xml');
$zbozi = $xml->children('diffgr', TRUE)->diffgram->children()->Cenik->Zbozi;
$id_arr = array();
foreach ($zbozi as $zbozi_element)
{
$id_arr[] = (string) $zbozi_element['kod_zbozi'];
}
First we load the XML file, nothing new there. But in the second line, we are traversing down the XML file. First we set the prefix namespace to diffgr (because of the semicolon in diffgr:diffgram), then we simply find the Zbozi elements, and loop for them.
You can see that in the loop I've added all of the kod_zbozi attribute values into an array. You can really do anything you'd like with that information at this point, this was just to get you started.
Related
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;
}
Sorry for possible newbie question, but I need to use xml for an import. I've figured it out so far but then scratched my eyeballs out while trying to figure out this (and searched for it)
I have this
<?php
$xml = new DOMDocument("1.0","UTF-8");
$container = $xml-> createElement("container");
$container = $xml-> appendChild($container);
for($n=0;$n<8;$n++){
$maxnum[]=$n;
}
$xtags = $xml->CreateElement("tags",$maxnum); $xtags = $container->appendChild($xtags);
if($xml->save("stuff2.xml")){echo 'success';} else {echo 'not working';}
?>
Basically I dont want to create a child node for ever value of a loop. And I know thats not the proper way to do it, nor is array_values and so on. But it's what I want to achieve. I need to generate an XML file for wpall import so that I can succesfully bulk import to woocommerce. The specific attribute here i ize, and Im getting that usingfile_get_contents` from the server, parsing which xpath with a foreach loop. Problem is I want them all in a single field rather than having this
<size>
<value>1</value>
<value>2</value>
</size>
and so on, when I want it like this <size><value>1,2,3....</value></size>
Any help, please?
Then you do not need to use an array,
you can do something like:
echo "<size><value>";
foreach($n as $n){
$string="$string, ".$n;
}
echo $string;
echo" </value></size>";
I'm fairly new to php although I've been programming for a couple years.
I'm working on a project and the end goal is to load certain elements of an xml file into an oracle table on a nightly basis. I have a script which runs nightly and saves a the file on my local machine. I've searched endlessly for answers but have been unsuccessful.
Here is an aggregated example of the xml file.
<?xml version="1.0" encoding="UTF-8" ?>
<Report account="7869" start_time="2012-02-23T00:00:00+00:00" end_time="2012-02-23T15:27:59+00:00" user="twilson" more_sessions="false">
<Session id="ID742247692" realTimeID="4306650378">
<Visitor id="5390643113837">
<ip>128.XXX.XX.XX</ip>
<agent>MSIE 8.0</agent>
</Visitor>
</Session>
<Session id="ID742247695" realTimeID="4306650379">
<Visitor id="7110455516320">
<ip>173.XX.XX.XXX</ip>
<agent>Chrome 17.0.963.56</agent>
</Visitor>
</Session>
</Report>
One thing to note is that the xml file will contain several objects which I will need to load into my table and the above example would just be for two rows of data. I'm familiar with the whole process of connecting and loading data into oracle and have setup similar scripts which perform ETL of txt. and csv. files using php. Unfortunately for me in this case the data is stored in xml. The approach I've taken when loading a csv. file is to load the data into an array and proceed from there.
I'm pretty certain that I can use something similar and perhaps create variable for each or something similar but am not really too sure how to do that with an xml. file.
$xml = simplexml_load_file('C:/Dev/report.xml');
echo $xml->Report->Session->Visitor->agent;
In the above code i'm trying to just return the agent associated with each visitor. This returns an error 'Trying to get property of non-object in C:\PHP\chatTest.php on line 11'
The end result would be for me to load the data into a table similar to the example I provided would be to load two rows into my table which would look similar to below however I think I can handle that if i'm able to get the data into an array or something similar.
IP|AGENT
128.XXX.XX.XX MSIE 8.0
173.XX.XX.XXX Chrome 17.0.963.56
Any help would be greatly appreciated.
Revised Code:
$doc = new DOMDocument();
$doc->load( 'C:/Dev/report.xml' );
$sessions = $doc->getElementsByTagName( "Session" );
foreach( $sessions as $session )
{
$visitors = $session->getElementsByTagName( "Visitor" );
foreach( $visitors as $visitor )
$sessionid = $session->getAttribute( 'realTimeID' );
{
$ips = $visitor->getElementsByTagName( "ip" );
$ip = $ips->item(0)->nodeValue;
$agents = $visitor->getElementsByTagName( "agent" );
$agent = $ips->item(0)->nodeValue;
echo "$sessionid- $ip- $agent\n";
}}
?>
The -> operator in PHP means that you are trying to invoke a field or method on an object. Since Report is not a method within $xml, you are receiving the error that you are trying to invoke a property on a non-object.
You can try something like this (don't know if it works, didn't test it and haven't written PHP for a long time, but you can google it):
$doc = new DOMDocument();
$doc->loadXML($content);
foreach ($doc->getElementsByTagName('Session') as $node)
{
$agent = $node->getElementsByTagName('Visitor')->item(0)->getElementsByTagName('agent')->item(0)->nodeValue;
}
edit:
Adding stuff to an array in PHP is easy as this:
$arr = array();
$arr[] = "some data";
$arr[] = "some more data";
The PHP arrays should be seen as a list, since they can be resized on the fly.
I was able to figure this out using simplexml_load_file rather than the DOM approach. Although DOM works after modifying the Leon's suggestion the approach below is what I would suggest.
$xml_object = simplexml_load_file('C:/Dev/report.xml');
foreach($xml_object->Session as $session) {
foreach($session->Visitor as $visitor) {
$ip = $visitor->ip;
$agent = $visitor->agent;
}
echo $ip.','.$agent."\n";
}
I'm trying to get a product list for a client from a webservices xml file over to an SQL databse using a little php script, but I can't seem to get it to work.
The relevant code is as follows:
$c = 0;
...
$xml = simplexml_load_file($completeurl);
$listingsArray = $xml->listings->listing;
foreach($listingsArray as $listing){
$addition[0] = $listing[$c]->type;
$addition[1] = $listing[$c]->condition;
//etcetera
c = c + 1;
}
The XML file is formated like:
<inventory>
<listings>
<listing>
//tags for type, condition, etc
</listing>
</listings>
</inventory>
$completeurl is a string that contains the url of the xml file
$addition is an array that's defined earlier in the code
I've been working on this for a while now, but I can't seem to figure out where the error is in my code. The problem that I'm having is that $listingsArray should have close to 100 elements in it, but is constantly coming up with 0. Anybody see what I'm doing wrong?
EDIT: I tried changing
$listingsArray = $xml->listings->listing;
to
$listingsArray = $xml->listings;
But empty strings are still being written to the $addition array. A var_dump of listingsArray show that all of the information is in there, though.
If you want each listing i believe you are going a child too deep.
$listingsArray = $xml->listings->listing;
shoudl be
$listingsArray = $xml->listings;
foreach($listingsArray as $listing){
$addition[0] = $listing[$c]->type;
$addition[1] = $listing[$c]->condition;
//etcetera
}
additionally what is $c? It also helps to post your exact errors. When debugging inserting var_dumps is extremely helpful. If you think the probelm is $listingArray
print it out and see if it contains the data you want.
changing
$listingsArray = $xml->listings->listing;
to
$listingsArray = $xml->listings;
Should solve the issue. You set $listingsArray to the array of listings, then the foreach tries to go down another level
I'm trying to loop through multiple <LineItemInfo> products contained within a <LineItems> within XML I'm parsing to pull product Ids out and send emails and do other actions for each product.
The problem is that it's not returning anything. I've verified that the XML data is valid and it does contain the necessary components.
$itemListObject = $orderXML->getElementsByTagName('LineItemInfo');
var_dump($itemListObject->length);
var_dump($itemListObject);
The output of the var_dump is:
int(0)
object(DOMNodeList)#22 (0) {
}
This is my first time messing with this and it's taken me a couple of hours but I can't figure it out. Any advice would be awesome.
EDIT:
My XML looks like this... except with a lot more tags than just ProductId
<LineItems>
<LineItemInfo>
<ProductId href='[URL_TO_PRODUCT_XML]'>149593</ProductId>
</LineItemInfo>
<LineItemInfo>
<ProductId href='[URL_TO_PRODUCT_XML]'>149593</ProductId>
</LineItemInfo>
</LineItems>
Executing the following code does NOT get me the ProductId
$itemListObject = $orderXML->getElementsByTagName('LineItemInfo');
foreach ($itemListObject as $element) {
$product = $element->getElementsByTagName('ProductId');
$productId = $product->item(0)->nodeValue;
echo $productId.'-';
}
EDIT #2
As a side note, calling
$element->item(0)->nodeValue
on $element instead of $product caused my script's execution to discontinue and not throwing any errors that were logged by the server. It's a pain to debug when you have to run a credit card to find out whether it's functioning or not.
DOMDocument stuff can be tricky to get a handle on, because functions such as print_r() and var_dump() don't necessarily perform the same as they would on normal arrays and objects (see this comment in the manual).
You have to use various functions and properties of the document nodes to pull out the data. For instance, if you had the following XML:
<LineItemInfo attr1="hi">This is a line item.</LineItemInfo>
You could output various parts of that using:
$itemListObjects = $orderXML->getElementsByTagName('LineItemInfo');
foreach($itemListObjects as $node) {
echo $node->nodeValue; //echos "This is a line item."
echo $node->attributes->getNamedItem('attr1')->nodeValue; //echos "hi"
}
If you had a nested structure, you can follow basically the same procedure using the childNodes property. For example, if you had this:
<LineItemInfo attr1="hi">
<LineItem>Line 1</LineItem>
<LineItem>Line 2</LineItem>
</LineItemInfo>
You might do something like this:
$itemListObjects = $orderXML->getElementsByTagName('LineItemInfo');
foreach($itemListObjects as $node) {
if ($node->hasChildNodes()) {
foreach($node->childNodes as $c) {
echo $c->nodeValue .",";
}
}
}
//you'll get output of "Line 1,Line 2,"
Hope that helps.
EDIT for specific code and XML
I ran the following code in a test script, and it seemed to work for me. Can you be more specific about what's not working? I used your code exactly, except for the first two lines that create the document. Are you using loadXML() over loadHTML()? Are there any errors?
$orderXML = new DOMDocument();
$orderXML->loadXML("
<LineItems>
<LineItemInfo>
<ProductId href='[URL_TO_PRODUCT_XML]'>149593</ProductId>
</LineItemInfo>
<LineItemInfo>
<ProductId href='[URL_TO_PRODUCT_XML]'>149593</ProductId>
</LineItemInfo>
</LineItems>
");
$itemListObject = $orderXML->getElementsByTagName('LineItemInfo');
foreach ($itemListObject as $element) {
$product = $element->getElementsByTagName('ProductId');
$productId = $product->item(0)->nodeValue;
echo $productId.'-';
}
//outputs "149593-149595-"
XML tags tend to be lower-camel-case (or just "camel-case"), i.e. "lineItemInfo", instead of "LineItemInfo" and XML is case-sensitive, so check for that.