假设我刚刚解析了其他人的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
答案 0 :(得分:5)
我会使用解析后的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。
<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>