Создание иерархической XML-структуры с ColdFusion - PullRequest
2 голосов
/ 01 марта 2011

Может кто-нибудь помочь мне улучшить это? Там должен быть лучший путь. То, что я делаю, - это создание локального веб-сервиса для гибкого захвата, чтобы заполнить древовидное меню. 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 Ответ

2 голосов
/ 01 марта 2011

Посмотрите на код, который я создал с помощью преобразования 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)

...