Rob Richards wrote:
Expected behavior. See comments within code snippet.

D. Dante Lorenso wrote:
I am using XMLWriter with PHP 5.1.4 and find that it doesn't behave as I expect. I am under the impressing that until I call 'endElement', I should be free to continue adding attributes to an opened element regardless of whether I have already added elements or text below it. Look at this sample code:

<?php
//--------------------------------------------------
// create an object to write to an in-memory buffer
$XML = new XMLWriter();
$XML->openMemory();

// start new element and add 1 attribute
$XML->startElement("a");
$XML->writeAttribute("href", "http://www.google.com";);

// add a text node
$XML->text("Google");
Here you just closed the starting element tag and moved into content.

So adding a text node closes the starting tag?  That shouldn't happen.

Seems to me that this is non-intuitive. I would expect that until I call 'endElement' that the node is still constructible. Internally it should work something like DOM where the node is not 'serialized' to xml tag form until the endElement is called. That way, attributes could still be defined even after 'text' nodes were appended.
// add another attribute (DOES NOT WORK)
$XML->writeAttribute("target", "_blank");
If you check the return value (FALSE), you will see it failed.
The writer is positioned within element content so cannot write an attribute. Attributes must be written while still positioned within the element's start tag.

If you look at XML as a tree, despite delving deeper into the tree (adding text node), as I walk back up, I should be positioned back on the element I opened with 'startElement'. Turning the node into a string should not occur until the leaf nodes are closed.

I understand slightly more memory will be consumed the way I define it, but the object would certainly be more useful. In the way I extend XMLWriter, I have a method like this:

<?php
class A extends XMLWriter {
...
//--------------------------------
public function push() {
   $args = func_get_args();

   // create new node
   $this->startElement(array_shift($args));
// we have a text node
   if (count($args) % 2) {
       $this->text(array_pop($args));
   }

   // add attributes
   for ($i = 0; $i < count($args); $i += 2) {
       $this->attr($args[$i], $args[$i +1]);
   }
}

//--------------------------------
...
}
?>

The way this works is as follows:

   * first argument is the tag name
   * last argument (if present and even number of arguments) is the
     text value inside the node
   * middle arguments are attribute = attribute_value pairs of 2

After this node is created, I still want to use $X->attr() to set more attributes.

<?php
$X = new A();
$X->push("a", "href", "http://www.php.net";, "Click Here");
if ($want_new_window) {
   $X->attr("target", "_blank");
}
print $X->to_string();
?>

I have an object like this already written on top of DOM, but found XMLWriter to be more attractive because of better memory utilization. But still, 'endElement' doesn't do what it sounds like it does if the element is closed long before it gets called.

Is it possible to change this behavior?

Dante


--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to