tracker issue : CF-4199973

select a category, or use search below
(searches all categories and all time range)
Title:

[ANeff] ER for: relevant string, struct and array member functions on XML variables

| View in Tracker

Status/Resolution/Reason: Closed/Fixed/Fixed

Reporter/Name(from Bugbase): Aaron Neff / Aaron Neff ()

Created: 10/08/2017

Components: Language, Member Functions

Versions: 2016

Failure Type: Others

Found In Build/Fixed In Build: / 2018.0.0.308743

Priority/Frequency: Normal /

Locale/System: /

Vote Count: 1

This ER is for: relevant string, struct and array member functions on XML variables

The following String, Struct and Array functions can be used on XML variables, but their member function equivalents don't: toString(), arrayLen(), arrayIsEmpty(), structCount(), structIsEmpty(), structKeyList(), structKeyArray(), structAppend() and structUpdate().

The following member functions should be added to XML variables: .toString(), .len(), .count(), .isEmpty(), .keyList(), .keyArray(), .append(), .update()

Once this ER is implemented, the following should return the expected results notated in the comments:

<cfxml variable="myXMLVar">
<myXML a="b">
  <foo>foo1</foo>
  <foo>foo2</foo>
  <foo></foo>
  <bar>bar1</bar>
  <bar></bar>
  foobar
</myXML>
</cfxml>

<cfscript>
  //xml.toString()
  writeOutput(toString(myXMLVar) & '<br>');//foo1 foo2 bar1 foobar
  writeOutput(myXMLVar.toString() & '<br>');//should return "foo1 foo2 bar1 foobar" but returns "[#document: null]"
  
  //xmlElement.len()
  writeOutput(arrayLen(myXMLVar.myXML.foo) & '<br>');//3
  writeOutput(myXMLVar.myXML.foo.len() & '<br>');//should return "3" but throws "The len method was not found."
  
  //xmlElement.isEmpty()
  writeOutput(arrayIsEmpty(myXMLVar.myXML) & '<br>');//NO
  writeOutput(myXMLVar.myXML.isEmpty() & '<br>');//should return "NO" but throws "The isEmpty method was not found."
  
  //xmlElement.count()
  writeOutput(structCount(myXMLVar.myXML) & '<br>');//5
  writeOutput(myXMLVar.myXML.count() & '<br>');//should return "5" but throws "The count method was not found."
  
  //xmlElement.isEmpty()
  writeOutput(structIsEmpty(myXMLVar.myXML.foo[1]) & '<br>');//YES
  writeOutput(myXMLVar.myXML.foo[1].isEmpty() & '<br>');//should return "YES" but throws "The isEmpty method was not found."
  
  //xmlElement.keyList()
  writeOutput(structKeyList(myXMLVar.myXML) & '<br>');//foo,foo,foo
  writeOutput(myXMLVar.myXML.keyList() & '<br>');//should return "foo,foo,foo" but throws "The keyList method was not found."
  
  //xmlElement.keyArray()
  writeDump(structKeyArray(myXMLVar.myXML));//[foo,foo,foo]
  writeDump(myXMLVar.myXML.keyArray());//should return [foo,foo,foo] but throws "The keyArray method was not found."
  
  //xmlElement.append()
  xmlElem = xmlElemNew(myXMLVar, "myXML");
  xmlElem.xmlChildren[1] = xmlElemNew(myXMLVar, "newElement");
  xmlElem.xmlChildren[1].xmlText = "new element value";
  writeOutput(structAppend(myXMLVar.myXML.bar[1], xmlElem));//YES
  writeDump(myXMLVar.myXML.bar[1].append(xmlElem));//should return updated XML element but throws "The append method was not found."
  
  //xmlElement.update()
  writeOutput(structUpdate(myXMLVar.myXML, "xmlText", "bla bla"));//YES
  writeDump(myXMLVar.myXML.update("xmlText", "bla bla"));//should return updated XML element but throws "The update method was not found."
</cfscript>

Note: arrayIsEmpty(myXMLVar) and structIsEmpty(myXMLVar) both serve the same purpose (identifying if a node has any children) and thus there's no conflict and the member function can be .isEmpty()

Related URL: https://helpx.adobe.com/coldfusion/developing-applications/using-web-elements-and-external-objects/using-xml-and-wddx/modifying-a-coldfusion-xml-object.html

Attachments:

Comments:

"isEmpty" xml member function has been removed and instead exposed  "hasChild" xml member function as that makes more sense in xml context.
Comment by Vijay M.
27732 | May 10, 2018 10:55:56 AM GMT
Hi Adobe, I've verified this is mostly fixed in ColdFusion 2018 (build 2018.0.0.310739). The unfixed items are: 1) member function equivalent of `arrayIsEmpty(myXMLVar.myXML.xmlChildren)` wasn't added. Issue: The member function equivalent must also work. By allowing the BIF to work, but the member function to not work, you're creating inconsistency and confusion in the language. 2) member function equivalent of `structIsEmpty(myXMLVar.myXML.xmlAttributes)` wasn't added. Issue: The member function equivalent must also work. By allowing the BIF to work, but the member function to not work, you're creating inconsistency and confusion in the language. 3) `myXMLVar.myXML.update("xmlText", "bla bla")` returns a funky struct instead of XML. Issue: The return value should contain the updated string. Please run the example code I gave in this ticket's description, to see the issue. It needs to return XML (as noted in this ticket's description), so that a dump of the returned variable contains the "bla bla". 4) The `.hasChild()` member function is not even a workaround for #2. Additionally, `.hasChild()` doesn't even work b/c it always returns YES, even if a node has no child nodes. Ex: the following return YES: <cfxml variable="myXMLVar"><myXML></myXML></cfxml> <cfscript> writeOutput(myXMLVar.myXML.hasChild())//YES (bad) </cfscript> <cfxml variable="myXMLVar"><myXML attribute="value"></myXML></cfxml> <cfscript> writeOutput(myXMLVar.myXML.hasChild())//YES (bad) </cfscript> For completeness: If `isEmpty()` even worked properly, then it must correspond to a BIF. And if a BIF is added for checking if a node has children, then a BIF must be added for checking if a node has attributes. So `XmlHasChild()` and `XmlHasAttributes()` would both need added. And `xmlNode.hasAttributes()` member function would also need added. Instead of doing all this, can `xmlNode.hasChild()` please be removed since it doesn't even work? !IMPORTANT! - The "Functions for XML object management" table on the https://helpx.adobe.com/coldfusion/developing-applications/using-web-elements-and-external-objects/using-xml-and-wddx/modifying-a-coldfusion-xml-object.html must be predictable. It is not predictable if only -some- of the member function counterparts work but not others, like `.isEmpty()`. Can this ticket please be re-opened and fixed-as-filed? Thanks!, -Aaron
Comment by Aaron N.
29537 | August 18, 2018 05:55:42 AM GMT
For anyone that's following along, my following statement in this ticket's description is incorrect: ----------- Note: arrayIsEmpty(myXMLVar) and structIsEmpty(myXMLVar) both serve the same purpose (identifying if a node has any children) and thus there's no conflict and the member function can be .isEmpty() ----------- It is _certainly_ unclear from the "Modifying a ColdFusion XML object" doc's "Functions for XML object management" table (Doc Bug!), but this is the actual behavior of ArrayLen(XMLNode), ArrayIsEmpty(XMLNode), StructCount(XMLNode) and StructIsEmpty(XMLNode): - ArrayLen(fooNode.barNode) counts how many nodes named 'barNode' are under node named 'fooNode' - ArrayIsEmpty(fooNode.barNode) returns YES if there are no nodes named 'barNode' under node named 'fooNode', otherwise returns YES - StructCount(fooNode.barNode) counts how many nodes are under node named 'barNode' - StructIsEmpty(fooNode.barNode) returns YES if there are no nodes under node named 'barNode', otherwise returns YES Repro: <cfxml variable="myXMLVar"><myXML></myXML></cfxml> <cfscript> writeOutput(arrayLen(myXMLVar.myXML) & arrayIsEmpty(myXMLVar.myXML))//1NO writeOutput(structCount(myXMLVar.myXML) & structIsEmpty(myXMLVar.myXML))//0YES </cfscript> <cfxml variable="myXMLVar"><myXML><child></child></myXML></cfxml> <cfscript> writeOutput(arrayLen(myXMLVar.myXML) & arrayIsEmpty(myXMLVar.myXML))//1NO writeOutput(structCount(myXMLVar.myXML) & structIsEmpty(myXMLVar.myXML))//1NO </cfscript> <cfxml variable="myXMLVar"><myXML attribute="value"></myXML></cfxml> <cfscript> writeOutput(arrayLen(myXMLVar.myXML) & arrayIsEmpty(myXMLVar.myXML))//1NO writeOutput(structCount(myXMLVar.myXML) & structIsEmpty(myXMLVar.myXML))//0YES </cfscript> As shown, ArrayIsEmpty(xmlNode) and StructIsEmpty(xmlNode) serve _different_ purposes. Thus, there would be a conflict if `.isEmpty()` was added onto XMLNode. So.. now to think of the best solution for all this.. =) Thanks!, -Aaron
Comment by Aaron N.
29540 | August 18, 2018 07:28:47 AM GMT
Hi Adobe, Please ignore the above. Regarding .isEmpty() XML member function, I agree it's unnecessary. New questions/comments: 1) Are you adding the following BIFs?: XmlHasChild, XmlCount, XmlAppend, XmlUpdate, XmlKeyList and XmlKeyArray? 2) The .delete() XML member function should also be added. I mistakenly didn't include it in this ticket. And the BIF XMLDelete() should also be added. B/c StructDelete() also manipulates an XML object. 3) The XML BIF equivalent of ArrayLen(parentXMLNode.childXMLNode) should be added. But what would that XML BIF be named? (this counts the number of nodes named 'childXMLNode' under the parentXMLNode) 4) Can XMLUpdate, and the .update() XML member function, please return the updated XML? Currently, the .update() XML member function returns a struct that doesn't contain, for example, the updated xmlText. Thanks!, -Aaron
Comment by Aaron N.
29541 | August 18, 2018 10:27:03 AM GMT
Hi Adobe, Please ignore all my above comments. Filed CF-4203285. Thanks!, -Aaron
Comment by Aaron N.
29553 | August 20, 2018 07:51:12 AM GMT