Cte, который создает вложенные списки HTML - PullRequest
3 голосов
/ 04 мая 2011

У меня есть следующий cte:

WITH cte AS
(
        SELECT 
            c.ParentIDNo,  
            c.Category,
            c.ChildCategory,
            c.WSWebProductNameIDNo, 
            c.IDNo, 
            0 AS Level,
            CAST('/' + c.Category AS VARCHAR(1000)) as CteName
        FROM WSWebCategory as c
        WHERE c.ParentIDNo IS NULL

        UNION ALL

        SELECT   
            t.ParentIDNo, 
            t.Category,
            t.ChildCategory, 
            t.WSWebProductNameIDNo,
            t.IDNo, 
            cte.Level + 1 AS Level,
            CAST(cte.CteName + '/' + t.ChildCategory AS VARCHAR(1000)) AS CteName
        FROM WSWebCategory t
        INNER JOIN cte ON t.ParentIDNo = cte.IDNo
    )
    SELECT *, REPLICATE('----', Level) + CteName as CteName FROM cte
    ORDER BY cte.CteName

, который дает мне список вроде:

    /Apparatus
    ----/Apparatus/Autoclaves
    --------/Apparatus/Autoclaves/ALL-AMERICAN Portable Sterilizers (WAFCO)
    --------/Apparatus/Autoclaves/Autoclave Accessories
    ------------/Apparatus/Autoclaves/Autoclave Accessories/Clavies® Autoclave Gloves (Bel-Art Scienceware)
    ------------/Apparatus/Autoclaves/Autoclave Accessories/Grabbit™ Temp Mitts (Heathrow Scientific)
    ------------/Apparatus/Autoclaves/Autoclave Accessories/Odo-Clave® Deodorant Pads (Bel-Art Scienceware)
    --------/Apparatus/Autoclaves/Autoclave Bags
    ------------/Apparatus/Autoclaves/Autoclave Bags/Autoclavable Biohazard Disposal Bags (Bel-Art Scienceware)
    ------------/Apparatus/Autoclaves/Autoclave Bags/Autoclavable Biohazard Disposal Bags (Gosselin)
    ------------/Apparatus/Autoclaves/Autoclave Bags/Autoclavable Hi-Temp Biohazard Disposal Bags (Bel-Art Scienceware)
    ------------/Apparatus/Autoclaves/Autoclave Bags/Chex-All® II Sterilization Pouches (Propper)
    ------------/Apparatus/Autoclaves/Autoclave Bags/Clavies® Autoclave Gloves (Bel-Art Scienceware)
    ------------/Apparatus/Autoclaves/Autoclave Bags/Clavies® Bag Holder (Bel-Art Scienceware)
    ------------/Apparatus/Autoclaves/Autoclave Bags/Clavies® General Purpose Autoclavable Bags (Bel-Art Scienceware)
    ------------/Apparatus/Autoclaves/Autoclave Bags/Poxygrid® Biohazard Bag Holder (Bel-Art Scienceware)

но мне нужно множество вложенных html-списков:

<ul> 
<li>Apparatus
   <ul> 
    <li>Autoclaves
        <ul>   
            <li>ALL-AMERICAN Portable Sterilizers (WAFCO)</li> 
            <li>Autoclave Accessories
                <ul>
                    <li>Clavies® Autoclave Gloves (Bel-Art Scienceware)</li>
                    <li>Grabbit™ Temp Mitts (Heathrow Scientific)</li>
                    <li>Odo-Clave® Deodorant Pads (Bel-Art Scienceware) </li>
                </ul>
            </li>
            <li>Autoclave Bags
                <ul>
                    <li>Autoclavable Biohazard Disposal Bags (Bel-Art Scienceware)</li>
                    <li>Autoclavable Biohazard Disposal Bags (Gosselin)</li>
                    <li>Autoclavable Hi-Temp Biohazard Disposal Bags (Bel-Art Scienceware)</li>
                    <li>Chex-All® II Sterilization Pouches (Propper)</li>
                    <li>Clavies® Autoclave Gloves (Bel-Art Scienceware)</li>
                    <li>Clavies® Bag Holder (Bel-Art Scienceware)</li>
                    <li>Clavies® General Purpose Autoclavable Bags (Bel-Art Scienceware)</li>
                    <li>Poxygrid® Biohazard Bag Holder (Bel-Art Scienceware)</li>
                </ul>
            </li>
        </ul>
    </li> 
    </ul>
</li>
</ul> 

Я в тупик, как это сделать!

Ответы [ 2 ]

0 голосов
/ 21 апреля 2015

Четыре года спустя ...

псевдокод:

previousLevel = -1;

for each item in items

  if item.level > previousLevel
    print "<ul>"

  if item.level < previousLevel
    print repeat("</ul>", previousLevel - item.level)

  print "<li>" + item.text + "</li>"

  previousLevel = item.level

end for

print repeat("</ul>", previousLevel + 1)

JSP / JSTL:

<c:set var="previousLevel" value="-1"/>

<c:forEach items="${items}" var="item">

    <c:if test="${ item.level > previousLevel }">
        <ul>
    </c:if>

    <c:if test="${ item.level < prevLevel }">
        ${xfn:repeat("</ul>", previousLevel - item.level)}
    </c:if>

    <li>${item.text}</li>

    <c:set var="previousLevel" value="${item.level}"/>

</c:forEach>

<c:if test="${previousLevel > -1}">
    ${xfn:repeat("</ul>",  previousLevel + 1 )}
</c:if>

Где xfn:repeat - функция tld для любой функции повтора строки

0 голосов
/ 10 мая 2011

Есть ли какая-то причина, по которой вы не можете просто разобрать его на обратной стороне, используя какой-либо язык программирования более высокого уровня?

Может показаться, что ваши данные являются отличным кандидатом для вывода XML (используя SELECT ... FOR XML EXPLICIT.) Кажется, ваши данные настроены идеально для этого, что может быть легко проанализировано чем-то на стороне вашего приложения.

Помимо этого, вы, вероятно, могли бы добавить теги элементов списка, используя объединение результатов и удаление тега в следующем цикле CTE, прежде чем читать его в расширенном тексте. Однако закрывающие теги станут проблемой, так как я не верю, что CTE рекурсивно отступит назад, чтобы позволить вам закрыть их.

...