count number of items in xml with php - php

I have to parse xml files that look like this : http://goo.gl/QQirq
How can I count number of items/records in this xml- by 'item' I mean a 'productItem' element, ie there are 5 items in the example xml. I don't specify the tag name 'productItem' when parsing the xml, so I can't count occurrences of 'productItem'. Here is the code I have:
<?php
$doc = new DOMDocument();
$doc->load("test.xml");
$xpath = new DOMXpath( $doc );
$nodes = $xpath->query( '//*| //#*' );
$nodeNames = array();
foreach( $nodes as $node )
{
$nodeNames = $node->nodeName;
$name=$node->nodeName;
$value=$node->nodeValue;
echo ''.$name.':'.$value.'<br>';
}
?>
How can I count number of items and display them one by one, like this ideally : http://goo.gl/O1FI8 ?

Why don't you use DOMDocument::getElementsByTagName?
//get the number of product items
echo $doc->getElementsByTagName('productitem')->length;
//traverse the collection of productitem
foreach($doc->getElementsByTagName('productitem') as $element){
//$element is a DOMElement
$nodeNames = $element->nodeName;
$name=$element->nodeName;
$value=$element->nodeValue;
echo ''.$name.':'.$value.'<br>';
}
As you want to traverse your document, use XPath is just greedy. Moreover you will instantiate each node of the document even if you only want one or two.
You can use hasChildNodes methode and childNodes attribute to traverse your document
function searchInNode(DOMNode $node){
if(isGoodNode($node)){//if your node is good according to your database
mapTheNode($node);
}
if($node->hasChildNodes()){
foreach($node->childNodes as $nodes){
searchInNode($nodes);
}
}
}
searchInNode($domdocument);

Related

Remove child from XML with PHP DOM

I want to remove first video element (video src=time.mp4) from this xml (filename.xml) and save the xml into filename4.smil :
<?xml version="1.0" encoding="utf-8"?>
<smil>
<stream name="mysq"/>
<playlist name="Default" playOnStream="mysq" repeat="true" scheduled="2010-01-01 01:01:00">
<video src="time.mp4" start="0" length="-1"> </video>
<video src="sample.mp4" start="0" length="-1"> </video>
</playlist>
</smil>
i am using this code, but is not working:
<?php
$doc = new DOMDocument;
$doc->load("filename.xml");
$thedocument = $doc->documentElement;
//this gives you a list of the messages
$list0 = $thedocument->getElementsByTagName('playlist');
$list = $list0->item(0);
$nodeToRemove = null;
foreach ($list as $domElement){
$videos = $domElement->getElementsByTagName( 'video' );
$video = $videos->item(0);
$attrValue = $video->getAttribute('src');
if ($attrValue == 'time.mp4') {
$nodeToRemove = $videos; //will only remember last one- but this is just an example :)
}
}
//Now remove it.
if ($nodeToRemove != null)
$thedocument->removeChild($nodeToRemove);
$doc->save('filename4.smil');
?>
Assuming that there is only 1 playlist item and you want to remove the first video element from that, here are 2 methods.
This one uses getElementsByTagName() as you are in your code, but simple picks the first item from each list and then removes the item (you have to use parentNode to remove the child node).
$playlist = $doc->getElementsByTagName('playlist')->item(0);
$video = $playlist->getElementsByTagName( 'video' )->item(0);
$video->parentNode->removeChild($video);
This version uses XPath, which is more flexible, it looks for the playlist elements with a video element somewhere inside. Again, just taking the first one and removing it...
$xp = new DOMXPath($doc);
$video = $xp->query('//playlist//video')->item(0);
$video->parentNode->removeChild($video);
The problem with
$thedocument->removeChild($nodeToRemove);
is that you are trying to remove a child element from the base document. As this node is nested in the hierarchy, it won't be able to remove it, you need to remove it from it's direct parent.
Using Xpath expressions you can fetch video nodes with a specific src attribute, iterate them and remove them.
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$expression = '/smil/playlist/video[#src="time.mp4"]';
foreach ($xpath->evaluate($expression) as $video) {
$video->parentNode->removeChild($video);
}
var_dump($document->saveXML());
It is possible to fetch nodes by position as well: /smil/playlist/video[1].

How to get id of HTML elements

In PHP, I want to parse a HTML page and obtain the ids of certain elements. I am able to obtain all the elements, but unable to obtain the ids.
$doc = new DOMDocument();
$doc->loadHTML('<html><body><h3 id="h3-elem-id">A</h3></body></html>');
$divs = $doc->getElementsByTagName('h3');
foreach($divs as $n) {
(...)
}
Is there a way to also obtain the id of the element?
Thank you.
If you want the id attribute values, then you need to use getAttribute():
$doc = new DOMDocument();
$doc->loadHTML('<html><body><h3 id="h3-elem-id">A</h3></body></html>');
$divs = $doc->getElementsByTagName('h3');
foreach($divs as $n) {
echo $n->getAttribute('id') . '<br/>';
}

Get just the first item with DOMDocument in PHP

I am using this below code to get the elements that are in special HTML element :
$dom = new DOMDocument();
#$dom->loadHTML($google_html);
$xpath = new DOMXPath($dom);
$tags = $xpath->query('//span[#class="st"]');
foreach ($tags as $tag) {
echo $node_value;
}
Now, the problem is that, the code gives all of the elements that are in one special class, but i just need to get the First item that has that class name.
So i don't need using foreach loops.
How to use that code to get JUST the FIRST item ?
The following will make sure you get just the first one in the DOMNodeList that is returned
$xpath->query('//span[#class="st"][1]');
The following gets the only item in the DOMNodeList
$tags = $xpath->query('//span[#class="st"][1]');
$first = $tags->item(0);
$text = $first->textContent;
See XPath: Select first element with a specific attribute

confused with xpath

I've got this PHP code loading in some html.
$dom = new DOMDocument();
$dom->loadHTML($somehtml);
$xpath = new DOMXPath($dom);
$divContent = $xpath->query('//table[class="defURLP"]');
echo $divContent;
I'm too confused to understand quite what needs to go on here, however my desire would it to be able to populate the variable $divContent to have the html contents of the table with the classname defURLP
It's currently just returning
object(DOMNodeList)#3 (0) { }
You need to retrieve the first item from the DOMNodeList returned by your xpath query, since there may be more than one in the list.
// Queries for tables having class defURLP
$tables = $xpath->query('//table[class="defURLP"]');
// Reference the first one in $divContent
$divContent = $tables->item(0);
// Output its nodeValue
echo $divContent->nodeValue;
Or iterate over the node list with a foreach:
$tables = $xpath->query('//table[class="defURLP"]');
// Iterate over the whole node list in $tables (if it is multiple nodes)
foreach ($tables as $t) {
echo $t->nodeValue;
}

PHP: get attributes value of xml

I have following xml structure:
<stores>
<store>
<name></name>
<address></address>
<custom-attributes>
<custom-attribute attribute-id="country">Deutschland</custom-attribute>
<custom-attribute attribute-id="displayWeb">false</custom-attribute>
</custom-attributes>
</store>
</stores>
how can i get the value of "displayWeb"?
The best solution for this is use PHP DOM, you may either loop trough all stores:
$dom = new DOMDocument();
$dom->loadXML( $yourXML);
// With use of child elements:
$storeNodes = $dom->documentElement->childNodes;
// Or xpath
$xPath = new DOMXPath( $dom);
$storeNodes = $xPath->query( 'store/store');
// Store nodes now contain DOMElements which are equivalent to this array:
// 0 => <store><name></name>....</store>
// 1 => <store><name>Another store not shown in your XML</name>....</store>
Those uses DOMDocument properties and DOMElement attribute childNodes or DOMXPath. Once you have all stores you may iterate trough them with foreach loop and get either all elements and store them into associative array with getElementsByTagName:
foreach( $storeNodes as $node){
// $node should be DOMElement
// of course you can use xPath instead of getAttributesbyTagName, but this is
// more effective
$domAttrs = $node->getAttributesByTagName( 'custom-attribute');
$attributes = array();
foreach( $domAttrs as $domAttr){
$attributes[ $domAttr->getAttribute( 'attribute-id')] = $domAttr->nodeValue;
}
// $attributes = array( 'country' => 'Deutschland', 'displayWeb' => 'false');
}
Or select attribute directly with xPath:
// Inside foreach($storeNodes as $node) loop
$yourAttribute = $xPath->query( "custom-attribute[#attribute-id='displayWeb']", $node)
->item(0)->nodeValue; // Warning will cause fatal error when missing desired tag
Or when you need just one value from whole document you could use (as Kirill Polishchuk suggested):
$yourAttribute = $xPath->query( "stores/store/custom-attributes/custom-attribute[#attribute-id='displayWeb']")
->item(0)->nodeValue; // Warning will cause fatal error when missing desired tag
Carefully study manual to understand what type is returned when and what does which attribute contain.
For example I can parse XML DOM. http://php.net/manual/en/book.dom.php
You can use XPath:
stores/store/custom-attributes/custom-attribute[#attribute-id='displayWeb']
I'd suggest PHP's SimpleXML. That web page has lots of user-supplied examples of use to extract values from the parsed data.

Categories