使用ColdFusion创建分层xml结构

时间:2011-02-28 21:10:32

标签: xml coldfusion hierarchical

有人可以帮我改进吗?一定有更好的方法。我正在做的是构建一个本地Web服务,以便flex来抓取以填充树状菜单。作为我正在调用Web服务的应用程序的Flex只是一些背景,但与问题无关。

为了为这棵树创建分层数据,我编写了以下内容。

    <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>

正如您所看到的,我只是循环遍历不同的查询。虽然这适用于我的目的,我怎么能编码它,以便没有那么多的代码重复?

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

任何建议都会很棒!

1 个答案:

答案 0 :(得分:2)

看看我使用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)