...

View Full Version : is_array not working on PHP DOM cross SimpleXML



funnymoney
10-12-2009, 10:52 PM
This is some weird thing that happend today.. Dunno why. I'm new to XML so maybe you could teach me better way. I was playing with PHP DOM and SimpleXML to try and create some database PHP. But before database i stumbled upon this problem


<?php
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;

$root = $doc->createElement('book');
$root = $doc->appendChild($root);

$title = $doc->createElement('content');
$title = $root->appendChild($title);

$text = $doc->createTextNode('This is the title 1');
$text = $title->appendChild($text);

$title = $doc->createElement('content');
$title = $root->appendChild($title);

$text = $doc->createTextNode('This is the title 2');
$text = $title->appendChild($text);

$title = $doc->createElement('place');
$title = $root->appendChild($title);


$text = $doc->createTextNode('Our place is here');
$text = $title->appendChild($text);

$string = $doc->saveXML();

$xmldom = simplexml_load_string($string);

if (is_array($xmldom->content)) {
print "bark";
}
else {
print "i am not an array although i do have some storage space inside :?<br>\n";
}
print "i count ". (count($xmldom->content))." members inside<br>\n";

foreach ($xmldom->content as $key => $val) {
print "but my key is missing, weird???-$key-MISSING!! <b>key</b> ".$val."<br>\n";
}

?>

this creation is something like an array, but ain't an array? weird

Fou-Lu
10-13-2009, 01:36 AM
simplexml_load_string returns an object representation of the SimpleXMLElement class. This is not the same as an array, what it is is a collection of other SimpleXMLElements.

However, even though the API doesn't indicate this, reflection reveals that the SimpleXMLElement class is classified as Traversable (Class [ <internal:SimpleXML> <iterateable> class SimpleXMLElement implements Traversable ]). is_array literally works only on array items; however, you can determine if its iterable by checking the type:


if ($xmldom instanceof Traversable)
{
foreach ($xmldom AS $item)....
}


I don't really see a need to do this though, the dom is sufficient, you can retreive the root with the documentElement member, and the children with the childNodes. The childNodes will return a DomNodeList object which is also traversable (once again, not indicated in the API).

funnymoney
10-13-2009, 02:17 AM
this is what i'm trying to do


<?php
error_reporting(E_ALL);
$commentXMLDocument = new DOMDocument('1.0');
$commentXMLDocument->formatOutput = true;

$sql_comment_author = array("mark", "dwayne", "john", "bob");
$sql_comment_text = array("hi i'm mark", "hy i'm dwayne", "hi i'm john", "hy i'm bob");

$root = $commentXMLDocument->createElement('root');
$root = $commentXMLDocument->appendChild($root);

$comments = $commentXMLDocument->createElement("comments");
$comments = $root->appendChild($comments);



if (count($sql_comment_author) > count($sql_comment_text)) {
$count = count($sql_comment_author);
}
else {
$count = count($sql_comment_text);
}
$i = 0;
while ($i < $count) {

if ($i >= count($sql_comment_author)) {
$sql_comment_author[$i] = "n/a";
}
if ($i >= count($sql_comment_text)) {
$sql_comment_text[$i] = "n/a";
}
$comment_xml = $commentXMLDocument->createElement("comment");
$comment_xml = $comments->appendChild($comment_xml);


$comment_xml_author = $commentXMLDocument->createElement("author");
$comment_xml_author = $comment_xml->appendChild($comment_xml_author);

$comment_author_name = $commentXMLDocument->createTextNode($sql_comment_author[$i]);
$comment_author_name = $comment_xml_author->appendChild($comment_author_name);

$comment_xml_author = $commentXMLDocument->createElement("text");
$comment_xml_author = $comment_xml->appendChild($comment_xml_author);

$text = $commentXMLDocument->createTextNode($sql_comment_text[$i]);
$text = $comment_xml_author->appendChild($text);

#$text = $commentXMLDocument->createTextNode("This is the title $i");
#$text = $comment_xml->appendChild($text);

$i++;
}

header("Content-Type: text/xml");
echo $commentXMLDocument->saveXML() . "\n";
#echo $commentXMLDocument->saveXML($comment_xml_author) . "\n";

/*
$string = $commentXMLDocument->saveXML();
$xmldom = simplexml_load_string($string);
print "<pre>";
print_r($xmldom);
*/
?>

now when i comment on ->saveXML and uncomment ->saveXML($comment_xml_author) then i get only last result from while loop, but i need a way to get all results... :\

Fou-Lu
10-13-2009, 03:30 AM
Are you cached? Mine dumps correctly (just a copy/paste from here):


<?xml version="1.0"?>
<root>
<comments>
<comment>
<author>mark</author>
<text>hi i'm mark</text>
</comment>
<comment>
<author>dwayne</author>
<text>hy i'm dwayne</text>
</comment>
<comment>
<author>john</author>
<text>hi i'm john</text>
</comment>
<comment>
<author>n/a</author>
<text>hy i'm bob</text>
</comment>
</comments>
</root>

Fetching the childNodes on the $comments will provide you with a DOMNodeList containing each comment DOMElement.


BTW, I removed one of the authors to get the n/a, but what happens if the n/a is supposed to be associated with the second entry?

funnymoney
10-13-2009, 06:37 AM
Are you cached? Mine dumps correctly (just a copy/paste from here):
you get that dump for this
echo $commentXMLDocument->saveXML() . "\n";
but this code doesn't work


echo $commentXMLDocument->saveXML($comment_xml_author) . "\n";


Fetching the childNodes on the $comments will provide you with a DOMNodeList containing each comment DOMElement.

example maybe?



BTW, I removed one of the authors to get the n/a, but what happens if the n/a is supposed to be associated with the second entry?


if there is no author then n/a goes to author, if there's no text n/a goes to text. at least that is how it's supposed to work :)

Fou-Lu
10-13-2009, 08:49 AM
Sorry, missed the last line you had in that post.
I got how you're doing the n/a, but I what happens if its the second entry that has no author? There is no way to differentiate between the entry being the second thats missing and the last entry, so it will always associate n/a with either the last text or the last author.

$comment_xml_author is a single element, '<text>text here</text>'. You can't iterate it, but you can save it as the individual. Each iteration will overwrite that element.

Are you just looking to get the author's names (judging that from the $comment_xml_author)?


$list = $commentXMLDocument->getElementsByTagName('author');

foreach ($list AS $author)
{
printf("%s\n", $author->nodeValue);
}

funnymoney
10-13-2009, 03:08 PM
Sorry, missed the last line you had in that post.
I got how you're doing the n/a, but I what happens if its the second entry that has no author? There is no way to differentiate between the entry being the second thats missing and the last entry, so it will always associate n/a with either the last text or the last author.

well, yeah, you are right.. i didn't bother much about that because i just needed a quick fix because i accidentally made one array larger so i played with the code to fix it.

now when i look at it a bit better it looks really complicated to solve it. but XML is strict formatted structure.

my example above was ment to teach me on how to create XML elements in PHP DOM to later use SQL to populate information.

so of course comments SQL would contain table comments and fields author and text. With PHP and mysql_query(); i would query comments table and store it in XML file for latter use..


$comment_xml_author is a single element, '<text>text here</text>'. You can't iterate it, but you can save it as the individual. Each iteration will overwrite that element.

Are you just looking to get the author's names (judging that from the $comment_xml_author)?


$list = $commentXMLDocument->getElementsByTagName('author');

foreach ($list AS $author)
{
printf("%s\n", $author->nodeValue);
}


yeah! but that doesn't suit my need either. by the looks of it, i was going the wrong way from the beginning. i did mention above how i tried to create PHP DOM XML object, but i forgot that i will probably never have to use only 'author' tags because, later now when i have XML of (all) comment details i can just use specific XSLT to transform that XML into HTML readable output, and so if i have to use only authors in let's say comments authors search, then i will use XSLT transformation that will show only authors of such comments.

adding stuff like pagination and rest is also part of this job.. wow, i really did get myself into trouble when i thought that i should learn website programming. now i see that there is just so so much more left to learn.. :tired:

Fou-Lu
10-13-2009, 07:08 PM
XML requires a well-formed structure, correctness is considered something different. So this is valid:


<?xml version="1.0"?>
<root>
<comments>
<comment>
<author>Fou-Lu</author>
<text>This is text</text>
</comment>
<comment>
<text>This is an un-authored comment</text>
</comment>
</comments>
</root>

The difference will be if you apply a DTD or schema to control what is required in you're document tree. Generally, the above wouldn't make a lot of sense, but it does allow us to do (if you're structure allows an optional author tag in comment) is to insert N/A later where the author tags do not exist. So that's kinda handy.

DOMDocument is a lot more powerful than SimpleXML, but there is a catch, its not as well... simple as SimpleXML lol. DOMDocument uses... 18 classes I think it is to control each aspect of an xml document, while SimpleXML uses 1. On the plus side, DOMDocument and SimpleXML actually play pretty well together; if you like using the SimpleXMLElement class you can use the simplexml_import_dom function to create a SimpleXMLElement from any DOMNode object, and vice versa (using dom_import_simplexml). So thats very handy. The DOMNode is superclass of every DOM based classes except for Exceptions, Lists, Maps, Notation and XPATH. So essentially, you can take any single element off of you're document tree and convert it into a simpleXMLElement.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum