XML卷之实战锦囊(5):结构树图

2016-02-19 22:27 8 1 收藏

关注图老师设计创意栏目可以让大家能更好的了解电脑,知道有关于电脑的更多有趣教程,今天给大家分享XML卷之实战锦囊(5):结构树图教程,希望对大家能有一点小小的帮助。

【 tulaoshi.com - Web开发 】

  动机:
  最初想起做二叉树是因为需要做一个公司结构图。 以前的做法都是直接用图象软件画出来一个图片。很好看,但每次有变动后都需要重新画一个新的。 另一方面,网页上对线条的显示、布局相当局限。根据动态生成的数据进行排版、定位都相当困难, 而且在美观上也差强人意。 做了各种尝试以后,决定用XML+XSL作数据运算; 用VML来美化线条,用JAVASCRIPT来给对象定位。

  材料:
  XML卷之结构树图
  有2个文件:flow2.xml 和 flow2.xsl 
  效果:
  浏览这里 
  讲解:
  二叉树思路(1)

  html xmlns:v="urn:schemas-microsoft-com:vml"
  STYLE
  v:* { BEHAVIOR: url(#default#VML) }
  /STYLE
  v:group id="group1" name="group1" coordsize = "100,100"
  …
  /v:group
  以上这些都是VML的基本格式,我就不详细讲解了。

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  XML是树型结构,我们读取每个数据就需要对这个
  XML数据树进行遍历。而递归运算是XSL优势之一。
  我也是在用其它多种方法进行遍历运算失败后才
  决定使用XSL的。

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  FlowRoot
  vcTitle二叉树--结构图/vcTitle
  AuthorSailflying/Author
  Emailsailflying@163.net/Email
  FlowNode
  iProcess1/iProcess
  vcCourse第一个节点/vcCourse
  iNextYes
  FlowNode
  iProcess2/iProcess
  vcCourse第二个节点/vcCourse
  iNextYes…/iNextYes
  iNextNo…/iNextNo
  /FlowNode
  /iNextYes
  iNextNo
  FlowNode
  iProcess3/iProcess
  vcCourse第三个节点/vcCourse
  iNextYes…/iNextYes
  iNextNo…/iNextNo
  /FlowNode
  /iNextNo
  /FlowNode
  /FlowRoot

  
  逻辑上很简单,当前节点(1)下面有两个子节点(2,3)。
  只需要将节点2和节点3定位在节点1的左下方和右下方就可以了。
  这里我将左右节点的连接线分别用了绿色和红色,方便显示。

  
  前面我们说到了XSL的递归功能,为了更清楚的看到每一个详细的
  显示步骤,只需要仿照下面的代码,加一个alert语句就可以了。

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  xsl:template match="FlowNode"
  …
  SCRIPT language="JavaScript1.2"
  …
  alert('逐步显示');
  …
  /SCRIPT
  …
  /xsl:template

  
  看了上面的慢动作,是否能让大家了解到我的思路。

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  
  二叉树思路(2)
  我的思路很简单:
  (1)读取当前节点的资料,用VML生成一个新的对象。
  给对象赋初始数值(如 name,id,style样式等)
  (2)用脚本控制来给当前对象定位
  (3)当前节点和它的父亲节点之间加箭头,线条。
  (4)继续找当前节点的子节点,一直循环定位到结束。
  也就是所有节点都遍历完毕,已经生成好了树。

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  
  xsl:template match="FlowNode"
  …
  xsl:apply-templates /
  …
  /xsl:template
  xsl:template match="iNextYes"
  xsl:apply-templates select="./FlowNode" /
  /xsl:template

  xsl:template match="iNextNo"
  xsl:apply-templates select="./FlowNode" /
  /xsl:template

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  整个递归过程就是靠上面这三个模块(template)来完成的。
  第一个template在匹配当前节点中每一个子节点的模板的时候
  调用了后面两个template; 而后面两个template又在具体执行
  的时候调用了第一个template ,这就相当于一个递归函数。

  语法:

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  要依次匹配当前节点中的每个子节点的模板,应使用该元
  素的基本形式 xsl:apply-templates /。
  否则,匹配的节点由 select 参数中 XPath 表达式的值决
  定,如 xsl:apply-templates select="./FlowNode" /

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  (1)和(2)的作用都是返回由 select 参数给出的表达式的字符串值。
  他们的搜索条件相同,所以返回的值也一样。
  只不过是使用的场合不同,他们的书写形式也就不一样。

  
  (1) xsl:value-of select="./iProcess/text()" /
  (2) {./iProcess/text()}

  
  这里定义了一些变量,节点的定位就是根据这些变量来调用运算公式的。

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  root_left //根的左边距=所有叶子的分配宽度(y*10) + 所有叶子的宽度(y*50) + 左边距基本值(10)
  root_top //根的上边距=上边距基本值(10)
  objOval //当前对象,是一个object
  objOval_iProcess //当前对象的步骤值
  objParentOval //当前对象的父节点,是一个object
  objParentOval_iProcess //当前对象父节点的步骤值
  objParent_name //当前对象父节点的名称
  Leaf_left //当前对象的所有子节点中的左边叶子数
  Leaf_right //当前对象的所有子节点中的右边叶子数
  Leaf_sum //当前对象的所有子节点中叶子数

  叶子:是指当前节点没有子节点

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  
  节点的定位公式:

  (1) 当前节点是根节点

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  //根的位置
  SobjOval.style.left=parseInt(root_left);
  SobjOval.style.top=parseInt(root_top);
  //parseInt() 函数的作用是取整数值,如果不是则为NAN
  //isNaN()函数的作用是判断parseInt取得的是否为整数

  
  (2)当前节点是父节点的左边子节点

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  1)判断的条件是: 当前对象父节点的名称='iNextYes'
  …
  2)如果存在右边子叶子,则公式为:
  当前节点的left=父节点的left - 当前节点的右边子叶子的总宽度- 当前节点的宽度

  3)如果不存在右边子叶子,但存在左边子叶子,则公式为:
  当前节点的left=父节点的left - 当前节点的左边子叶子的总宽度

  4)如果当前节点本身就是叶子,则公式为:
  当前节点的left=父节点的left - 当前节点的宽度
  …

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  (3)当前节点是父节点的右边子节点

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  1)判断的条件是: 当前对象父节点的名称='iNextNo'
  …
  2)如果存在左边子叶子,则公式为:
  当前节点的left=父节点的left + 当前节点的左边子叶子的总宽度 + 当前节点的宽度

  3)如果不存在左边子叶子,但存在右边子叶子,则公式为:
  当前节点的left=父节点的left + 当前节点的右边子叶子的总宽度

  4)如果当前节点本身就是叶子,则公式为:
  当前节点的left=父节点的left + 当前节点的宽度
  …

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  
  (2)和(3)的公式都是得到当前节点的left,我们还需要得到当前节点的top
  很简单的公式:当前节点的top=父节点的top + 偏移量(80)

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  
  二叉树思路(3)
  连接线条的定位思路:
  (1)找到当前节点和父节点的位置
  (2)判断当前节点是父节点的左边子节点,还是右边子节点
  (3)画线条

  
  这里定义了一些变量。

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  objOval //当前节点,是一个object
  objParentOval //当前对象的父节点,是一个object
  objLine //当前线条,是一个object

  
  线条的定位公式:

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  
  from="x1,y1" to="x2,y2" 是 VML 里定位线条的方式

  当前节点是父节点的左边子节点,则公式为:
  from = 父节点的left + 偏移量(15) , 父节点的top + 偏移量(32)
  to = 父节点的left + 偏移量(30) , 父节点的top - 偏移量(2)

  当前节点是父节点的右边子节点,则公式为:
  from = 父节点的left + 偏移量(35) ,父节点的top + 偏移量(32)
  to = 父节点的left + 偏移量(20) ,父节点的top - 偏移量(2)

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  
  我所能想到的也就这么多了。

  如果只是单纯的做一个公司结构图的话,会更简单很多。
  下面是赛扬的思路,我也是在他的基础上深入一点而已。

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  首先计算最下层节点个数,得出宽度,
  然后应该根据节点的从属关系计算其上层节点位置,递归。
  每一层级的节点要按从属关系先排序
  首先设“基本值”=节点应向右偏移量
  每个包含子节点的节点的left值等于它所拥有的节点所占宽度的一半加上基本值

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  后话:

  最近不知为何,网络一直都不好。断线的时间比在线的时间多。
  所以没对代码简化,其实,要完善的功能还有很多,比如:
  需要加右键菜单
  右键菜单内含新建节点、修改节点名称、改变关联关系等
  在每一个节点上都可右键打开这个节点的右键菜单
   

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  讲解:
  1)flow2.xml 是数据文件,相信大家都不会有问题。
  2)flow2.xsl 是格式文件,有几个地方要注意。 
  (1)脚本中:

  (1) xsl:value-of select="./iProcess/text()" / ;
  (2) {./iProcess/text()}

  (1)和(2)的作用都是返回由 select 参数给出的表达式的字符串值。
  他们的搜索条件相同,所以返回的值也一样。
  只不过是使用的场合不同,他们的书写形式也就不一样。
  xsl:apply-templates select="team" order-by="blue_ID"/
  比如我们想生成以下代码
  div 名称=“参数值”内容/div

  
  我们假设名称为“name”,参数值为XML数据中当前节点下面的子节点book的值

  
  第一种写法是先加属性名称,再加参数值
  div
  xsl:attribute name="name"
  xsl:value-of select="./book/text()"/ /xsl:attribute
  内容
  /div

  第二种写法是直接加属性名称和参数值
  div name="{./book/text()}"内容/div

  具体的使用你可以看我写的代码中的例子。

  XSL在正式的 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 的标准里

  xsl:value-of select="./book/text()"/
  作用是:只是把他的文本值写出来,而
  xsl:value-of select="./book"/
  是把他的文本值和他的所有子节点的内容显示出来。
  大家可以试验一下,输出一个有子节点的,一个无子节点的
  看看显示的结果是否相同。

  
  (2)需要注意:

  IE5 不支持 tag att="{xpath}"
  要用
  tagxsl:attribute name="att"xsl:value-of select="xpath"/xsl:attribute

  命名空间要用
  xmlns:xsl="http://www.w3.org/TR/WD-xsl"

  ?xml version="1.0" encoding="gb2312" ?
  另外说一点:
  在大多的XML教科书中所显示的代码中很少会加上encoding="gb2312" ,
  因此我们在XML中用到中文的时候会报错,原因就是没有写这个申明。

   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  
  后记:
  这里说的是一种思路。如果触类旁通,自然能够派上用场。 
  

来源:http://www.tulaoshi.com/n/20160219/1628362.html

延伸阅读
在前两篇文章中我们讨论了XML文件的读取和写入,但都是基于流模型的解决方案,今天我们就来谈谈在C#中如何实现DOM,DOM确实有它的不足,但在编程工作中它还是不可或缺的技术。下面我们来简单了解一下DOM的相关知识。 DOM的全称是Document Object Model(文档对象模型),它是来自W3C的官方标准,它允许按照W3C标准W3C DOM Level1和W3C...
标签: Web开发
html head meta http-equiv="Content-Type" content="text/html; charset=gb2312" title及联选择-用于权限选择比较合适/title /head body ul id="tree"     liinput type=checkbox         ul             liinput type=checkbox...
标签: SQLServer
  ********************************************************************* Author:黄山光明顶 mail:leimin@jxfw.com version:1.0.0 date:2004-1-30 (如需转载,请注明出处!,如果有问题请发MAIL给我:-)) ************************************************************************    我所讲的一个故事的背景是这样的...
.Alpha 通道   虽然Alpha通道不能完全实现PNG功能,但它确实能使图象和文字呈现半透明 效果,甚至可以实现渐变半透明效果。 filter: Alpha(Opacity=starting opacity level, FinishOpacity=finish opacity level, Style=gradient style,startX=gradient start X position, FinishX=gradient finish X position, Fini...
标签: ASP
  bigeagle】 于 2000-12-6 14:43:38 加贴在 Joy ASP ↑: 下面这种方法是大怪兽和怡红公子现在采用的方法 create table forum ( ID int NOT NULL IDENTITY,/*帖子序列号*/ rootID int NOT NULL, /*根帖子序列号*/ parentID int NOT NULL default=0,/*双亲帖子序列号*/ indent tinyint,/*缩进*/ order tinyint,/*同主题帖子排序*/ user...

经验教程

196

收藏

34
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部