Jump to content

Need help with SimpleXML to check if node has attributes


mpsn

Recommended Posts

Hi, I am new to xml parsing and I just want to know how to check whether a node has attributes:

 

Here is my xml file to use:

=================

<?xml version="1.0" encoding="ISO-8859-1"?>
<email>
<message>
	<to>
		<toFirstName>Tove</toFirstName>
		<toLastName toType="common" style="swag">Smith</toLastName>
	</to>
	<from>
		<fromFirstName>Jani</fromFirstName>
		<fromLastName fromType="unique">Dravison</fromLastName>
	</from>
	<heading>Reminder</heading>
	<body>
		<prologue>Tis the night before Xmas...</prologue>
		<paragraph1>Don't forget me this weekend!</paragraph1>
		<paragraph2>Jump the gun!</paragraph2>
		<epilogue>The end of the world.</epilogue>
	</body>
</message>

<message>
	<to>employees</to>
	<from>CEO</from>
	<heading>Power Lunch</heading>
	<body>
		<prologue></prologue>
		<paragraph1>Year over year data</paragraph1>
		<paragraph2>Downsizing</paragraph2>
		<epilogue>The end.</epilogue>
	</body>
</message>
</email>

 

Here the simple script that I cannot get to work:

==================================

<?php
$simpleXMLObj=simplexml_load_file("email.xml");

if($simpleXMLObj->to[0]->toLastName[0]->attributes()->getName)
print "YES: this node has attributes!";
else
        print "NO:";
?>

 

Please I really need help, it is simple I know but I am new to xml parsing and mixed up. :'(

no, that is not what i am asking, how do i just check if a node has attribrutes, period.

 

This is how i would do it via DOM using the same email.xml file from the first post of this thread:

===================================================================

<?php
$dom=new DOMDocument();
$dom->load("email.xml");

if($dom->getElementsByTagName("to")->item(0)->getElementsByTagName("toLastName")->item(0)->hasAttributes())
print "YES DOM WORKS to check if node has ATTRIBUTES!";
?>

 

So how do i do the equivalent of this checking via SimpleXML?

:rtfm:

if (PHP_VERSION >= "5.3") {
    echo "Use SimpleXMLElement::count. And if you didn't notice, attributes() returns a SimpleXMLElement object.\n";
} else {
    echo "Use [url=http://php.net/count]count[/url]. You can pretend the attributes() returns an array.\n";
}

I am unsure about how to get this to work. Basically this function will parse an XML file passed as parameter, and then it should output whatever appropriate nodes exist (eg: is there attribute node, text node, more child tag nodes). This is a little test program I would like to get working so that I can start my actualy project. My professor said I can only use SimpleXML and DOM to parse XML.

 

this is the code:

===========

/*FOR SimpleXML*/
$simpleXMLobj=simplexml_load_file("email.xml");

/*FOR DOM */
$dom=new DOMDocument();
$dom->load("email.xml");

/*TO ALLOW FOR switching b/t SimpleXML and DOM*/
$simpleXMLandDOM=simplexml_import_dom($dom);

function _xmlToScreen($root) {
foreach($root->children() AS $curNode) {
	//print tag nodes first
	print $root->getName();

	//check if any attribute nodes
	if(count($root->attributes())) {
		foreach($root->attributes() AS $attrName=>$attrValue) {
			print "Attr: $attrName:$attrValue <br />";
		}
	}

	//check if any text-nodes
	if($root->nodeType==XML_TEXT_NODE) {
		print $root->nodeValue."<br />";
	}

	//check if more children nodes
	if($root->hasChildNodes()) {
		_xmlToScreen($dom);
	}
}
}
_xmlToScreen($simpleXMLandDOM);

 

Please I need major help. I greatly appreciate all contributions, thanks.  :'(

I am using PHP 5.3, and I got the count() to count attributes, but that is not my concern now. I am using simplexml_import_dom and set as a variable $simpleXMLandDOM so that I can automatically switch b/t functionalities of SimpleXML and DOM, but I cannot get it to work.

I would appreciate any help!

Ok, now it is giving me an infinte loop. Here is the script below:

<?php
/*FOR SimpleXML*/
$simpleXMLobj=simplexml_load_file("email.xml");

/*FOR DOM */
$dom=new DOMDocument();
$dom->load("email.xml");

/*TO ALLOW FOR switching b/t SimpleXML and DOM*/
$simpleXMLandDOM=simplexml_import_dom($dom);

function xmlToScreen($root) {
foreach($root->children() AS $curNode) {
	//print tag nodes first
	print $root->getName();

	//check if any attribute nodes
	if(count($root->attributes())) {
		foreach($root->attributes() AS $attrName=>$attrValue) {
			print "Attr: $attrName = $attrValue <br />";
		}
	}

	//check if any text-nodes
	if($root->nodeType==XML_TEXT_NODE) {
		print $root->nodeValue."<br />"; //or in SimpleXML: just $root 
	}

	//check if more children nodes
	if($root->children()) {
		foreach($root->children() AS $curNode) {
			xmlToScreen($root);
		}
	}
}
}

xmlToScreen($simpleXMLandDOM);

?>

 

I just want to output each component of node to browser display. Please help!  :'(

Hi, ok now i have a new problem, but first here is the *almost* working script

 

<?php
/*FOR SimpleXML*/
$simpleXMLobj=simplexml_load_file("email.xml");

/*FOR DOM */
$dom=new DOMDocument();
$dom->load("email.xml");

/*TO ALLOW SimpleXML to use DOM's fts*/
$simpleXMLandDOM=simplexml_import_dom($dom);

/*TO ALLOW DOM to use SimpleXML's properties*/
$DOMandSimpleXML=dom_import_simplexml($simpleXMLobj);

function xmlToScreen($root) {
	//print tag node names first
	print "<strong>Tag node name:</strong>".$root->getName()."<br />";

	//check if any attribute nodes via SimpleXML
	if(count($root->attributes())) {
		foreach($root->attributes() AS $attrName=>$attrValue) {
			print "<em><strong>Attr:</strong></em> $attrName = $attrValue <br />";
		}
	}

	//check if any text-nodes via DOM
	if($root->nodeType==XML_TEXT_NODE) {
		print "Text node:".$root->nodeValue."<br />"; //or in SimpleXML: just $root 
	}

	//check if more children nodes
	if($root->children()) {
		foreach($root->children() AS $curNode) {
			xmlToScreen($curNode);
		}
	}
}

xmlToScreen($simpleXMLandDOM);

?>

The problem now is that it DOESN'T output the text-node checking block. The whole reason I am using SimpleXML and DOM is b/c of the limited functionality of SimpleXML such as case in point where I would like check if the current node is a text node or not (eg: $root->nodeType==XML_TEXT_NODE). So please I hope you php experts can help me out! Thanks.

So I figured out how to output textnodes:

<?php
//print text nodes or indicate current tag node's child is tag node too
	if(trim($root)=="")
		$textNodeStatus="NO TEXT NODE b/c has child tag nodes!<br />";		
	else
		$textNodeStatus=$root."<br />";
	print "<strong>TEXT NODE:</strong>".$textNodeStatus;
?>

 

BUT I don't know how to get it to do the same via DOM, you see I am using simplexml_import_dom($dom) so the functionalities of DOM should work, right?

 

This is the block I cannot get to work:

<?php
//print text nodes or indicate current tag node's child is tag node too
	if(trim($root)=="")
		$textNodeStatus="NO TEXT NODE b/c has child tag nodes!<br />";		
	else
		$textNodeStatus=$root."<br />";
	print "<strong>TEXT NODE:</strong>".$textNodeStatus;

?>

 

And here is the complete script once again:

<?php
/*FOR SimpleXML*/
$simpleXMLobj=simplexml_load_file("email.xml");

/*FOR DOM */
$dom=new DOMDocument();
$dom->load("email.xml");

/*TO ALLOW SimpleXML to use DOM's fts*/
$simpleXMLandDOM=simplexml_import_dom($dom);

/*TO ALLOW DOM to use SimpleXML's properties*/
$DOMandSimpleXML=dom_import_simplexml($simpleXMLobj);

function xmlToScreen($root) {
	//print tag node names first
	print "<strong>Tag node name:</strong>".$root->getName()."<br />";

	//check if any attribute nodes via SimpleXML
	if(count($root->attributes())) {
		foreach($root->attributes() AS $attrName=>$attrValue) {
			print "<em><strong>Attr:</strong></em> $attrName = $attrValue <br />";
		}
	}

	//print text nodes or indicate current tag node's child is tag node too
	if(trim($root)=="")
		$textNodeStatus="NO TEXT NODE b/c has child tag nodes!<br />";		
	else
		$textNodeStatus=$root."<br />";
	print "<strong>TEXT NODE:</strong>".$textNodeStatus;
	print "====================<br />";

	//check if any text-nodes via DOM
	if($root->nodeType==XML_TEXT_NODE) {
		print "Text node:".$root->nodeValue."<br />"; //or in SimpleXML: just $root 
	}

	//check if more children nodes
	if($root->children()) {
		foreach($root->children() AS $curNode) {
			xmlToScreen($curNode);
		}
	}
}

xmlToScreen($simpleXMLandDOM);
?>

 

Can't anyone reply to help me, I'd greatly appreciate it. THanks.

 

Btw, please see the email.xml I posted early on for this thread, thanks.

You want to know if there are child nodes, right? You've already figured out how to do that:

//check if more children nodes
if($root->children()) {

If there aren't any children and the trim($root) isn't empty then the $root has text.

 

you see I am using simplexml_import_dom($dom) so the functionalities of DOM should work, right?

No. That's not what simplexml_import_dom() does. All it does is load the document into SimpleXML. As in whoever wrote the SimpleXML extension made it so you could load from a DOMDocument as well as a file or string. Loading something into DOMDocument then using simplexml_import_dom() is the same as going directly into a SimpleXMLElement (though perhaps with different error messages).

Since I was given a warning since this involves same email.xml file, I will continue in this thread EVEN though it does not pertain to SimpleXML.

 

Hi, I am trying to build an XML parser that outputs the nodes (attribute, text, tag/element) to browser screen, but I keep getting an infinite loop:

 

Here is script:

=========

<?php
/*FOR DOM */
$dom=new DOMDocument();
$dom->load("email.xml");

function writeXMLtoScreenViaDOM($dom) {

//print current tag node names 
//	if current tag node has whitespace, go to the next sibling that's
// guaranteed to be a tag node
if(trim($dom->firstChild->nodeName)=="") {
	$dom=$dom->nextSibling;
}
print "ELEMENT NODE:".$dom->nodeName."<br />";

//print the current tag node's text node child if any
if($dom->nodeType==XML_TEXT_NODE) {
	if(trim($dom->nodeValue)=="") 
		print "<strong>TEXT NODE:</strong> has child tag nodes.<br />";
	else 
		print "<strong>TEXT NODE:</strong>".$dom->nodeValue."<br />";	
}
//print any attributes
// NB: later make sure to skip over EMPTY ATTRIBUTE NODE VALUES
if($dom->hasAttributes()) {
	for($i=0;$i<$dom->length;$i++) {
		print "<strong>ATTRIBUTE NODE:</strong>".$dom->attributes->item($i)->nodeValue."<br />";
	}
}

//check if any child tag nodes
if($dom->hasChildNodes()) {
	writeXMLtoScreenViaDOM($dom);
}

}//END FCN writeXMLtoScreenViaDOM

writeXMLtoScreenViaDOM($dom);

?>

 

Please any help greatly appreciated! Thanks.

PS: please see the email.xml in earlier posts and please try to run the script yourself.

**NOTE: this doesn't pertain to SimpleXML, only pure DOM for XML parsing but I was warned in putting same email.xml in a new post so that's why I've attached this question in this thread.

 

I want to test if the <toFirstName> element/tag node's child is a text node, but I get error when I run this in the browser.

 

Please see code:

============

<?php
$dom=new DOMDocument();
$dom->load("email.xml");

$curNode=$dom->getElementsByTagName("toFirstName")->item(0);
if($curNode->hasChildNodes()) {
print "yes";
}
else
print "no";
$curNode=$curNode->childNodes;

if($curNode->nodeType==XML_TEXT_NODE)
print "<toFirstName> has NON-EMPTY text node child";
?>

 

Please look at my email.xml I provided very early on in this thread. I really hope some can help me.

Ok, I found it was b/c I forgot that I need to use the keyword item(index) along with childNodes such as:

 

<?php
$dom=new DOMDocument();
$dom->load("email.xml");
$curNode=$dom->getElementsByTagName("toFirstName")->item(0);
if($curNode->hasChildNodes()) {
print "yes <br />";
}
else
print "no <br />";
$curNode=$curNode->childNodes->item(0);//NB:so needs to be in for loop to set up 
//tmp index for that instance (for that current node in other words)

if(trim($curNode->nodeName)!="")
print "<toFirstName> has NON-EMPTY text node child <br />";

//NB:COUNT how many child nodes $curNode has (which is currently <toFirstName>)
$totChildren=0;
for($i=0;$i<$curNode->length;$i++) {
$totChildren=$totChildren+$i;
}
print "Tot children of toFirstName: $totChildren <br />";

?>

 

Now my problem is: Why does it output 6 children nodes for the element node <toFirstName>??? Please help out anyone, thanks.

So I guess I shouldn't use length so I am using count. So now I want this piece of code to output the total children for the given element node: <to>; it should be 2, but it is not though.

 

Here is the code below:

<?php
$dom=new DOMDocument();
$dom->load("email.xml");

//NB:COUNT how many child nodes $curNode has (which is currently <to>)
$curNode0=$dom->getElementsByTagName("to")->item(0);
$totChildren=0;
if($curNode0->hasChildNodes()) {
for($i=0;$i<count($curNode0);$i++) {
	//NB: DON'T COUNT white space (=>empty text nodes!)
	if($curNode0->nodeType==XML_TEXT_NODE && trim($curNode0->nodeName)!="")
		$totChildren=$totChildren+1;
	if($curNode0->nodeType==XML_ELEMENT_NODE)
		$totChildren=$totChildren+1;
}
}

print "tot children of tag TO:".$totChildren."<br />";
?>

 

Please ignore last post to this thread using length property. I just need help with getting total child nodes of the given tag/element node. PLEASE I need help!!

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.