新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> XML网站展示,XML源代码,XML编程示例。 本版仅接受原创、转贴、网站展示,具体的技术交流请前往各相关版块。
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - XML技术『 XML源码及示例(仅原创和转载) 』 → [转帖]XML卷之实战锦囊(5):结构树图 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 3546 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [转帖]XML卷之实战锦囊(5):结构树图 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     admin 帅哥哟,离线,有人找我吗?
      
      
      
      威望:9
      头衔:W3China站长
      等级:计算机硕士学位(管理员)
      文章:5255
      积分:18406
      门派:W3CHINA.ORG
      注册:2003/10/5

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给admin发送一个短消息 把admin加入好友 查看admin的个人资料 搜索admin在『 XML源码及示例(仅原创和转载) 』的所有贴子 点击这里发送电邮给admin  访问admin的主页 引用回复这个贴子 回复这个贴子 查看admin的博客楼主
    发贴心情 [转帖]XML卷之实战锦囊(5):结构树图

    转载自:http://www.knowsky.com/list.asp?id=3163

    文章类别:XML教程   发表日期:2003-9-29  星期一  
        
          

    --------------------------------------------------------------------------------

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




    ----------------------------------------------

    -----------------------------------------------

    第十二章第一节《用ROR创建面向资源的服务》
    第十二章第二节《用Restlet创建面向资源的服务》
    第三章《REST式服务有什么不同》
    InfoQ SOA首席编辑胡键评《RESTful Web Services中文版》
    [InfoQ文章]解答有关REST的十点疑惑

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/3/1 15:02:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 XML源码及示例(仅原创和转载) 』的所有贴子 点击这里发送电邮给Google AdSense  访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/5 21:55:46

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    4,835.938ms