我正在尝试创建一个章节官员列表及其各自的职位。数据来自通过Web服务访问的一系列XML键/值对(Key:Member_Name,Value:Joe Member。键:Position_Name,Value:President等等。)给定章节的每个官员都有自己的Member_Name和Position_Name。
我正在使用的API只会返回一个完整的对象,因此我设置了一个数组来转换XML名称并保存所有内容:
<cfset keyValue = xmlSearch(soapBody,"//*[local-name()='KeyValueOfstringanyType']") />
我的想法是遍历该数组,并且对于关键Member_Name和Position_Name的每个实例,将值添加到结构中:
<cfset chapterOfficers=structNew()>
<cfloop index="i" from="1" to="#arrayLen(keyValue)#">
<cfif keyValue[i].Key.xmlText EQ 'Member_Name'>
<cfset chapterOfficers.Name=keyValue[i].Value.xmlText>
</cfif>
<cfif keyValue[i].Key.xmlText EQ 'Position_Name'>
<cfset chapterOfficers.Position = keyValue[i].Value.xmlText>
</cfif>
<cfif keyValue[i].Key.xmlText EQ 'Term_Name'>
<cfset chapterOfficers.Term = keyValue[i].Value.xmlText>
</cfif>
</cfloop>
倾倒这个结构给了我一个漂亮整洁的小桌子,上面有一个人的名字,那个人的位置和他们的名词 - 但只有那个(这恰好是XML文件中的最后一个条目)。即使添加i = i + 1也没有任何影响 - 它几乎就像循环从最后开始,而不是继续。
我尝试过在结构中添加内容的其他方法, 遍历所有内容,但键/值对以不相关的顺序出现。我知道结构不是有序的,但是我需要有一些方法来对XML输出中的数据进行排序。我还尝试了各种其他循环,尝试将一系列像这样的小结构添加到数组中。它起作用,但同样,只为那个人 - 没有实际的“循环”似乎发生!我可以在同一时间看到我需要的所有信息 - 所以也许是为了让我做错了所有这一切?
提前谢谢大家,我感谢任何有关正确方向的建议或推动!
更新:不知道这是否有帮助,但刚才我在我正在使用的循环中交换了To和From的值,并将步骤设置为-1,它给了我列表中的第一个人。但仍然没有循环。
更新:感谢Peter,以下是我正在使用的XML示例:
<b:KeyValueOfstringanyType>
<b:Key>Member_Guid</b:Key>
<b:Value i:type="d:string">006e1c09-25f9-4178-86de-13c3e63200ce</b:Value>
</b:KeyValueOfstringanyType>
<b:KeyValueOfstringanyType>
<b:Key>Member_Type</b:Key>
<b:Value i:type="d:string">Entity</b:Value>
</b:KeyValueOfstringanyType>
<b:KeyValueOfstringanyType>
<b:Key>Member_Name</b:Key>
<b:Value i:type="d:string">Member, Joe</b:Value>
</b:KeyValueOfstringanyType>
<b:KeyValueOfstringanyType>
<b:Key>Position_Guid</b:Key>
<b:Value i:type="d:string">02ae1c09-5779-4891-8cd1-05cf475cf5af</b:Value>
</b:KeyValueOfstringanyType>
<b:KeyValueOfstringanyType>
<b:Key>Position_Type</b:Key>
<b:Value i:type="d:string">CommitteePosition</b:Value>
</b:KeyValueOfstringanyType>
<b:KeyValueOfstringanyType>
<b:Key>Position_Name</b:Key>
<b:Value i:type="d:string">President</b:Value>
</b:KeyValueOfstringanyType>
<b:KeyValueOfstringanyType>
<b:Key>Term_Guid</b:Key>
<b:Value i:type="d:string">044e1c09-a90b-495f-891f-afa13e653dee</b:Value>
</b:KeyValueOfstringanyType>
<b:KeyValueOfstringanyType>
<b:Key>Term_Type</b:Key>
<b:Value i:type="d:string">CommitteeTerm</b:Value>
</b:KeyValueOfstringanyType>
<b:KeyValueOfstringanyType>
<b:Key>Term_Name</b:Key>
<b:Value i:type="d:string">2011-2012</b:Value>
</b:KeyValueOfstringanyType>
对每个章员进行重复。
更新:这是我提出的代码。它做我想做的事,但有更好的方法来做,我相信......
首先,我从SOAP响应中获取结果,“向下钻取”到我需要的级别,然后删除特定于xml的内容并将数据放入可用的数组中:
<cfset soapBody = xmlParse(cfhttp.fileContent)>
<cfset soapBody = soapBody['s:Envelope']['s:Body'].QueryResponse.QueryResult.Objects.anyType.Fields />
<cfset keyValue = xmlSearch(soapBody,"//*[local-name()='KeyValueOfstringanyType']") />
然后
<cfset chapterOfficers=arrayNew(2)>
<cfset x=1>
<cfset y=1>
<cfloop index="i" from="1" to="#arrayLen(keyValue)#">
<cfif keyValue[i].Key.xmlText EQ 'Member_Name'>
<cfset memberName = keyValue[i].Value.xmlText>
<cfset chapterOfficers[x][y]=#memberName#>
<cfset y=y+1>
</cfif>
<cfif keyValue[i].Key.xmlText EQ 'Position_Name'>
<cfset positionName = keyValue[i].Value.xmlText>
<cfset chapterOfficers[x][y]=#positionName#>
<cfset x=x+1>
<cfset y=1>
</cfif>
<cfif keyValue[i].Key.xmlText EQ 'Member_Guid'>
<cfset memberGuid = keyValue[i].Value.xmlText>
<cfset chapterOfficers[x][3]=#memberGuid#>
</cfif>
</cfloop>
我做了一些其他处理,检查是否存在变量等,然后输出官员的姓名及其各自的职位
<cfloop from="1" to="#arrayLen(chapterOfficers)#" index="x">
<p>
<cfoutput><a href="OfficerDetail.cfm?sessionGuid=<cfoutput>#URL.sessionGuid#</cfoutput>&memberGuid=<cfoutput>#chapterOfficers[x][3]#</cfoutput>">#chapterOfficers[x][1]#</a></cfoutput><br />
<cfoutput>#chapterOfficers[x][2]#</cfoutput><br />
</p>
</cfloop>
我能够将Member_Guid添加到阵列并使用它,以便网站访问者可以点击某个人的姓名以查看更多详细信息(公司,电子邮件地址等)。这就是它!你怎么看?再次,非常感谢花时间,我真的很感激!
答案 0 :(得分:1)
以下是我可能会解决的问题:
<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>
它使用您已完成的现有XmlSearch,并假设Member_Guid
始终是第一个键/值对。我已经使用了var / local范围,假设这是在一个函数内部(它可能应该是这样),但如果不是只是删除它们。
它使用结构,因此查找特定的GUID很容易,但是不保留顺序(尽管如果有必要,你可以保留一个单独的数组来执行该操作),并且您不必记住哪个数组位置匹配哪个键。
如果您想基于其他字段进行查找,您还可以将数据转换为查询,如下所示:
<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>
这可以维护顺序,使更多的常规查找更容易,如果您的主要用途是直接输出到HTML,也会更容易。
我在那里对列密钥进行了硬编码,但如果它们易于改变,你也可以先进行预循环,然后再进行整理。
希望这一切都有意义吗?
答案 1 :(得分:0)
在Coldfusion 10或Railo 4中,您可以使用Underscore.cfc library来帮助清理您的解决方案:
<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>
现在不是更好吗?我不确定你的SOAP响应是什么样的,但你应该能够调整xmlSearch()以匹配KeyValueOfstringanyType的父元素。我还为您删除了所有不必要的cfoutput。另外,我建议切换到JSON而不是XML。这很容易解析。
(免责声明:我写了Underscore.cfc库)