使用 ColdFusion 创建分层 xml 结构

发布于 2024-10-19 21:57:04 字数 2263 浏览 3 评论 0原文

有人可以帮助我改进这个吗?必须有更好的方法。我正在做的是构建一个本地网络服务,供 Flex 抓取以填充树形菜单。 Flex 是我称之为 Web 服务的应用程序,只是一些背景知识,但与问题无关。

为了为该树创建分层数据,我编写了以下代码。

    <cffunction name="getFormsBinMenu" access="remote" returntype="string">
    <cfquery name="getParents" datasource="db_intranet_data">
        SELECT * FROM formsbin_categories WHERE parentid = 1 ORDER BY sortorder ASC
    </cfquery>

    <cfoutput>
        <cfxml variable="formsBinMenu">
            <?xml version='1.0' encoding='utf-8' ?>
            <folder label="Forms Bin">
                <cfloop query="getParents">
                    <folder label="#XMLFormat(getParents.catname)#">
                            <cfquery name="getSubParents" datasource="db_intranet_data">
                                SELECT * FROM formsbin_categories WHERE parentid = #catid# and testonly = 0 and visible = 1 ORDER BY sortorder ASC
                            </cfquery>
                            <cfloop query="getSubParents">
                                <folder label="#XMLFormat(getSubParents.catname)#">
                                          <cfquery name="getNextSubParents" datasource="db_intranet_data">
                                                SELECT * FROM formsbin_categories WHERE parentid = #catid# and testonly = 0 and visible = 1 ORDER BY sortorder ASC
                                            </cfquery>
                                            <cfloop query="getNextSubParents">
                                                <folder label="#XMLFormat(getNextSubParents.catname)#"/>
                                            </cfloop>                        
                                </folder>   
                            </cfloop>                                         
                    </folder>
                </cfloop>
            </folder>
        </cfxml>
    </cfoutput>

    <cfset menu =  #toString(formsBinMenu)#>
    <cfreturn menu>
</cffunction>

正如你所看到的,我只是循环不同的查询。虽然这符合我的目的,但我如何编码才能避免太多代码重复?

我考虑过检查结构的深度,然后在索引循环中运行它,但这似乎仍然是太多的开销。

任何建议都会很棒!

Can someone help me improve on this? There has to be a better way. What I am doing is building a local web service for flex to grab in order to populate a tree menu. Flex being the application I'm calling the web service is just some background but has nothing to do with the problem.

In order to create hierarchical data for this tree, I've coded the following.

    <cffunction name="getFormsBinMenu" access="remote" returntype="string">
    <cfquery name="getParents" datasource="db_intranet_data">
        SELECT * FROM formsbin_categories WHERE parentid = 1 ORDER BY sortorder ASC
    </cfquery>

    <cfoutput>
        <cfxml variable="formsBinMenu">
            <?xml version='1.0' encoding='utf-8' ?>
            <folder label="Forms Bin">
                <cfloop query="getParents">
                    <folder label="#XMLFormat(getParents.catname)#">
                            <cfquery name="getSubParents" datasource="db_intranet_data">
                                SELECT * FROM formsbin_categories WHERE parentid = #catid# and testonly = 0 and visible = 1 ORDER BY sortorder ASC
                            </cfquery>
                            <cfloop query="getSubParents">
                                <folder label="#XMLFormat(getSubParents.catname)#">
                                          <cfquery name="getNextSubParents" datasource="db_intranet_data">
                                                SELECT * FROM formsbin_categories WHERE parentid = #catid# and testonly = 0 and visible = 1 ORDER BY sortorder ASC
                                            </cfquery>
                                            <cfloop query="getNextSubParents">
                                                <folder label="#XMLFormat(getNextSubParents.catname)#"/>
                                            </cfloop>                        
                                </folder>   
                            </cfloop>                                         
                    </folder>
                </cfloop>
            </folder>
        </cfxml>
    </cfoutput>

    <cfset menu =  #toString(formsBinMenu)#>
    <cfreturn menu>
</cffunction>

As you can see I'm just looping through different queries. While this works for my purpose, how could I code it so that there isn't so much code repetition?

I thought about checking to see how many levels deep the structure would be and then running it all in an index loop but that still seems like too much overhead.

Any suggestions would be great!

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

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

发布评论

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

评论(1

也只是曾经 2024-10-26 21:57:04

看看我使用 xslt 转换创建的代码,我确信您可以在代码中使用相同的方法(请注意,我的查询中的parentID是brandID的外键):

<cfquery name="queryBrands" datasource="#dsn#">
    SELECT brandID, brand, isAssignable, isnull(parentID, 0) AS parentID, abbreviation
    FROM dbo.BrandTree
</cfquery>


<cfxml variable="rawNodeTree">
    <cfoutput>
        <nodes>
            <cfloop query="queryBrands">
                <node id="#queryBrands.brandID#"
                      parentID="#queryBrands.parentID#"
                      name="#XmlFormat(queryBrands.brand)#"
                      isAssignable="#queryBrands.isAssignable#"
                      abbreviation="#queryBrands.abbreviation#" />
            </cfloop>
        </nodes>
    </cfoutput>
</cfxml>

<cfxml variable="xslt">
    <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="/nodes">
            <nodes>
                <xsl:call-template name="getChildNodes" />
            </nodes>
        </xsl:template>

        <xsl:template name="getChildNodes">
            <xsl:param name="parentID" select="0" />

            <xsl:for-each select="//node[ @parentID = $parentID ]">
                <xsl:sort select="@name" />

                <node id="{@id}"
                      parentID="{@parentID}"
                      name="{@name}"
                      isAssignable="{@isAssignable}"
                      abbreviation="{@abbreviation}">
                      <xsl:call-template name="getChildNodes">
                        <xsl:with-param name="parentID" select="@id" />
                      </xsl:call-template>
                </node>
            </xsl:for-each>
        </xsl:template>
    </xsl:transform>
</cfxml>

<cfset result = xmlTransform(rawNodeTree, xslt) />

我相信当我在研究如何解决这个问题时我使用了同样的问题 http:// /www.bennadel.com/blog/1080-Recursive-XSLT-For-Nested-XML-Nodes-In-ColdFusion.htm 来帮助我。

另一种选择是使用 CTE 进行查询,然后使用其中的字段构建您的 xml。 (如果您使用的是 ms sql server)

Take a look at the code I created using xslt transformation, I'm sure you can use the same approach in your code (note that parentID in my query is a foreign key of brandID):

<cfquery name="queryBrands" datasource="#dsn#">
    SELECT brandID, brand, isAssignable, isnull(parentID, 0) AS parentID, abbreviation
    FROM dbo.BrandTree
</cfquery>


<cfxml variable="rawNodeTree">
    <cfoutput>
        <nodes>
            <cfloop query="queryBrands">
                <node id="#queryBrands.brandID#"
                      parentID="#queryBrands.parentID#"
                      name="#XmlFormat(queryBrands.brand)#"
                      isAssignable="#queryBrands.isAssignable#"
                      abbreviation="#queryBrands.abbreviation#" />
            </cfloop>
        </nodes>
    </cfoutput>
</cfxml>

<cfxml variable="xslt">
    <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="/nodes">
            <nodes>
                <xsl:call-template name="getChildNodes" />
            </nodes>
        </xsl:template>

        <xsl:template name="getChildNodes">
            <xsl:param name="parentID" select="0" />

            <xsl:for-each select="//node[ @parentID = $parentID ]">
                <xsl:sort select="@name" />

                <node id="{@id}"
                      parentID="{@parentID}"
                      name="{@name}"
                      isAssignable="{@isAssignable}"
                      abbreviation="{@abbreviation}">
                      <xsl:call-template name="getChildNodes">
                        <xsl:with-param name="parentID" select="@id" />
                      </xsl:call-template>
                </node>
            </xsl:for-each>
        </xsl:template>
    </xsl:transform>
</cfxml>

<cfset result = xmlTransform(rawNodeTree, xslt) />

I believe when I was researching how to solve this same issue I used http://www.bennadel.com/blog/1080-Recursive-XSLT-For-Nested-XML-Nodes-In-ColdFusion.htm to help me out.

Another option is to use CTE for your query then use fields from that to build your xml. (if you're using ms sql server)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文