ColdFusion - 如何遍历XML输出并添加到结构或数组?
我正在尝试创建章军官和他们各自的职位清单。数据来自通过Web服务访问的一系列XML键值对(Key:Member_Name,Value:Joe Member。Key:Position_Name,Value:President,等等。)给定章节的每个主管都有自己的Member_Name和Position_Name。ColdFusion - 如何遍历XML输出并添加到结构或数组?
我用仅会返回整个对象工作的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输出中排序数据。我也尝试过各种其他循环,试图将一系列像这样的小结构添加到数组中。它的工作,但再次,只为那个人 - 没有真正的“循环”似乎发生!我可以同时看到所有我需要的信息 - 也许这是为了让我做错了什么?
谢谢大家提前,我感谢任何建议或在正确的方向轻推!
UPDATE:不知道这是否有帮助,但现在我在我正在使用的循环中交换了To和From的值,并将步骤设置为-1,并且它给了我名单上的第一个人。但仍然没有循环。
更新:谢谢彼得,这里是我一起工作的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添加到数组中并使用它,因此网站访问者可以点击一个人的姓名以查看更多详细信息(公司,电子邮件地址等)。这就是它!你怎么看?再次感谢您抽出时间,我非常感谢!
这是我怎么可能会解决这个问题:
<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。
我已经硬编码列键,但你也可以做一个预循环来整理那些第一,如果他们是可以改变的东西。
希望这一切都有道理?
哇,彼得,这太棒了!我对你最初的例子中的嵌套结构非常满意 - 这使得在循环中输出成员信息变得更容易。它也帮助我建立链接。我在我的网站上的其他地方广泛使用了我的旧方法,但是您的方法更加高效和简洁,而且说实话,现在我可以看到它并且仔细考虑它。非常感谢!我必须承认,我仍然试图去处理你的第二个例子,但我现在正在试验它。再次感谢Peter,这真是太棒了,我非常感谢你的帮助和建议! – daltec 2012-07-29 22:38:20
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的父元素。我还为您删除了所有不必要的cfoutputs。另外,我建议切换到JSON而不是XML。这很容易解析。
(声明:我写的Underscore.cfc库)
嗨,Russ看起来更容易处理 - 如果我们转向CF10,我会给它一个镜头。谢谢!感谢JSON的提示,我很感激。 – daltec 2012-08-04 20:37:38
的Structs只能包含一个组键 - 如果你需要一个额外的维度需要放置结构中的处于阵列(或使用查询记录) 。但是,您也不需要循环遍历所有的键,而是正确地处理XML - 在没有看到XML结构的情况下很难说更多的东西,所以发布XML数据的样本(带有任何被屏蔽/删除的敏感信息)。 – 2012-07-29 01:00:00
彼得你好,非常感谢你的帮助。下面是一个XML示例: – daltec 2012-07-29 01:33:43
@PeterBoughton我在原始文章中添加了一些XML示例。命名空间比这里展示的更广泛,但这有帮助吗?如果您需要更多信息,请告知我们,并非常感谢您的帮助。 – daltec 2012-07-29 01:42:26