无法解决这个html生成难题

时间:2015-05-05 21:23:29

标签: c# html algorithm

我有Tree我执行depth-first算法。它按照元素应该在HTML中的顺序创建树的list

我使用它来generate the HTML显示在视图上。 (作为问题的每个元素都有2个元素,答案没有;答案是leaf;质疑branch

var html = "<ul>";

    foreach (var c in listWithElements)
    {
        html += "<li>";
        if (c is Question)
        {
            var v = (Question)c;
            html += v.Content + "<ul>";
        }
        else
        {
            var t = (Answer)c;
            html += t.Content + "</li>";
        }
    }
return html + "</ul>";

这会产生一个完美的结构:

<ul>
    <li>QUESTION
        <ul>
            <li>QUESTION
                <ul>
                    <li>ANSWER</li>
                    <li>ANSWER</li>
              **</ul>**
            <li>QUESTION
                <ul>
                    <li>ANSWER</li>
                    <li>QUESTION
                        <ul>
                            <li>QUESTION
                                <ul>
                                    <li>ANSWER</li>
                                    <li>ANSWER</li>
                              **</ul>**
                            <li>ANSWER</li>
                      **</ul>**   
                    </li>
              **</ul>**
            </li>
      **</ul>**
    </li>
    <li>ANSWER</li>
</ul>

除了HTML生成部分不创建 ul 结束标记。这不是我没有尝试过,只是我似乎无法找到一个模式来确定插入它们的时间/位置。我暂时添加了结束标记,以便更清楚地显示它们的位置。

我能找到的唯一模式是:标签应放在第二个DIRECT li子的ul结束标签之后。

任何帮助?

3 个答案:

答案 0 :(得分:3)

你做不到。您需要有关每个节点的更多信息。例如,如果你看一下这个位:

> <ul>
>                                     <li>ANSWER</li>
>                                     <li>ANSWER</li>
>                               **</ul>**
>                             <li>ANSWER</li>

您的代码无法“知道”那里应该有“ / ul ”。通过循环,没有给出足够的信息。你需要在Answer对象上有一些标记,上面写着“这是当前组中的最后一个答案”或者什么。

答案 1 :(得分:2)

你可以做这样的事情:(我在小提琴样本中进行了测试,看起来效果很好)

var html = "<ul>";
var stack = [];
var pointer = 0;
stack.push(0);
    foreach (var c in listWithElements)
    {
      while (stack[pointer]==2&& pointer>0){
        html += "</ul>";
        stack.pop();
        pointer--;
      }
        stack[pointer]++;
        html += "<li>";
        if (c is Question)
        {
            stack.push(0);
            pointer++;
            var v = (Question)c;
            html += v.Content + "<ul>";

        }
        else
        {
            var t = (Answer)c;
            html += t.Content + "</li>";

        }
    }
return html + "</ul>";

工作小提琴示例 - fiddle

编辑:这个解决方案适用于JS,但它在C#中与列表相同:

static void Main(string[] args)
{

    Console.WriteLine("<ul>");
    string[] listWithElements = { "q", "a", "a", "q", "a", "q", "a", "a", "q" };

    List<int> stack = new List<int>();

    stack.Add(0);
    foreach (var c in listWithElements)
    {

        while (stack[stack.Count() - 1] == 2 && stack.Count() > 1)
        {
            Console.WriteLine("</ul>");
            stack.RemoveAt(stack.Count() - 1);
        }

        stack[stack.Count() - 1]++;

        Console.WriteLine("<li>");
        if (listWithElements[stack.Count() - 1] == "q")
        {
            stack.Add(0);
            Console.WriteLine("qqq");
            Console.WriteLine("<ul>");
        }
        else
        {
            Console.WriteLine("aaa");
            Console.WriteLine("</li>");
        }
    }
    Console.WriteLine("</ul>");

}

答案 2 :(得分:1)

使用depthfirst搜索会非常简单。如果您更深入一步(远离根),则打印开始标记和您现在所在节点的内容。如果你走出一步(到根),则在执行该步骤之前打印节点的结束标记。只需省略将树转换为列表的步骤,事情变得非常简单。

define node: {string content}
define question: node AND {node right , node left}
define answer: node

define toHTML:
input: node root
output: string html

list visited
stack stack

push(stack , root)
add(visited , root)

while ! isEmpty(stack)
     node n = first(stack)

     add(visited , n)    
     append(getContent(n))

     if isAnswer(n)
          remove(stack , n)
     else
          question q = (question) n

          if contains(visited , q.left)
               if contains(visited , q.right)
                     pop(stack)
                     append(html , closingTag(q))//append the closingtag of the question
               else
                     push(stack , q.right)
          else
               push(stack , q.left)