Copy link to clipboard
Copied
Why is the XML.toString method inconsistant?
var xml:XML = new XML( "<root/>" );
var xml_withtext:XML = new XML( "<root>a</root>" );
var xml_withchild:XML = new XML( "<root><child/></root>" );
trace(xml.toString()); //traces "" (blank)
trace(xml_withtext.toString()); //traces "a"
trace(xml_withchild.toString()); //traces "<root><child/></root>"
If the XML contains only a root node, toString prints nothing. When it contains text, it prints the text. That would make sense if toString was printing only the contents of the root node, but if the root node contains a child, it doesn't print "<child/>" as one would expect. Instead, it suddenly includes the root node as well in the string. That is inconsistant/unexpected. For some reason, there is also a separate toXMLString method that consistantly prints the entire XML structure. Was that some kind of patch since toString doesn't work in a consistant manner, instead opting to sometimes include the root node depending on whether it contains simple or complex content?
Copy link to clipboard
Copied
It works as promised: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/XML.html#toString()
The convenience of toString() returning particular node content becomes apparent when XML is parsed iteratively. Each node is an XML on its own merits. In other words node's children can be either XML or a simple content - toString() reflects this duality.
Copy link to clipboard
Copied
I understand how it works, already read the documentation, but as I stated it doesn't make sense for it return something different based on whether the node has "simple or complex" content.
XML is already a string, so a common method like "toString" when applied to string data should return the string. Instead, the rather universal toString method returns something unintuitive, sometimes including the node's tag and sometimes not, depending on whether the node has child elements and whether those elements are text or another XML node.
I just think that the obviously special and exceptional functionality should have got the special name (e.g. toContentString) rather than having toString return something other than the xml string itself and instead adding a toXMLString method that actually just returns the existing string. It's just strange, IMO.
Bottom line is, XML is a string, and most people would think that calling toString on an XML node would return the XML string, not "a blank string unless it contains child nodes, then it returns not the child node but suddenly the entire node".
Copy link to clipboard
Copied
1. It is what it is. Not all conventions are intuitive and we all know that there may be hundreds of reasons/dependencies why more descriptive or intuitive conventions are not chosen. We just have to deal with it.
2.
XML is already a string, so a common method like "toString" when applied to string data should return the string.
Strictly speaking, initial XML is not a String but an abstract text. It becomes/cast to String datatype when it is interpreted by consuming application IF this application has datatype String and when application's capacity to translate text into String is invoked. Before then XML is meaningless.
If content of file loaded or string written has a character positioning pattern that meets requirements of XML conventions (which is just an idea) - it is defined as something that can be named/interpreted as XML. One very well can name file with tags something different than XML - for example HTML or just text.
AS3 XML object is not a String - it is datatype XML.
3.
Instead, the rather universal toString method returns something unintuitive, sometimes including the node's tag and sometimes not, depending on whether the node has child elements and whether those elements are text or another XML node.
a. There is no universal toString() method that does everything exactly the same with all datatypes and contexts. In the instance of XML class, it is obvious that for one reason or another it was found optimal to override Object.toString() to accommodate particular logic.
This brings me back to the point 1 - since toString() is overridden - it is plain efficient not to create another API entity.
b. All XML elements are children of the corresponding parent elements no matter their structure. From this perspective there is no any ambiguity in XML.toString() implementation. I personally like it like that because XML structure and individual element meaning is fluid and unpredictable. Thus - toString() offers a bridge from an abstract idea of XML element child to particular implementation.
4.
... then it returns not the child node but suddenly the entire node".
toString() is not returning AS3 XML object but just an AS3 (ECMA) String. This means that value obtained via calling XML.toString() looses all XML object related functionality. In some cases this can be a very desirable outcome.
In other words toString() does not return XML at all but an un-interpreted representation that is cast to String.
It is worth mentioning again that toString() returns specific to AS3 String datatype. This special datatype may have nothing in common with the programmatic concept of string. In other languages datatype string can be a totally different animal.
5.
Bottom line is, XML is a string, and most people would think that calling toString on an XML node would return the XML string, not "a blank string unless it contains child nodes, then it returns not the child node but suddenly the entire node".
Again, XML is not a string until application says so and XML in AS3 is not a String but a special object.
Copy link to clipboard
Copied
Andrei1:
1. No, it's not what it is. No, there aren't hundreds of reasons/dependencies why more descriptive or intuitive conventions are not chosen. In this case, the reason (singular) is spelled out in the E4X spec, and it basically boils down to them naively thinking it would be easier for programmers if the node would just magically return text if that's all it contains. In other words, they thought it would be simpler for a node to run specialized arbitrary logic to decide what to return, than it would for a programmer to explicitly select what they want by typing ".text". I see no reason why XML.toString should return anything other than the underlying/original string of characters that originally represented the node in the first place. If programmers wanted the child text of a node, they should call a method like "getTextContent". Since an original, unaltered string of XML character had to exist in the first place in order to instantiate an XML object, anything that creates a new string based on arbitrary logic, for whatever reason, has no business existing within the toString method. For classes that represent data that is not fundamentally a string, any string representation is by definition arbitrary and in that case they can override the universal (i.e. a member of every base Object) toString method. But for classes that represent strings, toString should return the string they represent, unaltered.
2. An AS3 XML object IS an XML-type object, but the AS3 XML class is actually instantiated from String-type data or from bytes that represent encoded String data (i.e. sequences of known characters), because XML is very strictly and fundamentally a "markup language" which is essentially a format of a string of characters. Its rules are based around characters, exact unicode character classes, and a logical ordering of those characters. XML is logically and fundamentally the kind of data that a String class represents, text, so its converstion to a String instance should be straightforward. As a string, a "toString" method for a node should return the original string representation of that node from the first character that is part of that XML node to the last character that is part of that node. XML may contain data the represents anything, but XML itself is a string of characters. Period.
3. There is a universal string method called toString and it's a member of the most basic class "Object" which all other classes inherit from. Although the technical details are different in different object-oriented langauges, they all tend to have a method like that, whether we're talking about AS3, C#, Java, or JavaScript. Calling toString on a String returns the string itself. Calling toString on a class that represents a string, should return the string it represents; not some arbitrary tranformation of that string. Calling toString on a class that doesn't represent a string, has no default string representation to return, and therefore any string returned is by definition arbitrary.
4.
In other words toString() does not return XML at all but an un-interpreted representation that is cast to String
That's precisely what it DOESN'T do. Instead of returning the original, un-interpretted representation of the string FROM WHICH THE NODE WAS CONSTRUCTED, it returns some arbitrarily interpretted represention. It decides whether the XML string is interpretted as complex or simple content, and then it arbitrarily decides to include or not include the outermost tags representing the XML of that node. The fact remains, the string representation PRECEDES the existance of the XML instance, so toString should not be performing arbitrary logic to construct a brand new string.
In other languages datatype string can be a totally different animal.
No, actually a string always refers to a secquence of characters. Each of those character may contain one or more bytes, they may be contiguous in memory or not, they may be represented by arrays, linked lists, doubly-linked lists, etc. but their logical data is always a sequence of characters. That is the same in every programming language, and is even codified in the Unicode standards which represents characters in hundreds of different written languages.
5.
Again, XML is not a string until application says so and XML in AS3 is not a String but a special object.
XML is actually a string BEFORE the application says it is XML, since the XML is constructed FROM A STRING. XML is a special object, which is constructed from, represents, and processes a string.
I could very easily create a class named "AllCapsSentence" and like "XML", the class itself is not "String", but they logically represent a string of characters and any "toString" method on either of such classes should return the underlying string representation without mangling it.
Copy link to clipboard
Copied
And just to be clear, the XML.toString method does not reflect the child content. If the child content is blank and toString returns blank, that's expected. But if the child content is not blank, it doesn't just return the non-blank child content... it includes the child content and the wrapping XML node, which it left out when the nodes content is blank.
So I have two issues with it. First, that toString is applying conditional logic to something that is already a string. Second, that the logic it applies is inconsistent in that it's not returning just the node's content... it's actually returning the node's content, unless the node contains another node, then it's returning the node itself and the node's content.
Copy link to clipboard
Copied
Take it up with the w3c or whoever wrote the e4x spec.
Copy link to clipboard
Copied
Amy, thanks for pointing out that this is an E4X issue. I looked up the EMCA 4 XML (E4X) spec here: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-357.pdf
Around page 29, it explains the implementation
If a value of type XML has simple content (i.e., contains no elements), it represents a primitive value and ToString returns the String contents of the XML object, omitting the start tag, attributes, namespace declarations and end tag. Otherwise, ToString returns a string representing the entire XML object, including the start tag, attributes, namespace declarations and the end tag.
NOTE the actual format of the resulting string content is implementation defined.
It seems that they thought they were doing programmers a favor:
...this behaviour allows E4X programmers to access the values of XML leaf nodes in much the same way they access the values of object properties.
E4X does not require the programmer to explicitly select the text nodes associated with each leaf element or explicitly select the first element of each XMLList return value. For cases where this is not the desired behaviour, the ToXMLString operator is provided.
All I'm saying is, as a programmer, it's not the desired behavior. It's not desired, it's not expected, it's frankly suprising that a toString method on an object constructed from and which represents a string of character to begin with, to not return that string of characters. And to wrap such a string in an object-oriented wrapper such as XML or XMLNode and then think that a programmer wouldn't expect to have to access a property like "text" on that node and would rather just have the node magically and inconsistantly convert itself to some arbitrary text representation, is just asinine
And then, as if as an afterthought, or like their better judgement tapping them on the back, they add a "toXMLString" like "oh, maybe all this arbitrary specialized transformation occuring under the hood isn't the programmer's desired behavior when calling toString on a class that basically already represents a string".
You know [sarcasm] "why on earth would a programmer want to *explicitly* access a property on an object when the object can just pick an arbitrary property to return for them!!! it's so much easier that way, herp derp"[/sarcasm] and they just tack on toXMLstring to save face.
I would LOVE to take this up with the E4X spec authors.
Copy link to clipboard
Copied
Like I said, e4x is a pain. After many years of pain, I have sort of come to terms with how it works and explained that to the best of my ability on my blog, which I linked to above.
Copy link to clipboard
Copied
To add to what Andre1, another thing that toString() does is convert CDATA to a usable string. e4x is just a pain. You may find this link useful.
Copy link to clipboard
Copied
I agree that there is some inconsitency in the return data, where sometimes there's XML tags, and sometimes there's just text. That's odd for a language like AS3 to have different return values where sometimes it's plain text and sometimes it's code.
Languages don't always get everything 100% right the first time, but when there's another function that does consistently return what you need, be happy that there's at least that because in AS2 it was a mess and largely devoid of "another function that does exactly what it should!"
Find more inspiration, events, and resources on the new Adobe Community
Explore Now