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. :'(

Link to comment
Share on other sites

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:

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.  :'(

Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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!  :'(

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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!!

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.