PHP XML file filter on match - php

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).

Related

Get xml node full path in Php / SimpleXml

I need the full path of an xml node.
I saw the answer in this question but I wasn't able to use it.
Below the code I used on a php web tester with no success:
$xml = <<<EOF
<root>
<First>
<Martha>Text01</Martha>
<Lucy>Text02</Lucy>
<Bob>
<Jhon>Text03</Jhon>
</Bob>
<Frank>One</Frank>
<Jessy>Two</Jessy>
</First>
<Second>
<Mary>
<Jhon>Text04</Jhon>
<Frank>Text05</Frank>
<Jessy>Text06</Jessy>
</Mary>
</Second>
</root>
EOF;
$MyXml = new SimpleXMLElement($xml);
$Jhons = $MyXml->xpath('//Jhon');
foreach ($Jhons as $Jhon){
echo (string) $Jhon;
//No one of the following works
echo (string) $Jhon->xpath('./node()/path()');
echo (string) $Jhon->xpath('./path()');
echo (string) $Jhon->xpath('.path()');
echo (string) $Jhon->path();
echo '<br/> ';
}
I need: "/root/First/Bob/Jhon" and "/root/Second/Mary/Jhon"
You can use the much more powerful DOM (DOMDocument based in PHP) api to do this...
$MyXml = new SimpleXMLElement($xml);
$Jhons = $MyXml->xpath('//Jhon');
foreach ($Jhons as $Jhon){
$dom = dom_import_simplexml($Jhon);
echo $dom->getNodePath().PHP_EOL;
}
The dom_import_simplexml($Jhon) converts the node and then getNodePath() displays the path...
This gives ( for the example)
/root/First/Bob/Jhon
/root/Second/Mary/Jhon
Or if you just want to stick to SimpleXML, you can use the XPath axes ancestor-or-self to list the current node and each parent node...
$MyXml = new SimpleXMLElement($xml);
$Jhons = $MyXml->xpath('//Jhon');
foreach ($Jhons as $Jhon){
$parent = $Jhon->xpath("ancestor-or-self::*");
foreach ( $parent as $p ) {
echo "/".$p->getName();
}
echo PHP_EOL;
}

Get values from tag from XML using PHP DOMDocument

I have a XML file with the following contents:
<Klassen>
<Klas>
<Klas>HT1</Klas>
<Omschrijving>Klas HT1</Omschrijving>
</Klas>
<Klas>
<Klas>HT2</Klas>
<Omschrijving>Klas HT2</Omschrijving>
</Klas>
</Klassen>
I want to get the values from the second level Klas tag. I used the following PHP script, but it doesn't work;
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load($apiurl);
$hallo = $xmlDoc->getElementsByTagName('Klas');
foreach ($hallo as $book) {
$result = $book->nodeValue;
echo '<option value="'.$result.'">'.$result.'</option>';
}
?>
I can't change the tag names because it's not my API and also the creator of the API won't change it. What can I do to get the values (in this example) HT1 and HT2 into the select box?
Thank you!
Here's a solution for you using DOMXpath:
<?php
$xml = <<<XML
<Klassen>
<Klas>
<Klas>HT1</Klas>
<Omschrijving>Klas HT1</Omschrijving>
</Klas>
<Klas>
<Klas>HT2</Klas>
<Omschrijving>Klas HT2</Omschrijving>
</Klas>
</Klassen>
XML;
$xmlDoc = new DOMDocument();
$xmlDoc->loadXML($xml);
$xpath = new DOMXpath($xmlDoc);
$hallo = $elements = $xpath->query("//Klas/Klas");
foreach ($hallo as $book) {
$result = $book->nodeValue;
echo '<option value="'.$result.'">'.$result.'</option>';
}
Output:
<option value="HT1">HT1</option><option value="HT2">HT2</option>
Here's an online working example.

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

How can i get the value of attribute in of a xml node in php?

I'm using simplexml to read a xml file. So far i'm unable to get the attribute value i'm looking for. this is my code.
if(file_exists($xmlfile)){
$doc = new DOMDocument();
$doc->load($xmlfile);
$usergroup = $doc->getElementsByTagName( "preset" );
foreach($usergroup as $group){
$pname = $group->getElementsByTagName( "name" );
$att = 'code';
$name = $pname->attributes()->$att; //not working
$name = $pname->getAttribute('code'); //not working
if($name==$preset_name){
echo($name);
$group->parentNode->removeChild($group);
}
}
}
and my xml file looks like
<presets>
<preset>
<name code="default">Default</name>
<createdBy>named</createdBy>
<icons>somethignhere</icons>
</preset>
</presets>
Try this :
function getByPattern($pattern, $source)
{
$dom = new DOMDocument();
#$dom->loadHTML($source);
$xpath = new DOMXPath($dom);
$result = $xpath->evaluate($pattern);
return $result;
}
And you may use it like (using XPath) :
$data = getByPattern("/regions/testclass1/presets/preset",$xml);
UPDATE
Code :
<?php
$xmlstr = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><presets><preset><name code=\"default\">Default</name><createdBy>named</createdBy><icons>somethignhere</icons></preset></presets>";
$xml = new SimpleXMLElement($xmlstr);
$result = $xml->xpath("/presets/preset/name");
foreach($result[0]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
?>
Output :
code="default"
P.S. And also try accepting answers as #TJHeuvel mentioned; it's an indication that you respect the community (and the community will be more than happy to help you more, next time...)
Actually question in my head includes deleting a node as well , mistakenly i could not add it. So in my point of view this is the complete answer, i a case if someone else find this useful.
This answer doesn't include SimpleXMLElement class because how hard i tried it didn't delete the node with unset(); . So back to where i was , i finally found an answer. This is my code.
and its Simple!!!
if(file_exists($xmlfile)){
$doc = new DOMDocument();
$doc->load($xmlfile);
$presetgroup = $doc->getElementsByTagName( "preset" );
foreach($presetgroup as $group){
$pname = $group->getElementsByTagName( "name" );
$pcode = $pname->item(0)->getAttribute('code');
if($pcode==$preset_name){
echo($preset_name);
$group->parentNode->removeChild($group);
}
}
}
$doc->save($xmlfile);

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