Load and read elements from this XML in PHP - php

http://pastebin.com/hXuHpcUQ
Is what I have..
How can I load and read the data?
so for each node, I could do something like:
foreach($nodes as $node)
{
echo $node->getElementsByTagName("url") . "<br />";
}
But how should $nodes be defined to grab alle the <node type="link">'s?
This is what I have started out and currently got:
$doc = new DOMDocument();
try
{
$doc = new DOMDocument();
$doc->loadXml(file_get_contents('new.xml'));
}catch(Exception $e)
{
continue;
}
I would like to output the value in <url> inside each <node></node> element

I would use SimpleXML - should be something like.
$xml = simplexml_load_file('new.xml');
foreach ($xml->node as $node) {
echo $node->url;
}
(untested..)

You should read about DOMXPath
Your query will look like (not tested):
$nodes = $xpath_obj->query("//node[type='link']/url");

Related

Extract node information from external URL using query

I want to be able to extract information from specific nodes from an external XML file. I currently have been trying
$contents = file_get_contents('https://experiencehermann.com/post-sitemap.xml');
$dom = new DOMDocument;
$dom -> loadXML($contents);
$finder = new DOMXPath($dom);
$nodes = $finder->query('//loc');
foreach ($nodes as $node) {
echo $node->nodeValue ."</br />";
}
I'm able to use this same technique when I have the XML in the PHP directly but not when pulling from an external source.
Thanks in advance!
As your query is quite simple, you don't even need XPath, you can simply use the getElementsByTagName method on the DOMDocument object:
$dom = new DOMDocument;
$dom->loadXML($contents);
$nodes = $dom->getElementsByTagName('loc');
foreach ($nodes as $node) {
if ($node->nodeName === 'image:loc')
continue;
echo $node->nodeValue ."<br />\n";
}

PHP - Get value from xml file

Using the following xml: http://www.bnr.ro/nbrfxrates.xml
How can I get the EUR value?
Been trying like this ... but no luck.
$xmlDoc = new DOMDocument();
$xmlDoc->load('http://www.bnr.ro/nbrfxrates.xml');
$searchNode = $xmlDoc->getElementsByTagName("Cube");
var_dump($searchNode);
foreach ($searchNode as $searchNode) {
$valueID = $searchNode->getAttribute('Rate');
echo $valueID;
}
Check this
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load('http://www.bnr.ro/nbrfxrates.xml');
foreach ($xmlDoc->getElementsByTagName('Rate') as $searchNode) {
if($searchNode->getAttribute('currency') === 'EUR') {
echo $searchNode->nodeValue;
}
}
?>
First Rate is not an attribute but an element. So you would need another getElementsByTagName('Rate') and loop over it. However the XML uses a default namespace so getElementByTagNameNS('http://www.bnr.ro/xsd', 'Rate') would be the correct way.
An easier way is to use Xpath to fetch the value directly:
$document = new DOMDocument();
$document->load('http://www.bnr.ro/nbrfxrates.xml');
$xpath = new DOMXpath($document);
$xpath->registerNamespace('r', 'http://www.bnr.ro/xsd');
var_dump(
$xpath->evaluate('number(//r:Cube/r:Rate[#currency="EUR"])')
);
Output:
float(4.4961)
Xpath does not have a default namespace, so you have to register your own alias for it (I used r in the example.).
The Xpath expression
fetch any {http://www.bnr.ro/nbrfxrates.xml}Cube
//r:Cube
fetch all {http://www.bnr.ro/nbrfxrates.xml}Rate children
//r:Cube/r:Rate
filter by the currency attribute
//r:Cube/r:Rate[#currency="EUR"]
cast the first found node into a number
number(//r:Cube/r:Rate[#currency="EUR"])
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load('http://www.bnr.ro/nbrfxrates.xml');
foreach($xmlDoc->getElementsByTagName("Rate") as $node)
{
$currency = $node->getAttribute('currency');
if($currency == 'EUR')
{
$value = $node->nodeValue;
}
}
echo 'value for EUR is - '. $value;
?>

Need to show child data on parent id

i'm struggling with Xpath, i have an xml list and i need to get the child data based on the parent id ...
My xml file :
<projecten>
<project id="1">
<titel>Shop 1</titel>
<siteurl>http://test.be</siteurl>
<screenshot>test.jpg</screenshot>
<omschrijving>comment 1</omschrijving>
</project>
<project id="2">
<titel>Shop 2</titel>
<siteurl>http://test2.be</siteurl>
<screenshot>test2.jpg</screenshot>
<omschrijving>comment</omschrijving>
</project>
</projecten>
the code i use to get for example the project 1 data (does not work):
$xmlDoc = new DOMDocument();
$xmlDoc->load(data.xml);
$xpath = new DOMXPath($xmlDoc);
$projectId = '1';
$query = '//projecten/project[#id='.$projectId.']';
$details = $xpath->query($query);
foreach( $details as $detail )
{
echo $detail->titel;
echo $detail->siteurl;
echo $detail->screenshot;
echo $detail->omschrijving;
}
But this does not show anything, if someone can point me out ... thanks
In addition to the solution already given you can also use:
foreach ($xpath->query(sprintf('/projecten/project[#id="%d"]', $id)) as $projectNode) {
echo
$projectNode->getElementsByTagName('titel')->item(0)->nodeValue,
$projectNode->getElementsByTagName('siteurl')->item(0)->nodeValue,
$projectNode->getElementsByTagName('screenshot')->item(0)->nodeValue,
$projectNode->getElementsByTagName('omschrijving')->item(0)->nodeValue;
}
or fetch the DOMText node values directly with Xpath
foreach ($xpath->query(sprintf('/projecten/project[#id="%d"]', $id)) as $projectNode) {
echo
$xpath->evaluate('string(titel)', $projectNode),
$xpath->evaluate('string(siteurl)', $projectNode),
$xpath->evaluate('string(screenshot)', $projectNode),
$xpath->evaluate('string(omschrijving)', $projectNode);
}
or import the node to SimpleXml
foreach ($xpath->query(sprintf('/projecten/project[#id="%d"]', $id)) as $projectNode) {
$detail = simplexml_import_dom($projectNode);
echo
$detail->titel,
$detail->siteurl,
$detail->screenshot,
$detail->omschrijving;
}
or even concatenate all the values directly in the XPath:
$xpath = new DOMXPath($dom);
echo $xpath->evaluate(
sprintf(
'concat(
/projecten/project[#id = %1$d]/titel,
/projecten/project[#id = %1$d]/siteurl,
/projecten/project[#id = %1$d]/screenshot,
/projecten/project[#id = %1$d]/omschrijving
', $id
)
);
Accessing the child nodes as you do:
echo $detail->title;
Is not valid, if you use DOM* functions. This would probably work if you were using SimpleXML.
For DOM* try this:
$dom = new DOMDocument;
$dom->loadXml('<projecten>
<project id="1">
<titel>Shop 1</titel>
<siteurl>http://test.be</siteurl>
<screenshot>test.jpg</screenshot>
<omschrijving>comment 1</omschrijving>
</project>
<project id="2">
<titel>Shop 2</titel>
<siteurl>http://test2.be</siteurl>
<screenshot>test2.jpg</screenshot>
<omschrijving>comment</omschrijving>
</project>
</projecten>
');
$id = 2;
$xpath = new DOMXPath($dom);
foreach ($xpath->query(sprintf('/projecten/project[#id="%s"]', $id)) as $projectNode) {
// repeat this for every needed node
$titleNode = $xpath->query('titel', $projectNode)->item(0);
if ($titleNode instanceof DOMElement) {
echo $titleNode->nodeValue;
}
// or us a loop for all child nodes
foreach ($projectNode->childNodes as $childNode) {
echo $childNode->nodeValue;
}
}

PHP XML file filter on match

I am having a heck of a time getting this working...
What I want to do is filter a xml file by a city (or market in this case).
This is the xml data.
<itemset>
<item>
<id>2171</id>
<market>Vancouver</market>
<url>http://</url></item>
<item>
<id>2172</id>
<market>Toronto</market>
<url>http://</url></item>
<item>
<id>2171</id>
<market>Vancouver</market>
<url>http://</url></item>
This is my code...
<?php
$source = 'get-xml-feed.php.xml';
$xml = new SimpleXMLElement($source);
$result = $xml->xpath('//item/[contains(market, \'Toronto\')]');
while(list( , $node) = each($result)) {
echo '//Item/[contains(Market, \'Toronto\')]',$node,"\n";
}
?>
If I can get this working I would like to access each element, item[0], item[1] base on filtered results.
Thanks
I think this implements what you are looking for using XPath:
<?php
$source = file_get_contents('get-xml-feed.php.xml');
$xml = new SimpleXMLElement($source);
foreach ($xml as $node)
{
$row = simplexml_load_string($node->asXML());
$result = $row->xpath("//item/market[.='Toronto']");
if ($result[0])
{
var_dump($row);
}
}
?>
As another answer mentioned, unless you are wed to the use of XPath it's probably more trouble than it's worth for this application: just load the XML and treat the result as an array.
I propose using simplexml_load_file. The learning curve is less step than using the specific XML objects + XPath. It returns an object in the format you descibe.
Try this and you'll see what I mean:
<?php
$source = 'get-xml-feed.php.xml';
$xml = simplexml_load_file($source);
var_dump($xml);
?>
There is also simplexml_load_string if you just have an XML snippet.
<?php
$source = 'get-xml-feed.php.xml';
//$xml = new SimpleXMLElement($source);
$dom = new DOMDocument();
#$dom->loadHTMLFile($source);
$xml = simplexml_import_dom($dom);
$result = $xml->xpath("//item/market[.='Toronto']/..");
while(list( , $node) = each($result)) {
print_r($node);
}
?>
This will get you the parent nodeset when it contains a node with "Toronto" in it. It returns $node as a simplexml element so you will have to deal with it accordingly (I just printed it as an array).

ignoring nested elements when parsing xml with php

probably a simple question to answer for someone:::
xml:
<foobar>
<foo>i am a foo</foo>
<bar>i am a bar</bar>
<foo>i am a <bar>bar</bar></foo>
</foobar>
In the above, I want to display all elements that are <foo>. When the script gets to the line with the nested < bar > the result is "i am a bar" .. which isn't the result I had hoped for.
Is it not possible to print out the entire contents of that element as it is, so that i see: "i am a <bar>bar</bar>"
php:
$xml = file_get_contents('sample');
$dom = new DOMDocument;
#$dom->loadHTML($xml);
$resources= $dom->getElementsByTagName('foo');
foreach ($resources as $resource){
echo $resource->nodeValue . "\n";
}
After some trolling and trying to do what I needed with SimpleXML, I arrived at the following conclusion. My issue with SimpleXML was where the elements are. If the xml is structured, and the hierarchy is standard ... I have no problem.
If the XML is a web page for example, and the <foo> element is anywhere, SimpleXML doesn't have a good facility like getElementsByTagName to pull out the element wherever it may be....
<?php
$doc = new DOMDocument();
$doc->load('sample');
$element_name = 'foo';
if ($doc->getElementsByTagName($element_name)->length > 0) {
$resources = $doc->getElementsByTagName($element_name);
foreach ($resources as $resource) {
$id = null;
if (!$resource->hasAttribute('id')) {
$resource->setAttribute('id', gen_uuid());
}
$innerHTML = null;
$children = $resource->childNodes;
foreach ($children as $child) {
$tmp_doc = new DOMDocument();
$tmp_doc->appendChild($tmp_doc->importNode($child,true));
$innerHTML .= rtrim($tmp_doc->saveHTML());
}
$resource->nodevalue = $innerHTML;
}
}
echo $doc->saveHTML();
?>
Rather than writing all that code, you might try XPath. That expression would be "//foo", which would get a list of all the elements in the document named "foo".
http://php.net/manual/en/simplexmlelement.xpath.php

Categories