3
votes

I'm currently using ColdFusion 10/11 and am still relatively new with it. I normally code in PHP/C# so the concept of using a scripting language (if that's what you would call it), to manage data in XML is kind of odd to me. If I could redesign the web application in PHP, I would but unfortunately that's not an option right now.

As far as platforms go, I'm NOT using Adobe ColdFusion Builder or CF Administrator. I'm using Dreamweaver and CFEclipse.

So, right now I'm reading an XML file and am checking if the XML child contains "yes", "no", etc and display the corresponding tag. It worked correctly previously, but I have to add a new child to the XML file called "GNTrained".

After adding the new element, it is still saying that the value is an empty string. I used "structKeyExists" to verify that the child exists, but the value is still coming up empty.

I also verified that it is reading the correct XML file. Great ColdFusion references don't really exist online anymore (though, I'm not sure if they ever did exist) so any help would be greatly appreciated!

Any ideas why this would happen?
Anywhere else the XML location would be delegated?

I've tried reworking this multiple times and am still left wondering why the value is still an empty string. I've tried various different values, swapped the elements around, anything and everything to get this to work.

For the sake of my work, this is example code and not the exact set of code I'm using. So if I left anything out, please let me know. However, this is the most simplistic version of the code and really all I believe that is needed to solve this issue.

There are 3 different files: the front-end display file, the query file, and the XML file.

Here's the code for the display page:

<cfinclude template="#APPLICATION.root#employee/details/employee-query.cfm" />
<cfoutput>
<cfquery name="get_employee" dbtype="query">
    SELECT id,name,GNTrained from session.employeeDetails order by name
</cfquery>
<cfloop query="get_employee">
<cfif tr eq "RowEven">
    <cfset tr="RowOdd">
    <cfelse>
    <cfset tr="RowEven">
</cfif>
<li class="EmployeeRow #tr#" id="company_#get_employee.currentrow#">#htmleditformat(get_employee.name)#
    <div id="bfeat_#get_employee.currentrow#" class="Hidden">
        <div class="employeeGroup" style="width:371px;">
            <ul class="EmpTrainingList">
            <li>BBTrained:
                <cfif get_employee.BBTrained contains "YES">
                    <span class="yes">#get_employee.BBTrained#</span>
                <cfelse>
                    <span class="no">#get_employee.BBTrained#</span>
                </cfif>
            </li>
            <li>GNTrained: 
            <cfif structKeyExists( get_employee, "GNTrained" )>
                <span style="color: red;"><strong>EXISTS! </strong></span>
                <cfelse> DOES NOT EXIST!
            </cfif>
            <cfif get_employee.GNTrained contains "YES">
                    <span class="yes">#get_employee.GNTrained#</span>
                <cfelseif get_employee.GNTrained contains "In Progress">
                    <span class="in-progress">#get_employee.GNTrained#</span>
                <cfelseif get_employee.GNTrained eq "">
                    <span class="no">EMPTY</span>    
                <cfelse>
                    <span class="no">#get_employee.GNTrained#</span>
            </cfif>             
            </li>
            </ul>
        </div>
    </div>
</li>
</cfloop>
</cfoutput>

Here's the code for the query:

<cffile action="read" file="#ExpandPath('#application.root#cf_test/employeeDetails.xml')#" variable="myxml">

<cfset mydoc = XmlParse(myxml)>
<cfset apps = mydoc.data.XmlChildren>
<cfset size = ArrayLen(apps)>

<cfset session.employeeDetails = QueryNew("employee_id,employee_name,GNTrained") >
<cfset temp = QueryAddRow(session.employeeDetails, #size#)>

<cfloop index="i" from = "1" to = #size#>
    <cfloop index="x" from="1" to="8">
        <cfset attr_name = REReplace(#mydoc.data.employees[i].XMLChildren[x].xmlName#, "[^a-zA-Z0-9__]", "", "ALL") />
        <cfset temp = QuerySetCell(session.employeeDetails, "#attr_name#", 
            #mydoc.data.employees[i].XMLChildren[x].xmlText#, #i#)>
    </cfloop>     
</cfloop>

<cfcatch>Error loading</cfcatch>
</cftry>

</cfoutput>

Here's the XML file:

<!---- File Name: employeeDetails.xml ---->
<?xml version="1.0" encoding="utf-8" ?>
<data>
<employees>
        <name>John Smith</name>
        <id>1234</id>
        <BBTrained>NO</BBTrained>
        <DEPT>21</DEPT>
        <EXP>12</EXP>
        <current>YES</current>
        <Status>ACTIVE</Status>
        <StateCode>CO122</StateCode>
        <GNTrained>NO</GNTrained>
</employees>
<employees>
        <name>Mary Chapman</name>
        <id>3344</id>
        <BBTrained>YES</BBTrained>
        <DEPT>21</DEPT>
        <EXP>18</EXP>
        <Status>LOA</Status>
        <StateCode>DE255</StateCode>
        <GNTrained>YES</GNTrained>
</employees>
<employees>
        <name>Alex Fisher</name>
        <id>6655</id>
        <BBTrained>NO</BBTrained>
        <DEPT>22</DEPT>
        <EXP>6</EXP>
        <Status>ACTIVE</Status>
        <StateCode>ME255</StateCode>
        <GNTrained>YES</GNTrained>
</employees>
</data>

UPDATED CODE - Includes cfloop now. (4/20/16)

**SOLUTION: ** With the help of SpliFF, I was able to find the issue. Seriously one of the easiest fixes I've come across. In the following code on the query page:

I needed to change "8" to "9" to account for the new element. Yes... It really was that small of a change. sigh

1
Not sure I completely follow, but it sounds like you are reading an XML file, parsing it and using the data to populate a query object. If so, where is the code that actually populates the query with data? The code above creates a query object and adds some empty rows, ie QueryAddRow(session.employeeDetails, #size#) but does not actually populate those rows. - Leigh
Yeah, it looks like you missed the second half of example in the documentation: help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/…. You'll need to add the cfloop and the querySetCell function inside the loop. - Chester
I added more of the code which shows the cfloop. So hypothetically, let's say BBTrained showed up correctly, but GNTrained did not. Is there anything that would make it not show up or show up as an empty string when clearly it's not empty?... - Rocket Risa
Well, the obvious possibility is if the column is not actually being populated. Because the code initializes the query with X rows, the column value would then be an empty string. To troubleshoot, add some debugging code. Dump out the current column/row/value before the QuerySetCell to see what is happening. <cfoutput>adding #attr_name# [#i#] [#x#] : mydoc.data.employees[i].XMLChildren[x].xmlText</cfoutput> - Leigh
BTW, if you are not a fan of tags, CF10+ has very good support for cfscript. - Leigh

1 Answers

2
votes

You are only setting temp to row 1 when you build your query because your QueryAddRow is outside the loop. You need it to point to the current row on each XML child:

<cfloop index="i" from = "1" to = #size#>
    <cfset temp = QueryAddRow(session.employeeDetails)>
    <cfloop index="x" from="1" to="#ArrayLen(mydoc.data.employees[i].XMLChildren)#">
        <cfset attr_name = REReplace(#mydoc.data.employees[i].XMLChildren[x].xmlName#, "[^a-zA-Z0-9__]", "", "ALL") />
        <cfset QuerySetCell(session.employeeDetails, "#attr_name#", 
            #mydoc.data.employees[i].XMLChildren[x].xmlText#, #i#)>
    </cfloop>
</cfloop>