ColdFusion - how to loop through XML output and adding to struct or array?

后端 未结 2 1251
梦如初夏
梦如初夏 2021-01-25 14:03

I am trying to create a list of Chapter Officers and their respective positions. The data comes from a series of XML key/value pairs accessed via web service (Key: Member_Name,

相关标签:
2条回答
  • 2021-01-25 14:18

    In Coldfusion 10 or Railo 4, you could use the Underscore.cfc library to help clean your solution up a lot:

    <cfscript>
        soapBody = XmlParse(cfhttp.filecontent);
        fields = xmlSearch(soapBody,"//*[local-name()='Fields']");
        chapterOfficers = _.map(fields, function (field) {
            var officer = {};
            _.each(field.xmlChildren, function (KeyValueOfstringanyType) {
                var key = KeyValueOfstringanyType['b:Key'].xmlText;
                var value = KeyValueOfstringanyType['b:Value'].xmlText;
                officer[key] = value;
            });
            return officer;
        });
    </cfscript>
    
    <cfoutput>
    <cfloop array="#chapterOfficers#" index="officer">
        <a href="OfficerDetail.cfm?sessionGuid=#URL.sessionGuid#&memberGuid=#officer.Member_Guid#">#officer.Member_Name#</a> 
        #officer.Position_Name#<br />
    </cfloop>
    </cfoutput>
    

    Now isn't that nicer? I'm not exactly sure what your SOAP response looks like, but you should be able to tweak the xmlSearch() to match on the parent element of KeyValueOfstringanyType. I also removed all the unnecessary cfoutputs for you. Also, I'd recommend switching to JSON instead of XML. It's a LOT easier to parse.

    (Disclaimer: I wrote the Underscore.cfc library)

    0 讨论(0)
  • 2021-01-25 14:33

    Here's how I would probably solve this:

    <cfset var ChapterOfficers = StructNew()>
    <cfset var CurMemberGuid = '' />
    
    <cfloop index="local.CurPair" array=#keyValue#>
    
        <cfif CurPair.Key.XmlText EQ 'Member_Guid' >
            <cfset CurMemberGuid = CurPair.Value.XmlText />
            <cfset ChapterOfficers[CurMemberGuid] = StructNew() />
        <cfelse>
            <cfset ChapterOfficers[CurMemberGuid][CurPair.Key.XmlText] = CurPair.Value.XmlText />
        </cfif>
    
    </cfloop>
    

    It uses the existing XmlSearch you've done, and assumes Member_Guid is always the first key/value pair. I've used var/local scope assuming this is going inside a function (which it probably should be), but if not just remove them.

    It uses structs so lookup of a particular GUID is easy, but order isn't preserved (though if necessary you could keep a separate array to do that), and you don't have to remember which array position matches to which key.

    If you wanted to lookup based on other fields, you could also convert the data into a query, like so:

    <cfset var ChapterOfficers = QueryNew('Member_Guid,Member_Type,Member_Name,Position_Guid,Position_Type,Position_Name,Term_Guid,Term_Type,Term_Name')>
    <cfset var CurRow = 1 />
    
    <cfloop index="local.CurPair" array=#keyValue#>
    
        <cfif CurPair.Key.XmlText EQ 'Member_Guid' >
            <cfset QueryAddRow(ChapterOfficers) />
        </cfif>
    
        <cfset QuerySetCell(ChapterOfficers,CurPair.Key.XmlText,CurPair.Value.XmlText) />
    
    </cfloop>
    

    This maintains order and makes more general lookup easier, also makes it easier if your main use is outputting direct to HTML.

    I've hard-coded the column keys there, but you could also do a pre-loop to collate those first, if they are something that is liable to change.


    Hopefully this all makes sense?

    0 讨论(0)
提交回复
热议问题