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

发布于 2024-10-17 17:42:34 字数 881 浏览 4 评论 0 原文

假设我刚刚解析了其他人的 XML 文档,该文档是对 API 请求的响应。我想知道是否存在嵌套在深处的值。如果我的 API 请求有效,它每次都会出现在同一个位置。如果我的 API 请求失败,XML 的根就会非常不同。

如果我在失败的 api 请求上尝试 ,我会收到致命错误: Element LEVEL1.LEVEL2 is undefined在 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

Let's say i've just parsed someone else's XML document which is a response to an API request. I want to know if a value nested deep inside exists. If my API request worked, it will be in the same place every time. If my API request fails, the root of the XML is very different.

If I try <cfif structKeyExists(myStruct.level1.level2.level3, 'myTarget')> on a failed api request, I get the fatal error: Element LEVEL1.LEVEL2 is undefined in MYSTRUCT.

Of course, I could try to depend on the root level of the XML telling me of success or failure, and not looking for the result if it failed, but... barring that solution, what should i do?

Do i need to check for the existence of each level of the struct? As in:

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

This is not a real-world problem, this is just something i've faced too many times. Please don't tell me solutions that involve changing the API or solutions like those in the third paragraph.

Thanks!

edit: i should have mentioned why i can't use isDefined() - some of the keys do not have syntactically valid names, so isDefined() throws an error, eg myStruct.level1[42].level3

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

天煞孤星 2024-10-24 17:42:34

XMLSearch

我将使用解析的 XML 文档(即 xmlDoc)和 XMLSearch< /a>:

<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,您想要的节点也可能被定义为可选的,因此它仍然可以验证。

XMLSearch

I would use the parsed XML document (i.e. xmlDoc) and 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>

xpath for XMLSearch() assumes the structure keys are nodes. You would need to modify accordingly if, for instance, 'myTarget' is an attribute of a node.

StructFindKey

Another way of doing this would be StructFindKey.

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

Conclusion

Haven't tested, but I believe either will be faster than using IsDefined() or a try-catch block. Has the advantage over XMLValidate() of not needing a DTD. And, even with a DTD, the node you want may be defined as optional, so it could still validate.

星星的軌跡 2024-10-24 17:42:34

您可以根据 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>

You could validate the XML against a DTD to make sure the document was in the right format. XmlParse() and XmlValidate() both take a DTD as a parameter.

<cfset validateResult = XmlValidate(myXmlDocument, myDTD)>
<cfif validateResult.status>
    <!--- xml is valid continue processing --->
<cfelse>
    <!--- xml did not validate handle the error --->
</cfif>
飘落散花 2024-10-24 17:42:34

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

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

<cftry>

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

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

希望对一些人有所帮助。

Personally I wouldn't go crazy checking for every level of a 'deep' structure like this. I would presume that if the top level exists the rest of the document will be as you expect, and I'd just address the document from there.

If you wanted you could perhaps try to address the value in your struct and wrap it in a try/catch. That way you can handle any errors at any 'level' in the same way.

<cftry>

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

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

Hope that helps some.

一向肩并 2024-10-24 17:42:34

我知道我会被嘘下台,但这就是 isDefined() 可以为您节省大量打字的地方:

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

I know I'm going to get booed off the stage here, but this is where isDefined() can save you a lot of typing:

<cfif isDefined(structKeyExists(myStruct.level1.level2.level3)>
<!--- do something --->
</cfif>
温柔戏命师 2024-10-24 17:42:34

我知道这已经过去一年了,但我要在这里给出答案。我在这个问题上挣扎了很长时间,直到找到一个简单的解决方案。如果我已经知道 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>

I know this is a year old, but I'm going to put in an answer here. I struggled for a good long time with this one, till I found a simple solution. If I know the structure of the XML already, a simple IsDefined works to test if the node or node attribute exists. I don't think most people know you can do this, or have tried and failed because they didn't include single quotes in the IsDefined function.

So say I grab some user xml from a web service somewhere and want to display the user's 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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文