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

动机:
最初想起做二叉树是因为需要做一个公司结构图。 以前的做法都是直接用图象软件画出来一个图片。很好看,但每次有变动后都需要重新画一个新的。 另一方面,网页上对线条的显示、布局相当局限。根据动态生成的数据进行排版、定位都相当困难, 而且在美观上也差强人意。 做了各种尝试以后,决定用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的基本格式,我就不详细讲解了。

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

<FlowRoot>
<vcTitle>二叉树--结构图</vcTitle>
<Author>Sailflying</Author>
<Email>sailflying@163.net</Email>
<FlowNode>
<iProcess>1</iProcess>
<vcCourse>第一个节点</vcCourse>
<iNextYes>
<FlowNode>
<iProcess>2</iProcess>
<vcCourse>第二个节点</vcCourse>
<iNextYes>…</iNextYes>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextYes>
<iNextNo>
<FlowNode>
<iProcess>3</iProcess>
<vcCourse>第三个节点</vcCourse>
<iNextYes>…</iNextYes>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextNo>
</FlowNode>
</FlowRoot>

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

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

<xsl:template match="FlowNode">

<SCRIPT language="JavaScript1.2">

alert('逐步显示');

</SCRIPT>

</xsl:template>

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

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

<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>

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

语法:

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

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

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

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

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 //当前对象的所有子节点中叶子数

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

节点的定位公式:

(1) 当前节点是根节点

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

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

1)判断的条件是: 当前对象父节点的名称='iNextYes'

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

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

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

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

1)判断的条件是: 当前对象父节点的名称='iNextNo'

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

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

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

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

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

这里定义了一些变量。

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

线条的定位公式:

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)

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

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

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

后话:

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

讲解:
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}">
要用
<tag><xsl: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中用到中文的时候会报错,原因就是没有写这个申明。

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

(0)

相关推荐

  • XML卷之实战锦囊(3):动态分页

    动机: 为了方便用户查看大批量数据,我们会用到动态分页,因此分页功能是我们在网站上见过的最普遍也是最常用的一个功能模块了.而以往的信息分页都是连接到数据库的,每一次点击都必须要后台数据库的支持.这样不但服务器的负担加重,而且严重的影响用户浏览的速度.试想,如果把分页的功能放到客户端,那会产生什么样的效果呢?呵呵,看看下面的设计吧! . 材料: XML卷之动态分页有2个文件:pages.xml 和 pages.xsl 作用: 把分页的功能放到客户端.在不刷新页面的情况下对数据进行过滤筛选,有效的提

  • XML卷之实战锦囊(2):动态查询

    动机: 查询功能是我们在网站上见过的最普遍也是最常用的一个功能模块了.以往的信息查询都是连接到数据库的,每一次点击都必须要后台数据库的支持.然而很多情况下用户往往只针对某一部分的数据进行操作,这样不但服务器的负担加重,而且严重的影响用户浏览的速度. 针对这种情况我们需要将用户需要的某一部分数据以XML的方式传递到客户端,用户对这些数据可以很方便的进行操作.既方便了用户,又减轻了服务器数据库的负担.何乐而不为呢!而且这项功能可以通用到其他众多模块,因此添加了这个动态查询功能. 材料: XML卷之动

  • XML卷之实战锦囊(1):动态排序

    动机: 排序功能让我们页面上的数据显的更人性化,是我们在网站上见过的很普遍的一个功能效果了.以往的自动排序都是用大量的脚本代码来完成的,对一般的爱好者来说这是件困难的事情.然而用XML来处理的话就简单多了.让自己的页面更加绚丽,哈哈,您是不是也心动了呢! 材料: XML卷之动态排序有2个文件:paixu.xml 和 paixu.xsl 作用: 在不刷新页面的情况下更据用户自己的需要对数据重新进行排序显示,有效的提高数据互动功能,让自己的页面更加绚丽多彩.  效果: 浏览这里  代码: paixu

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

    动机: 最初想起做二叉树是因为需要做一个公司结构图. 以前的做法都是直接用图象软件画出来一个图片.很好看,但每次有变动后都需要重新画一个新的. 另一方面,网页上对线条的显示.布局相当局限.根据动态生成的数据进行排版.定位都相当困难, 而且在美观上也差强人意. 做了各种尝试以后,决定用XML+XSL作数据运算: 用VML来美化线条,用JAVASCRIPT来给对象定位. 材料: XML卷之结构树图有2个文件:flow2.xml 和 flow2.xsl  效果: 浏览这里  讲解: 二叉树思路(1)

  • XML卷之实战锦囊(4):选单连动

    动机: 现在我们做个在IE里应用XML的一个小例子:解决双下拉选单的连动问题.大家最常见的可能就是选取省份后改变城市选项的例子了,那我们就来尝试着用XML来完成吧. 以前介绍的一些功能我是直接用XML+XSL文件来完成的,大家可能还不是很熟悉它的用法,所以我这次就用HMTL+XML来做,希望能够让大家更清楚的了解--"XML原来可以如此简单!":) 材料: XML卷之选单连动有2个文件:Citys.xml 和 CitySelect.htm 作用: 选择省份后可以自动显示相对应的城市,这

  • 关于html嵌入xml数据岛如何穿过树形结构关系的问题

    如下面的代码细节,html里面引用xml的数据岛,如何穿过树形结构的关系? 我不知道这个datafld里面应该如何使用xml里面的标签名称,如何加前缀,如何从resume得到name子元素?同时我的html文件应该如何修改呢? xml的数据文件是: XML code: 复制代码 代码如下: <?xml version="1.0" encoding="UTF-8"?> <resume> <name>mike</name>

  • XML入门精解之结构与语法

    现在我们暂且使用"记事本"来创建我们的XML文件吧.先看一个XML文件: 例1 〈?xml version="1.0" encoding="gb2312" ?〉 〈参考资料〉 〈书籍〉 〈名称〉XML入门精解〈/名称〉 〈作者〉张三〈/作者〉 〈价格 货币单位="人民币"〉20.00〈/价格〉 〈/书籍〉 〈书籍〉 〈名称〉XML语法〈/名称〉 〈!--此书即将出版--〉 〈作者〉李四〈/作者〉 〈价格 货币单位="

  • 初识XML基础知识

     XML定义: 用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. XML发展史? 简单提一下Markup Language历史: 1969:GML(Generalized Markup Language)--(IBMResearch) 1968: SGML(Standard Generalized Markup Language)--(ISO) 1989:HTML(Hypertext Markup Language)--T

  • 对比分析json及XML

    随着移动互联网时代的大潮,越来越多的App不光是需要和网络服务器进行数据传输和交互,也需要和其他 App 进行数据传递.承担App与网络来进行传输和存储数据的一般是XML或者JSON.在移动互联网时代,XML和JSON很重要. 最近一段时间,个人综合了之前对XML.JSON的一些了解,参考了相关资料,再结合视频的代码,把自己的一些思考融入了这篇总结文档中,同时尝试用通俗诙谐的语言风格来阐述,期望能给感兴趣的读者带来帮助. 为了不和时代落伍,我们必须要学习 XML 和 JSON,但同时它们也很容易

  • PHP中使用SimpleXML检查XML文件结构实例

    利用 SimpleXML 去检查 XML 结构是否符合规格,为了让这个程序可以多用途,采用了一个基准文件的作为结构准则,依据里面定义的节点跟属性,去检查文件是否符合基本要求的格式. 复制代码 代码如下: <?php        /**检查 XML 文件结构   * @param string $baseFilePath 基准结构文件   * @param string $checkFilePath 待检查文件   * @return bool 当结构与基准文件相符合时则传递 true,否则是

随机推荐