XML Xpath Usage - php

ornek.xml here :
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book onay="e" katid="31" dil="tr">
<kitapadi>Dear Lovely</kitapadi>
<yazar>Author 1234</yazar>
<isbn>1234513</isbn>
</book>
<book onay="e" katid="32" dil="en">
<kitapadi>Love and Hate</kitapadi>
<yazar>Author 345</yazar>
<isbn>1234513</isbn>
</book>
</library>
PHP Code:
$xml = simplexml_load_file('veri/ornek.xml');
$search= '34';
$result = $xml->xpath('//yazar[contains(.,"'.$search.'")]');
foreach($result as $tt){
echo $tt;
}
If I use this, I can get the yazar attributes. But I want get another attributes
example:
$search = 34 where match yazar 34 giving this block in kitapadi,isbn,yazar

If you like to get the book containing a serach sring in yazar. Use something like this:
$xml = simplexml_load_file('veri/ornek.xml');
$search= "34";
$result = $xml->xpath("//book[yazar[contains(.,' $search')]]");
foreach($result as $tt){
echo $tt->isbn;
}

This XPath query does the trick:
//*[text()[contains(., '34')]]
Result:
Element='<yazar>Author 1234</yazar>'
Element='<isbn>1234513</isbn>'
Element='<yazar>Author 345</yazar>'
Element='<isbn>1234513</isbn>'

Related

Using variables as object reference for XML

Let's say I have a XML file like this one:
<?xml version="1.0" encoding="utf-8"?>
<test>
<foo>
<bar>Hello, World!</bar>
</foo>
</test>
So, if I use something like this I can echo Hello, World!:
<?php
$xml = simplexml_load_file("myxml.xml");
echo $xml->foo->bar;
?>
But, what if I want to refer to bar with a variable?
<?php
$xml = simplexml_load_file("myxml.xml");
$reference = "foo->bar";
echo $xml->$reference;
?>
That won't work. Any solution?
It's because you are trying to access 3rd level in one variable. PHP couldn't handle -> in variable.
$level1 = 'foo';
$level2 = 'bar';
echo $xml->$level1->$level2;
You can't do that because it will look for a property with the literal foo->bar, and not bar inside foo.
You could do it like this:
$xml = simplexml_load_file("myxml.xml");
$reference = "foo->bar";
$tmp = $xml;
foreach(explode('->', $reference) as $v){
$tmp = $tmp->$v;
}
echo $tmp;
Output:
Hello, World!
This would work even if you don't want to go until the last element. Take a look at the following example.
Test with this XML:
<?xml version="1.0" encoding="utf-8"?>
<test>
<foo>
<bar>Hello, World!</bar>
<something>
<values>
<v1>Some value here (1)</v1>
<v2>Some value here (2)</v2>
<v3>Some value here (3)</v3>
<v4>Some value here (4)</v4>
</values>
</something>
</foo>
</test>
Now, change to $reference = "foo->something->values"; and from echo $tmp; to print_r($tmp);. This will be the output:
SimpleXMLElement Object
(
[v1] => Some value here (1)
[v2] => Some value here (2)
[v3] => Some value here (3)
[v4] => Some value here (4)
)
Use Xpath. It allows you to use expressions to fetch parts of an XML.
$xml = <<<'XML'
<?xml version="1.0" encoding="utf-8"?>
<test>
<foo>
<bar>Hello, World!</bar>
</foo>
</test>
XML;
$xml = new SimpleXMLElement($xml);
$expression = 'foo/bar';
var_dump(
(string)$xml->xpath($expression)[0]
);
Xpath is a really powerful tool. However to use the full potential you will have to use DOMXpath::evaluate(). SimpleXMLElement::xpath() can only return node lists as arrays of SimpleXMLElement objects. DOMXpath:evaluate() can return node lists or scalar values.
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$expression = 'string(foo/bar)';
var_dump(
$xpath->evaluate($expression)
);

Getting a specific part from XML

I am trying to get the PAY where it has the ID 3 Where it says the label phone
but i really dont know how, i tried everything.
Thanks for helping!
Here is the XML code:
$books = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<data>
<login>1</login>
<arrStatsData>
<item>
<Id>500</Id>
<Label>website_name</Label>
<Data>
<item>
<Id>4</Id>
<Label>transactions</Label>
<Data>
<sum>2029.34</sum>
<cst>47.67575</cst>
<num>86</num>
<avg>23.6</avg>
<pay>1981.66</pay>
</Data>
</item>
<item>
<Id>3</Id>
<Label>Phone</Label>
<Data>
<sum>205</sum>
<cst>17.353</cst>
<num>205</num>
<avg>1</avg>
<pay>187.647</pay>
</Data>
</item>
......
PHP Code:
$xml = simplexml_load_string($arrResult); //load xml from above
foreach($xml->arrStatsData->item->Data as $item)
{
foreach($item->item as $DATA)
{
echo $DATA->Id.'<br>';
}
My result now is:
1981.66
187.647
-0.4448
Since you know some information that's tell the node apart from the rest you can use XPath to get the value directly instead of iterating through all of them:
<?php
$sxe = new SimpleXMLElement($books);
$pay = $sxe->xpath('//item[./Id=3]/Data/pay');
echo (string) $pay[0];
Ouput:
187.647
Your PHP code would be like this:
$xml = simplexml_load_string($books);
foreach($xml->arrStatsData->item->Data as $item)
{
//echo '$item;';
foreach($item->item as $DATA)
{
if($DATA->Id == '3'){
echo $DATA->Data->pay."<br/>";
}
}
}
It retrieve the pay value when the ID is equals to 3.
Rolando Isidoro was faster to recommend xpath, my solution is slightly different, that's why I post it, too:
$pay = (string)$xml->xpath("//item[Id = '3']/Data/pay")[0];
echo $pay;
see it working: http://codepad.viper-7.com/qzPlmp

Getting specific data from xml -> php?

I want to get to foreach loops from the following xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<players>
<player id="1">4</player>
<player id="2">3</player>
</players>
<chats>
<chat playerid="2">Some chat here...</chat>
<chat playerid="1">skfgjh kjgh fdskgjhdf kgjhdf gkjd gkjdfhg dkfjhg</chat>
</chats>
</data>
I want one foreach with the players and one with the chats, but can't seem to figure this out... I also wants the attributes out and don't know how?
Here is what i have tried:
$userXML = simplexml_load_file('xml_chats/0^0.xml') or die ("error");
foreach($userXML->chats as $nchats){
echo $nchats->chat.'<br>';
}
What am I doing wrong and how can i achive this?
Thanks in advance :-)
You can try using the xpath method to select the nodes of your interest:
$xml = simplexml_load_string($xml);
$chats = $xml->xpath('/data/chats/chat');
$players = $xml->xpath('/data/players/player');
Or you can use the magic mapping of simplexml to nodes like this:
foreach ($xml->players->player as $player) { ... }
foreach ($xml->chats->chat as $chat) { ... }
Try like this
$xml=simplexml_load_file(filename);
foreach($xml->chats as $nchats){
foreach($nchats as $chat)
{
echo $nchats->chat.'<br>';
foreach($chat->attributes() as $key=>$attrib)
{
echo $key."=>".$attrib.'<br>';
}
}
}

How to extract the content of <uri></uri> in a XML document?

I have a document that it's structure is like below.
There are a lot of <entry>. My question is how can I output the <uri> of each entry? And another question, how can I output only the USERNAME?
This is the file I want to get the usernames http://search.twitter.com/search.atom?q=yankees
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:google="http://base.google.com/ns/1.0" xml:lang="en-US" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns="http://www.w3.org/2005/Atom" xmlns:twitter="http://api.twitter.com/" xmlns:georss="http://www.georss.org/georss">
<entry>
<author>
<name></name>
<uri>http://twitter.com/USERNAME</uri>
</author>
</entry>
<?php
$xml = new DOMDocument;
// link to ur file
$xml->load('');
foreach ($xml->getElementsByTagName('entry') as $product )
{
$append = array();
foreach($product->getElementsByTagName('uri') as $name ) {
// Stick $name onto the array
$append[] = $name;
}
}
$result = $xml->saveXML();
print_r(str_replace('http://twitter.com/','',$result));
?>
You can use Xpath queries
http://www.php.net/manual/en/simplexmlelement.xpath.php
or
http://php.net/manual/en/domxpath.query.php
You should use SimpleXML some kind of a loop which goes trough all the s.
(foreach($xml->entry as $entry) loop should work fine, I think.)
And for the second: if it is always http://twitter.com/USERNAME, simply count the prefix's length than use a substr.
Resources to use: substr, SimpleXML, SimpleXML

Parsing an XML with Xpath in PHP

Consider the following code :
$dom = new DOMDocument();
$dom->loadXML($file);
$xmlPath = new DOMXPath($dom);
$arrNodes = $xmlPath->query('*/item');
foreach($arrNodes as $item){
//missing code
}
The $file is an xml and each item has a title and a description.
How can I display them (title and description)?
$file = "<item>
<title>test_title</title>
<desc>test</desc>
</item>";
I suggest using php's simplexml, with that, you still get xpath functionality, but with easier approach, for example you would access attributes like this:
$name = $item['name'];
Here's an example:
xmlfile.xml:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<items>
<item title="Hello World" description="Hellowing the world.." />
<item title="Hello People" description="greeting people.." />
</items>
</xml>
do.php:
<?php
$xml_str = file_get_contents('xmlfile.xml');
$xml = new SimpleXMLElement($xml_str);
$items = $xml->xpath('*/item');
foreach($items as $item) {
echo $item['title'], ': ', $item['description'], "\n";
}
If your item looks like this:
<item>
<title>foo</title>
<description>frob</description>
</item>
You could use getElementsByTagName() and nodeValue:
foreach($arrNodes as $item){
print $item->getElementsByTagName('title')->item(0)->nodeValue;
}
Are title and description attributes? E. g. does an item look like this:
<item title="foo" description="frob" />
If so, you could just use getAttribute():
...
foreach($arrNodes as $item){
print $item->getAttribute('title');
}
The right XPath expression should be:
/*/item/title | /*/item/desc
Or
/*/item/*[self::title or self::desc]
This is evaluate to a node set with title and desc element in document order

Categories