在 ColdFusion 8 中递归查询 XML 以查找未知数量的子级别 [英] Recursive Query of XML in ColdFusion 8 to find unknown number of children sub levels
问题描述
我们有一个由两个盒子组成的集群 ColdFusion 8 环境.我试图遍历由 Cognos 10.1 创建的 XML,以按照它们在 XML 中出现的顺序查找每个元素.目的是创建报告独特布局的缩略图 html 表示,用图标代替元素.
问题在于 Cognos 为报表中的每个新对象放置了一个新的 [block].[content] 元素,然后根据创建报表时确定的分层顺序将它们嵌套.
例如,如果您放入一个只有一列的列表对象,应用程序将不得不遍历
html.body.report.layouts.layout.reportPages.page [...]页面正文堵塞内容块=列表堵塞内容=列
每份报告都有不确定的复杂程度.我已经使用 Ben Nadel 的 CF8 技术和 cfgroovy 解析了 xml,并且有可用的 xml 源.
现在我必须找出列表"是否存在以及它在文件中的顺序.
到目前为止,我已经在如下循环中使用了循环:
<cfloop array="#XmlSearch(cleanedXml.html.body.report.layouts.layout.reportPages.page,'./.')#" index="i"><cfoutput><cfif structKeyExists(i, "xmlattributes")><cfloop collection="#i.xmlattributes#" item="a">#a#: #i.xmlAttributes[a]#<br/></cfloop></cff><cfloop array="#i.xmlchildren#" index="x">#x.xmlName#: #x.xmlText#<br/><cfif structKeyExists(x, "xmlchildren") ><cfloop array="#x.xmlchildren#" index="z">#z.xmlName#: #z.xmlText#<br/></cfloop></cff></cfloop></cfoutput><br/></cfloop>
然而,这只会下降两级(因为它只有两个循环).
我也尝试过与 Ben 的 Recusion:http://www.bennadel.com/blog/1069-ask-ben-simple-recursion-example.htm
失败是因为 CF8 不喜欢动态传入父节点.
cleanedXml.html.body.report.layouts.layout.reportPages.page
有效并且 cleanedXml.html.body.report.layouts.layout.reportPages.page.#parentString#
没有
看起来这应该是一个简单的修复,但我无法克服必须对每个潜在级别进行循环或递归的问题,这只会在第一次有人编写比我多一个级别的报告时中断已经预料到了.
如果在cfml中无法做到;我愿意在 jQuery 中尝试它,但我会重新开始,因为我的 jQuery 是有限的.
这是一个 1400 行 xml 的小示例,它是一个小型报告文件.请注意第 195 行的列表",然后是第 226 行的列表列",我将按此顺序需要这两个.
<代码>`xmlresults - 数组 - 1 行的前 1 行1) [xml 元素]XmlName: pageBodyXmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]xml名称:样式XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:内容XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:块XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:内容XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:提示按钮XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]类型:回XmlChildren:[xml 元素]XmlName:内容XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]xml名称:样式XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:HTMLItemXmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:数据源XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]Xml 名称:静态值XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XML 名称:文本项XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:数据源XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]Xml 名称:静态值XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtmlXmlText:注意:单击返回"按钮不会清除任何选定的过滤器.xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]xml名称:样式XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:条件样式XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:conditionalStyleCasesXmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]引用变量:back1XmlChildren:[xml 元素]XmlName: 条件样式XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]引用变量值:1XmlChildren:[xml 元素]xml名称:CSSXmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]值:可见性:隐藏XmlChildren:[xml 元素]XmlName:conditionalStyleDefaultXmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:块XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName:内容XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]xml名称:列表XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]水平分页:true名称:列表1refquery: Query1XmlChildren:[xml 元素]xml名称:样式XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName: listColumnsXmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]Xml 名称:列表列XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]XmlName: listColumnTitleXmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:[xml 元素]xml名称:样式XmlNs前缀:XmlNsURI:http://www.w3.org/1999/xhtml文本:xml注释:XmlAttributes: [结构]XmlChildren:`
我觉得自己完全是个傻瓜!我找到了满足我需求的答案;不一定是我的问题.而不是使用回避;我重新查看了我没有提到的 XmlSearch 代码,因为我认为我已经排除了它的可能性.原来我只是使用了错误的语法!在stackoverflow上找到:ColdFusion XmlSearch(): XPath with namespaces后,我去了这些-
导致:http://www.w3.org/TR/xpath/
我创建了一个搜索,将按照它们在 xml 中出现的顺序显示结果!
`<cfset listInXml = #XmlSearch(cleanedXml,"//*[ local-name()='list' or local-name()='combinationChart' ]")# >`
这返回了图表、图表、列表、图表...等,就像在我的 jsfiddle-http://jsfiddle.net/asheppardwork/3uuaj5jb/1/
我被卡住了,因为我只使用了 Ben Nadel 在他网站上的语法;我从未想过从那时起 cf8 可能会发生变化.
我希望这能帮助其他寻找相同类型事物的人.
We have a clustered ColdFusion 8 environment consisting of two boxes. I am trying to traverse XML that was created by Cognos 10.1 to find every element in the order they appear in the XML. The purpose is to create a thumbnail html representation of the report's unique layout that substitutes icons for elements.
The wrinkle is that Cognos puts a new [block].[content] element for each new object in a report and then nests them based on a layered order determined when the report is created.
For example if you put in a list object with a single column the app will have to traverse through
html.body.report.layouts.layout.reportPages.page [...]
pageBody
block
contents
block=list
block
contents=column
Each report will have a undetermined amount of complexity. I have parsed the xml using Ben Nadel's techniques for CF8 with cfgroovy and have usable xml source.
Now I have to find if a "list" exists and the order it is in the file.
So far, I've used loops in loops like:
<cfset cleanedXml = xmlParse( xhtml ) />
<cfloop array="#XmlSearch(cleanedXml.html.body.report.layouts.layout.reportPages.page,'./.')#" index="i">
<cfoutput>
<cfif structKeyExists(i, "xmlattributes")>
<cfloop collection="#i.xmlattributes#" item="a">
#a#: #i.xmlAttributes[a]#<br/>
</cfloop>
</cfif>
<cfloop array="#i.xmlchildren#" index="x">
#x.xmlName#: #x.xmlText#<br/>
<cfif structKeyExists(x, "xmlchildren") >
<cfloop array="#x.xmlchildren#" index="z">
#z.xmlName#: #z.xmlText#<br/>
</cfloop>
</cfif>
</cfloop>
</cfoutput>
<br/>
</cfloop>
However, that only goes down two levels (because its only two loops).
I've also tried Recusion with Ben's: http://www.bennadel.com/blog/1069-ask-ben-simple-recursion-example.htm
That failed because CF8 does not like having the parent node passed in dynamically.
cleanedXml.html.body.report.layouts.layout.reportPages.page
works and cleanedXml.html.body.report.layouts.layout.reportPages.page.#parentString#
does not
It seems like this should be a simple fix, but I just can't get past having to have a loop or recursion for each potential level, which would only break the first time someone wrote a report with one more level than I've anticipated.
If this can't be done in cfml; I am willing try it in jQuery but I would be starting all over again as my jQuery is limited.
Here is a small sample of a 1400 line xml which is a small report file. Notice the "list" on line 195 then its "listColumn" on line 226, I would need both of these in this order.
`
xmlresults - array - Top 1 of 1 rows
1) [xml element]
XmlName: pageBody
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: style
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: contents
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: block
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: contents
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: promptButton
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
type: back
XmlChildren:
[xml element]
XmlName: contents
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: style
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: HTMLItem
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: dataSource
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: staticValue
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: textItem
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: dataSource
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: staticValue
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText: Note: Clicking the "Back" button will not clear any selected Filters.
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: style
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: conditionalStyles
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: conditionalStyleCases
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
refvariable: back1
XmlChildren:
[xml element]
XmlName: conditionalStyle
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
refvariablevalue: 1
XmlChildren:
[xml element]
XmlName: CSS
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
value: visibility:hidden
XmlChildren:
[xml element]
XmlName: conditionalStyleDefault
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: block
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: contents
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: list
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
horizontalpagination: true
name: List1
refquery: Query1
XmlChildren:
[xml element]
XmlName: style
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: listColumns
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: listColumn
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: listColumnTitle
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
[xml element]
XmlName: style
XmlNsPrefix:
XmlNsURI: http://www.w3.org/1999/xhtml
XmlText:
XmlComment:
XmlAttributes: [struct]
XmlChildren:
`
I feel like a complete dummy on this one! I found a answer to my need; not necessarily my question. Rather than use recusion; I re-looked at my XmlSearch code which I didn't mention because I thought I already ruled it out as a possibility. Turns out I was just using the wrong syntax! After finding: ColdFusion XmlSearch(): XPath with namespaces on stackoverflow I went to these-
Which led to: http://www.w3.org/TR/xpath/
I've created a search that will display the results in the order they appear in in the xml!
`<cfset listInXml = #XmlSearch(cleanedXml,"//*[ local-name()='list' or local-name()='combinationChart' ]")# >`
This returned Chart, Chart, List, Chart... etc. like it is in my jsfiddle- http://jsfiddle.net/asheppardwork/3uuaj5jb/1/
I got stuck because I was only using the syntax that Ben Nadel had on his site; I never figured it might have changed since then for cf8.
I hope this helps anyone else looking for the same type of thing.
这篇关于在 ColdFusion 8 中递归查询 XML 以查找未知数量的子级别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!