xml+xsl 自动生成 二叉树
时间:2003-08-23
来源:互联网
演示地址:
myhyli.digichina.net/share/13.xml
图片预览:
myhyli.digichina.net/share/13.jpg
作者: 车仔 发布时间: 2003-08-23
以前的做法都是直接用图象软件画出来一个图片。
很好看,但每次有变动后都需要重新画一个新的。
另一方面,网页上对线条的显示、布局相当局限。
根据动态生成的数据进行排版、定位都相当困难,
而且在美观上也差强人意。
做了各种尝试以后,决定用XML+XSL作数据运算;
用VML来美化线条,用JAVASCRIPT来给对象定位。
[code]
<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的基本格式,我就不详细讲解了。
[/code]
XML是树型结构,我们读取每个数据就需要对这个
XML数据树进行遍历。而递归运算是XSL优势之一。
我也是在用其它多种方法进行遍历运算失败后才
决定使用XSL的。
[code]
<FlowRoot>
<vcTitle>二叉树--结构图</vcTitle>
<Author>车仔</Author>
<Email>[email protected]</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>
[/code]
逻辑上很简单,当前节点(1)下面有两个子节点(2,3)。
只需要将节点2和节点3定位在节点1的左下方和右下方就可以了。
这里我将左右节点的连接线分别用了绿色和红色,方便显示。
前面我们说到了XSL的递归功能,为了更清楚的看到每一个详细的
显示步骤,只需要仿照下面的代码,加一个alert语句就可以了。
[code]
<xsl:template match="FlowNode">
…
<SCRIPT language="JavaScript1.2">
…
alert('逐步显示');
…
</SCRIPT>
…
</xsl:template>
[/code]
看了上面的慢动作,是否能让大家了解到我的思路。
[ 本贴由 车仔 于 2003-8-26 13:12 最后编辑 ]
作者: 车仔 发布时间: 2003-08-25
谢谢!!
作者: useway 发布时间: 2003-08-26
(1)读取当前节点的资料,用VML生成一个新的对象。
给对象赋初始数值(如 name,id,style样式等)
(2)用脚本控制来给当前对象定位
(3)当前节点和它的父亲节点之间加箭头,线条。
(4)继续找当前节点的子节点,一直循环定位到结束。
也就是所有节点都遍历完毕,已经生成好了树。
[code]
<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>
[/code]
整个递归过程就是靠上面这三个模块(template)来完成的。
第一个template在匹配当前节点中每一个子节点的模板的时候
调用了后面两个template; 而后面两个template又在具体执行
的时候调用了第一个template ,这就相当于一个递归函数。
语法:
[code]
要依次匹配当前节点中的每个子节点的模板,应使用该元
素的基本形式 <xsl:apply-templates />。
否则,匹配的节点由 select 参数中 XPath 表达式的值决
定,如 <xsl:apply-templates select="./FlowNode" />
[/code]
(1)和(2)的作用都是返回由 select 参数给出的表达式的字符串值。
他们的搜索条件相同,所以返回的值也一样。
只不过是使用的场合不同,他们的书写形式也就不一样。
[code]
(1) <xsl:value-of select="./iProcess/text()" />
(2) {./iProcess/text()}
[/code]
这里定义了一些变量,节点的定位就是根据这些变量来调用运算公式的。
[code]
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 //当前对象的所有子节点中叶子数
叶子:是指当前节点没有子节点
[/code]
节点的定位公式:
(1) 当前节点是根节点
[code]
//根的位置
SobjOval.style.left=parseInt(root_left);
SobjOval.style.top=parseInt(root_top);
//parseInt() 函数的作用是取整数值,如果不是则为NAN
//isNaN()函数的作用是判断parseInt取得的是否为整数
[/code]
(2)当前节点是父节点的左边子节点
[code]
1)判断的条件是: 当前对象父节点的名称='iNextYes'
…
2)如果存在右边子叶子,则公式为:
当前节点的left=父节点的left - 当前节点的右边子叶子的总宽度- 当前节点的宽度
3)如果不存在右边子叶子,但存在左边子叶子,则公式为:
当前节点的left=父节点的left - 当前节点的左边子叶子的总宽度
4)如果当前节点本身就是叶子,则公式为:
当前节点的left=父节点的left - 当前节点的宽度
…
[/code]
(3)当前节点是父节点的右边子节点
[code]
1)判断的条件是: 当前对象父节点的名称='iNextNo'
…
2)如果存在左边子叶子,则公式为:
当前节点的left=父节点的left + 当前节点的左边子叶子的总宽度 + 当前节点的宽度
3)如果不存在左边子叶子,但存在右边子叶子,则公式为:
当前节点的left=父节点的left + 当前节点的右边子叶子的总宽度
4)如果当前节点本身就是叶子,则公式为:
当前节点的left=父节点的left + 当前节点的宽度
…
[/code]
(2)和(3)的公式都是得到当前节点的left,我们还需要得到当前节点的top
很简单的公式:当前节点的top=父节点的top + 偏移量(80)
作者: 车仔 发布时间: 2003-08-26
(1)找到当前节点和父节点的位置
(2)判断当前节点是父节点的左边子节点,还是右边子节点
(3)画线条
这里定义了一些变量。
[code]
objOval //当前节点,是一个object
objParentOval //当前对象的父节点,是一个object
objLine //当前线条,是一个object
[/code]
线条的定位公式:
[code]
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)
[/code]
我所能想到的也就这么多了。
如果只是单纯的做一个公司结构图的话,会更简单很多。
下面是赛扬的思路,我也是在他的基础上深入一点而已。
[code]
首先计算最下层节点个数,得出宽度,
然后应该根据节点的从属关系计算其上层节点位置,递归。
每一层级的节点要按从属关系先排序
首先设“基本值”=节点应向右偏移量
每个包含子节点的节点的left值等于它所拥有的节点所占宽度的一半加上基本值
[/code]
后话:
最近不知为何,网络一直都不好。断线的时间比在线的时间多。
所以没对代码简化,其实,要完善的功能还有很多,比如:
需要加右键菜单
右键菜单内含新建节点、修改节点名称、改变关联关系等
在每一个节点上都可右键打开这个节点的右键菜单
作者: 车仔 发布时间: 2003-08-26
我现在只知道,用VML画图的方法,请问XSL是做什么用的呢?如何使我用VML画的图根据鼠标等事件的触发而改变的呢?(就像你的myhyli.digichina.net/share/13.xml一样),在这方面有没有书可以参考呢?
谢谢!! [/quote]
触发事件跟HTML是一样的,跟XSL无关。
XSL只是把XML数据转换成HTML显示。
你会写JAVASCRIPT就可以。
关于VML的资料我也只有“美洲豹”写的《VML入门》
[ 本贴由 车仔 于 2003-8-26 13:56 最后编辑 ]
作者: 车仔 发布时间: 2003-08-26
但还想问一个问题。
如何,用JavaScript动态的改变已经用VML画出来的图呢?
如:动态的改变某一条线的top的值。能做吗?
谢谢。
作者: useway 发布时间: 2003-08-26
你看看 二叉树思路(3)里面说到的 连接线条的定位思路
前提是你要对每个对象命名。name , id
不然找不到对象,也就不能移动了
这是JS里写的,你应该看的懂我的意思
作者: 车仔 发布时间: 2003-08-26
此话怎讲?
你用的 VML 就不属于网页设计了?
从什么都没有到做成一个可供访问的页面
使用到的所有技术都是网页设计的范畴
作者: snakevil 发布时间: 2003-08-27
写的很累,感觉还不通俗,但已经能够把我想说的说了 。
感觉XML的应用更多的体现在数据传递和页面无刷新处理数据上 。
这方面对XML应用的人很少。
作者: 车仔 发布时间: 2003-08-28
第139行 28 字符,缺少;分号
只能看到第一个节点.
在IE6环境中正常。IE5.5不清楚,但IE5肯定报错。
很奇怪,同样的文件放在不同的电脑里居然回不同效果
作者: 车仔 发布时间: 2003-08-28
IE5.5 MsXML Parser 2.6
IE6 MsXML Parser 3.0
这就是有区别的原因
作者: snakevil 发布时间: 2003-08-29
xsl:value-of 这样的语句. 所以你的程序就执行不了了
除非把xsl:value-of的值通过JS读取xmldom来取得.要不在IE5下面就没办法运行了.
作者: 车仔 发布时间: 2003-08-29
现在 XML 的知识还只是学习
没有一个很成熟的运行环境
当然
如果学我那么恶心一点
让访问者强制性安装 MsXML4
就没问题了:)
作者: snakevil 发布时间: 2003-08-29
俺今天才看了书, 书上就是用 IE5做的例子啊?
作者: ※潇洒※ 发布时间: 2003-09-03
http://www.wy1997.com/gfxml/3.xsl
我想将折线换成圆弧线,但JS不好
比如我有两个点的坐标,怎么用函数将弧线的各个坐标点定位
作者: 车仔 发布时间: 2003-09-03
js 画弧线应该就是跟 sin cos 之类的函数相关了...
俺数学不好, 也想不出来.
作者: ※潇洒※ 发布时间: 2003-09-04
请教车仔...... 你xsl 里 {./iProcess/text()} 这个东东
是什么意思? 也是访问 XML 里的节点么?...
作者: ※潇洒※ 发布时间: 2003-09-04
(2) {./iProcess/text()}
(1)和(2)的作用都是返回由 select 参数给出的表达式的字符串值。
他们的搜索条件相同,所以返回的值也一样。
只不过是使用的场合不同,他们的书写形式也就不一样。
作者: 车仔 发布时间: 2003-09-04
另外, 你说的"使用的场合不同"... 这两种一般在什么场合下适用呢?..
作者: ※潇洒※ 发布时间: 2003-09-05
<div 名称=“参数值”>内容</div>
我们假设名称为“name”,参数值为XML数据中当前节点下面的子节点book的值
第一种写法是先加属性名称,再加参数值
<div>
<xsl:attribute name="name">
<xsl:value-of select="./book/text()"/> </xsl:attribute>
内容
</div>
第二种写法是直接加属性名称和参数值
<div name="{./book/text()}">内容</div>
具体的使用你可以看我写的代码中的例子
http://www.wy1997.com/gfxml/3.xsl
作者: 车仔 发布时间: 2003-09-05
我那天就是看你那个例子的时候看不懂, 所以特来请教.
另外, 还有点点小问题....... 访问节点值不是直接
select="./book/text" 就可以了吗? 你后面加个括号是啥意思?
作者: ※潇洒※ 发布时间: 2003-09-06
<xsl:value-of select="./book/text()"/>
只是把他的文本值写出来
而
<xsl:value-of select="./book"/>
是把他的文本值和他的所有子节点的内容显示出来
你可以试验一下,输出一个有子节点的,一个无子节点的
看看显示的结果是否相同
作者: 车仔 发布时间: 2003-09-06
select="./book/text"
这样写不规范啊。如果在XML数据中有这样的数据
<book>
<text/>
</book>
那你叫XSL如何判断呢?
作者: 车仔 发布时间: 2003-09-06
这下完全理解了. 以后还请多指教啊~~
(因为俺看的书是针对 IE5 的..而且比较早... 所以有些跟不上时代了..
select="./book/text" 这些也是书上这么写的, 所以我看到你加了括号就好奇.)
作者: ※潇洒※ 发布时间: 2003-09-06
作者: 飘逸书生 发布时间: 2003-09-15
触类旁通,自然能够派上用场。
作者: 车仔 发布时间: 2003-09-16
作者: 飞翔鸟 发布时间: 2003-10-10
作者: phddcg 发布时间: 2003-11-11
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28