how to filter XML - php

I'm looking for filtering this xml enter link description here
The best way to filter an xml it is :
-to run all the xml and to affect value in variable
-after that we rewrite this xml with this variable
is there any other method?
For this method i've used the dom like this:
$flux= new DOMDocument();
if ($flux->load('http://xml.weather.com/weather/local/FRXX0076?unit=m&hbhf=6&ut=C'))
{$loc=$flux->getElementsByTagName('t');
foreach($loc as $lo)
echo $lo->firstChild->nodeValue . "<br />";
}
in this code i've tried to display <t> but there are 2 balise <t> in <hour> , therefore i've two value of <t> instead the first child of <hour>

The brief answer:
$flux= new DOMDocument();
if ($flux->load('http://xml.weather.com/weather/local/FRXX0076?unit=m&hbhf=6&ut=C'))
{
$xpath = new DomXPath($flux);
$elements = $xpath->query("*/hour/t[1]");
if (!is_null($elements)) {
foreach ($elements as $element)
{
echo "<br/>[". $element->nodeName. "]";
$nodes = $element->childNodes;
foreach ($nodes as $node)
{
echo $node->nodeValue. "\n";
}
}
}
}
I think you should know where to go from this point :)
More advanced version will be to issue XPath query on all hour elements ("*/hour") and then in foreach for each hour element issue another xpath query in this element context ($xpath->query("*/t[1]", $hourElement);). This way you'll also have access to hour object and can for example display this hour.
UPDATE
Simpler version of foreach:
if (!is_null($elements)) {
foreach ($elements as $element)
{
echo "<br/>".$element->nodeValue;
}
}

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";
}

How to get an exact value from a website using php DOM and save it in a database?

I want to get the span id "CPH1_lblCurrent" from the url and save it in the database.
here is the code that i tried by seeing some examples.
<?php
$file = $DOCUMENT_ROOT. "http://www.mypetrolprice.com/2/Petrol-price-in-Delhi";
$doc = new DOMDocument();
$doc->loadHTMLFile($file);
$xpath = new DOMXpath($doc);
$elements = $xpath->query('//span[#id="CPH1_lblCurrent"]');
if (!is_null($elements)) {
foreach ($elements as $element) {
$nodes = $element->childNodes;
foreach ($nodes as $node) {
echo $node->nodeValue. "\n";
}
}
}
?>
This shows me the following.
Current Delhi Petrol Price = 67.12 Rs/Ltr
but i want only the value 67.12.
Can somebody help me.
try to use this simple regex for getting nubmer
.*= ([\d.]+) .*
preg_match

How to get a list of all html elements in PHP?

According to the documentation for DOMDocument::getElementsByTagName, I can call the function with "*" argument, and get a list of all HTML elements from some HTML code.
However, with the following code:
<?php
$dom = new DOMDocument();
$dom->loadHTML("<html><body><div>hello</div><div>bye</div></body></html>");
$nodes = $dom->getElementsByTagName("*");
foreach ($nodes as $node) {
$new_text= new DOMText($node->textContent."MODIFIED");
$node->removeChild($node->firstChild);
$node->appendChild($new_text);
}
$content = $dom->saveHTML();
echo $content;
?>
I get a list of only one element, and the result of execution of the code above is:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>hellobyeMODIFIED</html>
while I would expect something like this:
<html><body><div>helloMODIFIED</div><div>byeMODIFIED</div></body></html>
Shouldn't DOMDocument::getElementsByTagName method return a list of as many HTML elements as available in the HTML code?
Note: I need to create DOMText instances explicitly, because I need this to work in PHP 5.4. DOMNode::textContent is accessible for writing only from PHP 5.6
The DOMDocument::getElementsByTagName method actually returns all the tags, if the first argument is '*'. But your code replaces <body> tag (including all child nodes) with a text node at the first iteration.
Iterate the nodes, and modify only the nodes with nodeType property equal to XML_TEXT_NODE:
$nodes = $dom->getElementsByTagName('*');
foreach ($nodes as $node) {
for ($child = $node->firstChild; $child; $child = $child->nextSibling) {
if (! ($child->nodeType === XML_TEXT_NODE && trim($child->textContent))) {
continue;
}
// The textContent is writable since PHP 5.6.1
if (PHP_VERSION_ID >= 50601) {
$child->textContent .= 'MODIFIED';
continue;
}
// For older versions, create DOMText explicitly
$text = new DOMText($child->textContent . 'MODIFIED');
try {
if ($child->parentNode->replaceChild($text, $child))
$child = $text;
} catch (Exception $e) {
trigger_error("Failed to modify text '$child->textContent': "
. $e->getMessage(), E_USER_WARNING);
}
}
}
echo $dom->saveHTML();
Note, for PHP versions 5.6.1 and newer, you don't need to create DOMText instances explicitly, since the DOMNode::textContent property is accessible for read and write. So you can simply modify the text by assigning a string value to this property. Only make sure that the node has no child nodes other than XML_TEXT_NODE.
The code above checks if trim($child->textContent) is not empty, because the document may contain extra space characters (including newline), e.g.:
<div><!-- newline/spaces -->
<span>text</span><!-- newline/spaces -->
</div><!-- newline/spaces -->
This function 'DOMDocument::getElementsByTagName' returns a new instance of class DOMNodeList containing all the elements.
And it works fine:
<?php
$dom = new DOMDocument();
$dom->loadHTML("<html><body><div>hello</div><div>bye</div></body></html>");
$nodes = $dom->getElementsByTagName("*");
foreach ($nodes as $node) {
echo $node->tagName."<br />";
}
?>
it output all tags of your document.
Probably you need smth like:
<?php
$dom = new DOMDocument();
$dom->loadHTML("<html><body><div>hello</div><div>bye</div></body></html>");
$nodes = $dom->getElementsByTagName("*");
foreach ($nodes as $node) {
if ($node->tagName=='div'){
$node->nodeValue .= "new content";
}
}
$content = $dom->saveHTML();
echo htmlspecialchars($content);
?>
Try this:-
foreach($dom->getElementsByTagName('*') as $element ){
}

Load and read elements from this XML in 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");

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