API tr tree - noradle/plsql-print GitHub Wiki

tree 模板预解析一次,重复使用,提升性能

tr is synonym for tree

  • sys_refcursor 版本提供代码简洁性
  • 提供用于在 for-loop 中带入st变量重复调用的版本,允许在准备带入数据阶段进行更复杂的数据处理,包括条用其他plsql function

synopsis for all types

  • tree.p/o/r-st-loop/c
  • tree.p/o/rc/c
  • tree.prc
  • tree.n(level,'text')
  • tree.n(' ', 'text')
  • tree.n(' text')

regular version

synopsis

  • tr.p('<li class="@"><a href="@">@</a>|<ul>|</ul>|</li>', tmp.stv); (parse)
  • tr.o(true); (open list)
  • tr.r(i.level, tmp.stv, st(v1, v2, ...)); (render a record of data)
  • tr.c(tmp.stv); (close list)

说明:

  • 基于输出 list 版本的 m.p, m.r,进行一些调整来支持 hiearchical tree
  • m.p 模板分成四个部分,使用 | 来分割,分别代表:调试模板、子列表开、子列表结束、条目结束
  • 任意 cursor,但是第一个字段必须是代表节点所处层级的数值。
  • 和 m.r 相似,tr.r(render) 增加一个 level 参数,noradle 根据 level 来嵌套标签结构
  • 循环调用 tr.r 前必须先执行 tr.o (render open),进行内部状态初始化,并且可以通过参数设置是否进行 pretty 输出(也就是按照层级缩进)
  • 循环调用 tr.r 后必须执行 tr.c (render close),将剩余的尾部输出
  • 每次调用 tr.r 只输出一个条目,应用自己根据需要在loop前后添加 wrapper 标签,比如说条目是<li>的话,用<ul>包上
procedure parse_render_in_loop is
  cur sys_refcursor;
begin
  src_b.header;
  x.p('<h2>', 'use tree.p, tree.o, tree,r, tree.c to print tree');

  x.o('<ul>');
  tr.p(' <li class="xing-@"><a href="see?pid=@">@</a>|<ul>|</ul>|</li>', tmp.stv);
  tr.o(true);
  for a in (select level, substr(a.name, 1, 1), a.pid, a.name
              from emp_t a
             start with a.name = 'Li Xinyan'
            connect by a.ppid = prior a.pid) loop
    tr.r(a.level, tmp.stv, st(substr(a.name, 1, 1), a.pid, a.name));
  end loop;
  tr.c;
  x.c('</ul>');
end;

produce

<h2>use tree.p, tree.o, tree,r, tree.c to print tree</h2>
<ul>
<li class="xing-L"><a href="see?pid=3">Li Xinyan</a><ul>
 <li class="xing-L"><a href="see?pid=1">Li Yong</a><ul>
  <li class="xing-L"><a href="see?pid=4">Li Fushun</a></li>
  <li class="xing-X"><a href="see?pid=5">Xu Meixi</a></li></ul></li>
 <li class="xing-W"><a href="see?pid=2">Wang Wenyan</a></li></ul></li>
</ul>

使用 cursor 替换 st-in-loop

synopsis

tr.rc(tmp.stv, sys_refcursor) (render cursor)

  • 可以不在 loop 中调用 tr.r,而直接调用 tr.rc (render cursor)
  • sys_refcursor 第一个字段代表层级数,后面的字段为带入模板的数据
procedure parse_open_render_cur_close is
  cur sys_refcursor;
begin
  src_b.header;
  x.p('<h2>', 'use tree.rc(sys_refcursor) to print tree');
  open cur for
    select level, substr(a.name, 1, 1), a.pid, a.name
      from emp_t a
     start with a.name = 'Li Xinyan'
    connect by a.ppid = prior a.pid;
  x.o('<ul>');
  tr.p('<li class="xing-@"><a href="see?pid=@">@</a>|<ul>|</ul>|</li>', tmp.stv);
  tr.o(true);
  tr.rc(tmp.stv, cur);
  tr.c(tmp.stv);
  x.c('</ul>');
end;

produce

<h2>use tree.rc(sys_refcursor) to print tree</h2>
<ul>
<li class="xing-L"><a href="see?pid=3">Li Xinyan</a><ul>
 <li class="xing-L"><a href="see?pid=1">Li Yong</a><ul>
  <li class="xing-L"><a href="see?pid=4">Li Fushun</a></li>
  <li class="xing-X"><a href="see?pid=5">Xu Meixi</a></li></ul></li>
 <li class="xing-W"><a href="see?pid=2">Wang Wenyan</a></li></ul></li>
</ul>

直接使用 tr.prc 一站式输出 tree

synopsis

tr.prc('<li><span>@</span>|<ul>|</ul>|</li>', sys_refcursor[, fmt_date, pretty, indent]); (parse & render cursor)

  • 在 tr.rc 基础上,可以一步完成全部树的输出,tr.prc(parse render cursor)
  • 无需调用 tr.p, tr.o, tr.c, tr.prc 会在内部自动调用上述API
  • tr.prc 的参数包含 tr.p(indent), tr.o(pretty) 的参数
procedure parse_render_cur_united is
  cur sys_refcursor;
begin
  src_b.header;
  x.p('<h2>', 'use tree.prc(sys_refcursor) to print tree in one step');
  open cur for
    select level, substr(a.name, 1, 1), a.name
      from emp_t a
     start with a.name = 'Li Xinyan'
    connect by a.ppid = prior a.pid;
  x.o('<ul>');
  tr.prc('<li class="xing-@"><b>@</b>|<ul>|</ul>|</li>', cur, pretty => true);
  x.c('</ul>');
end;

produce

<h2>use tree.prc(sys_refcursor) to print tree in one step</h2>
<ul>
<li class="xing-L"><b>Li Xinyan</b><ul>
 <li class="xing-L"><b>Li Yong</b><ul>
  <li class="xing-L"><b>Li Fushun</b></li>
  <li class="xing-X"><b>Xu Meixi</b></li></ul></li>
 <li class="xing-W"><b>Wang Wenyan</b></li></ul></li>
</ul>

use node version

synopsis

  • tr.n(3, 'text') level number and item text

  • tr.n(' ', 'text') length of first string stand for level

  • tr.n(' text') indent of text stand for level, indent will be striped

  • since tr.n specified node level, you can use m.r to render item text with substitute st values

tr.n(level, m.r(st, st)) in loop

procedure hier_node_level_in_loop is
  cur sys_refcursor;
begin
  src_b.header;
  x.p('<h2>', 'use tree.p, tree.o, tree,r, tree.n(by level), tree.c to print tree');
  x.o('<ul>');
  tr.p('<li class="xing-@"><a href="see?pid=@">@</a>|<ul>|</ul>|</li>', tmp.stv);
  tr.o(true);
  for a in (select level, substr(a.name, 1, 1), a.pid, a.name
              from emp_t a
             start with a.name = 'Li Xinyan'
            connect by a.ppid = prior a.pid) loop
    tr.n(a.level, m.r(tmp.stv, st(substr(a.name, 1, 1), a.pid, a.name)));
  end loop;
  tr.c;
  x.c('</ul>');
end;

produce

<h2>use tree.p, tree.o, tree,r, tree.n(by level), tree.c to print tree</h2>
<ul>
<li class="xing-L"><a href="see?pid=3">Li Xinyan</a><ul>
 <li class="xing-L"><a href="see?pid=1">Li Yong</a><ul>
  <li class="xing-L"><a href="see?pid=4">Li Fushun</a></li>
  <li class="xing-X"><a href="see?pid=5">Xu Meixi</a></li></ul></li>
 <li class="xing-W"><a href="see?pid=2">Wang Wenyan</a></li></ul></li>
</ul>

all types not in loop

procedure hier_node_all_types is
begin
  src_b.header;
  x.p('<h2>', 'use tree.p, tree.o, tree.n(all types), tree.c to print tree');
  x.o('<ul>');
  tr.o(true);

  tr.n(1, '<li>' || x.a('<a>', 'file', '#'));
  tr.n(2, '<li>' || x.a('<a>', 'new', '#'));
  tr.n(2, '<li>' || x.a('<a>', 'open', '#'));
  tr.n(2, '<li>' || x.a('<a>', 'close', '#'));
  tr.n(3, '<li>' || x.a('<a>', 'close all', '#'));
  tr.n(3, '<li>' || x.a('<a>', 'close current', '#'));
  tr.n(2, '<li>' || x.a('<a>', 'save', '#'));
  tr.n(3, '<li>' || x.a('<a>', 'save all', '#'));
  tr.n(3, '<li>' || x.a('<a>', 'save current', '#'));

  tr.n(' ', '<li>' || x.a('<a>', 'file', '#'));
  tr.n('  ', '<li>' || x.a('<a>', 'new', '#'));
  tr.n('  ', '<li>' || x.a('<a>', 'open', '#'));
  tr.n('  ', '<li>' || x.a('<a>', 'close', '#'));
  tr.n('   ', '<li>' || x.a('<a>', 'close all', '#'));
  tr.n('   ', '<li>' || x.a('<a>', 'close current', '#'));
  tr.n('  ', '<li>' || x.a('<a>', 'save', '#'));
  tr.n('   ', '<li>' || x.a('<a>', 'save all', '#'));
  tr.n('   ', '<li>' || x.a('<a>', 'save current', '#'));

  tr.n(' <li>' || x.a('<a>', 'file', '#'));
  tr.n('  <li>' || x.a('<a>', 'new', '#'));
  tr.n('  <li>' || x.a('<a>', 'open', '#'));
  tr.n('  <li>' || x.a('<a>', 'close', '#'));
  tr.n('   <li>' || x.a('<a>', 'close all', '#'));
  tr.n('   <li>' || x.a('<a>', 'close current', '#'));
  tr.n('  <li>' || x.a('<a>', 'save', '#'));
  tr.n('   <li>' || x.a('<a>', 'save all', '#'));
  tr.n('   <li>' || x.a('<a>', 'save current', '#'));

  tr.n(' <li>', x.a('<a>', 'file', '#'));
  tr.n('  <li>', x.a('<a>', 'new', '#'));
  tr.n('  <li>', x.a('<a>', 'open', '#'));
  tr.n('  <li>', x.a('<a>', 'close', '#'));
  tr.n('   <li>', x.a('<a>', 'close all', '#'));
  tr.n('   <li>', x.a('<a>', 'close current', '#'));
  tr.n('  <li>', x.a('<a>', 'save', '#'));
  tr.n('   <li>', x.a('<a>', 'save all', '#'));
  tr.n('   <li>', x.a('<a>', 'save current', '#'));

  tr.c;
  x.c('</ul>');
end;

produce

<h2>use tree.p, tree.o, tree.n(all types), tree.c to print tree</h2>
<ul>
<li><a href="#">file</a><ul>
 <li><a href="#">new</a></li>
 <li><a href="#">open</a></li>
 <li><a href="#">close</a><ul>
  <li><a href="#">close all</a></li>
  <li><a href="#">close current</a></li></ul></li>
 <li><a href="#">save</a><ul>
  <li><a href="#">save all</a></li>
  <li><a href="#">save current</a></li></ul></li></ul></li>
<li><a href="#">file</a><ul>
 <li><a href="#">new</a></li>
 <li><a href="#">open</a></li>
 <li><a href="#">close</a><ul>
  <li><a href="#">close all</a></li>
  <li><a href="#">close current</a></li></ul></li>
 <li><a href="#">save</a><ul>
  <li><a href="#">save all</a></li>
  <li><a href="#">save current</a></li></ul></li></ul></li>
<li><a href="#">file</a><ul>
 <li><a href="#">new</a></li>
 <li><a href="#">open</a></li>
 <li><a href="#">close</a><ul>
  <li><a href="#">close all</a></li>
  <li><a href="#">close current</a></li></ul></li>
 <li><a href="#">save</a><ul>
  <li><a href="#">save all</a></li>
  <li><a href="#">save current</a></li></ul></li></ul></li>
<li><a href="#">file</a><ul>
 <li><a href="#">new</a></li>
 <li><a href="#">open</a></li>
 <li><a href="#">close</a><ul>
  <li><a href="#">close all</a></li>
  <li><a href="#">close current</a></li></ul></li>
 <li><a href="#">save</a><ul>
  <li><a href="#">save all</a></li>
  <li><a href="#">save current</a></li></ul></li></ul></li>
</ul>
⚠️ **GitHub.com Fallback** ⚠️