ColdFusion:我是否需要为深层结构的每个元素使用structKeyExists?

时间:2011-02-16 19:14:34

标签: coldfusion struct key exists

假设我刚刚解析了其他人的XML文档,这是对API请求的响应。我想知道嵌套在内部的值是否存在。如果我的API请求有效,则每次都会在同一个地方。如果我的API请求失败,则XML的根目录非常不同。

如果我在失败的api请求上尝试<cfif structKeyExists(myStruct.level1.level2.level3, 'myTarget')>,我会收到致命错误:Element LEVEL1.LEVEL2 is undefined in MYSTRUCT

当然,我可以尝试依赖XML的根级别告诉我成功或失败,如果失败则不会查找结果,但是......除非解决方案,我该怎么办?

我是否需要检查结构的每个级别是否存在?如:

<cfif structKeyExists(myStruct, 'level1') 
  and structKeyExists(myStruct.level1, 'level2') 
    and structKeyExists(myStruct.level1.level2, 'level3') 
      and structKeyExists(myStruct.level1.level2.level3, 'myTarget')>
<!--- ... --->
</cfif>

这不是一个现实世界的问题,这只是我面对太多次的问题。请不要告诉我涉及更改API的解决方案或第三段中的解决方案。

谢谢!

编辑:我应该已经提到为什么我不能使用isDefined() - 一些键没有语法上有效的名称,所以isDefined()抛出一个错误,例如myStruct.level1 [42] .level3

5 个答案:

答案 0 :(得分:5)

XMLSearch

我会使用解析后的XML文档(即xmlDoc)和XMLSearch

<cfset xmlDoc = xmlParse(responseData)>
<cfset nodes = XmlSearch(xmlDoc, '/level1/level2/level3/myTarget')>
<cfif arrayLen(nodes)>
    <!--- do something, you have the "nodes" array to work with too --->
</cfif>

XMLSearch()的xpath假定结构键是节点。例如,如果'myTarget'是节点的属性,则需要相应地进行修改。

StructFindKey

另一种方法是StructFindKey

<cfset result = structFindKey(myStruct, "myTarget")>
<cfif arrayLen(result) AND result.path EQ "level1.level2.level3">
    <!--- do something --->
</cfif>

结论

尚未测试,但我相信要么比使用IsDefined()或try-catch块更快。具有超过XMLValidate()不需要DTD的优势。而且,即使使用DTD,您想要的节点也可以定义为可选节点,因此它仍然可以验证。

答案 1 :(得分:3)

您可以针对DTD验证XML,以确保文档格式正确。 XmlParse()XmlValidate()都将DTD作为参数。

<cfset validateResult = XmlValidate(myXmlDocument, myDTD)>
<cfif validateResult.status>
    <!--- xml is valid continue processing --->
<cfelse>
    <!--- xml did not validate handle the error --->
</cfif>

答案 2 :(得分:2)

就我个人而言,我不会疯狂地检查这样的“深层”结构的每个级别。我认为如果顶层存在,文档的其余部分将如您所愿,我只是从那里处理文档。

如果您愿意,也许可以尝试解决结构中的值并将其包装在try/catch中。这样,您就可以以相同的方式处理任何“级别”的任何错误。

<cftry>

  <cfset myVar = myStruct.level1.level2.level3 />

<cfcatch type="any">
  <!--- Handle error --->
</cfcatch>
</cftry>

希望有所帮助。

答案 3 :(得分:2)

我知道我会在舞台上嘘声,但这是isDefined()可以为你节省大量打字的地方:

<cfif isDefined(structKeyExists(myStruct.level1.level2.level3)>
<!--- do something --->
</cfif>

答案 4 :(得分:1)

我知道这已经有一年了,但我会在这里提出答案。我用这个挣了很长时间,直到找到一个简单的解决方案。如果我已经知道XML的结构,那么简单的IsDefined可以测试节点或节点属性是否存在。我不认为大多数人都知道你可以做到这一点,或者尝试过失败,因为他们没有在IsDefined函数中包含单引号。

所以说我从某个地方的Web服务中获取了一些用户xml,并希望显示用户的ID。

<cfhttp url="https://mycompany.com/mywebservices/getusers" username="me" password="mysecret">
<cfset userXMLDoc = XMLParse(ToString(cfhttp.FileContent).trim())>

<cfif IsDefined('userXMLDoc.Data.Record.User.XmlAttributes.id')>
  <cfdump var="#userXMLDoc.Data.Record.User.XmlAttributes.id#">
<cfelse>
  <cfoutput>Failed: No User ID found</cfoutput>
</cfif>
相关问题