Parsing xml file using xpath and xquery - php

I have a xml file
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<settings>
<title>Calendar for September</title>
<subTitle>Calendar for September Calendar for September</subTitle>
</settings>
<events date="06-09-2010">
<event id="2">
<title>This is My Second Event</title>
<description>This is My Second Event </description>
</event>
<event id="3"><title>This is My Third Event </title><description>This is My Third Event This is My Third Event This is My Third Event </description></event></events>
</xml>
I am parsing the xml file using
$xml_str = file_get_contents('xmlfile');
$xml = simplexml_load_string($xml_str);
if(!empty($xml))
{
$nodes = $xml->xpath('//xml/events/event[#id="'.$id.'"]');
}
It will give only the title and description of event tag with specified id.How i can get the date

Try
//event[#id="2"]/parent::events/#date
Together with the original XPath:
//event[#id="2"]/parent::events/#date | //event[#id="2"]

Once you've found the <event> element use it as the context node for a new xpath query that fetches the nearest <events> element in the ancestor-axis.
$id = 2;
$xml = simplexml_load_file('xmlfile');
if( !$xml ) {
echo '!xml doc';
}
else if ( !($event=$xml->xpath('events/event[#id="'.$id.'"]')) ) {
echo '!event[id=...';
}
else if ( !($container = $event[0]->xpath('ancestor::events[1]')) ) {
echo '!events parent';
}
else {
echo $container[0]['date'], ' - ', $event[0]->title, "\n";
}

Related

Selecting Attribute and listing Value base on NODE Value using Xpath

How do i get All Attribute Value ID of every node FLOWER?
<Files>
<data id="1">
<Type>Flower</Type>
</data>
<data id="2">
<Type>Flower</Type>
</data>
<data id="3">
<Type>Flower</Type>
</data>
<data id="4">
<Type>Flower</Type>
</data>
</Files>
In mysql case it will be like SELECT id from Files WHERE Type="Flower"
How do i code xpath for this condition?
and List it using SimpleXML within option box.
<select>
<?php
foreach ($type as $id) {
echo '<option value="'.$id.'">'.$id.'</option>';
}
?>
</select>
To get all #id attribute's values try
/Files/data[normalize-space(Type) = 'Flower']/#id
'//data[(./Type/text()="Flower")]/#id'
Your XML is invalid, the closing root element does not match and the Type elements are closed as type. XML is case sensitive.
Xpath works uses location paths and conditions a location path is a hierarchical path to the element from the current context. They return a list of nodes. The list can be filtered using conditions.
SimpleXMLElement objects have a method xpath() to execute an expression in the context of the associated node.
$xml = <<<'XML'
<Files>
<data id="1">
<type>Flower</type>
</data>
<data id="2">
<type>Flower</type>
</data>
<data id="3">
<type>Flower</type>
</data>
<data id="4">
<type>Flower</type>
</data>
</Files>
XML;
$files = new SimpleXMLElement($xml);
$target = new SimpleXMLElement('<select/>');
foreach ($files->xpath('data[type = "Flower"]') as $data) {
echo '.';
$option = $target->addChild('option', $data['id']);
$option['value'] = $data['id'];
}
echo $target->asXml();
You should not create you XML as text. Use an XML Api for it.
DOM is more specific and powerful. For example you can serialize the created DOM as HTML.
$source = new DOMDocument();
$source->loadXml($xml);
$xpath = new DOMXpath($source);
$target = new DOMDocument();
$select = $target->appendChild($target->createElement('select'));
foreach ($xpath->evaluate('/Files/data[type = "Flower"]') as $data) {
$option = $select->appendChild($target->createElement('option'));
$option->setAttribute('value', $data->getAttribute('id'));
$option->appendChild($target->createTextNode($data->getAttribute('id')));
}
echo $target->saveHtml($select);
This is how i used the answer Feel free to use the code if you like.
Thanks!!
<?php
//I have used 2 given answer as example on how i used it. Feel Free to use the code below
$type = $_GET['type'];
if(file_exists("xml/data.xml")) {
$xml = simplexml_load_file('xml/data.xml') or die("Data Missing"); }
<!-- Code Example 1 -->
$ids = $xml->xpath('//data[(./Type/text()="'.$type.'")]/#id');
<!-- Code Example 2 -->
$idx = $xml->xpath('/Files/data[normalize-space(Type) = "'.$type.'"]/#id');
?>
<!-- Example 1 -->
<select>
<?php
//echo $ids[0];
foreach ($ids as $id) {
echo '<option value="'.$id[0].'">'.$id[0].'</option>';
}
?>
</select>
<!-- Example 2 -->
<select>
<?php
//echo $ids[0];
foreach ($idx as $id2) {
echo '<option value="'.$id2[0].'">'.$id2[0].'</option>';
}
?>
</select>
<a href="logout.php">Logout
</a>

Reading data from xml with php

please can anybody help me on how to retrieve data from the xml document below
<?xml version="1.0" encoding="utf-8"?>
<livescore-feed timestamp-created="1279745722">
<item id="afab6479053955afcd07dbe2eb972feb" status= "finished" timestamp-starts= "1278255600">
<teams>
<hosts id="zenspbfc_rus">
<name>Zenit</name>
<fullname>FC Zenit St. Petersburg</fullname>
</hosts>
<guests id="anzmfc_rus">
<name>Anzhi</name>
<fullname>FC Anzhi Makhachkala </fullname>
</guests>
</teams>
<events>
<event type="goal" team="hosts">
<player>Bystrov</player>
<minute>15</minute>
<score>1 - 0</score>
</event>
<event type="yellow_card" team="guests">
<player>Tsorayev</player>
<minute>40</minute>
</event>
</events>
</item>
</livescore-feed>
i have tried the following and i was able to some data, except from the events node, the events contains some nodes event. the problem i have is how to get the event from the events node
$xml = simplexml_load_string($data);
$match_id = $xml->{livescorefullname-feed}->matches->item[$i]['id'];
echo $match_id;
In SimpleXML, you don't specify the root node, because the SimpleXML object ($xml) is the root node.
This loops through each event and outputs the details.
foreach($xml->item->events->event as $event){
echo $event->score;
echo $event->player;
echo $event->attributes()->type;
echo $event->attributes()->team;
}

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

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

PHP: Find XML node and insert child

I have an xml document with the following structure:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<url>www.test.com</url>
</item>
<item>
<id>2</id>
<url>www.test2.com</url>
</item>
</items>
I would like to be able to search for a node value, such as the value of 1 for the id field. Then, once that node is found, select the parent node, which would be < item > and insert a new child within.
I know the concept of using dom document, but not sure how to do it in this instance.
This should be a start:
$dom = new DOMDocument;
$dom->loadXML($input);
$ids = $dom->getElementsByTagName('id');
foreach ($ids as $id) {
if ($id->nodeValue == '1') {
$child = $dom->createElement('tagname');
$child->appendChild($dom->createTextNode('some text'));
$id->parentNode->appendChild($child);
}
}
$xml = $dom->saveXML();
or something close to it.
You can do the same thing in a simpler way. Instead of looking for an <id/> node whose value is 1 then selecting its parent, you can reverse the relation and look for any node which has an <id/> child whose value is 1.
You can do that very easily in XPath, and here's how to do it in SimpleXML:
$items = simplexml_load_string(
'<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<url>www.test.com</url>
</item>
<item>
<id>2</id>
<url>www.test2.com</url>
</item>
</items>'
);
$nodes = $items->xpath('*[id = "1"]');
$nodes[0]->addChild('new', 'value');
echo $items->asXML();

Categories