cgicc:同一元素的多层次

时间:2011-10-31 16:47:15

标签: cgi structure gnu

我从cgicc开始,让我保持代码短而干净。但现在我在挣扎。我希望有类似的东西:

<ul>
  <li>
    <a href="#" ><span>Main 1</span></a>
    <ul>
      <li><a href="ref1-1" ><span>Sub 1</span></a></li>
      <li><a href="ref1-2" ><span>Sub 2</span></a></li>
      <li><a href="ref1-3" ><span>Sub 3</span></a></li>
    </ul>
  </li>
  <li>
    <a href="#" ><span>Main 2</span></a>
    <ul>
      <li><a href="ref2-1" ><span>Sub 1</span></a></li>
      <li><a href="ref2-2" ><span>Sub 2</span></a></li>
      <li><a href="ref2-3" ><span>Sub 3</span></a></li>
    </ul>
  </li>
</ul>

内部块非常大,因此我不想组合这些调用。我这样的第一个尝试(我希望我编码好):

cout << ul() << endl;
  cout << li() << endl;
    cout << a("Main 1").set("href", "#") << endl;
    cout << ul() << endl; // <-- must fail here!
      cout << li(a("Sub 1").set("href", "ref1-1")) << endl;
      cout << li(a("Sub 2").set("href", "ref1-2")) << endl;
      cout << li(a("Sub 3").set("href", "ref1-3")) << endl;
    cout << ul() << endl;
  cout << li() << endl;
  cout << li() << endl;
    cout << a("Main 2").set("href", "#") << endl;
    cout << ul() << endl;
      cout << li(a("Sub 1").set("href", "ref2-1")) << endl;
      cout << li(a("Sub 2").set("href", "ref2-2")) << endl;
      cout << li(a("Sub 3").set("href", "ref2-3")) << endl;
    cout << ul() << endl;
  cout << li() << endl;
cout << ul() << endl;

问题是像&lt;元素这样的元素的布尔状态。 ul&gt;和&lt; li>那么,是否有最佳实践和智能解决方案来处理这个问题? - 安迪

编辑:我的新解决方案:附加元素类“简单”:

#include <cgicc/HTMLElement.h>
#include <cgicc/HTMLAttributeList.h>

template<class Tag>
class HTMLSimpleElement : public cgicc::HTMLElement
{
public:
  HTMLSimpleElement() : HTMLElement(0, 0, 0, EElementType(-1))
  {}

  HTMLSimpleElement(const cgicc::HTMLAttributeList& attributes) : HTMLElement(&attributes, 0, 0, EElementType(-1))
  {}

  virtual ~HTMLSimpleElement() {}

  virtual inline HTMLElement* clone() const
  { return new HTMLSimpleElement<Tag>(*this); }

  virtual inline const char* getName() const
  { return Tag::getName(); }

  virtual void render(std::ostream& out) const
  {
    const cgicc::HTMLAttributeList* attributes = getAttributes();

    out << '<' << getName();

    if (attributes != NULL)
    {
      out << ' ';
      attributes->render(out);
    }

    out << ">";
  }
};

#define TAG(name, tag) \
class name##Tag   \
{ public: inline static const char* getName() { return tag; } }

#define SIMPLE_ELEMENT(name, tag) \
TAG(name, tag); typedef HTMLSimpleElement<name##Tag> name

SIMPLE_ELEMENT (divB, "div");
SIMPLE_ELEMENT (divE, "/div");

// and so on... 

这样我可以使用成员函数并完全控制BEGIN和END标记。 还有其他更聪明的解决方案吗?

1 个答案:

答案 0 :(得分:2)

这有点古老,你可能已经找到了答案,但如果他们遇到同样的问题,它可以帮助别人。

您的第二个代码块不正确。当您使用cgicc标记标记时,它会输出整个标记,包括包含的子标记。没有被包围的孩子,国家被记忆并与每个建筑交换。这意味着要堆叠它们,您应该使用组装为树的对象。 有关简化示例,请采用此缩短的所需输出:

<ul>
  <li>
    <a href="#" ><span>Main 1</span></a>
    <ul>
      <li><a href="ref1-1" ><span>Sub 1</span></a></li>
      <li><a href="ref1-2" ><span>Sub 2</span></a></li>
      <li><a href="ref1-3" ><span>Sub 3</span></a></li>
    </ul>
  </li>
</ul>

如果您尝试使用cgicc代码:

cout << ul() << endl;
  cout << li() << endl;
    cout << a("Main 1").set("href", "#") << endl;
    cout << ul() << endl; // <-- must fail here!
      cout << li(a("Sub 1").set("href", "ref1-1")) << endl;
      cout << li(a("Sub 2").set("href", "ref1-2")) << endl;
      cout << li(a("Sub 3").set("href", "ref1-3")) << endl;
    cout << ul() << endl;
  cout << li() << endl;
cout << ul() << endl;

你会得到这个混乱,这是不正确的html:

<ul>
<li>
<a href="#" >Main 1</a>
</ul>
<li><a href="ref1-1" >Sub 1</a></li>
<li><a href="ref1-2" >Sub 2</a></li>
<li><a href="ref1-3" >Sub 3</a></li>
<ul>
</li>
</ul>

您可能应该以更加面向对象的方式处理此问题,跟踪用于构建页面的对象,如此(指针将跟踪新添加的子项,并且将避免制作不必要的副本;没有指针,你需要确保以正确的顺序添加标签):

ul* outerList = new ul();
li* outerItem = new li();
ul* innerList = new ul();

outerList->add(outerItem);
outerItem->add(a(span("Main 1")).set("href", "#"));
outerItem->add(innerList);
innerList->add(li(a(span("Sub 1")).set("href", "ref1-1")));
innerList->add(li(a(span("Sub 2")).set("href", "ref1-2")));
innerList->add(li(a(span("Sub 3")).set("href", "ref1-3")));

cout << *outerList << endl;

您还可以使用构造函数和添加和设置方法动态构建它们:

cout << ul(li().add(a(span("Main 1")).set("href", "#")).add(ul().add(li(a(span("Sub 1")).set("href", "ref1-1"))).add(li(a(span("Sub 2")).set("href", "ref1-2"))).add(li(a(span("Sub 3")).set("href", "ref1-3"))))) << endl;

这可以说不太清楚,难以理解,难以调试,更容易犯错误;你可以通过一些换行和缩进来缓解它,但我不知道它会有多大帮助。

将HTML视为层次结构。我总是在使用XHTML和libxml时度过更好的时光。