Extract XML Elements With PHP - php

I wonder whether someone can help me please.
I have the following xml file which I need to pull the values from two of the file attributes, to be more precise, 'userid' and 'locationid' for each 'file name'. Ultimately these values will be used to determine which folders and files the user will be presented with on page load.
<?xml version="1.0" encoding="utf-8" ?>
- <files>
<file name="Test 1/Test Pic 2.jpg" source="Test_Pic_2.jpg" size="728573" originalname="Test Pic 2.jpg" thumbnail="Test_Pic_2.jpg" userid="1" locationid="1" description="No description provided" folder="Test_1" />
<file name="Test 1/stags-snow_1544533c.jpg" source="stags-snow_1544533c.jpg" size="21341" originalname="stags-snow_1544533c.jpg" thumbnail="stags-snow_1544533c.jpg" userid="1" locationid="1" description="Deer head." folder="Test_1" />
</files>
I must admit not not knowing a great deal about how to get this information, but after some searching I found a tutorial online, which I've adapted and have added below.
<?php
if( ! $xml = simplexml_load_file('UploadedFiles/files.xml') )
{
echo 'unable to load XML file';
}
else
{
foreach( $xml as $files )
{
echo 'userid: '.$file_name->userid.'<br />';
echo 'locationid: '.$file_name->locationid.'<br />';
}
}
?>
The problem I'm having is that when I run this, I just get the following results:
userid:
locationid:
userid:
locationid:
userid:
locationid:
The number of rows corresponds with the number of records but what I was wanting to get is the value of the field as well.
I just wondered whether someone could perhaps take a look at this and let me know where I'm going wrong.
Many thanks

Four basic things to remember about SimpleXML:
element access with properties: $elem->childname
attribute access with subscripting: $elem['attribname']
text content with casting: (string) $elem
xpath with $elem->xpath('')
You are using element access (->userid) when you should be using subscripting ['userid'], because userid is an attribute.

I think you require something like this. (An example found at http://php.net/manual/en/simplexmlelement.attributes.php )
<?php
$string = <<<XML
<a>
<foo name="one" game="lonely">1</foo>
</a>
XML;
$xml = simplexml_load_string($string);
foreach($xml->foo[0]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
?>
Hope this helps and if not please post back.

$file_name is undefined in your script assuming that's the whole PHP script you have.
You probably need to use $files->userid and $files->locationid

Related

Php delete element in xml

I'm trying to use php to delete an xml element but it doesn't work. I tried some different code but no one works. I would also like to use cookies to get element in the future. Can you suggest me what I have to do ? I'm not expert and for this I'm in difficulty.
Here the code:
<?php
$dom = new DOMDocument();
$dom->load("Dati.xml");
$matchingElements = $dom->getElementsByTagName("Matematica");
$totalMatches = $matchingElements->length;
$elementsToDelete = array();
$elementsToDelete[] = $matchingElements->item(0);
foreach ( $elementsToDelete as $elementToDelete ) {
$elementToDelete->parentNode->removeChild($elementToDelete);
}
$dom->save($xmlFileToLoad);
echo "<script type='text/javascript'>";
echo "window.close();";
echo "</script>";
echo "Puoi chiudere questa pagina";
?>
Here the xml:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<Informatica>
<nome>aaaa</nome>
<classe>3C</classe>
<titolo>Informatica</titolo>
<materia>Informatica</materia>
<ISBN>123456789101112</ISBN>
<prezzo>12</prezzo>
<autori>tizio</autori>
<contatto>nanni-lombardo1#hotmail.it</contatto>
<codice>123456</codice>
</Informatica>
<Matematica>
<nome>bbb</nome>
<classe>3C</classe>
<titolo>math</titolo>
<materia>Matematica</materia>
<ISBN>123456789101112</ISBN>
<prezzo>12</prezzo>
<autori>tizio</autori>
<contatto>nanni-lombardo1#hotmail.it</contatto>
<codice>123456</codice>
</Matematica>
</document>
Please be sure to :
Remove the space before your XML start tag
Define your $xmlFileToLoad variable
Make your destination XML writable (see Chmod & permissions)
My test file works fine : https://eu.andredasilva.fr/testandre/test.php (source code : https://eu.andredasilva.fr/testandre/test.php.source)
Base XML : https://eu.andredasilva.fr/testandre/Dati.xml
Result XML : https://eu.andredasilva.fr/testandre/test.xml

I need to extract a value of the result of xml generated by http query

I could really do with some help with this one, it's driving me mad!
I need to extract the value from an xml file that is generated by an http query...
I will explain...
I need to add a variable to this line:
http://ws.audioscrobbler.com/2.0/?method=artist.search&artist=ADD_ARTIST_HERE&api_key=b25b959554ed76058ac220b7b2e0a026
Which I can do with some variable editing in php
This will generate an xml file which looks like this:
<lfm status="ok">
<results for="rihanna">
<opensearch:Query role="request" searchTerms="rihanna" startPage="1"/>
<opensearch:totalResults>3821</opensearch:totalResults>
<opensearch:startIndex>0</opensearch:startIndex>
<opensearch:itemsPerPage>30</opensearch:itemsPerPage>
<artistmatches><artist><name>Rihanna</name>
<listeners>3236233</listeners>
<mbid>73e5e69d-3554-40d8-8516-00cb38737a1c</mbid>
<url>http://www.last.fm/music/Rihanna</url>
<streamable>1</streamable>
<image size="small">http://userserve-ak.last.fm/serve/34/71057304.png</image>
<image size="medium">http://userserve-ak.last.fm/serve/64/71057304.png</image>
<image size="large">http://userserve-ak.last.fm/serve/126/71057304.png</image>
<image size="extralarge">http://userserve-ak.last.fm/serve/252/71057304.png</image>
And so the file goes on...
From this xml output generated from my original query, I need to extract the URL in <image size="medium" and put it into another variable...
Sorry for a basic question (or what may be a long answer) but I really don't know how to go about this one at all...
Thank you in advance for any help you may be able to provide me with.
You can have a look at the XPATH function in php to reach that particular image link... the php docs are sufficient to help you out...
Assuming you have the XML string in $str:
$xmlObj = simplexml_load_string($str);
foreach($xmlObj->results as $result)
{
foreach($result->artistmatches->artist as $artist)
{
foreach($artist->image as $image)
{
if($image->attributes()->size == 'medium')
{
echo 'size medium: ' . (string)$image;
}
}
}
}
Instead of loading the string you could grab the XML directly from the URL with simplexml_load_file().
I use the Last.fm feed for an app I made and to get the images I used:
$imagexml = simplexml_load_file($imageurl) or $error = "Feed Not Loading";
$album = $imagexml->album;
$image = (string) $album->image[2];
$imageurl being the url for Last.FM and the $image will give you the url of that image

Selecting xml elements with the same name with simple_load_xml in PHP

I have a XML (simplified) like this:
<article>
<title>My Article</title>
<image src="someurl.jpg" />
<image src="someotherurl.jpg" />
</article>
How do I select the <image> elements? They have the same name. To select the <title> i simply do this:
$xml = simplexml_load_file( "theurltomyxml.xml" );
$article = $xml->article;
$title = $article->title;
But how do I get the images? They have the same name! Just writing $article->image won't work.
I know this is an older question/answer but I had a similar issue and solved it by using the second solution by ajreal with a few adjustments of my own. I had a series of top level nodes (the xml was not formatted properly and didn't split the elements into parent nodes - out of my control). So I used a for loop that counts the elements then used ajreal's solution to echo back the contents I wanted with the iteration of $i.
My use was a bit different than above so I've tried to change it to make it more relevant to your images issue. Anyone please let me know if I made a mistake.
$campaigns = $xml->children();
for($i=0;$i<=$campaigns->count();$i++){
echo $campaigns[$i]->article->title . $campaigns[$i]->article->image[0];
}
You can do this :-
foreach ($xml->xpath("/article/image") as $img)
{
...
}
Or (is list of image node, so normal way of access array is workable)
$xml->image[0];
$xml->image[1];

How can I extract data from XML to PHP using SimpleXML and echo?

I've successfully integrated the LinkedIn API with my website, but I'm struggling to extract information from the XML. At the moment I'm just trying to print it out so I can proceed to use the user's information once they have logged in and given permission.
Below is the format of the XML, and further down is the code I am using to extract the information. The "first name", "last name" and "headline" calls work perfectly, but where an element has sub-headings, nothing is printed out. I've tried using
echo 'Positions: ' . $xml->{'positions:(title)'};
but it doesn't work.
Here is the XML:
<person>
<id>
<first-name />
<last-name />
<headline>
<location>
<name>
<country>
<code>
</country>
</location>
<industry>
<summary/>
<positions total="">
<position>
<id>
<title>
<summary>
<start-date>
<year>
<month>
</start-date>
<is-current>
<company>
<name>
</company>
</position>
</person>
This is the code I've been using to try to extract the information. I know I have to include the sub-heading somehow but I just don't know how!
echo 'First Name: ' . $xml->{'first-name'};
echo '<br/>';
echo 'Last Name: ' . $xml->{'last-name'};
echo '<br/>';
echo 'Headline: ' . $xml->{'headline'};
echo '<br/>';
echo 'Positions: ' . $xml->{'positions'};
Any help would be greatly appreciated, thanks for reading!
Using SimpleXML, you'd access the LinkedIn XML data properties as follows:
Anything with a dash in the property gets {}, so first-name becomes:
$xml->{'first-name'}
Anything without a dash such as headline, is referenced like:
$xml->headline
Anything that is a collection, such as positions, is referenced like:
foreach($xml-positions as $position) {
echo $position->title;
echo $position->{'is-current'};
}
Your XML is not valid, its not well formed. Anyway here's a sample XML and how to use it.
$v = <<<ABC
<vitrine>
<canal>Hotwords</canal>
<product id="0">
<descricao>MP3 Apple iPod Class...</descricao>
<loja>ApetreXo.com</loja>
<preco>à vista R$765,22</preco>
<urlImagem>http://im</urlImagem>
<urlProduto>http://</urlProduto>
</product>
</vitrine>
ABC;
$xml = simplexml_load_string($v);
foreach ($xml->product as $c){
echo $c->loja; //echoing out value of 'loja'
}
Try to use PHP's XML Parser instead:
http://www.php.net/manual/en/function.xml-parse.php
Tried Paul's answer above for:
foreach($xml-positions as $position) {
echo $position->title;
echo $position->{'is-current'};
}
didn't work for me - so I used this - not as elegant but works
for($position_num = 0; $position_num < 10;$position_num++){
echo $xml->positions->position[$position_num]->company->name;
}
Your XML is not well-formed... there are several elements without close tags. So we have no way to know for sure the structure of your XML. (You can't do that in XML like you can in HTML.)
That being said, assuming that <person> is the context node, you can probably get the content of the <title> element using an XPath expression, as in
$xml->xpath('positions/position/title');
I'm assuming $xml is a SimpleXMLElement object.

PHP SimpleXML XPath contains() to find other elements referenced by this element

I'm being given XML in the following format, and am parsing it with PHP's SimpleXML.
<?xml version="1.0" encoding="UTF-8"?>
<ManageMyBooking>
<BookingInfo>
<PartyDetails>
<Passenger>
<PaxNo>1</PaxNo>
<Title>Mrs</Title>
<Surname>Murphy</Surname>
</Passenger>
<Passenger>
<PaxNo>2</PaxNo>
<Title>Mr</Title>
<Surname>Murphy</Surname>
</Passenger>
<Passenger>
<PaxNo>3</PaxNo>
<Title>Miss</Title>
<Surname>Murphy</Surname>
</Passenger>
</PartyDetails>
<Accommodation>
<Units>
<Unit>
<UnitNo>1</UnitNo>
<UnitDesc>...</UnitDesc>
<PaxAssociated>1|2</PaxAssociated>
</Unit>
<Unit>
<UnitNo>2</UnitNo>
<UnitDesc>...</UnitDesc>
<PaxAssociated>3</PaxAssociated>
</Unit>
</Units>
</Accommodation>
</BookingInfo>
</ManageMyBooking>
I'm looping through the Units (Rooms) thus:
// $Accommodation is a SimpleXML Object defined earlier, and able to provide relevant info
<? foreach ($Accommodation->Units as $Units) {
foreach ($Units->Unit as $Unit) {
// (room/unit details echoed out here)
foreach ($Unit->xpath('//Passenger[contains(PaxAssociated,./PaxNo)]') as $RoomPax) { ?>
<?= $RoomPax->Title $RoomPax->Surname" ?><br />
<?= "$RoomPax->Title $RoomPax->Surname" ?><br />
<? }
}
} ?>
in an attempt to show the names off the Passengers (Pax) in each room.
But this xpath finds no-one, and the following gets everyone.
//Passenger[contains(PaxNo,./PaxAssociated)]
What's especially frustrating is that I've successfully used XPath elsewhere in the same PHP for a very similar purpose, with no problems.
Any help/advice/suggestions will be much appreciated.
Edit:
for completeness, and to answer a question from multiple people:
The following works elsewhere in the code, (though not 100% correctly given the possible matching on '22' vs '2'.
//Flight[contains(PaxAssociated,./PaxNo)]
This:
//Passenger[contains(PaxNo,./PaxAssociated)]
is: Find any <Passenger> with a child <PaxNo> who's value contains the value of the child <PaxAssociated>. It would only work with such a data structure (which you clearly don't have):
<ManageMyBooking>
<BookingInfo>
<PartyDetails>
<Passenger>
<PaxNo>1|2</PaxNo> <!-- note the exchanged value! -->
<PaxAssociated>1</PaxAssociated>
</Passenger>
</PartyDetails>
</BookingInfo>
</ManageMyBooking>
So this is wrong on multiple accounts. What you mean is probably a dynamic XPath expression, like this:
foreach ($Units->Unit as $Unit) {
$XPath = "//Passenger[contains('". $Unit->PaxAssociated . "', PaxNo)]";
foreach ($Unit->xpath($XPath) as $RoomPax) {
// ...
}
}
This works on first glance, but it is not fail-safe, because "22" contains "2" as well. So doing a contains() alone won't get you anywhere. Correct would be:
$XPath = "//Passenger[contains('|". $Unit->PaxAssociated ."|', concat('|', PaxNo, '|'))]";
This way you check "|22|" against "|2|", which would return false.

Categories