(PHP 4 >= 4.1.0)
DomNode->child_nodes — Returns children of node
Returns all children of the node.
See also domnode_next_sibling(), and domnode_previous_sibling().
to avoid the "#text" what you can simply do without changing your xml file, is:
if($item->nodeName != "#text"){
// do your code.
}
Sometimes unless you know exactly where elements are it can be time consuming to pick each thing up with get_element_by_tagname calls.
I used a quick little function that, given a structure such as:
<customer>
<firstname>Joe</firstname>
<surname>Bloggs</surname>
<age>24</age>
<sex>Male</sex>
...
</customer>
it will return an associative array with the tag names as keys and the content as values. During the load I strip whitespace as well so it isn't confused by \n's creating blank nodes
-- CODE --
$xmldoc = domxml_open_mem($xmlstring,
DOMXML_LOAD_PARSING + //0
DOMXML_LOAD_COMPLETE_ATTRS + //8
DOMXML_LOAD_SUBSTITUTE_ENTITIES + //4
DOMXML_LOAD_DONT_KEEP_BLANKS //16 ));
// get the node root and then the children of it.
$noderoot = $xmldoc->document_element();
$childnodes = $noderoot->child_nodes();
// build the array
foreach ($childnodes as $value) {
echo $value->tagname . " : " . $value->get_content() . "<br>";
$nodeArray[$value->tagname] = $value->get_content();
}
-- END CODE --
You can then return node array or start using it however you like in other functions just like a normal associative array then.
$nodeArray['firstname'] == "Joe"
There were some comments about problems with whitespaces.
you can easily solve them by creating the dom-document as follows:
<?php
$xmlDoc = @domxml_open_mem(
$xmlString
, DOMXML_LOAD_PARSING + //0
DOMXML_LOAD_COMPLETE_ATTRS + //8
DOMXML_LOAD_SUBSTITUTE_ENTITIES + //4
DOMXML_LOAD_DONT_KEEP_BLANKS //16
, $error
);
?>
if you call child_nodes() on eg. the root-element whitespaces are ignored.
Here is a handy little function i started using at work and home quite a bit. It takes in an array of nodes, typically from DomNode->child_nodes() as well as a filter argument and returns an array of filtered out nodes.
If the $filter arg is a string, then the $boolean argument is used. If boolean is true, then only nodes named $filter will be returned. If boolean is false, then only nodes NOT named $filter will be returend.
Additionally, you can specify the filter as an assoc array in the form of $array[$node_name] = true|false and only nodes in the array with a true value are returend. Note that if it is an array, then $boolean is not used. I was planning on having the boolean act as a negation kinda like !in_array(), but it was more for completeness than need so i dropped it.
function get_filtered_children($children_array,$filter,$boolean = true){
$total_children = count($children_array);
for ($i = 0; $i < $total_children; $i++){
$cur_child = $children_array[$i];
$node_name = $cur_child->node_name();
if (is_array($filter)){ //array in the form of [node_name] = true|false
if ($filter[$node_name])
$filtered_children_array[] = $cur_child;
}
else if(is_string($filter)){ //string hopefully...
if ($boolean && $node_name == $filter)
$filtered_children_array[] = $cur_child;
elseif (!$boolean && $node_name != $filter)
$filtered_children_array[] = $cur_child;
}
else
user_error('filter is of type ' . gettype($filter) . '. Please only supply arrays or strings.', E_USER_ERROR);
}
return $filtered_children_array;
}
Blaine Garrett
Web Master of the Art Attack
http://artattack.to
A better way to check for Text Child nodes (PHP 4.3.0)
if ($childnode->node_type() == XML_TEXT_NODE)
{
echo "<br/>This item is a text node.";
}
else
{
echo "<br/>This item is not a text node.";
}
You may want to look at DomElement->is_blank_node() as well.
Loop through children making sure that the children are not text nodes.
<pre>
$moduleDoc = domxml_open_file("main_module_defs.xml");
$moduleDefinitionXPath = xpath_new_context($moduleDoc);
$dConvsNodeSet = xpath_eval($moduleDefinitionXPath, "//modules/module[@name='search']/dConvs");
$children = $dConvsNodeSet->nodeset[0]-> child_nodes();
$dTotal = count($children);
for ($i=0;$i<$dTotal;$i++){
$curNode = $children[$i];
if($curNode->node_name() != "#text"){
echo "This are probably TextNodes..."; }
}
</pre>
--
http://artattack.to
To answer hrosas)at(linuxmail)dot(org.
<node>
<child/>
</node>
<node> has 3 children.
1. whitespace between <node> and <child/>
2. <child/>
3. whitespace between <child/> and </node>
The whitespace is treated like text. To avoid this remove all whitespace.
<node><child/></node>
This can get hard to read, but correct.
But, you can tell some programs to ignore the whitespace, so it remains easy to read.
Jon Sprague
I was using child_nodes and if I have a node like this.
<node>
<child/>
</node>
the node <node> have two children: one the " " spaces that appear as #text on php and <child/>. Is that normal? I think node has just one child <child/>
if no children present, method
returns
FALSE (bool)
you can check the return result like this:
$children = $domNode -> child_nodes();
if (is_bool($children))
print "Sorry, no children present ...";